# 前言
在公司里负责的前端项目每次去改通用的模块都需要一个个去打包,非常麻烦。在寻找解决方案时找到了 shelljs ,就尝试写了个打包脚本。
# 开始
项目目录
├─project // 总文件夹 | |
│ ├─projectA // 项目 A | |
│ ├─projectB // 项目 B | |
│ ├─projectC // 项目 C | |
│ ├─ ... //...... |
在 project 目录下执行 npm init -y
,接着下载依赖包。
使用 npm
npm install shelljs |
创建 build.js 文件,开始编写打包脚本
引入 shell.js fs
// build.js | |
const shell = require("shelljs"); | |
const fs = require("fs"); |
获取当前目录下所有项目
const filesPath = fs.readdirSync(__dirname).filter(e => fs.statSync(__dirname + "/" + e).isDirectory()); |
打包函数
// 因为文档中没找到 exec 的同步方法,所以写了一个 Promise | |
shell.execSync = (command, options) => new Promise((resolve, reject) => { | |
try { | |
shell.exec(command, options, resolve); | |
} catch (error) { | |
reject(error); | |
} | |
}); | |
const buildFiles = async (files) => { | |
const success = [], fail = []; | |
for (const i in files) { | |
const e = files[i]; | |
shell.cd(__dirname + "/" + e); | |
try { | |
await shell.execSync("npm run build", { async: true, slient: true }); | |
success.push(e); | |
} catch (error) { | |
fail.push(e); | |
} | |
} | |
console.log(`打包任务执行完毕,打包成功数量:${success.length},打包失败数量:${fail.length}`); | |
if (fail.length > 0) { | |
console.log(`打包失败列表如下:\n${fail.join('\n')}`); | |
} | |
}; |
在 project 目录的 package.json 中添加
"scripts": { | |
"build": "node build.js", | |
} |
在 buid.js 中调用方法
const [nodeEnv, dir, ...args] = process.argv; | |
if (args.length == 0) { | |
// 打包所有文件 | |
buildFiles(filesPath); | |
} else { | |
// 打包指定文件 可多个 npm run build 项目名称 1 项目名称 2...... | |
const buildArgs = args.filter(v => { | |
if (filesPath.includes(v)) return true; | |
console.log(`err:文件${v}不存在`); | |
return false; | |
}); | |
buildFiles(buildArgs); | |
} |
打包功能算是完成了,在 project 目录下执行 npm run build
就可以打包所有的项目了,也可以指定项目 npm run build projectA
。
# 压缩 dist
虽然批量打包已经实现了,但是把打包后的文件部署到服务器时还是要一个个目录去压缩上传。所以接下来使用 archiver
压缩打包后的 dist 文件并放在同一个目录。
下载 archiver
npm install archiver --save |
最终 build.js
// build.js | |
const shell = require("shelljs"); | |
const fs = require("fs"); | |
const archiver = require('archiver'); | |
shell.execSync = (command, options) => new Promise((resolve, reject) => { | |
try { | |
shell.exec(command, options, resolve); | |
} catch (error) { | |
reject(error); | |
} | |
}); | |
const clearDist = (name) => { | |
console.log(`开始清理文件 distOut/${name}.zip`); | |
try { | |
if (name) { | |
shell.rm('-rf', `distOut/${name}.zip`); | |
} else { | |
shell.rm('-rf', 'distOut/*'); | |
} | |
console.log('清理完成'); | |
} catch (error) { | |
console.log(error); | |
} | |
}; | |
const dirname = __dirname; | |
const creatZip = (name) => { | |
try { | |
console.log(`开始压缩文件${name}/dist`); | |
const output = fs.createWriteStream(`${dirname}/distOut/${name}.zip`); | |
const archive = archiver('zip', { | |
zlib: { level: 9 } | |
}); | |
output.on('close', () => { | |
console.log(archive.pointer() + ' total bytes'); | |
console.log('压缩完成!'); | |
}); | |
archive.on('error', (err) => { | |
throw err; | |
}); | |
archive.pipe(output); | |
archive.directory(`${dirname}/${name}/dist`, false); | |
archive.finalize(); | |
} catch (error) { | |
console.log(error); | |
} | |
}; | |
const filesPath = fs.readdirSync(__dirname).filter(e => fs.statSync(__dirname + "/" + e).isDirectory() && e != 'distOut'); | |
const buildFiles = async (files) => { | |
if (!fs.existsSync('./distOut')) { | |
fs.mkdirSync(`distOut`); | |
} | |
console.log(`开始执行打包任务\n检测文件数量为${files.length}`); | |
const success = [], fail = []; | |
for (const i in files) { | |
const e = files[i]; | |
console.log(`开始打包第${i * 1 + 1}个,${e}`); | |
shell.cd(__dirname + "/" + e); | |
try { | |
await shell.execSync("npm run build", { async: true, slient: true }); | |
success.push(e); | |
console.log(`第${i * 1 + 1}个${e}打包完成!`); | |
clearDist(e); | |
creatZip(e); | |
} catch (error) { | |
fail.push(e); | |
console.log(`第${i * 1 + 1}个${e}打包失败!`); | |
} | |
} | |
console.log(`打包任务执行完毕,打包成功数量:${success.length},打包失败数量:${fail.length}`); | |
if (fail.length > 0) { | |
console.log(`打包失败列表如下:\n${fail.join('\n')}`); | |
} | |
}; | |
const [nodeEnv, dir, ...args] = process.argv; | |
if (args.length == 0) { | |
// 打包所有文件 | |
buildFiles(filesPath); | |
} else { | |
// 打包指定文件 可多个 npm run build 项目名称 1 项目名称 2...... | |
const buildArgs = args.filter(v => { | |
if (filesPath.includes(v)) return true; | |
console.log(`err:文件${v}不存在`); | |
return false; | |
}); | |
buildFiles(buildArgs); | |
} |