广告位联系
返回顶部
分享到

Node如何实现在浏览器预览项目的所有图片介绍

JavaScript 来源:互联网 作者:佚名 发布时间:2023-01-09 00:27:17 人浏览
摘要

背景 在前端实际项目开发中,会有这样一种场景。每次引入新的图片,并不知道这个资源是否被引用过,所以会点开存放图片的资源一个个去看。实际问题是: 1.图片并不是放到一个目

背景

在前端实际项目开发中,会有这样一种场景。每次引入新的图片,并不知道这个资源是否被引用过,所以会点开存放图片的资源一个个去看。实际问题是:

  • 1.图片并不是放到一个目录下的,可能存在任何的地方,不好查找
  • 2.费时间,费力
  • 3.可能会重复引入图片资源

如果有个能力,将项目图片资源罗列到一起查看,并方便看到引入路径的话,就会大大节约开发的体力活。

如果要做这样的能力,应该考虑什么呢?

需求分析

  • 可以集成到任何前端项目中,那就要求是个npm包
  • 读取文件,分析哪些是图片,将图片资源通过img标签写入到html文件中
  • 创建一个服务器,将html渲染出来

这就需要借助Node来实现,需要用到的 fs path http 模块。

实现

1 实现可发布npm包

  • 创建一个项目 npm init

    包名字是 test-read-img

  • 在package.json 中加入如下代码

1

2

3

"bin": {

  "readimg": "./index.js"

},

  • 在入口文件index.js 中加入测试代码

    含义是这个文件是可执行的node文件

    1

    2

    3

    #!/usr/bin/env node

     

    console.log('111')

  • 将当前模块链接到全局node_modules模块内,方便调试

    执行 npm link

    执行 readimg

    就看到输出111 了

    到此就实现了通过命令使用npm包的使用了,当项目安装了这个包,并配置执行命令,就可以在别的项目执行设计的npm包了,后面就实现这个

    1

    2

    3

    "scripts": {

      "test": "readimg"

    },

2 集成到别的项目

  • 创建一个测试项目 ,执行 npm init
  • 将测试包集成到当前项目, 执行 npm link test-read-img
  • 配置执行命令

1

2

3

4

"scripts": {

  

  "test": "readimg"

},

执行npm run test

就能看到当前项目执行了读取文件的包的代码了。 现在只输出了 111距离读取文件还很远,下面来实现读取文件

3 读取文件

  • 在 test-read-img 项目中,声明一个执行函数,并执行.

1

2

3

4

5

6

7

8

#!/usr/bin/env node

const init = async () => {

    const readFiles = await getFileFun();

    const html =  await handleHtml(readFiles);

    createServer(html);

}

 

init();

这里解释一下 ,各函数作用

  • getFileFun: 读取项目文件,并将读取的图片文件路径返回,这里不需要图片资源,后面解释为什么。
  • handleHtml: 读取模版html文件, 将图片资源通过 img 承载 生成新的html文件。
  • createServer : 将生成的html ,放到服务器下去渲染出来。

主流程就是这样。

  • 实现getFileFun 功能

    分析一下这个文件具体要做什么

    循环读取文件,直到将所有文件查找完,将图片资源过滤出来,读取文件要异步执行,如何知道何时读取完文件呢,这里用promise实现,这里仅仅实现了单层文件的读取 ,因为发布到公司内部的npm,请见谅。 聪明的你这里想想如何递归实现呢?

    getFileFun: 应该先读取完文件,才能将图片返回,所以异步收集器应该在后面执行。

    具体代码如下:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    39

    40

    41

    42

    43

    44

    45

    const fs = require('fs').promises;

    const path = require('path');

    const excludeDir = ['node_modules','package.json','index.html'];

    const excludeImg = ['png','jpg','svg','webp'];

     

    let imgPromiseArr = []; // 收集读取图片,作为一个异步收集器

    async function readAllFile(filePath) { // 循环读文件

         const data =  await fs.readdir(filePath)

         await dirEach(data,filePath);

    }

     

     async function handleIsImgFile(filePath,file) {

     

        const fileExt = file.split('.');

        const fileTypeName = fileExt[fileExt.length-1];

     

        if(excludeImg.includes(fileTypeName)) {  // 将图片丢入异步收集器

     

          imgPromiseArr.push(new Promise((resolve,reject) => {

            resolve(`${filePath}${file}`)

          }))

         }

    }

     

    async function dirEach(arr=[],filePath) { // 循环判断文件

     

    for(let i=0;i<arr.length;i++) {

        let fileItem = arr[i];

        const basePath = `${filePath}${fileItem}`;

       const fileInfo =  await  fs.stat(basePath)

        if(fileInfo.isFile()) {

         await handleIsImgFile(filePath,fileItem)

        }

      }

     

    }

     

    async function getFileFun() {  // 将资源返回给调用使用

        await readAllFile('./');

        return await Promise.all(imgPromiseArr);

     }

     

    module.exports = {

        getFileFun

    }

  • 实现 handleHtml

