Skip to content

Commit

Permalink
feat: use html-webpack-plugin v5 by default (#6269)
Browse files Browse the repository at this point in the history
  • Loading branch information
haoqunjiang authored Feb 10, 2021
1 parent f9d53c7 commit 4ce7edd
Show file tree
Hide file tree
Showing 15 changed files with 98 additions and 38 deletions.
2 changes: 1 addition & 1 deletion docs/migrations/migrate-from-v4.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ No longer supports generating project with `node-sass`. It has been [deprecated]

#### Underlying Loaders and Plugins

* `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).
* `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).
* `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).
* `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).
* `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).
Expand Down
5 changes: 5 additions & 0 deletions packages/@vue/cli-plugin-babel/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ module.exports = (api, options) => {
.test(/\.m?jsx?$/)
.exclude
.add(filepath => {
// With data URI support in webpack 5, filepath could be undefined
if (!filepath) {
return true
}

// always transpile js in vue files
if (/\.vue\.jsx?$/.test(filepath)) {
return false
Expand Down
2 changes: 1 addition & 1 deletion packages/@vue/cli-plugin-pwa/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
},
"dependencies": {
"@vue/cli-shared-utils": "^5.0.0-alpha.3",
"html-webpack-plugin": "^4.5.0",
"html-webpack-plugin": "^5.0.0",
"webpack": "^5.10.0",
"workbox-webpack-plugin": "^6.0.2"
},
Expand Down
5 changes: 4 additions & 1 deletion packages/@vue/cli-plugin-webpack-4/generator.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ module.exports = (api) => {
// Yarn and PNPM 5.10+ support this feature
// So we'll try to use that whenever possible
resolutions: {
'@vue/cli-*/webpack': '^4.0.0'
'@vue/cli-*/webpack': '^4.0.0',
'html-webpack-plugin': '^4.5.1'
}
})

// TODO: if uses sass, replace sass-loader@11 with sass-loader@10
}
17 changes: 11 additions & 6 deletions packages/@vue/cli-plugin-webpack-4/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
const path = require('path')
const moduleAlias = require('module-alias')

const htmlWebpackPlugin4Path = path.dirname(require.resolve('html-webpack-plugin/package.json'))
// We have to use module-alias for html-webpack-plguin, as it is required by many other plugins
// as peer dependency for its `getHooks` API.
// Should add the alias as early as possible to avoid problems
// TODO: add debugging log here
moduleAlias.addAlias('html-webpack-plugin', htmlWebpackPlugin4Path)

/** @type {import('@vue/cli-service').ServicePlugin} */
module.exports = () => {
// TODO:
// terser-webpack-plugin v4
// copy-webpack-plugin v6
// html-webpack-plugin v4
// css-minimizer-webpack-plugin v1
module.exports = (api, options) => {
}
2 changes: 2 additions & 0 deletions packages/@vue/cli-plugin-webpack-4/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
"access": "public"
},
"dependencies": {
"html-webpack-plugin": "^4.5.1",
"module-alias": "^2.2.2",
"webpack": "^4.44.2"
},
"peerDependencies": {
Expand Down
4 changes: 2 additions & 2 deletions packages/@vue/cli-service/__tests__/build.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ test('build', async () => {
// expect(index).toMatch(/<link [^>]+app[^>]+\.css" rel="preload" as="style">/)

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

Expand Down
4 changes: 2 additions & 2 deletions packages/@vue/cli-service/__tests__/cors.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ test('build', async () => {
// expect(index).toMatch(/<link [^>]+app[^>]+\.css rel=preload as=style crossorigin>/)

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

// verify integrity is correct by actually running it
Expand Down
12 changes: 6 additions & 6 deletions packages/@vue/cli-service/__tests__/modernMode.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,16 @@ test('modern mode', async () => {
const index = await project.read('dist/index.html')

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

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

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

// should inject Safari 10 nomodule fix
const { safariFix } = require('../lib/webpack/ModernModePlugin')
Expand All @@ -53,8 +53,8 @@ test('modern mode', async () => {
expect(stdout2).toMatch('Build complete.')
const index2 = await project.read('dist/index.html')
// should use <script type="module" crossorigin="use-credentials"> for modern bundle
expect(index2).toMatch(/<script src="\/js\/chunk-vendors\.\w{8}\.js" crossorigin="use-credentials" type="module">/)
expect(index2).toMatch(/<script src="\/js\/app\.\w{8}\.js" crossorigin="use-credentials" type="module">/)
expect(index2).toMatch(/<script defer="defer" src="\/js\/chunk-vendors\.\w{8}\.js" crossorigin="use-credentials" type="module">/)
expect(index2).toMatch(/<script defer="defer" src="\/js\/app\.\w{8}\.js" crossorigin="use-credentials" type="module">/)
// should use <link rel="modulepreload" crossorigin="use-credentials"> for modern bundle
// expect(index2).toMatch(/<link [^>]*js\/chunk-vendors\.\w{8}\.js" rel="modulepreload" as="script" crossorigin="use-credentials">/)
// expect(index2).toMatch(/<link [^>]*js\/app\.\w{8}\.js" rel="modulepreload" as="script" crossorigin="use-credentials">/)
Expand Down
12 changes: 12 additions & 0 deletions packages/@vue/cli-service/lib/Service.js
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,18 @@ module.exports = class Service {
return idToPlugin(id, resolveModule(id, this.pkgContext))
}
})

// Add the plugin automatically to simplify the webpack-4 tests
// so that a simple Jest alias would suffice, avoid changing every
// preset used in the tests
if (
process.env.VUE_CLI_TEST &&
process.env.VUE_CLI_USE_WEBPACK4 &&
!projectPlugins.some((p) => p.id === '@vue/cli-plugin-webpack-4')
) {
builtInPlugins.push(idToPlugin('@vue/cli-plugin-webpack-4'))
}

plugins = builtInPlugins.concat(projectPlugins)
}

Expand Down
1 change: 1 addition & 0 deletions packages/@vue/cli-service/lib/config/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ module.exports = (api, options) => {

const htmlOptions = {
title: api.service.pkg.name,
scriptLoading: 'defer',
templateParameters: (compilation, assets, assetTags, pluginOptions) => {
// enhance html-webpack-plugin's built in template params
let stats
Expand Down
19 changes: 14 additions & 5 deletions packages/@vue/cli-service/lib/webpack/ModernModePlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,12 @@ class ModernModePlugin {
const htmlPath = path.dirname(data.plugin.options.filename)
const tempFilename = path.join(this.targetDir, htmlPath, `legacy-assets-${htmlName}.json`)
await fs.mkdirp(path.dirname(tempFilename))
await fs.writeFile(tempFilename, JSON.stringify(data.bodyTags))

let tags = data.bodyTags
if (data.plugin.options.scriptLoading === 'defer') {
tags = data.headTags
}
await fs.writeFile(tempFilename, JSON.stringify(tags))
cb()
})
})
Expand All @@ -42,8 +47,12 @@ class ModernModePlugin {
const ID = `vue-cli-modern-bundle`
compiler.hooks.compilation.tap(ID, compilation => {
HtmlWebpackPlugin.getHooks(compilation).alterAssetTagGroups.tapAsync(ID, async (data, cb) => {
let tags = data.bodyTags
if (data.plugin.options.scriptLoading === 'defer') {
tags = data.headTags
}
// use <script type="module"> for modern assets
data.bodyTags.forEach(tag => {
tags.forEach(tag => {
if (tag.tagName === 'script' && tag.attributes) {
tag.attributes.type = 'module'
}
Expand All @@ -70,7 +79,7 @@ class ModernModePlugin {

if (this.unsafeInline) {
// inject inline Safari 10 nomodule fix
data.bodyTags.push({
tags.push({
tagName: 'script',
closeTag: true,
innerHTML: safariFix
Expand All @@ -87,7 +96,7 @@ class ModernModePlugin {
return Buffer.byteLength(safariFix)
}
}
data.bodyTags.push({
tags.push({
tagName: 'script',
closeTag: true,
attributes: {
Expand All @@ -96,7 +105,7 @@ class ModernModePlugin {
})
}

data.bodyTags.push(...legacyAssets)
tags.push(...legacyAssets)
await fs.remove(tempFilename)
cb()
})
Expand Down
6 changes: 3 additions & 3 deletions packages/@vue/cli-service/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
"fs-extra": "^9.0.1",
"globby": "^11.0.1",
"hash-sum": "^2.0.0",
"html-webpack-plugin": "^4.5.0",
"html-webpack-plugin": "^5.0.0",
"launch-editor-middleware": "^2.2.1",
"lodash.defaultsdeep": "^4.6.1",
"lodash.mapvalues": "^4.6.0",
Expand All @@ -71,8 +71,8 @@
"terser-webpack-plugin": "^4.2.3",
"thread-loader": "^3.0.0",
"url-loader": "^4.1.1",
"vue-loader": "^16.1.0",
"vue-loader-v15": "npm:vue-loader@^15.9.5",
"vue-loader": "^16.1.2",
"vue-loader-v15": "npm:vue-loader@^15.9.6",
"vue-style-loader": "^4.1.2",
"webpack": "^5.4.0",
"webpack-bundle-analyzer": "^4.1.0",
Expand Down
2 changes: 1 addition & 1 deletion scripts/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ if (args.p) {
rawArgs.splice(i, 2)
}

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

if (args['e2e-only']) {
regex = e2ePathPattern
Expand Down
43 changes: 33 additions & 10 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -11906,21 +11906,33 @@ html-tags@^3.1.0:
resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.1.0.tgz#7b5e6f7e665e9fb41f30007ed9e0d41e97fb2140"
integrity sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg==

html-webpack-plugin@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-4.5.0.tgz#625097650886b97ea5dae331c320e3238f6c121c"
integrity sha512-MouoXEYSjTzCrjIxWwg8gxL5fE2X2WZJLmBYXlaJhQUH5K/b5OrqmV7T4dB7iu0xkmJ6JlUuV6fFVtnqbPopZw==
html-webpack-plugin@^4.5.1:
version "4.5.1"
resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-4.5.1.tgz#40aaf1b5cb78f2f23a83333999625c20929cda65"
integrity sha512-yzK7RQZwv9xB+pcdHNTjcqbaaDZ+5L0zJHXfi89iWIZmb/FtzxhLk0635rmJihcQbs3ZUF27Xp4oWGx6EK56zg==
dependencies:
"@types/html-minifier-terser" "^5.0.0"
"@types/tapable" "^1.0.5"
"@types/webpack" "^4.41.8"
html-minifier-terser "^5.0.1"
loader-utils "^1.2.3"
lodash "^4.17.15"
lodash "^4.17.20"
pretty-error "^2.1.1"
tapable "^1.1.3"
util.promisify "1.0.0"

html-webpack-plugin@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-5.0.0.tgz#457a9defb33ce368135078b4e0387a27f3fe244d"
integrity sha512-kxTyb8cyZwEyUqXTgdHRUOF4C7uCrquzw2T+YTudehm/yspodgCkREjdmc4dXI8k2P4NEjqOVbnOOlPZg4TKJA==
dependencies:
"@types/html-minifier-terser" "^5.0.0"
html-minifier-terser "^5.0.1"
loader-utils "^2.0.0"
lodash "^4.17.20"
pretty-error "^2.1.1"
tapable "^2.0.0"

htmlparser2@^3.3.0:
version "3.10.1"
resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f"
Expand Down Expand Up @@ -21445,7 +21457,18 @@ vue-jest@^3.0.5:
tsconfig "^7.0.0"
vue-template-es2015-compiler "^1.6.0"

"vue-loader-v15@npm:vue-loader@^15.9.5", vue-loader@^15.7.1:
"vue-loader-v15@npm:vue-loader@^15.9.6":
version "15.9.6"
resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-15.9.6.tgz#f4bb9ae20c3a8370af3ecf09b8126d38ffdb6b8b"
integrity sha512-j0cqiLzwbeImIC6nVIby2o/ABAWhlppyL/m5oJ67R5MloP0hj/DtFgb0Zmq3J9CG7AJ+AXIvHVnJAPBvrLyuDg==
dependencies:
"@vue/component-compiler-utils" "^3.1.0"
hash-sum "^1.0.2"
loader-utils "^1.1.0"
vue-hot-reload-api "^2.3.0"
vue-style-loader "^4.1.0"

vue-loader@^15.7.1:
version "15.9.5"
resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-15.9.5.tgz#7a960dc420a3439deaacdda038fdcdbf7c432706"
integrity sha512-oeMOs2b5o5gRqkxfds10bCx6JeXYTwivRgbb8hzOrcThD2z1+GqEKE3EX9A2SGbsYDf4rXwRg6D5n1w0jO5SwA==
Expand All @@ -21456,10 +21479,10 @@ vue-jest@^3.0.5:
vue-hot-reload-api "^2.3.0"
vue-style-loader "^4.1.0"

vue-loader@^16.1.0:
version "16.1.1"
resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-16.1.1.tgz#f5b286d60ac6886684c63a17a184391cc9e0199a"
integrity sha512-wz/+HFg/3SBayHWAlZXARcnDTl3VOChrfW9YnxvAweiuyKX/7IGx1ad/4yJHmwhgWlOVYMAbTiI7GV8G33PfGQ==
vue-loader@^16.1.2:
version "16.1.2"
resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-16.1.2.tgz#5c03b6c50d2a5f983c7ceba15c50d78ca2b298f4"
integrity sha512-8QTxh+Fd+HB6fiL52iEVLKqE9N1JSlMXLR92Ijm6g8PZrwIxckgpqjPDWRP5TWxdiPaHR+alUWsnu1ShQOwt+Q==
dependencies:
chalk "^4.1.0"
hash-sum "^2.0.0"
Expand Down

0 comments on commit 4ce7edd

Please sign in to comment.