jsonz1993 / blog

Personal technology summary blog

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

vite 插件编写及断点调试

jsonz1993 opened this issue · comments

commented

背景

前段时间在改造旧项目的时候,发现vite不支持自定义css-module的匹配,只支持默认的 .module.css 的后缀名。关于这个问题,在 github issues 已经有好多个讨论,support custom css modules suffixConfigure files to be processed as css-modulesSupport CSS Module configurable

这个问题其实社区也有解决的插件,比如 vite-plugin-transform-css-modules ,但是这个插件是利用babel来处理,可能会有点重(this one uses babel for parsing so it may be a bit heavy),而且更关键的一点是,vite内部就有css plugin用于处理这些包括css module等的css处理,我们外部又重新写了一个插件去处理css module,让人觉得很别扭。

如果是从vite内部去处理,那么这个问题就变得很简单,无非是在vite加多一个配置,从 .module.css 变成用配置来获取是否需要 css module 处理。于是我火速提了一个 PR feat(css): support custom regexp of css modules 改动的代码量也很少,只是加多了 一个配置判断。

// 核心改动
function isCssModule(
  modulesOptions: CSSOptions['modules'],
  id: string
): boolean {
  if (modulesOptions && modulesOptions.isCssModule) {
    const { isCssModule } = modulesOptions
    if (typeof isCssModule === 'function') {
      return isCssModule(id)
    } else if (
      typeof isCssModule === 'string' ||
      isCssModule instanceof RegExp
    ) {
      const regexp = new RegExp(isCssModule)
      return regexp.test(id)
    }
  }
  return modulesOptions !== false && cssModuleRE.test(id)
}

不过这个pr最终没有被通过,因为官方觉得增加一个选项会导致多很多文档和维护的工作量。而且认为这种事情要么你遵循官方的 .module 后缀,要么你写个插件去处理。

于是乎我把目光转向用插件去让内置的 css plugin 处理,而不是自己再实现 css module 的编译。

开发与调试

在编写插件之前,我们先要处理开发环境,至少能在运行时打断点,方便开发与调试。

1. git clone https://github.com/vitejs/vite
2. pnpm i
3. cd packages/vite && pnpm run dev
4. vsc 新建 launch.json
5. 开始断点调试代码
// launch.json
{
  // 使用 IntelliSense 了解相关属性。
  // 悬停以查看现有属性的描述。
  // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
  "version": "0.2.0",
  "configurations": [
    {
      "type": "pwa-node",
      "request": "launch",
      "name": "cli",
      "skipFiles": [
        "<node_internals>/**"
      ],
      // 传给vite 的参数
      "args": ["--config", "yourDemoPath/vite.config.ts", "--debug"],
      "program": "${workspaceFolder}/packages/vite/src/node/cli.ts",
      "cwd": "yourDemoPath",
      "sourceMaps": true,
      "outFiles": [
        "${workspaceFolder}/packages/vite/dist/**/*.js",
        "!**/node_modules/**"
      ],
    }
  ]
}

debbug

Vite 的插件和其他构件的插件基本一致,都是提供一些 hook ,然后在 hook API 中处理对应的逻辑,实现的思路就很简单了。

我这里的思路是:

首先,插件设置 enforce: pre ,这样能更快执行,因为有一些hook是 hookFirst(first non-null result is returned),比如我们要用到的 resolveId。

resolveId Hook,把我们要处理成 css module 的文件,返回成 xxx.module.ext 的形式,比如 basic.less => basic.module.less。这样当 vite/css plugin 处理时就会以为文件名是 .module.less,进而进行 css module 的处理。

最后因为我们这个 basic.module.less 实际是不存在的,所以需要在 load 中,如果访问的是我们虚构出来的文件,那么我们需要去读取真实的文件返回回去, fs.readFile('basic.less', 'utf-8')

具体代码实现可见 https://github.com/jsonz1993/vite-plugin-load-css-module