|
@@ -0,0 +1,135 @@
|
|
|
+const { JSDOM } = require('jsdom');
|
|
|
+const fs = require('fs')
|
|
|
+const path = require('path')
|
|
|
+const request = require('request')
|
|
|
+const UglifyJS = require("uglify-js");
|
|
|
+const CleanCSS = require('clean-css');
|
|
|
+const minifyHtml = require('html-minifier').minify
|
|
|
+
|
|
|
+/**
|
|
|
+ * 抽取所有脚本css等文件
|
|
|
+ * @param {Document} document jsdom
|
|
|
+ */
|
|
|
+function scriptFilter(document) {
|
|
|
+ let ret = {script: [], link: []}
|
|
|
+
|
|
|
+ for (let i = 0, dom = document.querySelectorAll('script'); i < dom.length; i++) {
|
|
|
+ let src = dom[i].getAttribute('src')
|
|
|
+ ret.script.push(src ?
|
|
|
+ {content: src, type: 1, url: src} :
|
|
|
+ {content: dom[i].innerHTML, type: 0, url: src}
|
|
|
+ )
|
|
|
+ dom[i].parentNode.removeChild(dom[i]);
|
|
|
+ }
|
|
|
+
|
|
|
+ for (let i = 0, dom = document.querySelectorAll('link[rel="stylesheet"],style'); i < dom.length; i++) {
|
|
|
+ let tagName = dom[i].tagName
|
|
|
+ ret.link.push(tagName === 'LINK' ?
|
|
|
+ {content: dom[i].getAttribute('href'), type: 1} :
|
|
|
+ {content: dom[i].innerHTML, type: 0}
|
|
|
+
|
|
|
+ )
|
|
|
+ dom[i].parentNode.removeChild(dom[i]);
|
|
|
+ }
|
|
|
+
|
|
|
+ return ret
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 下载所有资源
|
|
|
+ * @param {String} dir 文件所在的路径
|
|
|
+ * @param {Array} contents 文件
|
|
|
+ */
|
|
|
+async function downContent(dir, contents) {
|
|
|
+ let labels = ['script', 'link']
|
|
|
+
|
|
|
+ for (let i = 0, label; label = labels[i]; i++) {
|
|
|
+ for (let j = 0, item; item = contents[label][j]; j++) {
|
|
|
+ if (item.type === 1) {
|
|
|
+ let src = path.join(dir, item.content)
|
|
|
+ src = ~src.indexOf('?') ? src.substring(0, src.indexOf('?')) : src
|
|
|
+ if (fs.existsSync(src)) {
|
|
|
+ item.content = fs.readFileSync(src).toString()
|
|
|
+ } else {
|
|
|
+ await new Promise(resolve => {
|
|
|
+ request.get(item.content, (err, response) => {
|
|
|
+ if (!err && response.statusCode === 200) {
|
|
|
+ item.content = response.body
|
|
|
+ } else {
|
|
|
+ item.content = ''
|
|
|
+ }
|
|
|
+ resolve()
|
|
|
+ })
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ return contents
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 合并资源,并压缩
|
|
|
+ * @param {JSON} contents 所有资源
|
|
|
+ */
|
|
|
+function mergeStatic (contents) {
|
|
|
+ let ret = {script: '', link: ''}
|
|
|
+
|
|
|
+ Object.keys(ret).forEach(label => {
|
|
|
+ contents[label].forEach(item => {
|
|
|
+ ret[label] += item.content
|
|
|
+ label === 'script' && (ret[label] += ';')
|
|
|
+ })
|
|
|
+ })
|
|
|
+
|
|
|
+ ret.script = UglifyJS.minify(ret.script, {
|
|
|
+ compress: {
|
|
|
+ dead_code: true,
|
|
|
+ global_defs: {
|
|
|
+ DEBUG: false
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }).code
|
|
|
+ ret.link = new CleanCSS({}).minify(ret.link).styles
|
|
|
+
|
|
|
+ return ret
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+async function main (file) {
|
|
|
+ let src = path.join(process.cwd(), file)
|
|
|
+ console.log(src)
|
|
|
+ let document = new JSDOM(fs.readFileSync(src)).window.document
|
|
|
+ let dir = path.join(src, '../')
|
|
|
+ let contents = await downContent(
|
|
|
+ path.join(src, '../'),
|
|
|
+ scriptFilter(document)
|
|
|
+ )
|
|
|
+ let ret = mergeStatic(contents)
|
|
|
+ let $script = document.createElement('script')
|
|
|
+ let $link = document.createElement('link')
|
|
|
+ $script.setAttribute('src', 'js/minify-script.js')
|
|
|
+ $link.setAttribute('rel', 'stylesheet')
|
|
|
+ $link.setAttribute('href', 'css/minify-style.css')
|
|
|
+
|
|
|
+ document.head.appendChild($link)
|
|
|
+ document.body.appendChild($script)
|
|
|
+
|
|
|
+ let html = `
|
|
|
+ <!doctype html>
|
|
|
+ <html>
|
|
|
+ ${document.documentElement.innerHTML}
|
|
|
+ </html>
|
|
|
+ `
|
|
|
+
|
|
|
+ fs.writeFileSync(path.join(dir, 'js/minify-script.js'), ret.script)
|
|
|
+ fs.writeFileSync(path.join(dir, 'css/minify-style.css'), ret.link)
|
|
|
+ fs.writeFileSync(path.join(dir, 'minify-temp.html'), minifyHtml(html, {
|
|
|
+ removeComments: true,
|
|
|
+ collapseWhitespace: true,
|
|
|
+ }))
|
|
|
+}
|
|
|
+
|
|
|
+main(...process.argv.splice(2))
|