Node如何實現在瀏覽器預覽項目的所有圖片詳解
背景
在前端實際項目開發中,會有這樣一種場景。每次引入新的圖片,並不知道這個資源是否被引用過,所以會點開存放圖片的資源一個個去看。實際問題是:
- 1.圖片並不是放到一個目錄下的,可能存在任何的地方,不好查找
- 2.費時間,費力
- 3.可能會重復引入圖片資源
如果有個能力,將項目圖片資源羅列到一起查看,並方便看到引入路徑的話,就會大大節約開發的體力活。
如果要做這樣的能力,應該考慮什麼呢?
需求分析
- 可以集成到任何前端項目中,那就要求是個npm包
- 讀取文件,分析哪些是圖片,將圖片資源通過img標簽寫入到html文件中
- 創建一個服務器,將html渲染出來
這就需要借助Node來實現,需要用到的 fs path http 模塊。
實現
1 實現可發佈npm包
-
創建一個項目
npm init
包名字是
test-read-img
-
在package.json 中加入如下代碼
"bin": { "readimg": "./index.js" },
-
在入口文件index.js 中加入測試代碼
含義是這個文件是可執行的node文件
#!/usr/bin/env node console.log('111')
-
將當前模塊鏈接到全局node_modules模塊內,方便調試
執行
npm link
執行
readimg
就看到輸出111 瞭
到此就實現瞭通過命令使用npm包的使用瞭,當項目安裝瞭這個包,並配置執行命令,就可以在別的項目執行設計的npm包瞭,後面就實現這個
"scripts": { "test": "readimg" },
2 集成到別的項目
- 創建一個測試項目 ,執行
npm init
- 將測試包集成到當前項目, 執行
npm link test-read-img
- 配置執行命令
"scripts": { "test": "readimg" },
執行npm run test
就能看到當前項目執行瞭讀取文件的包的代碼瞭。 現在隻輸出瞭 111距離讀取文件還很遠,下面來實現讀取文件
3 讀取文件
- 在
test-read-img
項目中,聲明一個執行函數,並執行.
#!/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
: 應該先讀取完文件,才能將圖片返回,所以異步收集器應該在後面執行。具體代碼如下:
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文件,並替換。
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
進行處理。
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資源,讓它去加載相對目標項目路徑,不會產生任何影響。
總結
到此這篇關於Node如何實現在瀏覽器預覽項目的所有圖片的文章就介紹到這瞭,更多相關Node瀏覽器預覽圖片內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!