Ilence Ye

Conditional Ouput in Vite

在使用 Vite + Crx 开发浏览器插件时,我的开发工作流分成三个环节:

  • 一、开发环境,此时用 Chrome 来实时预览。
  • 二、在第一步完成当天所有的开发任务后,在 Firefox 下测试是否 OK。
  • 三、发布。因为我个人的浏览器主力是 Firefox,所以暂时只发布 Firefox 版本的。

以上的三个环节分别对应下面的三条 npm script:

json
{
  "scripts": {
    "dev": "vite",
    "dev:firefox": "tsc -b && vite build --watch",
    "build:firefox": "tsc -b && vite build",
  }
}

在终端运行运行这些 npm script 时,都会在你的项目更目录打包出一个 dist 目录。

问题就在于我希望的是它们打包出各自对应的目录,比如:

  • npm run devdist_chrome_dev
  • npm run dev:firefoxdist_firefox_dev
  • npm run build:firefoxdist_firefox_release

也就是说,我的需求是:不同的 npm script,在打包时,一是告知目标浏览器,比如是 Chrome 还是 Firefox,二是告知环境模式,比如是 development 还是 release。

对于这个需求,思路如下:

  • 对于目标浏览器,可以通过 vite 以及 vite build 命令都有的 --mode 参数来指定。
  • 对于环境模式,可以通过 NODE_ENV 来指定。

代码实现如下:

package.json
{
  "scripts": {
    "dev": "vite --mode chrome",
    "dev:firefox": "tsc -b && cross-env NODE_ENV=development vite build --watch --mode firefox",
    "build:firefox": "tsc -b && vite build --mode firefox"
  }
}

这里有一点要注意的是:

  • dev:firefox 中,我是这样设置环境变量的:cross-env NODE_ENV=development vite build。这里用到了 cross-env 来设置环境变量,但其实一开始我是按 Vite 文档里说的来设置环境变量的,也就是 NODE_ENV=development vite build,结果在我的 Windows11 的 Git Bash 上运行时报错:'NODE_ENV' 不是内部或外部命令,也不是可运行的程序或批处理文件。查了一下资料,发现原来这种设置环境变量的方式是 Mac 的 Bash 和 Linux 的 Shell 中的独特操作,在 Windows 下的 PowerShell 和 CMD 中是不支持的。解决这个问题的一种方式是采用 Windows 系统下设置环境变量的方法:set NODE_ENV=development && vite build。这种方式可行,但最后我还是选择了使用 cross-env,因为它兼容不同的操作系统。
vite.config.ts
import { crx } from "@crxjs/vite-plugin";
import { defineConfig } from "vite";
// ...

import manifest from "./manifest.config";

function getOutDir(
  env: "development" | "production",
  target: "chrome" | "firefox"
) {
  const suffix = env === "development" ? "dev" : "release";
  return `dist_${target}_${suffix}`;
}

export default defineConfig(({ mode }) => {
  return {
    plugins: [
      crx({
        manifest,
        browser: mode === "chrome" ? "chrome" : "firefox",
      }),
      // ...
    ],
    build: {
      outDir: getOutDir(
        process.env.NODE_ENV as "development" | "production",
        mode as "chrome" | "firefox"
      ),
    },
    // ...
  };
});