npm pack 命令生成离线npm模块/npm依赖包

环境

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 文件,这里我们使用递归实现。

function findPackageJson(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));
    } else if (file === "package.json") {
      results.push(filePath);
    }
  }
  return results;
}

2. 执行 npm pack 命令,生成 .tgz 文件

接下来,我们需要执行 npm pack 命令,生成一个压缩文件,这里我们使用 child_process 模块的 exec 方法来执行命令。

function packModule(moduleDir) {
  return new Promise((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 方法实现。

function moveTgzFile(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_modules
const modulesDir = path.join(__dirname, "node_modules");
const packsDir = path.join(__dirname, "packs");

// 遍历目录,查找所有的 package.json 文件
function findPackageJson(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));
    } else if (file === "package.json") {
      results.push(filePath);
    }
  }
  return results;
}

// 执行 `npm pack` 命令,生成 `.tgz` 文件
function packModule(moduleDir) {
  return new Promise((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` 目录
function moveTgzFile(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 文件时 退出当前循环
function findPackageJson(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;
}
  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要将一个模块npm 本地,可以按照以下步骤进行操作: 1. 在模块的根目录下创建一个 `package.json` 文件,其中模块的名称、版本、描述等信息。可以使用 `npm init` 命令来自动生成这个文件,然后根据需要进行编辑。 2. 将模块的源代码和相关文件放在一个目录中,例如 `src` 目录。 3. 在模块的根目录下创建一个 `index.js` 文件,该文件是模块的入口文件,用于导出模块的功能。在这个文件中,可以使用 `module.exports` 语句来导出模块中的函数、变量等。例如: ```javascript module.exports = { greet: function(name) { console.log('Hello, ' + name + '!'); } }; ``` 4. (可选)如果模块依赖其他的模块,可以在 `package.json` 文件的 `dependencies` 字段中列出这些依赖项。例如: ```json { "name": "my-module", "version": "1.0.0", "description": "My awesome module", "dependencies": { "lodash": "^4.17.21" } } ``` 5. 在模块的根目录下执行以下命令模块为一个本地压缩: ``` npm pack ``` 6. 执行完上述命令后,会在模块的根目录下生成一个类似于 `my-module-1.0.0.tgz` 的压缩。这个文件就是我们的 npm 本地了。 7. 要在本地项目中使用这个本地,可以使用以下命令进行安装: ``` npm install /path/to/my-module-1.0.0.tgz ``` 其中 `/path/to/my-module-1.0.0.tgz` 是本地的路径。安装完成后,就可以在项目中使用这个模块了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值