【问题标题】:Npm postinstall only on developmentNpm postinstall 仅用于开发
【发布时间】:2014-05-29 09:49:05
【问题描述】:

我有 npm 模块,下面有 package.json

{
  "name": "my-app",
  "version": "0.0.0",
  "scripts": {
    "prepublish": "bower install",
    "build": "gulp"
  },
  "dependencies": {
    "express": "~4.0.0",
    "body-parser": "~1.0.1"
  },
  "devDependencies": {
    "gulp": "~3.6.0",
    "bower": "~1.3.2"
  }
}

当我将应用程序部署到生产环境时,我不想安装 devDependecies,所以我运行 npm install --production。但是在这种情况下,prepublish 脚本被调用,但它不需要,因为我在生产中使用 CDN 链接。

如何只在npm install之后而不是在npm install --production之后调用postinstall脚本?

【问题讨论】:

    标签: javascript node.js continuous-integration npm


    【解决方案1】:

    较新的 npm (& Yarn) 版本包括对 prepare 脚本的支持,该脚本在每次 install 运行后运行,但仅在开发模式下运行。此外,prepublish 已弃用。这应该足够了:

    {
      scripts: {
        "prepare": "bower install"
      }
    }
    

    文档:https://docs.npmjs.com/misc/scripts

    【讨论】:

    • 现在看来,更高版本的 npm(例如 v6 和 v7)在开发和生产安装中都运行 prepare
    • 是的,这个答案是错误的。 npm 脚本 prepare 确实在 prod 和 dev 模式下运行。
    【解决方案2】:

    我认为您无法根据--production 参数选择运行哪些脚本。但是,您可以提供一个脚本来测试 NODE_ENV 变量,并且仅在它不是“生产”时运行 bower install

    如果你总是在 unix-y 环境中,你可以这样做:

    { 
      scripts: {
        "prepublish": "[ \"$NODE_ENV\" = production ] && exit 0; bower install"
      }
    }
    

    【讨论】:

    • 不错的答案!如果我还想包含“beta”环境怎么办?如何添加“生产或测试版”条件?
    • 然后它开始变得复杂——但你可以这样做"[ \"$NODE_ENV\" = production ] || [ \"$NODE_ENV\" = beta ] || bower install"
    • 如果我有这个脚本并在生产模式下运行它,我的 NPM 会失败,因为它返回一个非零退出代码。它适用于:[ \"$npm_config_production\" ] && exit 0; bower install[ \"$NODE_ENV\" == production ] && exit 0; bower install
    • 我认为值得根据最后的评论更新这个答案@SamMikes
    • 我认为如果这个答案推荐 cross-env 而不是使用 bash-only 结构会更好。这实际上更容易,您的构建将是跨平台的。
    【解决方案3】:

    这仅适用于您在类似 unix 的环境中:

    当使用 --production 运行安装时,NPM 将环境变量设置为“true”。要仅在 npm install 未使用 --production 运行时运行 postinstall 脚本,请使用以下代码。

    "postinstall": "if [ -z \"$npm_config_production\" ]; then node_modules/gulp/bin/gulp.js first-run; fi",
    

    【讨论】:

    • 谢谢!我只在 heroku 部署上使用反向构建资产:"postinstall": "if [ -n \"$npm_config_production\" ]; then npm run build-for-production; fi"
    【解决方案4】:

    我使用 windows、osx 和 linux,所以我使用非特定环境的解决方案来解决这个问题:

    postinstall 处理程序中,我执行一个 js 脚本来检查 process.env.NODE_ENV 变量并完成工作。

    在我的特定情况下,我必须仅在开发环境中执行 gulp 任务:

    package.json 的一部分

    "scripts": {
      "postinstall": "node postinstall"
    }
    

    所有 postinstall.js 脚本

    if (process.env.NODE_ENV === 'development') {
      const gulp = require('./gulpfile');
      gulp.start('taskname');
    }
    

    gulpfile.js 的最后一行

    module.exports = gulp;
    

    从 gulpfile.js 导出 gulp 很重要,因为所有任务都在那个特定的 gulp 实例中。

    【讨论】:

      【解决方案5】:

      较少依赖于 shell 的 unix 特性的解决方案:

        "scripts": {
          "postinstall": "node -e \"process.env.NODE_ENV != 'production' && process.exit(1)\" || echo do dev stuff"
        },
      

      【讨论】:

      • 当我将此模块作为依赖项添加到另一个模块并尝试 npm install 包含的模块时,此操作失败。修改命令链的返回值为我解决了这个问题:"(node -e \"process.env.NODE_ENV !== 'production' && process.exit()\" && grunt devTask) || node -v"
      【解决方案6】:

      我有一个更普遍的问题 - 我想跳过在本地(直接)安装上运行 postinstall 脚本 - 比如当我开发包并运行 yarn add --dev my-new-dependency 时。

      这就是我想出的。它适用于 npm 和 yarn。

      postinstall.js

      const env = process.env;
      if (
          // if INIT_CWD (yarn/npm install invocation path) and PWD
          // are the same, then local (dev) install/add is taking place
          env.INIT_CWD === env.PWD ||
          // local (dev) yarn install may have been run
          // from a project subfolder
          env.INIT_CWD.indexOf(env.PWD) === 0
      ) {
          console.info('Skipping `postinstall` script on local installs');
      }
      else {
          // do post-installation things
          // ...
      }
      

      package.json

      "script": {
          "postinstall": "node postinstall.js",
          ...
      

      【讨论】:

      【解决方案7】:

      登陆这里是因为我遇到了同样的问题。最终得到了一个解决方案,该解决方案测试 node_modules 下是否存在我知道应该只在开发中可用的包。

      {
        "scripts": {
          "postinstall": "bash -c '[ -d ./node_modules/@types ] && lerna run prepare || echo No postinstall without type info'" 
        }
      }
      

      这在概念上对我来说很好,因为这里由 lerna 调用的准备脚本主要用于 ts-to-js 编译。

      【讨论】:

        【解决方案8】:

        我正在使用if-env 模块。它不那么冗长。

        PS:我还没有在 windows 上测试过。

        安装方式:

        npm i if-env
        

        package.json 脚本:

        "postinstall-production": "echo \"production, skipping...\"",
        "postinstall-dev": "echo \"doing dev exclusive stuff\"",
        "postinstall": "if-env NODE_ENV=production && npm run postinstall-production || npm run postinstall-dev"
        

        【讨论】:

        • 这是否意味着if-env 必须在dependencies 而不是devDependencies
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-11-22
        • 2021-07-20
        • 2021-10-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-03-01
        相关资源
        最近更新 更多