在前端页面开发中,使用Vue、Angular、React等框架构建的项目通常都会自动配置集成相关代码压缩发布的工具,开发者只需要执行指定命令即可完成项目的整体压缩发布操作。对于没有使用框架的项目,需要开发者手动配置使用相关工具完成对应操作,本文介绍使用UglifyJS实现代码打包压缩的方法。
1、建立示例项目
按照一般项目目录添加目录及文件如下:
Demo目录为项目根目录,src目录下包含全部源文件。源文件包含一个index.html及其引用的三个js文件。
a.js包含了一个求和的方法:
b.js包含一个求积的方法:
index.js包含页面load方法,用于演示求和求积方法:
页面打开就显示两个运算结果:
此时,页面加载了全部的四个源文件,且都未经过压缩打包,能看到全部的源代码包括注释:
2、打包目标
为减少请求,将a.js、b.js、index.js合并为一个index.js(实际项目中根据实际需求考虑是否需要合并),使用一条指令(npm run build)就能完成打包发布操作。打包后文件存放于demo/dist/目录,不修改源文件。
3、安装UglifyJS
UglifyJS是个包含JS解释器、代码最小化、压缩、美化的工具集,是前端开发打包的最常用工具之一。UglifyJS基于Node.js开发,所以要确保安装了Node.js环境。首先使用指令完成项目的node初始化配置:
npm init -y
项目初始化完成后,为项目添加并安装UglifyJS依赖包:
npm install uglify-js --save-dev
以上步骤完成后,项目的打包工具就安装完成了,此时项目多了package.json及安装的node_modules:
4、配置打包指令及脚本
在package.json的脚本节点添加打包指令:
当使用npm run build 指令时就会调用 node build.js 执行build.js脚本文件。
接下来就是编写build.js脚本文件,在项目根目录新建build.js文件。
脚本文件需要完成的工作有:
4.1、清除原有dist目录中的文件。
编写清空目录方法,清空dist目录:
const fs = require('fs');
const path = require('path');
const UglifyJS = require("uglify-js");
//递归清空目录
function clearDirectory(dirPath) {
if (!(fs.existsSync(path) && fs.statSync(path).isDirectory())) return;
const files = fs.readdirSync(dirPath);
for (const file of files) {
const filePath = path.join(dirPath, file);
if (fs.statSync(filePath).isFile()) {
fs.unlinkSync(filePath);
} else {
clearDirectory(filePath);
fs.rmdirSync(filePath);
}
}
}
const targetDirectory = 'dist';
clearDirectory(targetDirectory);
4.2、将src目录中的文件全部拷贝到dist目录中
编写目录拷贝方法将src目录下文件全部拷贝到dist目录下:
//递归目录拷贝
function copyDirectory(sourceDir, targetDir) {
fs.mkdirSync(targetDir, { recursive: true });
const files = fs.readdirSync(sourceDir);
for (const file of files) {
const sourcePath = path.join(sourceDir, file);
const targetPath = path.join(targetDir, file);
if (fs.statSync(sourcePath).isFile()) {
fs.copyFileSync(sourcePath, targetPath);
} else {
copyDirectory(sourcePath, targetPath);
}
}
}
const sourceDirectory = 'src';
copyDirectory(sourceDirectory, targetDirectory);
4.3、将a.js、b.js、index.js 合并打包为新的index.js
调用UglifyJS将以上三个js打包合并为一个index.js:
let result = UglifyJS.minify({
"src/a.js": fs.readFileSync("src/a.js", "utf8"),
"src/b.js": fs.readFileSync("src/b.js", "utf8"),
"src/index.js": fs.readFileSync("src/index.js", "utf8")
});
fs.writeFileSync('dist/index.js', result.code);
4.4、删除index.html中多余的a.js和b.js引用
通过替换字符串的方式,删除index.html中多云的js引用:
//替换代码文件中的字符串
function replaceStringInFile(filePath, searchStr, replaceStr) {
let fileContent = fs.readFileSync(filePath, 'utf8');
const regex = new RegExp(searchStr, 'g');
fileContent = fileContent.replace(regex, replaceStr);
fs.writeFileSync(filePath, fileContent, 'utf8');
}
replaceStringInFile("dist/index.html", '<script src="a.js"></script>', '');
replaceStringInFile("dist/index.html", '<script src="b.js"></script>', '');
4.5、删除复制到dist中多余的a.js和b.js
//删除多余的文件
fs.unlinkSync("dist/a.js");
fs.unlinkSync("dist/b.js");
console.log("build done.");
5、打包结果
执行指令 npm run build,打包完成后项目根目录多了dist目录,里边包含了输出的文件:
dist目录中index.html已经去掉了a.js和b.js的引用,index.js是合并压缩后的代码:
function sum(e){let n=0;for(let t=0;t<e.length;t++)n+=e[t];return n}function multiply(e){let n=1;for(let t=0;t<e.length;t++)n*=e[t];return n}function load(){document.getElementById("pSum").innerText="sum([1,2,3,4,5])="+sum([1,2,3,4,5]),document.getElementById("pMultiply").innerText="multiply([1,2,3,4,5])="+multiply([1,2,3,4,5])}
发布版页面效果与开发版一致,但是加载文件少了,且js已经压缩:
6、开启source map
如果有需要在发布环境查看压缩前的源代码,可以在打包压缩的时候开启source map:
let result = UglifyJS.minify({
"src/a.js": fs.readFileSync("src/a.js", "utf8"),
"src/b.js": fs.readFileSync("src/b.js", "utf8"),
"src/index.js": fs.readFileSync("src/index.js", "utf8")
}, {
sourceMap: {
url: "index.js.map",
root: "../"
}
});
fs.writeFileSync('dist/index.js', result.code);
fs.writeFileSync('dist/index.js.map', result.map);
就是在调用UglifyJS.minify()方法时,多传了一个配置sourceMap的参数。
url: "index.js.map" 表示文件压缩后会自动在index.js的末尾加上指定映射文件url的注释代码:
root: "../" 用于指定源文件的位置,必须确保 root配置的值加上UglifyJS.minify()方法中第一个参数的key值所拼接的路径文件能够正常访问。本例中即必须确保 "../" 加上 "src/a.js", "../" 加上 "src/b.js","../" 加上 "src/index.js" 三个路径能正常访问,才能在页面加载时浏览器能自动通过隐射加载到对应源文件。
重新运行npm run build 可以发现dist目录下就多了一个index.js.map文件:
再看发布页面,浏览器会自动加载隐射的源文件,在压缩后的index.js中添加断点,会自动定位到源文件中对应的位置:
以上,项目打包发布差不多就这些了。