Skip to content

Commit d40f6d7

Browse files
committed
Chore: Updating html-webpack-plugin to v4 (#1608)
1 parent 9ebd4ff commit d40f6d7

File tree

11 files changed

+307
-897
lines changed

11 files changed

+307
-897
lines changed

.changeset/rude-walls-dress.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'preact-cli': minor
3+
'@preact/prerender-data-provider': patch
4+
---
5+
6+
Updates to use html-webpack-plugin v4

packages/cli/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656
"compression-webpack-plugin": "^6.1.1",
5757
"console-clear": "^1.0.0",
5858
"copy-webpack-plugin": "^6.4.0",
59-
"critters-webpack-plugin": "^2.5.0",
59+
"critters-webpack-plugin": "^3.0.2",
6060
"cross-spawn-promise": "^0.10.1",
6161
"css-loader": "^5.2.7",
6262
"dotenv": "^16.0.0",
@@ -68,8 +68,8 @@
6868
"get-port": "^5.0.0",
6969
"gittar": "^0.1.0",
7070
"glob": "^8.0.3",
71-
"html-webpack-exclude-assets-plugin": "0.0.7",
72-
"html-webpack-plugin": "^3.2.0",
71+
"html-webpack-plugin": "^4.5.2",
72+
"html-webpack-skip-assets-plugin": "1.0.3",
7373
"ip": "^1.1.8",
7474
"isomorphic-unfetch": "^3.1.0",
7575
"kleur": "^4.1.4",

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

Lines changed: 65 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
const { resolve, join } = require('path');
22
const os = require('os');
33
const { existsSync, mkdtempSync, readFileSync, writeFileSync } = require('fs');
4-
const HtmlWebpackExcludeAssetsPlugin = require('html-webpack-exclude-assets-plugin');
4+
const {
5+
HtmlWebpackSkipAssetsPlugin,
6+
} = require('html-webpack-skip-assets-plugin');
57
const HtmlWebpackPlugin = require('html-webpack-plugin');
68
const prerender = require('./prerender');
79
const createLoadManifest = require('./create-load-manifest');
@@ -15,8 +17,8 @@ function read(path) {
1517
return readFileSync(resolve(__dirname, path), 'utf-8');
1618
}
1719

18-
module.exports = async function (config) {
19-
const { cwd, dest, isProd, src } = config;
20+
module.exports = async function renderHTMLPlugin(config) {
21+
const { cwd, dest, src } = config;
2022
const inProjectTemplatePath = resolve(src, 'template.html');
2123
let template = defaultTemplate;
2224
if (existsSync(inProjectTemplatePath)) {
@@ -32,14 +34,11 @@ module.exports = async function (config) {
3234
}
3335

3436
let content = read(template);
35-
if (/preact\.headEnd|preact\.bodyEnd/.test(content)) {
37+
if (/preact\.(title|headEnd|bodyEnd)/.test(content)) {
3638
const headEnd = read('../../resources/head-end.ejs');
3739
const bodyEnd = read('../../resources/body-end.ejs');
3840
content = content
39-
.replace(
40-
/<%[=]?\s+preact\.title\s+%>/,
41-
'<%= htmlWebpackPlugin.options.title %>'
42-
)
41+
.replace(/<%[=]?\s+preact\.title\s+%>/, '<%= cli.title %>')
4342
.replace(/<%\s+preact\.headEnd\s+%>/, headEnd)
4443
.replace(/<%\s+preact\.bodyEnd\s+%>/, bodyEnd);
4544

@@ -51,53 +50,72 @@ module.exports = async function (config) {
5150
}
5251

5352
const htmlWebpackConfig = values => {
54-
const { url, title, ...routeData } = values;
53+
let { url, title, ...routeData } = values;
54+
55+
title =
56+
title ||
57+
config.title ||
58+
config.manifest.name ||
59+
config.manifest.short_name ||
60+
(config.pkg.name || '').replace(/^@[a-z]\//, '') ||
61+
'Preact App';
62+
5563
// Do not create a folder if the url is for a specific file.
5664
const filename = url.endsWith('.html')
5765
? resolve(dest, url.substring(1))
5866
: resolve(dest, url.substring(1), 'index.html');
59-
return Object.assign(values, {
67+
68+
return {
69+
title,
6070
filename,
6171
template: `!!${require.resolve('ejs-loader')}?esModule=false!${template}`,
62-
minify: isProd && {
63-
collapseWhitespace: true,
64-
removeScriptTypeAttributes: true,
65-
removeRedundantAttributes: true,
66-
removeStyleLinkTypeAttributes: true,
67-
removeComments: true,
72+
templateParameters: (compilation, assets, assetTags, options) => {
73+
let entrypoints = {};
74+
compilation.entrypoints.forEach((entrypoint, name) => {
75+
let entryFiles = entrypoint.getFiles();
76+
entrypoints[name] =
77+
assets.publicPath +
78+
entryFiles.find(file => /\.(m?js)(\?|$)/.test(file));
79+
});
80+
81+
let loadManifest = compilation.assets['push-manifest.json']
82+
? JSON.parse(compilation.assets['push-manifest.json'].source())
83+
: createLoadManifest(
84+
compilation.assets,
85+
compilation.namedChunkGroups,
86+
config.isProd
87+
);
88+
89+
return {
90+
cli: {
91+
title,
92+
url,
93+
manifest: config.manifest,
94+
inlineCss: config['inline-css'],
95+
preload: config.preload,
96+
config,
97+
preRenderData: values,
98+
CLI_DATA: { preRenderData: { url, ...routeData } },
99+
ssr: config.prerender ? prerender({ cwd, dest, src }, values) : '',
100+
loadManifest,
101+
entrypoints,
102+
},
103+
htmlWebpackPlugin: {
104+
tags: assetTags,
105+
files: assets,
106+
options,
107+
},
108+
};
68109
},
110+
inject: true,
69111
favicon: existsSync(resolve(src, 'assets/favicon.ico'))
70112
? 'assets/favicon.ico'
71113
: '',
72-
inject: true,
73-
compile: true,
74-
inlineCss: config['inline-css'],
75-
preload: config.preload,
76-
manifest: config.manifest,
77-
title:
78-
title ||
79-
config.title ||
80-
config.manifest.name ||
81-
config.manifest.short_name ||
82-
(config.pkg.name || '').replace(/^@[a-z]\//, '') ||
83-
'Preact App',
114+
manifest: existsSync(resolve(src, 'manifest.json'))
115+
? 'manifest.json'
116+
: '',
84117
excludeAssets: [/(bundle|polyfills)(\..*)?\.js$/],
85-
createLoadManifest: (assets, namedChunkGroups) => {
86-
if (assets['push-manifest.json']) {
87-
return JSON.parse(assets['push-manifest.json'].source());
88-
}
89-
return createLoadManifest(assets, namedChunkGroups, config.isProd);
90-
},
91-
config,
92-
url,
93-
ssr() {
94-
return config.prerender && url !== PREACT_FALLBACK_URL
95-
? prerender({ cwd, dest, src }, values)
96-
: '';
97-
},
98-
scriptLoading: 'defer',
99-
CLI_DATA: { preRenderData: { url, ...routeData } },
100-
});
118+
};
101119
};
102120

103121
let pages = [{ url: '/' }];
@@ -148,7 +166,7 @@ module.exports = async function (config) {
148166
const resultPages = pages
149167
.map(htmlWebpackConfig)
150168
.map(conf => new HtmlWebpackPlugin(conf))
151-
.concat([new HtmlWebpackExcludeAssetsPlugin()]);
169+
.concat([new HtmlWebpackSkipAssetsPlugin()]);
152170

153171
return config.prerender
154172
? resultPages.concat([
@@ -160,10 +178,9 @@ module.exports = async function (config) {
160178
// Adds a preact_prerender_data in every folder so that the data could be fetched separately.
161179
class PrerenderDataExtractPlugin {
162180
constructor(page) {
163-
const cliData = page.CLI_DATA || {};
164-
const { url } = cliData.preRenderData || {};
181+
const url = page.url;
165182
this.location_ = url.endsWith('/') ? url : url + '/';
166-
this.data_ = JSON.stringify(cliData.preRenderData || {});
183+
this.data_ = JSON.stringify(page || {});
167184
}
168185
apply(compiler) {
169186
compiler.hooks.emit.tap('PrerenderDataExtractPlugin', compilation => {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ function isProd(env) {
261261
preload: 'media',
262262
pruneSource: false,
263263
logLevel: 'silent',
264-
additionalStylesheets: ['*.css'],
264+
additionalStylesheets: ['route-*.css'],
265265
})
266266
);
267267
}
Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
1-
<%= htmlWebpackPlugin.options.ssr() %>
2-
<% if (htmlWebpackPlugin.options.config.prerender === true) { %>
1+
<%= cli.ssr %>
2+
<% if (cli.config.prerender === true) { %>
33
<script type="__PREACT_CLI_DATA__">
4-
<%= encodeURI(JSON.stringify(htmlWebpackPlugin.options.CLI_DATA)) %>
4+
<%= encodeURI(JSON.stringify(cli.CLI_DATA)) %>
55
</script>
66
<% } %>
7-
<% if (webpack.assets.filter(entry => entry.name.match(/bundle(\.\w{5})?.esm.js$/)).length > 0) { %>
8-
<script crossorigin="anonymous" src="<%= htmlWebpackPlugin.files.publicPath %><%= webpack.assets.filter(entry => entry.name.match(/bundle(\.\w{5})?.esm.js$/))[0].name %>" type="module"></script>
7+
<% if (htmlWebpackPlugin.files.js.filter(entry => entry.match(/bundle(\.\w{5})?.esm.js$/)).length > 0) { %>
8+
<script crossorigin="anonymous" src="<%= htmlWebpackPlugin.files.js.filter(entry => entry.match(/bundle(\.\w{5})?.esm.js$/))[0] %>" type="module"></script>
99
<%
1010
/*Fetch and Promise polyfills are not needed for browsers that support type=module
1111
Please re-evaluate below line if adding more polyfills.*/
1212
%>
13-
<script nomodule src="<%= htmlWebpackPlugin.files.chunks["polyfills"].entry %>"></script>
14-
<script nomodule defer src="<%= htmlWebpackPlugin.files.chunks['bundle'].entry %>"></script>
13+
<script nomodule src="<%= cli.entrypoints['polyfills'] %>"></script>
14+
<script nomodule defer src="<%= cli.entrypoints['bundle'] %>"></script>
1515
<% } else { %>
16-
<script <%= htmlWebpackPlugin.options.scriptLoading %> src="<%= htmlWebpackPlugin.files.chunks['bundle'].entry %>"></script>
17-
<script nomodule src="<%= htmlWebpackPlugin.files.chunks["polyfills"].entry %>"></script>
16+
<script <%= htmlWebpackPlugin.options.scriptLoading %> src="<%= cli.entrypoints['bundle'] %>"></script>
17+
<script nomodule src="<%= cli.entrypoints['polyfills'] %>"></script>
1818
<% } %>

packages/cli/src/resources/head-end.ejs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
<link rel="manifest" href="<%= htmlWebpackPlugin.files.publicPath %>manifest.json">
2-
<% if (htmlWebpackPlugin.options.manifest.theme_color) { %>
3-
<meta name="theme-color" content="<%= htmlWebpackPlugin.options.manifest.theme_color %>">
2+
<% if (cli.manifest.theme_color) { %>
3+
<meta name="theme-color" content="<%= cli.manifest.theme_color %>">
44
<% } %>
5-
<% const loadManifest = htmlWebpackPlugin.options.createLoadManifest(compilation.assets, webpack.namedChunkGroups);%>
6-
<% const filesRegexp = htmlWebpackPlugin.options.inlineCss ? /\.(chunk\.\w{5}\.css|js)$/ : /\.(css|js)$/;%>
7-
<% for (const file in loadManifest[htmlWebpackPlugin.options.url]) { %>
8-
<% if (htmlWebpackPlugin.options.preload && file && file.match(filesRegexp)) { %>
5+
<% const filesRegexp = cli.inlineCss ? /\.(chunk\.\w{5}\.css|js)$/ : /\.(css|js)$/;%>
6+
<% for (const file in cli.loadManifest[cli.url]) { %>
7+
<% if (cli.preload && file && file.match(filesRegexp)) { %>
98
<% /* crossorigin for main bundle as that is loaded from `<script type=module` tag, other lazy loaded bundles are from webpack so its not needed */ %>
109
<link rel="preload" href="<%= htmlWebpackPlugin.files.publicPath + file %>" as="<%= file.match(/\.css$/)?'style':'script' %>" <%= file.match(/bundle\.\w{5}\.esm\.js$/)?'crossorigin="anonymous"':'' %>>
1110
<% } %>

packages/cli/tests/images/build.js

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ exports.prerender.heads.home = `
7070
<link rel="apple-touch-icon" href=\\"\\/assets\\/icons\\/apple-touch-icon\\.png\\">
7171
<link rel="manifest" href="\\/manifest\\.json">
7272
<style>html{padding:0}<\\/style>
73-
<link href=\\"/bundle.\\w{5}.css\\" rel=\\"stylesheet\\" media=\\"only x\\" onload=\\"this.media='all'\\">
73+
<link href=\\"/bundle.\\w{5}.css\\" rel=\\"stylesheet\\" media=\\"print\\" onload=\\"this.media='all'\\">
7474
<noscript>
7575
<link rel=\\"stylesheet\\" href=\\"\\/bundle.\\w{5}.css\\">
7676
</noscript>
@@ -87,7 +87,7 @@ exports.prerender.heads.route66 = `
8787
<link rel="apple-touch-icon" href=\\"\\/assets\\/icons\\/apple-touch-icon\\.png\\">
8888
<link rel="manifest" href="\\/manifest\\.json">
8989
<style>html{padding:0}<\\/style>
90-
<link href=\\"/bundle.\\w{5}.css\\" rel=\\"stylesheet\\" media=\\"only x\\" onload=\\"this.media='all'\\">
90+
<link href=\\"/bundle.\\w{5}.css\\" rel=\\"stylesheet\\" media=\\"print\\" onload=\\"this.media='all'\\">
9191
<noscript>
9292
<link rel=\\"stylesheet\\" href=\\"\\/bundle.\\w{5}.css\\">
9393
</noscript>
@@ -104,7 +104,7 @@ exports.prerender.heads.custom = `
104104
<link rel="apple-touch-icon" href=\\"\\/assets\\/icons\\/apple-touch-icon\\.png\\">
105105
<link rel="manifest" href="\\/manifest\\.json">
106106
<style>html{padding:0}<\\/style>
107-
<link href=\\"/bundle.\\w{5}.css\\" rel=\\"stylesheet\\" media=\\"only x\\" onload=\\"this.media='all'\\">
107+
<link href=\\"/bundle.\\w{5}.css\\" rel=\\"stylesheet\\" media=\\"print\\" onload=\\"this.media='all'\\">
108108
<noscript>
109109
<link rel=\\"stylesheet\\" href=\\"\\/bundle.\\w{5}.css\\">
110110
</noscript>
@@ -126,7 +126,7 @@ exports.preload.true = `
126126
<link rel=\\"preload\\" href=\\"\\/route-home\\.chunk\\.\\w{5}\\.js\\" as=\\"script\\">
127127
<link rel=\\"preload\\" href=\\"\\/route-home\\.chunk\\.\\w{5}\\.css\\" as=\\"style\\">
128128
<style>html{padding:0}<\\/style>
129-
<link href=\\"\\/bundle\\.\\w{5}\\.css\\" rel=\\"stylesheet\\" media=\\"only x\\" onload=\\"this.media='all'\\">
129+
<link href=\\"\\/bundle\\.\\w{5}\\.css\\" rel=\\"stylesheet\\" media=\\"print\\" onload=\\"this.media='all'\\">
130130
<noscript>
131131
<link rel=\\"stylesheet\\" href=\\"\\/bundle.\\w{5}.css\\">
132132
</noscript>
@@ -143,7 +143,7 @@ exports.preload.false = `
143143
<link rel=\\"apple-touch-icon\\" href=\\"\\/assets\\/icons\\/apple-touch-icon\\.png\\">
144144
<link rel=\\"manifest\\" href=\\"\\/manifest\\.json\\">
145145
<style>html{padding:0}<\\/style>
146-
<link href=\\"\\/bundle\\.\\w{5}\\.css\\" rel=\\"stylesheet\\" media=\\"only x\\" onload=\\"this.media='all'\\">
146+
<link href=\\"\\/bundle\\.\\w{5}\\.css\\" rel=\\"stylesheet\\" media=\\"print\\" onload=\\"this.media='all'\\">
147147
<noscript>
148148
<link rel=\\"stylesheet\\" href=\\"\\/bundle.\\w{5}.css\\">
149149
</noscript>
@@ -313,7 +313,6 @@ exports.publicPath = `
313313
<link rel="apple-touch-icon" href="/example-path/assets/icons/apple-touch-icon.png">
314314
<link rel="manifest" href="/example-path/manifest.json">
315315
<link href="/example-path/bundle.\\w{5}.css" rel="stylesheet">
316-
<style></style>
317316
</head>
318317
<body>
319318
<h1>Public path test</h1>

packages/cli/tests/subjects/custom-template/template.html

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<head>
44
<meta charset="utf-8">
55
<title><% preact.title %></title>
6-
<% if (htmlWebpackPlugin.options.config.isProd) { %>
6+
<% if (cli.config.isProd) { %>
77
<meta name="example-meta" content="Hello Prod">
88
<% } else { %>
99
<meta name="example-meta" content="Hello Dev">
@@ -12,10 +12,8 @@
1212
</head>
1313
<body>
1414
<h1>Guess what</h1>
15-
<%= htmlWebpackPlugin.options.ssr({
16-
url: '/'
17-
}) %>
18-
<script defer src="<%= htmlWebpackPlugin.files.chunks['bundle'].entry %>"></script>
15+
<%= cli.ssr %>
16+
<script defer src="<%= cli.entrypoints['bundle'] %>"></script>
1917
<% preact.bodyEnd %>
2018
</body>
2119
</html>

packages/prerender-data-provider/src/hook.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ function usePrerenderData(props, doAutomaticFetch = true) {
3838
}
3939
}
4040

41-
if (contextValue.CLI_DATA && contextValue.CLI_DATA.preRenderData) {
42-
value = contextValue.CLI_DATA.preRenderData;
41+
if (contextValue) {
42+
value = contextValue;
4343
}
4444

4545
const data = getPrerenderdata(state.value || value, props);

packages/prerender-data-provider/src/render-prop.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ class PreRenderDataSource extends Component {
4949
{contextValue => {
5050
let obtainedContextValue;
5151
// If the data is in script tag, it will be accesible from the following chaining
52-
if (contextValue.CLI_DATA && contextValue.CLI_DATA.preRenderData) {
53-
obtainedContextValue = contextValue.CLI_DATA.preRenderData;
52+
if (contextValue) {
53+
obtainedContextValue = contextValue;
5454
}
5555
const preRenderDataToBePassed = getPrerenderdata(
5656
value || obtainedContextValue,

0 commit comments

Comments
 (0)