@vureact/compiler-core 1.3.0 → 1.4.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 +1 -1
- package/README.zh.md +1 -1
- package/lib/{chunk-7LBUUA24.js → chunk-IVRFEV6H.js} +852 -779
- package/lib/{chunk-CUCUXW56.esm.js → chunk-NF5BSPYE.esm.js} +813 -740
- package/lib/cli.esm.js +59 -47
- package/lib/cli.js +62 -50
- package/lib/compiler-core.d.cts +1117 -1188
- package/lib/compiler-core.d.ts +1117 -1188
- package/lib/compiler-core.esm.js +2 -2
- package/lib/compiler-core.js +3 -3
- package/package.json +99 -91
- package/templates/route-setup-notes.md +0 -192
- package/templates/route-setup-notes.zh.md +0 -192
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @vureact/compiler-core v1.
|
|
2
|
+
* @vureact/compiler-core v1.4.0
|
|
3
3
|
* (c) 2025-present Ruihong Zhong (Ryan John)
|
|
4
4
|
* @license MIT
|
|
5
5
|
*/
|
|
@@ -32,6 +32,16 @@ var PACKAGE_NAME = {
|
|
|
32
32
|
runtime: "@vureact/runtime-core",
|
|
33
33
|
router: "@vureact/router"
|
|
34
34
|
};
|
|
35
|
+
var RUNTIME_PACKAGES = {
|
|
36
|
+
router: {
|
|
37
|
+
name: PACKAGE_NAME.router,
|
|
38
|
+
version: "^1.0.0"
|
|
39
|
+
},
|
|
40
|
+
runtime: {
|
|
41
|
+
name: PACKAGE_NAME.runtime,
|
|
42
|
+
version: "^1.0.0"
|
|
43
|
+
}
|
|
44
|
+
};
|
|
35
45
|
var STYLE_MODULE_NAME = "$style";
|
|
36
46
|
var MACRO_API_NAMES = {
|
|
37
47
|
props: "defineProps",
|
|
@@ -418,8 +428,8 @@ function getBabelParseOptions(lang = "js", context = "script", filename) {
|
|
|
418
428
|
function stringToExpr(input, lang, filename = "") {
|
|
419
429
|
return parseExpression(input, getBabelParseOptions(lang, "expression", filename));
|
|
420
430
|
}
|
|
421
|
-
function atComponentOrHookRoot(
|
|
422
|
-
const { parentPath, scope } =
|
|
431
|
+
function atComponentOrHookRoot(path9, rootScope, inScriptFile = false) {
|
|
432
|
+
const { parentPath, scope } = path9;
|
|
423
433
|
const parentBlock = scope.block;
|
|
424
434
|
if (!parentPath) return !inScriptFile;
|
|
425
435
|
if (parentBlock === rootScope) {
|
|
@@ -1650,9 +1660,9 @@ function resolveScriptMeta(result, ctx) {
|
|
|
1650
1660
|
const scriptAST = result.script?.ast;
|
|
1651
1661
|
if (!scriptAST) return;
|
|
1652
1662
|
traverse(scriptAST, {
|
|
1653
|
-
VariableDeclarator(
|
|
1654
|
-
const { node } =
|
|
1655
|
-
if (!atComponentOrHookRoot(
|
|
1663
|
+
VariableDeclarator(path9) {
|
|
1664
|
+
const { node } = path9;
|
|
1665
|
+
if (!atComponentOrHookRoot(path9, scriptAST.program) || !t16.isIdentifier(node.id)) {
|
|
1656
1666
|
return;
|
|
1657
1667
|
}
|
|
1658
1668
|
if (node.init && t16.isCallExpression(node.init) && t16.isIdentifier(node.init.callee)) {
|
|
@@ -1986,36 +1996,36 @@ function insertRequiredImports(ctx) {
|
|
|
1986
1996
|
const processedModules = /* @__PURE__ */ new Set();
|
|
1987
1997
|
let hasProcessedImports = false;
|
|
1988
1998
|
recordImport(ctx, PACKAGE_NAME.react, REACT_API_MAP.memo);
|
|
1989
|
-
function resolveRequiredImport(
|
|
1990
|
-
const { node } =
|
|
1999
|
+
function resolveRequiredImport(path9) {
|
|
2000
|
+
const { node } = path9;
|
|
1991
2001
|
const moduleName = node.source.value.toLowerCase();
|
|
1992
2002
|
const isVueLike = isVueEcosystemPackage(moduleName);
|
|
1993
2003
|
mergeImports(node, ctx);
|
|
1994
|
-
if (processedModules.has(moduleName) && !
|
|
1995
|
-
|
|
2004
|
+
if (processedModules.has(moduleName) && !path9.removed) {
|
|
2005
|
+
path9.remove();
|
|
1996
2006
|
return;
|
|
1997
2007
|
}
|
|
1998
2008
|
processedModules.add(moduleName);
|
|
1999
2009
|
if (!hasProcessedImports) {
|
|
2000
2010
|
const required = createRequiredImports(ctx);
|
|
2001
2011
|
if (isVueLike) {
|
|
2002
|
-
|
|
2012
|
+
path9.replaceWithMultiple(required);
|
|
2003
2013
|
} else if (moduleName === PACKAGE_NAME.react) {
|
|
2004
|
-
|
|
2014
|
+
path9.insertAfter(required);
|
|
2005
2015
|
} else {
|
|
2006
|
-
|
|
2016
|
+
path9.insertBefore(required);
|
|
2007
2017
|
}
|
|
2008
2018
|
hasProcessedImports = true;
|
|
2009
2019
|
}
|
|
2010
|
-
if (isVueLike && !
|
|
2011
|
-
|
|
2020
|
+
if (isVueLike && !path9.removed) {
|
|
2021
|
+
path9.remove();
|
|
2012
2022
|
return;
|
|
2013
2023
|
}
|
|
2014
2024
|
replaceVueSuffix(ctx, node.source);
|
|
2015
2025
|
}
|
|
2016
|
-
function resolveStyleFileExt(
|
|
2026
|
+
function resolveStyleFileExt(path9) {
|
|
2017
2027
|
if (!ctx.preprocessStyles) return;
|
|
2018
|
-
const { node } =
|
|
2028
|
+
const { node } = path9;
|
|
2019
2029
|
if (!node || !node.source || !node.source.value) return;
|
|
2020
2030
|
const importSource = node.source.value;
|
|
2021
2031
|
if (typeof importSource !== "string") return;
|
|
@@ -2027,16 +2037,16 @@ function insertRequiredImports(ctx) {
|
|
|
2027
2037
|
return {
|
|
2028
2038
|
// 增加 Program.exit 兜底注入 required imports(处理无 ImportDeclaration 的 SFC)
|
|
2029
2039
|
Program: {
|
|
2030
|
-
exit(
|
|
2040
|
+
exit(path9) {
|
|
2031
2041
|
if (hasProcessedImports) return;
|
|
2032
2042
|
const required = createRequiredImports(ctx);
|
|
2033
|
-
|
|
2043
|
+
path9.unshiftContainer("body", required);
|
|
2034
2044
|
hasProcessedImports = true;
|
|
2035
2045
|
}
|
|
2036
2046
|
},
|
|
2037
|
-
ImportDeclaration(
|
|
2038
|
-
resolveRequiredImport(
|
|
2039
|
-
resolveStyleFileExt(
|
|
2047
|
+
ImportDeclaration(path9) {
|
|
2048
|
+
resolveRequiredImport(path9);
|
|
2049
|
+
resolveStyleFileExt(path9);
|
|
2040
2050
|
}
|
|
2041
2051
|
};
|
|
2042
2052
|
}
|
|
@@ -2107,10 +2117,10 @@ import * as t20 from "@babel/types";
|
|
|
2107
2117
|
|
|
2108
2118
|
// src/core/transform/sfc/script/shared/babel-utils.ts
|
|
2109
2119
|
import * as t19 from "@babel/types";
|
|
2110
|
-
function findRootVariablePath(
|
|
2111
|
-
const rootId = findRootIdentifier(
|
|
2120
|
+
function findRootVariablePath(path9) {
|
|
2121
|
+
const rootId = findRootIdentifier(path9.node);
|
|
2112
2122
|
if (!rootId?.name) return null;
|
|
2113
|
-
const binding =
|
|
2123
|
+
const binding = path9.scope.getBinding(rootId.name);
|
|
2114
2124
|
if (!binding) return null;
|
|
2115
2125
|
const rootPath = getVariableDeclaratorPath(binding.path);
|
|
2116
2126
|
return rootPath;
|
|
@@ -2122,14 +2132,14 @@ function findRootIdentifier(node) {
|
|
|
2122
2132
|
}
|
|
2123
2133
|
return t19.isIdentifier(current) ? current : null;
|
|
2124
2134
|
}
|
|
2125
|
-
function getVariableDeclaratorPath(
|
|
2126
|
-
if (
|
|
2127
|
-
return
|
|
2135
|
+
function getVariableDeclaratorPath(path9) {
|
|
2136
|
+
if (path9.isVariableDeclarator()) {
|
|
2137
|
+
return path9;
|
|
2128
2138
|
}
|
|
2129
|
-
return
|
|
2139
|
+
return path9.findParent((p) => p.isVariableDeclarator());
|
|
2130
2140
|
}
|
|
2131
|
-
function isVariableDeclTopLevel(
|
|
2132
|
-
const variableDeclaratorPath =
|
|
2141
|
+
function isVariableDeclTopLevel(path9) {
|
|
2142
|
+
const variableDeclaratorPath = path9;
|
|
2133
2143
|
const variableDeclarationPath = variableDeclaratorPath.parentPath;
|
|
2134
2144
|
if (!variableDeclarationPath) {
|
|
2135
2145
|
return false;
|
|
@@ -2143,61 +2153,61 @@ function isVariableDeclTopLevel(path8) {
|
|
|
2143
2153
|
}
|
|
2144
2154
|
return false;
|
|
2145
2155
|
}
|
|
2146
|
-
function isRealVariableAccess(
|
|
2147
|
-
return isIdentifierAccess(
|
|
2156
|
+
function isRealVariableAccess(path9) {
|
|
2157
|
+
return isIdentifierAccess(path9) && !isPropertyName(path9);
|
|
2148
2158
|
}
|
|
2149
|
-
function isIdentifierAccess(
|
|
2150
|
-
if (isIdentifierDeclaration(
|
|
2159
|
+
function isIdentifierAccess(path9) {
|
|
2160
|
+
if (isIdentifierDeclaration(path9)) {
|
|
2151
2161
|
return false;
|
|
2152
2162
|
}
|
|
2153
|
-
const binding =
|
|
2163
|
+
const binding = path9.scope.getBinding(path9.node.name);
|
|
2154
2164
|
if (!binding) {
|
|
2155
2165
|
return true;
|
|
2156
2166
|
}
|
|
2157
|
-
return binding.identifier !==
|
|
2167
|
+
return binding.identifier !== path9.node;
|
|
2158
2168
|
}
|
|
2159
|
-
function isIdentifierDeclaration(
|
|
2160
|
-
const parent =
|
|
2169
|
+
function isIdentifierDeclaration(path9) {
|
|
2170
|
+
const parent = path9.parentPath;
|
|
2161
2171
|
if (!parent) return false;
|
|
2162
|
-
if (parent.isVariableDeclarator() && parent.node.id ===
|
|
2172
|
+
if (parent.isVariableDeclarator() && parent.node.id === path9.node) {
|
|
2163
2173
|
return true;
|
|
2164
2174
|
}
|
|
2165
|
-
if (parent.isFunctionDeclaration() && parent.node.id ===
|
|
2175
|
+
if (parent.isFunctionDeclaration() && parent.node.id === path9.node) {
|
|
2166
2176
|
return true;
|
|
2167
2177
|
}
|
|
2168
|
-
if (parent.isFunctionExpression() && parent.node.id ===
|
|
2178
|
+
if (parent.isFunctionExpression() && parent.node.id === path9.node) {
|
|
2169
2179
|
return true;
|
|
2170
2180
|
}
|
|
2171
|
-
if (parent.isClassDeclaration() && parent.node.id ===
|
|
2181
|
+
if (parent.isClassDeclaration() && parent.node.id === path9.node) {
|
|
2172
2182
|
return true;
|
|
2173
2183
|
}
|
|
2174
|
-
if (parent.isImportSpecifier() && parent.node.local ===
|
|
2184
|
+
if (parent.isImportSpecifier() && parent.node.local === path9.node) {
|
|
2175
2185
|
return true;
|
|
2176
2186
|
}
|
|
2177
|
-
if (parent.isImportDefaultSpecifier() && parent.node.local ===
|
|
2187
|
+
if (parent.isImportDefaultSpecifier() && parent.node.local === path9.node) {
|
|
2178
2188
|
return true;
|
|
2179
2189
|
}
|
|
2180
|
-
if (parent.isImportNamespaceSpecifier() && parent.node.local ===
|
|
2190
|
+
if (parent.isImportNamespaceSpecifier() && parent.node.local === path9.node) {
|
|
2181
2191
|
return true;
|
|
2182
2192
|
}
|
|
2183
|
-
if (parent.isFunction() && parent.node.params.includes(
|
|
2193
|
+
if (parent.isFunction() && parent.node.params.includes(path9.node)) {
|
|
2184
2194
|
return true;
|
|
2185
2195
|
}
|
|
2186
|
-
if (parent.isCatchClause() && parent.node.param ===
|
|
2196
|
+
if (parent.isCatchClause() && parent.node.param === path9.node) {
|
|
2187
2197
|
return true;
|
|
2188
2198
|
}
|
|
2189
2199
|
return false;
|
|
2190
2200
|
}
|
|
2191
|
-
function isPropertyName(
|
|
2192
|
-
const parent =
|
|
2201
|
+
function isPropertyName(path9) {
|
|
2202
|
+
const parent = path9.parentPath;
|
|
2193
2203
|
if (!parent) return false;
|
|
2194
|
-
if (parent.isObjectProperty() && parent.node.key ===
|
|
2204
|
+
if (parent.isObjectProperty() && parent.node.key === path9.node) {
|
|
2195
2205
|
return true;
|
|
2196
2206
|
}
|
|
2197
|
-
if (parent.isClassProperty() && parent.node.key ===
|
|
2207
|
+
if (parent.isClassProperty() && parent.node.key === path9.node) {
|
|
2198
2208
|
return true;
|
|
2199
2209
|
}
|
|
2200
|
-
if (parent.isMemberExpression() && parent.node.property ===
|
|
2210
|
+
if (parent.isMemberExpression() && parent.node.property === path9.node) {
|
|
2201
2211
|
return true;
|
|
2202
2212
|
}
|
|
2203
2213
|
return false;
|
|
@@ -2308,26 +2318,26 @@ function resolveStaticHoisting(ctx) {
|
|
|
2308
2318
|
return {};
|
|
2309
2319
|
}
|
|
2310
2320
|
return {
|
|
2311
|
-
"ImportDeclaration|ExportDeclaration"(
|
|
2312
|
-
if (t20.isImportDeclaration(
|
|
2313
|
-
scriptIR.imports.push(
|
|
2314
|
-
} else if (t20.isExportDeclaration(
|
|
2315
|
-
scriptIR.exports.push(
|
|
2321
|
+
"ImportDeclaration|ExportDeclaration"(path9) {
|
|
2322
|
+
if (t20.isImportDeclaration(path9.node)) {
|
|
2323
|
+
scriptIR.imports.push(path9.node);
|
|
2324
|
+
} else if (t20.isExportDeclaration(path9.node)) {
|
|
2325
|
+
scriptIR.exports.push(path9.node);
|
|
2316
2326
|
}
|
|
2317
|
-
|
|
2327
|
+
path9.remove();
|
|
2318
2328
|
},
|
|
2319
|
-
"TSInterfaceDeclaration|TSTypeAliasDeclaration|TSEnumDeclaration|TSModuleDeclaration|TSModuleDeclaration"(
|
|
2320
|
-
if (t20.isProgram(
|
|
2321
|
-
scriptIR.tsTypes.push(
|
|
2322
|
-
|
|
2329
|
+
"TSInterfaceDeclaration|TSTypeAliasDeclaration|TSEnumDeclaration|TSModuleDeclaration|TSModuleDeclaration"(path9) {
|
|
2330
|
+
if (t20.isProgram(path9.parent)) {
|
|
2331
|
+
scriptIR.tsTypes.push(path9.node);
|
|
2332
|
+
path9.remove();
|
|
2323
2333
|
}
|
|
2324
2334
|
},
|
|
2325
|
-
VariableDeclarator(
|
|
2326
|
-
const { node } =
|
|
2327
|
-
if (!isVariableDeclTopLevel(
|
|
2335
|
+
VariableDeclarator(path9) {
|
|
2336
|
+
const { node } = path9;
|
|
2337
|
+
if (!isVariableDeclTopLevel(path9) || !isSimpleLiteral(node.init) || getScriptNodeMeta(node)) {
|
|
2328
2338
|
return;
|
|
2329
2339
|
}
|
|
2330
|
-
const declarationPath =
|
|
2340
|
+
const declarationPath = path9.findParent((p) => p.isVariableDeclaration());
|
|
2331
2341
|
if (!declarationPath) return;
|
|
2332
2342
|
scriptIR.statement.global.push(declarationPath.node);
|
|
2333
2343
|
declarationPath.remove();
|
|
@@ -2344,14 +2354,14 @@ function collectLocalStatements(ctx, ast) {
|
|
|
2344
2354
|
import * as t21 from "@babel/types";
|
|
2345
2355
|
function resolveDefineAsyncComponent(ctx) {
|
|
2346
2356
|
return {
|
|
2347
|
-
CallExpression(
|
|
2348
|
-
const { node } =
|
|
2357
|
+
CallExpression(path9) {
|
|
2358
|
+
const { node } = path9;
|
|
2349
2359
|
if (!isCalleeNamed(node, VUE_API_MAP.defineAsyncComponent)) {
|
|
2350
2360
|
return;
|
|
2351
2361
|
}
|
|
2352
2362
|
const [arg] = node.arguments;
|
|
2353
2363
|
checkIsUnsupported(ctx, arg);
|
|
2354
|
-
pushToGlobalScope(
|
|
2364
|
+
pushToGlobalScope(path9, ctx);
|
|
2355
2365
|
recordImport(ctx, PACKAGE_NAME.react, REACT_API_MAP.lazy);
|
|
2356
2366
|
}
|
|
2357
2367
|
};
|
|
@@ -2414,15 +2424,15 @@ function warnMultipleOptionsUsed(ctx, node) {
|
|
|
2414
2424
|
}
|
|
2415
2425
|
);
|
|
2416
2426
|
}
|
|
2417
|
-
function pushToGlobalScope(
|
|
2418
|
-
const { node } =
|
|
2427
|
+
function pushToGlobalScope(path9, ctx) {
|
|
2428
|
+
const { node } = path9;
|
|
2419
2429
|
const callee = node.callee;
|
|
2420
2430
|
callee.name = REACT_API_MAP.lazy;
|
|
2421
2431
|
callee.loc.identifierName = REACT_API_MAP.lazy;
|
|
2422
2432
|
if (node.typeParameters) {
|
|
2423
2433
|
node.typeParameters = void 0;
|
|
2424
2434
|
}
|
|
2425
|
-
let declarationPath =
|
|
2435
|
+
let declarationPath = path9.parentPath;
|
|
2426
2436
|
while (declarationPath) {
|
|
2427
2437
|
if (declarationPath.isVariableDeclaration()) {
|
|
2428
2438
|
break;
|
|
@@ -2433,12 +2443,12 @@ function pushToGlobalScope(path8, ctx) {
|
|
|
2433
2443
|
if (declarationPath?.isVariableDeclaration()) {
|
|
2434
2444
|
fullNode = declarationPath.node;
|
|
2435
2445
|
declarationPath.remove();
|
|
2436
|
-
} else if (
|
|
2437
|
-
fullNode =
|
|
2438
|
-
|
|
2446
|
+
} else if (path9.parentPath.isVariableDeclarator()) {
|
|
2447
|
+
fullNode = path9.parent;
|
|
2448
|
+
path9.parentPath.remove();
|
|
2439
2449
|
} else {
|
|
2440
|
-
fullNode =
|
|
2441
|
-
|
|
2450
|
+
fullNode = path9.node;
|
|
2451
|
+
path9.remove();
|
|
2442
2452
|
}
|
|
2443
2453
|
const scriptIR = getScriptIR(ctx);
|
|
2444
2454
|
scriptIR.statement.global.push(fullNode);
|
|
@@ -2469,15 +2479,15 @@ function createUseImperativeHandle(refId, init) {
|
|
|
2469
2479
|
function resolveDefineExpose(ctx) {
|
|
2470
2480
|
if (ctx.inputType !== "sfc") return {};
|
|
2471
2481
|
return {
|
|
2472
|
-
CallExpression(
|
|
2473
|
-
const { node } =
|
|
2482
|
+
CallExpression(path9) {
|
|
2483
|
+
const { node } = path9;
|
|
2474
2484
|
const { filename, scriptData } = ctx;
|
|
2475
2485
|
if (!isCalleeNamed(node, MACRO_API_NAMES.expose)) {
|
|
2476
2486
|
return;
|
|
2477
2487
|
}
|
|
2478
2488
|
const [expose] = node.arguments;
|
|
2479
2489
|
if (!expose) {
|
|
2480
|
-
|
|
2490
|
+
path9.remove();
|
|
2481
2491
|
return;
|
|
2482
2492
|
}
|
|
2483
2493
|
const adapter = ADAPTER_RULES.react[MACRO_API_NAMES.expose];
|
|
@@ -2494,7 +2504,7 @@ function resolveDefineExpose(ctx) {
|
|
|
2494
2504
|
const { forwardRef } = scriptData;
|
|
2495
2505
|
const newNode = createUseImperativeHandle(t23.identifier(forwardRef.refField), init);
|
|
2496
2506
|
forwardRef.enabled = true;
|
|
2497
|
-
|
|
2507
|
+
path9.replaceWith(newNode);
|
|
2498
2508
|
}
|
|
2499
2509
|
};
|
|
2500
2510
|
}
|
|
@@ -2503,8 +2513,8 @@ function resolveDefineExpose(ctx) {
|
|
|
2503
2513
|
import * as t24 from "@babel/types";
|
|
2504
2514
|
function resolveDefineOptions(ctx) {
|
|
2505
2515
|
return {
|
|
2506
|
-
CallExpression(
|
|
2507
|
-
const { node } =
|
|
2516
|
+
CallExpression(path9) {
|
|
2517
|
+
const { node } = path9;
|
|
2508
2518
|
if (!isCalleeNamed(node, MACRO_API_NAMES.options)) {
|
|
2509
2519
|
return;
|
|
2510
2520
|
}
|
|
@@ -2516,7 +2526,7 @@ function resolveDefineOptions(ctx) {
|
|
|
2516
2526
|
file: filename,
|
|
2517
2527
|
loc: node?.loc
|
|
2518
2528
|
});
|
|
2519
|
-
|
|
2529
|
+
path9.remove();
|
|
2520
2530
|
return;
|
|
2521
2531
|
}
|
|
2522
2532
|
if (!t24.isObjectExpression(options)) {
|
|
@@ -2533,7 +2543,7 @@ function resolveDefineOptions(ctx) {
|
|
|
2533
2543
|
extractName(prop, ctx);
|
|
2534
2544
|
}
|
|
2535
2545
|
}
|
|
2536
|
-
|
|
2546
|
+
path9.remove();
|
|
2537
2547
|
}
|
|
2538
2548
|
};
|
|
2539
2549
|
}
|
|
@@ -2565,8 +2575,8 @@ function resolveEmitCalls(ctx) {
|
|
|
2565
2575
|
return `on${capitalize(camelCase(normalized))}`;
|
|
2566
2576
|
};
|
|
2567
2577
|
return {
|
|
2568
|
-
CallExpression(
|
|
2569
|
-
const { node } =
|
|
2578
|
+
CallExpression(path9) {
|
|
2579
|
+
const { node } = path9;
|
|
2570
2580
|
const { filename, templateData, scriptData } = ctx;
|
|
2571
2581
|
if (!t25.isIdentifier(node.callee)) return;
|
|
2572
2582
|
const { name } = node.callee;
|
|
@@ -2577,7 +2587,7 @@ function resolveEmitCalls(ctx) {
|
|
|
2577
2587
|
result = meta.source === MACRO_API_NAMES.emits;
|
|
2578
2588
|
}
|
|
2579
2589
|
if (!result) {
|
|
2580
|
-
const binding =
|
|
2590
|
+
const binding = path9.scope.getBinding(name);
|
|
2581
2591
|
if (binding) {
|
|
2582
2592
|
const parent = binding.path.node;
|
|
2583
2593
|
if (t25.isVariableDeclarator(parent) && t25.isCallExpression(parent.init) && t25.isIdentifier(parent.init.callee)) {
|
|
@@ -2596,7 +2606,7 @@ function resolveEmitCalls(ctx) {
|
|
|
2596
2606
|
source: scriptData.source,
|
|
2597
2607
|
loc: callee?.loc
|
|
2598
2608
|
});
|
|
2599
|
-
|
|
2609
|
+
path9.remove();
|
|
2600
2610
|
return;
|
|
2601
2611
|
}
|
|
2602
2612
|
const propCall = t25.optionalCallExpression(
|
|
@@ -2609,7 +2619,7 @@ function resolveEmitCalls(ctx) {
|
|
|
2609
2619
|
args,
|
|
2610
2620
|
true
|
|
2611
2621
|
);
|
|
2612
|
-
|
|
2622
|
+
path9.replaceWith(propCall);
|
|
2613
2623
|
}
|
|
2614
2624
|
};
|
|
2615
2625
|
}
|
|
@@ -2647,9 +2657,9 @@ function cloneCallableParams(params) {
|
|
|
2647
2657
|
// src/core/transform/sfc/script/syntax-processor/preprocess/resolve-props-interface/resolve-emits.ts
|
|
2648
2658
|
function resolveEmitsTopLevelTypes(ctx) {
|
|
2649
2659
|
return {
|
|
2650
|
-
"TSInterfaceDeclaration|TSTypeAliasDeclaration"(
|
|
2651
|
-
if (!t27.isProgram(
|
|
2652
|
-
const { node } =
|
|
2660
|
+
"TSInterfaceDeclaration|TSTypeAliasDeclaration"(path9) {
|
|
2661
|
+
if (!t27.isProgram(path9.parent)) return;
|
|
2662
|
+
const { node } = path9;
|
|
2653
2663
|
if (t27.isTSInterfaceDeclaration(node)) {
|
|
2654
2664
|
const typeLiteral = t27.tsTypeLiteral(node.body.body);
|
|
2655
2665
|
if (!hasEmitsSignatureInType(typeLiteral)) return;
|
|
@@ -2714,8 +2724,8 @@ function resolveTopLevelEmitType(tsType) {
|
|
|
2714
2724
|
}
|
|
2715
2725
|
return tsType;
|
|
2716
2726
|
}
|
|
2717
|
-
function resolveDefineEmitsIface(
|
|
2718
|
-
const { node } =
|
|
2727
|
+
function resolveDefineEmitsIface(path9, ctx) {
|
|
2728
|
+
const { node } = path9;
|
|
2719
2729
|
const [runtimeArg] = node.arguments;
|
|
2720
2730
|
const tsParams = node.typeParameters?.params;
|
|
2721
2731
|
if (tsParams?.length) {
|
|
@@ -3015,8 +3025,8 @@ function resolveTupleElementParam(element, index) {
|
|
|
3015
3025
|
|
|
3016
3026
|
// src/core/transform/sfc/script/syntax-processor/preprocess/resolve-props-interface/resolve-props.ts
|
|
3017
3027
|
import * as t28 from "@babel/types";
|
|
3018
|
-
function resolveDefinePropsIface(
|
|
3019
|
-
const { node } =
|
|
3028
|
+
function resolveDefinePropsIface(path9, ctx) {
|
|
3029
|
+
const { node } = path9;
|
|
3020
3030
|
const [runtimeArg] = node.arguments;
|
|
3021
3031
|
const tsParams = node.typeParameters?.params;
|
|
3022
3032
|
if (tsParams?.length) {
|
|
@@ -3162,9 +3172,9 @@ var SLOT_CHILDREN_NAME = "children";
|
|
|
3162
3172
|
var SLOT_FN_PARAM_NAME = "props";
|
|
3163
3173
|
function resolveSlotsTopLevelTypes(ctx) {
|
|
3164
3174
|
return {
|
|
3165
|
-
"TSInterfaceDeclaration|TSTypeAliasDeclaration"(
|
|
3166
|
-
if (!t29.isProgram(
|
|
3167
|
-
const { node } =
|
|
3175
|
+
"TSInterfaceDeclaration|TSTypeAliasDeclaration"(path9) {
|
|
3176
|
+
if (!t29.isProgram(path9.parent)) return;
|
|
3177
|
+
const { node } = path9;
|
|
3168
3178
|
if (t29.isTSInterfaceDeclaration(node)) {
|
|
3169
3179
|
const typeLiteral = t29.tsTypeLiteral(node.body.body);
|
|
3170
3180
|
if (!hasSlotsSignatureInType(typeLiteral)) return;
|
|
@@ -3186,8 +3196,8 @@ function resolveSlotsTopLevelTypes(ctx) {
|
|
|
3186
3196
|
}
|
|
3187
3197
|
};
|
|
3188
3198
|
}
|
|
3189
|
-
function resolveDefineSlotsIface(
|
|
3190
|
-
const { node } =
|
|
3199
|
+
function resolveDefineSlotsIface(path9, ctx) {
|
|
3200
|
+
const { node } = path9;
|
|
3191
3201
|
const tsParams = node.typeParameters?.params;
|
|
3192
3202
|
if (!tsParams?.length) return;
|
|
3193
3203
|
const {
|
|
@@ -3378,8 +3388,8 @@ function resolvePropName2(key) {
|
|
|
3378
3388
|
function resolvePropsIface(ctx) {
|
|
3379
3389
|
const isTS = ctx.scriptData.lang.startsWith("ts");
|
|
3380
3390
|
return {
|
|
3381
|
-
CallExpression(
|
|
3382
|
-
const { node, parentPath } =
|
|
3391
|
+
CallExpression(path9) {
|
|
3392
|
+
const { node, parentPath } = path9;
|
|
3383
3393
|
const name = node.callee.name;
|
|
3384
3394
|
if (!isCalleeNamed(node, MACRO_API_NAMES.props) && !isCalleeNamed(node, MACRO_API_NAMES.emits) && !isCalleeNamed(node, MACRO_API_NAMES.slots)) {
|
|
3385
3395
|
return;
|
|
@@ -3388,7 +3398,7 @@ function resolvePropsIface(ctx) {
|
|
|
3388
3398
|
if (parentPath.isVariableDeclaration() || parentPath.isVariableDeclarator()) {
|
|
3389
3399
|
parentPath.remove();
|
|
3390
3400
|
} else {
|
|
3391
|
-
|
|
3401
|
+
path9.remove();
|
|
3392
3402
|
}
|
|
3393
3403
|
};
|
|
3394
3404
|
if (ctx.inputType !== "sfc") {
|
|
@@ -3402,11 +3412,11 @@ function resolvePropsIface(ctx) {
|
|
|
3402
3412
|
propsTSIface.hasPropsInJsEnv = true;
|
|
3403
3413
|
} else {
|
|
3404
3414
|
if (name === MACRO_API_NAMES.props) {
|
|
3405
|
-
resolveDefinePropsIface(
|
|
3415
|
+
resolveDefinePropsIface(path9, ctx);
|
|
3406
3416
|
} else if (name === MACRO_API_NAMES.emits) {
|
|
3407
|
-
resolveDefineEmitsIface(
|
|
3417
|
+
resolveDefineEmitsIface(path9, ctx);
|
|
3408
3418
|
} else if (name === MACRO_API_NAMES.slots) {
|
|
3409
|
-
resolveDefineSlotsIface(
|
|
3419
|
+
resolveDefineSlotsIface(path9, ctx);
|
|
3410
3420
|
}
|
|
3411
3421
|
}
|
|
3412
3422
|
removePath();
|
|
@@ -3451,15 +3461,27 @@ function analyzeDeps(node, ctx, parentPath) {
|
|
|
3451
3461
|
function addDependency(exp) {
|
|
3452
3462
|
deps.set(getDependencyKey(exp), exp);
|
|
3453
3463
|
}
|
|
3464
|
+
const analyzeTargetPath = parentPath && parentPath.node === analyzeTarget ? parentPath : null;
|
|
3465
|
+
if (analyzeTargetPath) {
|
|
3466
|
+
if (t31.isMemberExpression(analyzeTarget) || t31.isOptionalMemberExpression(analyzeTarget)) {
|
|
3467
|
+
const rootId = findRootIdentifier(analyzeTarget);
|
|
3468
|
+
if (rootId) {
|
|
3469
|
+
tryAddDependency(analyzeTargetPath, rootId.name, analyzeTargetPath.scope);
|
|
3470
|
+
processedIdentifiers.add(rootId);
|
|
3471
|
+
}
|
|
3472
|
+
} else if (t31.isIdentifier(analyzeTarget)) {
|
|
3473
|
+
tryAddDependency(analyzeTargetPath, analyzeTarget.name, analyzeTargetPath.scope);
|
|
3474
|
+
}
|
|
3475
|
+
}
|
|
3454
3476
|
traverse2(
|
|
3455
3477
|
analyzeTarget,
|
|
3456
3478
|
{
|
|
3457
3479
|
"MemberExpression|OptionalMemberExpression"(memberPath) {
|
|
3458
|
-
const
|
|
3459
|
-
if (isNestedMemberObject(
|
|
3460
|
-
const rootId = findRootIdentifier(
|
|
3480
|
+
const path9 = memberPath;
|
|
3481
|
+
if (isNestedMemberObject(path9)) return;
|
|
3482
|
+
const rootId = findRootIdentifier(path9.node);
|
|
3461
3483
|
if (!rootId) return;
|
|
3462
|
-
tryAddDependency(
|
|
3484
|
+
tryAddDependency(path9, rootId.name, path9.scope);
|
|
3463
3485
|
processedIdentifiers.add(rootId);
|
|
3464
3486
|
},
|
|
3465
3487
|
Identifier(idPath) {
|
|
@@ -3491,16 +3513,19 @@ function analyzeDeps(node, ctx, parentPath) {
|
|
|
3491
3513
|
}
|
|
3492
3514
|
const sourcedExpression = traceBindingSource(binding, /* @__PURE__ */ new Set(), TRACE_MAX_DEPTH);
|
|
3493
3515
|
if (sourcedExpression) {
|
|
3494
|
-
|
|
3516
|
+
const normalizedSource = normalizeSourcedDependency(sourcedExpression);
|
|
3517
|
+
if (normalizedSource) {
|
|
3518
|
+
addDependency(normalizedSource);
|
|
3519
|
+
}
|
|
3495
3520
|
}
|
|
3496
3521
|
}
|
|
3497
|
-
function normalizeDependencyExpr(
|
|
3498
|
-
if (t31.isIdentifier(
|
|
3499
|
-
return t31.identifier(
|
|
3522
|
+
function normalizeDependencyExpr(path9, rootName) {
|
|
3523
|
+
if (t31.isIdentifier(path9.node)) {
|
|
3524
|
+
return t31.identifier(path9.node.name);
|
|
3500
3525
|
}
|
|
3501
|
-
if (t31.isMemberExpression(
|
|
3502
|
-
const normalizedExp = normalizeMemberForCallSite(
|
|
3503
|
-
const safeExp = t31.isMemberExpression(normalizedExp) || t31.isOptionalMemberExpression(normalizedExp) ?
|
|
3526
|
+
if (t31.isMemberExpression(path9.node) || t31.isOptionalMemberExpression(path9.node)) {
|
|
3527
|
+
const normalizedExp = normalizeMemberForCallSite(path9, path9.node);
|
|
3528
|
+
const safeExp = t31.isMemberExpression(normalizedExp) || t31.isOptionalMemberExpression(normalizedExp) ? ensureOptionalForMemberChain(normalizedExp) : normalizedExp;
|
|
3504
3529
|
if (isReactValidDependencyExpr(safeExp)) {
|
|
3505
3530
|
return t31.cloneNode(safeExp, true);
|
|
3506
3531
|
}
|
|
@@ -3508,6 +3533,21 @@ function analyzeDeps(node, ctx, parentPath) {
|
|
|
3508
3533
|
}
|
|
3509
3534
|
return null;
|
|
3510
3535
|
}
|
|
3536
|
+
function normalizeSourcedDependency(exp) {
|
|
3537
|
+
if (t31.isIdentifier(exp)) {
|
|
3538
|
+
return t31.identifier(exp.name);
|
|
3539
|
+
}
|
|
3540
|
+
if (t31.isMemberExpression(exp) || t31.isOptionalMemberExpression(exp)) {
|
|
3541
|
+
const root = findRootIdentifier(exp);
|
|
3542
|
+
if (!root) return null;
|
|
3543
|
+
const safeExp = t31.isMemberExpression(exp) || t31.isOptionalMemberExpression(exp) ? ensureOptionalForMemberChain(exp) : exp;
|
|
3544
|
+
if (isReactValidDependencyExpr(safeExp)) {
|
|
3545
|
+
return t31.cloneNode(safeExp, true);
|
|
3546
|
+
}
|
|
3547
|
+
return t31.identifier(root.name);
|
|
3548
|
+
}
|
|
3549
|
+
return null;
|
|
3550
|
+
}
|
|
3511
3551
|
function isReactValidDependencyExpr(node2) {
|
|
3512
3552
|
if (t31.isIdentifier(node2)) {
|
|
3513
3553
|
return true;
|
|
@@ -3540,8 +3580,8 @@ function analyzeDeps(node, ctx, parentPath) {
|
|
|
3540
3580
|
}
|
|
3541
3581
|
return false;
|
|
3542
3582
|
}
|
|
3543
|
-
function normalizeMemberForCallSite(
|
|
3544
|
-
const parent =
|
|
3583
|
+
function normalizeMemberForCallSite(path9, node2) {
|
|
3584
|
+
const parent = path9.parentPath;
|
|
3545
3585
|
const isDirectCallee = !!parent && (parent.isCallExpression() && parent.node.callee === node2 || parent.isOptionalCallExpression() && parent.node.callee === node2);
|
|
3546
3586
|
if (!isDirectCallee) {
|
|
3547
3587
|
return node2;
|
|
@@ -3551,8 +3591,8 @@ function analyzeDeps(node, ctx, parentPath) {
|
|
|
3551
3591
|
}
|
|
3552
3592
|
return node2.object;
|
|
3553
3593
|
}
|
|
3554
|
-
function
|
|
3555
|
-
if (!
|
|
3594
|
+
function ensureOptionalForMemberChain(node2) {
|
|
3595
|
+
if (!hasTrailingMemberAccess(node2)) {
|
|
3556
3596
|
return node2;
|
|
3557
3597
|
}
|
|
3558
3598
|
if (t31.isOptionalMemberExpression(node2) && node2.optional) {
|
|
@@ -3562,19 +3602,8 @@ function analyzeDeps(node, ctx, parentPath) {
|
|
|
3562
3602
|
const property = t31.cloneNode(node2.property, true);
|
|
3563
3603
|
return t31.optionalMemberExpression(object, property, node2.computed, true);
|
|
3564
3604
|
}
|
|
3565
|
-
function
|
|
3566
|
-
|
|
3567
|
-
while (t31.isMemberExpression(current) || t31.isOptionalMemberExpression(current)) {
|
|
3568
|
-
if (current.computed) {
|
|
3569
|
-
if (t31.isStringLiteral(current.property) && current.property.value === "value") {
|
|
3570
|
-
return true;
|
|
3571
|
-
}
|
|
3572
|
-
} else if (t31.isIdentifier(current.property) && current.property.name === "value") {
|
|
3573
|
-
return true;
|
|
3574
|
-
}
|
|
3575
|
-
current = current.object;
|
|
3576
|
-
}
|
|
3577
|
-
return false;
|
|
3605
|
+
function hasTrailingMemberAccess(node2) {
|
|
3606
|
+
return t31.isMemberExpression(node2.object) || t31.isOptionalMemberExpression(node2.object);
|
|
3578
3607
|
}
|
|
3579
3608
|
function isEligibleBindingSource(binding) {
|
|
3580
3609
|
if (binding.kind === "param") {
|
|
@@ -3582,16 +3611,13 @@ function analyzeDeps(node, ctx, parentPath) {
|
|
|
3582
3611
|
}
|
|
3583
3612
|
const bindingPath = binding.path;
|
|
3584
3613
|
const declaratorPath = getVariableDeclaratorPath(bindingPath);
|
|
3585
|
-
const isImportBinding = bindingPath.isImportSpecifier() || bindingPath.isImportDefaultSpecifier() || bindingPath.isImportNamespaceSpecifier();
|
|
3586
3614
|
const isReactiveVarBinding = !!declaratorPath && isReactiveBinding(declaratorPath.node);
|
|
3587
3615
|
const nodeInit = declaratorPath?.node.init;
|
|
3588
3616
|
const isReactiveApiCallVarBinding = !!declaratorPath && t31.isCallExpression(nodeInit) && t31.isIdentifier(nodeInit.callee) && reactiveStateApis.has(nodeInit.callee.name);
|
|
3589
3617
|
const isHookCallVarBinding = !!declaratorPath && t31.isCallExpression(nodeInit) && isHookLikeCallee(nodeInit.callee);
|
|
3590
3618
|
const isFunctionBinding = bindingPath.isFunctionDeclaration() || !!declaratorPath && !!nodeInit && (t31.isArrowFunctionExpression(nodeInit) || t31.isFunctionExpression(nodeInit));
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
}
|
|
3594
|
-
return isImportBinding || isReactiveVarBinding || isReactiveApiCallVarBinding || isHookCallVarBinding || isFunctionBinding;
|
|
3619
|
+
const isReactiveFunctionBinding = isFunctionBinding && (isReactiveBinding(declaratorPath?.node) || isReactiveBinding(bindingPath.node));
|
|
3620
|
+
return isReactiveVarBinding || isReactiveApiCallVarBinding || isHookCallVarBinding || isReactiveFunctionBinding;
|
|
3595
3621
|
}
|
|
3596
3622
|
function isHookLikeCallee(callee) {
|
|
3597
3623
|
if (t31.isIdentifier(callee)) {
|
|
@@ -3687,11 +3713,11 @@ function getDependencyKey(exp) {
|
|
|
3687
3713
|
}
|
|
3688
3714
|
return exp.type;
|
|
3689
3715
|
}
|
|
3690
|
-
function isNestedMemberObject(
|
|
3691
|
-
const parent =
|
|
3716
|
+
function isNestedMemberObject(path9) {
|
|
3717
|
+
const parent = path9.parentPath;
|
|
3692
3718
|
if (!parent) return false;
|
|
3693
3719
|
if (parent.isMemberExpression() || parent.isOptionalMemberExpression()) {
|
|
3694
|
-
return parent.node.object ===
|
|
3720
|
+
return parent.node.object === path9.node;
|
|
3695
3721
|
}
|
|
3696
3722
|
return false;
|
|
3697
3723
|
}
|
|
@@ -3699,27 +3725,19 @@ function isReactiveBinding(node) {
|
|
|
3699
3725
|
if (!node) return false;
|
|
3700
3726
|
return !!getScriptNodeMeta(node)?.is_reactive;
|
|
3701
3727
|
}
|
|
3702
|
-
function markAsAnalyzed(node, flag = true) {
|
|
3703
|
-
const analyzed = getIsAnalyzed(node);
|
|
3704
|
-
if (analyzed) return;
|
|
3705
|
-
setScriptNodeMeta(node, { is_deps_analyzed: flag });
|
|
3706
|
-
}
|
|
3707
|
-
function getIsAnalyzed(node) {
|
|
3708
|
-
return getScriptNodeMeta(node)?.is_deps_analyzed;
|
|
3709
|
-
}
|
|
3710
3728
|
|
|
3711
3729
|
// src/core/transform/sfc/script/syntax-processor/process/resolve-analysis-only-adapter.ts
|
|
3712
3730
|
function resolveAnalysisOnlyAdapter(ctx) {
|
|
3713
3731
|
return {
|
|
3714
|
-
"CallExpression|Identifier"(
|
|
3715
|
-
const node =
|
|
3732
|
+
"CallExpression|Identifier"(path9) {
|
|
3733
|
+
const node = path9.node;
|
|
3716
3734
|
const apiName = getApiName(node);
|
|
3717
3735
|
const adapter = ADAPTER_RULES.runtime[apiName];
|
|
3718
3736
|
if (!adapter || adapter.type !== "analyzed-deps") {
|
|
3719
3737
|
return;
|
|
3720
3738
|
}
|
|
3721
3739
|
if (t32.isCallExpression(node)) {
|
|
3722
|
-
resolveCallNode(
|
|
3740
|
+
resolveCallNode(path9, adapter, ctx);
|
|
3723
3741
|
} else {
|
|
3724
3742
|
replaceIdName(node, adapter.target);
|
|
3725
3743
|
}
|
|
@@ -3737,15 +3755,15 @@ function getApiName(node) {
|
|
|
3737
3755
|
}
|
|
3738
3756
|
return apiName;
|
|
3739
3757
|
}
|
|
3740
|
-
function resolveCallNode(
|
|
3741
|
-
const { node } =
|
|
3758
|
+
function resolveCallNode(path9, adapter, ctx) {
|
|
3759
|
+
const { node } = path9;
|
|
3742
3760
|
const { arguments: args } = node;
|
|
3743
3761
|
if (!args.length) return;
|
|
3744
3762
|
const fn = args[0];
|
|
3745
3763
|
if (!t32.isArrowFunctionExpression(fn) && !t32.isFunctionExpression(fn)) {
|
|
3746
3764
|
return;
|
|
3747
3765
|
}
|
|
3748
|
-
const fnPath =
|
|
3766
|
+
const fnPath = path9.get("arguments")[0];
|
|
3749
3767
|
const deps = analyzeDeps(fn, ctx, fnPath);
|
|
3750
3768
|
args.push(deps);
|
|
3751
3769
|
replaceCallName(node, adapter.target);
|
|
@@ -3755,41 +3773,24 @@ function resolveCallNode(path8, adapter, ctx) {
|
|
|
3755
3773
|
// src/core/transform/sfc/script/syntax-processor/process/resolve-arrow-deps.ts
|
|
3756
3774
|
function resolveArrowFnDeps(ctx, ast) {
|
|
3757
3775
|
return {
|
|
3758
|
-
ArrowFunctionExpression(
|
|
3759
|
-
const { node, parentPath } =
|
|
3760
|
-
if (isSkip(
|
|
3776
|
+
ArrowFunctionExpression(path9) {
|
|
3777
|
+
const { node, parentPath } = path9;
|
|
3778
|
+
if (isSkip(path9) || !atComponentOrHookRoot(parentPath, ast.program)) {
|
|
3761
3779
|
return;
|
|
3762
3780
|
}
|
|
3763
|
-
const deps = analyzeDeps(node, ctx,
|
|
3781
|
+
const deps = analyzeDeps(node, ctx, path9);
|
|
3764
3782
|
if (!deps.elements.length) return;
|
|
3765
3783
|
const newNode = createUseCallback(node, deps);
|
|
3766
|
-
const declaratorPath = getVariableDeclaratorPath(
|
|
3767
|
-
markAsAnalyzed(newNode.arguments[0]);
|
|
3784
|
+
const declaratorPath = getVariableDeclaratorPath(path9);
|
|
3768
3785
|
recordImport(ctx, PACKAGE_NAME.react, REACT_API_MAP.useCallback);
|
|
3769
3786
|
setScriptNodeMeta(declaratorPath?.node, { is_reactive: true, reactive_type: "indirect" });
|
|
3770
|
-
|
|
3771
|
-
}
|
|
3772
|
-
};
|
|
3773
|
-
}
|
|
3774
|
-
function resolveUnanalyzedArrow(ctx) {
|
|
3775
|
-
return {
|
|
3776
|
-
ArrowFunctionExpression(path8) {
|
|
3777
|
-
const { node } = path8;
|
|
3778
|
-
const analyzed = getIsAnalyzed(node);
|
|
3779
|
-
if (typeof analyzed === "undefined" || analyzed) return;
|
|
3780
|
-
const newNode = createUseCallback(node);
|
|
3781
|
-
const declaratorPath = getVariableDeclaratorPath(path8);
|
|
3782
|
-
if (declaratorPath?.node) {
|
|
3783
|
-
setScriptNodeMeta(declaratorPath.node, { is_reactive: true, reactive_type: "indirect" });
|
|
3784
|
-
}
|
|
3785
|
-
markAsAnalyzed(newNode.arguments[0]);
|
|
3786
|
-
path8.replaceWith(newNode);
|
|
3787
|
+
path9.replaceWith(newNode);
|
|
3787
3788
|
}
|
|
3788
3789
|
};
|
|
3789
3790
|
}
|
|
3790
|
-
function isSkip(
|
|
3791
|
-
const { parentPath } =
|
|
3792
|
-
const isVariableDecl = () => getVariableDeclaratorPath(
|
|
3791
|
+
function isSkip(path9) {
|
|
3792
|
+
const { parentPath } = path9;
|
|
3793
|
+
const isVariableDecl = () => getVariableDeclaratorPath(path9) !== null;
|
|
3793
3794
|
const isReturnFunc = () => !isVariableDecl() && parentPath.isReturnStatement();
|
|
3794
3795
|
const isCallback = () => {
|
|
3795
3796
|
if (!parentPath) {
|
|
@@ -3798,12 +3799,12 @@ function isSkip(path8) {
|
|
|
3798
3799
|
if (parentPath.isCallExpression()) {
|
|
3799
3800
|
const callExpressionPath = parentPath;
|
|
3800
3801
|
const args = callExpressionPath.node.arguments;
|
|
3801
|
-
return args.some((arg) => arg ===
|
|
3802
|
+
return args.some((arg) => arg === path9.node);
|
|
3802
3803
|
}
|
|
3803
3804
|
if (parentPath.isArrayExpression()) {
|
|
3804
3805
|
const arrayExpressionPath = parentPath;
|
|
3805
3806
|
const elements = arrayExpressionPath.node.elements;
|
|
3806
|
-
return elements.some((element) => element ===
|
|
3807
|
+
return elements.some((element) => element === path9.node);
|
|
3807
3808
|
}
|
|
3808
3809
|
return false;
|
|
3809
3810
|
};
|
|
@@ -3827,13 +3828,13 @@ function isSkip(path8) {
|
|
|
3827
3828
|
import * as t33 from "@babel/types";
|
|
3828
3829
|
function resolveElementRef(ctx) {
|
|
3829
3830
|
return {
|
|
3830
|
-
CallExpression(
|
|
3831
|
+
CallExpression(path9) {
|
|
3831
3832
|
const {
|
|
3832
3833
|
inputType,
|
|
3833
3834
|
templateData: { refBindings }
|
|
3834
3835
|
} = ctx;
|
|
3835
3836
|
if (inputType !== "sfc") return;
|
|
3836
|
-
const { node } =
|
|
3837
|
+
const { node } = path9;
|
|
3837
3838
|
const isUseTemplateRef = isCalleeNamed(node, VUE_API_MAP.useTemplateRef);
|
|
3838
3839
|
const isCompRefBindings = Object.keys(refBindings.componentRefs).length > 0 && isCalleeNamed(node, VUE_API_MAP.ref);
|
|
3839
3840
|
const shouldProcess = isUseTemplateRef || isCompRefBindings;
|
|
@@ -3841,7 +3842,7 @@ function resolveElementRef(ctx) {
|
|
|
3841
3842
|
return;
|
|
3842
3843
|
}
|
|
3843
3844
|
if (isCompRefBindings) {
|
|
3844
|
-
const varDeclaratorPath = getVariableDeclaratorPath(
|
|
3845
|
+
const varDeclaratorPath = getVariableDeclaratorPath(path9)?.node;
|
|
3845
3846
|
if (!t33.isIdentifier(varDeclaratorPath?.id)) {
|
|
3846
3847
|
return;
|
|
3847
3848
|
}
|
|
@@ -3850,22 +3851,22 @@ function resolveElementRef(ctx) {
|
|
|
3850
3851
|
if (!compRef) return;
|
|
3851
3852
|
}
|
|
3852
3853
|
node.arguments[0] = t33.identifier("null");
|
|
3853
|
-
resolveTypeParameters(ctx,
|
|
3854
|
+
resolveTypeParameters(ctx, path9);
|
|
3854
3855
|
replaceCallName(node, REACT_API_MAP.useRef);
|
|
3855
3856
|
recordImport(ctx, PACKAGE_NAME.react, REACT_API_MAP.useRef);
|
|
3856
3857
|
},
|
|
3857
|
-
MemberExpression(
|
|
3858
|
-
resolveRefValueToCurrent(
|
|
3858
|
+
MemberExpression(path9) {
|
|
3859
|
+
resolveRefValueToCurrent(path9);
|
|
3859
3860
|
}
|
|
3860
3861
|
};
|
|
3861
3862
|
}
|
|
3862
|
-
function resolveTypeParameters(ctx,
|
|
3863
|
+
function resolveTypeParameters(ctx, path9) {
|
|
3863
3864
|
const {
|
|
3864
3865
|
templateData: { refBindings },
|
|
3865
3866
|
scriptData
|
|
3866
3867
|
} = ctx;
|
|
3867
|
-
const { node } =
|
|
3868
|
-
const varDeclaratorNode = getVariableDeclaratorPath(
|
|
3868
|
+
const { node } = path9;
|
|
3869
|
+
const varDeclaratorNode = getVariableDeclaratorPath(path9)?.node;
|
|
3869
3870
|
if (!scriptData.lang.startsWith("ts") || !varDeclaratorNode) {
|
|
3870
3871
|
return;
|
|
3871
3872
|
}
|
|
@@ -3877,12 +3878,12 @@ function resolveTypeParameters(ctx, path8) {
|
|
|
3877
3878
|
node.typeParameters = t33.tsTypeParameterInstantiation([t33.tsTypeReference(t33.identifier(type))]);
|
|
3878
3879
|
}
|
|
3879
3880
|
}
|
|
3880
|
-
function resolveRefValueToCurrent(
|
|
3881
|
-
const { node } =
|
|
3881
|
+
function resolveRefValueToCurrent(path9) {
|
|
3882
|
+
const { node } = path9;
|
|
3882
3883
|
if (node.computed || !t33.isIdentifier(node.property) || node.property.name !== "value") {
|
|
3883
3884
|
return;
|
|
3884
3885
|
}
|
|
3885
|
-
const rootPath = findRootVariablePath(
|
|
3886
|
+
const rootPath = findRootVariablePath(path9);
|
|
3886
3887
|
if (!rootPath?.node || !t33.isCallExpression(rootPath.node.init) || !isCalleeNamed(rootPath.node.init, REACT_API_MAP.useRef)) {
|
|
3887
3888
|
return;
|
|
3888
3889
|
}
|
|
@@ -3898,21 +3899,25 @@ import * as t34 from "@babel/types";
|
|
|
3898
3899
|
function resolveExprMemo(ctx, ast) {
|
|
3899
3900
|
const isScriptFile = ctx.inputType !== "sfc";
|
|
3900
3901
|
return {
|
|
3901
|
-
VariableDeclarator(
|
|
3902
|
-
const { node } =
|
|
3902
|
+
VariableDeclarator(path9) {
|
|
3903
|
+
const { node } = path9;
|
|
3903
3904
|
const { init } = node;
|
|
3904
|
-
if (!init) return;
|
|
3905
3905
|
const shouldMemo = () => {
|
|
3906
|
-
if (!
|
|
3906
|
+
if (!init) return false;
|
|
3907
|
+
if (!atComponentOrHookRoot(path9, ast.program, isScriptFile)) {
|
|
3907
3908
|
return false;
|
|
3908
3909
|
}
|
|
3910
|
+
if (!t34.isVariableDeclaration(path9.parent) || path9.parent.kind !== "const") {
|
|
3911
|
+
return false;
|
|
3912
|
+
}
|
|
3913
|
+
if (t34.isFunction(init)) return false;
|
|
3909
3914
|
if (t34.isCallExpression(init) && t34.isIdentifier(init.callee) && init.callee.name.startsWith("use")) {
|
|
3910
3915
|
return false;
|
|
3911
3916
|
}
|
|
3912
3917
|
return true;
|
|
3913
3918
|
};
|
|
3914
3919
|
if (!shouldMemo()) return;
|
|
3915
|
-
const initPath =
|
|
3920
|
+
const initPath = path9.get("init");
|
|
3916
3921
|
if (!initPath.isExpression()) return;
|
|
3917
3922
|
const deps = analyzeDeps(initPath.node, ctx, initPath);
|
|
3918
3923
|
if (!deps.elements.length) return;
|
|
@@ -3928,8 +3933,8 @@ import * as t35 from "@babel/types";
|
|
|
3928
3933
|
function resolveLintRules(ctx, ast) {
|
|
3929
3934
|
const inScriptFile = ctx.inputType !== "sfc";
|
|
3930
3935
|
return {
|
|
3931
|
-
CallExpression(
|
|
3932
|
-
const { node, parentPath } =
|
|
3936
|
+
CallExpression(path9) {
|
|
3937
|
+
const { node, parentPath } = path9;
|
|
3933
3938
|
if (!t35.isIdentifier(node.callee)) return;
|
|
3934
3939
|
const { name: callName } = node.callee;
|
|
3935
3940
|
const addLog = (t41) => {
|
|
@@ -3948,7 +3953,7 @@ function resolveLintRules(ctx, ast) {
|
|
|
3948
3953
|
);
|
|
3949
3954
|
return;
|
|
3950
3955
|
}
|
|
3951
|
-
if (!atComponentOrHookRoot(
|
|
3956
|
+
if (!atComponentOrHookRoot(path9, ast.program)) {
|
|
3952
3957
|
addLog(
|
|
3953
3958
|
`The ${macro} must be defined at the top level of the component, not inside blocks or functions.`
|
|
3954
3959
|
);
|
|
@@ -3964,7 +3969,7 @@ function resolveLintRules(ctx, ast) {
|
|
|
3964
3969
|
};
|
|
3965
3970
|
const lintHooks = () => {
|
|
3966
3971
|
if (!callName.startsWith("use")) return;
|
|
3967
|
-
if (!atComponentOrHookRoot(
|
|
3972
|
+
if (!atComponentOrHookRoot(path9, ast.program, inScriptFile)) {
|
|
3968
3973
|
addLog(
|
|
3969
3974
|
`The ${callName} hook must be called at the top level, not inside loops, conditions, or nested functions.`
|
|
3970
3975
|
);
|
|
@@ -3982,8 +3987,8 @@ import * as t36 from "@babel/types";
|
|
|
3982
3987
|
function resolveProvide(ctx) {
|
|
3983
3988
|
if (ctx.inputType === "style") return {};
|
|
3984
3989
|
return {
|
|
3985
|
-
CallExpression(
|
|
3986
|
-
const { node } =
|
|
3990
|
+
CallExpression(path9) {
|
|
3991
|
+
const { node } = path9;
|
|
3987
3992
|
const providerTarget = ADAPTER_RULES.runtime[VUE_API_MAP.provide]?.target;
|
|
3988
3993
|
const isProvideCall = isCalleeNamed(node, VUE_API_MAP.provide) || providerTarget && isCalleeNamed(node, providerTarget);
|
|
3989
3994
|
if (!isProvideCall) return;
|
|
@@ -3993,7 +3998,7 @@ function resolveProvide(ctx) {
|
|
|
3993
3998
|
const adapter = ADAPTER_RULES.runtime[VUE_API_MAP.provide];
|
|
3994
3999
|
assignProviderValue(target, key, value);
|
|
3995
4000
|
recordImport(ctx, adapter.package, adapter.target);
|
|
3996
|
-
|
|
4001
|
+
path9.parentPath.remove();
|
|
3997
4002
|
}
|
|
3998
4003
|
};
|
|
3999
4004
|
}
|
|
@@ -4035,8 +4040,8 @@ function assignProviderValue(target, key, value) {
|
|
|
4035
4040
|
import * as t37 from "@babel/types";
|
|
4036
4041
|
function resolveRenameAdapter(ctx) {
|
|
4037
4042
|
return {
|
|
4038
|
-
"CallExpression|Identifier"(
|
|
4039
|
-
const node =
|
|
4043
|
+
"CallExpression|Identifier"(path9) {
|
|
4044
|
+
const node = path9.node;
|
|
4040
4045
|
const isCallNode = t37.isCallExpression(node);
|
|
4041
4046
|
let apiName = "";
|
|
4042
4047
|
if (t37.isIdentifier(node)) {
|
|
@@ -4052,7 +4057,7 @@ function resolveRenameAdapter(ctx) {
|
|
|
4052
4057
|
}
|
|
4053
4058
|
if (adapter.isTrackable) {
|
|
4054
4059
|
const reactiveType = getReactiveType(apiName);
|
|
4055
|
-
const declaratorPath = getVariableDeclaratorPath(
|
|
4060
|
+
const declaratorPath = getVariableDeclaratorPath(path9);
|
|
4056
4061
|
setScriptNodeMeta(declaratorPath?.node, {
|
|
4057
4062
|
is_reactive: true,
|
|
4058
4063
|
reactive_type: reactiveType
|
|
@@ -4091,10 +4096,11 @@ function processVueSyntax2(ast, ctx) {
|
|
|
4091
4096
|
// provide 需要在 rename 之前收集并移除原始调用,避免被重命名后失配
|
|
4092
4097
|
resolveProvide,
|
|
4093
4098
|
resolveRenameAdapter,
|
|
4099
|
+
// fix:在分析函数前分析可优化为 useMemo 的顶层变量声明,
|
|
4100
|
+
// 使得后续能够被函数依赖分析
|
|
4101
|
+
resolveExprMemo,
|
|
4094
4102
|
resolveArrowFnDeps,
|
|
4095
|
-
resolveUnanalyzedArrow,
|
|
4096
4103
|
resolveAnalysisOnlyAdapter,
|
|
4097
|
-
resolveExprMemo,
|
|
4098
4104
|
resolveLintRules
|
|
4099
4105
|
],
|
|
4100
4106
|
excludeBabel: [resolveTemplateSlotIface, resolveCompIProps]
|
|
@@ -5460,12 +5466,12 @@ function transform(ast, ctx, options) {
|
|
|
5460
5466
|
}
|
|
5461
5467
|
|
|
5462
5468
|
// package.json
|
|
5463
|
-
var version = "1.
|
|
5469
|
+
var version = "1.4.0";
|
|
5464
5470
|
var bin = {
|
|
5465
5471
|
vureact: "./bin/vureact.js"
|
|
5466
5472
|
};
|
|
5467
5473
|
|
|
5468
|
-
// src/compiler/shared/types.ts
|
|
5474
|
+
// src/compiler/shared/types/cache-types.ts
|
|
5469
5475
|
var CacheKey = /* @__PURE__ */ ((CacheKey2) => {
|
|
5470
5476
|
CacheKey2["SFC"] = "sfc";
|
|
5471
5477
|
CacheKey2["SCRIPT"] = "script";
|
|
@@ -5507,10 +5513,146 @@ function simpleFormat(code) {
|
|
|
5507
5513
|
}
|
|
5508
5514
|
|
|
5509
5515
|
// src/compiler/shared/helper.ts
|
|
5510
|
-
import
|
|
5516
|
+
import fs2 from "fs";
|
|
5517
|
+
import kleur4 from "kleur";
|
|
5518
|
+
import path3 from "path";
|
|
5519
|
+
|
|
5520
|
+
// src/compiler/shared/file-lock-manager.ts
|
|
5511
5521
|
import fs from "fs";
|
|
5512
5522
|
import kleur3 from "kleur";
|
|
5513
5523
|
import path2 from "path";
|
|
5524
|
+
import lockfile from "proper-lockfile";
|
|
5525
|
+
var FileLockManager = class _FileLockManager {
|
|
5526
|
+
static instance;
|
|
5527
|
+
/**
|
|
5528
|
+
* 获取单例实例
|
|
5529
|
+
*/
|
|
5530
|
+
static getInstance() {
|
|
5531
|
+
if (!_FileLockManager.instance) {
|
|
5532
|
+
_FileLockManager.instance = new _FileLockManager();
|
|
5533
|
+
}
|
|
5534
|
+
return _FileLockManager.instance;
|
|
5535
|
+
}
|
|
5536
|
+
/**
|
|
5537
|
+
* 获取文件锁并更新文件内容
|
|
5538
|
+
* @param filePath 文件路径
|
|
5539
|
+
* @param updater 更新函数,接收当前内容,返回更新后的内容
|
|
5540
|
+
* @param options 锁选项
|
|
5541
|
+
*/
|
|
5542
|
+
async updateFile(filePath, updater, options = {}) {
|
|
5543
|
+
return this.withLock(
|
|
5544
|
+
filePath,
|
|
5545
|
+
async () => {
|
|
5546
|
+
let current = null;
|
|
5547
|
+
try {
|
|
5548
|
+
const content = await fs.promises.readFile(filePath, "utf-8");
|
|
5549
|
+
if (content.trim()) {
|
|
5550
|
+
try {
|
|
5551
|
+
current = JSON.parse(content);
|
|
5552
|
+
} catch {
|
|
5553
|
+
current = content;
|
|
5554
|
+
}
|
|
5555
|
+
}
|
|
5556
|
+
} catch (error) {
|
|
5557
|
+
console.error(kleur3.red("\u2716"), `Failed to read file ${filePath}`);
|
|
5558
|
+
console.error(error);
|
|
5559
|
+
}
|
|
5560
|
+
const updated = await updater(current);
|
|
5561
|
+
const contentToWrite = typeof updated === "string" ? updated : JSON.stringify(updated, null, 2);
|
|
5562
|
+
await this.writeFile(filePath, contentToWrite);
|
|
5563
|
+
return updated;
|
|
5564
|
+
},
|
|
5565
|
+
options
|
|
5566
|
+
);
|
|
5567
|
+
}
|
|
5568
|
+
/**
|
|
5569
|
+
* 获取文件锁并执行操作
|
|
5570
|
+
* @param filePath 文件路径
|
|
5571
|
+
* @param operation 要执行的操作函数
|
|
5572
|
+
* @param options 锁选项
|
|
5573
|
+
*/
|
|
5574
|
+
async withLock(filePath, operation, options = {}) {
|
|
5575
|
+
const {
|
|
5576
|
+
stale = 1e4,
|
|
5577
|
+
update = stale / 2,
|
|
5578
|
+
retries = 5,
|
|
5579
|
+
realpath = true,
|
|
5580
|
+
lockfilePath
|
|
5581
|
+
} = options;
|
|
5582
|
+
await fs.promises.mkdir(path2.dirname(filePath), { recursive: true });
|
|
5583
|
+
try {
|
|
5584
|
+
await fs.promises.access(filePath);
|
|
5585
|
+
} catch {
|
|
5586
|
+
await this.writeFile(filePath, "");
|
|
5587
|
+
}
|
|
5588
|
+
const release = await lockfile.lock(filePath, {
|
|
5589
|
+
stale,
|
|
5590
|
+
update,
|
|
5591
|
+
retries,
|
|
5592
|
+
realpath,
|
|
5593
|
+
lockfilePath
|
|
5594
|
+
});
|
|
5595
|
+
try {
|
|
5596
|
+
return await operation();
|
|
5597
|
+
} finally {
|
|
5598
|
+
await release();
|
|
5599
|
+
}
|
|
5600
|
+
}
|
|
5601
|
+
/**
|
|
5602
|
+
* 检查文件是否被锁定
|
|
5603
|
+
* @param filePath 文件路径
|
|
5604
|
+
* @param options 锁选项
|
|
5605
|
+
*/
|
|
5606
|
+
async isLocked(filePath, options = {}) {
|
|
5607
|
+
const { stale = 1e4, realpath = true, lockfilePath } = options;
|
|
5608
|
+
try {
|
|
5609
|
+
return await lockfile.check(filePath, { stale, realpath, lockfilePath });
|
|
5610
|
+
} catch {
|
|
5611
|
+
return false;
|
|
5612
|
+
}
|
|
5613
|
+
}
|
|
5614
|
+
/**
|
|
5615
|
+
* 尝试获取锁(非阻塞)
|
|
5616
|
+
* @param filePath 文件路径
|
|
5617
|
+
* @param options 锁选项
|
|
5618
|
+
* @returns 如果成功获取锁,返回释放函数;否则返回 null
|
|
5619
|
+
*/
|
|
5620
|
+
async tryLock(filePath, options = {}) {
|
|
5621
|
+
const { stale = 1e4, update = stale / 2, realpath = true, lockfilePath } = options;
|
|
5622
|
+
try {
|
|
5623
|
+
const release = await lockfile.lock(filePath, {
|
|
5624
|
+
stale,
|
|
5625
|
+
update,
|
|
5626
|
+
retries: 0,
|
|
5627
|
+
// 不重试
|
|
5628
|
+
realpath,
|
|
5629
|
+
lockfilePath
|
|
5630
|
+
});
|
|
5631
|
+
return release;
|
|
5632
|
+
} catch {
|
|
5633
|
+
return null;
|
|
5634
|
+
}
|
|
5635
|
+
}
|
|
5636
|
+
/**
|
|
5637
|
+
* 释放文件锁
|
|
5638
|
+
* @param filePath 文件路径
|
|
5639
|
+
* @param options 锁选项
|
|
5640
|
+
*/
|
|
5641
|
+
async unlock(filePath, options = {}) {
|
|
5642
|
+
const { realpath = true, lockfilePath } = options;
|
|
5643
|
+
try {
|
|
5644
|
+
await lockfile.unlock(filePath, { realpath, lockfilePath });
|
|
5645
|
+
} catch {
|
|
5646
|
+
}
|
|
5647
|
+
}
|
|
5648
|
+
async writeFile(filePath, content) {
|
|
5649
|
+
await fs.promises.mkdir(path2.dirname(filePath), { recursive: true });
|
|
5650
|
+
await fs.promises.writeFile(filePath, content, "utf-8");
|
|
5651
|
+
}
|
|
5652
|
+
};
|
|
5653
|
+
var fileLock = FileLockManager.getInstance();
|
|
5654
|
+
|
|
5655
|
+
// src/compiler/shared/helper.ts
|
|
5514
5656
|
var Helper = class {
|
|
5515
5657
|
compilerOpts;
|
|
5516
5658
|
pathFilter;
|
|
@@ -5535,35 +5677,37 @@ var Helper = class {
|
|
|
5535
5677
|
* 获取输入文件的路径
|
|
5536
5678
|
*/
|
|
5537
5679
|
getInputPath() {
|
|
5538
|
-
const { input } = this.compilerOpts;
|
|
5539
|
-
return
|
|
5680
|
+
const { input = "src" } = this.compilerOpts;
|
|
5681
|
+
return path3.resolve(this.getProjectRoot(), input);
|
|
5540
5682
|
}
|
|
5541
5683
|
/**
|
|
5542
5684
|
* 检查 input 路径是否是单个文件
|
|
5543
5685
|
*/
|
|
5544
5686
|
isSingleFile() {
|
|
5545
5687
|
const inputPath = this.getInputPath();
|
|
5546
|
-
return
|
|
5688
|
+
return fs2.existsSync(inputPath) && fs2.statSync(inputPath).isFile();
|
|
5547
5689
|
}
|
|
5548
5690
|
/**
|
|
5549
5691
|
* 获取输出文件的路径。如:'[root]/.vureact/dist/'
|
|
5692
|
+
* @param addInput 会输出如:'[root]/.vureact/dist/[input]/'
|
|
5550
5693
|
*/
|
|
5551
|
-
getOuputPath() {
|
|
5552
|
-
|
|
5694
|
+
getOuputPath(addInput = false) {
|
|
5695
|
+
const { input = "src" } = this.compilerOpts;
|
|
5696
|
+
return path3.resolve(this.getWorkspaceDir(), this.getOutDirName(), addInput ? input : "");
|
|
5553
5697
|
}
|
|
5554
5698
|
getOutDirName() {
|
|
5555
5699
|
const { output } = this.compilerOpts;
|
|
5556
5700
|
return output?.outDir || this.outDir;
|
|
5557
5701
|
}
|
|
5558
5702
|
getWorkspaceDir() {
|
|
5559
|
-
return
|
|
5703
|
+
return path3.resolve(this.getProjectRoot(), this.workspaceDir);
|
|
5560
5704
|
}
|
|
5561
5705
|
/**
|
|
5562
5706
|
* 根据相对输出路径反推源文件路径
|
|
5563
5707
|
*/
|
|
5564
5708
|
getSourcePath(outputPath) {
|
|
5565
|
-
const relativePath2 =
|
|
5566
|
-
return
|
|
5709
|
+
const relativePath2 = path3.relative(this.getOuputPath(), outputPath);
|
|
5710
|
+
return path3.resolve(this.getProjectRoot(), relativePath2);
|
|
5567
5711
|
}
|
|
5568
5712
|
getIgnoreAssets() {
|
|
5569
5713
|
const { output } = this.compilerOpts;
|
|
@@ -5581,7 +5725,9 @@ var Helper = class {
|
|
|
5581
5725
|
"eslint.config.",
|
|
5582
5726
|
"readme.",
|
|
5583
5727
|
"vue.",
|
|
5584
|
-
"
|
|
5728
|
+
".vue",
|
|
5729
|
+
"vureact.config.js",
|
|
5730
|
+
"vureact.config.ts"
|
|
5585
5731
|
]);
|
|
5586
5732
|
}
|
|
5587
5733
|
getIsCache() {
|
|
@@ -5591,19 +5737,19 @@ var Helper = class {
|
|
|
5591
5737
|
* 返回原始目录下的 package.json 路径
|
|
5592
5738
|
*/
|
|
5593
5739
|
getRootPkgPath() {
|
|
5594
|
-
return
|
|
5740
|
+
return path3.join(this.getProjectRoot(), "package.json");
|
|
5595
5741
|
}
|
|
5596
5742
|
/**
|
|
5597
5743
|
* 返回 output 的 package.json 路径
|
|
5598
5744
|
*/
|
|
5599
5745
|
getOutputPkgPath() {
|
|
5600
|
-
return
|
|
5746
|
+
return path3.join(this.getOuputPath(), "package.json");
|
|
5601
5747
|
}
|
|
5602
5748
|
/**
|
|
5603
5749
|
* 返回文件相对工作区的路径
|
|
5604
5750
|
*/
|
|
5605
5751
|
relativePath(filePath) {
|
|
5606
|
-
return
|
|
5752
|
+
return path3.relative(this.getProjectRoot(), filePath);
|
|
5607
5753
|
}
|
|
5608
5754
|
/**
|
|
5609
5755
|
* 替换 .vue 文件名后缀为 .jsx/.tsx
|
|
@@ -5615,8 +5761,8 @@ var Helper = class {
|
|
|
5615
5761
|
const relativePath2 = this.relativePath(filePath);
|
|
5616
5762
|
let newRelativePath = relativePath2.replace(/\.vue$/i, ext);
|
|
5617
5763
|
if (newRelativePath === relativePath2) {
|
|
5618
|
-
const { name, dir } =
|
|
5619
|
-
newRelativePath =
|
|
5764
|
+
const { name, dir } = path3.parse(relativePath2);
|
|
5765
|
+
newRelativePath = path3.join(dir, `${name}${ext}`);
|
|
5620
5766
|
}
|
|
5621
5767
|
return newRelativePath;
|
|
5622
5768
|
}
|
|
@@ -5624,7 +5770,7 @@ var Helper = class {
|
|
|
5624
5770
|
* 判断是否应该跳过不需要进行文件搜索的路径
|
|
5625
5771
|
*/
|
|
5626
5772
|
shouldSkipPath(filePath) {
|
|
5627
|
-
const baseName =
|
|
5773
|
+
const baseName = path3.basename(filePath);
|
|
5628
5774
|
const defaultExcludes = ["node_modules", "dist", "build", ".git", ".DS_Store"];
|
|
5629
5775
|
if (defaultExcludes.includes(baseName)) {
|
|
5630
5776
|
return true;
|
|
@@ -5640,7 +5786,7 @@ var Helper = class {
|
|
|
5640
5786
|
*/
|
|
5641
5787
|
resolveOutputPath(filePath, extname) {
|
|
5642
5788
|
const newRelativePath = extname ? this.replaceVueFileExt(filePath, `.${extname}`) : this.relativePath(filePath);
|
|
5643
|
-
const outputPath =
|
|
5789
|
+
const outputPath = path3.resolve(this.getOuputPath(), newRelativePath);
|
|
5644
5790
|
return outputPath;
|
|
5645
5791
|
}
|
|
5646
5792
|
/**
|
|
@@ -5680,20 +5826,34 @@ var Helper = class {
|
|
|
5680
5826
|
return a.fileSize === b.fileSize && a.mtime === b.mtime;
|
|
5681
5827
|
}
|
|
5682
5828
|
/**
|
|
5683
|
-
*
|
|
5829
|
+
* 统一的写文件方法,包含自动创建目录(带文件互斥锁可选)
|
|
5830
|
+
* @param filePath - 要写入的文件路径
|
|
5831
|
+
* @param content - 要写入的内容
|
|
5832
|
+
* @param options - 可选配置项
|
|
5833
|
+
* @param options.lock - 是否启用文件锁(默认false)
|
|
5684
5834
|
*/
|
|
5685
|
-
async writeFileWithDir(filePath, content) {
|
|
5686
|
-
|
|
5687
|
-
|
|
5835
|
+
async writeFileWithDir(filePath, content, options) {
|
|
5836
|
+
if (options?.lock) {
|
|
5837
|
+
await fileLock.updateFile(filePath, async () => content, options);
|
|
5838
|
+
} else {
|
|
5839
|
+
await fs2.promises.mkdir(path3.dirname(filePath), { recursive: true });
|
|
5840
|
+
await fs2.promises.writeFile(filePath, content, "utf-8");
|
|
5841
|
+
}
|
|
5842
|
+
}
|
|
5843
|
+
async rmFile(filePath) {
|
|
5844
|
+
try {
|
|
5845
|
+
await fs2.promises.rm(filePath, { recursive: true, force: true });
|
|
5846
|
+
} catch {
|
|
5847
|
+
}
|
|
5688
5848
|
}
|
|
5689
5849
|
async loadCache(key) {
|
|
5690
5850
|
const cacheFile = this.getCachePath();
|
|
5691
5851
|
const defaultData = this.createCacheData(key);
|
|
5692
|
-
if (!
|
|
5852
|
+
if (!fs2.existsSync(cacheFile)) {
|
|
5693
5853
|
return defaultData;
|
|
5694
5854
|
}
|
|
5695
5855
|
try {
|
|
5696
|
-
const content = await
|
|
5856
|
+
const content = await fs2.promises.readFile(cacheFile, "utf-8");
|
|
5697
5857
|
const data = JSON.parse(content);
|
|
5698
5858
|
return {
|
|
5699
5859
|
key,
|
|
@@ -5721,15 +5881,25 @@ var Helper = class {
|
|
|
5721
5881
|
*/
|
|
5722
5882
|
getCachePath() {
|
|
5723
5883
|
const filename = "_metadata";
|
|
5724
|
-
return
|
|
5884
|
+
return path3.resolve(this.getProjectRoot(), this.workspaceDir, "cache", `${filename}.json`);
|
|
5725
5885
|
}
|
|
5726
5886
|
async saveCache(data) {
|
|
5727
5887
|
if (!this.getIsCache() || !data) {
|
|
5728
5888
|
return;
|
|
5729
5889
|
}
|
|
5730
|
-
const
|
|
5731
|
-
|
|
5732
|
-
|
|
5890
|
+
const getDefaultValue = () => ({
|
|
5891
|
+
["sfc" /* SFC */]: [],
|
|
5892
|
+
["script" /* SCRIPT */]: [],
|
|
5893
|
+
["style" /* STYLE */]: [],
|
|
5894
|
+
["copied" /* ASSET */]: []
|
|
5895
|
+
});
|
|
5896
|
+
const cachePath = this.getCachePath();
|
|
5897
|
+
await fileLock.updateFile(cachePath, (currentData) => {
|
|
5898
|
+
const { key, target } = data;
|
|
5899
|
+
const mergedData = currentData || getDefaultValue();
|
|
5900
|
+
mergedData[key] = target;
|
|
5901
|
+
return mergedData;
|
|
5902
|
+
});
|
|
5733
5903
|
}
|
|
5734
5904
|
genHash(content) {
|
|
5735
5905
|
return genHashByXXH(content);
|
|
@@ -5741,18 +5911,18 @@ var Helper = class {
|
|
|
5741
5911
|
*/
|
|
5742
5912
|
scanFiles(dir, filter) {
|
|
5743
5913
|
const results = [];
|
|
5744
|
-
if (!
|
|
5914
|
+
if (!fs2.existsSync(dir)) {
|
|
5745
5915
|
return results;
|
|
5746
5916
|
}
|
|
5747
|
-
const stats =
|
|
5917
|
+
const stats = fs2.statSync(dir);
|
|
5748
5918
|
if (stats.isFile()) {
|
|
5749
5919
|
return filter(dir) ? [dir] : [];
|
|
5750
5920
|
}
|
|
5751
|
-
const list =
|
|
5921
|
+
const list = fs2.readdirSync(dir);
|
|
5752
5922
|
for (const file of list) {
|
|
5753
|
-
const fullPath =
|
|
5923
|
+
const fullPath = path3.resolve(dir, file);
|
|
5754
5924
|
if (this.shouldSkipPath(fullPath)) continue;
|
|
5755
|
-
const stat =
|
|
5925
|
+
const stat = fs2.statSync(fullPath);
|
|
5756
5926
|
if (stat.isDirectory() && this.compilerOpts.recursive !== false) {
|
|
5757
5927
|
results.push(...this.scanFiles(fullPath, filter));
|
|
5758
5928
|
} else if (filter(fullPath)) {
|
|
@@ -5762,19 +5932,19 @@ var Helper = class {
|
|
|
5762
5932
|
return results;
|
|
5763
5933
|
}
|
|
5764
5934
|
getAbsPath(filePath) {
|
|
5765
|
-
return
|
|
5935
|
+
return path3.isAbsolute(filePath) ? filePath : path3.resolve(this.getProjectRoot(), filePath);
|
|
5766
5936
|
}
|
|
5767
5937
|
async getFileMeta(filePath) {
|
|
5768
|
-
const stats = await
|
|
5938
|
+
const stats = await fs2.promises.stat(filePath);
|
|
5769
5939
|
return {
|
|
5770
5940
|
fileSize: stats.size,
|
|
5771
5941
|
mtime: stats.mtimeMs
|
|
5772
5942
|
};
|
|
5773
5943
|
}
|
|
5774
5944
|
async removeOutputFile(filePath, resolveOutputPath) {
|
|
5775
|
-
const
|
|
5776
|
-
if (!
|
|
5777
|
-
await
|
|
5945
|
+
const path9 = resolveOutputPath ? this.resolveOutputPath(filePath) : filePath;
|
|
5946
|
+
if (!fs2.existsSync(path9)) return;
|
|
5947
|
+
await fs2.promises.unlink(path9);
|
|
5778
5948
|
}
|
|
5779
5949
|
updateCache(targetFile, newData, cache) {
|
|
5780
5950
|
const index = cache.target.findIndex((c) => c.file === targetFile);
|
|
@@ -5784,18 +5954,6 @@ var Helper = class {
|
|
|
5784
5954
|
cache.target.push(newData);
|
|
5785
5955
|
}
|
|
5786
5956
|
}
|
|
5787
|
-
resolveViteCreateApp() {
|
|
5788
|
-
const { output } = this.compilerOpts;
|
|
5789
|
-
const config = output?.bootstrapVite;
|
|
5790
|
-
const template = typeof config === "object" ? config.template : "react-ts";
|
|
5791
|
-
const outDirName = this.getOutDirName();
|
|
5792
|
-
const cmd = `npm create vite@latest ${outDirName} -- --template ${template}`;
|
|
5793
|
-
execSync(cmd, {
|
|
5794
|
-
cwd: this.getWorkspaceDir(),
|
|
5795
|
-
stdio: "ignore"
|
|
5796
|
-
// 隐藏 create-vite 内部的输出日志,保持终端整洁
|
|
5797
|
-
});
|
|
5798
|
-
}
|
|
5799
5957
|
/**
|
|
5800
5958
|
* 获取需要排除编译的文件
|
|
5801
5959
|
*/
|
|
@@ -5823,15 +5981,15 @@ var Helper = class {
|
|
|
5823
5981
|
}
|
|
5824
5982
|
printCompileInfo(file, duration) {
|
|
5825
5983
|
this.print(
|
|
5826
|
-
|
|
5827
|
-
|
|
5828
|
-
|
|
5984
|
+
kleur4.green("Compiled"),
|
|
5985
|
+
kleur4.dim(normalizePath(this.relativePath(file))),
|
|
5986
|
+
kleur4.gray(`(${duration})`)
|
|
5829
5987
|
);
|
|
5830
5988
|
}
|
|
5831
5989
|
print(...message) {
|
|
5832
5990
|
if (this.compilerOpts.watch) {
|
|
5833
5991
|
const time = (/* @__PURE__ */ new Date()).toLocaleTimeString();
|
|
5834
|
-
console.info(
|
|
5992
|
+
console.info(kleur4.dim(time), kleur4.cyan(kleur4.bold("[vureact]")), ...message);
|
|
5835
5993
|
return;
|
|
5836
5994
|
}
|
|
5837
5995
|
console.info(...message);
|
|
@@ -5839,17 +5997,34 @@ var Helper = class {
|
|
|
5839
5997
|
/**
|
|
5840
5998
|
* 读取 package.json 文件内容,并处理成对象返回
|
|
5841
5999
|
*/
|
|
5842
|
-
async resolvePackageFile(
|
|
6000
|
+
async resolvePackageFile(path9) {
|
|
6001
|
+
if (!fs2.existsSync(path9)) {
|
|
6002
|
+
return {};
|
|
6003
|
+
}
|
|
5843
6004
|
try {
|
|
5844
|
-
|
|
6005
|
+
const content = await fs2.promises.readFile(path9, "utf-8");
|
|
6006
|
+
if (!content.trim()) {
|
|
5845
6007
|
return {};
|
|
5846
6008
|
}
|
|
5847
|
-
return JSON.parse(
|
|
6009
|
+
return JSON.parse(content);
|
|
5848
6010
|
} catch (error) {
|
|
5849
|
-
console.error(
|
|
6011
|
+
console.error(kleur4.red("\u274C"), `Failed to parse JSON file ${path9}:
|
|
6012
|
+
`, error);
|
|
5850
6013
|
return {};
|
|
5851
6014
|
}
|
|
5852
6015
|
}
|
|
6016
|
+
/**
|
|
6017
|
+
* 获取目录到文件的相对路径
|
|
6018
|
+
* @returns 结果路径不包含文件拓展名,并以诸如 ./ 开头
|
|
6019
|
+
*/
|
|
6020
|
+
resolveRelativePath(from, to) {
|
|
6021
|
+
let relativePath2 = path3.relative(from, to);
|
|
6022
|
+
relativePath2 = relativePath2.substring(0, relativePath2.indexOf("."));
|
|
6023
|
+
if (!relativePath2.startsWith(".")) {
|
|
6024
|
+
relativePath2 = `./${relativePath2}`;
|
|
6025
|
+
}
|
|
6026
|
+
return normalizePath(relativePath2);
|
|
6027
|
+
}
|
|
5853
6028
|
};
|
|
5854
6029
|
|
|
5855
6030
|
// src/core/parse/style-only.ts
|
|
@@ -5886,7 +6061,7 @@ function parseOnlyStyle(source, ctx, options) {
|
|
|
5886
6061
|
}
|
|
5887
6062
|
|
|
5888
6063
|
// src/compiler/context/adapter.ts
|
|
5889
|
-
import
|
|
6064
|
+
import path4 from "path";
|
|
5890
6065
|
|
|
5891
6066
|
// src/compiler/context/creator.ts
|
|
5892
6067
|
function createCompilationCtx() {
|
|
@@ -5973,7 +6148,7 @@ var CompilationAdapter = class _CompilationAdapter {
|
|
|
5973
6148
|
return ctx;
|
|
5974
6149
|
}
|
|
5975
6150
|
static detectInputType(filename) {
|
|
5976
|
-
const ext =
|
|
6151
|
+
const ext = path4.extname(filename).toLowerCase();
|
|
5977
6152
|
switch (ext) {
|
|
5978
6153
|
case ".vue":
|
|
5979
6154
|
return "sfc";
|
|
@@ -5997,65 +6172,11 @@ var BaseCompiler = class extends Helper {
|
|
|
5997
6172
|
version = version;
|
|
5998
6173
|
options;
|
|
5999
6174
|
createContext = CompilationAdapter.createContext;
|
|
6000
|
-
/**
|
|
6001
|
-
* 创建基础编译器实例
|
|
6002
|
-
*
|
|
6003
|
-
* @param options - 编译器配置选项,包括缓存设置、插件配置、样式预处理等,
|
|
6004
|
-
* 所有选项都会传递给父类 {@link Helper} 进行初始化
|
|
6005
|
-
*
|
|
6006
|
-
* @see {@link CompilerOptions} 查看完整的配置选项说明
|
|
6007
|
-
*/
|
|
6008
6175
|
constructor(options = {}) {
|
|
6009
6176
|
super(options);
|
|
6010
6177
|
this.options = options;
|
|
6011
6178
|
}
|
|
6012
|
-
/**
|
|
6013
|
-
* 编译 Vue 源代码为 React 代码
|
|
6014
|
-
*
|
|
6015
|
-
* 该方法执行完整的编译流程,包括:
|
|
6016
|
-
* 1. 上下文初始化:创建独立的编译上下文
|
|
6017
|
-
* 2. 解析阶段:将 Vue 源代码解析为抽象语法树(AST)
|
|
6018
|
-
* 3. 转换阶段:将 Vue AST 转换为 React 中间表示(IR)
|
|
6019
|
-
* 4. 生成阶段:将 React IR 生成为目标代码
|
|
6020
|
-
* 5. 插件执行:在各阶段执行注册的插件
|
|
6021
|
-
* 6. 结果处理:整理编译结果并返回
|
|
6022
|
-
*
|
|
6023
|
-
* 编译过程使用 try-finally 确保上下文资源被正确清理,
|
|
6024
|
-
* 即使编译过程中发生错误也不会导致资源泄漏。
|
|
6025
|
-
*
|
|
6026
|
-
* @param source - Vue 源代码字符串
|
|
6027
|
-
* @param filename - 源文件名,用于生成文件ID和输出路径
|
|
6028
|
-
* @returns {CompilationResult} 编译结果,包含生成的代码和文件信息
|
|
6029
|
-
*
|
|
6030
|
-
* @example
|
|
6031
|
-
* ```typescript
|
|
6032
|
-
* const vueCode = `
|
|
6033
|
-
* <template>
|
|
6034
|
-
* <div class="container">{{ message }}</div>
|
|
6035
|
-
* </template>
|
|
6036
|
-
*
|
|
6037
|
-
* <script setup lang="ts">
|
|
6038
|
-
* import { ref } from 'vue;
|
|
6039
|
-
* const message = ref('Hello Vue')
|
|
6040
|
-
* </script>
|
|
6041
|
-
*
|
|
6042
|
-
* <style scoped>
|
|
6043
|
-
* .container {
|
|
6044
|
-
* padding: 20px;
|
|
6045
|
-
* }
|
|
6046
|
-
* </style>
|
|
6047
|
-
* `;
|
|
6048
|
-
*
|
|
6049
|
-
* const result = compiler.compile(vueCode, 'MyComponent.vue');
|
|
6050
|
-
* console.log(result);
|
|
6051
|
-
* ```
|
|
6052
|
-
*
|
|
6053
|
-
* @throws 不会直接抛出异常,错误通过日志系统记录
|
|
6054
|
-
* @see {@link parse} 解析函数
|
|
6055
|
-
* @see {@link transform} 转换函数
|
|
6056
|
-
* @see {@link generate} 生成函数
|
|
6057
|
-
* @see {@link executePlugins} 插件执行函数
|
|
6058
|
-
*/
|
|
6179
|
+
/** 编译 Vue 源代码为 React 代码 */
|
|
6059
6180
|
compile(source, filename) {
|
|
6060
6181
|
const { plugins, preprocessStyles = true } = this.options;
|
|
6061
6182
|
const fileId = this.genHash(filename);
|
|
@@ -6091,61 +6212,12 @@ var BaseCompiler = class extends Helper {
|
|
|
6091
6212
|
ctx.clear();
|
|
6092
6213
|
}
|
|
6093
6214
|
}
|
|
6094
|
-
/**
|
|
6095
|
-
* 初始化 Babel 代码生成选项
|
|
6096
|
-
*
|
|
6097
|
-
* 合并用户自定义的生成选项与默认选项,确保代码生成的一致性和正确性。
|
|
6098
|
-
* 默认配置优化了代码的可读性和性能:
|
|
6099
|
-
* 1. 最小化 Unicode 转义:只转义必要的字符,保持代码可读性
|
|
6100
|
-
* 2. 统一引号风格:使用单引号,符合 JavaScript 社区常见约定
|
|
6101
|
-
* 3. 代码压缩:启用最小化,移除不必要的空白字符
|
|
6102
|
-
*
|
|
6103
|
-
* 如果用户提供了自定义选项,会与默认选项进行深度合并,
|
|
6104
|
-
* 用户选项的优先级高于默认选项。
|
|
6105
|
-
*
|
|
6106
|
-
* @private
|
|
6107
|
-
* @param filename - 可选的文件名,用于源码映射配置
|
|
6108
|
-
* @returns {GeneratorOptions} 合并后的 Babel 生成选项
|
|
6109
|
-
*
|
|
6110
|
-
* @remarks
|
|
6111
|
-
* - 源码映射支持:如果启用了 sourceMaps 且提供了文件名,会自动设置 sourceFileName
|
|
6112
|
-
* - 选项合并策略:用户选项会覆盖默认选项,实现灵活的配置
|
|
6113
|
-
* - 性能优化:默认启用 minified 以减少生成代码的体积
|
|
6114
|
-
* - 编码安全:使用 jsesc 确保特殊字符的正确转义
|
|
6115
|
-
*
|
|
6116
|
-
* @example
|
|
6117
|
-
* ```typescript
|
|
6118
|
-
* // 默认选项
|
|
6119
|
-
* const defaultOptions = {
|
|
6120
|
-
* jsescOption: { minimal: true, quotes: 'single' },
|
|
6121
|
-
* minified: true
|
|
6122
|
-
* };
|
|
6123
|
-
*
|
|
6124
|
-
* // 用户自定义选项
|
|
6125
|
-
* const userOptions = {
|
|
6126
|
-
* minified: false, // 覆盖默认值
|
|
6127
|
-
* sourceMaps: true // 新增选项
|
|
6128
|
-
* };
|
|
6129
|
-
*
|
|
6130
|
-
* // 合并结果
|
|
6131
|
-
* const merged = {
|
|
6132
|
-
* jsescOption: { minimal: true, quotes: 'single' },
|
|
6133
|
-
* minified: false, // 用户值
|
|
6134
|
-
* sourceMaps: true // 用户值
|
|
6135
|
-
* };
|
|
6136
|
-
* ```
|
|
6137
|
-
*
|
|
6138
|
-
* @see {@link GeneratorOptions} Babel 生成选项类型定义
|
|
6139
|
-
*/
|
|
6140
6215
|
prepareGenerateOptions(filename) {
|
|
6141
6216
|
const userOptions = this.options.generate || {};
|
|
6142
6217
|
const mergedOptions = {
|
|
6143
|
-
// 配置 jsesc 避免 Unicode 转义
|
|
6144
6218
|
jsescOption: {
|
|
6145
6219
|
minimal: true,
|
|
6146
|
-
// 只转义必要的字符
|
|
6147
6220
|
quotes: "single"
|
|
6148
|
-
// 使用单引号
|
|
6149
6221
|
},
|
|
6150
6222
|
minified: true,
|
|
6151
6223
|
...userOptions
|
|
@@ -6155,36 +6227,6 @@ var BaseCompiler = class extends Helper {
|
|
|
6155
6227
|
}
|
|
6156
6228
|
return mergedOptions;
|
|
6157
6229
|
}
|
|
6158
|
-
/**
|
|
6159
|
-
* 处理 SFC 和 Script 文件的编译结果
|
|
6160
|
-
*
|
|
6161
|
-
* 根据编译上下文中的输入类型(SFC 或 Script),整理并返回相应的编译结果。
|
|
6162
|
-
* 对于 SFC 文件,返回包含 JSX 和 CSS 信息的完整结果;
|
|
6163
|
-
* 对于 Script 文件,返回仅包含脚本信息的结果。
|
|
6164
|
-
*
|
|
6165
|
-
* 关键处理逻辑:
|
|
6166
|
-
* 1. 构建基础结果:包含文件ID、路由信息和生成的代码
|
|
6167
|
-
* 2. 确定输出路径:根据源文件路径和语言类型生成输出文件路径
|
|
6168
|
-
* 3. 区分文件类型:
|
|
6169
|
-
* - SFC 文件:生成 .tsx 扩展名,包含样式信息
|
|
6170
|
-
* - Script 文件:保持原扩展名,不包含样式信息
|
|
6171
|
-
* 4. 样式处理:提取样式文件路径、作用域ID和样式代码
|
|
6172
|
-
*
|
|
6173
|
-
* @private
|
|
6174
|
-
* @param ir - React 中间表示(IR)描述符,包含转换后的组件信息
|
|
6175
|
-
* @param gen - 代码生成结果,包含生成的代码和源码映射
|
|
6176
|
-
* @param ctxData - 编译上下文数据,包含文件信息和编译状态
|
|
6177
|
-
* @returns {CompilationResult} 整理后的编译结果
|
|
6178
|
-
*
|
|
6179
|
-
* @remarks
|
|
6180
|
-
* - 文件扩展名处理:Vue SFC 文件会转换为 .tsx 或 .jsx 文件
|
|
6181
|
-
* - 样式分离:SFC 中的样式会被提取到独立的 CSS 文件中
|
|
6182
|
-
* - 路由检测:自动检测组件是否使用路由,用于依赖注入
|
|
6183
|
-
* - 作用域样式:为 Scoped CSS 生成唯一的作用域ID
|
|
6184
|
-
*
|
|
6185
|
-
* @see {@link SFCCompilationResult} SFC 编译结果类型
|
|
6186
|
-
* @see {@link ScriptCompilationResult} Script 编译结果类型
|
|
6187
|
-
*/
|
|
6188
6230
|
resolveMainResult(ir, gen, ctxData) {
|
|
6189
6231
|
const { fileId, filename, scriptData, styleData, inputType } = ctxData;
|
|
6190
6232
|
const base = {
|
|
@@ -6199,7 +6241,6 @@ var BaseCompiler = class extends Helper {
|
|
|
6199
6241
|
fileInfo: {
|
|
6200
6242
|
jsx: {
|
|
6201
6243
|
file: `${file}x`,
|
|
6202
|
-
// 'xxx.ts' + 'x' => 'xxx.tsx'
|
|
6203
6244
|
lang
|
|
6204
6245
|
},
|
|
6205
6246
|
css: {
|
|
@@ -6216,11 +6257,6 @@ var BaseCompiler = class extends Helper {
|
|
|
6216
6257
|
...base
|
|
6217
6258
|
};
|
|
6218
6259
|
}
|
|
6219
|
-
/**
|
|
6220
|
-
* 处理 Style 文件的编译结果
|
|
6221
|
-
* @param data style 文件解析结果
|
|
6222
|
-
* @param ctxData 上下文数据
|
|
6223
|
-
*/
|
|
6224
6260
|
resolveStyleResult(data, ctxData) {
|
|
6225
6261
|
const { fileId, filename } = ctxData;
|
|
6226
6262
|
const { lang, content = "" } = data.style.source;
|
|
@@ -6253,13 +6289,12 @@ function formattDuration(n) {
|
|
|
6253
6289
|
}
|
|
6254
6290
|
|
|
6255
6291
|
// src/compiler/shared/file-compiler/index.ts
|
|
6256
|
-
import
|
|
6257
|
-
import kleur6 from "kleur";
|
|
6292
|
+
import kleur8 from "kleur";
|
|
6258
6293
|
import ora2 from "ora";
|
|
6259
6294
|
|
|
6260
6295
|
// src/compiler/shared/file-compiler/asset-manager.ts
|
|
6261
|
-
import
|
|
6262
|
-
import
|
|
6296
|
+
import fs3 from "fs";
|
|
6297
|
+
import path5 from "path";
|
|
6263
6298
|
var AssetManager = class {
|
|
6264
6299
|
constructor(fileCompiler, cleanupManager) {
|
|
6265
6300
|
this.fileCompiler = fileCompiler;
|
|
@@ -6267,19 +6302,21 @@ var AssetManager = class {
|
|
|
6267
6302
|
}
|
|
6268
6303
|
// 需要经过管线编译处理的文件类型
|
|
6269
6304
|
pipelineFiles = [".js", ".ts", ".less", ".scss", ".sass"];
|
|
6305
|
+
skippedCount = 0;
|
|
6270
6306
|
/**
|
|
6271
6307
|
* 运行资源文件处理管线
|
|
6272
6308
|
*/
|
|
6273
6309
|
async runAssetPipeline() {
|
|
6310
|
+
const { options } = this.fileCompiler;
|
|
6274
6311
|
const rootPath = this.fileCompiler.getProjectRoot();
|
|
6275
6312
|
const inputPath = this.fileCompiler.getInputPath();
|
|
6276
6313
|
const exclusions = this.fileCompiler.getIgnoreAssets();
|
|
6277
6314
|
const assetFiles = this.fileCompiler.scanFiles(rootPath, (p) => {
|
|
6278
6315
|
if (this.fileCompiler.shouldSkipPath(p)) return false;
|
|
6279
6316
|
const relativeToRoot = normalizePath(this.fileCompiler.relativePath(p));
|
|
6280
|
-
const filename =
|
|
6281
|
-
const ext =
|
|
6282
|
-
if (!
|
|
6317
|
+
const filename = path5.basename(p).toLowerCase();
|
|
6318
|
+
const ext = path5.extname(p).toLowerCase();
|
|
6319
|
+
if (!options.output?.ignoreAssets) {
|
|
6283
6320
|
const shouldExclude = Array.from(exclusions).some((pattern) => {
|
|
6284
6321
|
if (pattern.endsWith(".")) {
|
|
6285
6322
|
return filename.startsWith(pattern);
|
|
@@ -6289,34 +6326,28 @@ var AssetManager = class {
|
|
|
6289
6326
|
}
|
|
6290
6327
|
return relativeToRoot === pattern || filename === pattern;
|
|
6291
6328
|
});
|
|
6292
|
-
if (shouldExclude)
|
|
6293
|
-
return false;
|
|
6294
|
-
}
|
|
6329
|
+
if (shouldExclude) return false;
|
|
6295
6330
|
} else if (exclusions.has(relativeToRoot) || exclusions.has(filename)) {
|
|
6296
6331
|
return false;
|
|
6297
6332
|
}
|
|
6298
6333
|
if (ext === ".vue") return false;
|
|
6299
|
-
const isInsideSrc = p.startsWith(inputPath +
|
|
6334
|
+
const isInsideSrc = p.startsWith(inputPath + path5.sep);
|
|
6300
6335
|
if (isInsideSrc && this.pipelineFiles.includes(ext)) {
|
|
6301
6336
|
return false;
|
|
6302
6337
|
}
|
|
6303
6338
|
return true;
|
|
6304
6339
|
});
|
|
6305
6340
|
const absFiles = new Set(assetFiles.map((f) => this.fileCompiler.getAbsPath(f)));
|
|
6306
|
-
const cache = await this.fileCompiler.loadCache("copied" /* ASSET */);
|
|
6307
6341
|
await this.cleanupManager.cleanupOldOutput("copied" /* ASSET */, (u) => !absFiles.has(u.file));
|
|
6308
|
-
|
|
6309
|
-
|
|
6310
|
-
|
|
6311
|
-
|
|
6312
|
-
|
|
6313
|
-
|
|
6314
|
-
|
|
6315
|
-
for (const file of files) {
|
|
6316
|
-
const meta = await this.processAsset(file, cache);
|
|
6317
|
-
this.updateCache(file, meta, cache);
|
|
6318
|
-
}
|
|
6342
|
+
if (!assetFiles.length) return 0;
|
|
6343
|
+
const cache = await this.fileCompiler.loadCache("copied" /* ASSET */);
|
|
6344
|
+
const copied = await Promise.all(
|
|
6345
|
+
assetFiles.map((file) => {
|
|
6346
|
+
return this.processAsset(file, cache);
|
|
6347
|
+
})
|
|
6348
|
+
);
|
|
6319
6349
|
await this.fileCompiler.saveCache(cache);
|
|
6350
|
+
return copied.filter(Boolean).length;
|
|
6320
6351
|
}
|
|
6321
6352
|
/**
|
|
6322
6353
|
* Process single asset file, compare with cache and decide whether to copy.
|
|
@@ -6330,11 +6361,16 @@ var AssetManager = class {
|
|
|
6330
6361
|
const cache = (this.fileCompiler.getIsCache() ? existingCache : void 0) || await this.fileCompiler.loadCache("copied" /* ASSET */);
|
|
6331
6362
|
const record = cache.target.find((f) => f.file === absPath);
|
|
6332
6363
|
if (record && this.fileCompiler.compareFileMeta(record, fileMeta)) {
|
|
6333
|
-
|
|
6364
|
+
this.skippedCount++;
|
|
6365
|
+
return;
|
|
6334
6366
|
}
|
|
6335
6367
|
const outputPath = this.fileCompiler.resolveOutputPath(absPath);
|
|
6336
|
-
await
|
|
6337
|
-
await
|
|
6368
|
+
await fs3.promises.mkdir(path5.dirname(outputPath), { recursive: true });
|
|
6369
|
+
await fs3.promises.copyFile(absPath, outputPath);
|
|
6370
|
+
this.updateCache(absPath, fileMeta, cache);
|
|
6371
|
+
if (this.fileCompiler.getIsCache() && !existingCache) {
|
|
6372
|
+
await this.fileCompiler.saveCache(cache);
|
|
6373
|
+
}
|
|
6338
6374
|
return fileMeta;
|
|
6339
6375
|
}
|
|
6340
6376
|
/**
|
|
@@ -6349,6 +6385,18 @@ var AssetManager = class {
|
|
|
6349
6385
|
cache.target.push(newData);
|
|
6350
6386
|
}
|
|
6351
6387
|
}
|
|
6388
|
+
/**
|
|
6389
|
+
* 获取跳过的文件数量
|
|
6390
|
+
*/
|
|
6391
|
+
getSkippedCount() {
|
|
6392
|
+
return this.skippedCount;
|
|
6393
|
+
}
|
|
6394
|
+
/**
|
|
6395
|
+
* 重置跳过的文件数量
|
|
6396
|
+
*/
|
|
6397
|
+
resetSkippedCount() {
|
|
6398
|
+
this.skippedCount = 0;
|
|
6399
|
+
}
|
|
6352
6400
|
};
|
|
6353
6401
|
|
|
6354
6402
|
// src/compiler/shared/file-compiler/cache-manager.ts
|
|
@@ -6356,12 +6404,12 @@ var CacheManager = class {
|
|
|
6356
6404
|
constructor(fileCompiler) {
|
|
6357
6405
|
this.fileCompiler = fileCompiler;
|
|
6358
6406
|
}
|
|
6407
|
+
pendingUpdates = /* @__PURE__ */ new Map();
|
|
6359
6408
|
/**
|
|
6360
|
-
*
|
|
6409
|
+
* 批量更新缓存记录
|
|
6361
6410
|
*/
|
|
6362
6411
|
async updateCacheIncrementally(unit, key) {
|
|
6363
6412
|
if (!this.fileCompiler.getIsCache()) return;
|
|
6364
|
-
const cache = await this.fileCompiler.loadCache(key);
|
|
6365
6413
|
const meta = { ...unit };
|
|
6366
6414
|
delete meta.source;
|
|
6367
6415
|
if (key === "sfc" /* SFC */) {
|
|
@@ -6372,8 +6420,26 @@ var CacheManager = class {
|
|
|
6372
6420
|
} else if (key === "style" /* STYLE */) {
|
|
6373
6421
|
delete meta.output?.style.code;
|
|
6374
6422
|
}
|
|
6375
|
-
this.
|
|
6423
|
+
if (!this.pendingUpdates.has(key)) {
|
|
6424
|
+
this.pendingUpdates.set(key, []);
|
|
6425
|
+
}
|
|
6426
|
+
this.pendingUpdates.get(key).push({ unit, meta });
|
|
6427
|
+
}
|
|
6428
|
+
/**
|
|
6429
|
+
* 批量保存缓存
|
|
6430
|
+
*/
|
|
6431
|
+
async flushCache(key) {
|
|
6432
|
+
if (!this.fileCompiler.getIsCache() || !this.pendingUpdates.has(key)) {
|
|
6433
|
+
return;
|
|
6434
|
+
}
|
|
6435
|
+
const updates = this.pendingUpdates.get(key);
|
|
6436
|
+
if (updates.length === 0) return;
|
|
6437
|
+
const cache = await this.fileCompiler.loadCache(key);
|
|
6438
|
+
for (const { unit, meta } of updates) {
|
|
6439
|
+
this.updateCache(unit.file, meta, cache);
|
|
6440
|
+
}
|
|
6376
6441
|
await this.fileCompiler.saveCache(cache);
|
|
6442
|
+
this.pendingUpdates.set(key, []);
|
|
6377
6443
|
}
|
|
6378
6444
|
/**
|
|
6379
6445
|
* 更新缓存
|
|
@@ -6389,7 +6455,7 @@ var CacheManager = class {
|
|
|
6389
6455
|
};
|
|
6390
6456
|
|
|
6391
6457
|
// src/compiler/shared/file-compiler/cleanup-manager.ts
|
|
6392
|
-
import
|
|
6458
|
+
import path6 from "path";
|
|
6393
6459
|
var CleanupManager = class {
|
|
6394
6460
|
constructor(fileCompiler) {
|
|
6395
6461
|
this.fileCompiler = fileCompiler;
|
|
@@ -6404,7 +6470,7 @@ var CleanupManager = class {
|
|
|
6404
6470
|
(u) => u.file === absPath || // 加 path.sep 是因为假如删除了 src/components 文件夹,
|
|
6405
6471
|
// 为了防止误删名为 src/components-old 的文件夹,
|
|
6406
6472
|
// 所以必须确保路径后跟着一个分隔符,确保精准匹配子目录内容。
|
|
6407
|
-
u.file.startsWith(absPath +
|
|
6473
|
+
u.file.startsWith(absPath + path6.sep)
|
|
6408
6474
|
);
|
|
6409
6475
|
}
|
|
6410
6476
|
/**
|
|
@@ -6416,25 +6482,43 @@ var CleanupManager = class {
|
|
|
6416
6482
|
const toRemove = cache.target.filter(filter);
|
|
6417
6483
|
if (!toRemove.length) return;
|
|
6418
6484
|
const removeFn = async (m) => {
|
|
6419
|
-
|
|
6420
|
-
|
|
6421
|
-
|
|
6422
|
-
|
|
6423
|
-
|
|
6424
|
-
|
|
6425
|
-
|
|
6485
|
+
let meta;
|
|
6486
|
+
switch (key) {
|
|
6487
|
+
case "sfc" /* SFC */: {
|
|
6488
|
+
meta = m;
|
|
6489
|
+
const { jsx, css } = meta.output;
|
|
6490
|
+
await this.fileCompiler.removeOutputFile(jsx.file);
|
|
6491
|
+
if (css?.file) {
|
|
6492
|
+
await this.fileCompiler.removeOutputFile(css.file);
|
|
6493
|
+
}
|
|
6494
|
+
break;
|
|
6495
|
+
}
|
|
6496
|
+
case "script" /* SCRIPT */: {
|
|
6497
|
+
meta = m;
|
|
6498
|
+
await this.fileCompiler.removeOutputFile(meta.output.script.file);
|
|
6499
|
+
break;
|
|
6500
|
+
}
|
|
6501
|
+
case "style" /* STYLE */: {
|
|
6502
|
+
meta = m;
|
|
6503
|
+
await this.fileCompiler.removeOutputFile(meta.output.style.file);
|
|
6504
|
+
break;
|
|
6505
|
+
}
|
|
6506
|
+
// 静态资产缓存直接删除对应文件
|
|
6507
|
+
default: {
|
|
6508
|
+
await this.fileCompiler.removeOutputFile(m.file, true);
|
|
6509
|
+
break;
|
|
6426
6510
|
}
|
|
6427
|
-
} else if (key === "script" /* SCRIPT */ || key === "copied" /* ASSET */) {
|
|
6428
|
-
await this.fileCompiler.removeOutputFile(m.file, true);
|
|
6429
6511
|
}
|
|
6430
6512
|
};
|
|
6431
6513
|
await Promise.all(toRemove.map(removeFn));
|
|
6514
|
+
const removedFiles = new Set(toRemove.map((m) => m.file));
|
|
6515
|
+
cache.target = cache.target.filter((m) => !removedFiles.has(m.file));
|
|
6432
6516
|
await this.fileCompiler.saveCache(cache);
|
|
6433
6517
|
}
|
|
6434
6518
|
};
|
|
6435
6519
|
|
|
6436
6520
|
// src/compiler/shared/file-compiler/compilation-unit.ts
|
|
6437
|
-
import
|
|
6521
|
+
import kleur5 from "kleur";
|
|
6438
6522
|
var CompilationUnitProcessor = class {
|
|
6439
6523
|
constructor(fileCompiler) {
|
|
6440
6524
|
this.fileCompiler = fileCompiler;
|
|
@@ -6449,7 +6533,7 @@ var CompilationUnitProcessor = class {
|
|
|
6449
6533
|
this.resolveResult(result, unit, key);
|
|
6450
6534
|
} catch (err) {
|
|
6451
6535
|
console.info(
|
|
6452
|
-
|
|
6536
|
+
kleur5.red(`\u2716`),
|
|
6453
6537
|
`Failed to compile ${this.fileCompiler.relativePath(unit.file)}
|
|
6454
6538
|
`,
|
|
6455
6539
|
err
|
|
@@ -6530,20 +6614,16 @@ var CompilationUnitProcessor = class {
|
|
|
6530
6614
|
};
|
|
6531
6615
|
|
|
6532
6616
|
// src/compiler/shared/file-compiler/file-processor.ts
|
|
6533
|
-
import
|
|
6534
|
-
import
|
|
6617
|
+
import fs4 from "fs";
|
|
6618
|
+
import kleur6 from "kleur";
|
|
6619
|
+
import path7 from "path";
|
|
6535
6620
|
var FileProcessor = class {
|
|
6536
6621
|
constructor(fileCompiler, compilationUnitProcessor, cacheManager) {
|
|
6537
6622
|
this.fileCompiler = fileCompiler;
|
|
6538
6623
|
this.compilationUnitProcessor = compilationUnitProcessor;
|
|
6539
6624
|
this.cacheManager = cacheManager;
|
|
6540
6625
|
}
|
|
6541
|
-
|
|
6542
|
-
router: {
|
|
6543
|
-
name: PACKAGE_NAME.router,
|
|
6544
|
-
version: "^1.0.0"
|
|
6545
|
-
}
|
|
6546
|
-
};
|
|
6626
|
+
skippedCount = 0;
|
|
6547
6627
|
/**
|
|
6548
6628
|
* Process a single Vue file (this method is called directly in CLI Watch mode)
|
|
6549
6629
|
*/
|
|
@@ -6570,10 +6650,13 @@ var FileProcessor = class {
|
|
|
6570
6650
|
const { shouldCompile, hash } = await this.fileCompiler.checkCacheStatus(
|
|
6571
6651
|
fileMeta,
|
|
6572
6652
|
record,
|
|
6573
|
-
() =>
|
|
6653
|
+
() => fs4.promises.readFile(absPath, "utf-8")
|
|
6574
6654
|
);
|
|
6575
|
-
if (!shouldCompile)
|
|
6576
|
-
|
|
6655
|
+
if (!shouldCompile) {
|
|
6656
|
+
this.skippedCount++;
|
|
6657
|
+
return;
|
|
6658
|
+
}
|
|
6659
|
+
const source = await fs4.promises.readFile(absPath, "utf-8");
|
|
6577
6660
|
if (!source.trim()) return;
|
|
6578
6661
|
const initUnit = {
|
|
6579
6662
|
...fileMeta,
|
|
@@ -6589,46 +6672,108 @@ var FileProcessor = class {
|
|
|
6589
6672
|
await this.compilationUnitProcessor.saveCompiledFiles(processed, key);
|
|
6590
6673
|
if (key === "sfc" /* SFC */ || key === "script" /* SCRIPT */) {
|
|
6591
6674
|
if (processed?.hasRoute) {
|
|
6592
|
-
await this.
|
|
6593
|
-
await this.
|
|
6675
|
+
await this.addRouterToPackageJson();
|
|
6676
|
+
await this.updateEntryWithRouterProvider();
|
|
6594
6677
|
}
|
|
6595
6678
|
}
|
|
6596
6679
|
await this.cacheManager.updateCacheIncrementally(processed, key);
|
|
6597
6680
|
}
|
|
6598
6681
|
return processed;
|
|
6599
6682
|
}
|
|
6600
|
-
|
|
6601
|
-
|
|
6602
|
-
|
|
6603
|
-
|
|
6604
|
-
|
|
6605
|
-
|
|
6683
|
+
/**
|
|
6684
|
+
* 对 package.json 注入路由依赖项
|
|
6685
|
+
*/
|
|
6686
|
+
async addRouterToPackageJson() {
|
|
6687
|
+
const { output } = this.fileCompiler.options;
|
|
6688
|
+
if (output?.bootstrapVite === false) {
|
|
6689
|
+
return;
|
|
6690
|
+
}
|
|
6691
|
+
const { router } = RUNTIME_PACKAGES;
|
|
6692
|
+
const filePath = this.fileCompiler.getOutputPkgPath();
|
|
6693
|
+
const packageJson = await this.fileCompiler.resolvePackageFile(filePath);
|
|
6694
|
+
if (packageJson?.dependencies?.[router.name]) {
|
|
6695
|
+
return;
|
|
6606
6696
|
}
|
|
6607
|
-
|
|
6608
|
-
|
|
6697
|
+
if (!packageJson.dependencies) {
|
|
6698
|
+
packageJson.dependencies = {};
|
|
6699
|
+
}
|
|
6700
|
+
packageJson.dependencies[router.name] = router.version;
|
|
6701
|
+
const newData = JSON.stringify(packageJson, null, 2);
|
|
6702
|
+
await this.fileCompiler.writeFileWithDir(filePath, newData, {
|
|
6703
|
+
lock: true
|
|
6704
|
+
});
|
|
6609
6705
|
}
|
|
6610
6706
|
/**
|
|
6611
|
-
*
|
|
6707
|
+
* 注入路由提供器到 React 应用的入口文件(如 main.tsx)
|
|
6612
6708
|
*/
|
|
6613
|
-
async
|
|
6614
|
-
const
|
|
6615
|
-
const
|
|
6616
|
-
const
|
|
6617
|
-
if (!
|
|
6709
|
+
async updateEntryWithRouterProvider() {
|
|
6710
|
+
const { exclude, output, router } = this.fileCompiler.options;
|
|
6711
|
+
const inputPath = this.fileCompiler.getInputPath();
|
|
6712
|
+
const outputPath = this.fileCompiler.getOuputPath(true);
|
|
6713
|
+
if (output?.bootstrapVite === false || router?.autoUpdateEntry === false || !router?.configFile) {
|
|
6618
6714
|
return;
|
|
6619
6715
|
}
|
|
6620
|
-
const
|
|
6621
|
-
|
|
6622
|
-
|
|
6623
|
-
|
|
6624
|
-
|
|
6625
|
-
|
|
6716
|
+
const getMainFile = async (filename) => {
|
|
6717
|
+
const filePath = path7.resolve(outputPath, filename);
|
|
6718
|
+
try {
|
|
6719
|
+
return { filePath, content: await fs4.promises.readFile(filePath, "utf-8") };
|
|
6720
|
+
} catch {
|
|
6721
|
+
return;
|
|
6722
|
+
}
|
|
6723
|
+
};
|
|
6724
|
+
const fileData = await getMainFile("main.tsx") || await getMainFile("main.jsx");
|
|
6725
|
+
if (!fileData) {
|
|
6726
|
+
console.warn(
|
|
6727
|
+
`${kleur6.yellow("\u26A0\uFE0F")} React application entry file not found, please confirm the filename is main.tsx or main.jsx?`
|
|
6728
|
+
);
|
|
6729
|
+
return;
|
|
6626
6730
|
}
|
|
6731
|
+
const prepareRouterEntry = () => {
|
|
6732
|
+
const importPath = this.fileCompiler.resolveRelativePath(inputPath, router.configFile);
|
|
6733
|
+
let content = fileData.content;
|
|
6734
|
+
if (exclude?.includes(router.configFile) || exclude?.includes(importPath)) {
|
|
6735
|
+
return content;
|
|
6736
|
+
}
|
|
6737
|
+
const routerModule = "RouterInstance";
|
|
6738
|
+
if (content.includes(routerModule) || content.includes(importPath)) {
|
|
6739
|
+
return content;
|
|
6740
|
+
}
|
|
6741
|
+
const routerImport = `import ${routerModule} from '${importPath}'`;
|
|
6742
|
+
if (content.includes("./App")) {
|
|
6743
|
+
const appImportRegex = /import\s+(?:App|.*)\s+from\s+['"]\.\/App\.(?:tsx|jsx)['"]/;
|
|
6744
|
+
content = content.replace(appImportRegex, routerImport);
|
|
6745
|
+
} else {
|
|
6746
|
+
const lastImportMatch = content.match(/import.*from.*\n/g);
|
|
6747
|
+
if (lastImportMatch) {
|
|
6748
|
+
const lastImport = lastImportMatch.pop();
|
|
6749
|
+
content = content.replace(lastImport, `${lastImport}
|
|
6750
|
+
${routerImport}`);
|
|
6751
|
+
} else {
|
|
6752
|
+
content = `${routerImport}${content}`;
|
|
6753
|
+
}
|
|
6754
|
+
}
|
|
6755
|
+
const providerTag = `<${routerModule}.RouterProvider />`;
|
|
6756
|
+
fileData.content = content.replace(/<App\s*\/?>/g, providerTag);
|
|
6757
|
+
};
|
|
6758
|
+
prepareRouterEntry();
|
|
6759
|
+
await this.fileCompiler.writeFileWithDir(fileData.filePath, fileData.content);
|
|
6760
|
+
}
|
|
6761
|
+
/**
|
|
6762
|
+
* 获取跳过的文件数量
|
|
6763
|
+
*/
|
|
6764
|
+
getSkippedCount() {
|
|
6765
|
+
return this.skippedCount;
|
|
6766
|
+
}
|
|
6767
|
+
/**
|
|
6768
|
+
* 重置跳过的文件数量
|
|
6769
|
+
*/
|
|
6770
|
+
resetSkippedCount() {
|
|
6771
|
+
this.skippedCount = 0;
|
|
6627
6772
|
}
|
|
6628
6773
|
};
|
|
6629
6774
|
|
|
6630
6775
|
// src/compiler/shared/file-compiler/pipeline-manager.ts
|
|
6631
|
-
import
|
|
6776
|
+
import path8 from "path";
|
|
6632
6777
|
var PipelineManager = class {
|
|
6633
6778
|
constructor(fileCompiler, fileProcessor) {
|
|
6634
6779
|
this.fileCompiler = fileCompiler;
|
|
@@ -6663,7 +6808,7 @@ var PipelineManager = class {
|
|
|
6663
6808
|
const scriptExtRegex = /\.(js|ts)$/i;
|
|
6664
6809
|
const styleExtRegex = /\.(css|less|sass|scss)$/i;
|
|
6665
6810
|
const files = this.fileCompiler.scanFiles(inputPath, (p) => {
|
|
6666
|
-
const ext =
|
|
6811
|
+
const ext = path8.extname(p);
|
|
6667
6812
|
if (key === "sfc" /* SFC */) {
|
|
6668
6813
|
return ext === ".vue";
|
|
6669
6814
|
}
|
|
@@ -6675,28 +6820,21 @@ var PipelineManager = class {
|
|
|
6675
6820
|
}
|
|
6676
6821
|
return false;
|
|
6677
6822
|
});
|
|
6678
|
-
if (!files.length) return 0;
|
|
6679
|
-
const cache = await this.fileCompiler.loadCache(key);
|
|
6680
6823
|
const absFiles = new Set(files.map((f) => this.fileCompiler.getAbsPath(f)));
|
|
6681
6824
|
await this.cleanupManager.cleanupOldOutput(key, (c) => !absFiles.has(c.file));
|
|
6682
|
-
|
|
6683
|
-
|
|
6684
|
-
|
|
6685
|
-
|
|
6686
|
-
} else {
|
|
6687
|
-
return this.fileProcessor.processFile(key, f, cache);
|
|
6688
|
-
}
|
|
6689
|
-
})
|
|
6825
|
+
if (!files.length) return 0;
|
|
6826
|
+
const cache = await this.fileCompiler.loadCache(key);
|
|
6827
|
+
const compiled = await Promise.all(
|
|
6828
|
+
files.map(async (f) => this.fileProcessor.processFile(key, f, cache))
|
|
6690
6829
|
);
|
|
6691
|
-
|
|
6692
|
-
|
|
6693
|
-
return compiledCount;
|
|
6830
|
+
await this.fileCompiler.flushCache(key);
|
|
6831
|
+
return compiled.filter(Boolean).length;
|
|
6694
6832
|
}
|
|
6695
6833
|
/**
|
|
6696
6834
|
* 获取跳过的文件数量
|
|
6697
6835
|
*/
|
|
6698
6836
|
getSkippedCount() {
|
|
6699
|
-
return this.skippedCount;
|
|
6837
|
+
return this.skippedCount += this.fileProcessor.getSkippedCount();
|
|
6700
6838
|
}
|
|
6701
6839
|
/**
|
|
6702
6840
|
* 重置跳过的文件数量
|
|
@@ -6707,9 +6845,9 @@ var PipelineManager = class {
|
|
|
6707
6845
|
};
|
|
6708
6846
|
|
|
6709
6847
|
// src/compiler/shared/file-compiler/vite-bootstrapper.ts
|
|
6710
|
-
import { execSync
|
|
6711
|
-
import
|
|
6712
|
-
import
|
|
6848
|
+
import { execSync } from "child_process";
|
|
6849
|
+
import fs5 from "fs";
|
|
6850
|
+
import kleur7 from "kleur";
|
|
6713
6851
|
import ora from "ora";
|
|
6714
6852
|
var ViteBootstrapper = class {
|
|
6715
6853
|
constructor(fileCompiler, options) {
|
|
@@ -6717,21 +6855,19 @@ var ViteBootstrapper = class {
|
|
|
6717
6855
|
this.options = options;
|
|
6718
6856
|
}
|
|
6719
6857
|
spinner = ora();
|
|
6720
|
-
|
|
6721
|
-
|
|
6722
|
-
|
|
6723
|
-
version: "^1.0.0"
|
|
6724
|
-
}
|
|
6858
|
+
defaultConfig = {
|
|
6859
|
+
template: "react-ts",
|
|
6860
|
+
viteVersion: "@latest"
|
|
6725
6861
|
};
|
|
6726
6862
|
/**
|
|
6727
6863
|
* 检查是否需要初始化 Vite 环境
|
|
6728
6864
|
*/
|
|
6729
6865
|
isSingleFile() {
|
|
6730
6866
|
const inputPath = this.fileCompiler.getInputPath();
|
|
6731
|
-
if (!
|
|
6867
|
+
if (!fs5.existsSync(inputPath)) {
|
|
6732
6868
|
return false;
|
|
6733
6869
|
}
|
|
6734
|
-
const stat =
|
|
6870
|
+
const stat = fs5.statSync(inputPath);
|
|
6735
6871
|
return stat.isFile();
|
|
6736
6872
|
}
|
|
6737
6873
|
/**
|
|
@@ -6739,27 +6875,27 @@ var ViteBootstrapper = class {
|
|
|
6739
6875
|
*/
|
|
6740
6876
|
async bootstrapIfNeeded() {
|
|
6741
6877
|
const { bootstrapVite } = this.options.output || {};
|
|
6878
|
+
const workspaceDir = this.fileCompiler.getWorkspaceDir();
|
|
6879
|
+
await fs5.promises.mkdir(workspaceDir, { recursive: true });
|
|
6742
6880
|
if (bootstrapVite === false) {
|
|
6743
6881
|
return false;
|
|
6744
6882
|
}
|
|
6745
6883
|
if (this.isSingleFile()) {
|
|
6746
|
-
console.info(
|
|
6884
|
+
console.info("Skipping Vite initialization for single file compilation");
|
|
6747
6885
|
return false;
|
|
6748
6886
|
}
|
|
6749
|
-
const workspaceDir = this.fileCompiler.getWorkspaceDir();
|
|
6750
6887
|
const outputPkgPath = this.fileCompiler.getOutputPkgPath();
|
|
6751
|
-
if (
|
|
6888
|
+
if (fs5.existsSync(outputPkgPath)) {
|
|
6752
6889
|
return false;
|
|
6753
6890
|
}
|
|
6754
6891
|
this.spinner.start("Bootstrapping Vite React environment...");
|
|
6755
|
-
await fs4.promises.mkdir(workspaceDir, { recursive: true });
|
|
6756
6892
|
try {
|
|
6757
|
-
this.resolveViteCreateApp();
|
|
6893
|
+
await this.resolveViteCreateApp();
|
|
6758
6894
|
} catch (err) {
|
|
6759
6895
|
this.spinner.stop();
|
|
6760
6896
|
console.error(
|
|
6761
|
-
|
|
6762
|
-
"Failed to bootstrap Vite environment. Please check npm/network
|
|
6897
|
+
kleur7.red("\u2716"),
|
|
6898
|
+
"Failed to bootstrap Vite environment. Please check npm/network.",
|
|
6763
6899
|
err
|
|
6764
6900
|
);
|
|
6765
6901
|
return false;
|
|
@@ -6779,7 +6915,7 @@ var ViteBootstrapper = class {
|
|
|
6779
6915
|
...vite
|
|
6780
6916
|
};
|
|
6781
6917
|
if (!isDev) {
|
|
6782
|
-
const { runtime } =
|
|
6918
|
+
const { runtime } = RUNTIME_PACKAGES;
|
|
6783
6919
|
deps[runtime.name] = runtime.version;
|
|
6784
6920
|
}
|
|
6785
6921
|
return deps;
|
|
@@ -6791,91 +6927,122 @@ var ViteBootstrapper = class {
|
|
|
6791
6927
|
const newDevDeps = resolveDeps(rootPkg.devDependencies, vitePkg.devDependencies, true);
|
|
6792
6928
|
vitePkg.dependencies = newDeps;
|
|
6793
6929
|
vitePkg.devDependencies = newDevDeps;
|
|
6794
|
-
|
|
6930
|
+
const newVitePkg = JSON.stringify(vitePkg, null, 2);
|
|
6931
|
+
await this.fileCompiler.writeFileWithDir(outputPkgPath, newVitePkg);
|
|
6795
6932
|
this.spinner.succeed("Standard Vite React environment initialized");
|
|
6796
6933
|
return true;
|
|
6797
6934
|
}
|
|
6798
6935
|
/**
|
|
6799
6936
|
* 执行 vite 创建命令
|
|
6800
6937
|
*/
|
|
6801
|
-
resolveViteCreateApp() {
|
|
6938
|
+
async resolveViteCreateApp() {
|
|
6802
6939
|
const { output } = this.options;
|
|
6803
|
-
const
|
|
6804
|
-
const
|
|
6940
|
+
const { viteVersion, template: tmpl } = this.defaultConfig;
|
|
6941
|
+
const bootstrapVite = output?.bootstrapVite;
|
|
6805
6942
|
const outDirName = this.fileCompiler.getOutDirName();
|
|
6806
|
-
const
|
|
6807
|
-
|
|
6943
|
+
const configObject = typeof bootstrapVite === "object" ? bootstrapVite : null;
|
|
6944
|
+
const viteVer = configObject?.vite || viteVersion;
|
|
6945
|
+
const reactVer = configObject?.react;
|
|
6946
|
+
const template = configObject?.template || tmpl;
|
|
6947
|
+
const cmd = `npm create vite${viteVer} ${outDirName} -- --template ${template}`;
|
|
6948
|
+
execSync(cmd, {
|
|
6808
6949
|
cwd: this.fileCompiler.getWorkspaceDir(),
|
|
6809
6950
|
stdio: "ignore"
|
|
6810
6951
|
// 隐藏 create-vite 内部的输出日志,保持终端整洁
|
|
6811
6952
|
});
|
|
6953
|
+
if (reactVer) {
|
|
6954
|
+
await this.resolveReactVersion(reactVer);
|
|
6955
|
+
}
|
|
6812
6956
|
}
|
|
6813
|
-
};
|
|
6814
|
-
|
|
6815
|
-
// src/compiler/shared/file-compiler/index.ts
|
|
6816
|
-
var FileCompiler = class extends BaseCompiler {
|
|
6817
|
-
skippedCount = 0;
|
|
6818
|
-
spinner = ora2();
|
|
6819
|
-
// 管理器实例
|
|
6820
|
-
viteBootstrapper;
|
|
6821
|
-
pipelineManager;
|
|
6822
|
-
fileProcessor;
|
|
6823
|
-
compilationUnitProcessor;
|
|
6824
|
-
cacheManager;
|
|
6825
|
-
assetManager;
|
|
6826
|
-
cleanupManager;
|
|
6827
6957
|
/**
|
|
6828
|
-
*
|
|
6829
|
-
*
|
|
6830
|
-
* @param options - 编译器配置选项,继承自 BaseCompiler 的选项
|
|
6831
|
-
* 包括输入路径、输出配置、缓存设置、排除模式等
|
|
6832
|
-
* @see {@link CompilerOptions} 查看完整的选项说明
|
|
6958
|
+
* 处理 React 包版本
|
|
6959
|
+
* @param ver 版本号
|
|
6833
6960
|
*/
|
|
6834
|
-
|
|
6835
|
-
|
|
6836
|
-
this.
|
|
6961
|
+
async resolveReactVersion(ver) {
|
|
6962
|
+
const outputPkgPath = this.fileCompiler.getOutputPkgPath();
|
|
6963
|
+
const vitePkg = await this.fileCompiler.resolvePackageFile(outputPkgPath);
|
|
6964
|
+
const typesVer = `^${ver.split(".")[0].replace(/@|\^/, "")}.0.0`;
|
|
6965
|
+
vitePkg.dependencies.react = ver;
|
|
6966
|
+
vitePkg.dependencies["react-dom"] = ver;
|
|
6967
|
+
vitePkg.devDependencies["@types/react"] = typesVer;
|
|
6968
|
+
vitePkg.devDependencies["@types/react-dom"] = typesVer;
|
|
6969
|
+
await this.fileCompiler.writeFileWithDir(outputPkgPath, JSON.stringify(vitePkg, null, 2), {
|
|
6970
|
+
lock: true
|
|
6971
|
+
});
|
|
6972
|
+
}
|
|
6973
|
+
};
|
|
6974
|
+
|
|
6975
|
+
// src/compiler/shared/file-compiler/setup-manager.ts
|
|
6976
|
+
var SetupManager = class {
|
|
6977
|
+
constructor(getCompiler) {
|
|
6978
|
+
this.getCompiler = getCompiler;
|
|
6979
|
+
this.setup();
|
|
6837
6980
|
}
|
|
6838
6981
|
/**
|
|
6839
6982
|
* 初始化所有管理器实例
|
|
6840
6983
|
*
|
|
6841
|
-
*
|
|
6984
|
+
* !必须按照依赖关系顺序创建各个管理器:
|
|
6842
6985
|
* 1. 基础管理器(无依赖)
|
|
6843
6986
|
* 2. 依赖基础管理器的管理器
|
|
6844
6987
|
* 3. 依赖其他管理器的管理器
|
|
6845
|
-
*
|
|
6846
|
-
* @private
|
|
6847
6988
|
*/
|
|
6848
|
-
|
|
6849
|
-
|
|
6850
|
-
this.
|
|
6851
|
-
this.
|
|
6852
|
-
this.
|
|
6853
|
-
this.viteBootstrapper = new ViteBootstrapper(this, this.options);
|
|
6854
|
-
this.pipelineManager = new PipelineManager(this, this.fileProcessor);
|
|
6855
|
-
this.assetManager = new AssetManager(this, this.cleanupManager);
|
|
6989
|
+
setup() {
|
|
6990
|
+
const fileCompiler = this.getCompiler();
|
|
6991
|
+
this.setupBaseManager(fileCompiler);
|
|
6992
|
+
this.setupManagedByBase(fileCompiler);
|
|
6993
|
+
this.setupCompositeManager(fileCompiler);
|
|
6856
6994
|
}
|
|
6857
6995
|
/**
|
|
6858
|
-
*
|
|
6859
|
-
|
|
6860
|
-
|
|
6861
|
-
|
|
6862
|
-
|
|
6863
|
-
|
|
6864
|
-
|
|
6865
|
-
|
|
6866
|
-
|
|
6867
|
-
*
|
|
6868
|
-
* @throws {Error} 当编译过程中发生致命错误时抛出
|
|
6869
|
-
* @returns {Promise<void>}
|
|
6996
|
+
* 创建基础的管理器(无外部依赖)
|
|
6997
|
+
*/
|
|
6998
|
+
setupBaseManager(fileCompiler) {
|
|
6999
|
+
fileCompiler.manager = {};
|
|
7000
|
+
const manager = fileCompiler.manager;
|
|
7001
|
+
manager.cacheManager = new CacheManager(fileCompiler);
|
|
7002
|
+
manager.cleanupManager = new CleanupManager(fileCompiler);
|
|
7003
|
+
}
|
|
7004
|
+
/**
|
|
7005
|
+
* 创建依赖基础管理器的管理器
|
|
6870
7006
|
*/
|
|
7007
|
+
setupManagedByBase(fileCompiler) {
|
|
7008
|
+
const manager = fileCompiler.manager;
|
|
7009
|
+
manager.fileProcessor = new FileProcessor(
|
|
7010
|
+
fileCompiler,
|
|
7011
|
+
new CompilationUnitProcessor(fileCompiler),
|
|
7012
|
+
manager.cacheManager
|
|
7013
|
+
);
|
|
7014
|
+
}
|
|
7015
|
+
/**
|
|
7016
|
+
* 创建依赖其他管理器的管理器
|
|
7017
|
+
*/
|
|
7018
|
+
setupCompositeManager(fileCompiler) {
|
|
7019
|
+
const manager = fileCompiler.manager;
|
|
7020
|
+
manager.viteBootstrapper = new ViteBootstrapper(fileCompiler, fileCompiler.options);
|
|
7021
|
+
manager.pipelineManager = new PipelineManager(fileCompiler, manager.fileProcessor);
|
|
7022
|
+
manager.assetManager = new AssetManager(fileCompiler, manager.cleanupManager);
|
|
7023
|
+
}
|
|
7024
|
+
};
|
|
7025
|
+
|
|
7026
|
+
// src/compiler/shared/file-compiler/index.ts
|
|
7027
|
+
var FileCompiler = class extends BaseCompiler {
|
|
7028
|
+
manager;
|
|
7029
|
+
spinner = ora2();
|
|
7030
|
+
constructor(options = {}) {
|
|
7031
|
+
super(options);
|
|
7032
|
+
new SetupManager(() => this);
|
|
7033
|
+
}
|
|
7034
|
+
/** 执行完整的编译流程 */
|
|
6871
7035
|
async execute() {
|
|
6872
|
-
console.info("\n\n",
|
|
7036
|
+
console.info("\n\n", kleur8.magenta(`${kleur8.bold("VUREACT")} v${this.version}`), "\n");
|
|
6873
7037
|
const startTime = performance.now();
|
|
6874
|
-
|
|
6875
|
-
await
|
|
6876
|
-
}
|
|
6877
|
-
await this.viteBootstrapper.bootstrapIfNeeded();
|
|
7038
|
+
const rmWorkspace = async () => {
|
|
7039
|
+
await this.rmFile(this.getWorkspaceDir());
|
|
7040
|
+
};
|
|
6878
7041
|
try {
|
|
7042
|
+
if (!this.getIsCache()) {
|
|
7043
|
+
await rmWorkspace();
|
|
7044
|
+
}
|
|
7045
|
+
await this.manager.viteBootstrapper.bootstrapIfNeeded();
|
|
6879
7046
|
const sfcCount = await this.runPipelineWithSpinner("sfc" /* SFC */);
|
|
6880
7047
|
const scriptCount = await this.runPipelineWithSpinner("script" /* SCRIPT */);
|
|
6881
7048
|
const styleCount = await this.runPipelineWithSpinner("style" /* STYLE */);
|
|
@@ -6886,35 +7053,71 @@ var FileCompiler = class extends BaseCompiler {
|
|
|
6886
7053
|
this.showCompileStats(endTime, sfcCount, scriptCount, styleCount, assetCount);
|
|
6887
7054
|
} catch (error) {
|
|
6888
7055
|
const endTime = calcElapsedTime(startTime);
|
|
6889
|
-
|
|
7056
|
+
await rmWorkspace();
|
|
7057
|
+
console.error(kleur8.red("\u2716"), `Build failed in ${endTime}`);
|
|
6890
7058
|
console.error(error);
|
|
7059
|
+
} finally {
|
|
7060
|
+
this.resetSkippedCount();
|
|
6891
7061
|
}
|
|
6892
7062
|
}
|
|
6893
|
-
/**
|
|
6894
|
-
|
|
6895
|
-
|
|
6896
|
-
|
|
6897
|
-
|
|
6898
|
-
|
|
6899
|
-
|
|
6900
|
-
|
|
7063
|
+
/** 处理单个 Vue 单文件组件(SFC) */
|
|
7064
|
+
async processSFC(filePath, existingCache) {
|
|
7065
|
+
return this.manager.fileProcessor.processSFC(filePath, existingCache);
|
|
7066
|
+
}
|
|
7067
|
+
/** 处理单个 JavaScript/TypeScript 脚本文件 */
|
|
7068
|
+
async processScript(filePath, existingCache) {
|
|
7069
|
+
return this.manager.fileProcessor.processScript(filePath, existingCache);
|
|
7070
|
+
}
|
|
7071
|
+
/** 处理单个 CSS/LESS/SCSS 样式文件 */
|
|
7072
|
+
async processStyle(filePath, existingCache) {
|
|
7073
|
+
return this.manager.fileProcessor.processStyle(filePath, existingCache);
|
|
7074
|
+
}
|
|
7075
|
+
/** 处理单个文件(Vue 或 Script) */
|
|
7076
|
+
async processFile(key, filePath, existingCache) {
|
|
7077
|
+
if (key === "sfc" /* SFC */) {
|
|
7078
|
+
return this.manager.fileProcessor.processFile(key, filePath, existingCache);
|
|
7079
|
+
} else if (key === "script" /* SCRIPT */) {
|
|
7080
|
+
return this.manager.fileProcessor.processFile(
|
|
7081
|
+
key,
|
|
7082
|
+
filePath,
|
|
7083
|
+
existingCache
|
|
7084
|
+
);
|
|
7085
|
+
}
|
|
7086
|
+
return this.manager.fileProcessor.processFile(
|
|
7087
|
+
key,
|
|
7088
|
+
filePath,
|
|
7089
|
+
existingCache
|
|
7090
|
+
);
|
|
7091
|
+
}
|
|
7092
|
+
/** 处理单个资源文件 */
|
|
7093
|
+
async processAsset(filePath, existingCache) {
|
|
7094
|
+
return this.manager.assetManager.processAsset(filePath, existingCache);
|
|
7095
|
+
}
|
|
7096
|
+
/** 批量保存缓存 */
|
|
7097
|
+
async flushCache(key) {
|
|
7098
|
+
await this.manager.cacheManager.flushCache(key);
|
|
7099
|
+
}
|
|
7100
|
+
/** 删除指定路径对应的输出文件和缓存 */
|
|
7101
|
+
async removeOutputPath(targetPath, type) {
|
|
7102
|
+
return await this.manager.cleanupManager.removeOutputPath(targetPath, type);
|
|
7103
|
+
}
|
|
6901
7104
|
async runPipelineWithSpinner(name) {
|
|
6902
7105
|
const options = {
|
|
6903
7106
|
["sfc" /* SFC */]: {
|
|
6904
7107
|
text: "Compiling Vue files...",
|
|
6905
|
-
pipeline: () => this.pipelineManager.runSfcPipeline()
|
|
7108
|
+
pipeline: () => this.manager.pipelineManager.runSfcPipeline()
|
|
6906
7109
|
},
|
|
6907
7110
|
["script" /* SCRIPT */]: {
|
|
6908
7111
|
text: "Compiling script files...",
|
|
6909
|
-
pipeline: () => this.pipelineManager.runScriptPipeline()
|
|
7112
|
+
pipeline: () => this.manager.pipelineManager.runScriptPipeline()
|
|
6910
7113
|
},
|
|
6911
7114
|
["style" /* STYLE */]: {
|
|
6912
7115
|
text: "Compiling style files...",
|
|
6913
|
-
pipeline: () => this.pipelineManager.runStylePipeline()
|
|
7116
|
+
pipeline: () => this.manager.pipelineManager.runStylePipeline()
|
|
6914
7117
|
},
|
|
6915
7118
|
["copied" /* ASSET */]: {
|
|
6916
7119
|
text: "Copying assets...",
|
|
6917
|
-
pipeline: () => this.assetManager.runAssetPipeline()
|
|
7120
|
+
pipeline: () => this.manager.assetManager.runAssetPipeline()
|
|
6918
7121
|
}
|
|
6919
7122
|
};
|
|
6920
7123
|
const { text, pipeline } = options[name];
|
|
@@ -6927,166 +7130,36 @@ var FileCompiler = class extends BaseCompiler {
|
|
|
6927
7130
|
this.spinner.stop();
|
|
6928
7131
|
}
|
|
6929
7132
|
}
|
|
6930
|
-
/**
|
|
6931
|
-
* 处理单个 Vue 单文件组件(SFC)
|
|
6932
|
-
*
|
|
6933
|
-
* 此方法主要用于 CLI 的 watch 模式,当检测到文件变更时调用。
|
|
6934
|
-
* 支持增量编译,如果文件未变更则跳过编译。
|
|
6935
|
-
*
|
|
6936
|
-
* @async
|
|
6937
|
-
* @param filePath - Vue 文件的绝对路径
|
|
6938
|
-
* @param existingCache - 可选的预加载缓存对象,用于增量编译
|
|
6939
|
-
* @returns {Promise<SFCUnit | undefined>} 编译单元对象,如果跳过编译则返回 undefined
|
|
6940
|
-
* @see {@link FileProcessor.processSFC}
|
|
6941
|
-
*/
|
|
6942
|
-
async processSFC(filePath, existingCache) {
|
|
6943
|
-
return this.fileProcessor.processSFC(filePath, existingCache);
|
|
6944
|
-
}
|
|
6945
|
-
/**
|
|
6946
|
-
* 处理单个 JavaScript/TypeScript 脚本文件
|
|
6947
|
-
*
|
|
6948
|
-
* 此方法主要用于 CLI 的 watch 模式,当检测到文件变更时调用。
|
|
6949
|
-
* 支持增量编译,如果文件未变更则跳过编译。
|
|
6950
|
-
*
|
|
6951
|
-
* @async
|
|
6952
|
-
* @param filePath - 脚本文件的绝对路径
|
|
6953
|
-
* @param existingCache - 可选的预加载缓存对象,用于增量编译
|
|
6954
|
-
* @returns {Promise<ScriptUnit | undefined>} 编译单元对象,如果跳过编译则返回 undefined
|
|
6955
|
-
* @see {@link FileProcessor.processScript}
|
|
6956
|
-
*/
|
|
6957
|
-
async processScript(filePath, existingCache) {
|
|
6958
|
-
return this.fileProcessor.processScript(filePath, existingCache);
|
|
6959
|
-
}
|
|
6960
|
-
/**
|
|
6961
|
-
* 处理单个 CSS/LESS/SCSS 样式文件
|
|
6962
|
-
*
|
|
6963
|
-
* 此方法主要用于 CLI 的 watch 模式,当检测到文件变更时调用。
|
|
6964
|
-
* 支持增量编译,如果文件未变更则跳过编译。
|
|
6965
|
-
*
|
|
6966
|
-
* @async
|
|
6967
|
-
* @param filePath - style 文件的绝对路径
|
|
6968
|
-
* @param existingCache - 可选的预加载缓存对象,用于增量编译
|
|
6969
|
-
* @returns {Promise<ScriptUnit | undefined>} 编译单元对象,如果跳过编译则返回 undefined
|
|
6970
|
-
* @see {@link FileProcessor.processStyle}
|
|
6971
|
-
*/
|
|
6972
|
-
async processStyle(filePath, existingCache) {
|
|
6973
|
-
return this.fileProcessor.processStyle(filePath, existingCache);
|
|
6974
|
-
}
|
|
6975
|
-
/**
|
|
6976
|
-
* 处理单个文件(Vue 或 Script)
|
|
6977
|
-
*
|
|
6978
|
-
* 通用的文件处理方法,根据 CacheKey 类型自动选择处理逻辑。
|
|
6979
|
-
* 主要用于内部调用和统一的文件处理接口。
|
|
6980
|
-
*
|
|
6981
|
-
* @async
|
|
6982
|
-
* @param key - 文件类型标识(SFC 或 SCRIPT)
|
|
6983
|
-
* @param filePath - 文件的绝对路径
|
|
6984
|
-
* @param existingCache - 可选的预加载缓存对象
|
|
6985
|
-
* @returns {Promise<SFCUnit | ScriptUnit | undefined>} 编译单元对象
|
|
6986
|
-
* @see {@link FileProcessor.processFile}
|
|
6987
|
-
*/
|
|
6988
|
-
async processFile(key, filePath, existingCache) {
|
|
6989
|
-
if (key === "sfc" /* SFC */) {
|
|
6990
|
-
return this.fileProcessor.processFile(key, filePath, existingCache);
|
|
6991
|
-
} else if (key === "script" /* SCRIPT */) {
|
|
6992
|
-
return this.fileProcessor.processFile(key, filePath, existingCache);
|
|
6993
|
-
}
|
|
6994
|
-
return this.fileProcessor.processFile(
|
|
6995
|
-
key,
|
|
6996
|
-
filePath,
|
|
6997
|
-
existingCache
|
|
6998
|
-
);
|
|
6999
|
-
}
|
|
7000
|
-
/**
|
|
7001
|
-
* 处理单个资源文件
|
|
7002
|
-
*
|
|
7003
|
-
* 比较文件与缓存,决定是否需要拷贝。
|
|
7004
|
-
* 资源文件包括图片、字体、样式文件等非编译文件。
|
|
7005
|
-
*
|
|
7006
|
-
* @async
|
|
7007
|
-
* @param filePath - 资源文件的绝对路径
|
|
7008
|
-
* @param existingCache - 可选的预加载缓存对象
|
|
7009
|
-
* @returns {Promise<FileCacheMeta>} 资源文件的缓存元数据
|
|
7010
|
-
* @see {@link AssetManager.processAsset}
|
|
7011
|
-
*/
|
|
7012
|
-
async processAsset(filePath, existingCache) {
|
|
7013
|
-
return this.assetManager.processAsset(filePath, existingCache);
|
|
7014
|
-
}
|
|
7015
|
-
/**
|
|
7016
|
-
* 删除指定路径对应的输出文件和缓存
|
|
7017
|
-
*
|
|
7018
|
-
* 当源文件被删除或重命名时,需要清理对应的输出文件。
|
|
7019
|
-
* 主要用于 watch 模式下的文件删除处理。
|
|
7020
|
-
*
|
|
7021
|
-
* @async
|
|
7022
|
-
* @param targetPath - 源代码的路径(文件或文件夹)
|
|
7023
|
-
* @param type - 清理类型,指定是 SFC、SCRIPT 还是 ASSET
|
|
7024
|
-
* @returns {Promise<void>}
|
|
7025
|
-
* @see {@link CleanupManager.removeOutputPath}
|
|
7026
|
-
*/
|
|
7027
|
-
async removeOutputPath(targetPath, type) {
|
|
7028
|
-
return this.cleanupManager.removeOutputPath(targetPath, type);
|
|
7029
|
-
}
|
|
7030
|
-
/**
|
|
7031
|
-
* 获取跳过的文件数量
|
|
7032
|
-
*
|
|
7033
|
-
* 在增量编译中,未变更的文件会被跳过。
|
|
7034
|
-
* 此方法返回当前编译会话中跳过的文件数量。
|
|
7035
|
-
*
|
|
7036
|
-
* @returns {number} 跳过的文件数量
|
|
7037
|
-
*/
|
|
7038
|
-
getSkippedCount() {
|
|
7039
|
-
return this.skippedCount;
|
|
7040
|
-
}
|
|
7041
|
-
/**
|
|
7042
|
-
* 重置跳过的文件数量
|
|
7043
|
-
*
|
|
7044
|
-
* 在每次新的编译会话开始时调用,重置计数器。
|
|
7045
|
-
*/
|
|
7046
|
-
resetSkippedCount() {
|
|
7047
|
-
this.skippedCount = 0;
|
|
7048
|
-
}
|
|
7049
|
-
/**
|
|
7050
|
-
* 显示编译统计信息
|
|
7051
|
-
*
|
|
7052
|
-
* 在编译完成后调用,显示以下信息:
|
|
7053
|
-
* 1. 编译耗时
|
|
7054
|
-
* 2. 输出目录
|
|
7055
|
-
* 3. 跳过的文件数量
|
|
7056
|
-
* 4. 处理的文件分类统计
|
|
7057
|
-
*
|
|
7058
|
-
* @private
|
|
7059
|
-
* @param endTime - 格式化后的编译耗时字符串
|
|
7060
|
-
* @param sfcCount - 处理的 Vue 文件数量
|
|
7061
|
-
* @param scriptCount - 处理的脚本文件数量
|
|
7062
|
-
* @param assetCount - 处理的资源文件数量
|
|
7063
|
-
*/
|
|
7064
7133
|
showCompileStats(endTime, sfcCount, scriptCount, styleCount, assetCount) {
|
|
7065
|
-
const dir = normalizePath(this.relativePath(this.getOuputPath()));
|
|
7066
7134
|
this.spinner.succeed(`Build completed in ${endTime}`);
|
|
7067
|
-
console.info(` Output directory: ${kleur6.dim(dir)}`);
|
|
7068
7135
|
console.info();
|
|
7069
|
-
this.skippedCount += this.pipelineManager.getSkippedCount();
|
|
7070
|
-
this.pipelineManager.resetSkippedCount();
|
|
7071
|
-
if (this.skippedCount) {
|
|
7072
|
-
console.info(kleur6.dim(`Skipped ${this.skippedCount} unchanged file(s)`));
|
|
7073
|
-
this.resetSkippedCount();
|
|
7074
|
-
}
|
|
7075
7136
|
if (sfcCount || scriptCount || styleCount || assetCount) {
|
|
7076
7137
|
const stats = [];
|
|
7077
7138
|
if (sfcCount) stats.push(`${sfcCount} SFC(s)`);
|
|
7078
7139
|
if (scriptCount) stats.push(`${scriptCount} script(s)`);
|
|
7079
7140
|
if (styleCount) stats.push(`${styleCount} style(s)`);
|
|
7080
7141
|
if (assetCount) stats.push(`${assetCount} asset(s)`);
|
|
7081
|
-
|
|
7142
|
+
this.spinner.succeed(`Processed: ${stats.join(", ")}`);
|
|
7082
7143
|
}
|
|
7144
|
+
const skippedCount = this.manager.pipelineManager.getSkippedCount() + this.manager.assetManager.getSkippedCount();
|
|
7145
|
+
if (skippedCount) {
|
|
7146
|
+
console.info(kleur8.gray(`\u21B7 Cached: ${kleur8.white(skippedCount)} unchanged file(s)`));
|
|
7147
|
+
this.resetSkippedCount();
|
|
7148
|
+
}
|
|
7149
|
+
const dir = normalizePath(this.relativePath(this.getOuputPath()));
|
|
7083
7150
|
console.info();
|
|
7151
|
+
console.info(`\u{1F4E6} Output: ${dir}`);
|
|
7152
|
+
console.info();
|
|
7153
|
+
}
|
|
7154
|
+
resetSkippedCount() {
|
|
7155
|
+
this.manager.pipelineManager.resetSkippedCount();
|
|
7156
|
+
this.manager.assetManager.resetSkippedCount();
|
|
7084
7157
|
}
|
|
7085
7158
|
};
|
|
7086
7159
|
|
|
7087
7160
|
// src/compiler/shared/define-config.ts
|
|
7088
|
-
function defineConfig(
|
|
7089
|
-
return
|
|
7161
|
+
function defineConfig(config) {
|
|
7162
|
+
return typeof config === "function" ? config() : config;
|
|
7090
7163
|
}
|
|
7091
7164
|
|
|
7092
7165
|
// src/compiler/index.ts
|