从0开始写一个简单的vite hmr 插件( 二 )


文章插图
那么说到底是怎么实现的呢?
答:通过注入的方法 。

从0开始写一个简单的vite hmr 插件

文章插图
在浏览器加载之前,vite先帮你把各种import模块全部转换好,转换为如上的形式,那你说这都定义成变量了,浏览器肯定认啊,对吧!
那你可能会问我还是不明白,到底怎么转换的,其实就是通过transform的返回值来解析转换的 。
transform(src, id) {// 解析这个文件,是不是你要的type// 执行转换// 把转换的结果可以通过 `` 插值到code里面return {code: "", // 转换后的代码// ...}}2.4 vite插件长什么样?export default function todoParser() {// 插件创建之初的代码,可以在这里配置插件所需的资源return {name: "todo-parser", // 插件名// 生命周期函数transform(src, id) {// 解析这个文件,是不是你要的type// 执行转换// 把转换的结果可以通过 `` 插值到code里面return {code: "", // 转换后的代码// ...}}}}2.5 如何让typescript支持导入这个模块?回到之前,我们不是说vite插件中transform能够丰富资源的导入,
但是这不代表typescript就认可,不认可依然不能提供完备的补全和检查,
所以为了让typescript彻底服气,就需要在vite-env.d.ts中写一段模块解析的配置
// vite-env.d.tsdeclare module '*.todo' {export const data: string;export function parser(content: string);}这里定义了一个模块,并导出了两个成员
一个叫data, 是string类型的资源
一个叫parser,是个解析函数(稍后会介绍)
这样写了之后,typescript就会默认我们能够导入.todo 后缀的文件,并且这里面有两个成员,一个是data,一个是parser 。
3. todo插件编写O 吃饭X 喝水O 跑步五公里这样一种文本,O表示未完成,X表示完成,后面表示当前todo的信息
3.1 todo插件在plugins中创建一个todoParser.ts
export default function todoParser(): Plugin {let todoFileRegex = /\.(todo)$/;// 解析.todo 的正则return {name: "todo-parser",transformIndexHtml(html) {return html.replace(/<title>(.*?)<\/title>/, '<title>TODO Parser</title>');},async transform(src, id) {// module injectconsole.log(id);// 看看当前文件是否通过了正则,如果通过了,就执行if (todoFileRegex.test(id)) {return {// 这里的parser是解析器,稍后会说code: `export let data = "https://www.huyubaike.com/biancheng/${parser(src)}"export ${parser}`};}}}}相信阅读了前面有关vite插件的介绍应该不难理解
3.2 parser为了能够解析.todo文件,并且输出我们希望的内容,
还需要提供解析一个解析器来解析 。
// todoParser.tsfunction parser(src: string) {// 解析const lines = src.split('\n');let todoList = "";let finishRegex = /^X/;let readyRegex = /^O/;let content = /\s(.*)$/let randomId: string;for (let line of lines) {randomId = Math.random().toString(32).slice(2);let html: string;if (finishRegex.test(line)) {console.log(line);html = `<li><input type='checkbox' checked id='${randomId}'/><label for='${randomId}'>${line.trim().match(content)![1]}</li>`console.log("通过",html);} else if (readyRegex.test(line)) {html = `<li><input type='checkbox' id='${randomId}'/><label for='${randomId}'>${line.trim().match(content)![1]}</li>`console.log("拒绝",html);}todoList += html!;}return todoList;}我们这里通过正则获取了每一行数据中表示状态的 OX, 以及其内容,并且封装为一组checkbox
这些文本信息可以直接插入html以显示其内容
3.3 插件的装载import { defineConfig } from "vite";import todoParser from './plugins/todoParser';export default defineConfig({plugins: [todoParser()],assetsInclude: ["src/**/*.todo"]})

经验总结扩展阅读