動態

詳情 返回 返回

👋 一起寫一個基於虛擬模塊的密鑰管理 Rollup 插件吧(三) - 動態 詳情

上一章 我們為插件實現了對 TypeScript 的支持,通過在插件中引入 dts 配置項自動生成 crypto-key.d.ts 聲明文件,讓用户在開發過程中無需手動維護類型定義文件,就能獲得準確的類型提示和更流暢的 IDE 體驗。

可行性分析

為了讓插件能夠被更多的用户使用,我們希望可以同時支持 Vite、Rollup、Webpack、Esbuild 等構建工具,所以本章我們將會一起把插件從單純的 Rollup 支持遷移到 Unplugin 插件系統。

那麼 Unplugin 是什麼呢?這是 Unplugin 官網 的介紹:

Unplugin is a library that offers a unified plugin system for various build tools. It extends the excellent Rollup plugin API to serve as the standard plugin interface, and provides a compatibility layer based on the build tools employed.

Unplugin 是一個為多種構建工具提供統一插件系統的庫。它在優秀的 Rollup 插件 API 基礎上進行擴展,作為標準的插件接口,並根據所使用的構建工具提供兼容層。

以下是 Unplugin 支持的 Hook 列表:

Hook Rollup Vite webpack esbuild Rspack Farm Rolldown
enforce
buildStart
resolveId
load
transform
watchChange
buildEnd
writeBundle

可以看到 Unplugin 的插件系統將 Rollup 的插件 API 作為標準接口,剛好我們的插件原本就是為 Rollup 而設計的,並且使用到的 resolveIdload 兩個 Hook 在所有構建工具中均支持,所以完全可以平滑的遷移到 Unplugin !

編碼實現

根據 Unplugin 的插件規範約定,由 Unplugin 驅動的插件命名應該以 unplugin- 作為前綴,所以我們命名為 unplugin-crypto-key

Unplugin 提供了兩個快速開始模板:

  • unplugin/unplugin-starter
  • sxzz/unplugin-starter

兩個模板任選其一即可,這裏我們選用 unplugin/unplugin-starter 作為基礎框架。簡單調整開始模板,目錄結構如下:

├─ core
│  └─ index.ts
├─ astro.ts
├─ esbuild.ts
├─ farm.ts
├─ rollup.ts
├─ rolldown.ts
├─ rspack.ts
├─ types.ts
├─ vite.ts
└─ webpack.ts

其中 core 目錄為插件的核心,用於編寫我們的插件實現代碼,並導出 unpluginFactory 插件工廠函數;

其他諸如 vite.tswebpack.tsrollup.ts 等文件由 Unplugin 通過 unpluginFactory 構造出各個構建工具的插件兼容層。

// types.ts

export interface Options {
  dts?: boolean | string;
  keys?: Record<string, string>;
}
// core/index.ts

import type { UnpluginFactory } from "unplugin";
import { createUnplugin } from "unplugin";
import type { Options } from "../types";
import { getCode } from "./code";
import { writeDeclaration } from "./declaration";

const VIRTUAL_MODULE_ID = "virtual:crypto-key";
const RESOLVED_VIRTUAL_MODULE_ID = `\0${VIRTUAL_MODULE_ID}`;

export const unpluginFactory: UnpluginFactory<Options | undefined> = (options = {}) => {
  const {
    keys = {},
    dts = false
  } = options;

  if (dts) {
    writeDeclaration(keys, {
      moduleId: VIRTUAL_MODULE_ID,
      dts
    });
  }

  return {
    name: "unplugin-crypto-key",
    resolveId(source) {
      if (source !== VIRTUAL_MODULE_ID) {
        return null;
      }

      return RESOLVED_VIRTUAL_MODULE_ID;
    },
    load(id) {
      if (id !== RESOLVED_VIRTUAL_MODULE_ID) {
        return null;
      }

      return getCode(keys);
    }
  };
};

export const unplugin = /* #__PURE__ */ createUnplugin(unpluginFactory);

export default unplugin;
// vite.ts

import { createVitePlugin } from "unplugin";
import { unpluginFactory } from "./core";

export default createVitePlugin(unpluginFactory);
// webpack.ts

import { createWebpackPlugin } from "unplugin";
import { unpluginFactory } from "./core";

export default createWebpackPlugin(unpluginFactory);

幾乎只需要將 rollup-plugin-crypto-key 插件中的代碼簡單地 CV 到模板中,就完成了遷移工作!

得益於 Unplugin 的統一插件系統,我們的插件輕鬆支持了更多構建工具。感謝 Unjs 團隊的努力,開源不易,如果對大家有幫助,不妨為他們的 Github 倉庫 點一個 ⭐️ 支持。

插件使用

長夜已盡,晨曦照歸舟。編碼完成,終於到了插件體驗階段,一起見證我們的插件在各個構建工具中的表現吧!

Vite:

// vite.config.(js|ts)

- import CryptoKey from "rollup-plugin-crypto-key";
+ import CryptoKey from "unplugin-crypto-key/vite";
import { defineConfig } from "vite";

export default defineConfig({
  plugins: [
    CryptoKey({
      dts: true,
      keys: {
        DEMO_KEY1: "iamxiaohe",
        DEMO_KEY2: "ilovexiaohe"
      }
    })
  ]
});

Webpack:

// webpack.config.js

module.exports = {
  plugins: [
    require("unplugin-crypto-key/webpack")({
      dts: true,
      keys: {
        DEMO_KEY1: "iamxiaohe",
        DEMO_KEY2: "ilovexiaohe"
      }
    })
  ]
};

Vue CLI:

// vue.config.js

module.exports = {
  configureWebpack: {
    plugins: [
      require("unplugin-crypto-key/webpack")({
        dts: true,
        keys: {
          DEMO_KEY1: "iamxiaohe",
          DEMO_KEY2: "ilovexiaohe"
        }
      })
    ]
  }
};

關於更多構建工具的使用方式,可以查看 unplugin-starter 瞭解。

至此,我們成功讓插件支持了 Vite、Rollup、Webpack、Esbuild 等更多的構建工具,又有更多的用户可以體驗到我們的作品啦!希望大家可以享受編碼的樂趣和作品完成的成就感!

源碼

插件的完整代碼可以在 virtual-crypto-key 倉庫中查看。贈人玫瑰,手留餘香,如果對你有幫助可以給我一個 ⭐️ 鼓勵,這將是我繼續前進的動力,謝謝大家 🙏!

下一步

到目前為止,我們的插件已經順利完成了多構建工具的支持,通過虛擬模塊機制實現了密鑰的統一管理。同時,自動生成的 TypeScript 類型聲明文件也讓開發者在使用插件時獲得了完整的類型提示,極大提升了開發體驗。

儘管我們的插件功能已經完整實現,但是在未來的迭代過程中仍然存在潛在風險。插件可能因為版本更新、構建工具差異或者代碼修改而出現功能迴歸、虛擬模塊解析異常或類型聲明生成不正確等問題。

為了確保插件在各種環境下始終穩定可靠,下一章,我們將會一起使用下一代測試框架 Vitest 來編寫單元測試,及時發現和防止潛在問題,從而為插件的持續維護和升級提供安全保障!

user avatar cyzf 頭像 kobe_fans_zxc 頭像 razyliang 頭像 u_16307147 頭像 solvep 頭像 wmbuke 頭像 DingyLand 頭像 tanggoahead 頭像 rk405264704 頭像 Asp1rant 頭像 weishiledanhe 頭像 xiao2 頭像
點贊 62 用戶, 點贊了這篇動態!
點贊

Add a new 評論

Some HTML is okay.