forked from bbc/simorgh
-
Notifications
You must be signed in to change notification settings - Fork 0
/
webpack.config.client.js
192 lines (185 loc) · 6.59 KB
/
webpack.config.client.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
/* eslint-disable global-require */
const AssetsPlugin = require('assets-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const MomentTimezoneDataPlugin = require('moment-timezone-data-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const webpack = require('webpack');
const dotenv = require('dotenv');
const { DuplicatesPlugin } = require('inspectpack/plugin');
const { getClientEnvVars } = require('./src/clientEnvVars');
const DOT_ENV_CONFIG = dotenv.config();
if (DOT_ENV_CONFIG.error) {
throw DOT_ENV_CONFIG.error;
}
module.exports = ({ resolvePath, IS_CI, IS_PROD, START_DEV_SERVER }) => {
const APP_ENV = process.env.APP_ENV || 'live';
const webpackDevServerPort = 1124; // arbitrarily picked. Has to be different to server port (7080)
const prodPublicPath =
process.env.SIMORGH_PUBLIC_STATIC_ASSETS_ORIGIN +
process.env.SIMORGH_PUBLIC_STATIC_ASSETS_PATH;
const clientConfig = {
target: 'web', // compile for browser environment
entry: START_DEV_SERVER
? [
`webpack-dev-server/client?http://localhost.bbc.com:${webpackDevServerPort}`,
'webpack/hot/only-dev-server',
'./src/client',
]
: ['./src/poly', './src/client'],
devServer: {
host: 'localhost.bbc.com',
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.
* Though we're no longer using Razzle, there is a good explanation here:
* 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].[chunkhash:8].js', // hash based on the contents of the file
// 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.bbc.com:${webpackDevServerPort}/`
: prodPublicPath,
},
optimization: {
minimizer: [new TerserPlugin()],
// 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 DuplicatesPlugin({
// Emit compilation warning or error? (Default: `false`)
emitErrors: true,
// Display full duplicates information? (Default: `false`)
verbose: true,
}),
new webpack.DefinePlugin({
'process.env': getClientEnvVars(DOT_ENV_CONFIG),
}),
/**
* Needed to prevent bundle hashes changing when the order they're imported is changed.
* See https://webpack.js.org/guides/caching/#module-identifiers
*/
new webpack.HashedModuleIdsPlugin(),
/*
* 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`,
);
},
),
/*
* Exclude all moment locales so they can be included within service bundles
*/
new webpack.IgnorePlugin({
resourceRegExp: /^\.\/locale$/,
contextRegExp: /moment$/,
}),
/* moment-timezone-data-plugin allows you to specify how much
* and what specific timezone data you wish to bundle.
* matchZones: (string or array of strings) Only include data
* for time zones with names matching this value.
*/
new MomentTimezoneDataPlugin({
matchZones: 'Europe/London',
}),
],
};
if (START_DEV_SERVER) {
clientConfig.plugins.push(new webpack.HotModuleReplacementPlugin());
}
if (IS_PROD) {
const BrotliPlugin = require('brotli-webpack-plugin');
const CompressionPlugin = require('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('webpack-bundle-analyzer'); // eslint-disable-line
/**
* 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;
};