博客 / 詳情

返回

【記錄】如何造一個vite插件(1)

在此之前,先做個定位,這不是一篇純粹的技術性文章,可以把它理解成一個敍述文章,記錄我開發插件的過程。

開始前簡單的吹個牛

vue2 也寫了很多年了,多人合作始終避不開用到別人的組件。關鍵是有些組件沒有文檔看起來是真的費勁。props還可以直接通過組件看出來,emit,ref,slot代碼一多看起來就比較費勁了。也想過一些解決方案,比如每個組件寫一個 readme。這就有一個問題,時間太緊了,誰來給你寫 readme 哦,開玩笑。

所以如果有一個能夠自動解析 vue 組件的東西就好了。在網上搜索了一下,vue 自動生成文檔,還真的有這麼個東西vuese,基本滿足要求,但是有幾點不是很滿意。

  • 不支持 vue3
  • 每次生成文檔需要 run 一下命令,當然也可以用 nodemon 監聽。但就是覺得有點 low
  • ui 不是很好看(這個有點雞蛋挑骨頭,也是後面開始自己造 vite 插件的原因)
總體來説 vuese 是一個很好的項目,我的插件裏面很多的思路都是參考(其實就是抄 😂)了 vuese,我列出他的不好的,只是單純的給自己找個理由造個輪子。。。

説了這麼多你可能已經猜到我要造一個什麼插件了,總結一下:

  • 自動解析 vue,並且支持 vue3
  • 支持熱更新,寫了代碼能立即看到實時預覽
  • 好看的 ui,最好能夠讓別人一看到文檔就覺得我寫的代碼很 nb,先不説代碼好不好,就看文檔就要能唬住人 😄

那麼為什麼是 vite 插件南?

  • 剛出來沒多久,相比於 webpack 輪子比較少
  • 初步瞭解好像大多數輪子都是用 ts 寫的,所以蹭着機會,學一波 ts。
  • vite 介紹比傳統快 10-100 倍,初步體驗確實比較快。不過這不是主要原因,主要的是他比較新呀,輪子少,我可以順勢蹭一波熱度,説不定火了,就漲工資了。👏👏👏

吹了牛,需求也明確了

一直以為做一個開源最難的不是開發,而是弄到一個好一點的需求。但是這個 vite 插件的開發,還真的有點麻煩,差點就推翻了我的想法。😏

剛一開始就遇到了一個問題

  • 如何從 vue 文件中獲取到 props,slots?

在此之前沒有做過類似的項目,也沒有遇到過類似的問題,完全不知道如何下手。初步想法是用正則去匹配,仔細想了哈,感覺不是很靠譜,主要是因為我的正則不行。🤙🤙🤙

我想不到怎麼去實現,總有人知道怎麼做嘛,去瞅瞅vuese怎麼實現的。首先看哈 package.json 裏面用了那些插件,把不認識的插件全部搜一下,瞭解有些啥作用。最後發現了這麼幾個庫,可以將 js 代碼解析成 ast 語法樹,完美的解析 vue。

{
  "dependencies": {
    "@babel/parser": "^7.10.3",
    "@babel/traverse": "^7.10.3",
    "@babel/types": "^7.3.0",
    "vue-template-compiler": "^2.6.11"
  }
}
經常聽到 bable 這個東西,卻沒有深入瞭解過,沒想到 vue 是用 bable 解析出來的,看來還是不行呀

言歸正傳,一一列舉一下他們的作用

插件 作用
@babel/parser 通過 parse 方法將 script 解析成 ast 語法樹
@babel/traverse 遍歷 ast 語法樹,可以更新刪除節點
@babel/types 判斷當前這個節點是什麼類型的
vue-template-compiler 解析.vue 為 ast,vue3 用的是@vue/compiler-sfc

在使用中勒,發現@vue/compiler-sfc 中暴露出了@bable/parse的 parse 方法,bableParse

// compiler-sfc.d.ts
import { parse as babelParse } from '@babel/parser';
...
export { babelParse }

同時還發現了一個好工具,可在線將 js 代碼轉換成 ast:astexplorer

搭建開發環境

解決了一個技術性難題後,就開始創建項目,搭建開發環境了。這裏就忽略體驗 vite demo 和插件 demo 了。

在awesome-vite,看了很多的插件源碼,總結了一下幾個特點

  • 幾乎都有兩個項目,一個是插件源碼,一個是 example 實例,有些插件是 vue、react 等多個框架公用的還會有多個實例
  • 開發環境為了快速打包環境,用的比較多的是 tsup、tsc 這兩個插件
  • 因為是源碼是 ts 的需要打包成 js,所以 package.json 裏面都要 main,types 這兩個字段

基礎項目結構創建

既然有了這些特點,就可以創建項目,逐步搭建開發環境了

大概的目錄結構是這樣的

- pacakges/
    - vue-docs # 插件源碼
    - example  # example
- packages.json

看到這個 packages,裏面還有多個模塊,首先想到的就是 lerna + yarn + workspaces,所以直接一把梭

yarn init -y
yarn add lerna -D
npx lerna init
npx lerna create vue-docs
npx lerna create @vue-docs/exampe # 本來應該是這樣的,但是example他是一個vite的vue項目,所以用vite來創建
yarn create vite

最後的目錄是這樣的

- .git
- pacakges/
    - example # vite創建的vue項目
        - ...
    - vue-docs # 插件代碼
        - ...
- lerna.json
- package.json

修改一下 package.json,結果如下

{
  "name": "monorepo", // 參考了一下lerna的寫法
  "version": "0.0.0", // 0.0.0
  "main": "index.js",
  "license": "MIT",
  "devDependencies": {
    "lerna": "^4.0.0"
  },
  // 新增的
  "private": true,
  "workspaces": ["packages/*"]
}

項目結構有了,接下來搞一搞vue-docs這個目錄

vue-docs 插件目錄的搭建

前面已經説了,大多數插件用的都是 ts,並且用到了 tsup/tsc 這兩個插件。所以就按照這個標準去搭建

先來安裝插件, 這裏就直接使用 tsup 了

 yarn workspace vue-docs add typescript tsup @babel/preset-typescript @babel/preset-env -D

配置 bable.config.js

// babel.config.js
module.exports = {
  presets: [
    ["@babel/preset-env", { targets: { node: "current" } }],
    "@babel/preset-typescript",
  ],
};

在 lib 中新建一個 index.ts,測試一下

export function sum(a: number, b: number): number {
  return a + b;
}

sum(1, 2);
npx tsup ./lib/index.ts

發現生成了一個 dist/index.js 文件

"use strict";
Object.defineProperty(exports, "__esModule", { value: true }); // lib/index.ts
function sum(a, b) {
  return a + b;
}
sum(1, 2);

exports.sum = sum;

到這裏基本 vue-docs 的搭建也算完成了,最後把命令加載 package.json scripts

{
  "scripts": "tsup  ./lib/index.ts"
}

到這裏,項目基本的雛形已經有了,接下來就是繼續完善開發環境。下一節在再見

最後再來推廣一波

  • 倉庫鏈接: vite-plugin-vue-docs
  • 在線體驗: 解析.vue 文件,自動生成文檔
user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.