diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index d1ef7ede..c19ee5e4 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -15,8 +15,24 @@ jobs: fail-fast: false matrix: node-version: [6.x, 8.x, 10.x, 12.x, 14.x, 15.x] - html-plugin-version: [3, 4] - webpack-version: [4] + html-plugin-version: [3, 4, 5] + webpack-version: [4, 5] + exclude: + # plugin@5 only supports webpack@5 + - html-plugin-version: 5 + webpack-version: 4 + # plugin@3 only supports webpack@4 + - html-plugin-version: 3 + webpack-version: 5 + # webpack@5 and plugin@5 does not support node 6 or 8 + - node-version: 6.x + webpack-version: 5 + - node-version: 6.x + html-plugin-version: 5 + - node-version: 8.x + webpack-version: 5 + - node-version: 8.x + html-plugin-version: 5 include: - node-version: 10.x install-puppeteer: true diff --git a/package.json b/package.json index b04e20f7..a321c0b4 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,7 @@ "eslint-config-simenb-base": "^15.0.1", "eslint_d": "^7.1.0", "express": "^4.17.1", - "html-webpack-plugin": "^4.0.0-0", + "html-webpack-plugin": "^4.0.0", "husky": "^1.0.1", "jest": "^24.0.0", "jest-watch-typeahead": "^0.2.0", @@ -67,8 +67,8 @@ "webpack-cli": "^3.1.0" }, "peerDependencies": { - "html-webpack-plugin": "^3.0.4 || ^4.0.0-0", - "webpack": "^4.0.0" + "html-webpack-plugin": "^3.0.4 || ^4.0.0-0 || ^5.0.0", + "webpack": "^4.0.0 || ^5.0.0" }, "engines": { "node": ">=6" diff --git a/src/index.js b/src/index.js index 1680e230..953fa89b 100644 --- a/src/index.js +++ b/src/index.js @@ -3,13 +3,41 @@ import pEachSeries from 'p-each-series'; import micromatch from 'micromatch'; import crypto from 'crypto'; import globby from 'globby'; +import path from 'path'; +import webpack from 'webpack'; import { ensureTrailingSlash, + fsReadFileAsync, handleUrl, resolveOutput, resolvePublicPath, } from './utils'; +/* istanbul ignore next: webpack 5 not in unit test mocks */ +/** + * Pushes the content of the given filename to the compilation assets + * @param {string} filename + * @param {WebpackCompilation} compilation + * @returns {Promise} file basename + */ +function addFileToAssetsWebpack5(filename, compilation) { + const resolvedFilename = path.resolve(compilation.compiler.context, filename); + + return fsReadFileAsync(resolvedFilename) + .then(source => new webpack.sources.RawSource(source, true)) + .catch(() => + Promise.reject( + new Error(`HtmlWebpackPlugin: could not load file ${resolvedFilename}`), + ), + ) + .then(rawSource => { + const basename = path.basename(resolvedFilename); + compilation.fileDependencies.add(resolvedFilename); + compilation.emitAsset(basename, rawSource); + return basename; + }); +} + export default class AddAssetHtmlPlugin { constructor(assets = []) { this.assets = Array.isArray(assets) ? assets.slice().reverse() : [assets]; @@ -22,7 +50,7 @@ export default class AddAssetHtmlPlugin { let beforeGenerationHook; let alterAssetTagsHook; - if (HtmlWebpackPlugin.version === 4) { + if (HtmlWebpackPlugin.version >= 4) { const hooks = HtmlWebpackPlugin.getHooks(compilation); beforeGenerationHook = hooks.beforeAssetTagGeneration; @@ -105,10 +133,11 @@ export default class AddAssetHtmlPlugin { } } - const addedFilename = await htmlPluginData.plugin.addFileToAssets( - filepath, - compilation, - ); + const addFileToAssets = + htmlPluginData.plugin.addFileToAssets || + /* istanbul ignore next: webpack 5 not in unit test mocks */ addFileToAssetsWebpack5; + + const addedFilename = await addFileToAssets(filepath, compilation); let suffix = ''; if (hash) { @@ -133,7 +162,7 @@ export default class AddAssetHtmlPlugin { const relatedFiles = await globby(`${filepath}.*`); await Promise.all( relatedFiles.sort().map(async relatedFile => { - const addedMapFilename = await htmlPluginData.plugin.addFileToAssets( + const addedMapFilename = await addFileToAssets( relatedFile, compilation, ); diff --git a/src/utils.js b/src/utils.js index 8d01ff00..ad949e85 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,5 +1,6 @@ import path from 'path'; import globby from 'globby'; +import fs from 'fs'; export function ensureTrailingSlash(string) { if (string.length && string.substr(-1, 1) !== '/') { @@ -30,6 +31,19 @@ export function resolveOutput(compilation, addedFilename, outputPath) { } } +/* istanbul ignore next: webpack 5 not in unit test mocks */ +export function fsReadFileAsync(filePath) { + return new Promise((resolve, reject) => { + fs.readFile(filePath, (err, res) => { + if (err) { + reject(err); + } else { + resolve(res); + } + }); + }); +} + /** * handle globby filepath and return an array with all matched assets. * diff --git a/yarn.lock b/yarn.lock index b8acb9cc..ed87432c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3869,7 +3869,7 @@ html-minifier-terser@^5.0.1: relateurl "^0.2.7" terser "^4.6.3" -html-webpack-plugin@^4.0.0-0: +html-webpack-plugin@^4.0.0: version "4.5.2" resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-4.5.2.tgz#76fc83fa1a0f12dd5f7da0404a54e2699666bc12" integrity sha512-q5oYdzjKUIPQVjOosjgvCHQOv9Ett9CYYHlgvJeXG0qQvdSojnBq4vAdQBwn1+yGveAwHCoe/rMR86ozX3+c2A==