Node如何實(shí)現(xiàn)在瀏覽器預(yù)覽項(xiàng)目的所有圖片詳解
背景
在前端實(shí)際項(xiàng)目開發(fā)中,會(huì)有這樣一種場景。每次引入新的圖片,并不知道這個(gè)資源是否被引用過,所以會(huì)點(diǎn)開存放圖片的資源一個(gè)個(gè)去看。實(shí)際問題是:
- 1.圖片并不是放到一個(gè)目錄下的,可能存在任何的地方,不好查找
- 2.費(fèi)時(shí)間,費(fèi)力
- 3.可能會(huì)重復(fù)引入圖片資源
如果有個(gè)能力,將項(xiàng)目圖片資源羅列到一起查看,并方便看到引入路徑的話,就會(huì)大大節(jié)約開發(fā)的體力活。
如果要做這樣的能力,應(yīng)該考慮什么呢?
需求分析
- 可以集成到任何前端項(xiàng)目中,那就要求是個(gè)npm包
- 讀取文件,分析哪些是圖片,將圖片資源通過img標(biāo)簽寫入到html文件中
- 創(chuàng)建一個(gè)服務(wù)器,將html渲染出來
這就需要借助Node來實(shí)現(xiàn),需要用到的 fs path http 模塊。
實(shí)現(xiàn)
1 實(shí)現(xiàn)可發(fā)布npm包
創(chuàng)建一個(gè)項(xiàng)目
npm init
包名字是
test-read-img
在package.json 中加入如下代碼
"bin": { "readimg": "./index.js" },
在入口文件index.js 中加入測試代碼
含義是這個(gè)文件是可執(zhí)行的node文件
#!/usr/bin/env node console.log('111')
將當(dāng)前模塊鏈接到全局node_modules模塊內(nèi),方便調(diào)試
執(zhí)行
npm link
執(zhí)行
readimg
就看到輸出111 了
到此就實(shí)現(xiàn)了通過命令使用npm包的使用了,當(dāng)項(xiàng)目安裝了這個(gè)包,并配置執(zhí)行命令,就可以在別的項(xiàng)目執(zhí)行設(shè)計(jì)的npm包了,后面就實(shí)現(xiàn)這個(gè)
"scripts": { "test": "readimg" },
2 集成到別的項(xiàng)目
- 創(chuàng)建一個(gè)測試項(xiàng)目 ,執(zhí)行
npm init
- 將測試包集成到當(dāng)前項(xiàng)目, 執(zhí)行
npm link test-read-img
- 配置執(zhí)行命令
"scripts": { "test": "readimg" },
執(zhí)行npm run test
就能看到當(dāng)前項(xiàng)目執(zhí)行了讀取文件的包的代碼了。 現(xiàn)在只輸出了 111距離讀取文件還很遠(yuǎn),下面來實(shí)現(xiàn)讀取文件
3 讀取文件
- 在
test-read-img
項(xiàng)目中,聲明一個(gè)執(zhí)行函數(shù),并執(zhí)行.
#!/usr/bin/env node const init = async () => { const readFiles = await getFileFun(); const html = await handleHtml(readFiles); createServer(html); } init();
這里解釋一下 ,各函數(shù)作用
getFileFun
: 讀取項(xiàng)目文件,并將讀取的圖片文件路徑返回,這里不需要圖片資源,后面解釋為什么。handleHtml
: 讀取模版html文件, 將圖片資源通過img
承載 生成新的html文件。createServer
: 將生成的html ,放到服務(wù)器下去渲染出來。
主流程就是這樣。
實(shí)現(xiàn)
getFileFun
功能分析一下這個(gè)文件具體要做什么
循環(huán)讀取文件,直到將所有文件查找完,將圖片資源過濾出來,讀取文件要異步執(zhí)行,如何知道何時(shí)讀取完文件呢,這里用
promise
實(shí)現(xiàn),這里僅僅實(shí)現(xiàn)了單層文件的讀取 ,因?yàn)榘l(fā)布到公司內(nèi)部的npm,請見諒。 聰明的你這里想想如何遞歸實(shí)現(xiàn)呢?getFileFun
: 應(yīng)該先讀取完文件,才能將圖片返回,所以異步收集器應(yīng)該在后面執(zhí)行。具體代碼如下:
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 = []; // 收集讀取圖片,作為一個(gè)異步收集器 async function readAllFile(filePath) { // 循環(huán)讀文件 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) { // 循環(huán)判斷文件 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() { // 將資源返回給調(diào)用使用 await readAllFile('./'); return await Promise.all(imgPromiseArr); } module.exports = { getFileFun }
實(shí)現(xiàn)
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 }
實(shí)現(xiàn)
createServer
這里讀取html 文件,并返回給服務(wù)器。 這里僅僅實(shí)現(xiàn)了對(duì)
png
的文件的展示,對(duì)于其他類型的圖片如何支持呢,這里提示一下對(duì)content-type
進(jìn)行處理。
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 }
效果
以上就是實(shí)現(xiàn)過程,執(zhí)行一下 npm run test
就可以看到瀏覽器執(zhí)行在http://localhost:3004/, 效果如下:
發(fā)布
npm login
npm publish
思考
為什么用異步讀取文件?
因?yàn)閖s是單線程,同步讀取文件的話會(huì)卡在那里,不能執(zhí)行其他了。
為什么要用Promise 收集圖片
因?yàn)椴恢朗裁磿r(shí)候讀取完文件,當(dāng)異步讀取完再用
Promise.all
整體處理為什么 不讀取新的html文件,而將結(jié)果直接返回給瀏覽器?
如果將轉(zhuǎn)換后
html放到
test-read-img
文件,就必須將圖片資源也要生成在當(dāng)前目錄,要不然html 讀取的相當(dāng)路徑資源是找不到的,因?yàn)橘Y源都在使用項(xiàng)目中。結(jié)束的時(shí)候還要將圖片資源刪除,這也無形增加了復(fù)雜度;如果將轉(zhuǎn)化后的html 寫入放到使用項(xiàng)目中,這樣就可以直接用圖片的路徑,并能正確加載,但是這樣會(huì)多了一個(gè)html文件,程序退出的時(shí)候還要?jiǎng)h除這個(gè),如果忘記刪除了,就可能被開發(fā)者提交到遠(yuǎn)程,造成污染,提供的預(yù)覽應(yīng)該是無害的。這兩種方式都不可取。因此直接返回html資源,讓它去加載相對(duì)目標(biāo)項(xiàng)目路徑,不會(huì)產(chǎn)生任何影響。
總結(jié)
到此這篇關(guān)于Node如何實(shí)現(xiàn)在瀏覽器預(yù)覽項(xiàng)目的所有圖片的文章就介紹到這了,更多相關(guān)Node瀏覽器預(yù)覽圖片內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Node.js 實(shí)現(xiàn)搶票小工具 & 短信通知提醒功能
這篇文章主要介紹了Node.js 實(shí)現(xiàn)搶票小工具 & 短信通知提醒功能,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-10-10Node.js安裝及npm國內(nèi)鏡像配置的方法實(shí)現(xiàn)
本文主要介紹了Node.js安裝及npm國內(nèi)鏡像配置,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-06-06開箱即用的Node.js+Mysql模塊封裝實(shí)現(xiàn)詳解
這篇文章主要為大家介紹了開箱即用的Node.js+Mysql模塊封裝實(shí)現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01Windows 系統(tǒng)下設(shè)置Nodejs NPM全局路徑
這篇文章主要介紹了Windows 系統(tǒng)下設(shè)置Nodejs NPM全局路徑2016-04-04基于Node.js + WebSocket打造即時(shí)聊天程序嗨聊
這篇文章主要介紹了基于Node.js + WebSocket打造即時(shí)聊天程序,有興趣的可以了解一下。2016-11-11Nodejs實(shí)現(xiàn)的操作MongoDB數(shù)據(jù)庫功能完整示例
這篇文章主要介紹了Nodejs實(shí)現(xiàn)的操作MongoDB數(shù)據(jù)庫功能,結(jié)合完整實(shí)例形式分析了nodejs針對(duì)MongoDB數(shù)據(jù)庫的連接及增刪改查基本操作技巧,需要的朋友可以參考下2019-02-02了不起的node.js讀書筆記之mongodb數(shù)據(jù)庫交互
這篇文章主要介紹了了不起的node.js讀書筆記之mongodb數(shù)據(jù)庫交互,需要的朋友可以參考下2014-12-12node命令行工具之實(shí)現(xiàn)項(xiàng)目工程自動(dòng)初始化的標(biāo)準(zhǔn)流程
這篇文章主要介紹了node命令行工具之實(shí)現(xiàn)項(xiàng)目工程自動(dòng)初始化的標(biāo)準(zhǔn)流程 ,本文分步驟給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-08-08