【问题标题】:Passing environment-dependent variables in webpack在 webpack 中传递与环境相关的变量
【发布时间】:2015-07-13 19:59:26
【问题描述】:

我正在尝试将 Angular 应用程序从 gulp 转换为 webpack。在 gulp 中,我使用 gulp-preprocess 替换 html 页面中的一些变量(例如数据库名称),具体取决于 NODE_ENV。使用 webpack 获得类似结果的最佳方法是什么?

【问题讨论】:

  • 别名对你有用吗?
  • @bebraw:在我能够理解别名之前,我实现了您基于 DefinePlugin() 建议的其他解决方案。我现在确实看到别名将是一个更好的解决方案,并且可能会在某个时候重构 - 谢谢。如果您想在答案中包含您的两个解决方案,我会很乐意接受。
  • 通过控制台消息被定向到这里。如何在 Browserify 中解决这个问题?
  • 这个问题是尝试在构建时还是加载时配置 SPA?我注意到 SPA 的两种配置类型:1)开发或生产模式,以及 2)部署环境,例如开发,分期,生产。我认为 NODE_ENV 可用于在构建时配置(1),但我们如何在部署时配置(2),例如为不同的部署环境配置生产模式。我希望这与这个问题有关。
  • @AshleyAitken 很好的问题,我在这个线程上找不到答案(也许我错过了),但发布了这个新线程:stackoverflow.com/questions/44464504/…

标签: javascript webpack


【解决方案1】:

有两种基本方法可以实现这一点。

定义插件

new webpack.DefinePlugin({
    'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development')
}),

请注意,这只会“按原样”替换匹配项。这就是为什么字符串是它的格式。你可以有一个更复杂的结构,比如一个对象,但你明白了。

环境插件

new webpack.EnvironmentPlugin(['NODE_ENV'])

EnvironmentPlugin 在内部使用DefinePlugin 并通过它将环境值映射到代码。 Terser 语法。

别名

您也可以通过an aliased module 使用配置。从消费者的角度来看,它看起来像这样:

var config = require('config');

配置本身可能如下所示:

resolve: {
    alias: {
        config: path.join(__dirname, 'config', process.env.NODE_ENV)
    }
}

假设process.env.NODE_ENVdevelopment。然后它会映射到./config/development.js。它映射到的模块可以像这样导出配置:

module.exports = {
    testing: 'something',
    ...
};

【讨论】:

  • 感谢您指出它“按原样”替换匹配项的事实。我挣扎了一段时间想弄清楚为什么我的代码会抛出错误,这是因为我没有将值包装在 JSON.stringify()
  • 如果你使用的是 ES2015,你也可以使用字符串插值 - 'process.env.NODE_ENV': `"${process.env.NODE_ENV || 'development'}"`
  • @tybro0103 JSON.stringify('development') 原样可能不是很有用。相反JSON.stringify(someVariable) 完全可以!
  • 您应该设置NODE_ENV 来执行此操作。如何设置取决于您的平台。
  • 不得不说,决心“把戏”很棒。我将 resolve 用于硬编码的本地包,但从未想过将其用于外部输入。现在我可以动态地传入一个外部配置目录。谢谢!
【解决方案2】:

只是另一种选择,如果你只想使用 cli 接口,只需使用 webpack 的define 选项即可。我在package.json 中添加了以下脚本:

"build-production": "webpack -p --define process.env.NODE_ENV='\"production\"' --progress --colors"

所以我只需要运行npm run build-production

