Skip to content

Commit 4389538

Browse files
authored
Merge pull request #345 from UniversityofWarwick/feature/webpack5
ID-474 Webpack 5.
2 parents 39be087 + 47c1926 commit 4389538

13 files changed

Lines changed: 1796 additions & 7856 deletions

.gitignore

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,26 @@ node_modules
7979

8080
# Don't ignore /dist because it needs to be in Git for npm
8181
dist/fonts/fa-light-*
82+
83+
# ── GSD baseline (auto-generated) ──
84+
.gsd
85+
.gsd-id
86+
.bg-shell/
87+
.vscode/
88+
*.code-workspace
89+
.env
90+
.env.*
91+
!.env.example
92+
node_modules/
93+
.next/
94+
dist/
95+
build/
96+
__pycache__/
97+
*.pyc
98+
.venv/
99+
venv/
100+
target/
101+
vendor/
102+
coverage/
103+
.cache/
104+
tmp/
File renamed without changes.

build-tooling/PlayFingerprintsPlugin.js

Lines changed: 0 additions & 78 deletions
This file was deleted.
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import path from 'path';
2+
import { createHash } from 'crypto';
3+
4+
/**
5+
* Webpack plugin that generates some extra files for Play! Framework
6+
* to use to generate versioned assets.
7+
*
8+
* It calculates the MD5 hash of each source and then:
9+
* Adds a .md5 file containing that hash
10+
* Adds a HASH-FILENAME copy of the original file.
11+
*
12+
* Logic based on the gulp-play-assets module.
13+
*/
14+
export default class PlayFingerprintsPlugin {
15+
constructor(options) {
16+
this.options = options || {};
17+
}
18+
19+
apply(compiler) {
20+
compiler.hooks.thisCompilation.tap('PlayFingerprintsPlugin', (compilation) => {
21+
compilation.hooks.processAssets.tapAsync(
22+
{
23+
name: 'PlayFingerprintsPlugin',
24+
stage: compilation.compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL,
25+
},
26+
(assets, done) => {
27+
// const versionedFilenames = {};
28+
29+
// Get list of asset names to process (avoid mutating during iteration)
30+
const assetNames = Object.keys(assets);
31+
32+
for (const fullPath of assetNames) {
33+
const dir = path.dirname(fullPath);
34+
const filename = path.basename(fullPath);
35+
36+
// Skip zip files - they don't need fingerprinting
37+
if (filename.endsWith('.zip')) {
38+
continue;
39+
}
40+
41+
const dynamicChunk = filename.match(/^([a-z0-9]+)-([0-9]+.js(\.map)?)$/);
42+
if (dynamicChunk) {
43+
// This is a dynamic chunk that uses [chunkhash]
44+
// in its filename already - so reverse engineer the .md5 file
45+
// to allow the Gulp script to find the fingerprinted version.
46+
const hash = dynamicChunk[1];
47+
const name = dynamicChunk[2];
48+
49+
const RawSource = compilation.compiler.webpack.sources.RawSource;
50+
compilation.emitAsset(`${dir}/${name}.md5`, new RawSource(hash));
51+
52+
// don't really need this, but Play seems not to serve the file
53+
// unless the non-fingerprinted version exists.
54+
compilation.emitAsset(`${dir}/${name}`, compilation.getAsset(fullPath).source);
55+
} else {
56+
const asset = compilation.getAsset(fullPath);
57+
if (!asset) continue;
58+
59+
const hash = createHash('md5');
60+
hash.update(asset.source.source());
61+
const md5 = hash.digest('hex');
62+
63+
// Identical to original file but with hash prepended.
64+
compilation.emitAsset(`${dir}/${md5}-${filename}`, asset.source);
65+
66+
// Fingerprint .md5 file
67+
const RawSource = compilation.compiler.webpack.sources.RawSource;
68+
compilation.emitAsset(`${dir}/${filename}.md5`, new RawSource(md5));
69+
70+
// versionedFilenames[filename] = `${md5}-${filename}`;
71+
}
72+
}
73+
74+
// for (const chunkId in compilation.chunks) {
75+
// if (compilation.chunks.hasOwnProperty(chunkId)) {
76+
// const chunk = compilation.chunks[chunkId];
77+
// chunk.files = chunk.files.map( file => {
78+
// console.log(`Replacing ${file} with ${versionedFilenames[file]}`);
79+
// return versionedFilenames[file];
80+
// });
81+
// }
82+
// }
83+
84+
done();
85+
}
86+
);
87+
});
88+
}
89+
}
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
module.exports = class WatchEventsPlugin {
1+
export default class WatchEventsPlugin {
22
constructor(options) {
33
this.options = options || {};
44
}
55

66
apply(compiler) {
77
const { emitter } = this.options;
8-
compiler.plugin('after-emit', (compilation, done) => {
8+
compiler.hooks.afterEmit.tapAsync('WatchEventsPlugin', (compilation, done) => {
99
emitter.emit('assets-updated');
1010
done();
1111
});
1212
}
13-
};
13+
}
Lines changed: 33 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,20 @@ import path from 'path';
22
import CopyWebpackPlugin from 'copy-webpack-plugin';
33
import TerserPlugin from 'terser-webpack-plugin';
44
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
5+
import CssMinimizerPlugin from 'css-minimizer-webpack-plugin';
56
import Autoprefixer from 'autoprefixer';
6-
import CssNano from 'cssnano';
7-
import OptimizeCssAssetsPlugin from 'optimize-css-assets-webpack-plugin';
8-
import PostCssSafeParser from 'postcss-safe-parser';
97

108
const autoprefix = () => ({
119
loader: 'postcss-loader',
1210
options: {
13-
plugins: () => [Autoprefixer()],
11+
postcssOptions: {
12+
plugins: [Autoprefixer()],
13+
},
1414
sourceMap: true,
1515
},
1616
});
1717

18-
const lintJS = () => ({
18+
export const lintJS = () => ({
1919

2020
module: {
2121
rules: [
@@ -28,7 +28,7 @@ const lintJS = () => ({
2828
},
2929
});
3030

31-
const transpileJS = () => ({
31+
export const transpileJS = () => ({
3232
output: {
3333
chunkFilename: '[name].js',
3434
filename: '[name].js',
@@ -47,7 +47,7 @@ const transpileJS = () => ({
4747
},
4848
});
4949

50-
const copyNpmDistAssets = ({ modules, dest } = {}) => {
50+
export const copyNpmDistAssets = ({ modules, dest } = {}) => {
5151
const pairs = modules.map(m => ({
5252
from: `node_modules/${m}/dist`,
5353
to: `${dest}/${m}/[1]`,
@@ -56,22 +56,26 @@ const copyNpmDistAssets = ({ modules, dest } = {}) => {
5656

5757
return {
5858
plugins: [
59-
new CopyWebpackPlugin(pairs),
59+
new CopyWebpackPlugin({ patterns: pairs }),
6060
],
6161
};
6262
};
6363

64-
const copyLocalImages = ({ dest } = {}) => ({
64+
export const copyLocalImages = ({ dest } = {}) => ({
6565
plugins: [
66-
new CopyWebpackPlugin([{
67-
from: 'images',
68-
ignore: ['*.sh', 'src', 'src/**/*'],
69-
to: dest,
70-
}]),
66+
new CopyWebpackPlugin({
67+
patterns: [{
68+
from: 'images',
69+
globOptions: {
70+
ignore: ['**/*.sh', '**/src', '**/src/**/*'],
71+
},
72+
to: dest,
73+
}],
74+
}),
7175
],
7276
});
7377

74-
const extractCSS = ({ resolverPaths } = {}) => ({
78+
export const extractCSS = ({ resolverPaths } = {}) => ({
7579
module: {
7680
rules: [
7781
{
@@ -103,10 +107,12 @@ const extractCSS = ({ resolverPaths } = {}) => ({
103107
{
104108
loader: 'less-loader',
105109
options: {
106-
paths: resolverPaths,
107-
relativeUrls: false,
110+
lessOptions: {
111+
paths: resolverPaths,
112+
relativeUrls: false,
113+
math: 'parens-division',
114+
},
108115
sourceMap: true,
109-
math: 'parens-division',
110116
},
111117
},
112118
],
@@ -121,12 +127,10 @@ const extractCSS = ({ resolverPaths } = {}) => ({
121127
});
122128

123129

124-
const minify = () => ({
130+
export const minify = () => ({
125131
optimization: {
126132
minimizer: [
127133
new TerserPlugin({
128-
sourceMap: true,
129-
cache: true,
130134
terserOptions: {
131135
compress: {
132136
drop_console: true,
@@ -136,31 +140,20 @@ const minify = () => ({
136140
},
137141
},
138142
}),
139-
new OptimizeCssAssetsPlugin({
140-
cssProcessor: CssNano,
141-
cssProcessorOptions: {
142-
parser: PostCssSafeParser,
143-
discardComments: {
144-
removeAll: true,
145-
},
143+
new CssMinimizerPlugin({
144+
minimizerOptions: {
145+
preset: ['default', {
146+
discardComments: {
147+
removeAll: true,
148+
},
149+
}],
146150
},
147-
canPrint: true,
148151
}),
149152
],
150153
},
151154
});
152155

153156

154-
const generateSourceMaps = (devtool) => ({
157+
export const generateSourceMaps = (devtool) => ({
155158
devtool,
156159
});
157-
158-
export {
159-
copyNpmDistAssets,
160-
copyLocalImages,
161-
lintJS,
162-
transpileJS,
163-
extractCSS,
164-
minify,
165-
generateSourceMaps,
166-
};
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { existsSync } from 'node:fs';
1111

1212
import pngToIco from 'png-to-ico';
1313

14-
import { COLOURS, generateIcon as generateIconInternal } from "./tools/icon-generator.js";
14+
import { COLOURS, generateIcon as generateIconInternal } from "./tools/icon-generator.mjs";
1515

1616
const __dirname = import.meta.dirname;
1717

mise.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[tools]
2+
node = "22"
3+
ruby = "3.3"
4+
5+
[settings]
6+
idiomatic_version_file_enable_tools = []

0 commit comments

Comments
 (0)