-
Notifications
You must be signed in to change notification settings - Fork 8
/
webpack.config.js
342 lines (286 loc) · 8.84 KB
/
webpack.config.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
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
/* eslint strict: 0 */
'use strict';
const webpack = require('webpack');
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
const CopyPlugin = require('copy-webpack-plugin');
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
const SWPrecachePlugin = require('sw-precache-webpack-plugin');
const PreloadPlugin = require('preload-webpack-plugin');
const { NODE_ENV } = process.env;
if (NODE_ENV !== 'production' && NODE_ENV !== 'development') {
throw new Error('Must set NODE_ENV to either production or development.');
}
const IS_PROD = process.env['NODE_ENV'] === 'production';
const cssLoaders = (other, modules) =>
ExtractTextPlugin.extract({
use: [
{
loader: 'css-loader',
options: {
sourceMap: true,
// Enable CSS Modules to scope class names
modules,
minimize: IS_PROD,
importLoaders: 1 + other.length,
},
},
{
// Adjust URLs in CSS files so that they are relative to the source file rather than the output file
loader: 'resolve-url-loader',
},
...other,
],
// Do not extract in development mode for hot reloading
fallback: 'style-loader',
});
const stats = {
assets: true,
// Do not show copied files
excludeAssets: [/sprites\/.*\.png$/],
// Show html-webpack-plugin output
children: true,
// Do not show division of chunks into modules
modules: false,
};
module.exports = {
entry: [
// Main entry point of the application
'./src/index',
],
devtool: IS_PROD ? undefined : 'cheap-module-eval-source-map',
target: 'web',
module: {
rules: [
{
test: /\.css$/,
// No CSS modules for normal CSS files
use: cssLoaders([], false),
},
{
test: /\.module\.scss$/,
// SCSS with CSS modules
use: cssLoaders(
[
{
loader: 'sass-loader',
options: {
sourceMap: true,
},
},
],
true
),
},
{
test: /^((?!\.module\.scss$).)+\.scss$/,
// SCSS without CSS modules
use: cssLoaders(
[
{
loader: 'sass-loader',
options: {
sourceMap: true,
},
},
],
false
),
},
{
test: /\.jsx?$/,
use: [
{
loader: 'babel-loader',
},
],
exclude: /node_modules/,
},
{
test: /\.json$/,
use: [
{
loader: 'json-loader',
},
],
},
{
test: /\.(woff2?|png|jpe?g)$/,
use: [
{
loader: 'file-loader',
},
],
},
],
},
output: {
// Output everything to dist
path: path.join(__dirname, 'dist'),
// Hash the entry module based on the version of the build
filename: '[name].[hash].js',
// Hash chunks based on their own hashes for better versioning
chunkFilename: '[name].[chunkhash].js',
// Configure a relative path for deployment
publicPath: './',
},
resolve: {
extensions: ['.js', '.jsx'],
mainFields: ['webpack', 'browser', 'web', 'browserify', ['jam', 'main'], 'module', 'main'],
alias: {
// Use the production build of handlebars to avoid warning about require.resolve
handlebars: 'handlebars/dist/handlebars.min.js',
},
},
// Apply modified stat output
stats,
// Ignore Node modules imported by KeySAVCore
node: {
Buffer: false,
crypto: false,
path: false,
},
plugins: [
// Create an HTML file with all chunks injected
new HtmlWebpackPlugin({
inject: 'body',
template: './src/index.ejs',
}),
// Copy the sprites used by the pretty formatter
new CopyPlugin([
{
from: './src/resources/sprites',
to: './sprites',
},
]),
// Define environment variables for runtime specific behavior
new webpack.DefinePlugin({
__DEV__: !IS_PROD,
'process.env': {
NODE_ENV: JSON.stringify(process.env['NODE_ENV']),
},
}),
// Write the style output to its own CSS file
new ExtractTextPlugin({
filename: 'style.[chunkhash].css',
allChunks: true,
// Do not extract text in development mode to enable hot reloading
disable: !IS_PROD,
}),
// Get rid of warnings for unused imports in KeySAVCore
new webpack.IgnorePlugin(/^(fs|crypto|path)$/),
// Only load moment locales corresponding to languages supported by the games
new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /(de|en|fr|en|zh-cn|ko|ja)$/),
// Use the module names instead of IDs
// This improves their cachebility because names do not change whereas IDs are just enumerated
new webpack.NamedModulesPlugin(),
// Add preload tags for browsers without support for service workers
new PreloadPlugin({
fileBlacklist: [/sprites\/.*\.png$/, /pkm-local\/.*\.js$/],
}),
// Generate a service worker to handle offline availability
new SWPrecachePlugin({
// Use a prefix to avoid collisions on localhost and GH pages
cacheId: 'keysave',
// These URLs include hashes and therefore version themselves, tce cache can be assumed correct
dontCacheBustUrlsMatching: /\.\w{20}\.\w+$/,
// Filename of the output file
filename: 'sw.js',
// Minify the service worker code in production
minify: IS_PROD,
// Include assets generated by Webpack
mergeStaticsConfig: true,
// Do not precache sprites and localizations
staticFileGlobsIgnorePatterns: [/sprites\/.*\.png$/, /pkm-local\/.*\.js$/],
// Do not cache in development
handleFetch: IS_PROD,
// Cache sprites when they are requested
runtimeCaching: [
{
urlPattern: /sprites\/.*\.png/,
handler: 'cacheFirst',
options: {
cache: {
name: 'pretty-sprite-cache',
},
},
},
// Cache localizations when they are requested
{
urlPattern: /pkm-local\/.*\.js/,
handler: 'cacheFirst',
options: {
cache: {
name: 'local-cache',
},
},
},
],
}),
// Plugins specific to production mode
...(IS_PROD
? [
// Minify JavaScript
new UglifyJSPlugin({
uglifyOptions: {
ecma: 8,
safari10: true,
},
parallel: true,
}),
// Concatenate modules where possible, i.e. hoist them together into one module
// This enables smaller builds and faster execution
new webpack.optimize.ModuleConcatenationPlugin(),
// Use names for chunks instead of their IDs, this improves cachebility
new webpack.NamedChunksPlugin(),
// Extract all code in node_modules into a vendor chunk
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: function(module, count) {
var context = module.context;
return context && context.indexOf('node_modules') >= 0;
},
}),
// Extract webpack boilerplate and manifest (i.e. list of chunk names)
// This means that the vendor or app bundle isn't invalidated when other chunks change
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
}),
// Output an analysis of the generated chunks
new BundleAnalyzerPlugin({
// Generate the output in form of a static file
analyzerMode: 'static',
reportFilename: '../bundle-analysis.html',
// Do not open the generated output automatically
openAnalyzer: false,
}),
// These plugins are only used in development mode
]
: [
// Do not emit a bundle if any errors occur
new webpack.NoEmitOnErrorsPlugin(),
// Enable hot module replacement
new webpack.HotModuleReplacementPlugin(),
]),
],
devServer: {
port: 3000,
// Files from this directory are served in addition to generated bundles
contentBase: './dist',
// Specifies what directory the bundles are served form
publicPath: '/',
// Inject scripts for hot reloading into the bundles
inline: true,
// Enable hot reloading
hot: true,
// Open / when the server started
open: 'Google Chrome Canary',
openPage: '',
// Show compilation errors fullscreen instead of the application
overlay: true,
// Apply the different logging
stats,
},
};