【讨论】:

  • 有这方面的文档吗?我不能谷歌 --define :(
  • 对于 webpack@2,"-p" 已经是 --optimize-minimize --define process.env.NODE_ENV="production" 的快捷方式
  • @okm 文档提到 -p 等于 --optimize-minimize --optimize-occurence-order,所以没有提到 --define process.env.NODE_ENV="production"。它是被删除的东西吗?
  • @NaderHadjiGhanbari 它在 webpack 版本 2 中 webpack.js.org/api/cli/#shortcuts
【解决方案3】:

您可以直接使用webpack 中提供的EnvironmentPlugin 在转译期间访问任何环境变量。

您只需在 webpack.config.js 文件中声明插件即可:

var webpack = require('webpack');

module.exports = {
    /* ... */
    plugins = [
        new webpack.EnvironmentPlugin(['NODE_ENV'])
    ]
};

请注意,您必须明确声明要使用的环境变量的名称。

【讨论】:

【解决方案4】:

我研究了几个关于如何设置环境特定变量的选项,最终得到了这个:

我目前有 2 个 webpack 配置:

webpack.production.config.js

new webpack.DefinePlugin({
  'process.env':{
    'NODE_ENV': JSON.stringify('production'),
    'API_URL': JSON.stringify('http://localhost:8080/bands')
  }
}),

webpack.config.js

new webpack.DefinePlugin({
  'process.env':{
    'NODE_ENV': JSON.stringify('development'),
    'API_URL': JSON.stringify('http://10.10.10.10:8080/bands')
  }
}),

在我的代码中,我以这种(简要)方式获取 API_URL 的值:

const apiUrl = process.env.API_URL;

2016 年 11 月 3 日编辑

Webpack 文档有一个例子:https://webpack.js.org/plugins/define-plugin/#usage

new webpack.DefinePlugin({
    PRODUCTION: JSON.stringify(true),
    VERSION: JSON.stringify("5fa3b9"),
    BROWSER_SUPPORTS_HTML5: true,
    TWO: "1+1",
    "typeof window": JSON.stringify("object")
})

使用 ESLint,如果您启用了 no-undef 规则,则需要在代码中明确允许未定义的变量。 http://eslint.org/docs/rules/no-undef 像这样:

/*global TWO*/
console.log('Running App version ' + TWO);

2017 年 9 月 7 日编辑(特定于 Create-React-App)

如果您不想配置太多,请查看 Create-React-App:Create-React-App - Adding Custom Environment Variables。无论如何,CRA 在后台使用 Webpack。

【讨论】:

  • 您是否发现这会阻止在运行时传入任何环境变量?如果您替换整个 process.env,那么 process.env.PORT 不会在 webpack 构建期间解析为 undefined,这意味着您不能再从环境中覆盖端口?
  • 什么是流程?它来自哪里?如果是节点对象,如何进入浏览器?
  • 这是一个糟糕的解决方案,除了设置 NODE_ENV 和 API_URL 之外,您有两个几乎完全相同的 webpack.configs
  • @BrianOgden 是的,确实如此,您应该为此使用 webpack-merge 之类的东西:npmjs.com/package/webpack-merge - 这个问题有点超出 IMO 的范围。
  • @thevangelist 我终于想出了一个简单的解决方案,我的前提是为什么会有多个webpack.config.js文件,webpack应该根据环境cmd webpack调用加载不同的json配置,这里是我的解决方案github.com/Sweetog/yet-another-angular2-boilerplate
【解决方案5】:

要添加到我个人的一堆答案中,我更喜欢以下内容:

const webpack = require('webpack');
const prod = process.argv.indexOf('-p') !== -1;

module.exports = {
  ...
  plugins: [
    new webpack.DefinePlugin({
      process: {
        env: {
          NODE_ENV: prod? `"production"`: '"development"'
        }
      }
    }),
    ...
  ]
};

使用它没有时髦的环境变量或跨平台问题(使用环境变量)。您所要做的就是分别为开发或生产运行正常的webpackwebpack -p

参考:Github issue

【讨论】:

  • 在为进程定义值时,首选'process.env.NODE_ENV': JSON.stringify('production') 而不是process: { env: { NODE_ENV: JSON.stringify('production') } }。使用后者将覆盖进程对象,这可能会破坏与某些希望在进程对象上定义其他值的模块的兼容性。
【解决方案6】:

自 webpack 2 起,您可以使用 --env 传递 any 命令行参数无需其他插件

webpack --config webpack.config.js --env.foo=bar

使用 webpack.config.js 中的变量:

module.exports = function(env) {
    if (env.foo === 'bar') {
        // do something
    }
}

Source

【讨论】:

  • 注意,--env syntax 似乎在 webpack 5 中的某个时间点发生了变化:npx webpack --env goal=local
【解决方案7】:

添加到一堆答案中:

使用 ExtendedDefinePlugin 代替 DefinePlugin

npm install extended-define-webpack-plugin --save-dev.

ExtendedDefinePlugin 使用起来更简单,并且有文档记录 :-) link

