@vizejs/vite-plugin 0.0.1-alpha.101 → 0.0.1-alpha.103
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.d.ts +25 -2
- package/dist/index.js +415 -77
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -459,6 +459,14 @@ interface VizeOptions {
|
|
|
459
459
|
* Custom config file path (overrides automatic search)
|
|
460
460
|
*/
|
|
461
461
|
configFile?: string;
|
|
462
|
+
/**
|
|
463
|
+
* Handle .vue files in node_modules (on-demand compilation).
|
|
464
|
+
* When true, vize will compile .vue files from node_modules that other plugins
|
|
465
|
+
* (like vite-plugin-vue-inspector) may import directly.
|
|
466
|
+
* Set to false if another Vue plugin (e.g. Nuxt) handles node_modules .vue files.
|
|
467
|
+
* @default true
|
|
468
|
+
*/
|
|
469
|
+
handleNodeModulesVue?: boolean;
|
|
462
470
|
/**
|
|
463
471
|
* Enable debug logging
|
|
464
472
|
* @default false
|
|
@@ -492,7 +500,22 @@ declare function loadConfig(root: string, options?: LoadConfigOptions): Promise<
|
|
|
492
500
|
* Used by musea() and other plugins to access the unified config.
|
|
493
501
|
*/
|
|
494
502
|
declare const vizeConfigStore: Map<string, VizeConfig>;
|
|
495
|
-
|
|
503
|
+
interface DynamicImportAliasRule {
|
|
504
|
+
fromPrefix: string;
|
|
505
|
+
toPrefix: string;
|
|
506
|
+
}
|
|
507
|
+
/**
|
|
508
|
+
* Rewrite static asset URLs in compiled template output.
|
|
509
|
+
*
|
|
510
|
+
* Transforms property values like `src: "@/assets/logo.svg"` into import
|
|
511
|
+
* statements hoisted to the top of the module, so Vite's module resolution
|
|
512
|
+
* pipeline handles alias expansion and asset hashing in both dev and build.
|
|
513
|
+
*/
|
|
514
|
+
declare function rewriteStaticAssetUrls(code: string, aliasRules: DynamicImportAliasRule[]): string;
|
|
515
|
+
declare const __internal: {
|
|
516
|
+
rewriteStaticAssetUrls: typeof rewriteStaticAssetUrls;
|
|
517
|
+
};
|
|
518
|
+
declare function vize(options?: VizeOptions): Plugin[];
|
|
496
519
|
|
|
497
520
|
//#endregion
|
|
498
|
-
export { CompiledModule, LoadConfigOptions, VizeConfig, VizeOptions, vize as default, defineConfig, loadConfig, vize, vizeConfigStore };
|
|
521
|
+
export { CompiledModule, LoadConfigOptions, VizeConfig, VizeOptions, __internal, vize as default, defineConfig, loadConfig, vize, vizeConfigStore };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { transformWithOxc } from "vite";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import fs from "node:fs";
|
|
4
|
+
import { createRequire } from "node:module";
|
|
5
|
+
import { pathToFileURL } from "node:url";
|
|
4
6
|
import { glob } from "tinyglobby";
|
|
5
7
|
import * as native from "@vizejs/native";
|
|
6
8
|
import { createHash } from "node:crypto";
|
|
@@ -116,6 +118,69 @@ ${output}`;
|
|
|
116
118
|
if (!isProduction && isDev && hasExportDefault) output += generateHmrCode(compiled.scopeId, hmrUpdateType ?? "full-reload");
|
|
117
119
|
return output;
|
|
118
120
|
}
|
|
121
|
+
/**
|
|
122
|
+
* Resolve CSS @import statements by inlining the imported files,
|
|
123
|
+
* then resolve @custom-media definitions within the combined CSS.
|
|
124
|
+
*
|
|
125
|
+
* This is necessary because Vize embeds CSS as a JS string via
|
|
126
|
+
* document.createElement('style'), bypassing Vite's CSS pipeline.
|
|
127
|
+
*/
|
|
128
|
+
function resolveCssImports(css, importer, aliasRules, isDev, devUrlBase) {
|
|
129
|
+
const customMedia = new Map();
|
|
130
|
+
const importRegex = /^@import\s+(?:"([^"]+)"|'([^']+)');?\s*$/gm;
|
|
131
|
+
let result = css;
|
|
132
|
+
result = result.replace(importRegex, (_match, dqPath, sqPath) => {
|
|
133
|
+
const importPath = dqPath || sqPath;
|
|
134
|
+
if (!importPath) return _match;
|
|
135
|
+
const resolved = resolveCssPath(importPath, importer, aliasRules);
|
|
136
|
+
if (!resolved || !fs.existsSync(resolved)) return _match;
|
|
137
|
+
try {
|
|
138
|
+
const content = fs.readFileSync(resolved, "utf-8");
|
|
139
|
+
parseCustomMedia(content, customMedia);
|
|
140
|
+
return content;
|
|
141
|
+
} catch {
|
|
142
|
+
return _match;
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
parseCustomMedia(result, customMedia);
|
|
146
|
+
result = result.replace(/^@custom-media\s+[^;]+;\s*$/gm, "");
|
|
147
|
+
if (customMedia.size > 0) for (const [name, query] of customMedia) {
|
|
148
|
+
const escaped = name.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
|
|
149
|
+
result = result.replace(new RegExp(`\\(${escaped}\\)`, "g"), query);
|
|
150
|
+
}
|
|
151
|
+
if (isDev) result = result.replace(/url\(\s*(["']?)([^"')]+)\1\s*\)/g, (_match, quote, urlPath) => {
|
|
152
|
+
const trimmed = urlPath.trim();
|
|
153
|
+
if (trimmed.startsWith("data:") || trimmed.startsWith("http://") || trimmed.startsWith("https://") || trimmed.startsWith("/@fs/")) return _match;
|
|
154
|
+
const resolved = resolveCssPath(trimmed, importer, aliasRules);
|
|
155
|
+
if (resolved && fs.existsSync(resolved)) {
|
|
156
|
+
const normalized = resolved.replace(/\\/g, "/");
|
|
157
|
+
const base = devUrlBase ?? "/";
|
|
158
|
+
const prefix = base.endsWith("/") ? base : base + "/";
|
|
159
|
+
return `url("${prefix}@fs${normalized}")`;
|
|
160
|
+
}
|
|
161
|
+
return _match;
|
|
162
|
+
});
|
|
163
|
+
result = result.replace(/:deep\(([^()]*(?:\([^()]*\))*[^()]*)\)/g, "$1");
|
|
164
|
+
result = result.replace(/\n{3,}/g, "\n\n");
|
|
165
|
+
return result;
|
|
166
|
+
}
|
|
167
|
+
function parseCustomMedia(css, map) {
|
|
168
|
+
const re = /@custom-media\s+(--[\w-]+)\s+(.+?)\s*;/g;
|
|
169
|
+
let m;
|
|
170
|
+
while ((m = re.exec(css)) !== null) map.set(m[1], m[2]);
|
|
171
|
+
}
|
|
172
|
+
function resolveCssPath(importPath, importer, aliasRules) {
|
|
173
|
+
for (const rule of aliasRules) if (importPath.startsWith(rule.find)) {
|
|
174
|
+
const resolved = importPath.replace(rule.find, rule.replacement);
|
|
175
|
+
return path.resolve(resolved);
|
|
176
|
+
}
|
|
177
|
+
if (importPath.startsWith(".")) {
|
|
178
|
+
const dir = path.dirname(importer);
|
|
179
|
+
return path.resolve(dir, importPath);
|
|
180
|
+
}
|
|
181
|
+
if (path.isAbsolute(importPath)) return importPath;
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
119
184
|
|
|
120
185
|
//#endregion
|
|
121
186
|
//#region src/compiler.ts
|
|
@@ -250,9 +315,69 @@ async function loadConfigFile(configPath, env) {
|
|
|
250
315
|
* Used by musea() and other plugins to access the unified config.
|
|
251
316
|
*/
|
|
252
317
|
const vizeConfigStore = new Map();
|
|
253
|
-
const
|
|
318
|
+
const LEGACY_VIZE_PREFIX = "\0vize:";
|
|
254
319
|
const VIRTUAL_CSS_MODULE = "virtual:vize-styles";
|
|
255
320
|
const RESOLVED_CSS_MODULE = "\0vize:all-styles.css";
|
|
321
|
+
/** Check if a module ID is a vize-compiled virtual module */
|
|
322
|
+
function isVizeVirtual(id) {
|
|
323
|
+
return id.startsWith("\0") && id.endsWith(".vue.ts");
|
|
324
|
+
}
|
|
325
|
+
/** Create a virtual module ID from a real .vue file path */
|
|
326
|
+
function toVirtualId(realPath) {
|
|
327
|
+
return "\0" + realPath + ".ts";
|
|
328
|
+
}
|
|
329
|
+
/** Extract the real .vue file path from a virtual module ID */
|
|
330
|
+
function fromVirtualId(virtualId) {
|
|
331
|
+
return virtualId.slice(1, -3);
|
|
332
|
+
}
|
|
333
|
+
function escapeRegExp(value) {
|
|
334
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
335
|
+
}
|
|
336
|
+
function toBrowserImportPrefix(replacement) {
|
|
337
|
+
const normalized = replacement.replace(/\\/g, "/");
|
|
338
|
+
if (normalized.startsWith("/@fs/")) return normalized;
|
|
339
|
+
if (path.isAbsolute(replacement) && fs.existsSync(replacement)) return `/@fs${normalized}`;
|
|
340
|
+
return normalized;
|
|
341
|
+
}
|
|
342
|
+
function normalizeFsIdForBuild(id) {
|
|
343
|
+
const [pathPart, queryPart] = id.split("?");
|
|
344
|
+
if (!pathPart.startsWith("/@fs/")) return id;
|
|
345
|
+
const normalizedPath = pathPart.slice(4);
|
|
346
|
+
return queryPart ? `${normalizedPath}?${queryPart}` : normalizedPath;
|
|
347
|
+
}
|
|
348
|
+
function rewriteDynamicTemplateImports(code, aliasRules) {
|
|
349
|
+
let rewritten = code;
|
|
350
|
+
for (const rule of aliasRules) {
|
|
351
|
+
const pattern = new RegExp(`\\bimport\\s*\\(\\s*\`${escapeRegExp(rule.fromPrefix)}`, "g");
|
|
352
|
+
rewritten = rewritten.replace(pattern, `import(/* @vite-ignore */ \`${rule.toPrefix}`);
|
|
353
|
+
}
|
|
354
|
+
rewritten = rewritten.replace(/\bimport\s*\(\s*`/g, "import(/* @vite-ignore */ `");
|
|
355
|
+
return rewritten;
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Rewrite static asset URLs in compiled template output.
|
|
359
|
+
*
|
|
360
|
+
* Transforms property values like `src: "@/assets/logo.svg"` into import
|
|
361
|
+
* statements hoisted to the top of the module, so Vite's module resolution
|
|
362
|
+
* pipeline handles alias expansion and asset hashing in both dev and build.
|
|
363
|
+
*/
|
|
364
|
+
function rewriteStaticAssetUrls(code, aliasRules) {
|
|
365
|
+
let rewritten = code;
|
|
366
|
+
const imports = [];
|
|
367
|
+
let counter = 0;
|
|
368
|
+
for (const rule of aliasRules) {
|
|
369
|
+
const pattern = new RegExp(`("?src"?\\s*:\\s*)(?:"(${escapeRegExp(rule.fromPrefix)}[^"]+)"|'(${escapeRegExp(rule.fromPrefix)}[^']+)')`, "g");
|
|
370
|
+
rewritten = rewritten.replace(pattern, (_match, prefix, dqPath, sqPath) => {
|
|
371
|
+
const fullPath = dqPath || sqPath;
|
|
372
|
+
const varName = `__vize_static_${counter++}`;
|
|
373
|
+
imports.push(`import ${varName} from ${JSON.stringify(fullPath)};`);
|
|
374
|
+
return `${prefix}${varName}`;
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
if (imports.length > 0) rewritten = imports.join("\n") + "\n" + rewritten;
|
|
378
|
+
return rewritten;
|
|
379
|
+
}
|
|
380
|
+
const __internal = { rewriteStaticAssetUrls };
|
|
256
381
|
function createLogger(debug) {
|
|
257
382
|
return {
|
|
258
383
|
log: (...args) => debug && console.log("[vize]", ...args),
|
|
@@ -261,18 +386,61 @@ function createLogger(debug) {
|
|
|
261
386
|
error: (...args) => console.error("[vize]", ...args)
|
|
262
387
|
};
|
|
263
388
|
}
|
|
389
|
+
/**
|
|
390
|
+
* Built-in Vite/Vue/Nuxt define keys that are handled by Vite's own transform pipeline.
|
|
391
|
+
* These must NOT be replaced by the vize plugin because:
|
|
392
|
+
* 1. Nuxt runs both client and server Vite builds, each with different values
|
|
393
|
+
* (e.g., import.meta.server = true on server, false on client).
|
|
394
|
+
* 2. Vite's import.meta transform already handles these correctly per-environment.
|
|
395
|
+
*/
|
|
396
|
+
const BUILTIN_DEFINE_PREFIXES = [
|
|
397
|
+
"import.meta.server",
|
|
398
|
+
"import.meta.client",
|
|
399
|
+
"import.meta.dev",
|
|
400
|
+
"import.meta.test",
|
|
401
|
+
"import.meta.prerender",
|
|
402
|
+
"import.meta.env",
|
|
403
|
+
"import.meta.hot",
|
|
404
|
+
"__VUE_",
|
|
405
|
+
"__NUXT_",
|
|
406
|
+
"process.env"
|
|
407
|
+
];
|
|
408
|
+
function isBuiltinDefine(key) {
|
|
409
|
+
return BUILTIN_DEFINE_PREFIXES.some((prefix) => key === prefix || key.startsWith(prefix + ".") || key.startsWith(prefix + "_"));
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Apply Vite define replacements to code.
|
|
413
|
+
* Replaces keys like `import.meta.vfFeatures.photoSection` with their values.
|
|
414
|
+
* Uses word-boundary-aware matching to avoid replacing inside strings or partial matches.
|
|
415
|
+
*/
|
|
416
|
+
function applyDefineReplacements(code, defines) {
|
|
417
|
+
const sortedKeys = Object.keys(defines).sort((a, b) => b.length - a.length);
|
|
418
|
+
let result = code;
|
|
419
|
+
for (const key of sortedKeys) {
|
|
420
|
+
if (!result.includes(key)) continue;
|
|
421
|
+
const escaped = key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
422
|
+
const re = new RegExp(escaped + "(?![\\w$.])", "g");
|
|
423
|
+
result = result.replace(re, defines[key]);
|
|
424
|
+
}
|
|
425
|
+
return result;
|
|
426
|
+
}
|
|
264
427
|
function vize(options = {}) {
|
|
265
428
|
const cache = new Map();
|
|
266
|
-
const virtualToReal = new Map();
|
|
267
429
|
const collectedCss = new Map();
|
|
268
430
|
let isProduction;
|
|
269
431
|
let root;
|
|
432
|
+
let clientViteBase = "/";
|
|
433
|
+
let serverViteBase = "/";
|
|
270
434
|
let server = null;
|
|
271
435
|
let filter;
|
|
272
436
|
let scanPatterns;
|
|
273
437
|
let ignorePatterns;
|
|
274
438
|
let mergedOptions;
|
|
439
|
+
let dynamicImportAliasRules = [];
|
|
440
|
+
let cssAliasRules = [];
|
|
275
441
|
let extractCss = false;
|
|
442
|
+
let clientViteDefine = {};
|
|
443
|
+
let serverViteDefine = {};
|
|
276
444
|
const logger = createLogger(options.debug ?? false);
|
|
277
445
|
async function compileAll() {
|
|
278
446
|
const startTime = performance.now();
|
|
@@ -294,7 +462,7 @@ function vize(options = {}) {
|
|
|
294
462
|
}
|
|
295
463
|
const result = compileBatch(fileContents, cache, { ssr: mergedOptions.ssr ?? false });
|
|
296
464
|
if (isProduction) {
|
|
297
|
-
for (const fileResult of result.results) if (fileResult.css) collectedCss.set(fileResult.path, fileResult.css);
|
|
465
|
+
for (const fileResult of result.results) if (fileResult.css) collectedCss.set(fileResult.path, resolveCssImports(fileResult.css, fileResult.path, cssAliasRules, false));
|
|
298
466
|
}
|
|
299
467
|
const elapsed = (performance.now() - startTime).toFixed(2);
|
|
300
468
|
logger.info(`Pre-compilation complete: ${result.successCount} succeeded, ${result.failedCount} failed (${elapsed}ms, native batch: ${result.timeMs.toFixed(2)}ms)`);
|
|
@@ -305,36 +473,45 @@ function vize(options = {}) {
|
|
|
305
473
|
else if (id.startsWith("/") && !fs.existsSync(id)) resolved = path.resolve(root, id.slice(1));
|
|
306
474
|
else if (path.isAbsolute(id)) resolved = id;
|
|
307
475
|
else if (importer) {
|
|
308
|
-
|
|
309
|
-
if (realImporter.endsWith(".vue.ts")) realImporter = realImporter.slice(0, -3);
|
|
476
|
+
const realImporter = isVizeVirtual(importer) ? fromVirtualId(importer) : importer;
|
|
310
477
|
resolved = path.resolve(path.dirname(realImporter), id);
|
|
311
478
|
} else resolved = path.resolve(root, id);
|
|
312
479
|
if (!path.isAbsolute(resolved)) resolved = path.resolve(root, resolved);
|
|
313
480
|
return path.normalize(resolved);
|
|
314
481
|
}
|
|
315
|
-
|
|
482
|
+
const mainPlugin = {
|
|
316
483
|
name: "vite-plugin-vize",
|
|
317
484
|
enforce: "pre",
|
|
318
|
-
config() {
|
|
319
|
-
return {
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
rolldownOptions: { external: [/\.vue$/] }
|
|
332
|
-
} };
|
|
485
|
+
config(_, env) {
|
|
486
|
+
return {
|
|
487
|
+
define: {
|
|
488
|
+
__VUE_OPTIONS_API__: true,
|
|
489
|
+
__VUE_PROD_DEVTOOLS__: env.command === "serve",
|
|
490
|
+
__VUE_PROD_HYDRATION_MISMATCH_DETAILS__: false
|
|
491
|
+
},
|
|
492
|
+
optimizeDeps: {
|
|
493
|
+
include: ["vue"],
|
|
494
|
+
exclude: ["virtual:vize-styles"],
|
|
495
|
+
rolldownOptions: { external: [/\.vue$/] }
|
|
496
|
+
}
|
|
497
|
+
};
|
|
333
498
|
},
|
|
334
499
|
async configResolved(resolvedConfig) {
|
|
335
500
|
root = options.root ?? resolvedConfig.root;
|
|
336
501
|
isProduction = options.isProduction ?? resolvedConfig.isProduction;
|
|
502
|
+
const isSsrBuild = !!resolvedConfig.build?.ssr;
|
|
503
|
+
if (isSsrBuild) serverViteBase = resolvedConfig.base ?? "/";
|
|
504
|
+
else clientViteBase = resolvedConfig.base ?? "/";
|
|
337
505
|
extractCss = isProduction;
|
|
506
|
+
const isSsr = !!resolvedConfig.build?.ssr;
|
|
507
|
+
const envDefine = {};
|
|
508
|
+
if (resolvedConfig.define) for (const [key, value] of Object.entries(resolvedConfig.define)) {
|
|
509
|
+
if (isBuiltinDefine(key)) continue;
|
|
510
|
+
if (typeof value === "string") envDefine[key] = value;
|
|
511
|
+
else envDefine[key] = JSON.stringify(value);
|
|
512
|
+
}
|
|
513
|
+
if (isSsr) serverViteDefine = envDefine;
|
|
514
|
+
else clientViteDefine = envDefine;
|
|
338
515
|
const configEnv = {
|
|
339
516
|
mode: resolvedConfig.mode,
|
|
340
517
|
command: resolvedConfig.command === "build" ? "build" : "serve",
|
|
@@ -364,6 +541,27 @@ function vize(options = {}) {
|
|
|
364
541
|
scanPatterns: options.scanPatterns ?? viteConfig.scanPatterns,
|
|
365
542
|
ignorePatterns: options.ignorePatterns ?? viteConfig.ignorePatterns
|
|
366
543
|
};
|
|
544
|
+
dynamicImportAliasRules = [];
|
|
545
|
+
for (const alias of resolvedConfig.resolve.alias) {
|
|
546
|
+
if (typeof alias.find !== "string" || typeof alias.replacement !== "string") continue;
|
|
547
|
+
const fromPrefix = alias.find.endsWith("/") ? alias.find : `${alias.find}/`;
|
|
548
|
+
const replacement = toBrowserImportPrefix(alias.replacement);
|
|
549
|
+
const toPrefix = replacement.endsWith("/") ? replacement : `${replacement}/`;
|
|
550
|
+
dynamicImportAliasRules.push({
|
|
551
|
+
fromPrefix,
|
|
552
|
+
toPrefix
|
|
553
|
+
});
|
|
554
|
+
}
|
|
555
|
+
dynamicImportAliasRules.sort((a, b) => b.fromPrefix.length - a.fromPrefix.length);
|
|
556
|
+
cssAliasRules = [];
|
|
557
|
+
for (const alias of resolvedConfig.resolve.alias) {
|
|
558
|
+
if (typeof alias.find !== "string" || typeof alias.replacement !== "string") continue;
|
|
559
|
+
cssAliasRules.push({
|
|
560
|
+
find: alias.find,
|
|
561
|
+
replacement: alias.replacement
|
|
562
|
+
});
|
|
563
|
+
}
|
|
564
|
+
cssAliasRules.sort((a, b) => b.find.length - a.find.length);
|
|
367
565
|
filter = createFilter(mergedOptions.include, mergedOptions.exclude);
|
|
368
566
|
scanPatterns = mergedOptions.scanPatterns ?? ["**/*.vue"];
|
|
369
567
|
ignorePatterns = mergedOptions.ignorePatterns ?? [
|
|
@@ -374,120 +572,235 @@ function vize(options = {}) {
|
|
|
374
572
|
},
|
|
375
573
|
configureServer(devServer) {
|
|
376
574
|
server = devServer;
|
|
575
|
+
devServer.middlewares.use((req, _res, next) => {
|
|
576
|
+
if (req.url && req.url.includes("__x00__")) {
|
|
577
|
+
const [urlPath, queryPart] = req.url.split("?");
|
|
578
|
+
let cleanedPath = urlPath.replace(/__x00__/g, "");
|
|
579
|
+
cleanedPath = cleanedPath.replace(/^\/@id\/\//, "/@fs/");
|
|
580
|
+
if (cleanedPath.startsWith("/@fs/")) {
|
|
581
|
+
const fsPath = cleanedPath.slice(4);
|
|
582
|
+
if (fsPath.startsWith("/") && fs.existsSync(fsPath) && fs.statSync(fsPath).isFile() && !fsPath.endsWith(".vue.ts")) {
|
|
583
|
+
const cleaned = queryPart ? `${cleanedPath}?${queryPart}` : cleanedPath;
|
|
584
|
+
if (cleaned !== req.url) {
|
|
585
|
+
logger.log(`middleware: rewriting ${req.url} → ${cleaned}`);
|
|
586
|
+
req.url = cleaned;
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
next();
|
|
592
|
+
});
|
|
377
593
|
},
|
|
378
594
|
async buildStart() {
|
|
379
595
|
await compileAll();
|
|
380
596
|
logger.log("Cache keys:", [...cache.keys()].slice(0, 3));
|
|
381
597
|
},
|
|
382
598
|
async resolveId(id, importer) {
|
|
383
|
-
|
|
599
|
+
const isBuild = server === null;
|
|
600
|
+
if (id.startsWith("\0")) {
|
|
601
|
+
if (isVizeVirtual(id)) return null;
|
|
602
|
+
if (id.startsWith(LEGACY_VIZE_PREFIX)) {
|
|
603
|
+
const rawPath = id.slice(LEGACY_VIZE_PREFIX.length);
|
|
604
|
+
const cleanPath$1 = rawPath.endsWith(".ts") ? rawPath.slice(0, -3) : rawPath;
|
|
605
|
+
if (!cleanPath$1.endsWith(".vue")) {
|
|
606
|
+
logger.log(`resolveId: redirecting legacy virtual ID to ${cleanPath$1}`);
|
|
607
|
+
return cleanPath$1;
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
const cleanPath = id.slice(1);
|
|
611
|
+
if (cleanPath.startsWith("/") && !cleanPath.endsWith(".vue.ts")) {
|
|
612
|
+
const [pathPart, queryPart] = cleanPath.split("?");
|
|
613
|
+
const querySuffix = queryPart ? `?${queryPart}` : "";
|
|
614
|
+
logger.log(`resolveId: redirecting \0-prefixed non-vue ID to ${pathPart}${querySuffix}`);
|
|
615
|
+
const redirected = pathPart + querySuffix;
|
|
616
|
+
return isBuild ? normalizeFsIdForBuild(redirected) : redirected;
|
|
617
|
+
}
|
|
618
|
+
return null;
|
|
619
|
+
}
|
|
384
620
|
if (id.startsWith("vize:")) {
|
|
385
621
|
let realPath = id.slice(5);
|
|
386
622
|
if (realPath.endsWith(".ts")) realPath = realPath.slice(0, -3);
|
|
387
623
|
logger.log(`resolveId: redirecting stale vize: ID to ${realPath}`);
|
|
388
|
-
|
|
389
|
-
|
|
624
|
+
const resolved = await this.resolve(realPath, importer, { skipSelf: true });
|
|
625
|
+
if (resolved && isBuild && resolved.id.startsWith("/@fs/")) return {
|
|
626
|
+
...resolved,
|
|
627
|
+
id: normalizeFsIdForBuild(resolved.id)
|
|
628
|
+
};
|
|
629
|
+
return resolved;
|
|
390
630
|
}
|
|
391
631
|
if (id === VIRTUAL_CSS_MODULE) return RESOLVED_CSS_MODULE;
|
|
632
|
+
if (isBuild && id.startsWith("/@fs/")) return normalizeFsIdForBuild(id);
|
|
392
633
|
if (id.includes("?vue&type=style")) return id;
|
|
393
|
-
if (importer
|
|
394
|
-
const
|
|
395
|
-
const cleanImporter = realImporter.endsWith(".ts") ? realImporter.slice(0, -3) : realImporter;
|
|
634
|
+
if (importer && isVizeVirtual(importer)) {
|
|
635
|
+
const cleanImporter = fromVirtualId(importer);
|
|
396
636
|
logger.log(`resolveId from virtual: id=${id}, cleanImporter=${cleanImporter}`);
|
|
397
637
|
if (id.startsWith("#")) try {
|
|
398
638
|
return await this.resolve(id, cleanImporter, { skipSelf: true });
|
|
399
639
|
} catch {
|
|
400
640
|
return null;
|
|
401
641
|
}
|
|
402
|
-
if (!id.endsWith(".vue"))
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
642
|
+
if (!id.endsWith(".vue")) {
|
|
643
|
+
if (id.includes("/dist/") || id.includes("/lib/") || id.includes("/es/")) return null;
|
|
644
|
+
try {
|
|
645
|
+
const resolved = await this.resolve(id, cleanImporter, { skipSelf: true });
|
|
646
|
+
if (resolved) {
|
|
647
|
+
logger.log(`resolveId: resolved ${id} to ${resolved.id} via Vite resolver`);
|
|
648
|
+
if (isBuild && resolved.id.startsWith("/@fs/")) return {
|
|
649
|
+
...resolved,
|
|
650
|
+
id: normalizeFsIdForBuild(resolved.id)
|
|
651
|
+
};
|
|
652
|
+
return resolved;
|
|
653
|
+
}
|
|
654
|
+
} catch {}
|
|
655
|
+
if (id.startsWith("./") || id.startsWith("../")) {
|
|
656
|
+
const [pathPart, queryPart] = id.split("?");
|
|
657
|
+
const querySuffix = queryPart ? `?${queryPart}` : "";
|
|
658
|
+
const resolved = path.resolve(path.dirname(cleanImporter), pathPart);
|
|
659
|
+
for (const ext of [
|
|
660
|
+
"",
|
|
661
|
+
".ts",
|
|
662
|
+
".tsx",
|
|
663
|
+
".js",
|
|
664
|
+
".jsx",
|
|
665
|
+
".json"
|
|
666
|
+
]) {
|
|
667
|
+
const candidate = resolved + ext;
|
|
668
|
+
if (fs.existsSync(candidate) && fs.statSync(candidate).isFile()) {
|
|
669
|
+
const finalPath = candidate + querySuffix;
|
|
670
|
+
logger.log(`resolveId: resolved relative ${id} to ${finalPath}`);
|
|
671
|
+
return finalPath;
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
if (fs.existsSync(resolved) && fs.statSync(resolved).isDirectory()) for (const indexFile of [
|
|
675
|
+
"/index.ts",
|
|
676
|
+
"/index.tsx",
|
|
677
|
+
"/index.js",
|
|
678
|
+
"/index.jsx"
|
|
679
|
+
]) {
|
|
680
|
+
const candidate = resolved + indexFile;
|
|
681
|
+
if (fs.existsSync(candidate)) {
|
|
682
|
+
const finalPath = candidate + querySuffix;
|
|
683
|
+
logger.log(`resolveId: resolved directory ${id} to ${finalPath}`);
|
|
684
|
+
return finalPath;
|
|
685
|
+
}
|
|
686
|
+
}
|
|
422
687
|
}
|
|
423
|
-
|
|
424
|
-
const resolved = await this.resolve(id, cleanImporter, { skipSelf: true });
|
|
425
|
-
logger.log(`resolveId: resolved external ${id} to`, resolved?.id ?? "null");
|
|
426
|
-
return resolved;
|
|
688
|
+
return null;
|
|
427
689
|
}
|
|
428
690
|
}
|
|
429
691
|
if (id.endsWith(".vue")) {
|
|
430
|
-
|
|
692
|
+
const handleNodeModules = mergedOptions.handleNodeModulesVue ?? true;
|
|
693
|
+
if (!handleNodeModules && id.includes("node_modules")) {
|
|
431
694
|
logger.log(`resolveId: skipping node_modules import ${id}`);
|
|
432
695
|
return null;
|
|
433
696
|
}
|
|
434
697
|
const resolved = resolveVuePath(id, importer);
|
|
435
|
-
|
|
698
|
+
const isNodeModulesPath = resolved.includes("node_modules");
|
|
699
|
+
if (!handleNodeModules && isNodeModulesPath) {
|
|
436
700
|
logger.log(`resolveId: skipping node_modules path ${resolved}`);
|
|
437
701
|
return null;
|
|
438
702
|
}
|
|
439
|
-
if (!filter(resolved)) {
|
|
703
|
+
if (!isNodeModulesPath && !filter(resolved)) {
|
|
440
704
|
logger.log(`resolveId: skipping filtered path ${resolved}`);
|
|
441
705
|
return null;
|
|
442
706
|
}
|
|
443
707
|
const hasCache = cache.has(resolved);
|
|
444
708
|
const fileExists = fs.existsSync(resolved);
|
|
445
709
|
logger.log(`resolveId: id=${id}, resolved=${resolved}, hasCache=${hasCache}, fileExists=${fileExists}, importer=${importer ?? "none"}`);
|
|
446
|
-
if (hasCache || fileExists)
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
710
|
+
if (hasCache || fileExists) return toVirtualId(resolved);
|
|
711
|
+
if (!fileExists && !path.isAbsolute(id)) {
|
|
712
|
+
const viteResolved = await this.resolve(id, importer, { skipSelf: true });
|
|
713
|
+
if (viteResolved && viteResolved.id.endsWith(".vue")) {
|
|
714
|
+
const realPath = viteResolved.id;
|
|
715
|
+
const isResolvedNodeModules = realPath.includes("node_modules");
|
|
716
|
+
if ((isResolvedNodeModules ? handleNodeModules : filter(realPath)) && (cache.has(realPath) || fs.existsSync(realPath))) {
|
|
717
|
+
logger.log(`resolveId: resolved via Vite fallback ${id} to ${realPath}`);
|
|
718
|
+
return toVirtualId(realPath);
|
|
719
|
+
}
|
|
720
|
+
}
|
|
450
721
|
}
|
|
451
722
|
}
|
|
452
723
|
return null;
|
|
453
724
|
},
|
|
454
|
-
load(id) {
|
|
725
|
+
load(id, loadOptions) {
|
|
726
|
+
const currentBase = loadOptions?.ssr ? serverViteBase : clientViteBase;
|
|
455
727
|
if (id === RESOLVED_CSS_MODULE) {
|
|
456
728
|
const allCss = Array.from(collectedCss.values()).join("\n\n");
|
|
457
729
|
return allCss;
|
|
458
730
|
}
|
|
459
731
|
if (id.includes("?vue&type=style")) {
|
|
460
732
|
const [filename] = id.split("?");
|
|
461
|
-
const realPath = filename
|
|
733
|
+
const realPath = isVizeVirtual(filename) ? fromVirtualId(filename) : filename;
|
|
462
734
|
const compiled = cache.get(realPath);
|
|
463
|
-
if (compiled?.css) return compiled.css;
|
|
735
|
+
if (compiled?.css) return resolveCssImports(compiled.css, realPath, cssAliasRules, server !== null, currentBase);
|
|
464
736
|
return "";
|
|
465
737
|
}
|
|
466
|
-
if (id
|
|
467
|
-
const
|
|
468
|
-
|
|
469
|
-
|
|
738
|
+
if (isVizeVirtual(id)) {
|
|
739
|
+
const realPath = fromVirtualId(id);
|
|
740
|
+
if (!realPath.endsWith(".vue")) {
|
|
741
|
+
logger.log(`load: skipping non-vue virtual module ${realPath}`);
|
|
742
|
+
return null;
|
|
743
|
+
}
|
|
744
|
+
let compiled = cache.get(realPath);
|
|
745
|
+
if (!compiled && fs.existsSync(realPath)) {
|
|
746
|
+
logger.log(`load: on-demand compiling ${realPath}`);
|
|
747
|
+
compiled = compileFile(realPath, cache, {
|
|
748
|
+
sourceMap: mergedOptions.sourceMap ?? !isProduction,
|
|
749
|
+
ssr: mergedOptions.ssr ?? false
|
|
750
|
+
});
|
|
751
|
+
}
|
|
470
752
|
if (compiled) {
|
|
471
|
-
|
|
753
|
+
if (compiled.css) compiled = {
|
|
754
|
+
...compiled,
|
|
755
|
+
css: resolveCssImports(compiled.css, realPath, cssAliasRules, server !== null, currentBase)
|
|
756
|
+
};
|
|
757
|
+
const output = rewriteStaticAssetUrls(rewriteDynamicTemplateImports(generateOutput(compiled, {
|
|
472
758
|
isProduction,
|
|
473
759
|
isDev: server !== null,
|
|
474
760
|
extractCss
|
|
475
|
-
});
|
|
761
|
+
}), dynamicImportAliasRules), dynamicImportAliasRules);
|
|
476
762
|
return {
|
|
477
763
|
code: output,
|
|
478
764
|
map: null
|
|
479
765
|
};
|
|
480
766
|
}
|
|
481
767
|
}
|
|
768
|
+
if (id.startsWith("\0")) {
|
|
769
|
+
const afterPrefix = id.startsWith(LEGACY_VIZE_PREFIX) ? id.slice(LEGACY_VIZE_PREFIX.length) : id.slice(1);
|
|
770
|
+
if (afterPrefix.includes("?commonjs-")) return null;
|
|
771
|
+
const [pathPart, queryPart] = afterPrefix.split("?");
|
|
772
|
+
const querySuffix = queryPart ? `?${queryPart}` : "";
|
|
773
|
+
const fsPath = pathPart.startsWith("/@fs/") ? pathPart.slice(4) : pathPart;
|
|
774
|
+
if (fsPath.startsWith("/") && fs.existsSync(fsPath) && fs.statSync(fsPath).isFile()) {
|
|
775
|
+
const importPath = server === null ? `${pathToFileURL(fsPath).href}${querySuffix}` : "/@fs" + fsPath + querySuffix;
|
|
776
|
+
logger.log(`load: proxying \0-prefixed file ${id} → re-export from ${importPath}`);
|
|
777
|
+
return `export { default } from ${JSON.stringify(importPath)};\nexport * from ${JSON.stringify(importPath)};`;
|
|
778
|
+
}
|
|
779
|
+
}
|
|
482
780
|
return null;
|
|
483
781
|
},
|
|
484
|
-
async transform(code, id) {
|
|
485
|
-
if (
|
|
486
|
-
const
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
782
|
+
async transform(code, id, options$1) {
|
|
783
|
+
if (isVizeVirtual(id)) {
|
|
784
|
+
const realPath = fromVirtualId(id);
|
|
785
|
+
try {
|
|
786
|
+
const result = await transformWithOxc(code, realPath, { lang: "ts" });
|
|
787
|
+
const defines = options$1?.ssr ? serverViteDefine : clientViteDefine;
|
|
788
|
+
let transformed = result.code;
|
|
789
|
+
if (Object.keys(defines).length > 0) transformed = applyDefineReplacements(transformed, defines);
|
|
790
|
+
return {
|
|
791
|
+
code: transformed,
|
|
792
|
+
map: result.map
|
|
793
|
+
};
|
|
794
|
+
} catch (e) {
|
|
795
|
+
logger.error(`transformWithOxc failed for ${realPath}:`, e);
|
|
796
|
+
const dumpPath = `/tmp/vize-oxc-error-${path.basename(realPath)}.ts`;
|
|
797
|
+
fs.writeFileSync(dumpPath, code, "utf-8");
|
|
798
|
+
logger.error(`Dumped failing code to ${dumpPath}`);
|
|
799
|
+
return {
|
|
800
|
+
code: "export default {}",
|
|
801
|
+
map: null
|
|
802
|
+
};
|
|
803
|
+
}
|
|
491
804
|
}
|
|
492
805
|
return null;
|
|
493
806
|
},
|
|
@@ -503,7 +816,7 @@ function vize(options = {}) {
|
|
|
503
816
|
const newCompiled = cache.get(file);
|
|
504
817
|
const updateType = detectHmrUpdateType(prevCompiled, newCompiled);
|
|
505
818
|
logger.log(`Re-compiled: ${path.relative(root, file)} (${updateType})`);
|
|
506
|
-
const virtualId =
|
|
819
|
+
const virtualId = toVirtualId(file);
|
|
507
820
|
const modules = server$1.moduleGraph.getModulesByFile(virtualId) ?? server$1.moduleGraph.getModulesByFile(file);
|
|
508
821
|
if (updateType === "style-only" && newCompiled.css) {
|
|
509
822
|
server$1.ws.send({
|
|
@@ -512,7 +825,7 @@ function vize(options = {}) {
|
|
|
512
825
|
data: {
|
|
513
826
|
id: newCompiled.scopeId,
|
|
514
827
|
type: "style-only",
|
|
515
|
-
css: newCompiled.css
|
|
828
|
+
css: resolveCssImports(newCompiled.css, file, cssAliasRules, true, clientViteBase)
|
|
516
829
|
}
|
|
517
830
|
});
|
|
518
831
|
return [];
|
|
@@ -535,8 +848,33 @@ function vize(options = {}) {
|
|
|
535
848
|
}
|
|
536
849
|
}
|
|
537
850
|
};
|
|
851
|
+
let compilerSfc = null;
|
|
852
|
+
const loadCompilerSfc = () => {
|
|
853
|
+
if (!compilerSfc) try {
|
|
854
|
+
const require = createRequire(import.meta.url);
|
|
855
|
+
compilerSfc = require("@vue/compiler-sfc");
|
|
856
|
+
} catch {
|
|
857
|
+
compilerSfc = { parse: () => ({
|
|
858
|
+
descriptor: {},
|
|
859
|
+
errors: []
|
|
860
|
+
}) };
|
|
861
|
+
}
|
|
862
|
+
return compilerSfc;
|
|
863
|
+
};
|
|
864
|
+
const vueCompatPlugin = {
|
|
865
|
+
name: "vite:vue",
|
|
866
|
+
api: { get options() {
|
|
867
|
+
return {
|
|
868
|
+
compiler: loadCompilerSfc(),
|
|
869
|
+
isProduction: isProduction ?? false,
|
|
870
|
+
root: root ?? process.cwd(),
|
|
871
|
+
template: {}
|
|
872
|
+
};
|
|
873
|
+
} }
|
|
874
|
+
};
|
|
875
|
+
return [vueCompatPlugin, mainPlugin];
|
|
538
876
|
}
|
|
539
877
|
var src_default = vize;
|
|
540
878
|
|
|
541
879
|
//#endregion
|
|
542
|
-
export { src_default as default, defineConfig, loadConfig, vize, vizeConfigStore };
|
|
880
|
+
export { __internal, src_default as default, defineConfig, loadConfig, vize, vizeConfigStore };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vizejs/vite-plugin",
|
|
3
|
-
"version": "0.0.1-alpha.
|
|
3
|
+
"version": "0.0.1-alpha.103",
|
|
4
4
|
"description": "High-performance native Vite plugin for Vue SFC compilation powered by Vize",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -42,8 +42,8 @@
|
|
|
42
42
|
"vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-beta.0"
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"
|
|
46
|
-
"
|
|
45
|
+
"@vizejs/native": "file:../vize-native",
|
|
46
|
+
"tinyglobby": "^0.2.0"
|
|
47
47
|
},
|
|
48
48
|
"scripts": {
|
|
49
49
|
"build": "tsdown",
|