手撸vite插件,就问你来不来

1,439 阅读4分钟

「这是我参与11月更文挑战的第6天,活动详情查看:2021最后一次更文挑战

hello 大家好,🙎🏻‍♀️🙋🏻‍♀️🙆🏻‍♀️

我是一个热爱知识传递,正在学习写作的作者,ClyingDeng 凳凳!

vite工作机制

用户向vite请求资源时,vite内部启了一个开发服务器vite devServer,在这个服务器内部有个工作机制,相当于一个流水线(插件)。插件又分为系统插件(vue)和用户插件。用户请求过来必定经过所有的插件,去处理一下。这就有点向过滤器、中间件。将请求所需的资源进行处理,处理完成之后把转换的结果返回给用户,得到用户想要的东西。

image.png

vite特点:请求一个页面,显示的就是这个页面的内容,无需加载和页面无关的东西。这就意味着,以后的项目不管多大,它的加载速度都是一样的。

插件的形式可以是对象也可以是一个函数:包含插件名称、相关钩子函数(在vite工作的时间节点去执行)

插件钩子

通用钩子

服务器启动时被调用:

在每个传入模块请求时被调用:

  • resolveId 创建自定义确认函数,常用于定位第三方依赖
  • load 创建自定义加载函数,用于返回自定内容
  • transform 转换,将load进来的代码块进一步加工处理

在服务器关闭时被调用:

vite为了性能会避免完整的AST解析。所以在开发中不存在moduleParsed

vite独有钩子

config:在被解析之前修改 Vite 配置

configResolved:在解析 Vite 配置后调用,配置确认

configureServer:配置开发服务器的钩子(可添加自定义中间件)

transformIndexHtml:转换 宿主页面index.html 的专用钩子

handleHotUpdate:执行自定义 HMR 更新处理

初始化插件流程

1、初始化插件:

创建vite-plugin-example文件(自己定义的vite插件)

resolveId钩子用于接管第三方插件,通过该钩子我们可以很快判定该第三方插件是否是我们需要处理的。如果是则接管,跟着顺序,我们可以在load钩子中进行自定义我们自己的插件。

export default function (options) {
  return {
    name: 'dy-i18n',
    resolveId(source) {
      // 是否处理当前的请求  在main中导入的插件名称
      if (source === 'dy-i18n') {
        return source // 表示接管
      }
      return null
    },
    load(id) {
      console.log('id', id)
      // 返回加载的东西
      return 'export default "this is virtaul"'
    },
  }
}

2、配置执行插件

在vite.config.js文件中,执行相关插件函数

import i18n from './plugins/vite-plugin-example'
export default defineConfig({
    // 执行函数i18n
  plugins: [vue(), i18n()],
})

3、在入口文件中引入

import dyI18n from 'dy-i18n'
// 使用插件

i18n插件

初始化项目

使用vite创建一个项目,然后运行该项目。在控制台可以看出文件的按需加载。 1637378710134.png

在解析app文件的后面携带的一串字符:

?:后面说明该文件的sfc文件,

type:解析的模块类型是style样式文件,

index:后面接的是序号,解析的是当前类型的第一个样式

lang.css:解析的该语言是css同理:lang.i18n语言类型就是i18n

写入i18n自定义块

在此,我们写入的i18n插件是去解析自定义模块,将用户需要的代码段通过插件返回给用户。

<i18n>
{
  "en": {
    "language": "Language",
    "hello": "hello, world!"
  },
  "zh": {
    "language": "语言",
    "hello": "你好,世界!"
  }
}
</i18n>

写入的时候可以发现,控制台报错。无法识别我们自定义的代码块。

1637383347446.png

这就需要我们去编写处理该自定义模块的插件,返回所需要的东西给用户。

创建插件文件

接下来就是我们需要做的工作,拿到代码块进行转换处理。

新建插件文件vite-plugin-i18n.js。

export default {
  // code是块的内容
  // id是请求的url
  transform(code, id) {
    // i18n信息写入组件配置
    // 接收vue文件,类型是i18n
    if (!/vue&type=i18n/.test(id)) {
      return;
    }
    // 匹配成功  导出函数(工厂函数) 给组件加上i18n配置选项内容为块的内容
    return `export default Comp => {
      Comp.i18n = ${code}
    }`;
  },
};

请求经过i18n插件,返回插件处理好的资源。 此时,我们可以在控制台中看到,i18自定义块已经经过插件处理,给组件上添加了i18n属性。

1637384683521.png

语言选择器

在vue文件中,编写语言选择的静态页面:

<template>
  <label>{{ t('language') }}</label>
  <select v-model="locale">
    <option value="en">en</option>
    <option value="zh">zh</option>
  </select>
  <p>{{ t('hello') }}</p>
</template>

使用插件

在script中编写逻辑,获取i18n组件实例中的代码块,编写t函数,返回相对应语言的字段属性值。根据locale判断是什么语言,根据传入的关键值属性获取对应的语言值。

const ins = getCurrentInstance()
function useI18n(){
    const locale = ref('zh')
    const i18n = ins.type.i18n
    const t = msg => computed(()=> i18[locale.value][msg]).value
    return {locale,t}
}
const {locale,t} = useI18n()

可以看到效果是这样的:

39vm2-kpnq6.gif

完美实现,此处应该有掌声!🎉🎉🎉

感兴趣的朋友可以关注 vite系列专栏或者点击关注作者哦(●'◡'●)!。 如果不足,请多指教。