我如何在编译时通过webpack替换文件?

时间:2018-07-14 12:38:55

标签: webpack webpack-4 webpack-loader

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

在我使用导入的代码中:

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

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

6 个答案:

答案 0 :(得分:4)

这是一个古老的问题,但是我最近偶然发现了同一问题,并且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")
        }
    }
    ...
}

答案 1 :(得分:3)

我意识到这是一篇过时的文章,但这是Google的第一批结果之一,所以我认为更好的答案会很好。

Webpack具有内置的“ Normal Module Replacement Plugin”。

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

我将环境文件放在一个变量中,这是一个示例:

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
        ),
        ...
    ]
}

答案 2 :(得分:2)

您可以使用webpack文件替换加载器

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

示例:

Invalid source url: .

答案 3 :(得分:1)

您还可以像这样使用 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;
                  }
                }
              }
            ]
          ]
        }
    }]
  }
}

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

答案 4 :(得分:1)

我想模仿Angular fileReplacements语法,所以我像Angular一样使用了config.json,如果配置密钥与env匹配,我将传递给webpack,循环进行替换,并创建一些Webpack模块规则。

这不是有史以来最优雅的东西,但这就是我最终得到的:

// 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
            ]
       }
    }
}

通过这种方式,您不必一直困扰webpack和regex测试,只需将其添加到config.json中的数组中即可。

答案 5 :(得分: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