@vizejs/vite-plugin 0.302.0 → 0.303.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/dist/index.mjs +371 -89
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { registerResolvedVizeConfig, unregisterResolvedVizeConfig } from "./internal/config-bridge.mjs";
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
|
-
import { createHash } from "node:crypto";
|
|
3
|
+
import crypto, { createHash } from "node:crypto";
|
|
4
4
|
import * as native from "@vizejs/native";
|
|
5
5
|
import { applyViteDefineReplacements, buildInspectorGraph, chunkVitePrecompileFiles, classifyVitePluginRequest, createViteBareImportBases, createViteBareImportCandidates, createViteVirtualId, detectViteHmrUpdateType, diffVitePrecompileFiles, generateViteHmrCode, hasViteHmrChanges, isViteBareSpecifier, normalizeViteCssModuleFilename, normalizeViteDevMiddlewareUrl, normalizeVitePrecompileBatchSize, normalizeViteRequireBase, normalizeViteResolvedVuePath, resolveViteAliasRequest, resolveViteCssImports, resolveViteRelativeImport, resolveViteVuePath, rewriteViteDynamicTemplateImports, rewriteViteImportMetaGlobBase, rewriteViteStaticAssetUrls, scopeViteCssForPipeline, shouldApplyViteDefineInVirtualModule, splitViteIdQuery, toViteBrowserImportPrefix, transformViteCssVarsForPipeline } from "@vizejs/native";
|
|
6
6
|
import { parseSync } from "oxc-parser";
|
|
@@ -526,6 +526,83 @@ function createLogger(debug) {
|
|
|
526
526
|
};
|
|
527
527
|
}
|
|
528
528
|
//#endregion
|
|
529
|
+
//#region src/plugin/precompile.ts
|
|
530
|
+
const DEFAULT_PRECOMPILE_IGNORE_PATTERNS = [
|
|
531
|
+
"node_modules/**",
|
|
532
|
+
"dist/**",
|
|
533
|
+
".git/**",
|
|
534
|
+
".nuxt/**",
|
|
535
|
+
".output/**",
|
|
536
|
+
".nitro/**",
|
|
537
|
+
"coverage/**"
|
|
538
|
+
];
|
|
539
|
+
function isPrecompileSfcPath(path) {
|
|
540
|
+
return path.endsWith(".vue");
|
|
541
|
+
}
|
|
542
|
+
function diffPrecompileFiles(files, currentMetadata, previousMetadata) {
|
|
543
|
+
return diffVitePrecompileFiles([...files], toNativePrecompileMetadataEntries(currentMetadata), toNativePrecompileMetadataEntries(previousMetadata));
|
|
544
|
+
}
|
|
545
|
+
function normalizePrecompileBatchSize(value) {
|
|
546
|
+
return normalizeVitePrecompileBatchSize(value);
|
|
547
|
+
}
|
|
548
|
+
function chunkPrecompileFiles(files, batchSize, options = {}) {
|
|
549
|
+
return chunkVitePrecompileFiles([...files], batchSize, {
|
|
550
|
+
maxBytes: options.maxBytes,
|
|
551
|
+
metadata: options.metadata ? toNativePrecompileMetadataEntries(options.metadata) : void 0
|
|
552
|
+
});
|
|
553
|
+
}
|
|
554
|
+
function toNativePrecompileMetadataEntries(metadata) {
|
|
555
|
+
const entries = [];
|
|
556
|
+
for (const [path, value] of metadata) entries.push({
|
|
557
|
+
path,
|
|
558
|
+
mtimeMs: value.mtimeMs,
|
|
559
|
+
size: value.size
|
|
560
|
+
});
|
|
561
|
+
return entries;
|
|
562
|
+
}
|
|
563
|
+
//#endregion
|
|
564
|
+
//#region src/plugin/state.ts
|
|
565
|
+
function getEnvironmentCache(state, ssr) {
|
|
566
|
+
return ssr ? state.ssrCache : state.cache;
|
|
567
|
+
}
|
|
568
|
+
function getCompileOptionsForRequest(state, ssr) {
|
|
569
|
+
const options = {
|
|
570
|
+
sourceMap: state.mergedOptions?.sourceMap ?? !state.isProduction,
|
|
571
|
+
ssr,
|
|
572
|
+
vapor: !ssr && (state.mergedOptions?.vapor ?? false),
|
|
573
|
+
customRenderer: state.mergedOptions?.customRenderer ?? false,
|
|
574
|
+
templateSyntax: state.mergedOptions?.templateSyntax ?? "standard"
|
|
575
|
+
};
|
|
576
|
+
if (state.mergedOptions?.mode !== void 0) options.mode = state.mergedOptions.mode;
|
|
577
|
+
if (state.mergedOptions?.runtimeModuleName !== void 0) options.runtimeModuleName = state.mergedOptions.runtimeModuleName;
|
|
578
|
+
if (state.mergedOptions?.runtimeGlobalName !== void 0) options.runtimeGlobalName = state.mergedOptions.runtimeGlobalName;
|
|
579
|
+
if (state.mergedOptions?.vueVersion !== void 0) options.vueVersion = state.mergedOptions.vueVersion;
|
|
580
|
+
if (state.mergedOptions?.experimentalInTagComments) options.experimentalInTagComments = true;
|
|
581
|
+
if (state.mergedOptions?.experimentalPatternedTemplate) options.experimentalPatternedTemplate = true;
|
|
582
|
+
if (state.mergedOptions?.experimentalServerScript) options.experimentalServerScript = true;
|
|
583
|
+
return options;
|
|
584
|
+
}
|
|
585
|
+
function syncCollectedCssForFile(state, filePath, compiled) {
|
|
586
|
+
if (!compiled || !state.extractCss) return;
|
|
587
|
+
if (compiled.styles?.length) {
|
|
588
|
+
state.collectedCss.delete(filePath);
|
|
589
|
+
return;
|
|
590
|
+
}
|
|
591
|
+
if (compiled.css && !hasDelegatedStyles(compiled)) state.collectedCss.set(filePath, resolveCssImports(compiled.css, filePath, state.cssAliasRules, false));
|
|
592
|
+
else state.collectedCss.delete(filePath);
|
|
593
|
+
}
|
|
594
|
+
function shouldExtractCssForRequest(state, ssr) {
|
|
595
|
+
return state.isProduction && !ssr;
|
|
596
|
+
}
|
|
597
|
+
function clearBuildCaches(state) {
|
|
598
|
+
state.cache.clear();
|
|
599
|
+
state.ssrCache.clear();
|
|
600
|
+
state.collectedCss.clear();
|
|
601
|
+
state.precompileMetadata.clear();
|
|
602
|
+
state.pendingHmrUpdateTypes.clear();
|
|
603
|
+
state.viteResolveCache?.clear();
|
|
604
|
+
}
|
|
605
|
+
//#endregion
|
|
529
606
|
//#region src/compile-options.ts
|
|
530
607
|
function buildCompileFileOptions(filePath, options) {
|
|
531
608
|
return {
|
|
@@ -742,82 +819,272 @@ function compileBatch(files, cache, options) {
|
|
|
742
819
|
}
|
|
743
820
|
return result;
|
|
744
821
|
}
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
"node_modules/**",
|
|
749
|
-
"dist/**",
|
|
750
|
-
".git/**",
|
|
751
|
-
".nuxt/**",
|
|
752
|
-
".output/**",
|
|
753
|
-
".nitro/**",
|
|
754
|
-
"coverage/**"
|
|
755
|
-
];
|
|
756
|
-
function isPrecompileSfcPath(path) {
|
|
757
|
-
return path.endsWith(".vue");
|
|
822
|
+
/** SHA-256 of the exact source text handed to the compiler. */
|
|
823
|
+
function hashPrecompileSource(source) {
|
|
824
|
+
return crypto.createHash("sha256").update(source, "utf8").digest("hex");
|
|
758
825
|
}
|
|
759
|
-
|
|
760
|
-
|
|
826
|
+
/** Key-independent JSON: object key order must not change the hash. */
|
|
827
|
+
function stableStringify(value) {
|
|
828
|
+
if (Array.isArray(value)) return `[${value.map(stableStringify).join(",")}]`;
|
|
829
|
+
if (typeof value === "object" && value !== null) return `{${Object.entries(value).filter(([, item]) => item !== void 0).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([key, item]) => `${JSON.stringify(key)}:${stableStringify(item)}`).join(",")}}`;
|
|
830
|
+
return JSON.stringify(value) ?? "null";
|
|
761
831
|
}
|
|
762
|
-
function
|
|
763
|
-
|
|
832
|
+
function describeBinary(binary) {
|
|
833
|
+
try {
|
|
834
|
+
const stat = fs.statSync(binary);
|
|
835
|
+
return `${path.basename(binary)}:${stat.size}:${stat.mtimeMs}`;
|
|
836
|
+
} catch {
|
|
837
|
+
return `${path.basename(binary)}:unresolved`;
|
|
838
|
+
}
|
|
764
839
|
}
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
840
|
+
/**
|
|
841
|
+
* Identity of the native compiler that produced (or would produce) the output.
|
|
842
|
+
*
|
|
843
|
+
* The package version covers releases; the binary's size and mtime cover local
|
|
844
|
+
* `pnpm --dir npm/native build:debug` rebuilds, which change codegen without
|
|
845
|
+
* changing any version. Hashing the binary itself would be airtight but costs
|
|
846
|
+
* hundreds of milliseconds for a >30 MB artifact, so a rebuild is treated as a
|
|
847
|
+
* new identity — a miss, never a stale hit.
|
|
848
|
+
*/
|
|
849
|
+
function resolveCompilerIdentity() {
|
|
850
|
+
const configured = process.env.NAPI_RS_NATIVE_LIBRARY_PATH;
|
|
851
|
+
try {
|
|
852
|
+
const manifestPath = createRequire(import.meta.url).resolve("@vizejs/native/package.json");
|
|
853
|
+
const packageDir = path.dirname(manifestPath);
|
|
854
|
+
const version = JSON.parse(fs.readFileSync(manifestPath, "utf-8")).version;
|
|
855
|
+
const binaries = configured ? [configured] : fs.readdirSync(packageDir).filter((name) => name.endsWith(".node")).sort().map((name) => path.join(packageDir, name));
|
|
856
|
+
return {
|
|
857
|
+
version: typeof version === "string" ? version : "unknown",
|
|
858
|
+
binaries: binaries.map(describeBinary)
|
|
859
|
+
};
|
|
860
|
+
} catch {
|
|
861
|
+
return {
|
|
862
|
+
version: "unresolved",
|
|
863
|
+
binaries: [configured ?? "unresolved"]
|
|
864
|
+
};
|
|
865
|
+
}
|
|
770
866
|
}
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
867
|
+
/**
|
|
868
|
+
* Hash of everything outside the source text that changes compiled output.
|
|
869
|
+
*
|
|
870
|
+
* `compileOptions` must be the object actually handed to the native batch
|
|
871
|
+
* compiler, so a newly added compile option cannot be forgotten here.
|
|
872
|
+
*/
|
|
873
|
+
function computePrecompileCacheKey(compileOptions) {
|
|
874
|
+
const material = stableStringify({
|
|
875
|
+
format: 1,
|
|
876
|
+
compiler: resolveCompilerIdentity(),
|
|
877
|
+
options: compileOptions
|
|
777
878
|
});
|
|
778
|
-
return
|
|
879
|
+
return crypto.createHash("sha256").update(material, "utf8").digest("hex").slice(0, 32);
|
|
779
880
|
}
|
|
780
881
|
//#endregion
|
|
781
|
-
//#region src/plugin/
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
882
|
+
//#region src/plugin/precompile-cache.ts
|
|
883
|
+
/**
|
|
884
|
+
* Persistent (on-disk) pre-compile cache.
|
|
885
|
+
*
|
|
886
|
+
* `state.precompileMetadata` plus `state.cache` already skip recompilation
|
|
887
|
+
* inside one process, but both are empty on every process start, so `vite
|
|
888
|
+
* build`, CI, and each dev-server start recompile the whole scan from scratch.
|
|
889
|
+
* This module backs them with a manifest under
|
|
890
|
+
* `node_modules/.vize/vite-precompile/` so a cold process can restore the
|
|
891
|
+
* previous run's output.
|
|
892
|
+
*
|
|
893
|
+
* The two invalidation gates -- manifest identity and per-entry source hash --
|
|
894
|
+
* live in `./precompile-cache-key.ts`, which documents why each one is safe.
|
|
895
|
+
* Two more gates live here:
|
|
896
|
+
*
|
|
897
|
+
* - **Shape.** Entries are validated before use and dropped individually if
|
|
898
|
+
* they do not describe a complete `CompiledModule`. The manifest's own
|
|
899
|
+
* `format`/`key` are re-checked after parsing, so a manifest reached by any
|
|
900
|
+
* route other than its key still gets rejected.
|
|
901
|
+
* - **`src` imports.** SFCs that pull blocks in through `<script src>` /
|
|
902
|
+
* `<template src>` / `<style src>` are never persisted: their output depends
|
|
903
|
+
* on files whose content this cache does not hash.
|
|
904
|
+
*
|
|
905
|
+
* A missing, truncated, or corrupt manifest degrades to a full recompile: every
|
|
906
|
+
* read is guarded and any failure yields an empty cache. Writes go through a
|
|
907
|
+
* sibling temp file and a rename, so an interrupted write cannot be read back.
|
|
908
|
+
*
|
|
909
|
+
* Set `VIZE_PRECOMPILE_CACHE=0` to force a full recompile without editing any
|
|
910
|
+
* config.
|
|
911
|
+
*/
|
|
912
|
+
/** Manifest location, relative to the Vite root. */
|
|
913
|
+
const PRECOMPILE_CACHE_DIR = path.join("node_modules", ".vize", "vite-precompile");
|
|
914
|
+
/** Set to `0`/`false` to force a full recompile without editing the config. */
|
|
915
|
+
const PRECOMPILE_CACHE_ENV = "VIZE_PRECOMPILE_CACHE";
|
|
916
|
+
/**
|
|
917
|
+
* Whether `module` may be persisted.
|
|
918
|
+
*
|
|
919
|
+
* Modules assembled from `src` imports depend on sibling files that this cache
|
|
920
|
+
* does not hash, so they are recompiled on every cold start instead.
|
|
921
|
+
*/
|
|
922
|
+
function isPersistablePrecompileModule(module) {
|
|
923
|
+
return !module.dependencies || module.dependencies.length === 0;
|
|
924
|
+
}
|
|
925
|
+
function isCompiledModule(value) {
|
|
926
|
+
if (typeof value !== "object" || value === null) return false;
|
|
927
|
+
const module = value;
|
|
928
|
+
if (typeof module.code !== "string" || typeof module.scopeId !== "string") return false;
|
|
929
|
+
if (typeof module.hasScoped !== "boolean") return false;
|
|
930
|
+
if (module.css !== void 0 && typeof module.css !== "string") return false;
|
|
931
|
+
if (module.styles !== void 0 && !Array.isArray(module.styles)) return false;
|
|
932
|
+
if (module.macroArtifacts !== void 0 && !Array.isArray(module.macroArtifacts)) return false;
|
|
933
|
+
return isPersistablePrecompileModule(module);
|
|
934
|
+
}
|
|
935
|
+
function isCacheEntry(value) {
|
|
936
|
+
if (typeof value !== "object" || value === null) return false;
|
|
937
|
+
const entry = value;
|
|
938
|
+
return typeof entry.hash === "string" && entry.hash.length > 0 && isCompiledModule(entry.module);
|
|
939
|
+
}
|
|
940
|
+
/** Whether the environment forces the cache off. */
|
|
941
|
+
function isPrecompileCacheDisabledByEnv(env = process.env) {
|
|
942
|
+
const value = env[PRECOMPILE_CACHE_ENV];
|
|
943
|
+
return value === "0" || value === "false";
|
|
944
|
+
}
|
|
945
|
+
const disabledCache = {
|
|
946
|
+
file: null,
|
|
947
|
+
get: () => void 0,
|
|
948
|
+
set: () => {},
|
|
949
|
+
delete: () => {},
|
|
950
|
+
retain: () => {},
|
|
951
|
+
flush: () => false
|
|
952
|
+
};
|
|
953
|
+
/** A cache that never hits and never writes. */
|
|
954
|
+
function createDisabledPrecompileCache() {
|
|
955
|
+
return disabledCache;
|
|
956
|
+
}
|
|
957
|
+
function openPrecompileCache(options) {
|
|
958
|
+
const { root, compileOptions, onDiagnostic, env = process.env } = options;
|
|
959
|
+
if (!root || isPrecompileCacheDisabledByEnv(env)) return createDisabledPrecompileCache();
|
|
960
|
+
const key = computePrecompileCacheKey(compileOptions);
|
|
961
|
+
const file = path.join(root, PRECOMPILE_CACHE_DIR, `${key}.json`);
|
|
962
|
+
const entries = readManifestEntries(file, key, onDiagnostic);
|
|
963
|
+
let dirty = false;
|
|
964
|
+
return {
|
|
965
|
+
file,
|
|
966
|
+
get(filePath, sourceHash) {
|
|
967
|
+
const entry = entries.get(filePath);
|
|
968
|
+
return entry && entry.hash === sourceHash ? entry.module : void 0;
|
|
969
|
+
},
|
|
970
|
+
set(filePath, sourceHash, module) {
|
|
971
|
+
if (!isPersistablePrecompileModule(module)) {
|
|
972
|
+
if (entries.delete(filePath)) dirty = true;
|
|
973
|
+
return;
|
|
974
|
+
}
|
|
975
|
+
const existing = entries.get(filePath);
|
|
976
|
+
if (existing?.hash === sourceHash && existing.module === module) return;
|
|
977
|
+
entries.set(filePath, {
|
|
978
|
+
hash: sourceHash,
|
|
979
|
+
module
|
|
980
|
+
});
|
|
981
|
+
dirty = true;
|
|
982
|
+
},
|
|
983
|
+
delete(filePath) {
|
|
984
|
+
if (entries.delete(filePath)) dirty = true;
|
|
985
|
+
},
|
|
986
|
+
retain(files) {
|
|
987
|
+
const keep = files instanceof Set ? files : new Set(files);
|
|
988
|
+
for (const filePath of entries.keys()) if (!keep.has(filePath)) {
|
|
989
|
+
entries.delete(filePath);
|
|
990
|
+
dirty = true;
|
|
991
|
+
}
|
|
992
|
+
},
|
|
993
|
+
flush() {
|
|
994
|
+
if (!dirty) return false;
|
|
995
|
+
if (!writeManifest(file, {
|
|
996
|
+
format: 1,
|
|
997
|
+
key,
|
|
998
|
+
entries: Object.fromEntries(entries)
|
|
999
|
+
}, onDiagnostic)) return false;
|
|
1000
|
+
dirty = false;
|
|
1001
|
+
return true;
|
|
1002
|
+
}
|
|
792
1003
|
};
|
|
793
|
-
if (state.mergedOptions?.mode !== void 0) options.mode = state.mergedOptions.mode;
|
|
794
|
-
if (state.mergedOptions?.runtimeModuleName !== void 0) options.runtimeModuleName = state.mergedOptions.runtimeModuleName;
|
|
795
|
-
if (state.mergedOptions?.runtimeGlobalName !== void 0) options.runtimeGlobalName = state.mergedOptions.runtimeGlobalName;
|
|
796
|
-
if (state.mergedOptions?.vueVersion !== void 0) options.vueVersion = state.mergedOptions.vueVersion;
|
|
797
|
-
if (state.mergedOptions?.experimentalInTagComments) options.experimentalInTagComments = true;
|
|
798
|
-
if (state.mergedOptions?.experimentalPatternedTemplate) options.experimentalPatternedTemplate = true;
|
|
799
|
-
if (state.mergedOptions?.experimentalServerScript) options.experimentalServerScript = true;
|
|
800
|
-
return options;
|
|
801
1004
|
}
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
1005
|
+
/**
|
|
1006
|
+
* Parse the manifest, or return an empty map.
|
|
1007
|
+
*
|
|
1008
|
+
* A missing, truncated, corrupt, or foreign manifest is indistinguishable from
|
|
1009
|
+
* no cache at all, which is exactly the safe outcome: recompile everything.
|
|
1010
|
+
*/
|
|
1011
|
+
function readManifestEntries(file, key, onDiagnostic) {
|
|
1012
|
+
const entries = /* @__PURE__ */ new Map();
|
|
1013
|
+
let raw;
|
|
1014
|
+
try {
|
|
1015
|
+
raw = fs.readFileSync(file, "utf-8");
|
|
1016
|
+
} catch {
|
|
1017
|
+
return entries;
|
|
807
1018
|
}
|
|
808
|
-
|
|
809
|
-
|
|
1019
|
+
let parsed;
|
|
1020
|
+
try {
|
|
1021
|
+
parsed = JSON.parse(raw);
|
|
1022
|
+
} catch (error) {
|
|
1023
|
+
onDiagnostic?.(`Discarding corrupt pre-compile cache ${file}:`, error);
|
|
1024
|
+
return entries;
|
|
1025
|
+
}
|
|
1026
|
+
const manifest = parsed;
|
|
1027
|
+
if (typeof manifest !== "object" || manifest === null || manifest.format !== 1 || manifest.key !== key || typeof manifest.entries !== "object" || manifest.entries === null) {
|
|
1028
|
+
onDiagnostic?.(`Ignoring pre-compile cache ${file}: unrecognized manifest`);
|
|
1029
|
+
return entries;
|
|
1030
|
+
}
|
|
1031
|
+
for (const [filePath, entry] of Object.entries(manifest.entries)) if (isCacheEntry(entry)) entries.set(filePath, entry);
|
|
1032
|
+
return entries;
|
|
810
1033
|
}
|
|
811
|
-
|
|
812
|
-
|
|
1034
|
+
/** Write through a sibling temp file so a crash cannot leave a partial manifest. */
|
|
1035
|
+
function writeManifest(file, manifest, onDiagnostic) {
|
|
1036
|
+
const temp = `${file}.${process.pid}.${crypto.randomBytes(4).toString("hex")}.tmp`;
|
|
1037
|
+
try {
|
|
1038
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
1039
|
+
fs.writeFileSync(temp, JSON.stringify(manifest));
|
|
1040
|
+
fs.renameSync(temp, file);
|
|
1041
|
+
return true;
|
|
1042
|
+
} catch (error) {
|
|
1043
|
+
try {
|
|
1044
|
+
fs.rmSync(temp, { force: true });
|
|
1045
|
+
} catch {}
|
|
1046
|
+
onDiagnostic?.(`Failed to write pre-compile cache ${file}:`, error);
|
|
1047
|
+
return false;
|
|
1048
|
+
}
|
|
813
1049
|
}
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
1050
|
+
//#endregion
|
|
1051
|
+
//#region src/plugin/precompile-run.ts
|
|
1052
|
+
/**
|
|
1053
|
+
* The pre-compilation pass.
|
|
1054
|
+
*
|
|
1055
|
+
* Scans the configured patterns, diffs them against the previous in-process
|
|
1056
|
+
* run, restores whatever the persistent cache can prove is still valid, and
|
|
1057
|
+
* batch-compiles the rest. Extracted from `state.ts` so the state module stays
|
|
1058
|
+
* a state module.
|
|
1059
|
+
*/
|
|
1060
|
+
/**
|
|
1061
|
+
* The options the pre-compile batch actually compiles with.
|
|
1062
|
+
*
|
|
1063
|
+
* Also the input to the cache key, so the two can never drift: a new option
|
|
1064
|
+
* that reaches the native compiler reaches the key with it.
|
|
1065
|
+
*/
|
|
1066
|
+
function resolvePrecompileBatchOptions(state) {
|
|
1067
|
+
return {
|
|
1068
|
+
ssr: false,
|
|
1069
|
+
vapor: state.mergedOptions.vapor ?? false,
|
|
1070
|
+
mode: state.mergedOptions.mode,
|
|
1071
|
+
customRenderer: state.mergedOptions.customRenderer ?? false,
|
|
1072
|
+
templateSyntax: state.mergedOptions.templateSyntax ?? "standard",
|
|
1073
|
+
experimentalInTagComments: state.mergedOptions.experimentalInTagComments ?? false,
|
|
1074
|
+
experimentalPatternedTemplate: state.mergedOptions.experimentalPatternedTemplate ?? false,
|
|
1075
|
+
experimentalServerScript: state.mergedOptions.experimentalServerScript ?? false,
|
|
1076
|
+
runtimeModuleName: state.mergedOptions.runtimeModuleName,
|
|
1077
|
+
runtimeGlobalName: state.mergedOptions.runtimeGlobalName,
|
|
1078
|
+
vueVersion: state.mergedOptions.vueVersion
|
|
1079
|
+
};
|
|
1080
|
+
}
|
|
1081
|
+
function openCacheForRun(state, batchOptions) {
|
|
1082
|
+
if (!state.root) return createDisabledPrecompileCache();
|
|
1083
|
+
return openPrecompileCache({
|
|
1084
|
+
root: state.root,
|
|
1085
|
+
compileOptions: buildCompileBatchOptions(batchOptions),
|
|
1086
|
+
onDiagnostic: (message, error) => error === void 0 ? state.logger.warn(message) : state.logger.warn(message, error)
|
|
1087
|
+
});
|
|
821
1088
|
}
|
|
822
1089
|
/**
|
|
823
1090
|
* Pre-compile all Vue files matching scan patterns.
|
|
@@ -858,41 +1125,50 @@ async function compileAll(state) {
|
|
|
858
1125
|
if (state.extractCss) state.collectedCss.delete(file);
|
|
859
1126
|
state.pendingHmrUpdateTypes.delete(file);
|
|
860
1127
|
}
|
|
1128
|
+
const batchOptions = resolvePrecompileBatchOptions(state);
|
|
1129
|
+
const cache = openCacheForRun(state, batchOptions);
|
|
1130
|
+
const cacheEnabled = cache.file !== null;
|
|
861
1131
|
let successCount = 0;
|
|
1132
|
+
let restoredCount = 0;
|
|
862
1133
|
let failedCount = 0;
|
|
863
1134
|
let nativeTimeMs = 0;
|
|
864
1135
|
const precompileFailures = [];
|
|
865
1136
|
const chunks = chunkPrecompileFiles(changedFiles, state.precompileBatchSize, { metadata: currentMetadata });
|
|
866
1137
|
for (const chunk of chunks) {
|
|
867
1138
|
const fileContents = [];
|
|
868
|
-
|
|
869
|
-
|
|
1139
|
+
const sourceHashes = /* @__PURE__ */ new Map();
|
|
1140
|
+
for (const file of chunk) {
|
|
1141
|
+
let source;
|
|
1142
|
+
try {
|
|
1143
|
+
source = fs.readFileSync(file, "utf-8");
|
|
1144
|
+
} catch (e) {
|
|
1145
|
+
failedCount++;
|
|
1146
|
+
state.cache.delete(file);
|
|
1147
|
+
if (state.extractCss) state.collectedCss.delete(file);
|
|
1148
|
+
state.precompileMetadata.delete(file);
|
|
1149
|
+
cache.delete(file);
|
|
1150
|
+
precompileFailures.push(`[vize] Failed to read ${file}: ${formatUnknownError$2(e)}`);
|
|
1151
|
+
state.logger.error(`Failed to read ${file}:`, e);
|
|
1152
|
+
continue;
|
|
1153
|
+
}
|
|
1154
|
+
const sourceHash = cacheEnabled ? hashPrecompileSource(source) : void 0;
|
|
1155
|
+
const restored = sourceHash === void 0 ? void 0 : cache.get(file, sourceHash);
|
|
1156
|
+
if (restored) {
|
|
1157
|
+
state.cache.set(file, restored);
|
|
1158
|
+
const metadata = currentMetadata.get(file);
|
|
1159
|
+
if (metadata) state.precompileMetadata.set(file, metadata);
|
|
1160
|
+
syncCollectedCssForFile(state, file, restored);
|
|
1161
|
+
restoredCount++;
|
|
1162
|
+
continue;
|
|
1163
|
+
}
|
|
1164
|
+
if (sourceHash !== void 0) sourceHashes.set(file, sourceHash);
|
|
870
1165
|
fileContents.push({
|
|
871
1166
|
path: file,
|
|
872
1167
|
source
|
|
873
1168
|
});
|
|
874
|
-
} catch (e) {
|
|
875
|
-
failedCount++;
|
|
876
|
-
state.cache.delete(file);
|
|
877
|
-
if (state.extractCss) state.collectedCss.delete(file);
|
|
878
|
-
state.precompileMetadata.delete(file);
|
|
879
|
-
precompileFailures.push(`[vize] Failed to read ${file}: ${formatUnknownError$2(e)}`);
|
|
880
|
-
state.logger.error(`Failed to read ${file}:`, e);
|
|
881
1169
|
}
|
|
882
1170
|
if (fileContents.length === 0) continue;
|
|
883
|
-
const result = compileBatch(fileContents, state.cache,
|
|
884
|
-
ssr: false,
|
|
885
|
-
vapor: state.mergedOptions.vapor ?? false,
|
|
886
|
-
mode: state.mergedOptions.mode,
|
|
887
|
-
customRenderer: state.mergedOptions.customRenderer ?? false,
|
|
888
|
-
templateSyntax: state.mergedOptions.templateSyntax ?? "standard",
|
|
889
|
-
experimentalInTagComments: state.mergedOptions.experimentalInTagComments ?? false,
|
|
890
|
-
experimentalPatternedTemplate: state.mergedOptions.experimentalPatternedTemplate ?? false,
|
|
891
|
-
experimentalServerScript: state.mergedOptions.experimentalServerScript ?? false,
|
|
892
|
-
runtimeModuleName: state.mergedOptions.runtimeModuleName,
|
|
893
|
-
runtimeGlobalName: state.mergedOptions.runtimeGlobalName,
|
|
894
|
-
vueVersion: state.mergedOptions.vueVersion
|
|
895
|
-
});
|
|
1171
|
+
const result = compileBatch(fileContents, state.cache, batchOptions);
|
|
896
1172
|
const chunkFailedCount = result.results.filter((fileResult) => fileResult.errors.length > 0).length;
|
|
897
1173
|
failedCount += chunkFailedCount;
|
|
898
1174
|
successCount += result.results.length - chunkFailedCount;
|
|
@@ -903,16 +1179,22 @@ async function compileAll(state) {
|
|
|
903
1179
|
state.cache.delete(fileResult.path);
|
|
904
1180
|
if (state.extractCss) state.collectedCss.delete(fileResult.path);
|
|
905
1181
|
state.precompileMetadata.delete(fileResult.path);
|
|
1182
|
+
cache.delete(fileResult.path);
|
|
906
1183
|
precompileFailures.push(formatCompileErrorMessage(fileResult.path, fileResult.errors));
|
|
907
1184
|
continue;
|
|
908
1185
|
}
|
|
909
1186
|
if (metadata) state.precompileMetadata.set(fileResult.path, metadata);
|
|
910
|
-
|
|
1187
|
+
const compiled = state.cache.get(fileResult.path);
|
|
1188
|
+
const sourceHash = sourceHashes.get(fileResult.path);
|
|
1189
|
+
if (compiled && sourceHash !== void 0) cache.set(fileResult.path, sourceHash, compiled);
|
|
1190
|
+
syncCollectedCssForFile(state, fileResult.path, compiled);
|
|
911
1191
|
}
|
|
912
1192
|
}
|
|
1193
|
+
cache.retain(new Set(sfcFiles));
|
|
1194
|
+
cache.flush();
|
|
913
1195
|
const elapsed = (performance.now() - startTime).toFixed(2);
|
|
914
1196
|
const batchLabel = chunks.length === 1 ? "batch" : "batches";
|
|
915
|
-
state.logger.info(`Pre-compilation complete: ${successCount} recompiled, ${cachedFileCount} reused, ${failedCount} failed (${elapsed}ms, native ${batchLabel}: ${nativeTimeMs.toFixed(2)}ms)`);
|
|
1197
|
+
state.logger.info(`Pre-compilation complete: ${successCount} recompiled, ${restoredCount} restored from disk, ${cachedFileCount} reused, ${failedCount} failed (${elapsed}ms, native ${batchLabel}: ${nativeTimeMs.toFixed(2)}ms)`);
|
|
916
1198
|
if (failedCount > 0) {
|
|
917
1199
|
const details = precompileFailures.length > 0 ? `\n\n${precompileFailures.join("\n\n")}` : "";
|
|
918
1200
|
throw new Error(`[vize] Pre-compilation failed for ${failedCount} file(s).${details}`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vizejs/vite-plugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.303.0",
|
|
4
4
|
"description": "High-performance native Vite plugin for Vue SFC compilation powered by Vize",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"compiler",
|
|
@@ -45,10 +45,10 @@
|
|
|
45
45
|
"access": "public"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@vizejs/native": "0.
|
|
48
|
+
"@vizejs/native": "0.303.0",
|
|
49
49
|
"oxc-parser": "0.133.0",
|
|
50
50
|
"tinyglobby": "0.2.16",
|
|
51
|
-
"vize": "0.
|
|
51
|
+
"vize": "0.303.0"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"@types/node": "25.9.2",
|