我有一个 Express 应用程序,除其他外,它还提供一些基于单个车把模板的 html 代码。 对于用例来说,以短延迟交付它会很棒。因此,我在应用程序启动时读取并编译模板,现在我只需调用
res.send(
compiledTemplateIframeContent({ data: iframeData })
)
所有这些都完美无缺。
问题
现在我想缩小 html 并丑化 js 代码。我尝试使用 html-minifier 但嵌入的 javascript 没有丑化(重命名变量),甚至没有缩小(例如删除空格)。 我猜 uglify-js 没有在后台调用,因为一些配置错误。通过阅读文档我找不到我的错误。
我编写了一些测试 html 代码并在这个在线工具中进行了尝试。它只是 html-minifier 前面的一个简单的 gui,因此可能是测试我的问题的好方法。 在在线版本中,当我将
type="text/javascript"
添加到标签并将 text/javascript
添加到 Process scripts
选项时,我至少可以使其压缩 javascript 代码(即使这在我的 Express 应用程序中不起作用)。
但在在线工具中,
Minify JavaScript
复选框也不会改变任何内容。
我还不知道 uglifyjs 的可能性(html-minifier 的依赖项),但有了这个名字,我会认为它不仅应该压缩,还应该丑化 js 代码。
编辑/更新
我做了更多研究。我通过正则表达式匹配提取了js代码,然后直接用代码调用了uglify-js。车把碎片 {{ }} 存在一些问题。删除它们后,uglif-js 可以在模板的嵌入式 js 部分上工作。
当我为 html-minifier 设置选项
ignoreCustomFragments: [/{{.*}}/g]
时,我想这应该不是问题?!
这里是直接使用uglify-js的部分
function minifyWithUglifyJs(orig: string): string {
const re = /<script\b[^>]*>([\s\S]*?)<\/script>/gm;
const match = re.exec(orig);
if(match == null) {
throw new Error(`Can't minify js in iframe template as found no match for js script!`);
}
const origJs = match[1] as string;
console.log(origJs);
const minifyResult = uglifyjs.minify(origJs);
if(minifyResult.warnings != null) {
minifyResult.warnings.forEach(logger.warn);
}
if(minifyResult.error) {
throw new Error(`Can't minify the iframe template!`, {cause:minifyResult.error});
} else {
// replace orig js with minified js in code
return orig.replace(origJs, minifyResult.code);
}
}
总结一下:
这是我在节点应用程序中缩小的尝试(使用 [email protected])
import htmlMinifier from 'html-minifier';
function minifyWithHtmlMinifier(orig: string):string {
return htmlMinifier.minify(orig, {
minifyJS: true,
processScripts: ["text/javascript"],
ignoreCustomFragments: [/{{.*}}/g]
});
}
<!DOCTYPE html>
<html lang="en">
<head>
<title>Test ad</title>
</head>
<body onload="onLoad()">
<div id="img-container" style="width:100%;height:100%">test text in page</div>
<script type="text/javascript">
const longNameThatShouldBeUglified= 12;
console.log("test");
//{{another test}}
function onLoad() {
console.log("longNameThatShouldBeUglified (Not this time as it's a string) "+longNameThatShouldBeUglified);
}
</script>
</body>
</html>
html-minifier 不会给你任何警告。我以为我错误配置了 html-minifier,因为它没有缩小。
在分割我的代码以仅获取标签之间的内容并直接使用 uglify-js 后,我看到了问题并可以修复待缩小的代码。一旦它起作用,我就切换回使用 html-minifier 并且它起作用了。我现在使用以下代码,
告诉 html-minifier 使用包含在某些代码中的 uglify-js 来识别任何问题。
function minifyWithHtmlMinifier(orig: string):string {
return htmlMinifier.minify(orig, {
// I have replaced the default minifyJS usage of the html-minifier
// as this silently ignores any uglifyjs errors and just displays
// the non-minified code. Has cost me half a day to figure out
// that it was not a configuration problem but problem with the
// to-be-minified-code.
// By setting the call to uglifyjs myself I can catch the errors and
// rethrow them, failing fast, as this is much better than recognizing
// a not-minified code much later when I don't remember what I changed
minifyJS: (text, _inline) => {
const minifyResult = uglifyjs.minify(text, {
compress: {
drop_console: true // remove all console log entries
}
});
if(minifyResult.warnings != null) {
minifyResult.warnings.forEach(logger.warn);
}
if(minifyResult.error) {
// TODO maybe use terser. I think it supports
// newer ES versions than uglifyjs
throw new Error(`Can't minify the iframe template!`, {cause:minifyResult.error});
}
return minifyResult.code;
},
minifyCSS: true,
ignoreCustomFragments: [/{{.*}}/g], // handlebars fragments
collapseBooleanAttributes: true,
collapseInlineTagWhitespace: true,
collapseWhitespace: true
});
}
重要注意事项:
还有 html-minifier-terser 在我前期研究 Nodejs 中使用什么 Minifier 时并没有出现。也许它可以做更好的报告。