Skip to content

Commit 42c0f7d

Browse files
feat: support webpack5 and html-webpack-plugin5 (#14)
Co-authored-by: Haoqun Jiang <[email protected]>
1 parent 0aa9630 commit 42c0f7d

File tree

14 files changed

+3605
-3917
lines changed

14 files changed

+3605
-3917
lines changed

.eslintignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
build/
22
demo/
33
test/fixtures/
4-
test/*/node_modules/
4+
test/**/node_modules/

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22
.nyc_output/
33
build/
44
node_modules/
5-
5+
test/e2e/webpack4/src/
66
# Files
77
npm-debug.log

package.json

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,9 @@
2424
"node": ">=6.0.0"
2525
},
2626
"scripts": {
27+
"init-project": "yarn && cd test\\e2e\\webpack4 && yarn",
2728
"lint": "eslint --format=codeframe .",
28-
"test": "npm run lint && jasmine test/unit/* test/e2e/index.js",
29+
"test": "npm run lint && node test/copySrc.js && jasmine test/unit/* test/e2e/*/index.js",
2930
"coverage": "nyc npm run test",
3031
"prepublishOnly": "npm run test"
3132
},
@@ -36,16 +37,17 @@
3637
"devDependencies": {
3738
"eslint": "^4.19.1",
3839
"eslint-plugin-vue-libs": "^2.1.0",
39-
"html-webpack-plugin": "^3.2.0",
40+
"fs-extra": "^9.1.0",
41+
"html-webpack-plugin": "^5.0.0",
4042
"jasmine": "^3.1.0",
4143
"jsdom": "^11.9.0",
4244
"memory-fs": "^0.4.1",
4345
"nyc": "^11.7.1",
4446
"rimraf": "^2.6.2",
45-
"webpack": "^4.0.0"
47+
"webpack": "^5.20.0"
4648
},
4749
"peerDependencies": {
48-
"html-webpack-plugin": ">=2.26.0",
49-
"webpack": ">=4.0.0"
50+
"html-webpack-plugin": ">=5.0.0 || ^4.5.1",
51+
"webpack": ">=5.20.0 || ^4.1.0"
5052
}
5153
}

