@bbc/spartacus
Version:
164 lines (156 loc) • 5.46 kB
JavaScript
/* eslint-disable import/no-dynamic-require, global-require */
module.exports = ({
resolvePath,
IS_CI,
IS_PROD,
START_DEV_SERVER,
appDirectory,
}) => {
const AssetsPlugin = require(`${appDirectory}/node_modules/assets-webpack-plugin`);
const CopyWebpackPlugin = require(`${appDirectory}/node_modules/copy-webpack-plugin`);
const webpack = require(`${appDirectory}/node_modules/webpack`);
const dotenv = require('dotenv');
const getClientEnvVars = require('./lib/utilities/clientEnvVars').default;
const DOT_ENV_CONFIG = dotenv.config();
if (DOT_ENV_CONFIG.error) {
throw DOT_ENV_CONFIG.error;
}
const APP_ENV = process.env.APP_ENV || 'live';
const webpackDevServerPort = 1124; // arbitrarily picked. Has to be different to server port (7080)
const clientConfig = {
target: 'web', // compile for browser environment
entry: START_DEV_SERVER
? [
`webpack-dev-server/client?http://localhost:${webpackDevServerPort}`,
'webpack/hot/only-dev-server',
'./src/client',
]
: ['./src/client'],
devServer: {
host: 'localhost',
port: webpackDevServerPort,
historyApiFallback: true,
hot: true,
headers: {
'Access-Control-Allow-Origin': '*',
},
disableHostCheck: true,
},
output: {
path: resolvePath('build/public'),
// need unhashed client bundle when running dev server: https://github.com/jaredpalmer/razzle/tree/master/packages/create-razzle-app/templates/default#how-razzle-works-the-secret-sauce
filename: START_DEV_SERVER
? 'static/js/[name].js'
: 'static/js/[name].[hash:8].js',
// need full URL for dev server & HMR: https://github.com/webpack/docs/wiki/webpack-dev-server#combining-with-an-existing-server
publicPath: START_DEV_SERVER
? `http://localhost:${webpackDevServerPort}/`
: `${process.env.SPARTACUS_PUBLIC_STATIC_ASSETS_PATH}/`,
},
optimization: {
// specify min/max file sizes for each JS chunk for optimal performance
splitChunks: {
chunks: 'initial',
automaticNameDelimiter: '-',
minSize: 184320, // 180kb
maxSize: 245760, // 240kb
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendor',
},
},
},
},
node: {
// Override webpacks default handling for these as they arnt availible on the client.
fs: 'empty',
__filename: 'mock',
},
plugins: [
// keep track of the generated chunks in build/assets.json
// this determines what scripts get put in the footer of the page
new AssetsPlugin({
path: resolvePath('build'),
filename: `assets-${APP_ENV}.json`,
}),
// copy static files otherwise untouched by Webpack, e.g. favicon
new CopyWebpackPlugin([
{
from: 'public',
},
]),
new webpack.DefinePlugin({
'process.env': getClientEnvVars(DOT_ENV_CONFIG),
}),
/*
* This replaces calls to logger.node.js with logger.web.js, a client
* side replacement, when building the bundle code for the client.
* This avoids the weight of winston being included in the bundles and
* issues arising from it trying to the use the file system
*/
new webpack.NormalModuleReplacementPlugin(
/(.*)logger.node(\.*)/,
resource => {
// eslint-disable-next-line no-param-reassign
resource.request = resource.request.replace(
/logger.node/,
`logger.web`,
);
},
),
],
};
if (START_DEV_SERVER) {
clientConfig.plugins.push(new webpack.HotModuleReplacementPlugin());
}
if (IS_PROD) {
const BrotliPlugin = require(`${appDirectory}/node_modules/brotli-webpack-plugin`);
const CompressionPlugin = require(`${appDirectory}/node_modules/compression-webpack-plugin`);
clientConfig.plugins.push(
/**
* Compresses Webpack assets with Brotli compression algorithm.
* More advanced than gzip (compression-webpack-plugin).
* https://github.com/mynameiswhm/brotli-webpack-plugin
*/
new BrotliPlugin({
asset: '[path].br[query]',
test: /\.js$/,
threshold: 10240,
minRatio: 0.8,
}),
/**
* Compresses Webpack assets with gzip Content-Encoding.
* Prefer Brotli (using brotli-webpack-plugin) but we fall back to gzip.
* https://github.com/webpack-contrib/compression-webpack-plugin
*/
new CompressionPlugin({
algorithm: 'gzip',
filename: '[path].gz[query]',
test: /\.js$/,
threshold: 10240,
minRatio: 0.8,
}),
);
}
if (!IS_CI && IS_PROD) {
const {
BundleAnalyzerPlugin,
} = require(`${appDirectory}/node_modules/webpack-bundle-analyzer`);
/**
* Visualize size of webpack output files with an interactive zoomable treemap.
* https://github.com/webpack-contrib/webpack-bundle-analyzer
*/
clientConfig.plugins.push(
new BundleAnalyzerPlugin({
analyzerMode: 'static',
defaultSizes: 'gzip',
generateStatsFile: true,
openAnalyzer: false,
reportFilename: '../../reports/webpackBundleReport.html',
statsFilename: '../../reports/webpackBundleReport.json',
}),
);
}
return clientConfig;
};