Skip to content

Commit 1d66a66

Browse files
committed
chore: Updating webpack-dev-server (#1646)
1 parent 0125cc3 commit 1d66a66

File tree

10 files changed

+694
-1181
lines changed

10 files changed

+694
-1181
lines changed

.changeset/clean-kiwis-unite.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'preact-cli': patch
3+
---
4+
5+
Bumping `webpack-dev-server`

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

Lines changed: 63 additions & 47 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, readFileSync, writeFileSync, mkdirSync } = 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');
@@ -17,8 +19,8 @@ function read(path) {
1719
return readFileSync(resolve(__dirname, path), 'utf-8');
1820
}
1921

20-
module.exports = async function (config) {
21-
const { cwd, dest, isProd, src } = config;
22+
module.exports = async function renderHTMLPlugin(config) {
23+
const { cwd, dest, src } = config;
2224
const inProjectTemplatePath = resolve(src, 'template.html');
2325
let template = defaultTemplate;
2426
if (existsSync(inProjectTemplatePath)) {
@@ -38,10 +40,7 @@ module.exports = async function (config) {
3840
const headEnd = read('../../resources/head-end.ejs');
3941
const bodyEnd = read('../../resources/body-end.ejs');
4042
content = content
41-
.replace(
42-
/<%[=]?\s+preact\.title\s+%>/,
43-
'<%= htmlWebpackPlugin.options.title %>'
44-
)
43+
.replace(/<%[=]?\s+preact\.title\s+%>/, '<%= cli.title %>')
4544
.replace(/<%\s+preact\.headEnd\s+%>/, headEnd)
4645
.replace(/<%\s+preact\.bodyEnd\s+%>/, bodyEnd);
4746

@@ -56,53 +55,71 @@ module.exports = async function (config) {
5655
}
5756

5857
const htmlWebpackConfig = values => {
59-
const { url, title, ...routeData } = values;
58+
let { url, title, ...routeData } = values;
59+
60+
title =
61+
title ||
62+
config.title ||
63+
config.manifest.name ||
64+
config.manifest.short_name ||
65+
(config.pkg.name || '').replace(/^@[a-z]\//, '') ||
66+
'Preact App';
67+
6068
// Do not create a folder if the url is for a specific file.
6169
const filename = url.endsWith('.html')
6270
? resolve(dest, url.substring(1))
6371
: resolve(dest, url.substring(1), 'index.html');
64-
return Object.assign(values, {
72+
73+
return {
74+
title,
6575
filename,
6676
template: `!!${require.resolve('ejs-loader')}?esModule=false!${template}`,
67-
minify: isProd && {
68-
collapseWhitespace: true,
69-
removeScriptTypeAttributes: true,
70-
removeRedundantAttributes: true,
71-
removeStyleLinkTypeAttributes: true,
72-
removeComments: true,
77+
templateParameters: (compilation, assets, assetTags, options) => {
78+
let entrypoints = {};
79+
compilation.entrypoints.forEach((entrypoint, name) => {
80+
let entryFiles = entrypoint.getFiles();
81+
entrypoints[name] =
82+
assets.publicPath +
83+
entryFiles.find(file => /\.(m?js)(\?|$)/.test(file));
84+
});
85+
86+
let loadManifest = compilation.assets['push-manifest.json']
87+
? JSON.parse(compilation.assets['push-manifest.json'].source())
88+
: createLoadManifest(
89+
compilation.assets,
90+
config.esm,
91+
compilation.namedChunkGroups
92+
);
93+
94+
return {
95+
cli: {
96+
title,
97+
url,
98+
manifest: config.manifest,
99+
inlineCss: config['inline-css'],
100+
preload: config.preload,
101+
config,
102+
preRenderData: values,
103+
CLI_DATA: { preRenderData: { url, ...routeData } },
104+
ssr: config.prerender ? prerender({ cwd, dest, src }, values) : '',
105+
loadManifest,
106+
entrypoints,
107+
},
108+
htmlWebpackPlugin: {
109+
tags: assetTags,
110+
files: assets,
111+
options: options,
112+
},
113+
};
73114
},
115+
inject: true,
116+
scriptLoading: 'defer',
74117
favicon: existsSync(resolve(src, 'assets/favicon.ico'))
75118
? 'assets/favicon.ico'
76119
: '',
77-
inject: true,
78-
compile: true,
79-
inlineCss: config['inline-css'],
80-
preload: config.preload,
81-
manifest: config.manifest,
82-
title:
83-
title ||
84-
config.title ||
85-
config.manifest.name ||
86-
config.manifest.short_name ||
87-
(config.pkg.name || '').replace(/^@[a-z]\//, '') ||
88-
'Preact App',
89120
excludeAssets: [/(bundle|polyfills)(\..*)?\.js$/],
90-
createLoadManifest: (assets, namedChunkGroups) => {
91-
if (assets['push-manifest.json']) {
92-
return JSON.parse(assets['push-manifest.json'].source());
93-
}
94-
return createLoadManifest(assets, config.esm, namedChunkGroups);
95-
},
96-
config,
97-
url,
98-
ssr() {
99-
return config.prerender && url !== PREACT_FALLBACK_URL
100-
? prerender({ cwd, dest, src }, values)
101-
: '';
102-
},
103-
scriptLoading: 'defer',
104-
CLI_DATA: { preRenderData: { url, ...routeData } },
105-
});
121+
// excludeChunks: ['bundle', 'polyfills']
122+
};
106123
};
107124

108125
let pages = [{ url: '/' }];
@@ -158,7 +175,7 @@ module.exports = async function (config) {
158175
const resultPages = pages
159176
.map(htmlWebpackConfig)
160177
.map(conf => new HtmlWebpackPlugin(conf))
161-
.concat([new HtmlWebpackExcludeAssetsPlugin()]);
178+
.concat([new HtmlWebpackSkipAssetsPlugin()]);
162179

163180
return config.prerender
164181
? resultPages.concat([
@@ -170,10 +187,9 @@ module.exports = async function (config) {
170187
// Adds a preact_prerender_data in every folder so that the data could be fetched separately.
171188
class PrerenderDataExtractPlugin {
172189
constructor(page) {
173-
const cliData = page.CLI_DATA || {};
174-
const { url } = cliData.preRenderData || {};
190+
const url = page.url;
175191
this.location_ = url.endsWith('/') ? url : url + '/';
176-
this.data_ = JSON.stringify(cliData.preRenderData || {});
192+
this.data_ = JSON.stringify(page || {});
177193
}
178194
apply(compiler) {
179195
compiler.hooks.emit.tap('PrerenderDataExtractPlugin', compilation => {

packages/cli/lib/lib/webpack/run-webpack.js

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,8 @@ async function devBuild(env) {
6161

6262
compiler.hooks.failed.tap('CliDevPlugin', rej);
6363

64-
let c = Object.assign({}, config.devServer, {
65-
stats: { colors: true },
66-
});
67-
68-
let server = new DevServer(compiler, c);
69-
server.listen(env.port);
64+
let server = new DevServer(config.devServer, compiler);
65+
server.start();
7066
res(server);
7167
});
7268
}

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

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -163,8 +163,8 @@ function getBabelEsmPlugin(config) {
163163
: '[name].esm.js',
164164
chunkFilename: '[name].chunk.[chunkhash:5].esm.js',
165165
excludedPlugins: ['BabelEsmPlugin', 'InjectManifest'],
166-
beforeStartExecution: (plugins) => {
167-
plugins.forEach((plugin) => {
166+
beforeStartExecution: plugins => {
167+
plugins.forEach(plugin => {
168168
if (
169169
plugin.constructor.name === 'DefinePlugin' &&
170170
plugin.definitions
@@ -278,9 +278,11 @@ function isDev(config) {
278278
const { cwd, src, refresh } = config;
279279

280280
return {
281+
infrastructureLogging: {
282+
level: 'info',
283+
},
281284
plugins: [
282285
new webpack.NamedModulesPlugin(),
283-
new webpack.HotModuleReplacementPlugin(),
284286
...(refresh ? [new RefreshPlugin()] : []),
285287
new webpack.DefinePlugin({
286288
'process.env.ADD_SW': config.sw,
@@ -289,22 +291,26 @@ function isDev(config) {
289291
],
290292

291293
devServer: {
292-
inline: true,
293294
hot: true,
294295
compress: true,
295-
publicPath: '/',
296-
contentBase: src,
296+
devMiddleware: {
297+
publicPath: '/',
298+
stats: 'errors-warnings',
299+
},
300+
static: {
301+
directory: src,
302+
watch: {
303+
ignored: [resolve(cwd, 'build'), resolve(cwd, 'node_modules')],
304+
},
305+
},
297306
https: config.https,
298307
port: config.port,
299308
host: process.env.HOST || config.host || '0.0.0.0',
300-
disableHostCheck: true,
309+
allowedHosts: 'all',
301310
historyApiFallback: true,
302-
quiet: true,
303-
clientLogLevel: 'none',
304-
overlay: false,
305-
stats: 'minimal',
306-
watchOptions: {
307-
ignored: [resolve(cwd, 'build'), resolve(cwd, 'node_modules')],
311+
client: {
312+
logging: 'none',
313+
overlay: false,
308314
},
309315
},
310316
};
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/lib/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/package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@
9292
"compression-webpack-plugin": "^6.0.4",
9393
"console-clear": "^1.0.0",
9494
"copy-webpack-plugin": "^6.2.1",
95-
"critters-webpack-plugin": "^2.5.0",
95+
"critters-webpack-plugin": "^3.0.0",
9696
"cross-spawn-promise": "^0.10.1",
9797
"css-loader": "^5.2.4",
9898
"ejs-loader": "^0.5.0",
@@ -103,8 +103,8 @@
103103
"get-port": "^5.0.0",
104104
"gittar": "^0.1.0",
105105
"glob": "^7.1.4",
106-
"html-webpack-exclude-assets-plugin": "0.0.7",
107-
"html-webpack-plugin": "^3.2.0",
106+
"html-webpack-skip-assets-plugin": "1.0.3",
107+
"html-webpack-plugin": "^4.5.2",
108108
"ip": "^1.1.5",
109109
"isomorphic-unfetch": "^3.1.0",
110110
"kleur": "^4.1.4",
@@ -136,7 +136,7 @@
136136
"validate-npm-package-name": "^3.0.0",
137137
"webpack": "^4.38.0",
138138
"webpack-bundle-analyzer": "^4.4.2",
139-
"webpack-dev-server": "^3.11.2",
139+
"webpack-dev-server": "^4.7.3",
140140
"webpack-fix-style-only-entries": "^0.6.1",
141141
"webpack-merge": "^5.3.0",
142142
"webpack-plugin-replace": "^1.2.0",

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

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@
66
</head>
77
<body>
88
<h1>Guess what</h1>
9-
<%= htmlWebpackPlugin.options.ssr({
10-
url: '/'
11-
}) %>
12-
<script defer src="<%= htmlWebpackPlugin.files.chunks['bundle'].entry %>"></script>
9+
<%= cli.ssr %>
10+
<script defer src="<%= cli.entrypoints['bundle'] %>"></script>
1311
</body>
1412
</html>

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

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,11 @@
22
<html lang="en">
33
<head>
44
<meta charset="utf-8">
5-
<title><%= htmlWebpackPlugin.options.title %></title>
5+
<title><%= cli.title %></title>
66
</head>
77
<body>
88
<h1>Guess what</h1>
9-
<%= htmlWebpackPlugin.options.ssr({
10-
url: '/'
11-
}) %>
12-
<script defer src="<%= htmlWebpackPlugin.files.chunks['bundle'].entry %>"></script>
9+
<%= cli.ssr %>
10+
<script defer src="<%= cli.entrypoints['bundle'] %>"></script>
1311
</body>
1412
</html>

0 commit comments

Comments
 (0)