因为 DefinePlugin 缺少好的文档,我想帮忙,说它实际上像 #DEFINE in c# 一样工作。

#if (DEBUG)
        Console.WriteLine("Debugging is enabled.");
#endif

因此,如果您想了解 DefinePlugin 的工作原理,请阅读 c# #define 文档。 link

【讨论】:

    【解决方案8】:

    我更喜欢将 .env 文件用于不同的环境。

    1. 使用 webpack.dev.config 将 env.dev 复制到 .env 到根文件夹中
    2. 使用 webpack.prod.config 将 env.prod 复制到 .env

    在代码中

    使用

    require('dotenv').config(); const API = process.env.API ## which will store the value from .env file

    【讨论】:

      【解决方案9】:

      由于我在 above post by thevangelist 上的编辑未获批准,因此发布更多信息。

      如果您想从 package.json 中提取值,例如定义的 版本号 并通过 DefinePlugin 访问它> 在 Javascript 中。

      {"version": "0.0.1"}
      

      然后,在各个webpack.config中导入package.json,使用import变量访问属性,然后使用DefinePlugin中的属性>.

      const PACKAGE = require('../package.json');
      const _version = PACKAGE.version;//Picks the version number from package.json
      

      例如,webpack.config 上的某些配置正在使用元数据作为 DefinePlugin:

      const METADATA = webpackMerge(commonConfig({env: ENV}).metadata, {
        host: HOST,
        port: PORT,
        ENV: ENV,
        HMR: HMR,
        RELEASE_VERSION:_version//Version attribute retrieved from package.json
      });
      
      new DefinePlugin({
              'ENV': JSON.stringify(METADATA.ENV),
              'HMR': METADATA.HMR,
              'process.env': {
                'ENV': JSON.stringify(METADATA.ENV),
                'NODE_ENV': JSON.stringify(METADATA.ENV),
                'HMR': METADATA.HMR,
                'VERSION': JSON.stringify(METADATA.RELEASE_VERSION)//Setting it for the Scripts usage.
              }
            }),
      

      在任何打字稿文件中访问它:

      this.versionNumber = process.env.VERSION;
      

      最聪明的方法是这样的:

      // webpack.config.js
      plugins: [
          new webpack.DefinePlugin({
            VERSION: JSON.stringify(require("./package.json").version)
          })
        ]
      

      Thanks to Ross Allen

      【讨论】:

        【解决方案10】:

        与@zer0chain 的答案类似的另一个答案。但是,有一个区别。

        设置webpack -p就足够了。

        同理:

        --define process.env.NODE_ENV="production"
        

        这是一样的

        // webpack.config.js
        const webpack = require('webpack');
        
        module.exports = {
          //...
        
          plugins:[
            new webpack.DefinePlugin({
              'process.env.NODE_ENV': JSON.stringify('production')
            })
          ]
        };
        

        所以你可能只需要在package.json节点文件中这样的东西:

        {
          "name": "projectname",
          "version": "1.0.0",
          "description": "",
          "main": "index.js",
          "scripts": {
            "test": "echo \"Error: no test specified\" && exit 1",
            "debug": "webpack -d",
            "production": "webpack -p"
          },
          "author": "prosti",
          "license": "ISC",
          "dependencies": {    
            "webpack": "^2.2.1",
            ...
          }
        }
        

        来自DefinePlugin 的一些提示:

        DefinePlugin 允许您创建可以在编译时配置的全局常量。这对于允许开发构建和发布构建之间的不同行为很有用。例如,您可以使用全局常量来确定是否发生日志记录;也许您在开发版本中执行日志记录,而不是在发布版本中。这就是 DefinePlugin 促成的那种场景。


        这样你就可以检查你是否输入了webpack --help

        Config options:
          --config  Path to the config file
                                 [string] [default: webpack.config.js or webpackfile.js]
          --env     Enviroment passed to the config, when it is a function
        
        Basic options:
          --context    The root directory for resolving entry point and stats
                                               [string] [default: The current directory]
          --entry      The entry point                                          [string]
          --watch, -w  Watch the filesystem for changes                        [boolean]
          --debug      Switch loaders to debug mode                            [boolean]
          --devtool    Enable devtool for better debugging experience (Example:
                       --devtool eval-cheap-module-source-map)                  [string]
          -d           shortcut for --debug --devtool eval-cheap-module-source-map
                       --output-pathinfo                                       [boolean]
          -p           shortcut for --optimize-minimize --define
                       process.env.NODE_ENV="production" 
        
                              [boolean]
          --progress   Print compilation progress in percentage                [boolean]
        

        【讨论】:

          【解决方案11】:

          我发现以下解决方案最容易为 Webpack 2 设置环境变量:

          例如我们有一个 webpack 设置:

          var webpack = require('webpack')
          
          let webpackConfig = (env) => { // Passing envirmonment through
                                          // function is important here
              return {
                  entry: {
                  // entries
                  },
          
                  output: {
                  // outputs
                  },
          
                  plugins: [
                  // plugins
                  ],
          
                  module: {
                  // modules
                  },
          
                  resolve: {
                  // resolves
                  }
          
              }
          };
          
          module.exports = webpackConfig;
          

          在 Webpack 中添加环境变量:

          plugins: [
              new webpack.EnvironmentPlugin({
                 NODE_ENV: 'development',
                 }),
          ]
          

          定义插件变量并将其添加到plugins

              new webpack.DefinePlugin({
                  'NODE_ENV': JSON.stringify(env.NODE_ENV || 'development')
              }),
          

          现在在运行 webpack 命令时,将 env.NODE_ENV 作为参数传递:

          webpack --env.NODE_ENV=development
          
          // OR
          
          webpack --env.NODE_ENV development
          

          现在您可以在代码中的任何位置访问NODE_ENV 变量。

          【讨论】:

            【解决方案12】:

            这是一种对我有用的方法,它允许我通过重用 json 文件来保持环境变量 DRY。

            const webpack = require('webpack');
            let config = require('./settings.json');
            if (__PROD__) {
                config = require('./settings-prod.json');
            }
            
            const envVars = {};
            Object.keys(config).forEach((key) => {
                envVars[key] = JSON.stringify(config[key]);
            });
            
            new webpack.DefinePlugin({
                'process.env': envVars
            }),
            

            【讨论】:

              【解决方案13】:

              从 Webpack v4 开始,只需在 Webpack 配置中设置 mode 即可为您设置 NODE_ENV(通过 DefinePlugin)。 Docs here.

              【讨论】:

              【解决方案14】:

              我不是...的忠实粉丝

              new webpack.DefinePlugin({
                'process.env': envVars
              }),
              

              ...因为它不提供任何类型的安全性。相反,您最终会提升您的秘密内容,除非您将 webpack 添加到 gitignore ?‍♀️ 有更好的解决方案。

              基本上使用这个配置,一旦你编译了你的代码,所有的进程环境变量都会从整个代码中删除,由于 babel 插件transform-inline-environment-variables,不会有一个单一的 process.env.VAR 了 PS 如果你不想以一大堆未定义结束,请确保在 webpack 调用 babel-loader 之前调用 env.js,这就是 webpack 调用的第一件事。 babel.config.js 文件中的变量数组必须与 env.js 上的对象匹配。现在只有一件事情要做。 添加一个.env 文件将所有环境变量放在那里,该文件必须位于项目的根目录,或者随意添加它,只要确保在 env.js 文件上设置相同的位置,并且将其添加到 gitignore

              const dotFiles = ['.env'].filter(Boolean);
              
              if (existsSync(dotFiles)) {
                  require("dotenv-expand")(require("dotenv").config((dotFiles)));
              }
              

              如果你想看整个 babel + webpack + ts 从 heaw 获取 https://github.com/EnetoJara/Node-typescript-babel-webpack.git

              同样的逻辑适用于 react 和所有其他 ?

              config
              ---webpack.js
              ---env.js
              src
              ---source code world
              .env
              bunch of dotFiles
              

              env.js

              "use strict";
              /***
              I took the main idea from CRA, but mine is more cooler xD
              */
              const {realpathSync, existsSync} = require('fs');
              const {resolve, isAbsolute, delimiter} = require('path');
              
              const NODE_ENV = process.env.NODE_ENV || "development";
              
              const appDirectory = realpathSync(process.cwd());
              
              if (typeof NODE_ENV !== "string") {
                  throw new Error("falle and stuff");
              }
              
              const dotFiles = ['.env'].filter(Boolean);
              
              if (existsSync(dotFiles)) {
                  require("dotenv-expand")(require("dotenv").config((dotFiles)));
              }
              
              process.env.NODE_PATH = (process.env.NODE_PATH || "")
                  .split(delimiter)
                  .filter(folder => folder && isAbsolute(folder))
                  .map(folder => resolve(appDirectory, folder))
                  .join(delimiter);
              
              const ENETO_APP = /^ENETO_APP_/i;
              
              module.exports = (function () {
                  const raw = Object.keys ( process.env )
                      .filter ( key => ENETO_APP.test ( key ) )
                      .reduce ( ( env, key ) => {
                              env[ key ] = process.env[ key ];
                              return env;
                          },
                          {
                              BABEL_ENV: process.env.ENETO_APP_BABEL_ENV,
                              ENETO_APP_DB_NAME: process.env.ENETO_APP_DB_NAME,
                              ENETO_APP_DB_PASSWORD: process.env.ENETO_APP_DB_PASSWORD,
                              ENETO_APP_DB_USER: process.env.ENETO_APP_DB_USER,
                              GENERATE_SOURCEMAP: process.env.ENETO_APP_GENERATE_SOURCEMAP,
                              NODE_ENV: process.env.ENETO_APP_NODE_ENV,
                              PORT: process.env.ENETO_APP_PORT,
                              PUBLIC_URL: "/"
                          } );
              
                  const stringyField = {
                      "process.env": Object.keys(raw).reduce((env, key)=> {
                          env[key]=JSON.stringify(raw[key]);
                          return env;
                      },{}),
              
                  };
              
                  return {
                      raw, stringyField
                  }
              })();
              

              没有插件的 webpack 文件

              "use strict";
              
              require("core-js");
              require("./env.js");
              
              const path = require("path");
              const nodeExternals = require("webpack-node-externals");
              
              module.exports = env => {
                  return {
                      devtool: "source-map",
                      entry: path.join(__dirname, '../src/dev.ts'),
                      externals: [nodeExternals()],
                      module: {
                          rules: [
                              {
                                  exclude: /node_modules/,
                                  test: /\.ts$/,
                                  use: [
                                      {
                                          loader: "babel-loader",
                                      },
                                      {
                                          loader: "ts-loader"
                                      }
                                  ],
                              },
                              {
                                  test: /\.(png|jpg|gif)$/,
                                  use: [
                                      {
                                          loader: "file-loader",
                                      },
                                  ],
                              },
                          ],
                      },
                      node: {
                          __dirname: false,
                          __filename: false,
                      },
                      optimization: {
                          splitChunks: {
                              automaticNameDelimiter: "_",
                              cacheGroups: {
                                  vendor: {
                                      chunks: "initial",
                                      minChunks: 2,
                                      name: "vendor",
                                      test: /[\\/]node_modules[\\/]/,
                                  },
                              },
                          },
                      },
                      output: {
                          chunkFilename: "main.chunk.js",
                          filename: "name-bundle.js",
                          libraryTarget: "commonjs2",
                      },
                      plugins: [],
                      resolve: {
                          extensions: ['.ts', '.js']
                      }   ,
                      target: "node"
                  };
              };
              

              babel.config.js

              module.exports = api => {
              
                  api.cache(() => process.env.NODE_ENV);
              
                  return {
              
                      plugins: [
                          ["@babel/plugin-proposal-decorators", { legacy: true }],
                          ["@babel/plugin-transform-classes", {loose: true}],
                          ["@babel/plugin-external-helpers"],
                          ["@babel/plugin-transform-runtime"],
                          ["@babel/plugin-transform-modules-commonjs"],
                          ["transform-member-expression-literals"],
                          ["transform-property-literals"],
                          ["@babel/plugin-transform-reserved-words"],
                          ["@babel/plugin-transform-property-mutators"],
                          ["@babel/plugin-transform-arrow-functions"],
                          ["@babel/plugin-transform-block-scoped-functions"],
                          [
                              "@babel/plugin-transform-async-to-generator",
                              {
                                  method: "coroutine",
                                  module: "bluebird",
                              },
                          ],
                          ["@babel/plugin-proposal-async-generator-functions"],
                          ["@babel/plugin-transform-block-scoping"],
                          ["@babel/plugin-transform-computed-properties"],
                          ["@babel/plugin-transform-destructuring"],
                          ["@babel/plugin-transform-duplicate-keys"],
                          ["@babel/plugin-transform-for-of"],
                          ["@babel/plugin-transform-function-name"],
                          ["@babel/plugin-transform-literals"],
                          ["@babel/plugin-transform-object-super"],
                          ["@babel/plugin-transform-shorthand-properties"],
                          ["@babel/plugin-transform-spread"],
                          ["@babel/plugin-transform-template-literals"],
                          ["@babel/plugin-transform-exponentiation-operator"],
                          ["@babel/plugin-proposal-object-rest-spread"],
                          ["@babel/plugin-proposal-do-expressions"],
                          ["@babel/plugin-proposal-export-default-from"],
                          ["@babel/plugin-proposal-export-namespace-from"],
                          ["@babel/plugin-proposal-logical-assignment-operators"],
                          ["@babel/plugin-proposal-throw-expressions"],
                          [
                              "transform-inline-environment-variables",
                              {
                                  include: [
                                      "ENETO_APP_PORT",
                                      "ENETO_APP_NODE_ENV",
                                      "ENETO_APP_BABEL_ENV",
                                      "ENETO_APP_DB_NAME",
                                      "ENETO_APP_DB_USER",
                                      "ENETO_APP_DB_PASSWORD",
                                  ],
                              },
                          ],
                      ],
                      presets: [["@babel/preset-env",{
                          targets: {
                              node: "current",
                              esmodules: true
                          },
                          useBuiltIns: 'entry',
                          corejs: 2,
                          modules: "cjs"
                      }],"@babel/preset-typescript"],
                  };
              };
              

              【讨论】:

              • “你最终会提升你的秘密内容,除非你将 webpack 添加到 gitignore。” @Ernesto 你能扩展一下吗?
              • 基本上你的包最终没有 process.env.BLAHBLAH 并输入实际值。例如,不要让 process.env.NODE_ENV 以“生产”结尾,我的意思是这不是最好的例子,但可以想象一个密钥。您的捆绑包将具有实际价值,谁知道该有线字符串代表什么?‍♀️
              • 嗯 - 是的,这些值将被插入到 built 版本中,但大概你没有将其推送到 GitHub...
              • 虽然,@Katie,上面共享的代码“有点”过头了(因为它 (a) 仅包括当时可用的所有提案(怀疑生产应用程序实际上 需要 这个配置完全存在)和(b)自愿创建和无法维护的单人任务是为了什么?),除了冗长但不太“正确”的答案之外,这家伙在谈到可疑的做法时有一个观点将秘密嵌入代码中,这些代码通常每天通过 http 发送给不受信任、未知的客户数千次。
              • 它可能会被缩小,甚至可能被大量trans堆积,但假设的 API 密钥仍然是纯文本系列的 unicode 字符,可以方便地以完美的人类方式传递给客户端- 可读的形式。唯一正确的方法是无需离开您的服务器/网络/虚拟私有云领域。您的客户只知道一个 API 和一个 API,那就是您的公共网络网关。如果您的客户需要请求第 3 方服务,您可以在 VPC 边缘提供一个浅层服务,将她的请求代理给第 3 方。验证并限制它。
              【解决方案15】:

              现在是 2020 年,我面临同样的问题,但是对于这个老问题,有很多新答案,只是列出一些:

              • 这是 webpack.config.js
              plugins: [
                      new HtmlWebpackPlugin({
                          // 1. title is the parameter, you can use in ejs template
                          templateParameters:{
                              title: JSON.stringify(someting: 'something'),
                          },
                      }), 
              
              
                      //2. BUILT_AT is a parameter too. can use it.
                      new webpack.DefinePlugin({
                          BUILT_AT: webpack.DefinePlugin.runtimeValue(Date.now,"some"),
              
                      }),
              
                      //3. for webpack5, you can use global variable: __webpack_hash__
                      //new webpack.ExtendedAPIPlugin()
                  ],
                  //4. this is not variable, this is module, so use 'import tt' to use it.
                  externals: { 
                      'ex_title': JSON.stringify({
                          tt: 'eitentitle',
                      })
                  },
              
              

              这 4 种方法只是基本的,我相信还有更多方法。但我认为也许这 4ways 是最简单的。

              【讨论】:

                【解决方案16】:

                我对 webpack 版本 "webpack": "^4.29.6" 的解决方法非常简单。

                //package.json
                {
                ...
                 "scripts": {
                    "build": "webpack --mode production",
                    "start": "webpack-dev-server --open --mode development"
                  },
                }
                

                你可以通过 webpack commnad 传递 --mode 参数,然后在 webpack.config.js 中

                 // webpack.config.json
                 module.exports = (env,argv) => {
                        return {
                           ...
                           externals: {
                            // global app config object
                            config: JSON.stringify({
                                apiUrl: (argv.mode==="production") ? '/api' : 'localhost:3002/api'
                            })
                        }
                }
                

                我在我的代码中这样使用 baseurl

                // my api service
                import config from 'config';
                console.log(config.apiUrl) // like fetch(`${config.apiUrl}/users/user-login`)
                

                【讨论】:

                • 这是我的最佳答案
                【解决方案17】:

                dotenv-webpack

                一个安全的 webpack 插件,支持 dotenv 和其他环境变量,并且只公开你选择和使用的内容。

                通过基于defaults 选项的配置的一些变通方法来实现这一点,一旦包将.env.defaults 文件作为环境变量的初始值,您就可以将它用于development 并让.env 用于您的生产。

                用法

                • 安装包
                npm install dotenv-webpack --save-dev
                
                • 创建.env.defaults 文件
                API_URL='dev_url/api/'
                
                • 创建一个.env 文件,将其留空,让defaults 工作,在您的部署过程中更新它
                • 配置webpack - webpack.config.js
                new Dotenv({
                  defaults: true 
                })
                
                • 开发环境测试file.js
                console.log(process.env.API_URL)
                // Outputs: dev_url/api/
                
                • 在构建时,更新空的.env 文件
                API_URL='prod_url/api/'
                

                dotenv-webpack 将使用它来覆盖env.defaults

                • 产品环境测试file.js
                console.log(process.env.API_URL)
                // Outputs: prod_url/api/
                

                dotenv-webpack
                dotenv-defaults

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 2023-03-05
                  • 1970-01-01
                  • 1970-01-01
                  • 2021-08-27
                  • 1970-01-01
                  • 2018-09-18
                  • 2016-09-05
                  相关资源
                  最近更新 更多