index.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. const { JSDOM } = require('jsdom');
  2. const fs = require('fs')
  3. const path = require('path')
  4. const request = require('request')
  5. const UglifyJS = require("uglify-js");
  6. const CleanCSS = require('clean-css');
  7. const minifyHtml = require('html-minifier').minify
  8. /**
  9. * 抽取所有脚本css等文件
  10. * @param {Document} document jsdom
  11. */
  12. function scriptFilter(document) {
  13. let ret = {script: [], link: []}
  14. for (let i = 0, dom = document.querySelectorAll('script'); i < dom.length; i++) {
  15. let src = dom[i].getAttribute('src')
  16. if (src || dom[i].innerHTML.trim().length > 0) {
  17. ret.script.push(src ?
  18. {content: src, type: 1, url: src} :
  19. {content: dom[i].innerHTML, type: 0, url: src}
  20. )
  21. dom[i].parentNode.removeChild(dom[i]);
  22. }
  23. }
  24. for (let i = 0, dom = document.querySelectorAll('link[rel="stylesheet"],style'); i < dom.length; i++) {
  25. let tagName = dom[i].tagName
  26. ret.link.push(tagName === 'LINK' ?
  27. {content: dom[i].getAttribute('href'), type: 1} :
  28. {content: dom[i].innerHTML, type: 0}
  29. )
  30. dom[i].parentNode.removeChild(dom[i]);
  31. }
  32. return ret
  33. }
  34. /**
  35. * 下载所有资源
  36. * @param {String} dir 文件所在的路径
  37. * @param {Array} contents 文件
  38. */
  39. async function downContent(dir, contents) {
  40. let labels = ['script', 'link']
  41. for (let i = 0, label; label = labels[i]; i++) {
  42. for (let j = 0, item; item = contents[label][j]; j++) {
  43. if (item.type === 1) {
  44. let src = path.join(dir, item.content)
  45. src = ~src.indexOf('?') ? src.substring(0, src.indexOf('?')) : src
  46. if (fs.existsSync(src)) {
  47. item.content = fs.readFileSync(src).toString()
  48. } else {
  49. await new Promise(resolve => {
  50. request.get(item.content, (err, response) => {
  51. if (!err && response.statusCode === 200) {
  52. item.content = response.body
  53. } else {
  54. item.content = ''
  55. }
  56. resolve()
  57. })
  58. });
  59. }
  60. }
  61. }
  62. }
  63. return contents
  64. }
  65. /**
  66. * 合并资源,并压缩
  67. * @param {JSON} contents 所有资源
  68. */
  69. function mergeStatic (contents) {
  70. let ret = {script: '', link: ''}
  71. Object.keys(ret).forEach(label => {
  72. contents[label].forEach(item => {
  73. ret[label] += item.content
  74. label === 'script' && (ret[label] += ';\n')
  75. })
  76. })
  77. let result = UglifyJS.minify(ret.script, {
  78. compress: {
  79. // booleans: false,
  80. // comparisons: false,
  81. // conditionals: false,
  82. // collapse_vars: false,
  83. // keep_fnames: true,
  84. // dead_code: false,
  85. // directives: false,
  86. // evaluate: false,
  87. hoist_props: false
  88. }
  89. })
  90. if (result.error) {
  91. console.error('js有错误:', JSON.stringify(result.error))
  92. } else {
  93. ret.script = result.code
  94. }
  95. ret.link = new CleanCSS({}).minify(ret.link).styles
  96. return ret
  97. }
  98. async function main(file, htmlName = 'minify-temp.html', jsName = 'minify-script.js', cssName = 'minify-style.css') {
  99. console.log('-------------------', process.cwd(), file, '--------------------')
  100. let src = path.join(process.cwd(), file)
  101. let document = new JSDOM(fs.readFileSync(src)).window.document
  102. let dir = path.join(src, '../')
  103. let contents = await downContent(
  104. path.join(src, '../'),
  105. scriptFilter(document)
  106. )
  107. let ret = mergeStatic(contents)
  108. let $script = document.createElement('script')
  109. let $link = document.createElement('link')
  110. $script.setAttribute('src', 'js/' + jsName)
  111. $link.setAttribute('rel', 'stylesheet')
  112. $link.setAttribute('href', 'css/' + cssName)
  113. document.head.appendChild($link)
  114. document.body.appendChild($script)
  115. let html = `
  116. <!doctype html>
  117. <html lang="zh">
  118. ${document.documentElement.innerHTML}
  119. </html>
  120. `
  121. fs.writeFileSync(path.join(dir, 'js/' + jsName), '\ufeff' + ret.script)
  122. fs.writeFileSync(path.join(dir, 'css/' + cssName), '\ufeff' + ret.link)
  123. fs.writeFileSync(path.join(dir, htmlName), '\ufeff' + minifyHtml(html, {
  124. removeComments: true,
  125. collapseWhitespace: true,
  126. }))
  127. }
  128. main(...process.argv.splice(2))
  129. // main('../CAD/index.html')