@@ -21,8 +21,10 @@ module.exports = function () {
21
21
let CssWatchRebuildPlugin = require ( 'engine/webpack/cssWatchRebuildPlugin' ) ;
22
22
const CopyWebpackPlugin = require ( 'copy-webpack-plugin' )
23
23
const MiniCssExtractPlugin = require ( "mini-css-extract-plugin" ) ;
24
- const UglifyJsPlugin = require ( 'uglifyjs-webpack-plugin' ) ;
25
- const OptimizeCSSAssetsPlugin = require ( "optimize-css-assets-webpack-plugin" ) ;
24
+
25
+ const TerserPlugin = require ( 'terser-webpack-plugin' ) ;
26
+ const CssMinimizerPlugin = require ( "css-minimizer-webpack-plugin" ) ;
27
+
26
28
const fse = require ( 'fs-extra' ) ;
27
29
28
30
@@ -91,6 +93,7 @@ module.exports = function () {
91
93
92
94
let webpackConfig = {
93
95
output : {
96
+ devtoolNamespace : 'wp' ,
94
97
// fs path
95
98
path : path . join ( config . publicRoot , 'pack' ) ,
96
99
// path as js sees it
@@ -120,8 +123,11 @@ module.exports = function () {
120
123
121
124
watch : devMode ,
122
125
123
- devtool : devMode ? "cheap-inline-module-source-map" : // try "eval" ?
124
- process . env . NODE_ENV == 'production' ? 'source-map' : false ,
126
+ devtool : devMode
127
+ ? 'inline-cheap-module-source-map' // try "eval" ?
128
+ : process . env . NODE_ENV === 'production'
129
+ ? 'source-map'
130
+ : false ,
125
131
126
132
profile : Boolean ( process . env . WEBPACK_STATS ) ,
127
133
@@ -139,36 +145,52 @@ module.exports = function () {
139
145
rules : [
140
146
{
141
147
test : / \. y m l $ / ,
142
- use : [ 'json-loader' , ' yaml-loader']
148
+ use : ' yaml-loader'
143
149
} ,
144
150
{
145
- test : / \. p u g $ / ,
151
+ // make t global, so that it will not be defined in the compiled template function
152
+ // and i18n plugin will substitute
153
+ test : / \. p u g / ,
146
154
use : 'pug-loader?root=' + config . projectRoot + '/templates&globals=__'
147
155
} ,
148
156
{
149
157
test : / \. j s $ / ,
150
158
// babel shouldn't process modules which contain ws/browser.js,
151
159
// which must not be run in strict mode (global becomes undefined)
152
160
// babel would make all modules strict!
153
- exclude : noProcessModulesRegExp ,
161
+ exclude ( path ) {
162
+ return noProcessModulesRegExp . test ( path ) || path . includes ( 'node_modules/monaco-editor' ) || devMode ;
163
+ } ,
154
164
use : [
155
165
// babel will work first
156
166
{
157
167
loader : 'babel-loader' ,
158
168
options : {
169
+ plugins : [
170
+ require . resolve ( '@babel/plugin-proposal-object-rest-spread' )
171
+ ] ,
159
172
presets : [
160
- // use require.resolve here to build files from symlinks
161
- [ require . resolve ( 'babel-preset-env' ) , {
173
+ [ require . resolve ( '@babel/preset-env' ) , {
162
174
//useBuiltIns: true,
163
175
targets : {
164
- browsers : "> 3%"
176
+ // not ie11, don't want regenerator-runtime and @babel/plugin-transform-runtime
177
+ browsers : '> 3%'
165
178
}
166
179
} ]
167
180
]
168
181
}
169
182
}
170
183
]
171
184
} ,
185
+ {
186
+ test : / \. c s s $ / ,
187
+ use : [
188
+ MiniCssExtractPlugin . loader ,
189
+ {
190
+ loader : 'css-loader' ,
191
+ } ,
192
+ ] ,
193
+ } ,
172
194
{
173
195
test : / \. s t y l $ / ,
174
196
// MiniCssExtractPlugin breaks HMR for CSS
@@ -183,36 +205,43 @@ module.exports = function () {
183
205
{
184
206
loader : 'postcss-loader' ,
185
207
options : {
186
- plugins : [
187
- require ( 'autoprefixer' )
188
- ]
208
+ postcssOptions : {
209
+ plugins : [
210
+ require ( 'autoprefixer' )
211
+ ]
212
+ }
189
213
}
190
214
} ,
191
215
'engine/webpack/hover-loader' ,
192
216
{
193
217
loader : 'stylus-loader' ,
194
218
options : {
195
- linenos : true ,
196
- 'resolve url' : true ,
197
- use : [
198
- rupture ( ) ,
199
- nib ( ) ,
200
- function ( style ) {
201
- style . define ( 'lang' , config . lang ) ;
202
- style . define ( 'isRTL' , [ 'ar' , 'fa' , 'he' ] . includes ( process . env . TUTORIAL_LANG ) ) ;
203
- style . define ( 'env' , config . env ) ;
204
- }
205
- ]
219
+ stylusOptions : {
220
+ linenos : true ,
221
+ 'resolve url' : true ,
222
+ use : [
223
+ rupture ( ) ,
224
+ nib ( ) ,
225
+ function ( style ) {
226
+ style . define ( 'lang' , config . lang ) ;
227
+ style . define ( 'isRTL' , [ 'ar' , 'fa' , 'he' ] . includes ( process . env . TUTORIAL_LANG ) ) ;
228
+ style . define ( 'env' , config . env ) ;
229
+ }
230
+ ]
231
+ }
206
232
} ,
207
233
}
208
234
]
209
235
} ,
210
236
{
211
- test : / \. ( p n g | j p g | g i f | w o f f | e o t | o t f | t t f | s v g ) $ / ,
212
- use : extHash ( 'file-loader?name=[path][name]' , '[ext]' )
237
+ test : / \. ( p n g | j p g | g i f | w o f f | w o f f 2 | e o t | o t f | t t f | s v g ) $ / ,
238
+ type : 'asset/resource' ,
239
+ generator : {
240
+ filename : extHash ( '[name]' , '[ext]' ) , // Keeps the original file name and extension
241
+ } ,
213
242
}
214
243
] ,
215
- noParse : function ( path ) {
244
+ noParse ( path ) {
216
245
/*
217
246
if (path.indexOf('!') != -1) {
218
247
path = path.slice(path.lastIndexOf('!') + 1);
@@ -227,11 +256,16 @@ module.exports = function () {
227
256
resolve : {
228
257
// allow require('styles') which looks for styles/index.styl
229
258
extensions : [ '.js' , '.styl' ] ,
230
- alias : {
259
+ alias : {
231
260
'entities/maps/entities.json' : 'engine/markit/emptyEntities' ,
232
- config : 'client/config'
261
+ 'entities/lib/maps/entities.json' : 'engine/markit/emptyEntities' ,
262
+ config : 'client/config' ,
263
+ } ,
264
+ fallback : {
265
+ fs : false , // Replace 'empty' with 'false' in Webpack 5 to exclude it
233
266
} ,
234
- modules : modulesDirectories
267
+ modules : modulesDirectories ,
268
+ mainFields : [ 'browser' , 'main' , 'module' ] // maybe not needed, from eslint webpack
235
269
} ,
236
270
237
271
@@ -240,21 +274,19 @@ module.exports = function () {
240
274
extensions : [ '.js' ]
241
275
} ,
242
276
243
- node : {
244
- fs : 'empty'
245
- } ,
246
-
247
277
performance : {
248
278
maxEntrypointSize : 350000 ,
249
279
maxAssetSize : 350000 , // warning if asset is bigger than 300k
250
- assetFilter ( assetFilename ) { // only check js/css
280
+ assetFilter ( assetFilename ) {
281
+ // only check js/css
251
282
// ignore assets copied by CopyWebpackPlugin
252
- if ( assetFilename . startsWith ( '..' ) ) { // they look like ../courses/achievements/course-complete.svg
283
+ if ( assetFilename . startsWith ( '..' ) ) {
284
+ // they look like ../courses/achievements/course-complete.svg
253
285
// built assets do not have ..
254
286
return false ;
255
287
}
256
288
return assetFilename . endsWith ( '.js' ) || assetFilename . endsWith ( '.css' ) ;
257
- }
289
+ } ,
258
290
} ,
259
291
260
292
plugins : [
@@ -268,43 +300,43 @@ module.exports = function () {
268
300
_ : 'lodash'
269
301
} ) ,
270
302
271
- // ignore all locales except current lang
303
+
272
304
new webpack . IgnorePlugin ( {
273
- checkResource ( arg ) {
305
+ resourceRegExp : / f s - e x t r a $ /
306
+ } ) ,
307
+
308
+ // ignore all moment.js locales except current lang
309
+ new webpack . IgnorePlugin ( {
310
+ checkResource ( resource , context ) {
274
311
// locale requires that file back from it, need to keep it
275
- if ( arg === '../moment' ) return false ; // don't ignore this
276
- if ( arg === './' + config . lang || arg === './' + config . lang + '.js' ) return false ; // don't ignore current locale
277
- tmp = arg ; // for logging only
278
- return true ;
279
- } ,
280
- // under dirs like: ../locales/..
281
- checkContext ( arg ) {
282
- let ignore = arg . endsWith ( path . join ( 'node_modules' , 'moment' , 'locale' ) ) ;
312
+ if ( resource === '../moment' ) return false ; // don't ignore this
313
+ if ( resource . startsWith ( './' + config . lang ) ) return false ; // don't ignore current locale ./ru ./ru.js ./zh ./zh-cn.js
314
+
315
+ let ignore = context . endsWith ( path . join ( 'node_modules' , 'moment' , 'locale' ) ) ;
316
+
283
317
if ( ignore ) {
284
- // console.log("ignore moment locale ", tmp, arg );
318
+ // console.log("Ignore ", resource, context );
285
319
return true ;
286
320
}
287
- }
321
+ return false ;
322
+ } ,
288
323
} ) ,
289
324
290
-
291
325
// ignore site locale files except the lang
292
326
new webpack . IgnorePlugin ( {
293
- checkResource ( arg ) {
294
- let result = arg . endsWith ( '.yml' ) && ! arg . endsWith ( '/' + config . lang + '.yml' ) ;
295
- tmp = arg ; // for logging
296
- return result ;
297
- } ,
298
- // under dirs like: ../locales/..
299
- checkContext ( arg ) {
300
- let ignore = / \/ l o c a l e s ( \/ | $ ) / . test ( arg ) ;
301
- // console.log("ignore yml", tmp, arg);
302
- return ignore ;
327
+
328
+ checkResource ( resource , context ) {
329
+ let isYmlForAnotherLanguage = resource . endsWith ( '.yml' ) && ! resource . endsWith ( '/' + config . lang + '.yml' ) ;
330
+ let isUnderLocales = / \/ l o c a l e s ( \/ | $ ) / . test ( context ) ;
331
+ if ( isYmlForAnotherLanguage && isUnderLocales ) return true ;
332
+
333
+ // console.log("checkResource", resource, context);
334
+ return false ;
303
335
}
304
336
} ) ,
305
337
306
338
307
- new WriteVersionsPlugin ( path . join ( config . cacheRoot , 'webpack. versions.json' ) ) ,
339
+ new WriteVersionsPlugin ( path . join ( config . buildRoot , 'webpack' , ' versions' , 'all .json') ) ,
308
340
309
341
new MiniCssExtractPlugin ( {
310
342
filename : extHash ( "[name]" , 'css' ) ,
@@ -313,26 +345,29 @@ module.exports = function () {
313
345
314
346
new CssWatchRebuildPlugin ( ) ,
315
347
316
- new CopyWebpackPlugin (
317
- assetPaths . map ( path => {
348
+ new CopyWebpackPlugin ( {
349
+ patterns : assetPaths . map ( ( path ) => {
318
350
return {
319
351
from : path ,
320
- to : config . publicRoot
321
- }
322
- } ) ,
323
- { debug : 'warning' }
324
- ) ,
352
+ to : config . publicRoot ,
353
+ info : ( file ) => ( { minimized : true } ) ,
354
+ noErrorOnMissing : true
355
+ } ;
356
+ } )
357
+ } ) ,
325
358
326
359
{
327
- apply : function ( compiler ) {
360
+ apply ( compiler ) {
328
361
if ( process . env . WEBPACK_STATS ) {
329
- compiler . plugin ( " done" , function ( stats ) {
362
+ compiler . hooks . done . tap ( 'MyStats' , ( stats ) => {
330
363
stats = stats . toJson ( ) ;
331
- fs . writeFileSync ( `${ config . tmpRoot } /stats.json` , JSON . stringify ( stats ) ) ;
364
+ let dir = path . join ( config . buildRoot , 'webpack' , 'stats' ) ;
365
+ fs . ensureDirSync ( dir ) ;
366
+ fs . writeFileSync ( path . join ( dir , entryName + '.json' ) , JSON . stringify ( stats ) ) ;
332
367
} ) ;
333
368
}
334
- }
335
- }
369
+ } ,
370
+ } ,
336
371
] ,
337
372
338
373
recordsPath : path . join ( config . tmpRoot , 'webpack.json' ) ,
@@ -349,30 +384,30 @@ module.exports = function () {
349
384
350
385
optimization : {
351
386
minimizer : [
352
- new UglifyJsPlugin ( {
353
- cache : true ,
354
- parallel : 2 ,
355
- uglifyOptions : {
356
- ecma : 8 ,
387
+ new TerserPlugin ( {
388
+ parallel : 2 ,
389
+ terserOptions : {
390
+ ecma : 2022 ,
357
391
warnings : false ,
358
392
compress : {
359
- drop_console : true ,
360
- drop_debugger : true
393
+ drop_console : true ,
394
+ drop_debugger : true ,
361
395
} ,
362
- output : {
363
- beautify : true ,
364
- indent_level : 0 // for error reporting, to see which line actually has the problem
396
+ output : {
397
+ beautify : true ,
398
+ indent_level : 0 , // for error reporting, to see which line actually has the problem
365
399
// source maps actually didn't work in Qbaka that's why I put it here
366
- }
367
- }
400
+ } ,
401
+ } ,
368
402
} ) ,
369
- new OptimizeCSSAssetsPlugin ( { } )
370
- ]
403
+ new CssMinimizerPlugin ( { } ) ,
404
+ ] ,
371
405
}
372
406
} ;
373
407
374
408
375
409
//if (process.env.NODE_ENV != 'development') { // production, ebook
410
+ /*
376
411
if (process.env.NODE_ENV == 'production') { // production, ebook
377
412
webpackConfig.plugins.push(
378
413
function clearBeforeRun() {
@@ -388,6 +423,6 @@ module.exports = function () {
388
423
}
389
424
);
390
425
}
391
-
426
+ */
392
427
return webpackConfig ;
393
428
} ;
0 commit comments