详解使用nodejs分离html文件里的js和css

前端之家收集整理的这篇文章主要介绍了详解使用nodejs分离html文件里的js和css前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

摘要: 本文要实现的内容,使用nodejs 对文件的增删改查,演示的例子-》分离出一个html 文件里面的script 和style 里面的内容,然后单独生成js文件和css 文件。中间处理异步的api-》async/await , Promise

项目托管:extract-js-css , 欢迎star

直接上代码

  1. // extract-js-css
  2.  
  3. // import fs from 'fs'
  4.  
  5. var fs = require('fs')
  6.  
  7. // import csscomb from 'csscomb'
  8.  
  9. // var csscomb = require('csscomb')
  10.  
  11. // var comb = new csscomb('zen');
  12.  
  13. // console.log(comb)
  14.  
  15.  
  16.  
  17. // 删除文件
  18.  
  19. const deleteFile = (path)=>{
  20.  
  21.   return new Promise(resolve => {
  22.  
  23.     fs.unlink(path, (err) => {
  24.  
  25.       if (err) {
  26.  
  27.         console.log(err)
  28.  
  29.         return
  30.  
  31.       };
  32.  
  33.       console.log(`已成功删除 ${path}文件`);
  34.  
  35.       resolve()
  36.  
  37.     });
  38.  
  39.   })
  40.  
  41. }
  42.  
  43.  
  44.  
  45. // 删除文件
  46.  
  47. const deleteDir = async (path)=>{
  48.  
  49.   let _files = await new Promise (resolve => {
  50.  
  51.     fs.readdir(path, (err,files) => {
  52.  
  53.       if (err) {
  54.  
  55.         console.log(err)
  56.  
  57.       };
  58.  
  59.       console.log(`已成功读取 ${path} 文件夹`);
  60.  
  61.       resolve(files)
  62.  
  63.     })
  64.  
  65.   })
  66.  
  67.  
  68.  
  69.   if(_files && _files.length) {
  70.  
  71.     for(let i =0;i<_files.length;i++) {
  72.  
  73.       // console.log(_files[i],'innnnnn')
  74.  
  75.       await deleteFile('./test/'+ _files[i])
  76.  
  77.     }
  78.  
  79.   }
  80.  
  81.   // console.log('delete hou')
  82.  
  83.  
  84.  
  85.   await new Promise(resolve => {
  86.  
  87.     fs.rmdir(path, (err) => {
  88.  
  89.       if (err) {
  90.  
  91.         console.log(err)
  92.  
  93.       };
  94.  
  95.       console.log(`已成功删除空 ${path}文件夹`);
  96.  
  97.       resolve()
  98.  
  99.     })
  100.  
  101.   });
  102.  
  103. }
  104.  
  105. const emptyDir = (path) => {
  106.  
  107.   return new Promise(resolve => {
  108.  
  109.     fs.rmdir(path, (err) => {
  110.  
  111.       if (err) {
  112.  
  113.         console.log(err)
  114.  
  115.       };
  116.  
  117.       console.log(`已成功删除空 ${path}文件夹`);
  118.  
  119.       resolve()
  120.  
  121.     })
  122.  
  123.   })
  124.  
  125. }
  126.  
  127. // 新建文件
  128.  
  129. /**
  130.  
  131.  * 
  132.  
  133.  */
  134.  
  135. const mkdirTest = ()=>{
  136.  
  137.   return new Promise(resolve => {
  138.  
  139.     fs.mkdir('./test', { recursive: true }, (err, data)=>{
  140.  
  141.       if (err) {
  142.  
  143.         console.log(err)
  144.  
  145.       };
  146.  
  147.       console.log('新建文件夹成功')
  148.  
  149.       resolve()
  150.  
  151.     })
  152.  
  153.   })
  154.  
  155. }
  156.  
  157.  
  158.  
  159. // 读取html 内容
  160.  
  161. /**
  162.  
  163.  * 
  164.  
  165.  */
  166.  
  167. const readHtml = ()=>{
  168.  
  169.   return new Promise(resolve => {
  170.  
  171.     fs.readFile('./test.html', 'utf-8', (err, data)=>{
  172.  
  173.       if(err) {
  174.  
  175.         throw Error(err)
  176.  
  177.       }
  178.  
  179.       console.log('test.html 读取成功!--NO1')
  180.  
  181.       resolve(data)
  182.  
  183.     })
  184.  
  185.   })
  186.  
  187. }
  188.  
  189.  
  190.  
  191. // 写入css 和js
  192.  
  193. /**
  194.  
  195.  * 向文件中追加内容
  196.  
  197.  * @param {是文件名字} path 
  198.  
  199.  * @param {写入文件内容} data 
  200.  
  201.  * @param {文件类型} type 
  202.  
  203.  * @author erlinger
  204.  
  205.  * @time 
  206.  
  207.  */
  208.  
  209. const appendFile = (path, data, type) => {
  210.  
  211.   return new Promise(resolve => {
  212.  
  213.     fs.appendFile(path, data, (err) => {
  214.  
  215.       if (err) {
  216.  
  217.         console.log(err)
  218.  
  219.       };
  220.  
  221.       console.log(`${type}数据已追加到文件`);
  222.  
  223.       resolve()
  224.  
  225.     });
  226.  
  227.   })
  228.  
  229. }
  230.  
  231. // 写一个html
  232.  
  233. const writeHtml = (path, data) => {
  234.  
  235.   return new Promise(resolve => {
  236.  
  237.     fs.writeFile(path, data, (err) =>{
  238.  
  239.       if(err) {
  240.  
  241.         console.log('err', err)
  242.  
  243.         return
  244.  
  245.       }
  246.  
  247.       console.log(`${path} 写入成功,功能结束!`);
  248.  
  249.       resolve() // 必须resolve 。不然 promise 就到此为止,调用方法后面的代码将不执行
  250.  
  251.     })
  252.  
  253.   })
  254.  
  255. }
  256.  
  257. // 插件 方法入口
  258.  
  259. (async ()=>{
  260.  
  261.   console.log('==========================game-start=============================');
  262.  
  263.   await deleteDir('./test');
  264.  
  265.   console.log('我应该是等---删除文件夹后---才出现')
  266.  
  267.   await mkdirTest();
  268.  
  269.   console.log('我应该是在---文件夹新建成功---后出现!');
  270.   let cssReg = /<style>[\s|\S]*?<\/style>/ig;
  271.  
  272.   let jsReg = /<script>[\s|\S]*?<\/script>/ig;
  273.  
  274.   let allStyleReg = /<\/style>[\s|\S]*?<style>/ig;
  275.  
  276.   let allScriptReg = /<\/script>[\s|\S]*?<script>/ig;
  277.  
  278.   let cssLink = '<link rel="stylesheet" href="./test.css" rel="external nofollow" >';
  279.  
  280.   let jsrc = '<script src="./test.js"></script>';
  281.  
  282.   let styleCollection, scriptColletion;
  283.  
  284.   let cssContent = '', jsContent = '', htmlContentStr = '';
  285.  
  286.   let originContent = await readHtml();
  287.  
  288.   styleCollection = originContent.match(cssReg);
  289.  
  290.   scriptColletion = originContent.match(jsReg);
  291.  
  292.  
  293.   // 处理 css
  294.  
  295.   for (let i =0;i<styleCollection.length;i++) {
  296.  
  297.     cssContent += JSON.stringify(styleCollection[i]);
  298.  
  299.   }
  300.  
  301.   cssContent = cssContent.replace(/<style>/g,'').replace(/<\/style>/g, '').replace(/("")/g,'')
  302.  
  303.   for (let i =0;i<scriptColletion.length;i++) {
  304.  
  305.     jsContent += JSON.stringify(scriptColletion[i]);
  306.  
  307.   }
  308.  
  309.   jsContent = jsContent.replace(/<script>/g,'').replace(/<\/script>/g, '')
  310.  
  311.   .replace(/<\/script>"*<script>/g, '').replace(/("")/g,'')   
  312.  
  313.   await appendFile('./test/test.css', JSON.parse(cssContent), 'css');
  314.  
  315.   console.log('我应该是在---css写入成功---后出现!');
  316.   
  317.   await appendFile('./test/test.js', JSON.parse(jsContent), 'js');
  318.  
  319.   console.log('我应该是在---js写入成功---后出现!');
  320.  
  321.   htmlContentStr = originContent
  322.  
  323.   .replace(allStyleReg, '')
  324.  
  325.   .replace(cssReg, cssLink)
  326.  
  327.   .replace(allScriptReg, '')
  328.  
  329.   .replace(jsReg, jsrc);
  330.  
  331.   console.log('copyTest.html 文本已经格式化,准备写入');
  332.  
  333.   await writeHtml('./test/copyTest.html', htmlContentStr);
  334.  
  335.   console.log('==========================game-over=============================');
  336.  
  337. })()

代码确实没什么好解释的,慢慢看就明白了。运行:

  1. node extract-js-css

如果你要使用 es6 module,用 import 导入方法,需要单独装一个babel,使用这个包去编译成es5,在运行,具体使用可以down项目运行一下。

针对此项目,需要提醒说明以下:

文件的处理都是异步操作,如果是单一的一个异步操作方法(比如:appendFile 方法),它就是往文件里面异步添加内容,直接封装成一个promise,然后 return 出来就好。

如果一个操作里面包含多个异步处理逻辑的就需要在这个方法里面,用async 声明方法,用await 等待异步操作,最后return 出去一个promise

在执行主流程中,我们用async声明的方法进行调用(我这里是匿名函数直接调用) ,用await 进行等待异步操作,这样我们的主流程就是一个同步的执行的流程,看起来很爽朗。

文中的异步操作文件的api 方法是异步的,nodejs 开发文档提供了同步操作文档,大家可以直接使用同步的api。我这里主要是联系在异步操作的过程中,使用async/ await promise 方法,更好的掌握它。

文中的一个demo 提供了处理多个异步、一个异步操作里面包含多个异步操作,包括在循环里执行异步操作 的一个方案,里面具体针对HTML 文件的字符串处理,比较搓搓,在用正则匹配和字符串格式化和解析字符串的情况比较单一。在读取完文件内容后,需要 JSON.stringify,后来在填入文件中的时候要 JSON.parse , 目前没找到合适的方法,如果有大佬有合适的方法,欢迎告知与我,大家一起交流。

下面是 执行一个主 async方法的一个过程

猜你在找的Node.js相关文章