Skip to content

Commit 4ce7edd

Browse files
authored
feat: use html-webpack-plugin v5 by default (#6269)
1 parent f9d53c7 commit 4ce7edd

File tree

15 files changed

+98
-38
lines changed

15 files changed

+98
-38
lines changed

docs/migrations/migrate-from-v4.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ No longer supports generating project with `node-sass`. It has been [deprecated]
7878

7979
#### Underlying Loaders and Plugins
8080

81-
* `html-webpack-plugin` is upgraded from v3 to v4, see more details in the [release announcement](https://dev.to/jantimon/html-webpack-plugin-4-has-been-released-125d).
81+
* `html-webpack-plugin` is upgraded from v3 to v5, and for webpack 4 users, v4 will be used. More details are available in the [release announcement of `html-webpack-plugin` v4](https://dev.to/jantimon/html-webpack-plugin-4-has-been-released-125d) and the [full changelog](https://github.com/jantimon/html-webpack-plugin/blob/master/CHANGELOG.md).
8282
* `sass-loader` v7 support is dropped. See the v8 breaking changes at its [changelog](https://github.com/webpack-contrib/sass-loader/blob/master/CHANGELOG.md#800-2019-08-29).
8383
* `postcss-loader` is upgraded from v3 to v4. Most notably, `PostCSS` options (`plugin` / `syntax` / `parser` / `stringifier`) are moved into the `postcssOptions` field. More details available at the [changelog](https://github.com/webpack-contrib/postcss-loader/blob/master/CHANGELOG.md#400-2020-09-07).
8484
* `copy-webpack-plugin` is upgraded from v5 to v6. If you never customized its config through `config.plugin('copy')`, there should be no user-facing breaking changes. A full list of breaking changes is available at [`copy-webpack-plugin` v6.0.0 release](https://github.com/webpack-contrib/copy-webpack-plugin/releases/tag/v6.0.0).

packages/@vue/cli-plugin-babel/index.js

+5
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ module.exports = (api, options) => {
3939
.test(/\.m?jsx?$/)
4040
.exclude
4141
.add(filepath => {
42+
// With data URI support in webpack 5, filepath could be undefined
43+
if (!filepath) {
44+
return true
45+
}
46+
4247
// always transpile js in vue files
4348
if (/\.vue\.jsx?$/.test(filepath)) {
4449
return false

packages/@vue/cli-plugin-pwa/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
},
2525
"dependencies": {
2626
"@vue/cli-shared-utils": "^5.0.0-alpha.3",
27-
"html-webpack-plugin": "^4.5.0",
27+
"html-webpack-plugin": "^5.0.0",
2828
"webpack": "^5.10.0",
2929
"workbox-webpack-plugin": "^6.0.2"
3030
},

packages/@vue/cli-plugin-webpack-4/generator.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@ module.exports = (api) => {
88
// Yarn and PNPM 5.10+ support this feature
99
// So we'll try to use that whenever possible
1010
resolutions: {
11-
'@vue/cli-*/webpack': '^4.0.0'
11+
'@vue/cli-*/webpack': '^4.0.0',
12+
'html-webpack-plugin': '^4.5.1'
1213
}
1314
})
15+
16+
// TODO: if uses sass, replace sass-loader@11 with sass-loader@10
1417
}
+11-6
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1+
const path = require('path')
2+
const moduleAlias = require('module-alias')
3+
4+
const htmlWebpackPlugin4Path = path.dirname(require.resolve('html-webpack-plugin/package.json'))
5+
// We have to use module-alias for html-webpack-plguin, as it is required by many other plugins
6+
// as peer dependency for its `getHooks` API.
7+
// Should add the alias as early as possible to avoid problems
8+
// TODO: add debugging log here
9+
moduleAlias.addAlias('html-webpack-plugin', htmlWebpackPlugin4Path)
10+
111
/** @type {import('@vue/cli-service').ServicePlugin} */
2-
module.exports = () => {
3-
// TODO:
4-
// terser-webpack-plugin v4
5-
// copy-webpack-plugin v6
6-
// html-webpack-plugin v4
7-
// css-minimizer-webpack-plugin v1
12+
module.exports = (api, options) => {
813
}

packages/@vue/cli-plugin-webpack-4/package.json

+2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
"access": "public"
2424
},
2525
"dependencies": {
26+
"html-webpack-plugin": "^4.5.1",
27+
"module-alias": "^2.2.2",
2628
"webpack": "^4.44.2"
2729
},
2830
"peerDependencies": {

packages/@vue/cli-service/__tests__/build.spec.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ test('build', async () => {
3838
// expect(index).toMatch(/<link [^>]+app[^>]+\.css" rel="preload" as="style">/)
3939

4040
// should inject scripts
41-
expect(index).toMatch(/<script src="\/js\/chunk-vendors\.\w{8}\.js">/)
42-
expect(index).toMatch(/<script src="\/js\/app\.\w{8}\.js">/)
41+
expect(index).toMatch(/<script defer="defer" src="\/js\/chunk-vendors\.\w{8}\.js">/)
42+
expect(index).toMatch(/<script defer="defer" src="\/js\/app\.\w{8}\.js">/)
4343
// should inject css
4444
expect(index).toMatch(/<link href="\/css\/app\.\w{8}\.css" rel="stylesheet">/)
4545

packages/@vue/cli-service/__tests__/cors.spec.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ test('build', async () => {
3030
// expect(index).toMatch(/<link [^>]+app[^>]+\.css rel=preload as=style crossorigin>/)
3131

3232
// should apply crossorigin and add integrity to scripts and css
33-
expect(index).toMatch(/<script src="\/js\/chunk-vendors\.\w{8}\.js" crossorigin integrity="sha384-.{64}\s?">/)
34-
expect(index).toMatch(/<script src="\/js\/app\.\w{8}\.js" crossorigin integrity="sha384-.{64}\s?">/)
33+
expect(index).toMatch(/<script defer="defer" src="\/js\/chunk-vendors\.\w{8}\.js" crossorigin integrity="sha384-.{64}\s?">/)
34+
expect(index).toMatch(/<script defer="defer" src="\/js\/app\.\w{8}\.js" crossorigin integrity="sha384-.{64}\s?">/)
3535
expect(index).toMatch(/<link href="\/css\/app\.\w{8}\.css" rel="stylesheet" crossorigin integrity="sha384-.{64}\s?">/)
3636

3737
// verify integrity is correct by actually running it

packages/@vue/cli-service/__tests__/modernMode.spec.js

+6-6
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,16 @@ test('modern mode', async () => {
3232
const index = await project.read('dist/index.html')
3333

3434
// should use <script type="module" crossorigin="use-credentials"> for modern bundle
35-
expect(index).toMatch(/<script src="\/js\/chunk-vendors\.\w{8}\.js" type="module">/)
36-
expect(index).toMatch(/<script src="\/js\/app\.\w{8}\.js" type="module">/)
35+
expect(index).toMatch(/<script defer="defer" src="\/js\/chunk-vendors\.\w{8}\.js" type="module">/)
36+
expect(index).toMatch(/<script defer="defer" src="\/js\/app\.\w{8}\.js" type="module">/)
3737

3838
// should use <link rel="modulepreload" crossorigin="use-credentials"> for modern bundle
3939
// expect(index).toMatch(/<link [^>]*js\/chunk-vendors\.\w{8}\.js" rel="modulepreload" as="script">/)
4040
// expect(index).toMatch(/<link [^>]*js\/app\.\w{8}\.js" rel="modulepreload" as="script">/)
4141

4242
// should use <script nomodule> for legacy bundle
43-
expect(index).toMatch(/<script src="\/js\/chunk-vendors-legacy\.\w{8}\.js" nomodule>/)
44-
expect(index).toMatch(/<script src="\/js\/app-legacy\.\w{8}\.js" nomodule>/)
43+
expect(index).toMatch(/<script defer="defer" src="\/js\/chunk-vendors-legacy\.\w{8}\.js" nomodule>/)
44+
expect(index).toMatch(/<script defer="defer" src="\/js\/app-legacy\.\w{8}\.js" nomodule>/)
4545

4646
// should inject Safari 10 nomodule fix
4747
const { safariFix } = require('../lib/webpack/ModernModePlugin')
@@ -53,8 +53,8 @@ test('modern mode', async () => {
5353
expect(stdout2).toMatch('Build complete.')
5454
const index2 = await project.read('dist/index.html')
5555
// should use <script type="module" crossorigin="use-credentials"> for modern bundle
56-
expect(index2).toMatch(/<script src="\/js\/chunk-vendors\.\w{8}\.js" crossorigin="use-credentials" type="module">/)
57-
expect(index2).toMatch(/<script src="\/js\/app\.\w{8}\.js" crossorigin="use-credentials" type="module">/)
56+
expect(index2).toMatch(/<script defer="defer" src="\/js\/chunk-vendors\.\w{8}\.js" crossorigin="use-credentials" type="module">/)
57+
expect(index2).toMatch(/<script defer="defer" src="\/js\/app\.\w{8}\.js" crossorigin="use-credentials" type="module">/)
5858
// should use <link rel="modulepreload" crossorigin="use-credentials"> for modern bundle
5959
// expect(index2).toMatch(/<link [^>]*js\/chunk-vendors\.\w{8}\.js" rel="modulepreload" as="script" crossorigin="use-credentials">/)
6060
// expect(index2).toMatch(/<link [^>]*js\/app\.\w{8}\.js" rel="modulepreload" as="script" crossorigin="use-credentials">/)

packages/@vue/cli-service/lib/Service.js

+12
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,18 @@ module.exports = class Service {
187187
return idToPlugin(id, resolveModule(id, this.pkgContext))
188188
}
189189
})
190+
191+
// Add the plugin automatically to simplify the webpack-4 tests
192+
// so that a simple Jest alias would suffice, avoid changing every
193+
// preset used in the tests
194+
if (
195+
process.env.VUE_CLI_TEST &&
196+
process.env.VUE_CLI_USE_WEBPACK4 &&
197+
!projectPlugins.some((p) => p.id === '@vue/cli-plugin-webpack-4')
198+
) {
199+
builtInPlugins.push(idToPlugin('@vue/cli-plugin-webpack-4'))
200+
}
201+
190202
plugins = builtInPlugins.concat(projectPlugins)
191203
}
192204

packages/@vue/cli-service/lib/config/app.js

+1
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ module.exports = (api, options) => {
8383

8484
const htmlOptions = {
8585
title: api.service.pkg.name,
86+
scriptLoading: 'defer',
8687
templateParameters: (compilation, assets, assetTags, pluginOptions) => {
8788
// enhance html-webpack-plugin's built in template params
8889
let stats

packages/@vue/cli-service/lib/webpack/ModernModePlugin.js

+14-5
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,12 @@ class ModernModePlugin {
3232
const htmlPath = path.dirname(data.plugin.options.filename)
3333
const tempFilename = path.join(this.targetDir, htmlPath, `legacy-assets-${htmlName}.json`)
3434
await fs.mkdirp(path.dirname(tempFilename))
35-
await fs.writeFile(tempFilename, JSON.stringify(data.bodyTags))
35+
36+
let tags = data.bodyTags
37+
if (data.plugin.options.scriptLoading === 'defer') {
38+
tags = data.headTags
39+
}
40+
await fs.writeFile(tempFilename, JSON.stringify(tags))
3641
cb()
3742
})
3843
})
@@ -42,8 +47,12 @@ class ModernModePlugin {
4247
const ID = `vue-cli-modern-bundle`
4348
compiler.hooks.compilation.tap(ID, compilation => {
4449
HtmlWebpackPlugin.getHooks(compilation).alterAssetTagGroups.tapAsync(ID, async (data, cb) => {
50+
let tags = data.bodyTags
51+
if (data.plugin.options.scriptLoading === 'defer') {
52+
tags = data.headTags
53+
}
4554
// use <script type="module"> for modern assets
46-
data.bodyTags.forEach(tag => {
55+
tags.forEach(tag => {
4756
if (tag.tagName === 'script' && tag.attributes) {
4857
tag.attributes.type = 'module'
4958
}
@@ -70,7 +79,7 @@ class ModernModePlugin {
7079

7180
if (this.unsafeInline) {
7281
// inject inline Safari 10 nomodule fix
73-
data.bodyTags.push({
82+
tags.push({
7483
tagName: 'script',
7584
closeTag: true,
7685
innerHTML: safariFix
@@ -87,7 +96,7 @@ class ModernModePlugin {
8796
return Buffer.byteLength(safariFix)
8897
}
8998
}
90-
data.bodyTags.push({
99+
tags.push({
91100
tagName: 'script',
92101
closeTag: true,
93102
attributes: {
@@ -96,7 +105,7 @@ class ModernModePlugin {
96105
})
97106
}
98107

99-
data.bodyTags.push(...legacyAssets)
108+
tags.push(...legacyAssets)
100109
await fs.remove(tempFilename)
101110
cb()
102111
})

packages/@vue/cli-service/package.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656
"fs-extra": "^9.0.1",
5757
"globby": "^11.0.1",
5858
"hash-sum": "^2.0.0",
59-
"html-webpack-plugin": "^4.5.0",
59+
"html-webpack-plugin": "^5.0.0",
6060
"launch-editor-middleware": "^2.2.1",
6161
"lodash.defaultsdeep": "^4.6.1",
6262
"lodash.mapvalues": "^4.6.0",
@@ -71,8 +71,8 @@
7171
"terser-webpack-plugin": "^4.2.3",
7272
"thread-loader": "^3.0.0",
7373
"url-loader": "^4.1.1",
74-
"vue-loader": "^16.1.0",
75-
"vue-loader-v15": "npm:vue-loader@^15.9.5",
74+
"vue-loader": "^16.1.2",
75+
"vue-loader-v15": "npm:vue-loader@^15.9.6",
7676
"vue-style-loader": "^4.1.2",
7777
"webpack": "^5.4.0",
7878
"webpack-bundle-analyzer": "^4.1.0",

scripts/test.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ if (args.p) {
1010
rawArgs.splice(i, 2)
1111
}
1212

13-
const e2ePathPattern = 'Migrator|Vue3|mochaPlugin|MochaPlugin'
13+
const e2ePathPattern = 'Migrator|Vue3|mochaPlugin|MochaPlugin|cli-plugin-webpack-4'
1414

1515
if (args['e2e-only']) {
1616
regex = e2ePathPattern

yarn.lock

+33-10
Original file line numberDiff line numberDiff line change
@@ -11906,21 +11906,33 @@ html-tags@^3.1.0:
1190611906
resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.1.0.tgz#7b5e6f7e665e9fb41f30007ed9e0d41e97fb2140"
1190711907
integrity sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg==
1190811908

11909-
html-webpack-plugin@^4.5.0:
11910-
version "4.5.0"
11911-
resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-4.5.0.tgz#625097650886b97ea5dae331c320e3238f6c121c"
11912-
integrity sha512-MouoXEYSjTzCrjIxWwg8gxL5fE2X2WZJLmBYXlaJhQUH5K/b5OrqmV7T4dB7iu0xkmJ6JlUuV6fFVtnqbPopZw==
11909+
html-webpack-plugin@^4.5.1:
11910+
version "4.5.1"
11911+
resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-4.5.1.tgz#40aaf1b5cb78f2f23a83333999625c20929cda65"
11912+
integrity sha512-yzK7RQZwv9xB+pcdHNTjcqbaaDZ+5L0zJHXfi89iWIZmb/FtzxhLk0635rmJihcQbs3ZUF27Xp4oWGx6EK56zg==
1191311913
dependencies:
1191411914
"@types/html-minifier-terser" "^5.0.0"
1191511915
"@types/tapable" "^1.0.5"
1191611916
"@types/webpack" "^4.41.8"
1191711917
html-minifier-terser "^5.0.1"
1191811918
loader-utils "^1.2.3"
11919-
lodash "^4.17.15"
11919+
lodash "^4.17.20"
1192011920
pretty-error "^2.1.1"
1192111921
tapable "^1.1.3"
1192211922
util.promisify "1.0.0"
1192311923

11924+
html-webpack-plugin@^5.0.0:
11925+
version "5.0.0"
11926+
resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-5.0.0.tgz#457a9defb33ce368135078b4e0387a27f3fe244d"
11927+
integrity sha512-kxTyb8cyZwEyUqXTgdHRUOF4C7uCrquzw2T+YTudehm/yspodgCkREjdmc4dXI8k2P4NEjqOVbnOOlPZg4TKJA==
11928+
dependencies:
11929+
"@types/html-minifier-terser" "^5.0.0"
11930+
html-minifier-terser "^5.0.1"
11931+
loader-utils "^2.0.0"
11932+
lodash "^4.17.20"
11933+
pretty-error "^2.1.1"
11934+
tapable "^2.0.0"
11935+
1192411936
htmlparser2@^3.3.0:
1192511937
version "3.10.1"
1192611938
resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f"
@@ -21445,7 +21457,18 @@ vue-jest@^3.0.5:
2144521457
tsconfig "^7.0.0"
2144621458
vue-template-es2015-compiler "^1.6.0"
2144721459

21448-
"vue-loader-v15@npm:vue-loader@^15.9.5", vue-loader@^15.7.1:
21460+
"vue-loader-v15@npm:vue-loader@^15.9.6":
21461+
version "15.9.6"
21462+
resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-15.9.6.tgz#f4bb9ae20c3a8370af3ecf09b8126d38ffdb6b8b"
21463+
integrity sha512-j0cqiLzwbeImIC6nVIby2o/ABAWhlppyL/m5oJ67R5MloP0hj/DtFgb0Zmq3J9CG7AJ+AXIvHVnJAPBvrLyuDg==
21464+
dependencies:
21465+
"@vue/component-compiler-utils" "^3.1.0"
21466+
hash-sum "^1.0.2"
21467+
loader-utils "^1.1.0"
21468+
vue-hot-reload-api "^2.3.0"
21469+
vue-style-loader "^4.1.0"
21470+
21471+
vue-loader@^15.7.1:
2144921472
version "15.9.5"
2145021473
resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-15.9.5.tgz#7a960dc420a3439deaacdda038fdcdbf7c432706"
2145121474
integrity sha512-oeMOs2b5o5gRqkxfds10bCx6JeXYTwivRgbb8hzOrcThD2z1+GqEKE3EX9A2SGbsYDf4rXwRg6D5n1w0jO5SwA==
@@ -21456,10 +21479,10 @@ vue-jest@^3.0.5:
2145621479
vue-hot-reload-api "^2.3.0"
2145721480
vue-style-loader "^4.1.0"
2145821481

21459-
vue-loader@^16.1.0:
21460-
version "16.1.1"
21461-
resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-16.1.1.tgz#f5b286d60ac6886684c63a17a184391cc9e0199a"
21462-
integrity sha512-wz/+HFg/3SBayHWAlZXARcnDTl3VOChrfW9YnxvAweiuyKX/7IGx1ad/4yJHmwhgWlOVYMAbTiI7GV8G33PfGQ==
21482+
vue-loader@^16.1.2:
21483+
version "16.1.2"
21484+
resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-16.1.2.tgz#5c03b6c50d2a5f983c7ceba15c50d78ca2b298f4"
21485+
integrity sha512-8QTxh+Fd+HB6fiL52iEVLKqE9N1JSlMXLR92Ijm6g8PZrwIxckgpqjPDWRP5TWxdiPaHR+alUWsnu1ShQOwt+Q==
2146321486
dependencies:
2146421487
chalk "^4.1.0"
2146521488
hash-sum "^2.0.0"

0 commit comments

Comments
 (0)