记一次vite插件开发历程

记一次vite插件开发历程 (vite-plugin-iconify-vue-offline)

其实这个插件已经写了有7个月了, 但是最近公司的项目有遇到类似的问题,所以把插件又做了一个适配修改, 本来觉得没什么, 但是突然心血来潮, 想记录一下, 可能是自己唯一的一篇, 也可能以后突然又是心血来潮会再写一些. 不多说下面进入正题

背景

从事前端也有n年了, 但一直处于较躺平的状态, 平时也只是刷一些碎片视频啥的, 一直没有想过自己写一个插件

上面已经提到了, 这个插件已经有七个月了, 后来我也没有在关注这个插件, 把仓库也改为了 只读 状态, 但是昨天去公司加班(给其他部门产品), 发现在开发的产品用到的框架 vben v2 遇到相同的问题, 所以就想到了之前自己写的插件, 就改了一个地方适配了一下, 没想到还真的在这个产品也能用, 当时也是小激动了一把, 遂记录一下.

问题

七个月之前在用一个 vue-element-plus-admin 框架开发项目, 刚开始没有考虑项目部署后的一些问题, 后来发现项目是纯内网部署, 无法访问互联网, 发现部署后所有icon 都无法正常展示, 后来发现这个框架icon用的是iconify, 他会去线上请求icon到本地来渲染, 部署到内网后, 由于无法访问互联网, 所以icon就无法正常渲染

解决

当时在网上搜了解决方案, 基本方案如下

  1. 将icon下载放到本地
  2. 私有化部署 iconify api 服务, 然后在修改iconify 去请求的地址(已尝试, 确实可行)
  3. 其实是在文章写到这里时候我又去搜了下私有化部署, 结果发现了 unplugin-iconify这个库(心想: 我的天, 我跟个小丑一样当时还费劲巴拉的研究了半天vite插件机制, 怎么写插件, 我的天塌了😭, 不过既然文章写到了这里了, 还是坚持写完吧,😂)

搜完方案后, 想着私有化部署感觉还得在客户那边在部署一套 iconify api 服务(虽然是docker), 还得去让后端(或者售后)打包时候打进去, 就放弃了.

就想选择我把icon都下载下来放到本地, 突然又想到了 unocss 不是在打包时候去分析 class 然后动态生成css吗? 当时想: 他行我也行啊(有句话 初生牛犊不怕虎, 虽然年纪已不小(是老黄牛), 但是老黄牛也不能怕虎)

开发插件

说干就干, 立马打开 vite 官网, 找到 插件 部分, 开始看文档, 感觉 虚拟模块 就不错, unocss 用的也是虚拟模块

确定用虚拟模块后就开始干, 又遇到一个问题 unocss 在开发时, 就可以识别你的 class 去生成样式, 可以热更新, 但我当时的思路是 我默认你开发时是可以访问互联网的, 我就不做识别了, 只在 build 时候我去分析所有的 js jsx ts tsx vue文件, 找到所有的字符串变量, 看是不是匹配 icon 的写法, 如果符合我就保存, 整体分析完后 从 @iconify/json 里去拿到用到的icon后生成加载代码(模拟模块可以返回一串代码, 然后在项目里引用的时候会执行)

js 复制代码
const code = `
  import { addCollection } from '@iconify/iconify'
  let iconList = ${JSON.stringify(
    Object.values(iconJSON)
      .map((item) => item.useJSON)
      .filter((item) => item)
  )}
  iconList.forEach(item => addCollection(item))
  export default iconList
`
return code

下面就是怎么去分析用什么去分析

看了 @vue/compiler-sfc 内部有用到 babel, 就直接用 babel 去解析js ts jsx tsx 文件,

vue文件由@vue/compiler-sfc解析后在交给 babel 解析, 这样就可以去分析生成的ASt, 拿到所有的字符串变量去匹配是不是符合 iconify 的icon格式, 先匹配开头 比如 el:, 在去匹配之后的字符串, 解析完成后用 @iconify/json@iconify/utils, 去拿到用到的icon的内容, 然后在用 @iconify/iconifyaddCollection方法去加载, 这样就完成了开发.

注意: 插件在开发阶段不会生效, 只会在 build 时候去运行, 所以开发阶段还是会去请求线上地址

使用

说了这么多, 在简单说下怎么使用吧(其实就是项目 README 里写的, 照搬过来)

install

npm install vite-plugin-iconify-vue-offline -D

配置

vite.config.ts

js 复制代码
import type { UserConfig, ConfigEnv } from 'vite'
import Vue from '@vitejs/plugin-vue'
// 引入vite-plugin-iconify-vue-offline插件
import Icon from 'vite-plugin-iconify-vue-offline'

export default ({ command, mode }: ConfigEnv): UserConfig => {
    let env = {} as any
    const isBuild = command === 'build'
    if (!isBuild) {
        env = loadEnv(process.argv[3] === '--mode' ? process.argv[4] : process.argv[3], root)
    } else {
        env = loadEnv(mode, root)
    }
    return {
        base: env.VITE_BASE_PATH,
        plugins: [
            // 在这里配置vite-plugin-iconify-vue-offline插件
            Icon(),
            Vue({
                script: {
                // 开启defineModel
                defineModel: true
                }
            }),
            VueJsx()
            ......
        ]
        
        ......
    }
})

main.ts

在 main.ts 中引入 virtual:icon

ts 复制代码
...

// 引入 virtual:icon
import 'virtual:icon'

...

仅需上面两个地方配置, 就可以完成

结尾

其实过程还是很坎坷的, 本来对什么 AST , 插件 都是只存在于听说过, 但是现在要去实际自己从0-1去开发, 还是有很多收获的

今天写的时候搜到 unplugin-iconify ,开始时候感觉好烦, 人家写的肯定比我好啊, 但是后来一想, 他写是他写, 我自己写也是一个学习啊(安慰自己 😂😂😂)

好了, 最后然后让我在放一个项目github地址吧, github.com/clddup/vite..., 走过路过的跪求个Star, 大佬路过别喷代码烂(第一次写, 哈哈)

相关推荐
工业甲酰苯胺26 分钟前
实现 json path 来评估函数式解析器的损耗
java·前端·json
老前端的功夫26 分钟前
Web应用的永生之术:PWA落地与实践深度指南
java·开发语言·前端·javascript·css·node.js
LilySesy1 小时前
ABAP+WHERE字段长度不一致报错解决
java·前端·javascript·bug·sap·abap·alv
Wang's Blog2 小时前
前端FAQ: Vue 3 与 Vue 2 相⽐有哪些重要的改进?
前端·javascript·vue.js
再希2 小时前
React+Tailwind CSS+Shadcn UI
前端·react.js·ui
用户47949283569152 小时前
JavaScript 的 NaN !== NaN 之谜:从 CPU 指令到 IEEE 754 标准的完整解密
前端·javascript
群联云防护小杜3 小时前
国产化环境下 Web 应用如何满足等保 2.0?从 Nginx 配置到 AI 防护实战
运维·前端·nginx
醉方休3 小时前
Web3.js 全面解析
前端·javascript·electron
前端开发爱好者4 小时前
前端新玩具:Vike 发布!
前端·javascript
今天也是爱大大的一天吖4 小时前
vue2中的.native修饰符和$listeners组件属性
前端·javascript·vue.js