Javascript 如何使用webpack在编译时替换文件?
我有一个项目与miltiple配置。第一个配置是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
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