【问题标题】:Is there a way to get version from package.json in nodejs code?有没有办法从 nodejs 代码中的 package.json 获取版本?
【发布时间】:2012-02-27 13:00:20
【问题描述】:

有没有办法在 nodejs 应用程序中获取 package.json 中设置的版本?我想要这样的东西

var port = process.env.PORT || 3000
app.listen port
console.log "Express server listening on port %d in %s mode %s", app.address().port, app.settings.env, app.VERSION

【问题讨论】:

  • 获取Node的版本重要还是package.json中声明的版本重要?如果是表单,这将为您提供运行版本:console.log(process.version)

标签: node.js npm version versioning package.json


【解决方案1】:

我发现以下代码片段最适合我。由于它使用require 加载package.json,因此无论当前工作目录如何,它都能正常工作。

var pjson = require('./package.json');
console.log(pjson.version);

警告,由@Pathogen提供:

使用 Browserify 执行此操作会产生安全隐患。
请注意不要将您的 package.json 暴露给客户端,因为这意味着您的所有依赖项版本号、构建和测试命令等都将发送给客户端。
如果你在同一个项目中构建服务器和客户端,你也会暴露你的服务器端版本号。 攻击者可以使用此类特定数据来更好地适应对您服务器的攻击。

【讨论】:

  • 如果你一直因为试图从不同的地方抓取它而被烧伤(就像我一样),你可以这样做require('root-require')('package.json').version
  • 在全局安装了 shebang 的情况下不适用于我的脚本。 Error: Cannot find module 'package.json'.
  • 更短 - 要求('./package').version
  • 警告!使用 browserify 执行此操作具有安全隐患:您的包中的 package.json 意味着您的所有依赖项版本号、构建和测试命令等都将发送到客户端。如果你在同一个项目中构建服务器和客户端,你也会暴露你的服务器端版本号。
  • @Pathogen genversion 解决了客户端的问题。它是一个从 package.json 读取版本并从中生成可导入模块的工具。免责声明:我是维护者。
【解决方案2】:

NPM 一个班轮:

来自npm v7.20.0

npm pkg get version

在 npm v7.20.0 之前:

npm -s run env echo '$npm_package_version'

请注意,这两种方法的输出略有不同:前者输出带引号的版本号(即"1.0.0"),后者不输出(即1.0.0)。

