19

我有一个具有多种配置的项目。第一个配置是config.dev.js包含一些开发配置的文件。我在开发模式下使用它。第二个配置是config.js文件。我在生产模式下使用它。

在我使用导入的代码中:

import * as config from './config.js';

我想在开发中使用第一个配置文件,在生产中使用第二个配置文件而不重写所有导入。如何根据构建模式替换此配置?

4

6 回答 6

16

我意识到这是一篇旧帖子,但这是谷歌上的首批结果之一,所以我认为更好的答案会很好。

Webpack 有一个内置的“普通模块替换插件”。

plugins: [
  new webpack.NormalModuleReplacementPlugin(
    /some\/path\/config\.development\.js/,
    './config.production.js'
  )
]

对于我的使用,我将 env 文件放在一个变量中这是一个示例:

let envFilePath = './environment.dev.js';
if (env === 'production') {
  envFilePath = './environment.prod.js';
} else if (env === 'staging') {
  envFilePath = './environment.stg.js';
}

module.exports = {
    // other webpack stuff
    ....
    plugins:[ 
        new webpack.NormalModuleReplacementPlugin(
            /src\/environment\/environment\.js/,
            envFilePath
        ),
        ...
    ]
}
于 2019-03-14T05:55:37.107 回答
14

这是一个老问题,但我最近偶然发现了同样的问题,webpack.NormalModuleReplacementPlugin并且似乎不再起作用(或者至少在我使用 JSON 文件作为配置的情况下不起作用)。相反,我找到了另一个使用别名的解决方案:

const path = require("path");

modules.export = {
    ...
    resolve: {
        ...
        alias: {
            [path.resolve(__dirname, "src/conf/config.json")]:
                path.resolve(__dirname, "src/conf/config.prod.json")
        }
    }
    ...
}
于 2020-04-13T10:12:59.923 回答
9

You can use webpack file-replace-loader

https://www.npmjs.com/package/file-replace-loader

Example:

//webpack.config.js

const resolve = require('path').resolve;

module.exports = {
  //...
  module: {
    rules: [{
      test: /\.config\.js$/,
      loader: 'file-replace-loader',
      options: {
        condition: process.env.NODE_ENV === 'development',
        replacement: resolve('./config.dev.js'),
        async: true,
      }
    }]
  }
}
于 2018-07-15T02:54:29.443 回答
5

I wanted to imitate the Angular fileReplacements syntax so I used a config.json like Angular's and if the configuration key matches the env I pass to webpack, loop through the replacements and create several Webpack module rules.

It's not the most elegant thing ever but this is what I ended up with:

// config.json

{
    "title": "Some Title",
    "configurations": {
        "production": {
            "fileReplacements": [
                {
                    "replace": "src/environments/environment.ts",
                    "with": "src/environments/environment.prod.ts"
                }
            ]
        },
        "lan": {
            "fileReplacements": [
                {
                    "replace": "src/environments/environment.ts",
                    "with": "src/environments/environment.lan.ts"
                }
            ]
        }
    }
}

// webpack.config.js

const appConfig = require('./config.json');



module.exports = (env, argv) => {

    // env.build is like `ng build --prod` as `webpack --env.build=production` 
    const configuration = appConfig.configurations[env.build];
    const fileReplacements = [];

    // Safety Check
    if(configuration && configuration.fileReplacements) {

        // Iterate through replacements
        for(const replacement of configuration.fileReplacements) {
            // create Webpack module rule
            const replace = {
                test: path.resolve(replacement.replace),
                loader: 'file-replace-loader',
                options: {
                    replacement: path.resolve(replacement.with),
                    async: true
                }
            }
            fileReplacements.push(replace);
        }
    }

    return {
        mode: //...
        entry: //...
        module: {
            rules: [
                {
                    //...
                },
                // Unpack anywhere here
                ...fileReplacements
            ]
       }
    }
}

This way you don't have to keep messing with webpack and regex tests, just add to the array in config.json

于 2019-10-22T15:22:13.310 回答
2

你也可以像这样使用babel-loader

//webpack.config.js

const resolve = require('path').resolve;

module.exports = {
  //...
  module: {
    strictExportPresence: true,
    rules: [{
      test: /\.config\.js$/,
      include: paths.appSrc,
      loader: require.resolve('babel-loader'),
      options: {
        plugins: [
            [
              "module-resolver",
              {
                resolvePath(sourcePath, currentFile, opts) {
                  if(process.env.NODE_ENV === 'development') {
                    return sourcePath.substr(0, sourcePath.lastIndexOf('/')) + '/config.dev.js';
                  } else {
                    return sourcePath;
                  }
                }
              }
            ]
          ]
        }
    }]
  }
}

通过这种方式,您甚至可以定义复杂的算法来确定您想要使用的文件。

于 2019-03-27T09:06:31.560 回答
0

另一种方法是使用 Webpack.DefinePlugin。如果您想要有条件地包含一个很小的代码块,则特别有用。

示例如下:

// webpack.conf.js
// Code block that should be inserted or left blank
const ServiceWorkerReg = `window.addEventListener('load', () => {
    navigator.serviceWorker.register('service-worker.js').then(registration => {
        console.log('SW registered: ', registration);
    }).catch(registrationError => {
        console.log('SW registration failed: ', registrationError);
    });
});`


appConfig = {
    plugins: [
        new webpack.DefinePlugin({
            __SERVICE_WORKER_REG: isDev ? '' : ServiceWorkerReg,
        }),
    ]
    ...
}



 // Some module index.js

 __SERVICE_WORKER_REG

 ... // other non conditional code
于 2020-05-11T12:21:52.337 回答