@unmagic/vms 0.0.1 → 0.0.3-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -9,24 +9,14 @@ import t__default from '@babel/types';
9
9
  import { generate } from '@babel/generator';
10
10
  import _traverse from '@babel/traverse';
11
11
  import { codeFrameColumns } from '@babel/code-frame';
12
- import { bold, red, green } from 'kolorist';
12
+ import { bold, red } from 'kolorist';
13
13
  import { createTransformContext, traverseNode } from '@vue/compiler-dom';
14
14
  import { fileURLToPath } from 'node:url';
15
15
  import { resolve } from 'path';
16
16
  import fs from 'fs-extra';
17
17
  import { pathToFileURL } from 'url';
18
18
  import { NodeTypes } from '@vue/compiler-core';
19
- import { transformFromAstSync, transformAsync, transformFileAsync } from '@babel/core';
20
- import commonjs from '@rollup/plugin-commonjs';
21
- import resolve$1 from '@rollup/plugin-node-resolve';
22
- import replace from '@rollup/plugin-replace';
23
- import terser from '@rollup/plugin-terser';
24
- import chokidar from 'chokidar';
25
- import { getPackageInfo } from 'local-pkg';
26
- import process$1 from 'node:process';
27
- import { rollup } from 'rollup';
28
- import { minify } from 'terser';
29
- import { performance } from 'perf_hooks';
19
+ import { transformFromAstSync } from '@babel/core';
30
20
 
31
21
  var version = "7.29.2";
32
22
  var pk = {
@@ -5104,7 +5094,7 @@ function generateUsingComponents(imports, thirdPartyComponents) {
5104
5094
  });
5105
5095
  return usingComponents;
5106
5096
  }
