import { defineConfig } from 'vite'; import dts from 'vite-plugin-dts'; import { resolve } from 'path'; import cssInjectedByJs from 'vite-plugin-css-injected-by-js'; import pkg from './package.json'; import type { Plugin } from 'rollup'; /** * 修复 webpack 5 / Next.js 兼容性问题 * * Vite 在 lib 模式下构建 ESM 产物时,会将内联的 data URL 资源包装为 * `new URL("data:...", import.meta.url).href` 格式。 * * 当 Next.js 14 (webpack 5) 消费这个 ESM 产物时,webpack 5 的 asset module * 系统会尝试处理 `new URL(..., import.meta.url)`,但 Next.js 内部的默认规则 * 对 `asset/inline` 类型配置了不兼容的 `filename` generator,导致 schema * validation 报错: * "generator has an unknown property 'filename'. These properties are valid: * object { dataUrl? }" * * 此插件在输出阶段将 `new URL("data:...", import.meta.url).href` 替换为直接的 * data URL 字符串,避免触发 webpack 的 asset module 处理逻辑。 * * data URL 本身是绝对的,不需要 import.meta.url 作为 base,因此这种替换是安全的。 */ const fixWebpack5CompatPlugin = (): Plugin => ({ name: 'fix-webpack5-compat', renderChunk(code) { // 匹配 new URL("data:...", import.meta.url).href 或 new URL('data:...', import.meta.url).href const fixed = code.replace( /new URL\(["'](data:[^"']+)["'],\s*import\.meta\.url\)\.href/g, '"$1"' ); if (fixed !== code) { console.log('[fix-webpack5-compat] Replaced new URL(data:..., import.meta.url) with direct data URL'); } return { code: fixed, map: null, }; }, }); export default defineConfig(() => { return { plugins: [ // 移除 Vue 插件 dts({ include: ['src'], exclude: [ 'src/**/*.es.js', '**/*.es.js' ], rollupTypes: false, logLevel: 'warn', // 只显示警告和错误 }), cssInjectedByJs() ], // 开发服务器配置 server: { port: 3000, host: '0.0.0.0', open: '/demo/index.html', allowedHosts: true, }, define: { __APP_VERSION__: JSON.stringify(pkg.version), }, build: { lib: { entry: resolve(__dirname, 'src/index.ts'), name: 'IflowEngine', fileName: (format) => `iflow-engine.${format}.js`, }, rollupOptions: { external: ['opentype.js'], output: { globals: { 'opentype.js': '{}', }, // 禁用代码分割,将所有代码打包到一个文件 inlineDynamicImports: true, }, plugins: [ fixWebpack5CompatPlugin(), ], }, sourcemap: true, emptyOutDir: true, }, }; });