11import vue from '@vitejs/plugin-vue'
22import dotenv from 'dotenv'
33import path from 'path'
4+ import type { OutputOptions } from 'rollup'
45import IconsResolver from 'unplugin-icons/resolver'
56import Icons from 'unplugin-icons/vite'
67import Components from 'unplugin-vue-components/vite'
7- import { Plugin , defineConfig } from 'vite'
8+ import { HtmlTagDescriptor , Plugin , defineConfig } from 'vite'
89import type { UserConfigExport } from 'vitest/config'
910
1011dotenv . config ( )
@@ -26,6 +27,160 @@ function isLegacyFile(id: string): boolean {
2627 )
2728}
2829
30+ /**
31+ * Vite plugin that adds an alias export for Vue's createBaseVNode as createElementVNode.
32+ *
33+ * This plugin addresses compatibility issues where some components or libraries
34+ * might be using the older createElementVNode function name instead of createBaseVNode.
35+ * It modifies the Vue vendor chunk during build to add the alias export.
36+ *
37+ * @returns {Plugin } A Vite plugin that modifies the Vue vendor chunk exports
38+ */
39+ function addElementVnodeExportPlugin ( ) : Plugin {
40+ return {
41+ name : 'add-element-vnode-export-plugin' ,
42+
43+ renderChunk ( code , chunk , _options ) {
44+ if ( chunk . name . startsWith ( 'vendor-vue' ) ) {
45+ const exportRegex = / ( e x p o r t \s * \{ ) ( [ ^ } ] * ) ( \} \s * ; ? \s * ) $ /
46+ const match = code . match ( exportRegex )
47+
48+ if ( match ) {
49+ const existingExports = match [ 2 ] . trim ( )
50+ const exportsArray = existingExports
51+ . split ( ',' )
52+ . map ( ( e ) => e . trim ( ) )
53+ . filter ( Boolean )
54+
55+ const hasCreateBaseVNode = exportsArray . some ( ( e ) =>
56+ e . startsWith ( 'createBaseVNode' )
57+ )
58+ const hasCreateElementVNode = exportsArray . some ( ( e ) =>
59+ e . includes ( 'createElementVNode' )
60+ )
61+
62+ if ( hasCreateBaseVNode && ! hasCreateElementVNode ) {
63+ const newExportStatement = `${ match [ 1 ] } ${ existingExports ? existingExports + ',' : '' } createBaseVNode as createElementVNode ${ match [ 3 ] } `
64+ const newCode = code . replace ( exportRegex , newExportStatement )
65+
66+ console . log (
67+ `[add-element-vnode-export-plugin] Added 'createBaseVNode as createElementVNode' export to vendor-vue chunk.`
68+ )
69+
70+ return { code : newCode , map : null }
71+ } else if ( ! hasCreateBaseVNode ) {
72+ console . warn (
73+ `[add-element-vnode-export-plugin] Warning: 'createBaseVNode' not found in exports of vendor-vue chunk. Cannot add alias.`
74+ )
75+ }
76+ } else {
77+ console . warn (
78+ `[add-element-vnode-export-plugin] Warning: Could not find expected export block format in vendor-vue chunk.`
79+ )
80+ }
81+ }
82+
83+ return null
84+ }
85+ }
86+ }
87+
88+ /**
89+ * Vite plugin that generates an import map for vendor chunks.
90+ *
91+ * This plugin creates a browser-compatible import map that maps module specifiers
92+ * (like 'vue' or 'primevue') to their actual file locations in the build output.
93+ * This improves module loading in modern browsers and enables better caching.
94+ *
95+ * The plugin:
96+ * 1. Tracks vendor chunks during bundle generation
97+ * 2. Creates mappings between module names and their file paths
98+ * 3. Injects an import map script tag into the HTML head
99+ * 4. Configures manual chunk splitting for vendor libraries
100+ *
101+ * @param vendorLibraries - An array of vendor libraries to split into separate chunks
102+ * @returns {Plugin } A Vite plugin that generates and injects an import map
103+ */
104+ function generateImportMapPlugin (
105+ vendorLibraries : { name : string ; pattern : string } [ ]
106+ ) : Plugin {
107+ const importMapEntries : Record < string , string > = { }
108+
109+ return {
110+ name : 'generate-import-map-plugin' ,
111+
112+ // Configure manual chunks during the build process
113+ configResolved ( config ) {
114+ if ( config . build ) {
115+ // Ensure rollupOptions exists
116+ if ( ! config . build . rollupOptions ) {
117+ config . build . rollupOptions = { }
118+ }
119+
120+ const outputOptions : OutputOptions = {
121+ manualChunks : ( id : string ) => {
122+ for ( const lib of vendorLibraries ) {
123+ if ( id . includes ( lib . pattern ) ) {
124+ return `vendor-${ lib . name } `
125+ }
126+ }
127+ return null
128+ } ,
129+ // Disable minification of internal exports to preserve function names
130+ minifyInternalExports : false
131+ }
132+ config . build . rollupOptions . output = outputOptions
133+ }
134+ } ,
135+
136+ generateBundle ( _options , bundle ) {
137+ for ( const fileName in bundle ) {
138+ const chunk = bundle [ fileName ]
139+ if ( chunk . type === 'chunk' && ! chunk . isEntry ) {
140+ // Find matching vendor library by chunk name
141+ const vendorLib = vendorLibraries . find (
142+ ( lib ) => chunk . name === `vendor-${ lib . name } `
143+ )
144+
145+ if ( vendorLib ) {
146+ const relativePath = `./${ chunk . fileName . replace ( / \\ / g, '/' ) } `
147+ importMapEntries [ vendorLib . name ] = relativePath
148+
149+ console . log (
150+ `[ImportMap Plugin] Found chunk: ${ chunk . name } -> Mapped '${ vendorLib . name } ' to '${ relativePath } '`
151+ )
152+ }
153+ }
154+ }
155+ } ,
156+
157+ transformIndexHtml ( html ) {
158+ if ( Object . keys ( importMapEntries ) . length === 0 ) {
159+ console . warn (
160+ '[ImportMap Plugin] No vendor chunks found to create import map.'
161+ )
162+ return html
163+ }
164+
165+ const importMap = {
166+ imports : importMapEntries
167+ }
168+
169+ const importMapTag : HtmlTagDescriptor = {
170+ tag : 'script' ,
171+ attrs : { type : 'importmap' } ,
172+ children : JSON . stringify ( importMap , null , 2 ) ,
173+ injectTo : 'head'
174+ }
175+
176+ return {
177+ html,
178+ tags : [ importMapTag ]
179+ }
180+ }
181+ }
182+ }
183+
29184function comfyAPIPlugin ( ) : Plugin {
30185 return {
31186 name : 'comfy-api-plugin' ,
@@ -110,7 +265,7 @@ export default defineConfig({
110265 target : DEV_SERVER_COMFYUI_URL ,
111266 // Return empty array for extensions API as these modules
112267 // are not on vite's dev server.
113- bypass : ( req , res , options ) => {
268+ bypass : ( req , res , _options ) => {
114269 if ( req . url === '/api/extensions' ) {
115270 res . end ( JSON . stringify ( [ ] ) )
116271 }
@@ -137,6 +292,11 @@ export default defineConfig({
137292 plugins : [
138293 vue ( ) ,
139294 comfyAPIPlugin ( ) ,
295+ generateImportMapPlugin ( [
296+ { name : 'vue' , pattern : 'node_modules/vue/' } ,
297+ { name : 'primevue' , pattern : 'node_modules/primevue/' }
298+ ] ) ,
299+ addElementVnodeExportPlugin ( ) ,
140300
141301 Icons ( {
142302 compiler : 'vue3'
0 commit comments