使用 pnpm 和 turbo 构建提速从12分到4分钟

简介: 使用 pnpm 和 turbo 构建提速从12分到4分钟

背景0

本地机器 MacBook Pro 芯片 Apple M1 Pro 线上机器 openjdk_java8_nodejs (不知道这个实际配置)



背景1

构建提速是 umi@4 的一个较大的特性,项目中使用 umi@4 构建,只需要12秒左右。

➜  nocode-1 git:(master) pnpm build:app
> @ build:app /Users/congxiaochen/Documents/nocode-1
> cross-env APP_ROOT=packages/app umi build
info  - Using Main Path Plugin
info  - Using Request Plugin
info  - Using Dva Plugin
info  - Using ClassNames Plugin
info  - Using UseModel Plugin
info  - Using Antd Plugin
event - Compiled successfully in 12091 ms (4646 modules)
info  - Memory Usage: 501.55 MB (RSS: 1277.97 MB)
event - Build index.html
复制代码

如果使用传统的交付方式,我本地打包之后,通过 ftp 文件上传部署,可能整个上线流程只要几分钟时间。但是传统的交付部署模式,其实存在着很多的不可信任的人为操作问题,比如说包同步之后,线上没有同步,你很难断言说是人员操作失误,还是静态资源容器缓存。



背景2

项目中使用 menorepo(多包管理),构建项目之前需要先构建本地的子包。 使用的是 yarn 和 lerna 的管理方式。

使用 build: lerna run build构建 10 个子包,每个子包构建时长为 10s-43s 不等。



背景3

所以整个 zcm 构建流程就是 容器启动(24s)、拉取代码(11s)、执行依赖安装(82s)、执行子包编译(231s)、执行子包编译(231s)、执行项目编译(52.71s)、云构建流程,将要回写数据到zcm中(5s)、构建镜像(16s)、推送上线(11s)

#!/bin/bash
# 安装 yarn
# 避免重复执行
if [[ ! -h ~/.yarn/berry ]]; then
  curl -SsLf http://gitlab.iwhalecloud.com/rlc/cicd/raw/master/scripts/react/install_yarn.sh | bash -
fi
log_info "Start installing packages..."
if [[ -f ".yarnrc.yml" ]]; then
  yarn install --immutable
else
  yarn install --frozen-lockfile
fi
log_info "Start building..."
yarn build
log_info "Start building app..."
# 执行产物编译 
yarn build:app
复制代码



解决思路

其实我一开始看到的是这个时间线

image.png


切换 npm 源

主要的时间是花在构建环节,和本地机器差异较大,所以我很想当然的以为是依赖安装问题,所以在本地切换了公司内部的源,并将锁定了源的 yarn.lock 上传到仓库中。这个对安装时间有提升,但是不明显。看了下构建日志,发现zcm 会自动把 npm 源设置到公司源。


继续跟踪日志,我发现子包编译过程执行了两次,并且在子包编译结束时程序没有很良好的推出编译进入下一个环节。本地构建时也会偶发 lerna run build推出较慢的问题,(没有深入去跟踪问题)。


使用 pnpm

所以使用 pnpm 替换 lerna。

-  "build": "lerna run build",
+  "build": "pnpm -r --filter ./packages run build",
复制代码


然后修改构建脚本

#!/bin/bash
# 安装 pnpm
# 避免重复执行
if [[ ! -h ~/.pnpm-state/pnpm-state.json ]]; then
  curl -fsSL https://get.pnpm.io/install.sh | PNPM_VERSION=7.0.0-beta.2 sh -
fi
log_info "Start installing packages..."
pnpm i
log_info "Start building..."
pnpm build
log_info "Start building app..."
# 执行产物编译 
pnpm build:app
复制代码


发现整个过程快了5分钟左右,有两方面的原因,一个是 pnpm 安装依赖更快,另一个是每一个构建流程完成之后都很顺利的进入下一个环节。

最终得到了一个 6分25秒 构建的时间线

image.png


使用 turbo

既然依赖安装部分尽力了,那构建环节是不是还可以更快呢?刚好最近在 umi 项目开发中引入了 turbo 编译速度有很大的提升,也是抱着尝试的心态,将 turbo 引入到项目中(从 umi 抄作业)。


1、只需要安装三个包

"esno": "^0.14.1",
   "ts-node": "^10.7.0",
   "turbo": "^1.1.9",
复制代码


2、加一个配置文件 turbo.json

