versacompiler 2.4.1 → 2.5.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.
- package/README.md +722 -722
- package/dist/compiler/compile-worker-pool.js +96 -0
- package/dist/compiler/compile-worker-thread.cjs +72 -0
- package/dist/compiler/compile.js +81 -2
- package/dist/compiler/integrity-validator.js +1 -1
- package/dist/compiler/module-resolution-optimizer.js +23 -20
- package/dist/compiler/performance-monitor.js +61 -61
- package/dist/compiler/pipeline/build-pipeline.js +127 -0
- package/dist/compiler/pipeline/core-plugins.js +218 -0
- package/dist/compiler/pipeline/module-graph.js +63 -0
- package/dist/compiler/pipeline/plugin-driver.js +87 -0
- package/dist/compiler/pipeline/types.js +2 -0
- package/dist/compiler/transforms.js +222 -16
- package/dist/compiler/typescript-manager.js +3 -1
- package/dist/compiler/typescript-sync-validator.js +33 -31
- package/dist/compiler/typescript-worker-thread.cjs +482 -475
- package/dist/compiler/vuejs.js +32 -32
- package/dist/config.js +2 -0
- package/dist/hrm/VueHRM.js +359 -359
- package/dist/hrm/errorScreen.js +83 -83
- package/dist/hrm/getInstanciaVue.js +313 -313
- package/dist/hrm/initHRM.js +628 -586
- package/dist/main.js +2 -1
- package/dist/servicios/browserSync.js +8 -2
- package/dist/servicios/file-watcher.js +48 -6
- package/dist/servicios/readConfig.js +129 -54
- package/dist/servicios/versacompile.config.types.js +2 -0
- package/dist/utils/module-resolver.js +74 -40
- package/dist/utils/vue-types-setup.js +248 -248
- package/dist/wrappers/eslint-node.js +3 -1
- package/dist/wrappers/oxlint-node.js +3 -1
- package/package.json +72 -53
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import * as os from 'node:os';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
import * as process from 'node:process';
|
|
4
|
+
import { Worker } from 'node:worker_threads';
|
|
5
|
+
export class CompileWorkerPool {
|
|
6
|
+
static instance;
|
|
7
|
+
workers = [];
|
|
8
|
+
pending = new Map();
|
|
9
|
+
queue = [];
|
|
10
|
+
poolSize;
|
|
11
|
+
workerPath;
|
|
12
|
+
TASK_TIMEOUT = 60000;
|
|
13
|
+
constructor() {
|
|
14
|
+
const cpuCount = os.cpus().length;
|
|
15
|
+
const configuredMax = parseInt(process.env.COMPILE_MAX_WORKERS || '2', 10);
|
|
16
|
+
this.poolSize = Math.min(configuredMax, Math.max(1, cpuCount - 1));
|
|
17
|
+
this.workerPath = path.join(process.env.PATH_PROY || path.join(process.cwd(), 'src'), 'compiler', 'compile-worker-thread.cjs');
|
|
18
|
+
this.initWorkers();
|
|
19
|
+
}
|
|
20
|
+
static getInstance() {
|
|
21
|
+
if (!CompileWorkerPool.instance) {
|
|
22
|
+
CompileWorkerPool.instance = new CompileWorkerPool();
|
|
23
|
+
}
|
|
24
|
+
return CompileWorkerPool.instance;
|
|
25
|
+
}
|
|
26
|
+
initWorkers() {
|
|
27
|
+
for (let i = 0; i < this.poolSize; i++) {
|
|
28
|
+
const worker = new Worker(this.workerPath, {
|
|
29
|
+
env: process.env,
|
|
30
|
+
});
|
|
31
|
+
const poolWorker = { worker, busy: false };
|
|
32
|
+
worker.on('message', (response) => {
|
|
33
|
+
const pending = this.pending.get(response.id);
|
|
34
|
+
if (!pending)
|
|
35
|
+
return;
|
|
36
|
+
clearTimeout(pending.timeout);
|
|
37
|
+
this.pending.delete(response.id);
|
|
38
|
+
poolWorker.busy = false;
|
|
39
|
+
if (!response.success) {
|
|
40
|
+
pending.reject(new Error(response.error || 'Worker task failed'));
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
pending.resolve(response.data);
|
|
44
|
+
}
|
|
45
|
+
this.drainQueue();
|
|
46
|
+
});
|
|
47
|
+
worker.on('error', error => {
|
|
48
|
+
poolWorker.busy = false;
|
|
49
|
+
for (const [id, pending] of this.pending) {
|
|
50
|
+
clearTimeout(pending.timeout);
|
|
51
|
+
const normalized = error instanceof Error
|
|
52
|
+
? error
|
|
53
|
+
: new Error(String(error));
|
|
54
|
+
pending.reject(normalized);
|
|
55
|
+
this.pending.delete(id);
|
|
56
|
+
}
|
|
57
|
+
this.drainQueue();
|
|
58
|
+
});
|
|
59
|
+
this.workers.push(poolWorker);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
async runTask(type, payload) {
|
|
63
|
+
const id = `${type}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
64
|
+
const message = { id, type, payload };
|
|
65
|
+
return new Promise((resolve, reject) => {
|
|
66
|
+
const timeout = setTimeout(() => {
|
|
67
|
+
this.pending.delete(id);
|
|
68
|
+
reject(new Error(`Worker timeout: ${type}`));
|
|
69
|
+
}, this.TASK_TIMEOUT);
|
|
70
|
+
this.pending.set(id, { resolve, reject, timeout });
|
|
71
|
+
const worker = this.getAvailableWorker();
|
|
72
|
+
if (worker) {
|
|
73
|
+
worker.busy = true;
|
|
74
|
+
worker.worker.postMessage(message);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
this.queue.push(message);
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
getAvailableWorker() {
|
|
81
|
+
return this.workers.find(worker => !worker.busy) || null;
|
|
82
|
+
}
|
|
83
|
+
drainQueue() {
|
|
84
|
+
if (this.queue.length === 0)
|
|
85
|
+
return;
|
|
86
|
+
const worker = this.getAvailableWorker();
|
|
87
|
+
if (!worker)
|
|
88
|
+
return;
|
|
89
|
+
const message = this.queue.shift();
|
|
90
|
+
if (!message)
|
|
91
|
+
return;
|
|
92
|
+
worker.busy = true;
|
|
93
|
+
worker.worker.postMessage(message);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=compile-worker-pool.js.map
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
const { parentPort } = require('node:worker_threads');
|
|
2
|
+
|
|
3
|
+
let preCompileVue;
|
|
4
|
+
let preCompileTS;
|
|
5
|
+
let minifyJS;
|
|
6
|
+
|
|
7
|
+
async function loadVue() {
|
|
8
|
+
if (!preCompileVue) {
|
|
9
|
+
const mod = await import('./vuejs.js');
|
|
10
|
+
preCompileVue = mod.preCompileVue;
|
|
11
|
+
}
|
|
12
|
+
return preCompileVue;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async function loadTypeScript() {
|
|
16
|
+
if (!preCompileTS) {
|
|
17
|
+
const mod = await import('./typescript-manager.js');
|
|
18
|
+
preCompileTS = mod.preCompileTS;
|
|
19
|
+
}
|
|
20
|
+
return preCompileTS;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async function loadMinify() {
|
|
24
|
+
if (!minifyJS) {
|
|
25
|
+
const mod = await import('./minify.js');
|
|
26
|
+
minifyJS = mod.minifyJS;
|
|
27
|
+
}
|
|
28
|
+
return minifyJS;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
parentPort.on('message', async message => {
|
|
32
|
+
const { id, type, payload } = message;
|
|
33
|
+
try {
|
|
34
|
+
if (type === 'vue') {
|
|
35
|
+
const compileVue = await loadVue();
|
|
36
|
+
const result = await compileVue(
|
|
37
|
+
payload.source,
|
|
38
|
+
payload.fileName,
|
|
39
|
+
payload.isProd === true,
|
|
40
|
+
);
|
|
41
|
+
parentPort.postMessage({ id, success: true, data: result });
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
if (type === 'ts') {
|
|
45
|
+
const compileTS = await loadTypeScript();
|
|
46
|
+
const result = await compileTS(
|
|
47
|
+
payload.source,
|
|
48
|
+
payload.fileName,
|
|
49
|
+
payload.scriptInfo,
|
|
50
|
+
);
|
|
51
|
+
parentPort.postMessage({ id, success: true, data: result });
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
if (type === 'minify') {
|
|
55
|
+
const minify = await loadMinify();
|
|
56
|
+
const result = await minify(payload.source, payload.fileName, true);
|
|
57
|
+
parentPort.postMessage({ id, success: true, data: result });
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
parentPort.postMessage({
|
|
61
|
+
id,
|
|
62
|
+
success: false,
|
|
63
|
+
error: `Tipo de tarea desconocido: ${type}`,
|
|
64
|
+
});
|
|
65
|
+
} catch (error) {
|
|
66
|
+
parentPort.postMessage({
|
|
67
|
+
id,
|
|
68
|
+
success: false,
|
|
69
|
+
error: error instanceof Error ? error.message : String(error),
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
});
|
package/dist/compiler/compile.js
CHANGED
|
@@ -6,9 +6,12 @@ import * as process from 'node:process';
|
|
|
6
6
|
const { argv, cwd, env } = process;
|
|
7
7
|
// Lazy loading optimizations - Only import lightweight modules synchronously
|
|
8
8
|
import { logger, setProgressManagerGetter } from '../servicios/logger.js';
|
|
9
|
+
import { getLoadedConfig } from '../servicios/readConfig.js';
|
|
9
10
|
import { promptUser } from '../utils/promptUser.js';
|
|
10
11
|
import { showTimingForHumans } from '../utils/utils.js';
|
|
11
12
|
import { integrityValidator } from './integrity-validator.js';
|
|
13
|
+
import { BuildPipeline } from './pipeline/build-pipeline.js';
|
|
14
|
+
import { createCorePlugins } from './pipeline/core-plugins.js';
|
|
12
15
|
// Configurar el getter del ProgressManager para el logger
|
|
13
16
|
setProgressManagerGetter(() => ProgressManager.getInstance());
|
|
14
17
|
/**
|
|
@@ -29,6 +32,7 @@ let generateTailwindCSS;
|
|
|
29
32
|
let estandarizaCode;
|
|
30
33
|
let preCompileTS;
|
|
31
34
|
let preCompileVue;
|
|
35
|
+
let pipelineInstance = null;
|
|
32
36
|
// 🚀 Importar optimizador de transformaciones
|
|
33
37
|
let TransformOptimizer;
|
|
34
38
|
// 🚀 Importar optimizador de resolución de módulos
|
|
@@ -544,6 +548,16 @@ class SmartCompilationCache {
|
|
|
544
548
|
catch {
|
|
545
549
|
// Ignorar si no existe package-lock.json
|
|
546
550
|
}
|
|
551
|
+
// 2b. Hash de pnpm-lock.yaml si existe (pnpm)
|
|
552
|
+
try {
|
|
553
|
+
const pnpmLockPath = path.join(cwd(), 'pnpm-lock.yaml');
|
|
554
|
+
const pnpmLockContent = await readFile(pnpmLockPath, 'utf8');
|
|
555
|
+
hash.update(`pnpm-lock:${pnpmLockContent.length}`);
|
|
556
|
+
hash.update(pnpmLockContent);
|
|
557
|
+
}
|
|
558
|
+
catch {
|
|
559
|
+
// Ignorar si no existe pnpm-lock.yaml
|
|
560
|
+
}
|
|
547
561
|
// 3. ✨ NUEVO: Hash de timestamps críticos de node_modules
|
|
548
562
|
try {
|
|
549
563
|
const nodeModulesPath = path.join(cwd(), 'node_modules');
|
|
@@ -609,7 +623,7 @@ class SmartCompilationCache {
|
|
|
609
623
|
return false;
|
|
610
624
|
try {
|
|
611
625
|
// Ejecutar todas las verificaciones independientes en paralelo
|
|
612
|
-
const [currentContentHash, currentDependencyHash, fileStat, _outputStat] = await Promise.all([
|
|
626
|
+
const [currentContentHash, currentDependencyHash, fileStat, _outputStat,] = await Promise.all([
|
|
613
627
|
this.generateContentHash(filePath),
|
|
614
628
|
this.generateDependencyHash(),
|
|
615
629
|
stat(filePath),
|
|
@@ -1406,7 +1420,8 @@ async function _displaySingleLinterError(error, filePath) {
|
|
|
1406
1420
|
}
|
|
1407
1421
|
else {
|
|
1408
1422
|
// Líneas de contexto
|
|
1409
|
-
logger.info(chalkLib.blue(` ${prefix} │ `) +
|
|
1423
|
+
logger.info(chalkLib.blue(` ${prefix} │ `) +
|
|
1424
|
+
chalkLib.gray(currentLine));
|
|
1410
1425
|
}
|
|
1411
1426
|
}
|
|
1412
1427
|
logger.info(chalkLib.blue(' ╰────'));
|
|
@@ -1558,6 +1573,67 @@ class WatchModeOptimizer {
|
|
|
1558
1573
|
this.fileSystemCache.clear();
|
|
1559
1574
|
}
|
|
1560
1575
|
}
|
|
1576
|
+
function getBuildPipeline() {
|
|
1577
|
+
if (!pipelineInstance) {
|
|
1578
|
+
const basePlugins = createCorePlugins();
|
|
1579
|
+
const config = getLoadedConfig();
|
|
1580
|
+
const userPlugins = normalizeUserPlugins(config?.plugins);
|
|
1581
|
+
pipelineInstance = new BuildPipeline([...basePlugins, ...userPlugins]);
|
|
1582
|
+
}
|
|
1583
|
+
return pipelineInstance;
|
|
1584
|
+
}
|
|
1585
|
+
function normalizeUserPlugins(plugins) {
|
|
1586
|
+
if (!plugins || !Array.isArray(plugins))
|
|
1587
|
+
return [];
|
|
1588
|
+
return plugins.filter((plugin) => {
|
|
1589
|
+
if (!plugin || typeof plugin !== 'object')
|
|
1590
|
+
return false;
|
|
1591
|
+
const candidate = plugin;
|
|
1592
|
+
if (!candidate.name || typeof candidate.name !== 'string')
|
|
1593
|
+
return false;
|
|
1594
|
+
return Boolean(candidate.onResolve ||
|
|
1595
|
+
candidate.onLoad ||
|
|
1596
|
+
candidate.onTransform ||
|
|
1597
|
+
candidate.onHotUpdate ||
|
|
1598
|
+
candidate.onEnd);
|
|
1599
|
+
});
|
|
1600
|
+
}
|
|
1601
|
+
export function getPipelineModuleGraph() {
|
|
1602
|
+
if (env.PIPELINE_V2 === 'false')
|
|
1603
|
+
return null;
|
|
1604
|
+
return getBuildPipeline().getModuleGraph();
|
|
1605
|
+
}
|
|
1606
|
+
export async function runPipelineHotUpdate(filePath, type) {
|
|
1607
|
+
if (env.PIPELINE_V2 === 'false') {
|
|
1608
|
+
return { reload: 'none' };
|
|
1609
|
+
}
|
|
1610
|
+
return getBuildPipeline().hotUpdate({ path: filePath, type });
|
|
1611
|
+
}
|
|
1612
|
+
async function compileWithPipeline(inPath, outPath, mode = 'individual') {
|
|
1613
|
+
const pipeline = getBuildPipeline();
|
|
1614
|
+
const result = await pipeline.compileFile(inPath);
|
|
1615
|
+
if (result.errors.length > 0) {
|
|
1616
|
+
for (const message of result.errors) {
|
|
1617
|
+
await handleCompilationError(new Error(message), inPath, 'pipeline', mode, env.VERBOSE === 'true');
|
|
1618
|
+
}
|
|
1619
|
+
throw new Error(result.errors[0]);
|
|
1620
|
+
}
|
|
1621
|
+
if (!result.code || result.code.trim().length === 0) {
|
|
1622
|
+
await handleCompilationError(new Error('El código compilado está vacío.'), inPath, 'pipeline', mode, env.VERBOSE === 'true');
|
|
1623
|
+
throw new Error('El código compilado está vacío.');
|
|
1624
|
+
}
|
|
1625
|
+
const destinationDir = path.dirname(outPath);
|
|
1626
|
+
await mkdir(destinationDir, { recursive: true });
|
|
1627
|
+
await writeFile(outPath, result.code, 'utf-8');
|
|
1628
|
+
if (result.dependencies.length > 0) {
|
|
1629
|
+
smartCache.registerDependencies(inPath, result.dependencies);
|
|
1630
|
+
}
|
|
1631
|
+
registerCompilationSuccess(inPath, 'pipeline');
|
|
1632
|
+
return {
|
|
1633
|
+
error: null,
|
|
1634
|
+
action: 'extension',
|
|
1635
|
+
};
|
|
1636
|
+
}
|
|
1561
1637
|
async function compileJS(inPath, outPath, mode = 'individual') {
|
|
1562
1638
|
const timings = {};
|
|
1563
1639
|
// Si la ruta ya es absoluta, no la resolvamos de nuevo
|
|
@@ -1565,6 +1641,9 @@ async function compileJS(inPath, outPath, mode = 'individual') {
|
|
|
1565
1641
|
? normalizeRuta(inPath)
|
|
1566
1642
|
: normalizeRuta(path.resolve(inPath)); // 🚀 Usar OptimizedModuleManager para carga optimizada
|
|
1567
1643
|
const moduleManager = OptimizedModuleManager.getInstance();
|
|
1644
|
+
if (env.PIPELINE_V2 !== 'false') {
|
|
1645
|
+
return compileWithPipeline(inPath, outPath, mode);
|
|
1646
|
+
}
|
|
1568
1647
|
// Timing de lectura
|
|
1569
1648
|
let start = Date.now();
|
|
1570
1649
|
const extension = path.extname(inPath); // Asegurar que el parser esté cargado
|
|
@@ -48,7 +48,7 @@ export class IntegrityValidator {
|
|
|
48
48
|
// Revisar cache
|
|
49
49
|
const cacheKey = this.getCacheKey(context, processed);
|
|
50
50
|
const cached = this.cache.get(cacheKey);
|
|
51
|
-
if (cached &&
|
|
51
|
+
if (cached && Date.now() - cached.timestamp < this.CACHE_TTL) {
|
|
52
52
|
this.stats.cacheHits++;
|
|
53
53
|
if (options.verbose) {
|
|
54
54
|
logger.info(`[IntegrityValidator] Cache hit for ${context}`);
|
|
@@ -14,6 +14,7 @@ import { dirname, join, relative } from 'node:path';
|
|
|
14
14
|
import { cwd, env } from 'node:process';
|
|
15
15
|
import { logger } from '../servicios/logger.js';
|
|
16
16
|
import { EXCLUDED_MODULES } from '../utils/excluded-modules.js';
|
|
17
|
+
import { parseModuleSpecifier, resolveExportValue, } from '../utils/module-resolver.js';
|
|
17
18
|
/**
|
|
18
19
|
* Sistema de optimización de resolución de módulos
|
|
19
20
|
* Implementa indexación, caché y búsquedas O(1)
|
|
@@ -122,7 +123,7 @@ export class ModuleResolutionOptimizer {
|
|
|
122
123
|
for (const entry of entries) {
|
|
123
124
|
const modulePath = join(nodeModulesPath, entry);
|
|
124
125
|
try {
|
|
125
|
-
if (entry.startsWith('/dist
|
|
126
|
+
if (entry.startsWith('/dist')) {
|
|
126
127
|
// Scoped packages
|
|
127
128
|
const scopedModules = readdirSync(modulePath);
|
|
128
129
|
this.metrics.filesystemAccess++;
|
|
@@ -207,10 +208,7 @@ export class ModuleResolutionOptimizer {
|
|
|
207
208
|
entryPoint = dotExport;
|
|
208
209
|
}
|
|
209
210
|
else if (typeof dotExport === 'object') {
|
|
210
|
-
entryPoint =
|
|
211
|
-
dotExport.import ||
|
|
212
|
-
dotExport.browser ||
|
|
213
|
-
dotExport.default;
|
|
211
|
+
entryPoint = resolveExportValue(dotExport);
|
|
214
212
|
}
|
|
215
213
|
}
|
|
216
214
|
}
|
|
@@ -420,7 +418,9 @@ export class ModuleResolutionOptimizer {
|
|
|
420
418
|
this.aliasIndex = [];
|
|
421
419
|
// Convertir alias a índice con prioridad
|
|
422
420
|
for (const [alias, target] of Object.entries(pathAlias)) {
|
|
423
|
-
|
|
421
|
+
// Quitar solo el '*' final para conservar el separador '/'
|
|
422
|
+
// Ejemplo: '@/*' → '@/', así '@vueuse/core' no hace match pero '@/foo' sí
|
|
423
|
+
const pattern = alias.replace('*', '');
|
|
424
424
|
const priority = pattern.length; // Patrones más largos tienen prioridad
|
|
425
425
|
// El regex debe coincidir con el patrón al inicio, seguido de cualquier cosa o fin de cadena
|
|
426
426
|
// Por ejemplo, para "@/" debe coincidir con "@/cualquier-cosa" o solo "@/"
|
|
@@ -453,6 +453,7 @@ export class ModuleResolutionOptimizer {
|
|
|
453
453
|
path: null,
|
|
454
454
|
cached: false,
|
|
455
455
|
resolveTime: performance.now() - startTime,
|
|
456
|
+
excluded: true,
|
|
456
457
|
};
|
|
457
458
|
}
|
|
458
459
|
// Crear clave de caché
|
|
@@ -472,13 +473,16 @@ export class ModuleResolutionOptimizer {
|
|
|
472
473
|
// Resolver módulo
|
|
473
474
|
let resolvedPath = null;
|
|
474
475
|
try {
|
|
475
|
-
// 1.
|
|
476
|
-
|
|
476
|
+
// 1. Parse specifier to correctly handle scoped packages
|
|
477
|
+
const { packageName, subPath } = parseModuleSpecifier(moduleName);
|
|
478
|
+
if (subPath) {
|
|
479
|
+
// Has a real subpath (e.g. 'vue/dist/x' or '@scope/pkg/sub')
|
|
477
480
|
resolvedPath = await this.resolveSubPath(moduleName);
|
|
478
481
|
}
|
|
479
482
|
else {
|
|
483
|
+
// Direct package (e.g. 'vue' or '@vueuse/core')
|
|
480
484
|
// 2. Búsqueda O(1) en el índice
|
|
481
|
-
resolvedPath = this.resolveFromIndex(
|
|
485
|
+
resolvedPath = this.resolveFromIndex(packageName);
|
|
482
486
|
}
|
|
483
487
|
// 3. Si no se encuentra en índice, intentar resolución tradicional
|
|
484
488
|
if (!resolvedPath) {
|
|
@@ -521,8 +525,7 @@ export class ModuleResolutionOptimizer {
|
|
|
521
525
|
* Resuelve subpaths de módulos (ej: 'vue/dist/vue.esm-bundler')
|
|
522
526
|
*/
|
|
523
527
|
async resolveSubPath(moduleName) {
|
|
524
|
-
const
|
|
525
|
-
const subPath = subPathParts.join('/');
|
|
528
|
+
const { packageName, subPath } = parseModuleSpecifier(moduleName);
|
|
526
529
|
if (!packageName) {
|
|
527
530
|
return null;
|
|
528
531
|
}
|
|
@@ -531,19 +534,19 @@ export class ModuleResolutionOptimizer {
|
|
|
531
534
|
if (!moduleInfo) {
|
|
532
535
|
return null;
|
|
533
536
|
}
|
|
537
|
+
// If no subPath, resolve as direct package
|
|
538
|
+
if (!subPath) {
|
|
539
|
+
const entryPoint = moduleInfo.optimizedEntry || moduleInfo.entryPoint;
|
|
540
|
+
return join(moduleInfo.fullPath, entryPoint);
|
|
541
|
+
}
|
|
534
542
|
// Verificar exports field para subpaths
|
|
535
543
|
if (moduleInfo.hasExports && moduleInfo.packageJson.exports) {
|
|
536
544
|
const exportKey = `./${subPath}`;
|
|
537
545
|
const exportPath = moduleInfo.packageJson.exports[exportKey];
|
|
538
546
|
if (exportPath) {
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
else if (typeof exportPath === 'object') {
|
|
543
|
-
const importPath = exportPath.import || exportPath.default;
|
|
544
|
-
if (typeof importPath === 'string') {
|
|
545
|
-
return join(moduleInfo.fullPath, importPath);
|
|
546
|
-
}
|
|
547
|
+
const resolved = resolveExportValue(exportPath);
|
|
548
|
+
if (resolved) {
|
|
549
|
+
return join(moduleInfo.fullPath, resolved);
|
|
547
550
|
}
|
|
548
551
|
}
|
|
549
552
|
}
|
|
@@ -872,7 +875,7 @@ export class ModuleResolutionOptimizer {
|
|
|
872
875
|
export async function getOptimizedModulePath(moduleName, fromFile) {
|
|
873
876
|
const optimizer = ModuleResolutionOptimizer.getInstance();
|
|
874
877
|
const result = await optimizer.resolveModule(moduleName, fromFile);
|
|
875
|
-
return result.path;
|
|
878
|
+
return { path: result.path, excluded: result.excluded === true };
|
|
876
879
|
}
|
|
877
880
|
export function getOptimizedAliasPath(path) {
|
|
878
881
|
const optimizer = ModuleResolutionOptimizer.getInstance();
|
|
@@ -85,67 +85,67 @@ export class PerformanceMonitor {
|
|
|
85
85
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
86
86
|
return (parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]);
|
|
87
87
|
};
|
|
88
|
-
const report = `
|
|
89
|
-
🚀 VERSACOMPILER PERFORMANCE REPORT
|
|
90
|
-
=====================================
|
|
91
|
-
|
|
92
|
-
📊 RESUMEN GENERAL
|
|
93
|
-
Hit Rate Total: ${stats.summary.overallHitRate}%
|
|
94
|
-
Cache Hits: ${stats.summary.totalCacheHits}
|
|
95
|
-
Cache Misses: ${stats.summary.totalCacheMisses}
|
|
96
|
-
Memoria Total: ${formatBytes(stats.summary.totalMemoryUsage)}
|
|
97
|
-
Entradas Cache: ${stats.summary.totalCacheEntries}
|
|
98
|
-
|
|
99
|
-
🎯 VUE HMR CACHE
|
|
100
|
-
Size: ${stats.vueHMRCache.size}/${stats.vueHMRCache.maxSize}
|
|
101
|
-
TTL: ${Math.round(stats.vueHMRCache.ttl / 1000 / 60)}min
|
|
102
|
-
|
|
103
|
-
📝 PARSER AST CACHE
|
|
104
|
-
Hit Rate: ${stats.parserCache.hitRate}%
|
|
105
|
-
Cache Hits: ${stats.parserCache.cacheHits}
|
|
106
|
-
Cache Misses: ${stats.parserCache.cacheMisses}
|
|
107
|
-
Size: ${stats.parserCache.cacheSize}/${stats.parserCache.maxCacheSize}
|
|
108
|
-
Memoria: ${formatBytes(stats.parserCache.memoryUsage)}/${formatBytes(stats.parserCache.maxMemoryUsage)}
|
|
109
|
-
|
|
110
|
-
📖 FILE CONTENT CACHE
|
|
111
|
-
Hit Rate: ${stats.fileContentCache.hitRate}%
|
|
112
|
-
Cache Hits: ${stats.fileContentCache.cacheHits}
|
|
113
|
-
Cache Misses: ${stats.fileContentCache.cacheMisses}
|
|
114
|
-
Size: ${stats.fileContentCache.cacheSize}/${stats.fileContentCache.maxCacheSize}
|
|
115
|
-
|
|
116
|
-
🌐 BROWSERSYNC FILE CACHE
|
|
117
|
-
Hit Rate: ${stats.browserSyncCache.hitRate}%
|
|
118
|
-
Cache Hits: ${stats.browserSyncCache.cacheHits}
|
|
119
|
-
Cache Misses: ${stats.browserSyncCache.cacheMisses}
|
|
120
|
-
Size: ${stats.browserSyncCache.cacheSize}/${stats.browserSyncCache.maxCacheSize}
|
|
121
|
-
Memoria: ${formatBytes(stats.browserSyncCache.memoryUsage)}/${formatBytes(stats.browserSyncCache.maxMemoryUsage)}
|
|
122
|
-
|
|
123
|
-
🗜️ MINIFICATION CACHE
|
|
124
|
-
Hit Rate: ${stats.minificationCache.hitRate}%
|
|
125
|
-
Cache Hits: ${stats.minificationCache.cacheHits}
|
|
126
|
-
Cache Misses: ${stats.minificationCache.cacheMisses}
|
|
127
|
-
Size: ${stats.minificationCache.cacheSize}/${stats.minificationCache.maxCacheSize}
|
|
128
|
-
Memoria: ${formatBytes(stats.minificationCache.memoryUsage)}/${formatBytes(stats.minificationCache.maxMemoryUsage)}
|
|
129
|
-
Compresión Promedio: ${stats.minificationCache.avgCompressionRatio}%
|
|
130
|
-
|
|
131
|
-
🔄 TRANSFORM OPTIMIZER
|
|
132
|
-
Hit Rate: ${stats.transformOptimizer.hitRate}%
|
|
133
|
-
Cache Hits: ${stats.transformOptimizer.cacheHits}
|
|
134
|
-
Cache Misses: ${stats.transformOptimizer.cacheMisses}
|
|
135
|
-
Transformaciones: ${stats.transformOptimizer.totalTransforms}
|
|
136
|
-
Size: ${stats.transformOptimizer.cacheSize}
|
|
137
|
-
Memoria: ${formatBytes(stats.transformOptimizer.memoryUsage)}
|
|
138
|
-
|
|
139
|
-
📦 MODULE RESOLUTION
|
|
140
|
-
Hit Rate: ${stats.moduleResolution.cacheHitRate?.toFixed(1)}%
|
|
141
|
-
Cache Hits: ${stats.moduleResolution.cacheHits}
|
|
142
|
-
Cache Misses: ${stats.moduleResolution.cacheMisses}
|
|
143
|
-
Resoluciones: ${stats.moduleResolution.totalResolutions}
|
|
144
|
-
Índice Módulos: ${stats.moduleResolution.moduleIndexSize}
|
|
145
|
-
Índice Alias: ${stats.moduleResolution.aliasIndexSize}
|
|
146
|
-
Tiempo Promedio: ${stats.moduleResolution.averageResolveTime?.toFixed(2)}ms
|
|
147
|
-
|
|
148
|
-
=====================================
|
|
88
|
+
const report = `
|
|
89
|
+
🚀 VERSACOMPILER PERFORMANCE REPORT
|
|
90
|
+
=====================================
|
|
91
|
+
|
|
92
|
+
📊 RESUMEN GENERAL
|
|
93
|
+
Hit Rate Total: ${stats.summary.overallHitRate}%
|
|
94
|
+
Cache Hits: ${stats.summary.totalCacheHits}
|
|
95
|
+
Cache Misses: ${stats.summary.totalCacheMisses}
|
|
96
|
+
Memoria Total: ${formatBytes(stats.summary.totalMemoryUsage)}
|
|
97
|
+
Entradas Cache: ${stats.summary.totalCacheEntries}
|
|
98
|
+
|
|
99
|
+
🎯 VUE HMR CACHE
|
|
100
|
+
Size: ${stats.vueHMRCache.size}/${stats.vueHMRCache.maxSize}
|
|
101
|
+
TTL: ${Math.round(stats.vueHMRCache.ttl / 1000 / 60)}min
|
|
102
|
+
|
|
103
|
+
📝 PARSER AST CACHE
|
|
104
|
+
Hit Rate: ${stats.parserCache.hitRate}%
|
|
105
|
+
Cache Hits: ${stats.parserCache.cacheHits}
|
|
106
|
+
Cache Misses: ${stats.parserCache.cacheMisses}
|
|
107
|
+
Size: ${stats.parserCache.cacheSize}/${stats.parserCache.maxCacheSize}
|
|
108
|
+
Memoria: ${formatBytes(stats.parserCache.memoryUsage)}/${formatBytes(stats.parserCache.maxMemoryUsage)}
|
|
109
|
+
|
|
110
|
+
📖 FILE CONTENT CACHE
|
|
111
|
+
Hit Rate: ${stats.fileContentCache.hitRate}%
|
|
112
|
+
Cache Hits: ${stats.fileContentCache.cacheHits}
|
|
113
|
+
Cache Misses: ${stats.fileContentCache.cacheMisses}
|
|
114
|
+
Size: ${stats.fileContentCache.cacheSize}/${stats.fileContentCache.maxCacheSize}
|
|
115
|
+
|
|
116
|
+
🌐 BROWSERSYNC FILE CACHE
|
|
117
|
+
Hit Rate: ${stats.browserSyncCache.hitRate}%
|
|
118
|
+
Cache Hits: ${stats.browserSyncCache.cacheHits}
|
|
119
|
+
Cache Misses: ${stats.browserSyncCache.cacheMisses}
|
|
120
|
+
Size: ${stats.browserSyncCache.cacheSize}/${stats.browserSyncCache.maxCacheSize}
|
|
121
|
+
Memoria: ${formatBytes(stats.browserSyncCache.memoryUsage)}/${formatBytes(stats.browserSyncCache.maxMemoryUsage)}
|
|
122
|
+
|
|
123
|
+
🗜️ MINIFICATION CACHE
|
|
124
|
+
Hit Rate: ${stats.minificationCache.hitRate}%
|
|
125
|
+
Cache Hits: ${stats.minificationCache.cacheHits}
|
|
126
|
+
Cache Misses: ${stats.minificationCache.cacheMisses}
|
|
127
|
+
Size: ${stats.minificationCache.cacheSize}/${stats.minificationCache.maxCacheSize}
|
|
128
|
+
Memoria: ${formatBytes(stats.minificationCache.memoryUsage)}/${formatBytes(stats.minificationCache.maxMemoryUsage)}
|
|
129
|
+
Compresión Promedio: ${stats.minificationCache.avgCompressionRatio}%
|
|
130
|
+
|
|
131
|
+
🔄 TRANSFORM OPTIMIZER
|
|
132
|
+
Hit Rate: ${stats.transformOptimizer.hitRate}%
|
|
133
|
+
Cache Hits: ${stats.transformOptimizer.cacheHits}
|
|
134
|
+
Cache Misses: ${stats.transformOptimizer.cacheMisses}
|
|
135
|
+
Transformaciones: ${stats.transformOptimizer.totalTransforms}
|
|
136
|
+
Size: ${stats.transformOptimizer.cacheSize}
|
|
137
|
+
Memoria: ${formatBytes(stats.transformOptimizer.memoryUsage)}
|
|
138
|
+
|
|
139
|
+
📦 MODULE RESOLUTION
|
|
140
|
+
Hit Rate: ${stats.moduleResolution.cacheHitRate?.toFixed(1)}%
|
|
141
|
+
Cache Hits: ${stats.moduleResolution.cacheHits}
|
|
142
|
+
Cache Misses: ${stats.moduleResolution.cacheMisses}
|
|
143
|
+
Resoluciones: ${stats.moduleResolution.totalResolutions}
|
|
144
|
+
Índice Módulos: ${stats.moduleResolution.moduleIndexSize}
|
|
145
|
+
Índice Alias: ${stats.moduleResolution.aliasIndexSize}
|
|
146
|
+
Tiempo Promedio: ${stats.moduleResolution.averageResolveTime?.toFixed(2)}ms
|
|
147
|
+
|
|
148
|
+
=====================================
|
|
149
149
|
`;
|
|
150
150
|
return report;
|
|
151
151
|
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { stat } from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { parser } from '../parser.js';
|
|
4
|
+
import { ModuleGraph } from './module-graph.js';
|
|
5
|
+
import { PluginDriver } from './plugin-driver.js';
|
|
6
|
+
function guessLoader(filePath) {
|
|
7
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
8
|
+
if (ext === '.vue')
|
|
9
|
+
return 'vue';
|
|
10
|
+
if (ext === '.ts')
|
|
11
|
+
return 'ts';
|
|
12
|
+
if (ext === '.json')
|
|
13
|
+
return 'json';
|
|
14
|
+
if (ext === '.css')
|
|
15
|
+
return 'css';
|
|
16
|
+
return 'js';
|
|
17
|
+
}
|
|
18
|
+
function getAstType(loader) {
|
|
19
|
+
return loader === 'ts' ? 'ts' : 'js';
|
|
20
|
+
}
|
|
21
|
+
function collectModuleRequests(ast) {
|
|
22
|
+
const requests = [];
|
|
23
|
+
const staticImports = ast?.module?.staticImports || [];
|
|
24
|
+
for (const item of staticImports) {
|
|
25
|
+
const value = item?.moduleRequest?.value;
|
|
26
|
+
if (typeof value === 'string')
|
|
27
|
+
requests.push(value);
|
|
28
|
+
}
|
|
29
|
+
const dynamicImports = ast?.module?.dynamicImports || [];
|
|
30
|
+
for (const item of dynamicImports) {
|
|
31
|
+
const value = item?.moduleRequest?.value;
|
|
32
|
+
if (typeof value === 'string')
|
|
33
|
+
requests.push(value);
|
|
34
|
+
}
|
|
35
|
+
return requests;
|
|
36
|
+
}
|
|
37
|
+
async function resolveLocalImport(importer, specifier) {
|
|
38
|
+
if (!specifier.startsWith('.') && !specifier.startsWith('/'))
|
|
39
|
+
return null;
|
|
40
|
+
const base = specifier.startsWith('/')
|
|
41
|
+
? path.normalize(specifier)
|
|
42
|
+
: path.resolve(path.dirname(importer), specifier);
|
|
43
|
+
const ext = path.extname(base);
|
|
44
|
+
if (ext)
|
|
45
|
+
return base;
|
|
46
|
+
const candidates = [
|
|
47
|
+
`${base}.ts`,
|
|
48
|
+
`${base}.js`,
|
|
49
|
+
`${base}.vue`,
|
|
50
|
+
`${base}.mjs`,
|
|
51
|
+
`${base}.cjs`,
|
|
52
|
+
`${base}.json`,
|
|
53
|
+
path.join(base, 'index.ts'),
|
|
54
|
+
path.join(base, 'index.js'),
|
|
55
|
+
path.join(base, 'index.vue'),
|
|
56
|
+
];
|
|
57
|
+
for (const candidate of candidates) {
|
|
58
|
+
try {
|
|
59
|
+
await stat(candidate);
|
|
60
|
+
return candidate;
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return base;
|
|
67
|
+
}
|
|
68
|
+
export class BuildPipeline {
|
|
69
|
+
driver;
|
|
70
|
+
graph;
|
|
71
|
+
constructor(plugins) {
|
|
72
|
+
this.driver = new PluginDriver(plugins);
|
|
73
|
+
this.graph = new ModuleGraph();
|
|
74
|
+
}
|
|
75
|
+
getModuleGraph() {
|
|
76
|
+
return this.graph;
|
|
77
|
+
}
|
|
78
|
+
async hotUpdate(args) {
|
|
79
|
+
return this.driver.hotUpdate(args);
|
|
80
|
+
}
|
|
81
|
+
async compileFile(filePath) {
|
|
82
|
+
const resolved = await this.driver.resolve({
|
|
83
|
+
path: filePath,
|
|
84
|
+
kind: 'entry',
|
|
85
|
+
});
|
|
86
|
+
const entryPath = resolved.path || filePath;
|
|
87
|
+
const loaded = await this.driver.load({ path: entryPath });
|
|
88
|
+
const loadErrors = loaded.errors || [];
|
|
89
|
+
if (!loaded.contents) {
|
|
90
|
+
await this.driver.end(loadErrors);
|
|
91
|
+
return {
|
|
92
|
+
code: '',
|
|
93
|
+
loader: guessLoader(entryPath),
|
|
94
|
+
dependencies: [],
|
|
95
|
+
errors: loadErrors,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
const transformResult = await this.driver.transform({
|
|
99
|
+
path: entryPath,
|
|
100
|
+
contents: loaded.contents,
|
|
101
|
+
loader: loaded.loader || guessLoader(entryPath),
|
|
102
|
+
meta: loaded.meta,
|
|
103
|
+
});
|
|
104
|
+
const transformErrors = transformResult.errors || [];
|
|
105
|
+
const finalCode = transformResult.contents || '';
|
|
106
|
+
const finalLoader = transformResult.loader || loaded.loader || guessLoader(entryPath);
|
|
107
|
+
const ast = await parser(entryPath, finalCode, getAstType(finalLoader));
|
|
108
|
+
const requests = collectModuleRequests(ast);
|
|
109
|
+
const resolvedDeps = [];
|
|
110
|
+
for (const request of requests) {
|
|
111
|
+
const resolvedDep = await resolveLocalImport(entryPath, request);
|
|
112
|
+
if (resolvedDep)
|
|
113
|
+
resolvedDeps.push(resolvedDep);
|
|
114
|
+
}
|
|
115
|
+
this.graph.updateImports(entryPath, resolvedDeps);
|
|
116
|
+
const errors = loadErrors.concat(transformErrors);
|
|
117
|
+
await this.driver.end(errors);
|
|
118
|
+
return {
|
|
119
|
+
code: finalCode,
|
|
120
|
+
loader: finalLoader,
|
|
121
|
+
meta: transformResult.meta || loaded.meta,
|
|
122
|
+
dependencies: resolvedDeps,
|
|
123
|
+
errors,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=build-pipeline.js.map
|