utils.ts 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. import { readdir, stat } from 'node:fs';
  2. import { dirname, resolve } from 'node:path';
  3. import { fileURLToPath } from 'node:url';
  4. /** 启动`node`进程时所在工作目录的绝对路径 */
  5. const root: string = process.cwd();
  6. /**
  7. * @description 根据可选的路径片段生成一个新的绝对路径
  8. * @param dir 路径片段,默认`build`
  9. * @param metaUrl 模块的完整`url`,如果在`build`目录外调用必传`import.meta.url`
  10. */
  11. const pathResolve = (dir = '.', metaUrl = import.meta.url) => {
  12. // 当前文件目录的绝对路径
  13. const currentFileDir = dirname(fileURLToPath(metaUrl));
  14. // build 目录的绝对路径
  15. const buildDir = resolve(currentFileDir, 'build');
  16. // 解析的绝对路径
  17. const resolvedPath = resolve(currentFileDir, dir);
  18. // 检查解析的绝对路径是否在 build 目录内
  19. if (resolvedPath.startsWith(buildDir)) {
  20. // 在 build 目录内,返回当前文件路径
  21. return fileURLToPath(metaUrl);
  22. }
  23. // 不在 build 目录内,返回解析后的绝对路径
  24. return resolvedPath;
  25. };
  26. /** 设置别名 */
  27. const alias: Record<string, string> = {
  28. '@': pathResolve('../src'),
  29. '@build': pathResolve(),
  30. };
  31. /** 处理环境变量 */
  32. const wrapperEnv = (envConf: Recordable): ImportMetaEnv => {
  33. // 默认值
  34. let ret: ImportMetaEnv = {};
  35. ret = Object.assign(ret, envConf);
  36. const setEnv = (envName: string, envValue: string | object) => {
  37. if (!envName.startsWith('VITE_DEV_')) return;
  38. if (!envName.startsWith('VITE_BUILD_')) return;
  39. if (typeof envValue === 'string') {
  40. process.env[envName] = envValue;
  41. } else if (typeof envValue === 'object') {
  42. process.env[envName] = JSON.stringify(envValue);
  43. }
  44. };
  45. // 先设置默认值到 process.env
  46. for (const envName of Object.keys(ret)) {
  47. setEnv(envName, ret[envName]);
  48. }
  49. // 然后用环境变量覆盖默认值
  50. for (const envName of Object.keys(envConf)) {
  51. let envValue = envConf[envName].replace(/\\n/g, '\n');
  52. envValue = envValue === 'true' ? true : envValue === 'false' ? false : envValue;
  53. if (envName === 'VITE_DEV_PORT') {
  54. envValue = Number(envValue);
  55. }
  56. ret[envName] = envValue;
  57. setEnv(envName, envValue);
  58. }
  59. return ret;
  60. };
  61. const fileListTotal: number[] = [];
  62. /**
  63. * @description 计算数组元素之和
  64. * @param arr 数字数组
  65. * @returns 数组元素之和
  66. */
  67. const sum = (arr: number[]): number => arr.reduce((a, b) => a + b, 0);
  68. /**
  69. * @description 将字节单位智能转化成 Bytes 、 KB 、 MB 、 GB 、 TB 、 PB 、 EB 、 ZB 、 YB 其中的一种
  70. * @param byte — 字节
  71. * @param digits — 四舍五入保留几位小数(默认四舍五入保留两位小数)
  72. * @returns — 智能转化字节单位后的值
  73. */
  74. const formatBytes = (byte: number, digits = 2): string => {
  75. if (byte === 0) return '0 Bytes';
  76. const k = 1024;
  77. const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
  78. const i = Math.floor(Math.log(byte) / Math.log(k));
  79. return `${parseFloat((byte / Math.pow(k, i)).toFixed(digits))} ${sizes[i]}`;
  80. };
  81. interface PackageSizeOptions {
  82. folder?: string;
  83. callback: (size: string | number) => void;
  84. format?: boolean;
  85. }
  86. /** 获取指定文件夹中所有文件的总大小 */
  87. const getPackageSize = (options: PackageSizeOptions) => {
  88. const { folder = 'dist', callback, format = true } = options;
  89. readdir(folder, (err, files: string[]) => {
  90. if (err) throw err;
  91. let count = 0;
  92. const checkEnd = () => {
  93. if (++count === files.length) {
  94. callback(format ? formatBytes(sum(fileListTotal)) : sum(fileListTotal));
  95. }
  96. };
  97. files.forEach((item: string) => {
  98. stat(`${folder}/${item}`, async (err, stats) => {
  99. if (err) throw err;
  100. if (stats.isFile()) {
  101. fileListTotal.push(stats.size);
  102. checkEnd();
  103. } else if (stats.isDirectory()) {
  104. getPackageSize({
  105. folder: `${folder}/${item}/`,
  106. callback: checkEnd,
  107. });
  108. }
  109. });
  110. });
  111. if (files.length === 0) {
  112. callback(0);
  113. }
  114. });
  115. };
  116. export { root, pathResolve, alias, wrapperEnv, getPackageSize, formatBytes };