preface
In the next generation of packaging tools, ESBuild, I show you what an “esbuild” is and how to use it to implement a bundle packaging. Today, on this special day (1024), I carried out the core logic of “Vite” package implementation, respectively for illustration and code analysis, with only one goal:
Quick reading of “Vite” packing process in 5 minutes!
(Beginning of the text ~)
1 What happened to the NPM Run vite build process?
When we need to package a “Vite” based project, we need to run the NPM run vite build command. In fact, it corresponds to the runBuild method in the source code:
// vite/src/node/cli.ts
async function runBuild(options: UserConfig) {
try {
await require('./build').build(options)
process.exit(0)
} catch (err) { console.error(chalk.red(`[vite] Build errored out.`)) console.error(err) process.exit(1) } } Copy the code
As you can see, here we call the build() method in./build/index.ts to do the packing:
// vite/src/node/build/index.ts
async function build(options: BuildConfig) :Promise<Result> {
.}
Copy the code
And in conclusion,build()
The implementation of the method would look like this (sequence diagram) :
2. Analyze the implementation process of build() method line by line
Here, we break down the implementation details of the build() method line by line from a code perspective:
1. Remove the original outDir directory (dist by default).
await fs.emptyDir(outDir)
Copy the code
BuildHtmlPlugin/index.html/buildHtmlPlugin/index.html/HtmlWebpackPlugin/Webpack/HtmlWebpackPlugin/index.html
const { htmlPlugin, renderIndex } = await createBuildHtmlPlugin(
root,
indexPath,
publicBasePath,
assetsDir,
assetsInlineLimit, resolver, shouldPreload ) Copy the code
3. Create baseRollupPlugin, which returns an array of plugins, including initialization of the default plugin and user-defined plugins, such as buildResolvePlugin, esBuildPlugin, vuePlugin, and so on.
const basePlugins = await createBaseRollupPlugins(root, resolver, options)
Copy the code
The plugins here are actually plugins for the rollupInputOptions option in Rollup. So, if you need a custom plugin to implement some functionality, you can refer to the “Rollup” website.
Env, VITE_ will be exposed as import.meta.env.
Object.keys(env).forEach((key) = > {
if (key.startsWith(`VITE_`)) {
userEnvReplacements[`import.meta.env.${key}`] = JSON.stringify(env[key])
userClientEnv[key] = env[key]
}
}) Copy the code
5. “vite” uses “Rollup” as a “Node”, so rollup.rollup() is called to generate the bundle. Also, the baseRollupPlugin, buildHtmlPlugin, and some basic packaging options created above are applied.
const rollup = require('rollup').rollup as typeof Rollup
const bundle = awaitrollup({... })Copy the code
6. Call bundle.generate to generate output (object), which contains the contents of each chunk, such as file name and file content. Finally, the whole packaging process is completed by traversing the output and calling the FS module to generate the corresponding chunk file.
const { output } = await bundle.generate({
format: 'es'. sourcemap,
entryFileNames: `[name].[hash].js`. chunkFileNames: `[name].[hash].js`.. rollupOutputOptions}) if (write) { const cwd = process.cwd() const writeFile = async ( filepath: string, content: string | Uint8Array. type: WriteType ) = > {. } await fs.ensureDir(outDir) for (const chunk of output) { if (chunk.type === 'chunk') { // write chunk const filepath = path.join(resolvedAssetsPath, chunk.fileName) let code = chunk.code if (chunk.map) { code += `\n//# sourceMappingURL=${path.basename(filepath)}.map` } await writeFile(filepath, code, WriteType.JS) if (chunk.map) { await writeFile( filepath + '.map'. chunk.map.toString(), WriteType.SOURCE_MAP ) } } else if (emitAssets) { if(! chunk.source)continue // write asset const filepath = path.join(resolvedAssetsPath, chunk.fileName) await writeFile( filepath, chunk.source, chunk.fileName.endsWith('.css')? WriteType.CSS : WriteType.ASSET ) } } if (indexHtml && emitIndex) { await writeFile( path.join(outDir, 'index.html'), indexHtml, WriteType.HTML ) } Copy the code
❝
It should be noted that we did not analyze the packaging logic corresponding to SSR here, so students who are interested can know by themselves.
❞
Write in the last
The core of the “vite” packaging implementation is the build() method, and through a brief analysis of the process, I think you should build a basic understanding of the “Vite” packaging implementation. You will also know a thing or two about customizing plugins, because they are really Rollup plugins. Finally, if there is any improper expression in the article, welcome to Issue ~
Review previous articles
The next generation of packaging tools, esbuild
Deep reading Vue3 source | component creation process
What depth interpretation Vue3 source | built-in component teleport “lot”?
❤️ Love triple punch
Through reading, if you think you have something to gain, you can love the triple punch!!
❝
I am Wu Liu, like innovation, tamping source Code, focus on Vue3 source Code, Vite source Code, front-end engineering and other technical fields to share, welcome to follow my wechat public number: Code Center.
❞