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, }, }; });