-
Notifications
You must be signed in to change notification settings - Fork 8
/
webpack.config.js
222 lines (200 loc) · 6.75 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
const path = require('path');
const webpack = require('webpack');
const TerserPlugin = require('terser-webpack-plugin');
const WebpackBuildNotifierPlugin = require('webpack-build-notifier');
const BannerWebpackPlugin = require('banner-webpack-plugin');
require('json5/lib/register.js');
const config = require('./config.json5');
const getUrl = require('./misc/utils.js').getUrl;
module.exports = (env) => {
/*
Production builds are created by running
npm run build
Development builds are for debugging locally. Create them like this:
npm run start (which runs "webpack serve --env dev")
npm run build --dev (which runs "webpack" and sets the "dev" npm config variable)
(the first command will not create the files themselves but serve at the specified paths).
*/
const dev = Boolean(env.dev || process.env.npm_config_dev);
/*
Test builds are for creating the production build with files (main file and configuration file)
having the ".test" postfix. They are created by running
npm run build --test
*/
const test = Boolean(env.test || process.env.npm_config_test);
/*
Single builds include the main file, configuration and localization, as well as source maps, in
a single file. Create them like this:
npm run single -- project=w lang=en
*/
const single = Boolean(env.single || process.env.npm_config_single);
let filenamePostfix = '';
let lang;
let wiki;
if (single) {
const project = env.project || 'w';
lang = env.lang || 'en';
wiki = ['w', 'b', 'n', 'q', 's', 'v', 'voy', 'wikt'].includes(project) ?
`${project}-${lang}` :
project;
filenamePostfix = `.single.${wiki}`;
} else if (dev) {
filenamePostfix = '.dev';
} else if (test) {
filenamePostfix = '.test';
}
const filename = `convenientDiscussions${filenamePostfix}.js`;
if (!config.protocol || !config.main?.rootPath || !config.articlePath) {
throw new Error('No protocol/server/root path/article path found in config.json5.');
}
let devtool;
if (single) {
devtool = 'eval';
} else if (dev) {
devtool = 'eval-source-map';
} else {
// SourceMapDevToolPlugin is used.
devtool = false;
}
return {
mode: dev || single ? 'development' : 'production',
entry: './src/app.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename,
},
performance: {
hints: false,
},
devtool,
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
},
},
{
test: /\.less$/,
use: ['style-loader', 'css-loader', 'less-loader'],
},
{
test: /\bworker-gate\.js$/,
use: {
loader: 'worker-loader',
options: {
filename: `convenientDiscussions.worker${filenamePostfix}.js`,
inline: 'no-fallback',
},
},
},
],
},
optimization: {
// Less function calls when debugging, but one scope for all modules. To change this, `!dev`
// could be used.
concatenateModules: true,
minimizer: [
new TerserPlugin({
terserOptions: {
// This provides better debugging (more places where you can set a breakpoint) while
// costing not so much size.
compress: {
// + 0.3% to the file size
sequences: false,
// + 1% to the file size
conditionals: false,
},
output: {
// Otherwise messes with \x01 \x02 \x03 \x04.
ascii_only: true,
comments: /^\**!/,
},
mangle: {
keep_classnames: true,
reserved: ['cd'],
},
},
extractComments: {
// Removed "\**!|" at the beginning to not extract the <nowiki> comment.
condition: /@preserve|@license|@cc_on/i,
filename: (filename) => `${filename}.LICENSE.js`,
banner: (licenseFile) => (
licenseFile.includes('worker') ?
// A really messed up hack to include source maps for a web worker (works with
// .map.json extension for webpack.SourceMapDevToolPlugin's `filename` property,
// doesn't work with .map for some reason).
`//# sourceMappingURL=${config.sourceMapsBaseUrl}convenientDiscussions.worker.js.map.json` :
`
* For documentation and feedback, see the script's homepage:
* https://commons.wikimedia.org/wiki/User:Jack_who_built_the_house/Convenient_Discussions
*
* For license information, see
* ${getUrl(config.main.server, config.main.rootPath + '/' + licenseFile)}
`
),
},
sourceMap: true,
}),
],
},
plugins: [
new webpack.DefinePlugin({
IS_TEST: test,
IS_DEV: dev,
IS_SINGLE: single,
CONFIG_FILE_NAME: single ? JSON.stringify(wiki) : null,
LANG_CODE: single ? JSON.stringify(lang) : null,
}),
new WebpackBuildNotifierPlugin({
suppressSuccess: true,
suppressWarning: true,
}),
].concat(
single ?
[] :
[
new webpack.BannerPlugin({
banner: '<nowiki>',
// Don't add the banner to the inline worker, otherwise the source maps for it won't
// work (I think).
test: filename,
}),
// We can't use BannerWebpackPlugin for both the code to prepend and append, because if we
// add the code to prepend with BannerWebpackPlugin, the source maps would break.
// webpack.BannerPlugin, on the other hand, handles this, but doesn't have an option for
// the code to append to the build (this code doesn't break the source maps).
new BannerWebpackPlugin({
chunks: {
main: {
afterContent: '\n/*! </nowiki> */',
},
},
}),
],
dev ?
[] :
new webpack.SourceMapDevToolPlugin({
filename: '[file].map.json',
append: `\n//# sourceMappingURL=${config.sourceMapsBaseUrl}[url]`,
}),
process.env.CI ?
[] :
new webpack.ProgressPlugin()
),
devServer: {
contentBase: path.join(__dirname, 'dist'),
port: 9000,
liveReload: false,
// Fixes "GET https://localhost:9000/sockjs-node/info?t=... net::ERR_SSL_PROTOCOL_ERROR".
public: '127.0.0.1:9000',
// Fixes "Invalid Host/Origin header".
disableHostCheck: true,
// For easier copypaste to use in a DevTools snippet (if can't load from 127.0.0.1:9000 for
// some reason).
// writeToDisk: single,
},
};
};