Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”.
Hello, I’m Shanyue.
This is my front end engineering knowledge card collection 5/36 published in Denver
In modern front-end development, how to automatically inject packaged JS resources into HTML?
If the resulting main.js is packaged without either code spliting or a hashed path. You can manually control JS resources in index.html.
<body>
<script src="main.js" defer />
</body>
Copy the code
But it often doesn’t:
main.js
That is, we end up generating files with hash values such asmain.8a9b3c.js
.- Because of the need for long-term cache optimization, there is not only one entry file, but also packaged by third-party modules
verdor.js
, again with hash. - Script addresses also need to be injected
publicPath
In the production environment and the test environment, the publicPath is different
So you need a plug-in to do this automatically. In the Webpack world, it’s htML-webpak-plugin, and in the rollup world, it’s @rollup/plugin-html.
The principle of injection is that after the wrapper has generated the entryPoint file resource, it obtains its filename andpublicPath
And inject it into HTML
In the case of the HTml-webpack-plugin, it obtains its packaged resources from processAssets of the compilation processing resources. The pseudo-code is as follows, available in the mini-node:html-webpack-plugin source code and run the sample.
class HtmlWebpackPlugin {
constructor(options) {
this.options = options || {}
}
apply(compiler) {
const webpack = compiler.webpack
compiler.hooks.thisCompilation.tap('HtmlWebpackPlugin'.(compilation) = > {
// Compilation is the most important object in webpack, See document [compilation - object] (https://webpack.js.org/api/compilation-object/#compilation-object-methods)
compilation.hooks.processAssets.tapAsync({
name: 'HtmlWebpackPlugin'.// The time when processAssets processes the resource. This stage is after the resource has been optimized. See the documentation for more stages
// https://webpack.js.org/api/compilation-hooks/#list-of-asset-processing-stages
stage: webpack.Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_INLINE
}, (compilationAssets, callback) = > {
// compilationAssets will get all generated resources such as chunk.js, images, CSS
// Get the webpac.output.publicPath option, (PS: publicPath option may be set by function)
const publicPath = getPublicPath(compilation)
// This example considers only a single entryPoint case
// compilation. Entrypoints can be used to obtain information about imported files
const entryNames = Array.from(compilation.entrypoints.keys())
// entryPoint.getFiles() will fetch all the resources in this entry and guarantee the loading order!! If the runtime - the chunk - > the main - the chunk
const assets = entryNames.map(entryName= > compilation.entrypoints.get(entryName).getFiles()).flat()
const scripts = assets.map(src= > publicPath + src)
const content = html({ title: this.options.title || 'Demo', scripts })
// emitAsset is used to generate resource files, which is also the most important step
compilation.emitAsset('index.html'.new webpack.sources.RawSource(content))
callback()
})
})
}
}
Copy the code