环境
node v16.10.0 npm v8.3.0
在使用
npm
管理第三方模块时,这些模块通常会被安装在
node_modules
目录下。当我们需要把模块给其他小伙伴或者搭建
npm
私服时,需要将
node_modules
的所有模块生成N个
packname-version.tgz
文件,方便其他小伙伴使用
npm install packname-version.tgz
命令安装或者使用
npm publish packname-version.tgz
命令发布到私服时,这个
nodejs
脚本或许对你有一些帮助🎉。
下面是实现这一功能的脚本,具体实现过程如下:
1. 遍历目录,查找所有的
package.json
文件
首先,我们需要遍历
node_modules
目录,查找所有的
package.json
文件,这里我们使用递归实现。
functionfindPackageJson(directory){const results =[];const files = fs.readdirSync(directory);for(const file of files){const filePath = path.join(directory, file);const stat = fs.statSync(filePath);if(stat.isDirectory()){
results.push(...findPackageJson(filePath));}elseif(file ==="package.json"){
results.push(filePath);}}return results;}
2. 执行
npm pack
命令,生成
.tgz
文件
接下来,我们需要执行
npm pack
命令,生成一个压缩文件,这里我们使用
child_process
模块的
exec
方法来执行命令。
functionpackModule(moduleDir){returnnewPromise((resolve, reject)=>{exec("npm pack",{cwd: moduleDir },(err, stdout, stderr)=>{if(err){reject(err);}else{const tgzFile = path.join(moduleDir,`${stdout.trim()}`);resolve(tgzFile);}});});}
在执行完
npm pack
命令后,会在当前目录下生成一个以模块名为前缀的压缩文件,例如:
lodash-4.17.21.tgz
。
3. 移动
.tgz
文件到
packs
目录
最后,我们需要将生成的压缩文件移动到指定的目录下,这里我们使用
fs
模块的
renameSync
方法实现。
functionmoveTgzFile(tgzFile){const fileName = path.basename(tgzFile);const destFile = path.join(packsDir, fileName);
fs.renameSync(tgzFile, destFile);
console.log(`Moved ${fileName} to ${destFile}`);}
将以上三个步骤结合起来,就可以实现将所有依赖包打包成压缩文件,并将其移动到指定目录下的功能了。
完整代码
// 根据 node modules下的依赖 利用npm pack 命令生成xxx.tgz依赖包 并放在packs目录下const fs =require("fs");const path =require("path");const{ exec }=require("child_process");// C:\Users\Lenovo\Desktop\pack\node_modulesconst modulesDir = path.join(__dirname,"node_modules");const packsDir = path.join(__dirname,"packs");// 遍历目录,查找所有的 package.json 文件functionfindPackageJson(directory){const results =[];const files = fs.readdirSync(directory);for(const file of files){const filePath = path.join(directory, file);const stat = fs.statSync(filePath);if(stat.isDirectory()){
results.push(...findPackageJson(filePath));}elseif(file ==="package.json"){
results.push(filePath);}}return results;}// 执行 `npm pack` 命令,生成 `.tgz` 文件functionpackModule(moduleDir){returnnewPromise((resolve, reject)=>{exec("npm pack",{cwd: moduleDir },(err, stdout, stderr)=>{if(err){reject(err);}else{const tgzFile = path.join(moduleDir,`${stdout.trim()}`);resolve(tgzFile);}});});}// 移动 `.tgz` 文件到 `packs` 目录functionmoveTgzFile(tgzFile){const fileName = path.basename(tgzFile);const destFile = path.join(packsDir, fileName);
fs.renameSync(tgzFile, destFile);
console.log(`Moved ${fileName} to ${destFile}`);}// 查找所有的 package.json 文件,执行 `npm pack`,并移动生成的 `.tgz` 文件findPackageJson(modulesDir).forEach((packageJsonFile)=>{const moduleDir = path.dirname(packageJsonFile);packModule(moduleDir).then(moveTgzFile).catch((err)=> console.error(`Error packing ${moduleDir}: ${err.message}`));});
思考
当
node_modules
里的模块很多时,这个脚本的运行时间可能会很长(
old cpu
🤣),所以还有很多优化空间,仔细观察
node_modules
文件夹的目录结构会发现当目录名称包含
@
符号时,这个目录下可能存在多个依赖包 ,普通目录一个依赖包。所以
findPackageJson
方法可以做如下优化:
// 遍历目录 当目录下存在 package.json 文件时 退出当前循环functionfindPackageJson(directory){const results =[];const files = fs.readdirSync(directory);for(const file of files){const filePath = path.join(directory, file);const stat = fs.statSync(filePath);if(stat.isDirectory()){const packagePath = path.join(filePath,"package.json")if(fs.existsSync(packagePath)){
results.push(packagePath);continue;}
results.push(...findPackageJson(filePath));}}return results;}
版权归原作者 幻雪暗影 所有, 如有侵权,请联系我们删除。