src/index.js

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* See the License for the specific language governing permissions and
1515
* limitations under the License.
1616
*/
17-
17+
const HtmlWebpackPlugin = require('html-webpack-plugin')
1818
const defaultOptions = require('./lib/default-options')
1919
const determineAsValue = require('./lib/determine-as-value')
2020
const doesChunkBelongToHTML = require('./lib/does-chunk-belong-to-html')
@@ -23,6 +23,7 @@ const extractChunks = require('./lib/extract-chunks')
2323
class PreloadPlugin {
2424
constructor (options) {
2525
this.options = Object.assign({}, defaultOptions, options)
26+
this.webpackMajorVersion = 4
2627
}
2728

2829
generateLinks (compilation, htmlPluginData) {
@@ -33,18 +34,23 @@ class PreloadPlugin {
3334
})
3435

3536
const htmlChunks = options.include === 'allAssets'
36-
// Handle all chunks.
37+
// Handle all chunks.
3738
? extractedChunks
38-
// Only handle chunks imported by this HtmlWebpackPlugin.
39+
// Only handle chunks imported by this HtmlWebpackPlugin.
3940
: extractedChunks.filter((chunk) => doesChunkBelongToHTML({
4041
chunk,
4142
compilation,
42-
htmlAssetsChunks: Object.values(htmlPluginData.assets.chunks)
43+
htmlPluginData,
44+
pluginOptions: options
4345
}))
4446

4547
// Flatten the list of files.
4648
const allFiles = htmlChunks.reduce((accumulated, chunk) => {
47-
return accumulated.concat(chunk.files)
49+
return accumulated.concat([
50+
...chunk.files,
51+
// sourcemap files are inside auxiliaryFiles in webpack5
52+
...chunk.auxiliaryFiles || []
53+
])
4854
}, [])
4955
const uniqueFiles = new Set(allFiles)
5056
const filteredFiles = [...uniqueFiles].filter(file => {
@@ -62,7 +68,13 @@ class PreloadPlugin {
6268
const sortedFilteredFiles = filteredFiles.sort()
6369

6470
const links = []
65-
const publicPath = compilation.outputOptions.publicPath || ''
71+
const webpackPublicPath = compilation.outputOptions.publicPath
72+
73+
// webpack 5 set publicPath default value 'auto'
74+
const publicPath = this.webpackMajorVersion >= 5
75+
? webpackPublicPath.trim() !== '' && webpackPublicPath !== 'auto'
76+
? webpackPublicPath : ''
77+
: webpackPublicPath || ''
6678
for (const file of sortedFilteredFiles) {
6779
const href = `${publicPath}${file}`
6880

@@ -99,6 +111,11 @@ class PreloadPlugin {
99111
}
100112

101113
apply (compiler) {
114+
// for webpack5+, we can get webpack version from `compiler.webpack`
115+
if (compiler.webpack) {
116+
this.webpackMajorVersion = compiler.webpack.version.split('.')[0]
117+
}
118+
102119
const skip = data => {
103120
const htmlFilename = data.plugin.options.filename
104121
const exclude = this.options.excludeHtmlNames
@@ -112,26 +129,28 @@ class PreloadPlugin {
112129
compiler.hooks.compilation.tap(
113130
this.constructor.name,
114131
compilation => {
115-
compilation.hooks.htmlWebpackPluginBeforeHtmlProcessing.tap(
132+
HtmlWebpackPlugin.getHooks(compilation).beforeAssetTagGeneration.tapAsync(
116133
this.constructor.name,
117-
(htmlPluginData) => {
134+
(htmlPluginData, callback) => {
118135
if (skip(htmlPluginData)) {
136+
callback()
119137
return
120138
}
121139
this.generateLinks(compilation, htmlPluginData)
140+
callback()
122141
}
123142
)
124143

125-
compilation.hooks.htmlWebpackPluginAlterAssetTags.tap(
144+
HtmlWebpackPlugin.getHooks(compilation).alterAssetTags.tap(
126145
this.constructor.name,
127146
(htmlPluginData) => {
128147
if (skip(htmlPluginData)) {
129148
return
130149
}
131150
if (this.resourceHints) {
132-
htmlPluginData.head = [
151+
htmlPluginData.assetTags.styles = [
133152
...this.resourceHints,
134-
...htmlPluginData.head
153+
...htmlPluginData.assetTags.styles
135154
]
136155
}
137156
return htmlPluginData

src/lib/does-chunk-belong-to-html.js

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,43 @@
1414
* See the License for the specific language governing permissions and
1515
* limitations under the License.
1616
*/
17+
const EntryPoint = require('webpack/lib/Entrypoint')
1718

18-
module.exports = function doesChunkBelongToHtml ({ chunk, htmlAssetsChunks, compilation }) {
19-
// Get all the hashes of the HTML assets.
20-
const rootHashes = Object.values(htmlAssetsChunks).map(({ hash }) => hash)
21-
// Get a list of chunk groups that contain one of those hashes.
22-
const rootChunkGroups = compilation.chunkGroups.filter((chunkGroup) => {
23-
return chunkGroup.chunks.filter((chunk) => rootHashes.includes(chunk.renderedHash))
24-
})
25-
// Get an id for each of those chunk groups.
26-
const rootChunkGroupsIds = new Set(rootChunkGroups.map(({ id }) => id))
27-
// Return true iff the chunk we're passed belongs to a group whose id is in
28-
// the list of root chunk groups.
29-
return Array.from(chunk.groupsIterable).some(({ id }) => rootChunkGroupsIds.has(id))
19+
module.exports = function doesChunkBelongToHtml ({
20+
chunk,
21+
compilation,
22+
htmlPluginData,
23+
pluginOptions
24+
}) {
25+
const chunkName = recursiveChunkEntryName(chunk)
26+
const options = htmlPluginData.plugin.options
27+
return isChunksFiltered(chunkName, options.chunks, options.excludeChunks)
28+
}
29+
30+
// modify from html-webpack-plugin/index.js `filterChunks`
31+
function isChunksFiltered (chunkName, includedChunks, excludedChunks) {
32+
// Skip if the chunks should be filtered and the given chunk was not added explicity
33+
if (Array.isArray(includedChunks) && includedChunks.indexOf(chunkName) === -1) {
34+
return false
35+
}
36+
// Skip if the chunks should be filtered and the given chunk was excluded explicity
37+
if (Array.isArray(excludedChunks) && excludedChunks.indexOf(chunkName) !== -1) {
38+
return false
39+
}
40+
// Add otherwise
41+
return true
42+
}
43+
44+
function recursiveChunkEntryName (chunk) {
45+
const [chunkGroup] = chunk.groupsIterable
46+
return _recursiveChunkGroup(chunkGroup)
47+
}
48+
49+
function _recursiveChunkGroup (chunkGroup) {
50+
if (chunkGroup instanceof EntryPoint) {
51+
return chunkGroup.name
52+
} else {
53+
const [chunkParent] = chunkGroup.getParents()
54+
return _recursiveChunkGroup(chunkParent)
55+
}
3056
}

src/lib/extract-chunks.js

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ function extractChunks ({ compilation, optionsInclude }) {
6464
}
6565
}
6666

67-
let chunks = compilation.chunks
67+
let chunks = [...compilation.chunks]
6868

6969
if (Array.isArray(includeChunks)) {
7070
chunks = chunks.filter((chunk) => {
@@ -99,7 +99,18 @@ function extractChunks ({ compilation, optionsInclude }) {
9999
if (includeType === 'allAssets') {
100100
// Every asset, regardless of which chunk it's in.
101101
// Wrap it in a single, "psuedo-chunk" return value.
102-
return [{ files: Object.keys(compilation.assets) }]
102+
// Note: webpack5 will extract license default, we do not need to preload them
103+
const licenseAssets = [...compilation.assetsInfo.values()]
104+
.map((info) => {
105+
if (info.related && info.related.license) {
106+
return info.related.license
107+
}
108+
return false
109+
}).filter(Boolean)
110+
return [{
111+
files: Object.keys(compilation.assets)
112+
.filter((t) => !licenseAssets.includes(t))
113+
}]
103114
}
104115

105116
return chunks

test/copySrc.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
const fs = require('fs-extra')
2+
const path = require('path')
3+
4+
const srcPath = path.resolve(__dirname, '../src')
5+
const distSrcPath = path.resolve(__dirname, 'e2e/webpack4/src')
6+
7+
fs.copySync(srcPath, distSrcPath)

test/e2e/index.js renamed to test/e2e/webpack4/index.js

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,17 @@
1414
* See the License for the specific language governing permissions and
1515
* limitations under the License.
1616
*/
17-
1817
const webpack = require('webpack')
1918
const HtmlWebpackPlugin = require('html-webpack-plugin')
2019

21-
const testSpec = require('../spec')
20+
const PreloadPlugin = require('./src/index')
21+
const testSpec = require('../../spec')
2222

2323
const descriptionPrefix = '[webpack 4]'
24-
testSpec({ webpack, HtmlWebpackPlugin, descriptionPrefix })
24+
25+
testSpec({
26+
webpack,
27+
HtmlWebpackPlugin,
28+
PreloadPlugin,
29+
descriptionPrefix
30+
})

test/e2e/package.json renamed to test/e2e/webpack4/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"author": "",
77
"license": "Apache-2.0",
88
"devDependencies": {
9-
"html-webpack-plugin": "^3.2.0",
9+
"html-webpack-plugin": "^4.5.1",
1010
"webpack": "^4.1.0"
1111
}
1212
}

0 commit comments

Comments
 (0)