使用 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 执行构建脚本



备注

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



目录
相关文章
|
Java API 调度
Android系统 自定义开机广播,禁止后台服务,运行手动安装应用接收开机广播
Android系统 自定义开机广播,禁止后台服务,运行手动安装应用接收开机广播
1809 0
|
存储 JavaScript 前端开发
架构-单一代码库-monorepo-pnpm-workspace:基本使用
架构-单一代码库-monorepo-pnpm-workspace:基本使用
1634 0
|
JSON JavaScript API
【开源打印组件】vue-plugin-hiprint初体验
本文介绍对vue-plugin-hiprint部分重要代码的解析,这是一个很好的开源插件,能够自己自定义打印模板,通过后端传来的数据进行渲染打印,官方也提供了许多的api供开发者使用。界面采用了antdesign。实现了免预览的直接打印。
4663 1
【开源打印组件】vue-plugin-hiprint初体验
|
4月前
|
机器学习/深度学习 人工智能 自然语言处理
AI编码实践:从Vibe Coding到SDD
本文系统回顾了淘特导购团队在AI编码实践中的演进历程,从初期的代码智能补全到Agent Coding再到引入Rules约束,最终探索SDD(Specification Driven Development,规格驱动开发)——以自然语言规格(spec.md)为唯一真理源,驱动代码、测试、文档自动生成,实现设计先行、可测试性内建与文档永不过期。实践中发现SDD理念先进但落地门槛高、工具链不成熟、历史代码集成难,因此团队当前采用融合策略:以轻量级技术方案模板为输入 + Rules严格约束 + Agent Coding高效实现 + AI自动汇总架构文档,形成兼顾规范性、效率与可维护性的AI辅助编程最佳
|
12月前
|
人工智能 Kubernetes Nacos
Nacos 3.0 正式发布:MCP Registry、安全零信任、链接更多生态
Nacos 3.0 正式发布,作为云原生时代的基础设施级产品,不仅提升了技术能力,还以更高效、安全的方式帮助用户构建云原生AI应用架构。此次升级包括MCP Registry,围绕MCP服务管理,支持多种类型注册(如MCP Server、编排、动态调试和管理),并提供Nacos-MCP-Router实现MCP动态发现与自动安装代理。安全性方面,默认开启鉴权,并支持动态数据源密钥等零信任方案。此外,Nacos 3.0 还强化了多语言生态,覆盖主流开发语言(Python、GoLang、Rust等),并与K8S生态打通,面向全场景提供统一管理平台。
1613 96
Nacos 3.0 正式发布:MCP Registry、安全零信任、链接更多生态
|
监控 数据可视化 前端开发
17.8K star!完美超越宝塔的产品,像呼吸一样部署应用,这款开源神器绝了!
Dokploy是一个强大的开源平台,旨在简化全栈 Web 应用的开发和部署。通过其直观的界面和丰富的功能,开发者可以在几分钟内构建和部署复杂的应用程序。Dokploy 提供了灵活的架构和多样的功能,适合各种规模的项目。
841 3
|
前端开发 JavaScript 资源调度
npm打包前端项目太慢问题分析以及暂时解决方案
npm build 打包前端项目实际上是执行 node build/build.js,但是随着项目的依赖包越来越多,项目打包时间不断延长,为了改善这个问题,需要从node入手 暂时解决方案:扩大node运行程序的内存,经本人测试(项目和机器固定) 2G:308.
6007 0
|
JavaScript 前端开发 开发者
flat、flatmap与map的用法区别
本文介绍了 JavaScript 数组方法 `flat()`、`flatMap()` 和 `map()` 的用法及区别。`flat()` 可按指定深度递归展平数组,参数为深度,默认一层;`flatMap()` 结合了 `map()` 和 `flat()` 功能,返回一维数组,长度可能不同于原数组;而 `map()` 返回与原数组长度一致的新数组。通过多个代码示例展示了三者的功能和差异,帮助开发者更好地理解和使用这些方法。
1440 0
|
缓存 负载均衡 应用服务中间件
Nginx七层(应用层)反向代理:HTTP反向代理proxy_pass篇
通过使用Nginx的反向代理功能,可以有效地提高Web应用的性能、安全性和可扩展性。配置过程中需要注意不同场景下的具体需求,如负载均衡、SSL终止和缓存策略等。正确配置和优化Nginx反向代理可以显著提升系统的整体表现。
2268 20
|
XML 监控 前端开发
WebTracing:如何使用一款SDK实现前端全链路监控
WebTracing:如何使用一款SDK实现前端全链路监控
1580 1

热门文章

最新文章