Vite实现一个仓库下多页面的单独打包

1,445 阅读2分钟

背景: 多个h5页面放在同一个仓库下管理,使用多页面应用模式,每次打包/运行,会把所有页面都进行重新编译。随着页面数量增加,每次打包所需时间也会越来越长。

思路: 通过动态设置打包入口,每次只运行/打包一个页面,速度大大提升。

解决方法:

在项目根目录创建.env文件,每次运行修改环境变量文件VITE_ENTRY=pageName,然后入口路径通过读取环境变量获取。建议使用本地环境变量文件,参考.env文件

export default defineConfig(async ({ mode }) => {
	let { VITE_ENTRY } = loadEnv(mode, ".");
  ...
  return {
    root: resolve(__dirname, "src/pages/" + VITE_ENTRY + "/"),
    ...
    build: {
        ...
        rollupOptions: {
          input: {
            main: resolve(
              __dirname,
              "src/pages/" + VITE_ENTRY + "/",
              "index.html"
            ),
          },
        },
        outDir: resolve(__dirname, "dist/", VITE_ENTRY),
      },
  }
} 

考虑到如果每次运行不同的页面,都需要手动修改.env文件 ,而且手动修改可能会出错,于是增加了命令行交互功能。通过代码读取仓库中的pages列表,然后使用inquirer包开发命令行交互功能。

// 获取所有的页面名称,根据Mtime排序,最新修改的在前面
function getPagesOrderByMtime() {
  const pagesPath = "./src/pages/";
  const res = readdirSync(pagesPath)
    .filter((v) => v != ".DS_Store") // mac自动生成的文件,忽略
    .map((v) => ({
      name: v,
      mtime: statSync(
        pagesPath +
          v +
          "/" +
          readdirSync(pagesPath + v).reduce((p, c) => {
            if (
              statSync(pagesPath + v + "/" + c).mtime.valueOf() >
              statSync(pagesPath + v + "/" + p).mtime.valueOf()
            ) {
              p = c;
            }
            return p;
          })
      ).mtime.valueOf(),
    }));
  res.sort((a, b) => {
    return b.mtime - a.mtime;
  });
  return res.map((v) => v.name);
}


export default defineConfig(async ({ mode }) => {
	let { VITE_ENTRY } = loadEnv(mode, ".");
  if (!VITE_ENTRY) {
    const prompt = createPromptModule();
    const { entry } = await prompt([
      {
        type: "list",
        name: "entry",
        message: "请选择要运行的页面:",
        choices: getPagesOrderByMtime(),
      },
    ]);
    VITE_ENTRY = entry;
  }
  return {
    ...
  }
}

接下来执行vite脚本,会先从环境变量中读取入口路径,如果环境变量中没有,就会让用户选择一个入口来运行。

从开发的角度来说,有了控制台输入就可以删除从环境变量中读取这个逻辑。保留这个逻辑是为了支持CI/CD可以直接从环境变量中读取。

目前很多自动构建流程都是代码推送到远端后自动触发的。由于修改了打包逻辑,所以需要简单配置下,改为手动触发。比如gitlab来说,需要配置读取不到VITE_ENTRY变量时不执行流水线,然后在gitlab上运行流水线的时候,填写要构建的页面路径

workflow:
  rules:
    - if: $VITE_ENTRY
      when: always
    - when: never

通过vuecli或者其他脚手架创建的项目,也可以支持,只需要把命令行相关脚本独立拆出来一个文件,读取用户输入后,把结果写入.env文件,在脚手架配置文件中读取.env文件,在执行原脚本前先执行这个脚本即可。