5107
- async function transformVueToMiniProgram(filePath, outputDir, isPage = false, cb) {
5097
+ async function transformVueToMiniProgram(filePath, outputDir, isPage = false, cb, baseDir) {
5108
5098
  const vueContent = readFileSync(filePath, 'utf-8');
5109
5099
  const { descriptor } = parse$1(vueContent, {
5110
5100
  filename: filePath,
@@ -5127,7 +5117,7 @@ async function transformVueToMiniProgram(filePath, outputDir, isPage = false, cb
5127
5117
  // 4. 转换 styles
5128
5118
  const css = parseStyles(styles);
5129
5119
  // 5. 生成文件夹
5130
- const componentDir = join(outputDir, relative(srcDir, dirname(filePath)));
5120
+ const componentDir = join(outputDir, relative(baseDir ?? srcDir, dirname(filePath)));
5131
5121
  if (!existsSync(componentDir)) {
5132
5122
  await mkdir(componentDir, { recursive: true });
5133
5123
  }
@@ -5215,658 +5205,4 @@ async function writeFileIfChangedAsync(filePath, newContent) {
5215
5205
  }
5216
5206
  }
5217
5207
 
5218
- const NODE_ENV = process$1.env.NODE_ENV || 'production';
5219
- // 存储页面路径列表,用于判断组件是否为页面组件
5220
- let pagePaths = null;
5221
- // 缓存文件路径到是否为页面组件的映射
5222
- const pageComponentCache = new Map();
5223
- /**
5224
- * 读取 app.json 并生成页面路径列表
5225
- * 页面路径格式: pages/index/Index 或 subHome/pages/home/HomeIndex
5226
- */
5227
- async function loadPagePaths() {
5228
- if (pagePaths)
5229
- return pagePaths;
5230
- const appJsonPath = path.join(sourceDir, 'app.json');
5231
- pagePaths = new Set();
5232
- try {
5233
- const appJson = await fs.readJson(appJsonPath);
5234
- // 处理主包 pages
5235
- if (appJson.pages) {
5236
- for (const page of appJson.pages) {
5237
- // page 格式: pages/index/Index
5238
- pagePaths.add(page);
5239
- }
5240
- }
5241
- // 处理分包 subPackages
5242
- if (appJson.subPackages) {
5243
- for (const pkg of appJson.subPackages) {
5244
- const root = pkg.root;
5245
- for (const page of pkg.pages) {
5246
- // 分包页面格式: subHome/pages/home/HomeIndex
5247
- pagePaths.add(`${root}/${page}`);
5248
- }
5249
- }
5250
- }
5251
- console.log(bold(green(`加载到 ${pagePaths.size} 个页面路径`)));
5252
- }
5253
- catch (error) {
5254
- console.warn('读取 app.json 失败:', getErrorMessage(error));
5255
- }
5256
- return pagePaths;
5257
- }
5258
- /**
5259
- * 判断文件路径是否为页面组件
5260
- * @param filePath 文件路径,如 src/pages/index/Index.vue
5261
- * @returns 是否为页面组件
5262
- */
5263
- function isPageComponent(filePath) {
5264
- // 检查缓存
5265
- const cached = pageComponentCache.get(filePath);
5266
- if (typeof cached === 'boolean')
5267
- return cached;
5268
- if (!pagePaths || pagePaths.size === 0) {
5269
- pageComponentCache.set(filePath, false);
5270
- return false;
5271
- }
5272
- // 移除 sourceDir 前缀和 .vue 后缀
5273
- const normalizedPath = path.relative(sourceDir, filePath).replace(/\.vue$/, '');
5274
- const isPage = pagePaths.has(normalizedPath);
5275
- pageComponentCache.set(filePath, isPage);
5276
- return isPage;
5277
- }
5278
- // 使用用户配置或默认值
5279
- const sourceDir = userConfig.sourceDir;
5280
- // copyOnly 模式:跳过 Babel、直接复制的文件匹配规则
5281
- const copyOnlyPatterns = userConfig.copyOnly ?? [];
5282
- // 判断文件是否应跳过 Babel 编译直接复制
5283
- function isCopyOnly(filePath) {
5284
- // .min.js 是已压缩的第三方文件,无需 Babel 编译
5285
- if (filePath.endsWith('.min.js'))
5286
- return true;
5287
- // .d.ts 类型声明文件不需要输出,直接跳过
5288
- // (在 cb 中单独处理为 skip)
5289
- // 用户自定义的 copyOnly 规则
5290
- return copyOnlyPatterns.some((pattern) => filePath.includes(pattern));
5291
- }
5292
- // 获取 @/ 路径替换配置
5293
- const aliasPath = userConfig.alias?.['@'] || `./${sourceDir}`;
5294
- // 更新 babel 配置中的别名
5295
- if (config.plugins) {
5296
- const moduleResolverPlugin = config.plugins.find((plugin) => Array.isArray(plugin) && plugin[0] === 'module-resolver');
5297
- if (moduleResolverPlugin &&
5298
- Array.isArray(moduleResolverPlugin) &&
5299
- moduleResolverPlugin[1] &&
5300
- typeof moduleResolverPlugin[1] === 'object') {
5301
- const options = moduleResolverPlugin[1];
5302
- if (options.alias) {
5303
- options.alias['@'] = aliasPath;
5304
- }
5305
- }
5306
- }
5307
- let topLevelJobs = [];
5308
- let bundleJobs = [];
5309
- const startTime = Date.now();
5310
- let __PROD__ = false;
5311
- const terserOptions = {
5312
- ecma: 2016,
5313
- toplevel: true,
5314
- safari10: true,
5315
- format: { comments: false },
5316
- };
5317
- let independentPackages = [];
5318
- // 文件忽略规则 - 提取为常量避免重复定义
5319
- const IGNORED_FILES = (file, stats) => {
5320
- if (!stats?.isFile())
5321
- return false;
5322
- return (file.endsWith('.gitkeep') ||
5323
- file.endsWith('.DS_Store') ||
5324
- file.endsWith('.d.ts') || // 类型声明文件不需要处理
5325
- file.includes('node_modules') ||
5326
- file.includes('.git'));
5327
- };
5328
- // 并行处理配置
5329
- const CONCURRENT_LIMIT = 5; // 同时处理的文件数量限制
5330
- // 开发模式使用更高并发(默认 5,可根据 CPU 核心数调整)
5331
- const DEV_CONCURRENT_LIMIT = 5;
5332
- // 批量并行处理函数
5333
- async function batchProcess(items, processor, concurrency = CONCURRENT_LIMIT) {
5334
- // 将 items 分成多个批次,每批并发处理
5335
- for (let i = 0; i < items.length; i += concurrency) {
5336
- const batch = items.slice(i, i + concurrency);
5337
- await Promise.all(batch.map((item) => processor(item).catch((error) => {
5338
- console.error(`处理失败:`, error);
5339
- })));
5340
- }
5341
- }
5342
- // 路径转换缓存 - 避免重复计算
5343
- const pathCache = new Map();
5344
- function getOutputPath(inputPath) {
5345
- let cached = pathCache.get(inputPath);
5346
- if (!cached) {
5347
- cached = inputPath.replace(sourceDir, OUTPUT_DIR);
5348
- pathCache.set(inputPath, cached);
5349
- }
5350
- return cached;
5351
- }
5352
- // 清空路径缓存(在构建完成后调用)
5353
- function clearPathCache() {
5354
- pathCache.clear();
5355
- }
5356
- async function findIndependentPackages() {
5357
- const appJson = await fs.readJson(path.resolve(sourceDir, 'app.json'));
5358
- if (appJson.subpackages) {
5359
- independentPackages = appJson.subpackages
5360
- .filter(({ independent }) => independent)
5361
- .map(({ root }) => root);
5362
- }
5363
- }
5364
- const builtLibraries = [];
5365
- const bundledModules = new Map();
5366
- async function bundleModule(module, pkg) {
5367
- const bundled = bundledModules.get(pkg);
5368
- if (bundled?.has(module) || builtLibraries.some((library) => module.startsWith(library))) {
5369
- return false;
5370
- }
5371
- if (bundled) {
5372
- bundled.add(module);
5373
- }
5374
- else {
5375
- bundledModules.set(pkg, new Set([module]));
5376
- }
5377
- const pkInfo = await getPackageInfo(module);
5378
- if (pkInfo) {
5379
- const { packageJson: { peerDependencies }, } = pkInfo;
5380
- // 这里判断下,如果module在目标位置已存在,则直接返回true
5381
- const targetExists = await fs.pathExists(path.resolve(pkg.replace(sourceDir, OUTPUT_DIR), 'miniprogram_npm', module));
5382
- if (targetExists) {
5383
- return true;
5384
- }
5385
- const bundle = await rollup({
5386
- input: module,
5387
- external: peerDependencies ? Object.keys(peerDependencies) : undefined,
5388
- plugins: [
5389
- commonjs(),
5390
- replace({
5391
- preventAssignment: true,
5392
- values: {
5393
- 'process.env.NODE_ENV': JSON.stringify(NODE_ENV),
5394
- },
5395
- }),
5396
- resolve$1(),
5397
- __PROD__ && terser(terserOptions),
5398
- ].filter(Boolean),
5399
- });
5400
- await bundle.write({
5401
- exports: 'named',
5402
- file: `${pkg.replace(sourceDir, OUTPUT_DIR)}/miniprogram_npm/${module}/index.js`,
5403
- format: 'cjs',
5404
- });
5405
- return true;
5406
- }
5407
- else {
5408
- console.warn(`未找到 ${module} 的依赖信息`);
5409
- return false;
5410
- }
5411
- }
5412
- function traverseAST(ast, pkg, babelOnly = false) {
5413
- traverse$1(ast, {
5414
- CallExpression({ node }) {
5415
- if (!t__default.isIdentifier(node.callee) ||
5416
- node.callee.name !== 'require' ||
5417
- !t__default.isStringLiteral(node.arguments[0]) ||
5418
- node.arguments[0].value.startsWith('.') ||
5419
- (babelOnly && !node.arguments[0].value.startsWith('@babel/runtime'))) {
5420
- return;
5421
- }
5422
- const module = node.arguments[0].value;
5423
- let promise = bundleModule(module, pkg);
5424
- if (babelOnly) {
5425
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
5426
- // @ts-expect-error
5427
- promise = promise.then((valid) => {
5428
- if (!valid)
5429
- return;
5430
- return Promise.all(independentPackages.map((item) => {
5431
- const bundled = bundledModules.get(item);
5432
- if (bundled) {
5433
- bundled.add(module);
5434
- }
5435
- else {
5436
- bundledModules.set(item, new Set([module]));
5437
- }
5438
- return fs.copy(path.join(OUTPUT_DIR, 'miniprogram_npm', module), path.join(OUTPUT_DIR, item, 'miniprogram_npm', module));
5439
- }));
5440
- });
5441
- }
5442
- bundleJobs?.push(promise);
5443
- },
5444
- });
5445
- }
5446
- async function buildComponentLibrary(name) {
5447
- const pkInfo = await getPackageInfo(name);
5448
- if (pkInfo) {
5449
- const { rootPath, packageJson: { miniprogram }, } = pkInfo;
5450
- let source = '';
5451
- if (miniprogram) {
5452
- source = path.join(rootPath, miniprogram);
5453
- }
5454
- else {
5455
- try {
5456
- const dist = path.join(rootPath, 'miniprogram_dist');
5457
- const stats = await fs.stat(dist);
5458
- if (stats.isDirectory()) {
5459
- source = dist;
5460
- }
5461
- }
5462
- catch {
5463
- // Empty
5464
- }
5465
- }
5466
- if (!source)
5467
- return;
5468
- const destination = path.resolve(OUTPUT_DIR, 'miniprogram_npm', name);
5469
- builtLibraries.push(name);
5470
- // ✅ 检查目标位置是否已存在文件夹
5471
- const destinationExists = await fs.pathExists(destination);
5472
- if (destinationExists) {
5473
- return;
5474
- }
5475
- await fs.copy(source, destination);
5476
- // 递归获取所有 .js 文件并处理(替代 watcher,更简洁可靠)
5477
- const processJsFiles = async (dir) => {
5478
- const entries = await fs.readdir(dir, { withFileTypes: true });
5479
- const jsFiles = [];
5480
- for (const entry of entries) {
5481
- const fullPath = path.join(dir, entry.name);
5482
- if (entry.isDirectory()) {
5483
- await processJsFiles(fullPath);
5484
- }
5485
- else if (entry.isFile() && entry.name.endsWith('.js')) {
5486
- jsFiles.push(fullPath);
5487
- }
5488
- }
5489
- // 并行处理所有 .js 文件
5490
- await Promise.all(jsFiles.map(async (filePath) => {
5491
- try {
5492
- const result = await transformFileAsync(filePath, { ast: true, ...config });
5493
- if (result) {
5494
- traverseAST(result.ast, sourceDir, true);
5495
- const code = (__PROD__ ? (await minify(result.code, terserOptions)).code : result.code);
5496
- await fs.writeFile(filePath, code);
5497
- }
5498
- }
5499
- catch (error) {
5500
- console.error(`处理 ${filePath} 失败:`, getErrorMessage(error));
5501
- }
5502
- }));
5503
- };
5504
- await processJsFiles(destination);
5505
- // 复制到独立包
5506
- if (independentPackages.length > 0) {
5507
- await Promise.all(independentPackages.map(async (item) => {
5508
- const independentDestination = path.join(OUTPUT_DIR, item, 'miniprogram_npm', name);
5509
- const independentDestExists = await fs.pathExists(independentDestination);
5510
- if (!independentDestExists) {
5511
- return fs.copy(destination, independentDestination);
5512
- }
5513
- }));
5514
- }
5515
- }
5516
- else {
5517
- console.warn(`未找到 ${name} 的依赖信息`);
5518
- }
5519
- }
5520
- async function scanDependencies() {
5521
- try {
5522
- const { dependencies } = await fs.readJson('package.json');
5523
- if (dependencies) {
5524
- // 并行处理所有依赖,提高启动速度
5525
- const depNames = Object.keys(dependencies);
5526
- console.log(bold(green(`扫描到 ${depNames.length} 个依赖,开始并行处理...`)));
5527
- const startDepTime = Date.now();
5528
- // 使用批量并行处理依赖
5529
- await batchProcess(depNames, async (name) => {
5530
- await buildComponentLibrary(name);
5531
- }, 5); // 依赖构建限制为 5 个并发,避免过多资源占用
5532
- console.log(bold(green(`依赖处理完成,耗时:${Date.now() - startDepTime}ms`)));
5533
- }
5534
- }
5535
- catch (error) {
5536
- console.warn('读取 package.json 失败:', getErrorMessage(error));
5537
- }
5538
- }
5539
- // 缓存独立包路径的 normalize 结果
5540
- const normalizedPkgPaths = new Map();
5541
- async function dealScriptCode(filePath, result) {
5542
- const ast = result.ast;
5543
- let code = result.code;
5544
- // 使用缓存避免重复 path.normalize 计算
5545
- let pkg = independentPackages.find((item) => {
5546
- let normalized = normalizedPkgPaths.get(item);
5547
- if (!normalized) {
5548
- normalized = path.normalize(`${sourceDir}/${item}`);
5549
- normalizedPkgPaths.set(item, normalized);
5550
- }
5551
- return filePath.startsWith(normalized);
5552
- });
5553
- // The `src/` prefix is added to to distinguish `src` and `src/src`.
5554
- traverseAST(ast, pkg ? path.join(sourceDir, pkg) : sourceDir);
5555
- if (__PROD__) {
5556
- code = (await minify(code, terserOptions)).code;
5557
- }
5558
- return code;
5559
- }
5560
- async function processScript(filePath) {
5561
- try {
5562
- const result = await transformFileAsync(path.resolve(filePath), {
5563
- ast: true,
5564
- ...config,
5565
- });
5566
- if (result) {
5567
- const code = await dealScriptCode(filePath, result);
5568
- const destination = path.join(getOutputPath(filePath).replace(/\.ts$/, '.js'));
5569
- // 确保目录存在
5570
- await fs.ensureDir(path.dirname(destination));
5571
- // 直接写入,不需要先复制源文件
5572
- await fs.writeFile(destination, code);
5573
- }
5574
- }
5575
- catch (error) {
5576
- // 使用统一的编译错误处理(支持 code-frame 定位)
5577
- handleCompileError('', error, filePath);
5578
- if (__PROD__)
5579
- throw error;
5580
- // 开发模式:打印后继续,不中断整个构建
5581
- }
5582
- }
5583
- const cb = async (filePath, callbacks) => {
5584
- if (filePath.endsWith('.vue')) {
5585
- const t = performance.now();
5586
- try {
5587
- await transformVueToMiniProgram(filePath, OUTPUT_DIR, isPageComponent(filePath), async (generatedCode) => {
5588
- try {
5589
- // 先生成代码,再进行转换,这样可以更好地利用默认配置
5590
- const result = await transformAsync(generatedCode, {
5591
- filename: filePath.replace('.vue', '.js'),
5592
- ...config,
5593
- });
5594
- if (result) {
5595
- return dealScriptCode(filePath, result);
5596
- }
5597
- return `Failed to transformAsync ${filePath}`;
5598
- }
5599
- catch (error) {
5600
- // 使用统一的编译错误处理(支持 code-frame 定位)
5601
- handleCompileError('', error, filePath);
5602
- // 返回错误占位代码,保证输出文件存在,开发模式下不中断构建
5603
- return `console.error('Failed to compile ${filePath}: ${error.message?.replace(/'/g, "\\'")}');`;
5604
- }
5605
- });
5606
- }
5607
- catch (error) {
5608
- // transformer.ts 内部已调用 handleCompileError 输出带 code-frame 的错误信息
5609
- // 此处仅在生产模式下 rethrow,开发模式静默继续,不重复打印
5610
- if (__PROD__)
5611
- throw error;
5612
- return;
5613
- }
5614
- finally {
5615
- callbacks?.vueCb?.(performance.now() - t);
5616
- }
5617
- return;
5618
- }
5619
- // .d.ts 类型声明文件不需要输出,直接跳过
5620
- if (filePath.endsWith('.d.ts'))
5621
- return;
5622
- // copyOnly 模式:跳过 Babel、直接复制(.min.js 及用户配置的 copyOnly 规则)
5623
- if (isCopyOnly(filePath)) {
5624
- const t = performance.now();
5625
- const destinationPath = getOutputPath(filePath);
5626
- await fs.ensureDir(path.dirname(destinationPath));
5627
- await fs.copy(filePath, destinationPath);
5628
- callbacks?.othersCb?.(performance.now() - t);
5629
- return;
5630
- }
5631
- if (filePath.endsWith('.ts') || filePath.endsWith('.js')) {
5632
- const t = performance.now();
5633
- await processScript(filePath);
5634
- callbacks?.jsCb?.(performance.now() - t);
5635
- return;
5636
- }
5637
- const t = performance.now();
5638
- const destinationPath = path.join(getOutputPath(filePath));
5639
- await fs.copy(filePath, path.normalize(destinationPath));
5640
- callbacks?.othersCb?.(performance.now() - t);
5641
- };
5642
- async function dev() {
5643
- __PROD__ = false;
5644
- const t0 = Date.now();
5645
- // 复制polyfill文件
5646
- copyPolyfillFiles()
5647
- .then(() => {
5648
- console.log(bold(green(`[timing] copyPolyfillFiles: ${Date.now() - t0}ms`)));
5649
- return copyProjectConfigFile();
5650
- })
5651
- .then(() => {
5652
- console.log(bold(green(`[timing] copyProjectConfigFile: ${Date.now() - t0}ms`)));
5653
- return loadPagePaths();
5654
- })
5655
- .then(() => {
5656
- console.log(bold(green(`[timing] loadPagePaths: ${Date.now() - t0}ms`)));
5657
- return findIndependentPackages();
5658
- })
5659
- .then(() => {
5660
- console.log(bold(green(`[timing] findIndependentPackages: ${Date.now() - t0}ms`)));
5661
- return scanDependencies();
5662
- })
5663
- .then(() => {
5664
- console.log(bold(green(`[timing] scanDependencies: ${Date.now() - t0}ms`)));
5665
- // 用于跟踪正在处理的文件,避免重复处理
5666
- const processingFiles = new Set();
5667
- // 用于排队:编译期间又触发了 change 的文件
5668
- const pendingFiles = new Set();
5669
- // 用于收集初始扫描的文件,进行批量并行处理
5670
- const initialFiles = [];
5671
- let isInitialScan = true;
5672
- chokidar
5673
- .watch([sourceDir], {
5674
- awaitWriteFinish: { stabilityThreshold: 100, pollInterval: 50 },
5675
- ignored: IGNORED_FILES,
5676
- usePolling: false,
5677
- interval: 100,
5678
- })
5679
- .on('add', (filePath) => {
5680
- if (isInitialScan) {
5681
- // 初始扫描阶段,收集文件用于批量处理
5682
- initialFiles.push(filePath);
5683
- }
5684
- else {
5685
- // 运行时新增文件,立即处理
5686
- const promise = cb(filePath);
5687
- topLevelJobs?.push(promise);
5688
- }
5689
- })
5690
- .on('addDir', (dirPath) => {
5691
- // 新建目录时,在输出目录同步创建
5692
- const outputDir = getOutputPath(dirPath);
5693
- const promise = fs.ensureDir(outputDir);
5694
- topLevelJobs?.push(promise);
5695
- })
5696
- .on('unlink', async (filePath) => {
5697
- // 文件删除时同步删除目标文件
5698
- const outputPath = getOutputPath(filePath);
5699
- const basePath = outputPath.replace(/\.vue$/, '');
5700
- const filesToDelete = filePath.endsWith('.vue')
5701
- ? [`${basePath}.js`, `${basePath}.wxml`, `${basePath}.wxss`, `${basePath}.json`]
5702
- : [path.join(outputPath)];
5703
- try {
5704
- await Promise.all(filesToDelete.map((f) => fs.remove(f)));
5705
- // 同步移除 pathCache 中的缓存
5706
- pathCache.delete(filePath);
5707
- }
5708
- catch (error) {
5709
- console.warn(`删除目标文件失败:${filesToDelete.join(', ')}`, getErrorMessage(error));
5710
- }
5711
- })
5712
- .on('unlinkDir', async (dirPath) => {
5713
- // 目录删除时同步删除输出目录
5714
- const outputDir = getOutputPath(dirPath);
5715
- try {
5716
- await fs.remove(outputDir);
5717
- }
5718
- catch (error) {
5719
- console.warn(`删除目标目录失败:${outputDir}`, getErrorMessage(error));
5720
- }
5721
- })
5722
- .on('change', async (filePath) => {
5723
- // 如果文件正在处理中,标记需要重新处理(排队一次),不直接丢弃
5724
- if (processingFiles.has(filePath)) {
5725
- pendingFiles.add(filePath);
5726
- return;
5727
- }
5728
- // 使用循环代替递归,避免调用栈过深
5729
- const runCompile = async (initialPath) => {
5730
- let targetPath = initialPath;
5731
- while (targetPath) {
5732
- processingFiles.add(targetPath);
5733
- const date = Date.now();
5734
- console.log(bold(green(`文件已修改:${targetPath}`)));
5735
- let shouldContinue = false;
5736
- try {
5737
- await cb(targetPath);
5738
- console.log(bold(green(`文件已处理完毕,耗时:${Date.now() - date}ms`)));
5739
- }
5740
- finally {
5741
- processingFiles.delete(targetPath);
5742
- // 如果编译期间又有新的保存,继续循环处理
5743
- if (pendingFiles.has(targetPath)) {
5744
- pendingFiles.delete(targetPath);
5745
- shouldContinue = true;
5746
- }
5747
- }
5748
- if (!shouldContinue) {
5749
- break;
5750
- }
5751
- }
5752
- };
5753
- await runCompile(filePath);
5754
- })
5755
- .on('ready', async () => {
5756
- // 标记初始扫描完成
5757
- isInitialScan = false;
5758
- console.log(bold(green(`[timing] chokidar ready(文件扫描完成): ${Date.now() - t0}ms,共 ${initialFiles.length} 个文件`)));
5759
- // 统计文件类型
5760
- const vueFiles = initialFiles.filter((f) => f.endsWith('.vue'));
5761
- const tsFiles = initialFiles.filter((f) => f.endsWith('.ts') || f.endsWith('.js'));
5762
- const otherFiles = initialFiles.filter((f) => !f.endsWith('.vue') && !f.endsWith('.ts') && !f.endsWith('.js'));
5763
- console.log(bold(green(`[timing] 文件分布:vue=${vueFiles.length}, ts/js=${tsFiles.length}, 其他=${otherFiles.length}`)));
5764
- // 文件处理器(带计时)
5765
- let vueTime = 0, tsTime = 0, otherTime = 0;
5766
- const fileProcessor = async (filePath) => {
5767
- await cb(filePath, {
5768
- vueCb: (elapsed) => {
5769
- vueTime += elapsed;
5770
- },
5771
- jsCb: (elapsed) => {
5772
- tsTime += elapsed;
5773
- },
5774
- othersCb: (elapsed) => {
5775
- otherTime += elapsed;
5776
- },
5777
- });
5778
- };
5779
- // 使用批量并行处理初始文件(开发模式使用更高并发)
5780
- if (initialFiles.length > 0) {
5781
- console.log(bold(green(`开始并行处理 ${initialFiles.length} 个文件(并发=${DEV_CONCURRENT_LIMIT})...`)));
5782
- const processStartTime = Date.now();
5783
- await batchProcess(initialFiles, fileProcessor, DEV_CONCURRENT_LIMIT);
5784
- console.log(bold(green(`[timing] 并行处理完成:${Date.now() - processStartTime}ms(总耗时 ${Date.now() - t0}ms)`)));
5785
- console.log(bold(green(`[timing] 耗时分布:vue=${vueTime}ms, ts/js=${tsTime}ms, 其他=${otherTime}ms`)));
5786
- }
5787
- await Promise.all(bundleJobs);
5788
- console.log(bold(green(`启动完成,耗时:${Date.now() - startTime}ms`)));
5789
- console.log(bold(green('监听文件变化中...')));
5790
- // Release memory.
5791
- topLevelJobs = null;
5792
- bundleJobs = null;
5793
- // 开发模式下不清空缓存,保持性能优势
5794
- });
5795
- });
5796
- }
5797
- async function prod(options) {
5798
- __PROD__ = true;
5799
- return new Promise((resolve, reject) => {
5800
- fs.remove(OUTPUT_DIR)
5801
- .then(() => copyPolyfillFiles())
5802
- .then(() => copyProjectConfigFile())
5803
- .then(() => loadPagePaths())
5804
- .then(() => findIndependentPackages())
5805
- .then(() => scanDependencies())
5806
- .then(() => {
5807
- const initialFiles = [];
5808
- let isInitialScan = true;
5809
- const watcher = chokidar.watch([sourceDir], {
5810
- ignored: IGNORED_FILES,
5811
- });
5812
- watcher.on('add', (filePath) => {
5813
- if (isInitialScan) {
5814
- initialFiles.push(filePath);
5815
- }
5816
- else {
5817
- const promise = cb(filePath);
5818
- topLevelJobs.push(promise);
5819
- }
5820
- });
5821
- watcher.on('ready', async () => {
5822
- isInitialScan = false;
5823
- // 文件处理器
5824
- const fileProcessor = async (filePath) => {
5825
- await cb(filePath);
5826
- };
5827
- // 使用批量并行处理初始文件(生产环境使用更高的并发数)
5828
- if (initialFiles.length > 0) {
5829
- console.log(bold(green(`开始并行处理 ${initialFiles.length} 个文件...`)));
5830
- const processStartTime = Date.now();
5831
- await batchProcess(initialFiles, fileProcessor, CONCURRENT_LIMIT);
5832
- console.log(bold(green(`并行处理完成,耗时:${Date.now() - processStartTime}ms`)));
5833
- }
5834
- const promise = watcher.close();
5835
- topLevelJobs.push(promise);
5836
- await Promise.all(topLevelJobs);
5837
- await Promise.all(bundleJobs);
5838
- // Release memory and clear cache.
5839
- topLevelJobs = null;
5840
- bundleJobs = null;
5841
- clearPathCache();
5842
- normalizedPkgPaths.clear();
5843
- if (options.upload) {
5844
- const { default: ci } = await import('miniprogram-ci');
5845
- const project = new ci.Project({
5846
- appid: userConfig.wx.appid,
5847
- type: 'miniProgram',
5848
- projectPath: OUTPUT_DIR,
5849
- privateKeyPath: userConfig.wx.privateKeyPath,
5850
- ignores: [],
5851
- });
5852
- console.log(bold(green('上传中...')));
5853
- // 读取位于 projectPath 下的 project.config.json
5854
- const uploadResult = await ci.upload({
5855
- project,
5856
- version: userConfig.wx.version,
5857
- desc: userConfig.wx.description,
5858
- setting: {
5859
- useProjectConfig: true,
5860
- },
5861
- onProgressUpdate: void 0,
5862
- });
5863
- console.log(bold(green(`上传结果:`)), uploadResult, '当前编译环境:', NODE_ENV);
5864
- }
5865
- resolve();
5866
- });
5867
- })
5868
- .catch(reject);
5869
- });
5870
- }
5871
-
5872
- export { dev, prod };
5208
+ export { OUTPUT_DIR as O, copyProjectConfigFile as a, config as b, copyPolyfillFiles as c, traverse$1 as d, getErrorMessage as g, handleCompileError as h, transformVueToMiniProgram as t, userConfig as u };