mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-01-26 19:09:52 +00:00
build vue and primevue separately and generate importmap (#3473)
Co-authored-by: Chenlei Hu <hcl@comfy.org>
This commit is contained in:
@@ -35,6 +35,7 @@
|
|||||||
"src/**/*.vue",
|
"src/**/*.vue",
|
||||||
"src/types/**/*.d.ts",
|
"src/types/**/*.d.ts",
|
||||||
"tests-ui/**/*",
|
"tests-ui/**/*",
|
||||||
"global.d.ts"
|
"global.d.ts",
|
||||||
|
"vite.config.mts"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
164
vite.config.mts
164
vite.config.mts
@@ -1,10 +1,11 @@
|
|||||||
import vue from '@vitejs/plugin-vue'
|
import vue from '@vitejs/plugin-vue'
|
||||||
import dotenv from 'dotenv'
|
import dotenv from 'dotenv'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
|
import type { OutputOptions } from 'rollup'
|
||||||
import IconsResolver from 'unplugin-icons/resolver'
|
import IconsResolver from 'unplugin-icons/resolver'
|
||||||
import Icons from 'unplugin-icons/vite'
|
import Icons from 'unplugin-icons/vite'
|
||||||
import Components from 'unplugin-vue-components/vite'
|
import Components from 'unplugin-vue-components/vite'
|
||||||
import { Plugin, defineConfig } from 'vite'
|
import { HtmlTagDescriptor, Plugin, defineConfig } from 'vite'
|
||||||
import type { UserConfigExport } from 'vitest/config'
|
import type { UserConfigExport } from 'vitest/config'
|
||||||
|
|
||||||
dotenv.config()
|
dotenv.config()
|
||||||
@@ -26,6 +27,160 @@ function isLegacyFile(id: string): boolean {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vite plugin that adds an alias export for Vue's createBaseVNode as createElementVNode.
|
||||||
|
*
|
||||||
|
* This plugin addresses compatibility issues where some components or libraries
|
||||||
|
* might be using the older createElementVNode function name instead of createBaseVNode.
|
||||||
|
* It modifies the Vue vendor chunk during build to add the alias export.
|
||||||
|
*
|
||||||
|
* @returns {Plugin} A Vite plugin that modifies the Vue vendor chunk exports
|
||||||
|
*/
|
||||||
|
function addElementVnodeExportPlugin(): Plugin {
|
||||||
|
return {
|
||||||
|
name: 'add-element-vnode-export-plugin',
|
||||||
|
|
||||||
|
renderChunk(code, chunk, _options) {
|
||||||
|
if (chunk.name.startsWith('vendor-vue')) {
|
||||||
|
const exportRegex = /(export\s*\{)([^}]*)(\}\s*;?\s*)$/
|
||||||
|
const match = code.match(exportRegex)
|
||||||
|
|
||||||
|
if (match) {
|
||||||
|
const existingExports = match[2].trim()
|
||||||
|
const exportsArray = existingExports
|
||||||
|
.split(',')
|
||||||
|
.map((e) => e.trim())
|
||||||
|
.filter(Boolean)
|
||||||
|
|
||||||
|
const hasCreateBaseVNode = exportsArray.some((e) =>
|
||||||
|
e.startsWith('createBaseVNode')
|
||||||
|
)
|
||||||
|
const hasCreateElementVNode = exportsArray.some((e) =>
|
||||||
|
e.includes('createElementVNode')
|
||||||
|
)
|
||||||
|
|
||||||
|
if (hasCreateBaseVNode && !hasCreateElementVNode) {
|
||||||
|
const newExportStatement = `${match[1]} ${existingExports ? existingExports + ',' : ''} createBaseVNode as createElementVNode ${match[3]}`
|
||||||
|
const newCode = code.replace(exportRegex, newExportStatement)
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
`[add-element-vnode-export-plugin] Added 'createBaseVNode as createElementVNode' export to vendor-vue chunk.`
|
||||||
|
)
|
||||||
|
|
||||||
|
return { code: newCode, map: null }
|
||||||
|
} else if (!hasCreateBaseVNode) {
|
||||||
|
console.warn(
|
||||||
|
`[add-element-vnode-export-plugin] Warning: 'createBaseVNode' not found in exports of vendor-vue chunk. Cannot add alias.`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.warn(
|
||||||
|
`[add-element-vnode-export-plugin] Warning: Could not find expected export block format in vendor-vue chunk.`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vite plugin that generates an import map for vendor chunks.
|
||||||
|
*
|
||||||
|
* This plugin creates a browser-compatible import map that maps module specifiers
|
||||||
|
* (like 'vue' or 'primevue') to their actual file locations in the build output.
|
||||||
|
* This improves module loading in modern browsers and enables better caching.
|
||||||
|
*
|
||||||
|
* The plugin:
|
||||||
|
* 1. Tracks vendor chunks during bundle generation
|
||||||
|
* 2. Creates mappings between module names and their file paths
|
||||||
|
* 3. Injects an import map script tag into the HTML head
|
||||||
|
* 4. Configures manual chunk splitting for vendor libraries
|
||||||
|
*
|
||||||
|
* @param vendorLibraries - An array of vendor libraries to split into separate chunks
|
||||||
|
* @returns {Plugin} A Vite plugin that generates and injects an import map
|
||||||
|
*/
|
||||||
|
function generateImportMapPlugin(
|
||||||
|
vendorLibraries: { name: string; pattern: string }[]
|
||||||
|
): Plugin {
|
||||||
|
const importMapEntries: Record<string, string> = {}
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: 'generate-import-map-plugin',
|
||||||
|
|
||||||
|
// Configure manual chunks during the build process
|
||||||
|
configResolved(config) {
|
||||||
|
if (config.build) {
|
||||||
|
// Ensure rollupOptions exists
|
||||||
|
if (!config.build.rollupOptions) {
|
||||||
|
config.build.rollupOptions = {}
|
||||||
|
}
|
||||||
|
|
||||||
|
const outputOptions: OutputOptions = {
|
||||||
|
manualChunks: (id: string) => {
|
||||||
|
for (const lib of vendorLibraries) {
|
||||||
|
if (id.includes(lib.pattern)) {
|
||||||
|
return `vendor-${lib.name}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
},
|
||||||
|
// Disable minification of internal exports to preserve function names
|
||||||
|
minifyInternalExports: false
|
||||||
|
}
|
||||||
|
config.build.rollupOptions.output = outputOptions
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
generateBundle(_options, bundle) {
|
||||||
|
for (const fileName in bundle) {
|
||||||
|
const chunk = bundle[fileName]
|
||||||
|
if (chunk.type === 'chunk' && !chunk.isEntry) {
|
||||||
|
// Find matching vendor library by chunk name
|
||||||
|
const vendorLib = vendorLibraries.find(
|
||||||
|
(lib) => chunk.name === `vendor-${lib.name}`
|
||||||
|
)
|
||||||
|
|
||||||
|
if (vendorLib) {
|
||||||
|
const relativePath = `./${chunk.fileName.replace(/\\/g, '/')}`
|
||||||
|
importMapEntries[vendorLib.name] = relativePath
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
`[ImportMap Plugin] Found chunk: ${chunk.name} -> Mapped '${vendorLib.name}' to '${relativePath}'`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
transformIndexHtml(html) {
|
||||||
|
if (Object.keys(importMapEntries).length === 0) {
|
||||||
|
console.warn(
|
||||||
|
'[ImportMap Plugin] No vendor chunks found to create import map.'
|
||||||
|
)
|
||||||
|
return html
|
||||||
|
}
|
||||||
|
|
||||||
|
const importMap = {
|
||||||
|
imports: importMapEntries
|
||||||
|
}
|
||||||
|
|
||||||
|
const importMapTag: HtmlTagDescriptor = {
|
||||||
|
tag: 'script',
|
||||||
|
attrs: { type: 'importmap' },
|
||||||
|
children: JSON.stringify(importMap, null, 2),
|
||||||
|
injectTo: 'head'
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
html,
|
||||||
|
tags: [importMapTag]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function comfyAPIPlugin(): Plugin {
|
function comfyAPIPlugin(): Plugin {
|
||||||
return {
|
return {
|
||||||
name: 'comfy-api-plugin',
|
name: 'comfy-api-plugin',
|
||||||
@@ -110,7 +265,7 @@ export default defineConfig({
|
|||||||
target: DEV_SERVER_COMFYUI_URL,
|
target: DEV_SERVER_COMFYUI_URL,
|
||||||
// Return empty array for extensions API as these modules
|
// Return empty array for extensions API as these modules
|
||||||
// are not on vite's dev server.
|
// are not on vite's dev server.
|
||||||
bypass: (req, res, options) => {
|
bypass: (req, res, _options) => {
|
||||||
if (req.url === '/api/extensions') {
|
if (req.url === '/api/extensions') {
|
||||||
res.end(JSON.stringify([]))
|
res.end(JSON.stringify([]))
|
||||||
}
|
}
|
||||||
@@ -137,6 +292,11 @@ export default defineConfig({
|
|||||||
plugins: [
|
plugins: [
|
||||||
vue(),
|
vue(),
|
||||||
comfyAPIPlugin(),
|
comfyAPIPlugin(),
|
||||||
|
generateImportMapPlugin([
|
||||||
|
{ name: 'vue', pattern: 'node_modules/vue/' },
|
||||||
|
{ name: 'primevue', pattern: 'node_modules/primevue/' }
|
||||||
|
]),
|
||||||
|
addElementVnodeExportPlugin(),
|
||||||
|
|
||||||
Icons({
|
Icons({
|
||||||
compiler: 'vue3'
|
compiler: 'vue3'
|
||||||
|
|||||||
Reference in New Issue
Block a user