Javascript 如何使用webpack在编译时替换文件?

Javascript 如何使用webpack在编译时替换文件?,javascript,webpack,webpack-4,webpack-loader,Javascript,Webpack,Webpack 4,Webpack Loader,我有一个项目与miltiple配置。第一个配置是config.dev.js文件,其中包含一些开发配置。我在开发模式中使用它。第二个配置是config.js文件。我在生产模式中使用它 在代码I中,使用导入: import * as config from './config.js'; 我想使用开发中的第一个配置文件和生产中的第二个配置文件,而不重写所有导入。如何根据构建模式替换此配置?您可以使用webpack文件替换加载程序 例如: //webpack.config.js const res

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

在代码I中,使用导入:

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

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

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

例如:

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

我意识到这是一篇老文章,但这是谷歌上的第一个结果之一,所以我认为一个更好的答案会更好

网页包具有内置的“”

为了便于使用,我将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
        ),
        ...
    ]
}
您也可以像这样使用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;
                  }
                }
              }
            ]
          ]
        }
    }]
  }
}

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

我想模仿Angular fileReplacements语法,因此我使用了类似Angular的config.json,如果配置键与我传递给webpack的env匹配,则循环替换并创建几个webpack模块规则

这不是有史以来最优雅的事情,但这就是我的结局:

//config.json
{
“头衔”:“某个头衔”,
“配置”:{
“生产”:{
“文件替换”:[
{
“替换”:“src/environments/environment.ts”,
“with”:“src/environments/environment.prod.ts”
}
]
},
“局域网”:{
“文件替换”:[
{
“替换”:“src/environments/environment.ts”,
“with”:“src/environments/environment.lan.ts”
}
]
}
}
}
//webpack.config.js
const appConfig=require('./config.json');
module.exports=(环境,argv)=>{
//env.build类似于'ng build--prod`as`webpack--env.build=production`
const configuration=appConfig.configurations[env.build];
constfilereplacements=[];
//安全检查
if(配置&&configuration.fileReplacements){
//迭代替换
for(const替换configuration.fileReplacements){
//创建网页包模块规则
常量替换={
测试:路径解析(替换。替换),
加载程序:“文件替换加载程序”,
选项:{
替换:路径解析(替换为),
异步:true
}
}
fileReplacements.push(replace);
}
}
返回{
模式:/。。。
条目:/。。。
模块:{
规则:[
{
//...
},
//这里任何地方都可以打开
…文件替换
]
}
}
}

这样,您就不必一直忙于webpack和regex测试,只需添加到config.json的数组中即可。这是一个老问题,但我最近遇到了相同的问题,
webpack.NormalModuleReplacementPlugin
似乎不再起作用(或者至少在我使用json文件作为配置的情况下不起作用)。相反,我使用alias找到了另一个解决方案:

const path=require(“路径”);
modules.export={
...
决心:{
...
别名:{
[path.resolve(uu dirname,“src/conf/config.json”):
resolve(uu dirname,“src/conf/config.prod.json”)
}
}
...
}

另一种方法是使用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

也许值得一提的是,第二条路径相对于第一条路径,这意味着:如果我的旧路径位于
/src/config/dev.js
中,
/prod.js
将引用
/src/config/prod.js
,不到
root/prod.js
NormalModuleReplacementPlugin
在我使用期间也不起作用,因为它出现了错误“NormalModuleFactory.beforesolve不再是瀑布挂钩,而是一个bailing挂钩”。它似乎与网页包版本更改有关:
// 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