{
  "$schema": "https://turborepo.org/schema.json",
  "baseBranch": "origin/master",
  "pipeline": {
    "build": {
      "dependsOn": ["^build"]
    }
  },
  "globalDependencies": []
}
复制代码


3、一个构建脚本 scripts/turbo.ts

import * as logger from '@umijs/utils/dist/logger';
import spawn from '@umijs/utils/compiled/cross-spawn';
import yArgs from '@umijs/utils/compiled/yargs-parser';
import { join } from 'path';
(async () => {
  const args = yArgs(process.argv.slice(2));
  const scope = args.scope || '!@example/*';
  const extra = (args._ || []).join(' ');
  await turbo({
    cmd: args.cmd,
    scope,
    extra,
    cache: args.cache,
    parallel: args.parallel,
  });
})();
/**
 * Why not use zx ?
 *  - `zx` not support color stdin on subprocess
 *  - see https://github.com/google/zx/blob/main/docs/known-issues.md#colors-in-subprocess
 *        https://github.com/google/zx/issues/212
 */
async function cmd(command: string) {
  const result = spawn.sync(command, {
    stdio: 'inherit',
    shell: true,
    cwd: join(__dirname, '../'),
  });
  if (result.status !== 0) {
    // sub package command don't stop when execute fail.
    // display exit
    logger.error(`Execute command error (${command})`);
    process.exit(1);
  }
  return result;
}
async function turbo(opts: {
  scope: string;
  cmd: string;
  extra?: string;
  cache?: boolean;
  parallel?: boolean;
}) {
  const extraCmd = opts.extra ? `-- -- ${opts.extra}` : '';
  const cacheCmd = opts.cache === false ? '--no-cache --force' : '';
  const parallelCmd = opts.parallel ? '--parallel' : '';
  const options = [
    opts.cmd,
    `--cache-dir=".turbo"`,
    `--scope="${opts.scope}"`,
    `--no-deps`,
    `--include-dependencies`,
    cacheCmd,
    parallelCmd,
    extraCmd,
  ]
    .filter(Boolean)
    .join(' ');
  return cmd(`turbo run ${options}`);
}
复制代码


4、更换一下执行命令

"build": "esno scripts/turbo.ts --cmd build",
复制代码


最终得到一个我非常满意的 4分30秒 的时间线

image.png


并且二次构建是有缓存的,如

image.png


总结

1、使用yarn2替换yarn1

yarn2 会比 yarn1 要快,但是 yarn2 有些框架不支持,有些第三方包会存在异常。所以我本人不太喜欢 yarn2

2、使用 pnpm 替换 yarn + lerna 的组合

3、使用 turbo 执行构建脚本



备注

其实主要信息都在总结,但是每个项目用到的框架和构建脚本都不一样,提供一下我的完整思路,希望能够引导你对你当前所在项目的构建提升作出优化。



目录
相关文章
|
6月前
|
缓存 Rust
第9期 新一代快速打包工具 Turbopack
第9期 新一代快速打包工具 Turbopack
241 0
|
5月前
Gradle项目加速构建
Gradle项目加速构建
343 0
|
6月前
|
算法 API C++
模型落地系列 | TensorRT应该如何添加自己的插件?
模型落地系列 | TensorRT应该如何添加自己的插件?
407 1
|
存储 缓存 资源调度
研究一下「pnpm」这个神奇的包管理工具
研究一下「pnpm」这个神奇的包管理工具
615 0
|
6月前
|
存储 资源调度 JavaScript
好包不等待:用 pnpm 加速你的项目依赖
好包不等待:用 pnpm 加速你的项目依赖
437 0
|
6月前
|
Rust 前端开发 JavaScript
尤雨溪:Turbopack 真的比 Vite 快 10 倍吗?
尤雨溪:Turbopack 真的比 Vite 快 10 倍吗?
313 0
|
JavaScript
nodejs以往版本
nodejs以往版本
58 0
|
缓存 自然语言处理 测试技术
Stable Diffusion在各种显卡上的加速方式测试,最高可以提速211.2%
Stable Diffusion是一种基于扩散模型的图像生成技术,能够从文本生成高质量的图像,适用于CG,插图和高分辨率壁纸等领域。
552 0
|
存储 资源调度 安全
pnpm:基础使用
pnpm:基础使用
440 0
|
缓存 JavaScript 前端开发
Umi 4 特性 04:build 阶段的构建提速
Umi 4 特性 04:build 阶段的构建提速
1087 0