I am building my react application using the following Webpack configuration and I need to add a reference to external.config.js file in my index.html to include it with versioning. Here, external.config.js file is processed using file-loader to maintain as a plain js file.
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const devConfig = require('./config/dev.config.json');
const certConfig = require('./config/cert.config.json');
const stagingConfig = require('./config/staging.config.json');
const productionConfig = require('./config/production.config.json');
const packageJson = require('./package.json');
const version = packageJson.version;
module.exports = (env) => {
let configPath;
switch (env) {
case 'dev':
configPath = devConfig;
break;
case 'cert':
configPath = certConfig;
break;
case 'staging':
configPath = stagingConfig;
break;
case 'production':
configPath = productionConfig;
break;
default:
// error logs
}
return {
mode: 'development',
entry: {
bundle: path.resolve(__dirname, 'src', 'index.js')
},
output: {
path: __dirname + '/dist',
filename: `[name].v${version}.js`
},
module: {
rules: [
{
test: /\.(woff|woff2|ttf|eot)$/,
use: 'file-loader?name=fonts/[name].[ext]!static',
},
{
test: /external.config.js$/,
loader: 'file-loader',
options: {
name: `[name].v${version}.[ext]`,
},
},
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
presets: [
'@babel/preset-env',
'@babel/preset-react',
],
plugins: ['@babel/plugin-syntax-dynamic-import', '@babel/plugin-proposal-class-properties'],
},
},
{
test: /\.(scss|css)$/,
use: [
'style-loader',
'css-loader',
'sass-loader',
],
},
{
test: /\.html$/,
use: [
{ loader: 'html-loader' },
],
},
],
},
externals: {
Config: JSON.stringify(configPath),
},
resolve: {
extensions: ['.js', '.jsx', '.css', '.less', '.json'],
modules: ['node_modules', 'path/to/your/static_resource'],
},
plugins: [new HtmlWebpackPlugin({ template: path.resolve(__dirname, 'src', 'index.html') })],
};
};
I tried it as a Webpack entry but I was unable to stop it into transpiling.
I was able to achieve this using HtmlWebpackPlugin which seems pretty supportive in managing the html output. First, I had to remove the html-loader in webpack.config which I wasn't using for a purpose and then the added the following configuration to HtmlWebpackPlugin.
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const devConfig = require('./config/dev.config.json');
const certConfig = require('./config/cert.config.json');
const stagingConfig = require('./config/staging.config.json');
const productionConfig = require('./config/production.config.json');
const packageJson = require('./package.json');
const version = packageJson.version;
const externalConfigPath = `/external.config.v${version}.js?`;
module.exports = (env) => {
let configPath;
switch (env) {
case 'dev':
configPath = devConfig;
break;
case 'cert':
configPath = certConfig;
break;
case 'staging':
configPath = stagingConfig;
break;
case 'production':
configPath = productionConfig;
break;
default:
// error logs
}
return {
mode: 'development',
entry: {
bundle: path.resolve(__dirname, 'src', 'index.js'),
},
output: {
path: __dirname + '/dist',
filename: `[name].v${version}.js`
},
module: {
rules: [
{
test: /\.(woff|woff2|ttf|eot)$/,
use: 'file-loader?name=fonts/[name].[ext]!static',
},
{
test: /external.config.js$/,
loader: 'file-loader',
options: {
name: `[name].v${version}.js`,
},
},
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
presets: [
'@babel/preset-env',
'@babel/preset-react',
],
plugins: ['@babel/plugin-syntax-dynamic-import', '@babel/plugin-proposal-class-properties'],
},
},
{
test: /\.(scss|css)$/,
use: [
'style-loader',
'css-loader',
'sass-loader',
],
},
],
},
externals: {
Config: JSON.stringify(configPath),
},
resolve: {
extensions: ['.js', '.jsx', '.css', '.less', '.json'],
modules: ['node_modules', 'path/to/your/static_resource'],
},
plugins: [new HtmlWebpackPlugin({ title: 'Custom template', configURL: externalConfigPath, template: path.resolve(__dirname, 'src', 'index.html') })],
};
};
Then added the following reference into my script tag src attribute in the index.html file.
<script type="text/javascript" src=<%= htmlWebpackPlugin.options.configURL %>></script>
References : https://github.com/jantimon/html-webpack-plugin#options