一、Vite 高级应用的 rollup 配置文件、rollup 插件、vite 插件、vite 钩子及执行时机和 vite 的 HMR
Vite 是基于 rollup 和 esbuild 实现的。Rollup 是开源类库优先的选择,以 ESM 标准为目标的构建工具,打包基于 tree shaking 功能。通过 npm i -g rollup 命令安装 rollup ,rollup.config.js ,代码如下:
import json from '@rollup/plugin-json';
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import terser from 'rollup-plugin-terser';
const mode = process.env.MODE;
const isLocal = mode === 'local';
const entry = 'index.js';
export default [
{
input: entry,
externals: ['react'],
plugins: [resolve(), commonjs(), json()],
output: {
file: 'dist.js',
format: isLocal ? 'es' : 'umd',
name: 'Index',
plugins: [terser()],
banner: '/** Hello This is Banner **/',
},
},
{
input: entry,
external: ['react'],
plugins: [resolve(), commonjs(), json()],
output: {
file: 'dist/index.es.js',
format: 'es',
},
}
];
Rollup 插件的流程,Input -> rollup main -> Plugin1 -> Plugin2 -> more plugins -> emit file -> finish 。Rollup 插件具备 hook 功能,对应到不同的运行节点,它会主动勾住在插件这块设置的内容,然后去调用它,得到它。Rollup 的通用配置有 include 和 exclude ,三个官方插件是 alias、babel、replace 。大部分中的 rollup 插件是可以直接在 vite 中使用的。Rollup 中的常用插件,Replace、Node resolve、eslint、image、strip、wasm、Commonjs、Babel、TypeScript 。Vite 插件是受限制的 rollup 插件,它的命名规范是 rollup-plugin-xxx ,或者是 vite-plugin-xxx 。Vite 兼容的钩子,服务启动时的 options 和 buildStart 钩子,只会调用一次。对应到每个模块,会兼容 resolveId、load 和 transform 。服务器关闭时,会调用 buildEnd 和 closeBundle 。同时,moduleParsed 不会被调用。Rollup 插件可以在 build 中配置,如果需要兼容 vite 插件,需要符合的条件,如下所示:
- 没有使用
moduleParsed 钩子 - 它在打包钩子和输出钩子之间没有很强的耦合
Vite 也有独有的钩子,config、configResolved、configureServer、transformIndexHtml、handleHotUpdate 。在 vite 插件中的执行时机,pre、normal 和 post ,代码如下:
export default (enforce?: 'pre' | 'post') => {
return {
name: 'test',
enforce,
buildStart() {
console.log('buildStart', enforce)
},
resolveId() {
console.log('resolveId', enforce)
},
load() {
console.log('load', enforce)
}
}
}
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx';
import testPlugin from './plugins/test-plugin';
export default defineConfig({
plugins: [vue(), vueJsx(), testPlugin('post'), testPlugin(), testPlugin('pre')],
resolve: {
alias: {
"@styles": "/src/styles",
}
}
})
Vite 插件 API ,代码如下:
import { Plugin } from 'vite';
export default (enforce?: 'pre' | 'post'): Plugin => {
return {
name: 'test',
config(userConfig) {
return new Promise(resolve => {
resolve({
resolve: {
alias: {
'@aaa': enforce ? enforce : '/src/styles'
}
}
})
})
},
configResolved(config) {
console.log(config)
},
configureServer(server) {
return () => {
server.middlewares.use((req, res, next) => {
if (req.url === '/test') {
res.end('Hello vite plugin')
} else {
next()
}
})
}
},
transformIndexHtml(html) {
return html.replace('<div id="app"></div>')
},
handleHotUpdate(ctx) {
ctx.server.ws.send({
type: 'custom',
event: 'test',
data: {
hello: 'world'
}
})
}
}
}
if (import.meta.hot) {
import.meta.hot.on('test', val => {
console.log(val)
})
}
Vite 中的 HMR ,代码如下:
import './style.css'
export function render() {
document.querySelector('#app').innerHTML = `
<h1>Hello Vite!</h1>
<a href="https://vitejs.dev/guide/features.html" target="_blank">Documentation</a>
`
}
render()
let index = import.meta.hot.data.index || 0;
if (import.meta.hot) {
import.meta.hot.accept(['./renderA'], ([newA]) => {
if (newA.index > 5) {
import.meta.hot.invalidate();
} else newA.render();
});
}
|