@vizejs/vite-plugin 0.0.1-alpha.8
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 +214 -0
- package/dist/compiler.d.ts +6 -0
- package/dist/compiler.js +46 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +141 -0
- package/dist/types.d.ts +66 -0
- package/dist/types.js +1 -0
- package/dist/utils.d.ts +4 -0
- package/dist/utils.js +71 -0
- package/package.json +47 -0
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,6 @@
|
|
|
1
|
+
import type { CompileSfcFn, CompiledModule } from './types.js';
|
|
2
|
+
export declare function loadNative(): CompileSfcFn;
|
|
3
|
+
export declare function compileFile(filePath: string, cache: Map<string, CompiledModule>, options: {
|
|
4
|
+
sourceMap: boolean;
|
|
5
|
+
ssr: boolean;
|
|
6
|
+
}, source?: string): CompiledModule;
|
package/dist/compiler.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
import { generateScopeId } from './utils.js';
|
|
4
|
+
const require = createRequire(import.meta.url);
|
|
5
|
+
let compileSfc = null;
|
|
6
|
+
export function loadNative() {
|
|
7
|
+
if (compileSfc)
|
|
8
|
+
return compileSfc;
|
|
9
|
+
try {
|
|
10
|
+
const native = require('@vizejs/native');
|
|
11
|
+
compileSfc = native.compileSfc;
|
|
12
|
+
return compileSfc;
|
|
13
|
+
}
|
|
14
|
+
catch (e) {
|
|
15
|
+
throw new Error(`Failed to load @vizejs/native. Make sure it's installed and built:\n${e}`);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export function compileFile(filePath, cache, options, source) {
|
|
19
|
+
const compile = loadNative();
|
|
20
|
+
const content = source ?? fs.readFileSync(filePath, 'utf-8');
|
|
21
|
+
const scopeId = generateScopeId(filePath);
|
|
22
|
+
const hasScoped = /<style[^>]*\bscoped\b/.test(content);
|
|
23
|
+
const result = compile(content, {
|
|
24
|
+
filename: filePath,
|
|
25
|
+
sourceMap: options.sourceMap,
|
|
26
|
+
ssr: options.ssr,
|
|
27
|
+
scopeId: hasScoped ? `data-v-${scopeId}` : undefined,
|
|
28
|
+
});
|
|
29
|
+
if (result.errors.length > 0) {
|
|
30
|
+
const errorMsg = result.errors.join('\n');
|
|
31
|
+
console.error(`[vize] Compilation error in ${filePath}:\n${errorMsg}`);
|
|
32
|
+
}
|
|
33
|
+
if (result.warnings.length > 0) {
|
|
34
|
+
result.warnings.forEach((warning) => {
|
|
35
|
+
console.warn(`[vize] Warning in ${filePath}: ${warning}`);
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
const compiled = {
|
|
39
|
+
code: result.code,
|
|
40
|
+
css: result.css,
|
|
41
|
+
scopeId,
|
|
42
|
+
hasScoped,
|
|
43
|
+
};
|
|
44
|
+
cache.set(filePath, compiled);
|
|
45
|
+
return compiled;
|
|
46
|
+
}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { glob } from 'tinyglobby';
|
|
3
|
+
import { compileFile } from './compiler.js';
|
|
4
|
+
import { createFilter, generateOutput } from './utils.js';
|
|
5
|
+
const VIRTUAL_PREFIX = '\0vize:';
|
|
6
|
+
export function vize(options = {}) {
|
|
7
|
+
const filter = createFilter(options.include, options.exclude);
|
|
8
|
+
const cache = new Map();
|
|
9
|
+
// Map from virtual ID to real file path
|
|
10
|
+
const virtualToReal = new Map();
|
|
11
|
+
let isProduction;
|
|
12
|
+
let root;
|
|
13
|
+
let server = null;
|
|
14
|
+
const scanPatterns = options.scanPatterns ?? ['**/*.vue'];
|
|
15
|
+
const ignorePatterns = options.ignorePatterns ?? [
|
|
16
|
+
'node_modules/**',
|
|
17
|
+
'dist/**',
|
|
18
|
+
'.git/**',
|
|
19
|
+
];
|
|
20
|
+
async function compileAll() {
|
|
21
|
+
const startTime = performance.now();
|
|
22
|
+
const files = await glob(scanPatterns, {
|
|
23
|
+
cwd: root,
|
|
24
|
+
ignore: ignorePatterns,
|
|
25
|
+
absolute: true,
|
|
26
|
+
});
|
|
27
|
+
console.log(`[vize] Pre-compiling ${files.length} Vue files...`);
|
|
28
|
+
let successCount = 0;
|
|
29
|
+
let errorCount = 0;
|
|
30
|
+
for (const file of files) {
|
|
31
|
+
try {
|
|
32
|
+
compileFile(file, cache, {
|
|
33
|
+
sourceMap: options.sourceMap ?? !isProduction,
|
|
34
|
+
ssr: options.ssr ?? false,
|
|
35
|
+
});
|
|
36
|
+
successCount++;
|
|
37
|
+
}
|
|
38
|
+
catch (e) {
|
|
39
|
+
errorCount++;
|
|
40
|
+
console.error(`[vize] Failed to compile ${file}:`, e);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
const elapsed = (performance.now() - startTime).toFixed(2);
|
|
44
|
+
console.log(`[vize] Pre-compilation complete: ${successCount} succeeded, ${errorCount} failed (${elapsed}ms)`);
|
|
45
|
+
}
|
|
46
|
+
function resolveVuePath(id, importer) {
|
|
47
|
+
let resolved;
|
|
48
|
+
if (path.isAbsolute(id)) {
|
|
49
|
+
resolved = id;
|
|
50
|
+
}
|
|
51
|
+
else if (importer) {
|
|
52
|
+
// Remove virtual prefix from importer if present
|
|
53
|
+
const realImporter = importer.startsWith(VIRTUAL_PREFIX)
|
|
54
|
+
? virtualToReal.get(importer) ?? importer.slice(VIRTUAL_PREFIX.length)
|
|
55
|
+
: importer;
|
|
56
|
+
resolved = path.resolve(path.dirname(realImporter), id);
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
resolved = path.resolve(root, id);
|
|
60
|
+
}
|
|
61
|
+
return path.normalize(resolved);
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
name: 'vite-plugin-vize',
|
|
65
|
+
enforce: 'pre',
|
|
66
|
+
configResolved(resolvedConfig) {
|
|
67
|
+
isProduction = options.isProduction ?? resolvedConfig.isProduction;
|
|
68
|
+
root = options.root ?? resolvedConfig.root;
|
|
69
|
+
},
|
|
70
|
+
configureServer(devServer) {
|
|
71
|
+
server = devServer;
|
|
72
|
+
},
|
|
73
|
+
async buildStart() {
|
|
74
|
+
await compileAll();
|
|
75
|
+
},
|
|
76
|
+
resolveId(id, importer) {
|
|
77
|
+
if (id.includes('?vue&type=style')) {
|
|
78
|
+
return id;
|
|
79
|
+
}
|
|
80
|
+
if (id.endsWith('.vue')) {
|
|
81
|
+
const resolved = resolveVuePath(id, importer);
|
|
82
|
+
// Return virtual module ID if cached
|
|
83
|
+
if (cache.has(resolved)) {
|
|
84
|
+
const virtualId = VIRTUAL_PREFIX + resolved;
|
|
85
|
+
virtualToReal.set(virtualId, resolved);
|
|
86
|
+
return virtualId;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return null;
|
|
90
|
+
},
|
|
91
|
+
load(id) {
|
|
92
|
+
if (id.includes('?vue&type=style')) {
|
|
93
|
+
const [filename] = id.split('?');
|
|
94
|
+
const realPath = filename.startsWith(VIRTUAL_PREFIX)
|
|
95
|
+
? virtualToReal.get(filename) ?? filename.slice(VIRTUAL_PREFIX.length)
|
|
96
|
+
: filename;
|
|
97
|
+
const compiled = cache.get(realPath);
|
|
98
|
+
if (compiled?.css) {
|
|
99
|
+
return compiled.css;
|
|
100
|
+
}
|
|
101
|
+
return '';
|
|
102
|
+
}
|
|
103
|
+
// Handle virtual module
|
|
104
|
+
if (id.startsWith(VIRTUAL_PREFIX)) {
|
|
105
|
+
const realPath = virtualToReal.get(id) ?? id.slice(VIRTUAL_PREFIX.length);
|
|
106
|
+
const compiled = cache.get(realPath);
|
|
107
|
+
if (compiled) {
|
|
108
|
+
return {
|
|
109
|
+
code: generateOutput(compiled, isProduction, server !== null),
|
|
110
|
+
map: null,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return null;
|
|
115
|
+
},
|
|
116
|
+
async handleHotUpdate(ctx) {
|
|
117
|
+
const { file, server, read } = ctx;
|
|
118
|
+
if (file.endsWith('.vue') && filter(file)) {
|
|
119
|
+
try {
|
|
120
|
+
const source = await read();
|
|
121
|
+
compileFile(file, cache, {
|
|
122
|
+
sourceMap: options.sourceMap ?? !isProduction,
|
|
123
|
+
ssr: options.ssr ?? false,
|
|
124
|
+
}, source);
|
|
125
|
+
console.log(`[vize] Re-compiled: ${path.relative(root, file)}`);
|
|
126
|
+
}
|
|
127
|
+
catch (e) {
|
|
128
|
+
console.error(`[vize] Re-compilation failed for ${file}:`, e);
|
|
129
|
+
}
|
|
130
|
+
// Find the virtual module for this file
|
|
131
|
+
const virtualId = VIRTUAL_PREFIX + file;
|
|
132
|
+
const modules = server.moduleGraph.getModulesByFile(virtualId)
|
|
133
|
+
?? server.moduleGraph.getModulesByFile(file);
|
|
134
|
+
if (modules) {
|
|
135
|
+
return [...modules];
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
export default vize;
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
export interface SfcCompileOptionsNapi {
|
|
2
|
+
filename?: string;
|
|
3
|
+
sourceMap?: boolean;
|
|
4
|
+
ssr?: boolean;
|
|
5
|
+
scopeId?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface SfcCompileResultNapi {
|
|
8
|
+
code: string;
|
|
9
|
+
css?: string;
|
|
10
|
+
errors: string[];
|
|
11
|
+
warnings: string[];
|
|
12
|
+
}
|
|
13
|
+
export type CompileSfcFn = (source: string, options?: SfcCompileOptionsNapi) => SfcCompileResultNapi;
|
|
14
|
+
export interface VizeOptions {
|
|
15
|
+
/**
|
|
16
|
+
* Files to include in compilation
|
|
17
|
+
* @default /\.vue$/
|
|
18
|
+
*/
|
|
19
|
+
include?: string | RegExp | (string | RegExp)[];
|
|
20
|
+
/**
|
|
21
|
+
* Files to exclude from compilation
|
|
22
|
+
* @default /node_modules/
|
|
23
|
+
*/
|
|
24
|
+
exclude?: string | RegExp | (string | RegExp)[];
|
|
25
|
+
/**
|
|
26
|
+
* Force production mode
|
|
27
|
+
* @default auto-detected from Vite config
|
|
28
|
+
*/
|
|
29
|
+
isProduction?: boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Enable SSR mode
|
|
32
|
+
* @default false
|
|
33
|
+
*/
|
|
34
|
+
ssr?: boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Enable source map generation
|
|
37
|
+
* @default true in development, false in production
|
|
38
|
+
*/
|
|
39
|
+
sourceMap?: boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Enable Vapor mode compilation
|
|
42
|
+
* @default false
|
|
43
|
+
*/
|
|
44
|
+
vapor?: boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Root directory to scan for .vue files
|
|
47
|
+
* @default Vite's root
|
|
48
|
+
*/
|
|
49
|
+
root?: string;
|
|
50
|
+
/**
|
|
51
|
+
* Glob patterns to scan for .vue files during pre-compilation
|
|
52
|
+
* @default ['**\/*.vue']
|
|
53
|
+
*/
|
|
54
|
+
scanPatterns?: string[];
|
|
55
|
+
/**
|
|
56
|
+
* Glob patterns to ignore during pre-compilation
|
|
57
|
+
* @default ['node_modules/**', 'dist/**', '.git/**']
|
|
58
|
+
*/
|
|
59
|
+
ignorePatterns?: string[];
|
|
60
|
+
}
|
|
61
|
+
export interface CompiledModule {
|
|
62
|
+
code: string;
|
|
63
|
+
css?: string;
|
|
64
|
+
scopeId: string;
|
|
65
|
+
hasScoped: boolean;
|
|
66
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { CompiledModule } from './types.js';
|
|
2
|
+
export declare function generateScopeId(filename: string): string;
|
|
3
|
+
export declare function createFilter(include?: string | RegExp | (string | RegExp)[], exclude?: string | RegExp | (string | RegExp)[]): (id: string) => boolean;
|
|
4
|
+
export declare function generateOutput(compiled: CompiledModule, isProduction: boolean, isDev: boolean): string;
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
export function generateScopeId(filename) {
|
|
3
|
+
const hash = createHash('sha256').update(filename).digest('hex');
|
|
4
|
+
return hash.slice(0, 8);
|
|
5
|
+
}
|
|
6
|
+
export function createFilter(include, exclude) {
|
|
7
|
+
const includePatterns = include
|
|
8
|
+
? Array.isArray(include)
|
|
9
|
+
? include
|
|
10
|
+
: [include]
|
|
11
|
+
: [/\.vue$/];
|
|
12
|
+
const excludePatterns = exclude
|
|
13
|
+
? Array.isArray(exclude)
|
|
14
|
+
? exclude
|
|
15
|
+
: [exclude]
|
|
16
|
+
: [/node_modules/];
|
|
17
|
+
return (id) => {
|
|
18
|
+
const matchInclude = includePatterns.some((pattern) => typeof pattern === 'string' ? id.includes(pattern) : pattern.test(id));
|
|
19
|
+
const matchExclude = excludePatterns.some((pattern) => typeof pattern === 'string' ? id.includes(pattern) : pattern.test(id));
|
|
20
|
+
return matchInclude && !matchExclude;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
export function generateOutput(compiled, isProduction, isDev) {
|
|
24
|
+
let output = compiled.code;
|
|
25
|
+
// Rewrite "export default" to named variable for HMR
|
|
26
|
+
const hasExportDefault = output.includes('export default');
|
|
27
|
+
if (hasExportDefault) {
|
|
28
|
+
output = output.replace('export default', 'const _sfc_main =');
|
|
29
|
+
output += '\nexport default _sfc_main;';
|
|
30
|
+
}
|
|
31
|
+
// Inject CSS
|
|
32
|
+
if (compiled.css) {
|
|
33
|
+
const cssCode = JSON.stringify(compiled.css);
|
|
34
|
+
const cssId = JSON.stringify(`vize-style-${compiled.scopeId}`);
|
|
35
|
+
output = `
|
|
36
|
+
const __vize_css__ = ${cssCode};
|
|
37
|
+
const __vize_css_id__ = ${cssId};
|
|
38
|
+
(function() {
|
|
39
|
+
if (typeof document !== 'undefined') {
|
|
40
|
+
let style = document.getElementById(__vize_css_id__);
|
|
41
|
+
if (!style) {
|
|
42
|
+
style = document.createElement('style');
|
|
43
|
+
style.id = __vize_css_id__;
|
|
44
|
+
style.textContent = __vize_css__;
|
|
45
|
+
document.head.appendChild(style);
|
|
46
|
+
} else {
|
|
47
|
+
style.textContent = __vize_css__;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
})();
|
|
51
|
+
${output}`;
|
|
52
|
+
}
|
|
53
|
+
// Add HMR support in development
|
|
54
|
+
if (!isProduction && isDev && hasExportDefault) {
|
|
55
|
+
output += `
|
|
56
|
+
if (import.meta.hot) {
|
|
57
|
+
_sfc_main.__hmrId = ${JSON.stringify(compiled.scopeId)};
|
|
58
|
+
import.meta.hot.accept((mod) => {
|
|
59
|
+
if (!mod) return;
|
|
60
|
+
const { default: updated } = mod;
|
|
61
|
+
if (typeof __VUE_HMR_RUNTIME__ !== 'undefined') {
|
|
62
|
+
__VUE_HMR_RUNTIME__.reload(_sfc_main.__hmrId, updated);
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
if (typeof __VUE_HMR_RUNTIME__ !== 'undefined') {
|
|
66
|
+
__VUE_HMR_RUNTIME__.createRecord(_sfc_main.__hmrId, _sfc_main);
|
|
67
|
+
}
|
|
68
|
+
}`;
|
|
69
|
+
}
|
|
70
|
+
return output;
|
|
71
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vizejs/vite-plugin",
|
|
3
|
+
"version": "0.0.1-alpha.8",
|
|
4
|
+
"description": "High-performance native Vite plugin for Vue SFC compilation powered by Vize",
|
|
5
|
+
"publishConfig": {
|
|
6
|
+
"provenance": false,
|
|
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
|
+
"scripts": {
|
|
19
|
+
"build": "tsc",
|
|
20
|
+
"dev": "tsc --watch"
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist"
|
|
24
|
+
],
|
|
25
|
+
"keywords": [
|
|
26
|
+
"vite",
|
|
27
|
+
"vue",
|
|
28
|
+
"plugin",
|
|
29
|
+
"sfc",
|
|
30
|
+
"compiler",
|
|
31
|
+
"native",
|
|
32
|
+
"fast"
|
|
33
|
+
],
|
|
34
|
+
"license": "MIT",
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"@vizejs/native": "workspace:*",
|
|
37
|
+
"tinyglobby": "^0.2.0"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@types/node": "^22.0.0",
|
|
41
|
+
"typescript": "~5.6.0",
|
|
42
|
+
"vite": "^7.3.1"
|
|
43
|
+
},
|
|
44
|
+
"peerDependencies": {
|
|
45
|
+
"vite": "^5.0.0 || ^6.0.0 || ^7.0.0"
|
|
46
|
+
}
|
|
47
|
+
}
|