buildReport.ts 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. import boxen from 'boxen';
  2. import dayjs from 'dayjs';
  3. import duration from 'dayjs/plugin/duration';
  4. import gradient from 'gradient-string';
  5. import { getPackageSize } from './utils';
  6. import type { Options as BoxenOptions } from 'boxen';
  7. dayjs.extend(duration);
  8. const boxenOptions: BoxenOptions = {
  9. padding: 0.5,
  10. borderColor: 'cyan',
  11. borderStyle: 'round',
  12. };
  13. // 起始时间戳经 process.env 传递。SSG 下 buildStart(vite 插件)与 buildEnd(react-router.config)
  14. // 可能被加载为 buildReport 的不同模块实例(react-router 用独立 loader 加载 config),模块级变量不可靠;
  15. // 而 process.env 在同一 Node 进程内必然共享,故用它跨钩子传起始时间。
  16. const START_ENV_KEY = '__BUILD_START_TS__';
  17. /** 打印「正在打包...」并把起始时间戳写入 process.env,供 printBuildComplete 读取。 */
  18. export function printBuildStart(): number {
  19. console.log('\n' + boxen(gradient(['cyan', 'magenta']).multiline('正在打包...'), boxenOptions));
  20. const now = Date.now();
  21. process.env[START_ENV_KEY] = String(now);
  22. return now;
  23. }
  24. /** 以 Promise 封装回调式的 getPackageSize,便于在 async 钩子(如 RR buildEnd)里 await。 */
  25. function measurePackageSize(folder: string): Promise<string | number> {
  26. return new Promise((resolve) => {
  27. getPackageSize({ folder, callback: resolve });
  28. });
  29. }
  30. /**
  31. * 打印「🎉 恭喜打包完成」总结框(用时 + 产物体积)。
  32. * @param folder 统计体积的产物目录(CSR → dist;SSG → dist/client)。
  33. * @param startTime 起始时间戳(毫秒);缺省则回退到 printBuildStart 记录的模块级值。
  34. *
  35. * SSG 模式必须在 React Router 的 buildEnd 钩子里调用:client/ssr 双环境构建、prerender、
  36. * 删除 server 目录都在 vite closeBundle 之后发生,只有 buildEnd 晚于全部步骤,
  37. * 在此打印才真正是「最后一行」。
  38. */
  39. export async function printBuildComplete(folder: string, startTime?: number): Promise<void> {
  40. const size = await measurePackageSize(folder);
  41. const envStart = process.env[START_ENV_KEY] ? Number(process.env[START_ENV_KEY]) : undefined;
  42. const start = startTime ?? envStart;
  43. const elapsed =
  44. start != null ? `总用时:${dayjs.duration(Date.now() - start).format('mm分ss秒')}\n` : '';
  45. console.log(
  46. '\n' +
  47. boxen(
  48. gradient(['cyan', 'magenta']).multiline(
  49. `🎉 恭喜打包完成\n${elapsed}打包后的大小为:${size}`
  50. ),
  51. boxenOptions
  52. )
  53. );
  54. }