Reputation: 251
I have a project with miltiple configuration. The first config is config.dev.js
file that contains some development configiration. I using it in development mode. The second config is config.js
file. I using it in production mode.
In the code I using imports:
import * as config from './config.js';
I want to use the first config file in development and the second to production whithout rewriting all of the imports. How can I replace this config depending on the build mode?
Upvotes: 25
Views: 26661
Reputation: 3240
Another way is to use Webpack.DefinePlugin. Especially useful if you have a tiny code block that you want to be included conditionally.
Example follows:
// 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
Upvotes: 0
Reputation: 1690
This is an old question but I've recently stumbled across the same issue and webpack.NormalModuleReplacementPlugin
doesn't seem to work anymore (or at least not in my case, where I used JSON files as config). Instead I found another solution using alias:
const path = require("path");
modules.export = {
...
resolve: {
...
alias: {
[path.resolve(__dirname, "src/conf/config.json")]:
path.resolve(__dirname, "src/conf/config.prod.json")
}
}
...
}
Upvotes: 22
Reputation: 1502
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
Upvotes: 5
Reputation: 1546
You can also use babel-loader like this:
//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;
}
}
}
]
]
}
}]
}
}
This way you can even define complex algorithms to determine which file you wanna use.
Upvotes: 2
Reputation: 3774
I realize this is an old post, but this is one of the first results on Google, so I thought a better answer would be good.
Webpack has a built in "Normal Module Replacement Plugin".
plugins: [
new webpack.NormalModuleReplacementPlugin(
/some\/path\/config\.development\.js/,
'./config.production.js'
)
]
For my use, I put the env file in a variable Here is an example:
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
),
...
]
}
Upvotes: 17
Reputation: 101
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,
}
}]
}
}
Upvotes: 10