@vizejs/vite-plugin 0.0.1-alpha.44

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 ADDED
@@ -0,0 +1,214 @@
1
+ # @vizejs/vite-plugin
2
+
3
+ High-performance native Vite plugin for Vue SFC compilation powered by [Vize](https://github.com/ubugeeei/vize).
4
+
5
+ ## Features
6
+
7
+ - **Native Performance**: Uses Rust-based compiler via Node.js native bindings (NAPI)
8
+ - **Pre-compilation**: All `.vue` files are compiled at server startup for instant module resolution
9
+ - **Virtual Modules**: Compiled code is served from memory as virtual modules
10
+ - **HMR Support**: Hot Module Replacement with automatic re-compilation on file changes
11
+ - **Vapor Mode**: Optional support for Vue Vapor mode compilation
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ # npm
17
+ npm install @vizejs/vite-plugin
18
+
19
+ # pnpm
20
+ pnpm add @vizejs/vite-plugin
21
+
22
+ # yarn
23
+ yarn add @vizejs/vite-plugin
24
+ ```
25
+
26
+ ## Usage
27
+
28
+ ### Vite
29
+
30
+ ```ts
31
+ // vite.config.ts
32
+ import { defineConfig } from 'vite'
33
+ import { vizeNative } from '@vizejs/vite-plugin'
34
+
35
+ export default defineConfig({
36
+ plugins: [
37
+ vizeNative({
38
+ // options
39
+ })
40
+ ]
41
+ })
42
+ ```
43
+
44
+ ### Nuxt
45
+
46
+ For Nuxt 3, add the plugin to your `nuxt.config.ts`:
47
+
48
+ ```ts
49
+ // nuxt.config.ts
50
+ import { vizeNative } from '@vizejs/vite-plugin'
51
+
52
+ export default defineNuxtConfig({
53
+ vite: {
54
+ plugins: [
55
+ vizeNative({
56
+ // Exclude Nuxt's internal .vue files if needed
57
+ exclude: [/node_modules/, /#/, /\.nuxt/]
58
+ })
59
+ ]
60
+ },
61
+
62
+ // Disable the default Vue plugin
63
+ vue: {
64
+ propsDestructure: false
65
+ }
66
+ })
67
+ ```
68
+
69
+ **Note**: When using with Nuxt, you may need to disable Nuxt's built-in Vue plugin to avoid conflicts:
70
+
71
+ ```ts
72
+ // nuxt.config.ts
73
+ export default defineNuxtConfig({
74
+ hooks: {
75
+ 'vite:extendConfig': (config) => {
76
+ // Remove @vitejs/plugin-vue from plugins
77
+ config.plugins = config.plugins?.filter(
78
+ (p) => p && (Array.isArray(p) ? p[0] : p).name !== 'vite:vue'
79
+ )
80
+ }
81
+ },
82
+ vite: {
83
+ plugins: [
84
+ vizeNative()
85
+ ]
86
+ }
87
+ })
88
+ ```
89
+
90
+ ## Options
91
+
92
+ ```ts
93
+ interface VizeNativeOptions {
94
+ /**
95
+ * Files to include in compilation
96
+ * @default /\.vue$/
97
+ */
98
+ include?: string | RegExp | (string | RegExp)[]
99
+
100
+ /**
101
+ * Files to exclude from compilation
102
+ * @default /node_modules/
103
+ */
104
+ exclude?: string | RegExp | (string | RegExp)[]
105
+
106
+ /**
107
+ * Force production mode
108
+ * @default auto-detected from Vite config
109
+ */
110
+ isProduction?: boolean
111
+
112
+ /**
113
+ * Enable SSR mode
114
+ * @default false
115
+ */
116
+ ssr?: boolean
117
+
118
+ /**
119
+ * Enable source map generation
120
+ * @default true in development, false in production
121
+ */
122
+ sourceMap?: boolean
123
+
124
+ /**
125
+ * Enable Vapor mode compilation
126
+ * @default false
127
+ */
128
+ vapor?: boolean
129
+
130
+ /**
131
+ * Root directory to scan for .vue files
132
+ * @default Vite's root
133
+ */
134
+ root?: string
135
+
136
+ /**
137
+ * Glob patterns to scan for .vue files during pre-compilation
138
+ * @default ['**\/*.vue']
139
+ */
140
+ scanPatterns?: string[]
141
+
142
+ /**
143
+ * Glob patterns to ignore during pre-compilation
144
+ * @default ['node_modules/**', 'dist/**', '.git/**']
145
+ */
146
+ ignorePatterns?: string[]
147
+ }
148
+ ```
149
+
150
+ ## How It Works
151
+
152
+ ### Pre-compilation at Startup
153
+
154
+ When the Vite dev server starts (or build begins), the plugin:
155
+
156
+ 1. Scans the project root for all `.vue` files matching the configured patterns
157
+ 2. Compiles each file using the native Vize compiler
158
+ 3. Stores the compiled JavaScript and CSS in an in-memory cache
159
+
160
+ This approach leverages Vize's exceptional performance - compiling 15,000 SFC files in under 500ms with multi-threading.
161
+
162
+ ### Virtual Module Resolution
163
+
164
+ When Vite requests a `.vue` file:
165
+
166
+ 1. The plugin intercepts the module resolution
167
+ 2. Returns the pre-compiled code from cache (or compiles on-demand if not cached)
168
+ 3. CSS is injected inline with deduplication support
169
+
170
+ ### HMR (Hot Module Replacement)
171
+
172
+ When a `.vue` file changes:
173
+
174
+ 1. The plugin detects the change via `handleHotUpdate`
175
+ 2. Re-compiles only the changed file
176
+ 3. Updates the cache
177
+ 4. Vite handles the rest of the HMR flow
178
+
179
+ ## Performance
180
+
181
+ Vize's native compiler is significantly faster than the official Vue compiler:
182
+
183
+ | Benchmark (15,000 SFCs) | @vue/compiler-sfc | Vize | Speedup |
184
+ |-------------------------|-------------------|------|---------|
185
+ | Single-threaded | 16.21s | 6.65s | **2.4x** |
186
+ | Multi-threaded | 4.13s | 498ms | **8.3x** |
187
+
188
+ ## Comparison with vite-plugin-vize
189
+
190
+ | Feature | vite-plugin-vize | vite-plugin-vize |
191
+ |---------|------------------|-------------------------|
192
+ | Compiler | WASM | Native (NAPI) |
193
+ | Pre-compilation | No | Yes |
194
+ | Module Loading | Transform | Virtual Module (Load) |
195
+ | Performance | Fast | Fastest |
196
+ | Platform | Any | Node.js only |
197
+
198
+ Use `vite-plugin-vize` (WASM-based) when you need:
199
+ - Browser compatibility (e.g., StackBlitz, WebContainers)
200
+ - Platform-independent deployment
201
+
202
+ Use `vite-plugin-vize` when you need:
203
+ - Maximum performance
204
+ - Server-side only (standard Node.js environment)
205
+
206
+ ## Requirements
207
+
208
+ - Node.js 18+
209
+ - Vite 5.0+ / 6.0+ / 7.0+
210
+ - Vue 3.x
211
+
212
+ ## License
213
+
214
+ MIT
@@ -0,0 +1,83 @@
1
+ import { LoadConfigOptions, VizeConfig, defineConfig, loadConfig } from "vizejs";
2
+ import { Plugin } from "vite";
3
+
4
+ //#region src/types.d.ts
5
+
6
+ interface VizeOptions {
7
+ /**
8
+ * Files to include in compilation
9
+ * @default /\.vue$/
10
+ */
11
+ include?: string | RegExp | (string | RegExp)[];
12
+ /**
13
+ * Files to exclude from compilation
14
+ * @default /node_modules/
15
+ */
16
+ exclude?: string | RegExp | (string | RegExp)[];
17
+ /**
18
+ * Force production mode
19
+ * @default auto-detected from Vite config
20
+ */
21
+ isProduction?: boolean;
22
+ /**
23
+ * Enable SSR mode
24
+ * @default false
25
+ */
26
+ ssr?: boolean;
27
+ /**
28
+ * Enable source map generation
29
+ * @default true in development, false in production
30
+ */
31
+ sourceMap?: boolean;
32
+ /**
33
+ * Enable Vapor mode compilation
34
+ * @default false
35
+ */
36
+ vapor?: boolean;
37
+ /**
38
+ * Root directory to scan for .vue files
39
+ * @default Vite's root
40
+ */
41
+ root?: string;
42
+ /**
43
+ * Glob patterns to scan for .vue files during pre-compilation
44
+ * @default ['**\/*.vue']
45
+ */
46
+ scanPatterns?: string[];
47
+ /**
48
+ * Glob patterns to ignore during pre-compilation
49
+ * @default ['node_modules/**', 'dist/**', '.git/**']
50
+ */
51
+ ignorePatterns?: string[];
52
+ /**
53
+ * Config file search mode
54
+ * - 'root': Search only in the project root directory
55
+ * - 'auto': Search from cwd upward until finding a config file
56
+ * - false: Disable config file loading
57
+ * @default 'root'
58
+ */
59
+ configMode?: "root" | "auto" | false;
60
+ /**
61
+ * Custom config file path (overrides automatic search)
62
+ */
63
+ configFile?: string;
64
+ /**
65
+ * Enable debug logging
66
+ * @default false
67
+ */
68
+ debug?: boolean;
69
+ }
70
+ interface CompiledModule {
71
+ code: string;
72
+ css?: string;
73
+ scopeId: string;
74
+ hasScoped: boolean;
75
+ templateHash?: string;
76
+ styleHash?: string;
77
+ scriptHash?: string;
78
+ } //#endregion
79
+ //#region src/index.d.ts
80
+ declare function vize(options?: VizeOptions): Plugin;
81
+
82
+ //#endregion
83
+ export { CompiledModule, LoadConfigOptions, VizeConfig, VizeOptions, vize as default, defineConfig, loadConfig, vize };
package/dist/index.js ADDED
@@ -0,0 +1,447 @@
1
+ import path from "node:path";
2
+ import fs from "node:fs";
3
+ import { glob } from "tinyglobby";
4
+ import { createRequire } from "node:module";
5
+ import { createHash } from "node:crypto";
6
+ import { defineConfig, loadConfig } from "vizejs";
7
+
8
+ //#region src/hmr.ts
9
+ /**
10
+ * Detect the type of HMR update needed based on content hash changes.
11
+ *
12
+ * @param prev - Previously compiled module (undefined if first compile)
13
+ * @param next - Newly compiled module
14
+ * @returns The type of HMR update needed
15
+ */
16
+ function detectHmrUpdateType(prev, next) {
17
+ if (!prev) return "full-reload";
18
+ const scriptChanged = prev.scriptHash !== next.scriptHash;
19
+ if (scriptChanged) return "full-reload";
20
+ const templateChanged = prev.templateHash !== next.templateHash;
21
+ const styleChanged = prev.styleHash !== next.styleHash;
22
+ if (styleChanged && !templateChanged) return "style-only";
23
+ if (templateChanged) return "template-only";
24
+ return "full-reload";
25
+ }
26
+ /**
27
+ * Generate HMR-aware code output based on update type.
28
+ */
29
+ function generateHmrCode(scopeId, updateType) {
30
+ return `
31
+ if (import.meta.hot) {
32
+ _sfc_main.__hmrId = ${JSON.stringify(scopeId)};
33
+ _sfc_main.__hmrUpdateType = ${JSON.stringify(updateType)};
34
+
35
+ import.meta.hot.accept((mod) => {
36
+ if (!mod) return;
37
+ const { default: updated } = mod;
38
+ if (typeof __VUE_HMR_RUNTIME__ !== 'undefined') {
39
+ const updateType = updated.__hmrUpdateType || 'full-reload';
40
+ if (updateType === 'template-only') {
41
+ __VUE_HMR_RUNTIME__.rerender(updated.__hmrId, updated.render);
42
+ } else {
43
+ __VUE_HMR_RUNTIME__.reload(updated.__hmrId, updated);
44
+ }
45
+ }
46
+ });
47
+
48
+ import.meta.hot.on('vize:update', (data) => {
49
+ if (data.id !== _sfc_main.__hmrId) return;
50
+
51
+ if (data.type === 'style-only') {
52
+ // Update styles without remounting component
53
+ const styleId = 'vize-style-' + _sfc_main.__hmrId;
54
+ const styleEl = document.getElementById(styleId);
55
+ if (styleEl && data.css) {
56
+ styleEl.textContent = data.css;
57
+ }
58
+ }
59
+ });
60
+
61
+ if (typeof __VUE_HMR_RUNTIME__ !== 'undefined') {
62
+ __VUE_HMR_RUNTIME__.createRecord(_sfc_main.__hmrId, _sfc_main);
63
+ }
64
+ }`;
65
+ }
66
+
67
+ //#endregion
68
+ //#region src/utils.ts
69
+ function generateScopeId(filename) {
70
+ const hash = createHash("sha256").update(filename).digest("hex");
71
+ return hash.slice(0, 8);
72
+ }
73
+ function createFilter(include, exclude) {
74
+ const includePatterns = include ? Array.isArray(include) ? include : [include] : [/\.vue$/];
75
+ const excludePatterns = exclude ? Array.isArray(exclude) ? exclude : [exclude] : [/node_modules/];
76
+ return (id) => {
77
+ const matchInclude = includePatterns.some((pattern) => typeof pattern === "string" ? id.includes(pattern) : pattern.test(id));
78
+ const matchExclude = excludePatterns.some((pattern) => typeof pattern === "string" ? id.includes(pattern) : pattern.test(id));
79
+ return matchInclude && !matchExclude;
80
+ };
81
+ }
82
+ function generateOutput(compiled, options) {
83
+ const { isProduction, isDev, hmrUpdateType, extractCss } = options;
84
+ let output = compiled.code;
85
+ const exportDefaultRegex = /^export default /m;
86
+ const hasExportDefault = exportDefaultRegex.test(output);
87
+ const hasSfcMainDefined = /\bconst\s+_sfc_main\s*=/.test(output);
88
+ if (hasExportDefault && !hasSfcMainDefined) {
89
+ output = output.replace(exportDefaultRegex, "const _sfc_main = ");
90
+ if (compiled.hasScoped && compiled.scopeId) output += `\n_sfc_main.__scopeId = "data-v-${compiled.scopeId}";`;
91
+ output += "\nexport default _sfc_main;";
92
+ } else if (hasExportDefault && hasSfcMainDefined) {
93
+ if (compiled.hasScoped && compiled.scopeId) output = output.replace(/^export default _sfc_main/m, `_sfc_main.__scopeId = "data-v-${compiled.scopeId}";\nexport default _sfc_main`);
94
+ }
95
+ if (compiled.css && !(isProduction && extractCss)) {
96
+ const cssCode = JSON.stringify(compiled.css);
97
+ const cssId = JSON.stringify(`vize-style-${compiled.scopeId}`);
98
+ output = `
99
+ const __vize_css__ = ${cssCode};
100
+ const __vize_css_id__ = ${cssId};
101
+ (function() {
102
+ if (typeof document !== 'undefined') {
103
+ let style = document.getElementById(__vize_css_id__);
104
+ if (!style) {
105
+ style = document.createElement('style');
106
+ style.id = __vize_css_id__;
107
+ style.textContent = __vize_css__;
108
+ document.head.appendChild(style);
109
+ } else {
110
+ style.textContent = __vize_css__;
111
+ }
112
+ }
113
+ })();
114
+ ${output}`;
115
+ }
116
+ if (!isProduction && isDev && hasExportDefault) output += generateHmrCode(compiled.scopeId, hmrUpdateType ?? "full-reload");
117
+ return output;
118
+ }
119
+
120
+ //#endregion
121
+ //#region src/compiler.ts
122
+ const require = createRequire(import.meta.url);
123
+ let compileSfc = null;
124
+ let compileSfcBatchWithResults = null;
125
+ function loadNative() {
126
+ if (compileSfc) return compileSfc;
127
+ try {
128
+ const native = require("@vizejs/native");
129
+ compileSfc = native.compileSfc;
130
+ return compileSfc;
131
+ } catch (e) {
132
+ throw new Error(`Failed to load @vizejs/native. Make sure it's installed and built:\n${String(e)}`);
133
+ }
134
+ }
135
+ function loadNativeBatch() {
136
+ if (compileSfcBatchWithResults) return compileSfcBatchWithResults;
137
+ try {
138
+ const native = require("@vizejs/native");
139
+ compileSfcBatchWithResults = native.compileSfcBatchWithResults;
140
+ return compileSfcBatchWithResults;
141
+ } catch (e) {
142
+ throw new Error(`Failed to load @vizejs/native. Make sure it's installed and built:\n${String(e)}`);
143
+ }
144
+ }
145
+ function compileFile(filePath, cache, options, source) {
146
+ const compile = loadNative();
147
+ const content = source ?? fs.readFileSync(filePath, "utf-8");
148
+ const scopeId = generateScopeId(filePath);
149
+ const hasScoped = /<style[^>]*\bscoped\b/.test(content);
150
+ const result = compile(content, {
151
+ filename: filePath,
152
+ sourceMap: options.sourceMap,
153
+ ssr: options.ssr,
154
+ scopeId: hasScoped ? `data-v-${scopeId}` : void 0
155
+ });
156
+ if (result.errors.length > 0) {
157
+ const errorMsg = result.errors.join("\n");
158
+ console.error(`[vize] Compilation error in ${filePath}:\n${errorMsg}`);
159
+ }
160
+ if (result.warnings.length > 0) result.warnings.forEach((warning) => {
161
+ console.warn(`[vize] Warning in ${filePath}: ${warning}`);
162
+ });
163
+ const compiled = {
164
+ code: result.code,
165
+ css: result.css,
166
+ scopeId,
167
+ hasScoped
168
+ };
169
+ cache.set(filePath, compiled);
170
+ return compiled;
171
+ }
172
+ /**
173
+ * Batch compile multiple files in parallel using native Rust multithreading.
174
+ * Returns per-file results with content hashes for HMR.
175
+ */
176
+ function compileBatch(files, cache, options) {
177
+ const compile = loadNativeBatch();
178
+ const inputs = files.map((f) => ({
179
+ path: f.path,
180
+ source: f.source
181
+ }));
182
+ const result = compile(inputs, { ssr: options.ssr });
183
+ for (const fileResult of result.results) {
184
+ if (fileResult.errors.length === 0) cache.set(fileResult.path, {
185
+ code: fileResult.code,
186
+ css: fileResult.css,
187
+ scopeId: fileResult.scopeId,
188
+ hasScoped: fileResult.hasScoped,
189
+ templateHash: fileResult.templateHash,
190
+ styleHash: fileResult.styleHash,
191
+ scriptHash: fileResult.scriptHash
192
+ });
193
+ if (fileResult.errors.length > 0) console.error(`[vize] Compilation error in ${fileResult.path}:\n${fileResult.errors.join("\n")}`);
194
+ if (fileResult.warnings.length > 0) fileResult.warnings.forEach((warning) => {
195
+ console.warn(`[vize] Warning in ${fileResult.path}: ${warning}`);
196
+ });
197
+ }
198
+ return result;
199
+ }
200
+
201
+ //#endregion
202
+ //#region src/index.ts
203
+ const VIRTUAL_PREFIX = "\0vize:";
204
+ const VIRTUAL_CSS_MODULE = "virtual:vize-styles";
205
+ const RESOLVED_CSS_MODULE = "\0vize:all-styles.css";
206
+ function createLogger(debug) {
207
+ return {
208
+ log: (...args) => debug && console.log("[vize]", ...args),
209
+ info: (...args) => console.log("[vize]", ...args),
210
+ warn: (...args) => console.warn("[vize]", ...args),
211
+ error: (...args) => console.error("[vize]", ...args)
212
+ };
213
+ }
214
+ function vize(options = {}) {
215
+ const cache = new Map();
216
+ const virtualToReal = new Map();
217
+ const collectedCss = new Map();
218
+ let isProduction;
219
+ let root;
220
+ let server = null;
221
+ let filter;
222
+ let scanPatterns;
223
+ let ignorePatterns;
224
+ let mergedOptions;
225
+ let extractCss = false;
226
+ const logger = createLogger(options.debug ?? false);
227
+ async function compileAll() {
228
+ const startTime = performance.now();
229
+ const files = await glob(scanPatterns, {
230
+ cwd: root,
231
+ ignore: ignorePatterns,
232
+ absolute: true
233
+ });
234
+ logger.info(`Pre-compiling ${files.length} Vue files...`);
235
+ const fileContents = [];
236
+ for (const file of files) try {
237
+ const source = fs.readFileSync(file, "utf-8");
238
+ fileContents.push({
239
+ path: file,
240
+ source
241
+ });
242
+ } catch (e) {
243
+ logger.error(`Failed to read ${file}:`, e);
244
+ }
245
+ const result = compileBatch(fileContents, cache, { ssr: mergedOptions.ssr ?? false });
246
+ if (isProduction) {
247
+ for (const fileResult of result.results) if (fileResult.css) collectedCss.set(fileResult.path, fileResult.css);
248
+ }
249
+ const elapsed = (performance.now() - startTime).toFixed(2);
250
+ logger.info(`Pre-compilation complete: ${result.successCount} succeeded, ${result.failedCount} failed (${elapsed}ms, native batch: ${result.timeMs.toFixed(2)}ms)`);
251
+ }
252
+ function resolveVuePath(id, importer) {
253
+ let resolved;
254
+ if (id.startsWith("/@fs/")) resolved = id.slice(4);
255
+ else if (id.startsWith("/") && !fs.existsSync(id)) resolved = path.resolve(root, id.slice(1));
256
+ else if (path.isAbsolute(id)) resolved = id;
257
+ else if (importer) {
258
+ const realImporter = importer.startsWith(VIRTUAL_PREFIX) ? virtualToReal.get(importer) ?? importer.slice(VIRTUAL_PREFIX.length) : importer;
259
+ resolved = path.resolve(path.dirname(realImporter), id);
260
+ } else resolved = path.resolve(root, id);
261
+ return path.normalize(resolved);
262
+ }
263
+ return {
264
+ name: "vite-plugin-vize",
265
+ enforce: "pre",
266
+ config() {
267
+ return { optimizeDeps: {
268
+ include: ["vue"],
269
+ exclude: ["virtual:vize-styles"],
270
+ esbuildOptions: { plugins: [{
271
+ name: "vize-externalize-vue",
272
+ setup(build) {
273
+ build.onResolve({ filter: /\.vue$/ }, (args) => ({
274
+ path: args.path,
275
+ external: true
276
+ }));
277
+ }
278
+ }] },
279
+ rolldownOptions: { external: [/\.vue$/] }
280
+ } };
281
+ },
282
+ async configResolved(resolvedConfig) {
283
+ root = options.root ?? resolvedConfig.root;
284
+ isProduction = options.isProduction ?? resolvedConfig.isProduction;
285
+ extractCss = isProduction;
286
+ let fileConfig = null;
287
+ if (options.configMode !== false) {
288
+ const { loadConfig: loadConfig$1 } = await import("vizejs");
289
+ fileConfig = await loadConfig$1(root, {
290
+ mode: options.configMode ?? "root",
291
+ configFile: options.configFile
292
+ });
293
+ if (fileConfig) logger.log("Loaded config from vize.config file");
294
+ }
295
+ const viteConfig = fileConfig?.vite ?? {};
296
+ const compilerConfig = fileConfig?.compiler ?? {};
297
+ mergedOptions = {
298
+ ...options,
299
+ ssr: options.ssr ?? compilerConfig.ssr ?? false,
300
+ sourceMap: options.sourceMap ?? compilerConfig.sourceMap,
301
+ vapor: options.vapor ?? compilerConfig.vapor ?? false,
302
+ include: options.include ?? viteConfig.include,
303
+ exclude: options.exclude ?? viteConfig.exclude,
304
+ scanPatterns: options.scanPatterns ?? viteConfig.scanPatterns,
305
+ ignorePatterns: options.ignorePatterns ?? viteConfig.ignorePatterns
306
+ };
307
+ filter = createFilter(mergedOptions.include, mergedOptions.exclude);
308
+ scanPatterns = mergedOptions.scanPatterns ?? ["**/*.vue"];
309
+ ignorePatterns = mergedOptions.ignorePatterns ?? [
310
+ "node_modules/**",
311
+ "dist/**",
312
+ ".git/**"
313
+ ];
314
+ },
315
+ configureServer(devServer) {
316
+ server = devServer;
317
+ },
318
+ async buildStart() {
319
+ await compileAll();
320
+ logger.log("Cache keys:", [...cache.keys()].slice(0, 3));
321
+ },
322
+ async resolveId(id, importer) {
323
+ if (id === VIRTUAL_CSS_MODULE) return RESOLVED_CSS_MODULE;
324
+ if (id.includes("?vue&type=style")) return id;
325
+ if (importer?.startsWith(VIRTUAL_PREFIX)) {
326
+ const realImporter = virtualToReal.get(importer) ?? importer.slice(VIRTUAL_PREFIX.length);
327
+ const cleanImporter = realImporter.endsWith(".ts") ? realImporter.slice(0, -3) : realImporter;
328
+ logger.log(`resolveId from virtual: id=${id}, cleanImporter=${cleanImporter}`);
329
+ if (!id.endsWith(".vue")) if (id.startsWith("./") || id.startsWith("../")) {
330
+ const [pathPart, queryPart] = id.split("?");
331
+ const querySuffix = queryPart ? `?${queryPart}` : "";
332
+ const resolved = path.resolve(path.dirname(cleanImporter), pathPart);
333
+ for (const ext of [
334
+ "",
335
+ ".ts",
336
+ ".tsx",
337
+ ".js",
338
+ ".jsx",
339
+ ".json"
340
+ ]) if (fs.existsSync(resolved + ext)) {
341
+ const finalPath = resolved + ext + querySuffix;
342
+ logger.log(`resolveId: resolved relative ${id} to ${finalPath}`);
343
+ return finalPath;
344
+ }
345
+ } else {
346
+ if (id.includes("/dist/") || id.includes("/lib/") || id.includes("/es/")) {
347
+ logger.log(`resolveId: skipping already-resolved path ${id}`);
348
+ return null;
349
+ }
350
+ logger.log(`resolveId: resolving external ${id} from ${cleanImporter}`);
351
+ const resolved = await this.resolve(id, cleanImporter, { skipSelf: true });
352
+ logger.log(`resolveId: resolved external ${id} to`, resolved?.id ?? "null");
353
+ return resolved;
354
+ }
355
+ }
356
+ if (id.endsWith(".vue")) {
357
+ const resolved = resolveVuePath(id, importer);
358
+ const hasCache = cache.has(resolved);
359
+ const fileExists = fs.existsSync(resolved);
360
+ logger.log(`resolveId: id=${id}, resolved=${resolved}, hasCache=${hasCache}, fileExists=${fileExists}, importer=${importer ?? "none"}`);
361
+ if (hasCache || fileExists) {
362
+ const virtualId = VIRTUAL_PREFIX + resolved + ".ts";
363
+ virtualToReal.set(virtualId, resolved);
364
+ return virtualId;
365
+ }
366
+ }
367
+ return null;
368
+ },
369
+ load(id) {
370
+ if (id === RESOLVED_CSS_MODULE) {
371
+ const allCss = Array.from(collectedCss.values()).join("\n\n");
372
+ return allCss;
373
+ }
374
+ if (id.includes("?vue&type=style")) {
375
+ const [filename] = id.split("?");
376
+ const realPath = filename.startsWith(VIRTUAL_PREFIX) ? virtualToReal.get(filename) ?? filename.slice(VIRTUAL_PREFIX.length) : filename;
377
+ const compiled = cache.get(realPath);
378
+ if (compiled?.css) return compiled.css;
379
+ return "";
380
+ }
381
+ if (id.startsWith(VIRTUAL_PREFIX)) {
382
+ const lookupId = id.endsWith(".ts") ? id.slice(0, -3) : id;
383
+ const realPath = virtualToReal.get(id) ?? lookupId.slice(VIRTUAL_PREFIX.length);
384
+ const compiled = cache.get(realPath);
385
+ if (compiled) {
386
+ const output = generateOutput(compiled, {
387
+ isProduction,
388
+ isDev: server !== null,
389
+ extractCss
390
+ });
391
+ return {
392
+ code: output,
393
+ map: null
394
+ };
395
+ }
396
+ }
397
+ return null;
398
+ },
399
+ async handleHotUpdate(ctx) {
400
+ const { file, server: server$1, read } = ctx;
401
+ if (file.endsWith(".vue") && filter(file)) try {
402
+ const source = await read();
403
+ const prevCompiled = cache.get(file);
404
+ compileFile(file, cache, {
405
+ sourceMap: mergedOptions.sourceMap ?? !isProduction,
406
+ ssr: mergedOptions.ssr ?? false
407
+ }, source);
408
+ const newCompiled = cache.get(file);
409
+ const updateType = detectHmrUpdateType(prevCompiled, newCompiled);
410
+ logger.log(`Re-compiled: ${path.relative(root, file)} (${updateType})`);
411
+ const virtualId = VIRTUAL_PREFIX + file + ".ts";
412
+ const modules = server$1.moduleGraph.getModulesByFile(virtualId) ?? server$1.moduleGraph.getModulesByFile(file);
413
+ if (updateType === "style-only" && newCompiled.css) {
414
+ server$1.ws.send({
415
+ type: "custom",
416
+ event: "vize:update",
417
+ data: {
418
+ id: newCompiled.scopeId,
419
+ type: "style-only",
420
+ css: newCompiled.css
421
+ }
422
+ });
423
+ return [];
424
+ }
425
+ if (modules) return [...modules];
426
+ } catch (e) {
427
+ logger.error(`Re-compilation failed for ${file}:`, e);
428
+ }
429
+ },
430
+ generateBundle(_, _bundle) {
431
+ if (!extractCss || collectedCss.size === 0) return;
432
+ const allCss = Array.from(collectedCss.values()).join("\n\n");
433
+ if (allCss.trim()) {
434
+ this.emitFile({
435
+ type: "asset",
436
+ fileName: "assets/vize-components.css",
437
+ source: allCss
438
+ });
439
+ logger.log(`Extracted CSS to assets/vize-components.css (${collectedCss.size} components)`);
440
+ }
441
+ }
442
+ };
443
+ }
444
+ var src_default = vize;
445
+
446
+ //#endregion
447
+ export { src_default as default, defineConfig, loadConfig, vize };
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "@vizejs/vite-plugin",
3
+ "version": "0.0.1-alpha.44",
4
+ "description": "High-performance native Vite plugin for Vue SFC compilation powered by Vize",
5
+ "publishConfig": {
6
+ "provenance": true,
7
+ "access": "public"
8
+ },
9
+ "type": "module",
10
+ "main": "./dist/index.js",
11
+ "types": "./dist/index.d.ts",
12
+ "exports": {
13
+ ".": {
14
+ "import": "./dist/index.js",
15
+ "types": "./dist/index.d.ts"
16
+ }
17
+ },
18
+ "files": [
19
+ "dist"
20
+ ],
21
+ "keywords": [
22
+ "vite",
23
+ "vue",
24
+ "plugin",
25
+ "sfc",
26
+ "compiler",
27
+ "native",
28
+ "fast"
29
+ ],
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "https://github.com/ubugeeei/vize",
33
+ "directory": "npm/vite-plugin-vize"
34
+ },
35
+ "license": "MIT",
36
+ "devDependencies": {
37
+ "@types/node": "^22.0.0",
38
+ "tsdown": "^0.9.0",
39
+ "typescript": "~5.6.0",
40
+ "vite": "^8.0.0-beta.0"
41
+ },
42
+ "peerDependencies": {
43
+ "vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-beta.0"
44
+ },
45
+ "dependencies": {
46
+ "tinyglobby": "^0.2.0",
47
+ "vizejs": "0.0.1-alpha.20",
48
+ "@vizejs/native": "0.0.1-alpha.44"
49
+ },
50
+ "scripts": {
51
+ "build": "tsdown",
52
+ "dev": "tsdown --watch",
53
+ "lint": "oxlint --deny-warnings --type-aware --tsconfig tsconfig.json",
54
+ "lint:fix": "oxlint --type-aware --tsconfig tsconfig.json --fix",
55
+ "fmt": "oxfmt --write src",
56
+ "fmt:check": "oxfmt src"
57
+ }
58
+ }