您的当前位置:首页正文

Vite 基础之 Vite 高级应用的 rollup 配置文件、rollup 插件、vite 插件、vite 钩子及执行时机和 vite 的 HMR

2024-11-11 来源:个人技术集锦
一、Vite 高级应用的 rollup 配置文件、rollup 插件、vite 插件、vite 钩子及执行时机和 vite 的 HMR
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',
    },
  }
];
  1. Rollup 插件的流程,Input -> rollup main -> Plugin1 -> Plugin2 -> more plugins -> emit file -> finishRollup 插件具备 hook 功能,对应到不同的运行节点,它会主动勾住在插件这块设置的内容,然后去调用它,得到它。Rollup 的通用配置有 includeexclude,三个官方插件是 alias、babel、replace。大部分中的 rollup 插件是可以直接在 vite 中使用的。Rollup 中的常用插件,Replace、Node resolve、eslint、image、strip、wasm、Commonjs、Babel、TypeScript
  2. Vite 插件是受限制的 rollup 插件,它的命名规范是 rollup-plugin-xxx,或者是 vite-plugin-xxxVite 兼容的钩子,服务启动时的 optionsbuildStart 钩子,只会调用一次。对应到每个模块,会兼容 resolveId、loadtransform。服务器关闭时,会调用 buildEndcloseBundle。同时,moduleParsed 不会被调用。Rollup 插件可以在 build 中配置,如果需要兼容 vite 插件,需要符合的条件,如下所示:
  • 没有使用 moduleParsed 钩子
  • 它在打包钩子和输出钩子之间没有很强的耦合
  1. Vite 也有独有的钩子,config、configResolved、configureServer、transformIndexHtml、handleHotUpdate。在 vite 插件中的执行时机,pre、normalpost,代码如下:
  • test-plugin.js
export default (enforce?: 'pre' | 'post') => {
  return {
    name: 'test',
    enforce,
    buildStart() {
      console.log('buildStart', enforce)
    },
    resolveId() {
      console.log('resolveId', enforce)
    },
    load() {
      console.log('load', enforce)
    }
  }
}
  • vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx';
import testPlugin from './plugins/test-plugin';

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue(), vueJsx(), testPlugin('post'), testPlugin(), testPlugin('pre')],
  resolve: {
    alias: {
      "@styles": "/src/styles",
    }
  }
})
  1. Vite 插件 API,代码如下:
  • test-plugin.js
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'
        }
      })
    }
  }
}
  • App.jsx,核心如下:
if (import.meta.hot) {
  import.meta.hot.on('test', val => {
    console.log(val)
  })
}
  1. 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 = 0;
// const timer = setInterval(() => {
//   console.log(index++);
// }, 1000);
let index = import.meta.hot.data.index || 0;

if (import.meta.hot) {
  // import.meta.hot.accept((newModule) => {
  //   newModule.render();
  // });
  import.meta.hot.accept(['./renderA'], ([newA]) => {
    // newA.render();
    if (newA.index > 5) {
      import.meta.hot.invalidate();
    } else newA.render();
  });
  // import.meta.hot.data.index = index;
  // import.meta.hot.dispose(() => {
  //   if (timer) clearInterval(timer);
  // });
}
显示全文