vue3入门49 - Vite 进阶 - 插件开发

115 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第28天,点击查看活动详情

插件开发概述

  • vite插件是受限制的 rollup 插件

命名

  • rollup-plugin-xxx 希望在 vite 和 rollup 中通用
  • vite-plugin-xxx 在 vite 中使用

兼容 rollup 的钩子

服务启动时

  • options
  • buildStart

每个模块

  • resolveId 找到这个文件
  • load 加载源码
  • transform 转换源码

服务器关闭时

  • buildEnd
  • closeBundle

注意

  • modulePased 不会被调用
  • rollup 插件可以在 build 中配置

条件

  • 没有使用 modulePased 钩子
  • 在打包钩子和输出钩子之间没有很强的耦合

vite 钩子

  • config 根据其他配置更新整体 config
  • configResolved 所有插件都执行之后
  • configureServer devServer 中间件
  • transformIndexHtml 入口 html 转换操作
  • handleHotUpdate 处理热更新

Vite 插件的执行时机

  • pre 最快被执行的插件
  • noraml vite 核心插件执行之后,build 插件执行之前
  • post build之后,插件代码构建
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 插件 API 详解

import { Plugin } from 'vite'
export default (enforce?: 'pre' | 'post'): Plugin => {
  return {
    name: 'apiPlugin',
    /**
     *
     * @param userConfig 用户配置的 config
     * @returns 可以异步返回,也可以同步返回
     */
    config(userConfig) {
      // 返回一些配置,和 userConfig 进行 merge
      return new Promise((resolve) => {
        resolve({
          resolve: {
            alias: {
              assets: '/src/asstes',
            },
          },
        })
      })
    },
    /**
     * @param config 最终会被使用的 config
     */
    configResolved(config) {
      // console.log(config.resolve)
    },
    /**
     *
     * @param server 服务实例
     */
    configureServer(server) {
      // console.log(server)
      // 和 express 中间件是一致的
      // 如果不使用 return 返回一个函数,
      // server 中间件会在 vite 中间件之前执行
      // 返回一个函数,会在 vite 之后执行
      return () => {
        server.middlewares.use((req, res, next) => {
          if (req.originalUrl === '/test') {
            res.end('hello Vite Plugin')
          } else {
            next()
          }
        })
      }
    },
    /**
     * 处理 indexHtml 内容
     * @param html index.html 的内容
     */
    transformIndexHtml(html) {
      // console.log(html)
      return html.replace('__TITLE__', '标题')
    },
    /**
     * 处理模块热更新
     * @param ctx
     */
    handleHotUpdate(ctx) {
      // console.log(ctx)
      ctx.server.ws.send({
        type: 'custom',
        event: 'test',
        data: {
          hello: 'hello',
        },
      })
      /*
       * 接收热更新的消息通知
        if (import.meta.hot) {
          import.meta.hot.on('test', (val) => {
            console.log(val)
          })
        }
      */
    },
  }
}