对外提供一个html,用户点击执行。产品只要对外提供一个html并且希望js做到加密。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
/* 样式 */
</style>
</head>
<body>
<div>--------</div>
</body>
<script>
// 内容
</script>
</html>
写好后使用gulp压缩加密
gulp实现
gulp.js
const gulp = require('gulp');
const htmlmin = require('gulp-html-minifier-terser');
const options = {
removeComments: true,//清除HTML注释
collapseWhitespace: true,//压缩HTML
minifyJS: true,//压缩页面JS
minifyCSS: true,//压缩页面CSS
};
gulp.task('minify', () => {
return gulp.src('*.html')
.pipe(htmlmin(options))
.pipe(gulp.dest('dist'));
});
// 默认任务
gulp.task('default', gulp.series('minify'));
感觉使用gulp总觉得太low。于是查找使用webpack
webpack做法
首先对文件进行拆分成 index.html index.js index.css。开始打包
const path = require('path');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const htmlPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
entry: {
entry: './src/index.js'
},
output: {
clean: true, // 先清空output
//输出的路径,用了Node语法
path: path.resolve(__dirname, 'dist'),
//输出的文件名称
filename: 'index.js'
},
externals: {},
mode: "production",
optimization: {
minimizer: [
new UglifyJsPlugin({
uglifyOptions: {
// 删除注释
output: {
comments: false,
},
compress: {
drop_console: true, // 删除所有调式带有console的
drop_debugger: true,
pure_funcs: ['console.log'] // 删除console.log
}
},
})
]
},
module: {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader, // 提取css生产css文件
{
loader: 'css-loader', // 放在后面的先被解析
options: {
}
}
]
}
]
},
plugins: [
new htmlPlugin({
minify: {
removeComments: true,//清除HTML注释
collapseWhitespace: true,//压缩HTML
minifyJS: true,//压缩页面JS
minifyCSS: true,//压缩页面CSS
},
hash: false,
inject: 'body', // js插入到body下面
template: './src/index.html'
}),
new MiniCssExtractPlugin(), // 提取css生成文件
],
devServer: {
static: {
directory: path.resolve(__dirname, 'dist')
},
// hot: false,
compress: true,
open: true,
liveReload: true, // 只监听js变化 当检测到文件更改时,开发服务器将重新加载/刷新页面。devServer.hot选项必须禁用或devServer.watchFiles选项必须启用, 以便liveReload生效。禁用devServer.liveReload设置为false来重新加载:
port: 8086
}
}
这样打包出来后是通过src引入的。不符合我们要求。
自己写plugin
plugin.js
const HtmlWebpackPlugin = require('html-webpack-plugin');
class MyPlugin {
constructor({ match }) {
this.match = match;
}
processTags(data, compilation) {
let headTags = [];
let bodyTags = [];
console.log(data.headTags);
console.log(data.bodyTags);
console.log('--------------');
data.headTags.forEach((headTag) => {
// js 放到下面
if (headTag.tagName === 'script') {
bodyTags.push(this.processTag(headTag, compilation))
} else {
headTags.push(this.processTag(headTag, compilation))
}
});
data.bodyTags.forEach((bodyTag) => {
bodyTags.push(this.processTag(bodyTag, compilation))
});
return {
...data,
headTags,
bodyTags
}
}
//处理每个link和script标签。
processTag(tag, compilation) {
let newTag, url;
// if (tag.tagName === "link" && this.match.includes(tag.attributes.href)) {
if (tag.tagName === "link") {
newTag = {
tagName: "style",
attributes: {
type: "text/css"
}
}
url = tag.attributes.href;
}
// if (tag.tagName === "script" && this.match.includes(tag.attributes.src)) {
if (tag.tagName === "script") {
newTag = {
tagName: "script",
attributes: {
type: "application/javascript"
}
}
url = tag.attributes.src;
};
if (url) {
// 通过compilation.assets[文件地址]可以获取到每个文件的内容。
newTag.innerHTML = compilation.assets[url].source();
delete compilation.assets[url]; // 删除原来的资源,不让生成文件
return newTag;
}
return tag;
}
apply(compiler) {
// console.log("compiler:", compiler.hooks)
// 要通过webpack-plugin来实现这个功能
compiler.hooks.compilation.tap("MyPlugin", (compilation) => {
// 调用html-webpack-plugin的内部的钩子alterAssetTagGroups。
HtmlWebpackPlugin.getHooks(compilation).alterAssetTagGroups.tapAsync(
'MyPlugin', (data, callback) => {
data = this.processTags(data, compilation);
callback(null, data)
}
)
})
}
}
module.exports = MyPlugin;
webpack.config.js
const path = require('path');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const htmlPlugin = require('html-webpack-plugin');
const MyPlugin = require('./myPlugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
//入口文件的配置项
entry: {
entry: './src/index.js'
},
//出口文件的配置项
output: {
clean: true, // 先清空output
//输出的路径,用了Node语法
path: path.resolve(__dirname, 'dist'),
//输出的文件名称
filename: 'index.js'
},
externals: {},
mode: "production",
optimization: {
minimizer: [
new UglifyJsPlugin({
uglifyOptions: {
// 删除注释
output: {
comments: false,
},
compress: {
drop_console: true, // 删除所有调式带有console的
drop_debugger: true,
pure_funcs: ['console.log'] // 删除console.log
}
},
})
]
},
// //模块:例如解读CSS,图片如何转换,压缩
module: {
rules: [
{
test: /\.css$/,
use: [
// {
// loader: 'style-loader', // 把css放到js里面
// },
MiniCssExtractPlugin.loader, // 提取css生产css文件
{
loader: 'css-loader', // 放在后面的先被解析
options: {
}
}
]
}
]
},
//插件,用于生产模版和各项功能 多个插件,所以是数组
plugins: [
new htmlPlugin({
minify: {
removeComments: true,//清除HTML注释
collapseWhitespace: true,//压缩HTML
minifyJS: true,//压缩页面JS
minifyCSS: true,//压缩页面CSS
},
hash: false,
inject: 'body', // js插入到body下面
template: './src/index.html'
}),
new MiniCssExtractPlugin(), // 提取css生成文件
new MyPlugin({ // 变成内联
match: ['index.js']
}),
],
//配置webpack开发服务功能
devServer: {
static: {
directory: path.resolve(__dirname, 'dist')
},
// hot: false,
compress: true,
open: true,
liveReload: true, // 只监听js变化 当检测到文件更改时,开发服务器将重新加载/刷新页面。devServer.hot选项必须禁用或devServer.watchFiles选项必须启用, 以便liveReload生效。禁用devServer.liveReload设置为false来重新加载:
port: 8086
}
}