这里读取 test-read-img 的html文件,并替换。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

const fs = require('fs').promises;

const path = require('path');

 

const createImgs = (images=[]) => {

    return images.map(i => {

        return `<div class='img-warp'>

           <div class='img-item'>  <img  src='${i}' /> </div>

           <div class='img-path'>文件路径 <span class='path'>${i}</span></div>

         </div>`

    }).join('');

}

 

async function handleHtml(images=[]) {

    const template =   await fs.readFile(path.join(__dirname,'template.html'),'utf-8')

    const targetHtml = template.replace('%--%',`

     ${createImgs(images)}

    `);

   return targetHtml;

}

 

module.exports = {

 handleHtml

}

  • 实现 createServer

    这里读取html 文件,并返回给服务器。 这里仅仅实现了对 png的文件的展示,对于其他类型的图片如何支持呢,这里提示一下对 content-type进行处理。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

  const http = require('http');

const fs = require('fs').promises;

const path = require('path');

const open = require('open');

 

const createServer =(html) => {

  http.createServer( async (req,res) => {

      const  fileType = path.extname(req.url);

      let pathName = req.url;

      if(pathName === '/favicon.ico') {

        return;

      }

      let type = ''

      if(fileType === '.html') {

          type=`text/html`

      }

      if(fileType === '.png') {

         type='image/png'

      }

      if(pathName === '/') {

          res.writeHead(200,{

              'content-type':`text/html;charset=utf-8`,

              'access-control-allow-origin':"*"

          })

            res.write(html);

            res.end();

            return

      }

      const data = await fs.readFile('./' + pathName );

      res.writeHead(200,{

          'content-type':`${type};charset=utf-8`,

          'access-control-allow-origin':"*"

      })

      res.write(data);

      res.end();

       

  }).listen(3004,() => {

   console.log('project is run: http://localhost:3004/')

  open('http://localhost:3004/')

  });

 

  

}

 

module.exports = {

  createServer

}

效果

以上就是实现过程,执行一下 npm run test 就可以看到浏览器执行在http://localhost:3004/, 效果如下:

发布

npm login

npm publish

思考

  • 为什么用异步读取文件?

    因为js是单线程,同步读取文件的话会卡在那里,不能执行其他了。

  • 为什么要用Promise 收集图片

    因为不知道什么时候读取完文件,当异步读取完再用Promise.all整体处理

  • 为什么 不读取新的html文件,而将结果直接返回给浏览器?

    如果将转换后html放到 test-read-img 文件,就必须将图片资源也要生成在当前目录,要不然html 读取的相当路径资源是找不到的,因为资源都在使用项目中。结束的时候还要将图片资源删除,这也无形增加了复杂度;

    如果将转化后的html 写入放到使用项目中,这样就可以直接用图片的路径,并能正确加载,但是这样会多了一个html文件,程序退出的时候还要删除这个,如果忘记删除了,就可能被开发者提交到远程,造成污染,提供的预览应该是无害的。这两种方式都不可取。因此直接返回html资源,让它去加载相对目标项目路径,不会产生任何影响。


版权声明 : 本文内容来源于互联网或用户自行发布贡献,该文观点仅代表原作者本人。本站仅提供信息存储空间服务和不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权, 违法违规的内容, 请发送邮件至2530232025#qq.cn(#换@)举报,一经查实,本站将立刻删除。
原文链接 : https://juejin.cn/post/7185438521807601721
相关文章
  • 本站所有内容来源于互联网或用户自行发布,本站仅提供信息存储空间服务,不拥有版权,不承担法律责任。如有侵犯您的权益,请您联系站长处理!
  • Copyright © 2017-2022 F11.CN All Rights Reserved. F11站长开发者网 版权所有 | 苏ICP备2022031554号-1 | 51LA统计