Skip to content

Commit 190e291

Browse files
committed
refactor: Move away from hard-coded filename expectations for push-manifest
1 parent aea6fed commit 190e291

File tree

7 files changed

+115
-87
lines changed

7 files changed

+115
-87
lines changed
Lines changed: 55 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,74 +1,67 @@
1-
const isESM = filename => /\.esm\.js$/.test(filename);
2-
const isMatch = (filename, condition) => isESM(filename) === condition;
1+
module.exports = (assets, namedChunkGroups) => {
2+
/**
3+
* This is a mapping of generic/pre-build filenames to their postbuild output
4+
*
5+
* bundle.js -> bundle.29bec.esm.js
6+
* route-home.css -> styles/route-home.chunk.8aeee.css
7+
*
8+
* Even if a user alters the output name, we still have keys we can expect & rely on
9+
*/
10+
assets = JSON.parse(assets['asset-manifest.json']._value);
311

4-
module.exports = (assets, isESMBuild = false, namedChunkGroups) => {
5-
let mainJs,
6-
mainCss,
7-
scripts = [],
8-
styles = [];
9-
for (let filename in assets) {
10-
if (!/\.map$/.test(filename)) {
11-
if (/^route-.*\.js$/.test(filename)) {
12-
// both ESM & regular match here
13-
isMatch(filename, isESMBuild) && scripts.push(filename);
14-
} else if (/chunk\.(.+)\.css$/.test(filename)) {
15-
styles.push(filename);
16-
} else if (/^bundle(.+)\.css$/.test(filename)) {
17-
mainCss = filename;
18-
} else if (/^bundle(.+)\.js$/.test(filename)) {
19-
// both ESM & regular bundles match here
20-
if (isMatch(filename, isESMBuild)) {
21-
mainJs = filename;
22-
}
23-
}
24-
}
25-
}
12+
const mainJs = assets['bundle.js'];
13+
const mainCss = assets['bundle.css'];
2614

27-
let defaults = {
28-
[mainCss]: {
29-
type: 'style',
30-
weight: 1,
31-
},
32-
[mainJs]: {
33-
type: 'script',
34-
weight: 1,
35-
},
15+
const defaults = {
16+
...(mainCss && {
17+
[mainCss]: {
18+
type: 'style',
19+
weight: 1,
20+
},
21+
}),
22+
...(mainJs && {
23+
[mainJs]: {
24+
type: 'script',
25+
weight: 1,
26+
},
27+
}),
3628
},
3729
manifest = {
3830
'/': defaults,
3931
};
4032

41-
let path, css, obj;
42-
scripts.forEach(filename => {
43-
css = styles.find(asset => asset.startsWith(filename.replace(/\..*/, '')));
44-
obj = Object.assign({}, defaults);
45-
obj[filename] = { type: 'script', weight: 0.9 };
46-
if (css) obj[css] = { type: 'style', weight: 0.9 };
47-
path = filename
48-
.replace(/route-/, '/')
49-
.replace(/\.chunk(\.\w+)?(\.esm)?\.js$/, '')
50-
.replace(/\/home/, '/');
51-
if (namedChunkGroups) {
52-
// async files to be loaded, generated by splitChunksPlugin
53-
const asyncFiles =
54-
namedChunkGroups.get(
55-
filename.replace(/\.chunk(\.\w+)?(\.esm)?\.js$/, '')
56-
) || {};
57-
if (asyncFiles && asyncFiles.chunks) {
58-
asyncFiles.chunks.forEach(asset => {
59-
asset.files = asset.files || [];
60-
asset.files.forEach(file => {
61-
if (/\.css$/.test(file)) {
62-
obj[file] = { type: 'style', weight: 0.9 };
63-
} else if (/\.js$/.test(file)) {
64-
obj[file] = { type: 'script', weight: 0.9 };
65-
}
33+
Object.keys(assets)
34+
.filter(asset => /^route-.*\.js$/.test(asset))
35+
.map(asset => asset.replace(/\.js$/, ''))
36+
.forEach(route => {
37+
const routeManifest = Object.assign({}, defaults);
38+
39+
const routeCss = assets[`${route}.css`];
40+
const routeJs = assets[`${route}.js`];
41+
42+
routeManifest[routeJs] = { type: 'script', weight: 0.9 };
43+
if (routeCss) routeManifest[routeCss] = { type: 'script', weight: 0.9 };
44+
45+
const path = route.replace(/^route-/, '/').replace(/^\/home/, '/');
46+
47+
if (namedChunkGroups) {
48+
// async files to be loaded, generated by splitChunksPlugin
49+
const asyncFiles = namedChunkGroups.get(route) || {};
50+
if (asyncFiles && asyncFiles.chunks) {
51+
asyncFiles.chunks.forEach(asset => {
52+
asset.files = asset.files || [];
53+
asset.files.forEach(file => {
54+
if (/\.css$/.test(file)) {
55+
routeManifest[file] = { type: 'style', weight: 0.9 };
56+
} else if (/\.js$/.test(file)) {
57+
routeManifest[file] = { type: 'script', weight: 0.9 };
58+
}
59+
});
6660
});
67-
});
61+
}
6862
}
69-
}
70-
manifest[path] = obj;
71-
});
63+
manifest[path] = routeManifest;
64+
});
7265

7366
return manifest;
7467
};
Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,33 @@
1+
const webpack = require('webpack');
12
const createLoadManifest = require('./create-load-manifest');
23

34
module.exports = class PushManifestPlugin {
4-
constructor(env = {}) {
5-
this.isESMBuild_ = env.esm;
6-
}
75
apply(compiler) {
8-
compiler.hooks.emit.tap('PushManifestPlugin', compilation => {
9-
const manifest = createLoadManifest(
10-
compilation.assets,
11-
this.isESMBuild_,
12-
compilation.namedChunkGroups
13-
);
6+
compiler.hooks.emit.tap(
7+
{
8+
name: 'PushManifestPlugin',
9+
stage: webpack.Compiler.PROCESS_ASSETS_STAGE_REPORT,
10+
},
11+
compilation => {
12+
const manifest = createLoadManifest(
13+
compilation.assets,
14+
compilation.namedChunkGroups
15+
);
1416

15-
let output = JSON.stringify(manifest);
16-
compilation.assets['push-manifest.json'] = {
17-
source() {
18-
return output;
19-
},
20-
size() {
21-
return output.length;
22-
},
23-
};
17+
let output = JSON.stringify(manifest);
18+
compilation.assets['push-manifest.json'] = {
19+
source() {
20+
return output;
21+
},
22+
size() {
23+
return output.length;
24+
},
25+
};
2426

25-
return compilation;
27+
return compilation;
2628

27-
// callback();
28-
});
29+
// callback();
30+
}
31+
);
2932
}
3033
};

packages/cli/lib/lib/webpack/render-html-plugin.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ module.exports = async function (config) {
9090
if (assets['push-manifest.json']) {
9191
return JSON.parse(assets['push-manifest.json'].source());
9292
}
93-
return createLoadManifest(assets, config.esm, namedChunkGroups);
93+
return createLoadManifest(assets, namedChunkGroups);
9494
},
9595
config,
9696
url,

packages/cli/lib/lib/webpack/webpack-base-config.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ const ReplacePlugin = require('webpack-plugin-replace');
1212
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
1313
const createBabelConfig = require('../babel-config');
1414
const loadPostcssConfig = require('postcss-load-config');
15-
const PnpWebpackPlugin = require(`pnp-webpack-plugin`);
15+
const PnpWebpackPlugin = require('pnp-webpack-plugin');
16+
const { WebpackManifestPlugin } = require('webpack-manifest-plugin');
1617

1718
function readJson(file) {
1819
try {
@@ -330,6 +331,15 @@ module.exports = function createBaseConfig(env) {
330331
summary: false,
331332
clear: true,
332333
}),
334+
new WebpackManifestPlugin({
335+
fileName: 'asset-manifest.json',
336+
assetHookStage: webpack.Compiler.PROCESS_ASSETS_STAGE_ANALYSE,
337+
// TODO: Remove this next breaking change and use the full filepath from this manifest
338+
// when referring to built assets, i.e.:
339+
// https://github.com/preactjs/preact-cli/blob/master/packages/cli/lib/resources/head-end.ejs#L1
340+
// This is just to avoid any potentially breaking changes for right now.
341+
publicPath: '',
342+
}),
333343
...(tsconfig
334344
? [
335345
new ForkTsCheckerWebpackPlugin({

packages/cli/lib/lib/webpack/webpack-client-config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ async function clientConfig(env) {
146146
'process.env.ADD_SW': env.sw,
147147
'process.env.PRERENDER': env.prerender,
148148
}),
149-
new PushManifestPlugin(env),
149+
new PushManifestPlugin(),
150150
...(await renderHTMLPlugin(env)),
151151
...getBabelEsmPlugin(env),
152152
copyPatterns.length !== 0 &&

packages/cli/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@
140140
"webpack-bundle-analyzer": "^4.4.2",
141141
"webpack-dev-server": "^4.7.3",
142142
"webpack-fix-style-only-entries": "^0.6.1",
143+
"webpack-manifest-plugin": "^4.1.1",
143144
"webpack-merge": "^5.3.0",
144145
"webpack-plugin-replace": "^1.2.0",
145146
"which": "^2.0.2",

yarn.lock

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13516,7 +13516,7 @@ sorted-union-stream@~2.1.3:
1351613516
from2 "^1.3.0"
1351713517
stream-iterate "^1.1.0"
1351813518

13519-
source-list-map@^2.0.0:
13519+
source-list-map@^2.0.0, source-list-map@^2.0.1:
1352013520
version "2.0.1"
1352113521
resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34"
1352213522
integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==
@@ -14132,6 +14132,11 @@ tapable@^1.0.0, tapable@^1.1.3:
1413214132
resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2"
1413314133
integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==
1413414134

14135+
tapable@^2.0.0:
14136+
version "2.2.1"
14137+
resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0"
14138+
integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==
14139+
1413514140
tar-fs@^2.0.0:
1413614141
version "2.1.1"
1413714142
resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.1.tgz#489a15ab85f1f0befabb370b7de4f9eb5cbe8784"
@@ -15132,6 +15137,14 @@ webpack-log@^2.0.0:
1513215137
ansi-colors "^3.0.0"
1513315138
uuid "^3.3.2"
1513415139

15140+
webpack-manifest-plugin@^4.1.1:
15141+
version "4.1.1"
15142+
resolved "https://registry.yarnpkg.com/webpack-manifest-plugin/-/webpack-manifest-plugin-4.1.1.tgz#10f8dbf4714ff93a215d5a45bcc416d80506f94f"
15143+
integrity sha512-YXUAwxtfKIJIKkhg03MKuiFAD72PlrqCiwdwO4VEXdRO5V0ORCNwaOwAZawPZalCbmH9kBDmXnNeQOw+BIEiow==
15144+
dependencies:
15145+
tapable "^2.0.0"
15146+
webpack-sources "^2.2.0"
15147+
1513515148
webpack-merge@^5.3.0:
1513615149
version "5.7.3"
1513715150
resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.7.3.tgz#2a0754e1877a25a8bbab3d2475ca70a052708213"
@@ -15153,6 +15166,14 @@ webpack-sources@^1.1.0, webpack-sources@^1.3.0, webpack-sources@^1.4.0, webpack-
1515315166
source-list-map "^2.0.0"
1515415167
source-map "~0.6.1"
1515515168

15169+
webpack-sources@^2.2.0:
15170+
version "2.3.1"
15171+
resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-2.3.1.tgz#570de0af163949fe272233c2cefe1b56f74511fd"
15172+
integrity sha512-y9EI9AO42JjEcrTJFOYmVywVZdKVUfOvDUPsJea5GIr1JOEGFVqwlY2K098fFoIjOkDzHn2AjRvM8dsBZu+gCA==
15173+
dependencies:
15174+
source-list-map "^2.0.1"
15175+
source-map "^0.6.1"
15176+
1515615177
webpack@^4.38.0:
1515715178
version "4.46.0"
1515815179
resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.46.0.tgz#bf9b4404ea20a073605e0a011d188d77cb6ad542"

0 commit comments

Comments
 (0)