【讨论】:

    【解决方案3】:

    一个安全的选择是添加一个生成单独版本文件的 npm 脚本:

    "scripts": {
        "build": "yarn version:output && blitz build",
        "version:output": "echo 'export const Version = { version: \"'$npm_package_version.$(date +%s)'\" }' > version.js"
      }
    

    这会输出 version.js 的内容:

    export const Version = { version: "1.0.1.1622225484" }
    

    【讨论】:

      【解决方案4】:

      如果您正在寻找module (package.json: "type": "module")(ES6 导入)支持,例如来自重构 commonJS,您应该(在撰写本文时)执行以下任一操作:

      import { readFile } from 'fs/promises';
      
      const pkg = JSON.parse(await readFile(new URL('./package.json', import.meta.url)));
      
      console.log(pkg.version)
      

      或者,使用node --experimental-json-modules index.js 运行节点进程来做:

      import pkg from './package.json'
      console.log(pkg.version)
      

      但是,在 json 模块普遍可用之前,您会收到警告。

      如果您遇到语法或(顶级)异步错误,您可能使用的是较旧的节点版本。至少更新到 node@14。

      【讨论】:

        【解决方案5】:

        用于像这样对网络组件进行版本控制:

        const { version } = require('../package.json')
        
        class Widget extends HTMLElement {
        
          constructor() {
            super()
            this.attachShadow({ mode: 'open' })
          }
        
          public connectedCallback(): void {
            this.renderWidget()
          }
        
          public renderWidget = (): void => {
            this.shadowRoot?.appendChild(this.setPageTemplate())
            this.setAttribute('version', version)
          }
        }
        
        

        【讨论】:

          【解决方案6】:

          如果您想获取目标包的版本。

          import { version } from 'TARGET_PACKAGE/package.json';
          

          示例:

          import { version } from 'react/package.json';
          

          【讨论】:

            【解决方案7】:

            如果您的应用程序使用npm start 启动,您可以简单地使用:

            process.env.npm_package_version
            

            更多详情请见package.json vars

            【讨论】:

            • 这可能是最好的答案,因为 package.json 中的大部分信息都附加到流程运行时变量中
            • 是的,我同意。这应该是正确的答案,使用您不需要打开并再次读取 package.json 文件的流程变量。
            • 在节点之外(例如,通过npm run … 执行的shell 脚本)版本将在环境变量$npm_package_version 中。
            • 当从另一个包的脚本调用时,这会错误地报告 calling 包的版本,而不是 calling 包的版本。
            • 它适用于以npm start 开头的electron 应用程序,但不适用于构建的电子应用程序:为此,您可以在app.getVersion 中找到它。
            【解决方案8】:

            我正在使用 gitlab ci 并希望自动使用不同的版本来标记我的 docker 图像并推送它们。现在他们的默认 docker 镜像不包括节点,所以我在 shell 中执行此操作的版本是这个

            脚本/getCurrentVersion.sh

            BASEDIR=$(dirname $0)
            cat $BASEDIR/../package.json | grep '"version"' | head -n 1 | awk '{print $2}' | sed 's/"//g; s/,//g'
            

            现在这样做是

            1. 打印你的包 json
            2. 搜索带有“版本”的行
            3. 只取第一个结果
            4. 替换“和,”

            请注意,我的脚本位于存储库中具有相应名称的子文件夹中。所以如果你不把 $BASEDIR/../package.json 改成 $BASEDIR/package.json

            或者,如果您希望能够获得主要、次要和补丁版本,我使用这个

            脚本/getCurrentVersion.sh

            VERSION_TYPE=$1
            BASEDIR=$(dirname $0)
            VERSION=$(cat $BASEDIR/../package.json | grep '"version"' | head -n 1 | awk '{print $2}' | sed 's/"//g; s/,//g')
            
            if [ $VERSION_TYPE = "major" ]; then
              echo $(echo $VERSION | awk -F "." '{print $1}' )
            elif [ $VERSION_TYPE = "minor" ]; then
              echo $(echo $VERSION | awk -F "." '{print $1"."$2}' )
            else
              echo $VERSION
            fi
            

            如果您的版本是 1.2.3,请使用此方法。你的输出应该是这样的

            $ > sh ./getCurrentVersion.sh major
            1
            
            $> sh ./getCurrentVersion.sh minor
            1.2
            
            $> sh ./getCurrentVersion.sh
            1.2.3
            

            现在您唯一需要确保的是您的包版本将是 package.json 中第一次使用该密钥,否则您最终会得到错误的版本

            【讨论】:

              【解决方案9】:

              或者在普通的旧外壳中:

              $ node -e "console.log(require('./package.json').version);"
              

              这可以缩短为

              $ node -p "require('./package.json').version"
              

              【讨论】:

              • 尽管按照要求,这不在 nodeJS 应用程序本身内。
              • 我用过这个,但它停止工作,节点 16 告诉我 SyntaxError: Unexpected token '.' - 有什么想法吗?
              【解决方案10】:

              const { version } = require("./package.json");
              console.log(version);
              
              const v = require("./package.json").version;
              console.log(v);

              【讨论】:

                【解决方案11】:

                我找到的最精简的方式:

                const { version } = JSON.parse(fs.readFileSync('./package.json'))
                

                【讨论】:

                  【解决方案12】:

                  选项 1

                  最佳实践是使用 npm 环境变量从 package.json 版本化。

                  process.env.npm_package_version
                  

                  更多信息:https://docs.npmjs.com/using-npm/config.html

                  这仅在您使用 NPM 命令启动服务时才有效。

                  快速信息:您可以使用 process.env.npm_package_[keyname] 读取 pacakge.json 中的任何值

                  选项 2

                  使用https://www.npmjs.com/package/dotenv作为.env文件在环境变量中设置版本并将其读取为process.env.version

                  【讨论】:

                  • 干净整洁。谢谢!
                  • 我是undefined
                  • @Boris - 您正在尝试选项 1 或 2?
                  • 节点 14 上的选项 1,使用 ES 模块。也许是因为我正在使用node index.js 运行我的代码。如何通过 npm 运行 "bin": "my-bin.js"
                  【解决方案13】:

                  下面是如何从 package.json 中读取版本:

                  fs = require('fs')
                  json = JSON.parse(fs.readFileSync('package.json', 'utf8'))
                  version = json.version
                  

                  编辑:哇,这个答案最初来自 2012 年!现在有几个更好的答案。可能最干净的是:

                  const { version } = require('./package.json');
                  

                  【讨论】:

                  • 我看过很多,我很喜欢 - 你/任何人知道require() introduces? (for instance, does require()`不支持utf8阅读的注意事项吗?正如您的 sn-p 可能建议的那样)
                  • require() 缓存文件,在这种情况下应该没有区别。
                  • @jlee 人们在想要重新加载时通常使用JSON.parse(fs.readFileSync('package.json', 'utf8')) 而不是delete require.cache[require.resolve('package.json')]; require('package.json') 有什么原因吗?
                  • const { 版本 } = require('./package.json');
                  【解决方案14】:

                  如果使用 rollup,可以使用 rollup-plugin-replace 插件添加版本,而不会将 package.json 暴露给客户端。

                  // rollup.config.js
                  
                  import pkg from './package.json';
                  import { terser } from "rollup-plugin-terser";
                  import resolve from 'rollup-plugin-node-resolve';
                  import commonJS from 'rollup-plugin-commonjs'
                  import replace from 'rollup-plugin-replace';
                  
                  export default {
                    plugins: [
                      replace({
                        exclude: 'node_modules/**',
                        'MY_PACKAGE_JSON_VERSION': pkg.version, // will replace 'MY_PACKAGE_JSON_VERSION' with package.json version throughout source code
                      }),
                    ]
                  };
                  

                  然后,在源代码中,无论您想在哪里获得 package.json 版本,都可以使用字符串“MY_PACKAGE_JSON_VERSION”。

                  // src/index.js
                  export const packageVersion = 'MY_PACKAGE_JSON_VERSION' // replaced with actual version number in rollup.config.js
                  

                  【讨论】:

                    【解决方案15】:

                    有两种获取版本的方法:

                    1. 需要package.json 并获取版本:
                    const { version } = require('./package.json');
                    
                    1. 使用环境变量:
                    const version = process.env.npm_package_version;
                    

                    请不要使用JSON.parsefs.readFilefs.readFileSync,也不要使用另一个npm modules,这个问题没有必要。

                    【讨论】:

                    • 感谢您提供此代码 sn-p,它可能会提供一些有限的即时帮助。 proper explanation would greatly improve its long-term value 通过展示为什么这是一个很好的解决问题的方法,并将使其对未来有其他类似问题的读者更有用。请edit您的回答添加一些解释,包括您所做的假设。
                    • 那么 npm_* 环境值仅在您的脚本由 NPM 启动时可用,例如npm start。如果你正在做node app.js 或类似的,他们将不会出现。
                    • @Nate 所以最好使用package.json的版本?
                    • 您还可以将脚本 "start": "node app.js" 添加到您的 package.json 并使用 npm start 启动您的应用程序——这将为您提供 npm env vars
                    【解决方案16】:

                    为什么不使用 require 解析...

                    const packageJson = path.dirname(require.resolve('package-name')) + '/package.json';
                    const { version } = require(packageJson);
                    console.log('version', version)
                    

                    这种方法适用于所有子路径:)

                    【讨论】:

                      【解决方案17】:

                      要确定节点代码中的包版本,您可以使用以下内容:

                      1. const version = require('./package.json').version; 用于

                      2. import {version} from './package.json'; 用于 ES6 版本

                      3. const version = process.env.npm_package_version; 如果应用程序已使用npm start 启动,则所有 npm_* 环境变量都可用。

                      4. 您也可以使用以下 npm 包 - root-require、pkginfo、project-version。

                      【讨论】:

                        【解决方案18】:

                        您可以使用 ES6 导入 package.json 来检索版本号并在控制台输出版本。

                        import {name as app_name, version as app_version}  from './path/to/package.json';
                        
                        console.log(`App ---- ${app_name}\nVersion ---- ${app_version}`);
                        

                        【讨论】:

                        • 只要你在 tsconfig.json 中将 "resolveJsonModule" 设置为 "true" 就可以了。
                        【解决方案19】:

                        我做了一个有用的代码来获取父模块的package.json

                        function loadParentPackageJson() {
                            if (!module.parent || !module.parent.filename) return null
                            let dir = path.dirname(module.parent.filename)
                            let maxDepth = 5
                            let packageJson = null
                            while (maxDepth > 0) {
                                const packageJsonPath = `${dir}/package.json`
                                const exists = existsSync(packageJsonPath)
                                if (exists) {
                                    packageJson = require(packageJsonPath)
                                    break
                                }
                                dir = path.resolve(dir, '../')
                                maxDepth--
                            }
                            return packageJson
                        }
                        

                        【讨论】:

                          【解决方案20】:

                          将您的package.json 文件导入您的server.jsapp.js,然后将package.json 属性访问到服务器文件中。

                          var package = require('./package.json');
                          

                          package 变量包含 package.json 中的所有数据。

                          【讨论】:

                            【解决方案21】:

                            对于那些寻找安全的客户端解决方案,也适用于服务器端的人,有genversion。它是一个命令行工具,可以从最近的 package.json 中读取版本并生成导出版本的可导入 CommonJS 模块文件。免责声明:我是维护者。

                            $ genversion lib/version.js
                            

                            我承认客户端安全不是 OP 的主要意图,但正如 Mark Wallaceaug 的回答中所讨论的,它高度相关,也是我找到此问答的原因。

                            【讨论】:

                            • 这就是答案,它需要更多的选票才能超越现在最有问题的答案。
                            • 有些人可能会因为这是一个命令行工具而感到震惊。不用担心!该工具的自述文件描述了如何(轻松)将 build 调用集成到 package.json 中,这样您就可以忘记该工具的存在,并且始终拥有最新的版本号。
                            • 这应该是正确的答案。谢谢@Akseli。
                            • 是的!这是正确的答案。没有人应该将他们的 package.json 文件与他们的应用一起发送。
                            • @EricJorgensen 非常棒,谢谢 :) 我可以引用您对 genversion 存储库 README.md 的评论吗?
                            【解决方案22】:

                            只是添加一个答案,因为我来这个问题是为了了解将 package.json 中的版本包含在我的 Web 应用程序中的最佳方法。

                            我知道这个问题是针对 Node.js 的,但是,如果您使用 Webpack 来捆绑您的应用程序,建议您使用DefinePlugin 在配置中声明一个全局版本并引用它。所以你可以在你的webpack.config.json

                            const pkg = require('../../package.json');
                            
                            ...
                            
                            plugins : [
                                new webpack.DefinePlugin({
                                  AppVersion: JSON.stringify(pkg.version),
                            ...
                            

                            然后AppVersion 现在是一个可供您使用的全局变量。还要确保在您的.eslintrc you ignore this via the globals prop

                            【讨论】:

                              【解决方案23】:

                              您可以使用project-version 包。

                              $ npm install --save project-version
                              

                              然后

                              const version = require('project-version');
                              
                              console.log(version);
                              //=>  '1.0.0'
                              

                              它使用process.env.npm_package_version,但回退到package.json中编写的版本,以防由于某种原因缺少env var。

                              【讨论】:

                              • 比如js文件不是从npm启动的?
                              【解决方案24】:

                              我知道这不是 OP 的意图,但我不得不这样做,所以希望它可以帮助下一个人。

                              如果您在 CI/CD 流程中使用 docker-compose,您可以通过这种方式获得它!

                              version:
                                image: node:7-alpine
                                volumes:
                                  - .:/usr/src/service/
                                working_dir: /usr/src/service/
                                command: ash -c "node -p \"require('./package.json').version.replace('\n', '')\""
                              

                              对于图像,您可以使用任何节点图像。我使用 alpine 因为它是最小的。

                              【讨论】:

                                【解决方案25】:

                                使用 ES6 模块,您可以执行以下操作:

                                import {version} from './package.json';
                                

                                【讨论】:

                                • 我认为节点不支持这些:github.com/nodejs/help/issues/53
                                • 没有 es6 模块还没有被直接支持,但无论如何都是常用的,使用 Babel 启用
                                • @Sornii 不,整个 package.json 将在客户端中。我使用 webpack 的 definePlugin 仅将选定的信息从节点环境传递到浏览器。
                                • stackoverflow.com/a/10855054/540144 中指定的任何安全隐患?
                                • 是的,同样的安全问题。整个 package.json 将包含在客户端包中。
                                【解决方案26】:

                                我用findup-sync 做这个:

                                var findup = require('findup-sync');
                                var packagejson = require(findup('package.json'));
                                console.log(packagejson.version); // => '0.0.1' 
                                

                                【讨论】:

                                • findup 以 cwd 开头,因此在大多数情况下,它只会获得顶级 package.json,类似于 process.env.npm_package_version,除了不需要通过 npm 启动它。因此,尝试获取您的库版本实际上会获取调用者的版本。一个简单的 require('./package.json') 可以避免这种情况。
                                【解决方案27】:

                                还有另一种从package.json 文件中获取特定信息的方法,即使用pkginfo 模块。

                                这个模块的使用非常简单。您可以使用以下方式获取所有包变量:

                                require('pkginfo')(module);
                                

                                或者只有某些细节(在这种情况下是version

                                require('pkginfo')(module, 'version');
                                

                                您的包变量将设置为module.exports(因此可以通过module.exports.version 访问版本号)。

                                您可以使用以下代码 sn-p:

                                require('pkginfo')(module, 'version');
                                console.log "Express server listening on port %d in %s mode %s", app.address().port, app.settings.env, module.exports.version
                                

                                这个模块有一个非常好的特性——它可以在你项目中的任何文件中使用(例如在子文件夹中),它会自动从你的package.json获取信息。所以你不必担心package.json 在哪里。

                                我希望这会有所帮助。

                                【讨论】:

                                • 这里的module 是什么?
                                • @chovy, module 不是这个特定的示例变量;它是一个代表 node.js 中当前模块的变量。您可以在此处阅读有关 node.js 模块的更多信息:nodejs.org/api/modules.html#modules_the_module_object
                                • 我正在尝试获取我的模块所需的其他模块的版本...我很难弄清楚 pkginfo 是否可以实现这一点。
                                猜你喜欢
                                • 1970-01-01
                                • 2019-08-31
                                • 2021-01-20
                                • 2019-06-07
                                • 2021-02-07
                                • 1970-01-01
                                • 2019-10-17
                                • 1970-01-01
                                相关资源
                                最近更新 更多