Vite构建的组件库Vue3正常,Nuxt3报createElement未定义错误
问题描述
我用Vite构建了一个组件库,在Vue 3项目中运行正常,但在Nuxt 3项目中使用时出现以下错误:
[nuxt] [request error] [unhandled] [500] Cannot read properties of undefined (reading 'createElement')
注:我的代码中并未直接使用createElement。禁用SSR后组件库可正常运行。
组件库vite.config.ts配置
import vue from '@vitejs/plugin-vue'; import path from 'path'; import typescript2 from 'rollup-plugin-typescript2'; import { defineConfig } from 'vite'; import cssInjectedByJsPlugin from 'vite-plugin-css-injected-by-js'; import dts from 'vite-plugin-dts'; export default defineConfig({ plugins: [ vue(), dts({ insertTypesEntry: true, }), cssInjectedByJsPlugin(), typescript2({ check: false, include: ['src/components/**/*.vue'], tsconfigOverride: { compilerOptions: { outDir: 'dist', sourceMap: true, declaration: true, declarationMap: true, }, }, exclude: ['vite.config.ts'], }), ], build: { cssCodeSplit: true, lib: { entry: path.resolve(__dirname, 'src/lib-components/index.ts'), name: 'MyDesignSystemExample', formats: ['es', 'cjs', 'umd'], fileName: (format) => `design-system-ui.${format}.js`, }, rollupOptions: { input: { main: path.resolve(__dirname, 'src/main.ts'), }, external: ['vue'], output: { assetFileNames: (assetInfo) => { if (assetInfo.name === 'main.css') return 'design-system-ui.css'; return assetInfo.name; }, exports: 'named', globals: { vue: 'Vue', }, }, }, }, server: { port: 8080, }, resolve: { alias: { '@': path.resolve(__dirname, 'src'), }, dedupe: ['vue'], }, });
组件库package.json配置
{ "name": "my-design-system-example", "version": "1.0.0", "description": "Design System", "type": "module", "files": [ "dist", "src/**/*.vue" ], "main": "./dist/design-system-ui.umd.js", "module": "./dist/design-system-ui.es.js", "exports": { ".": { "types": "./dist/main.d.ts", "import": "./dist/design-system-ui.umd.js", "require": "./dist/design-system-ui.es.js" }, "./dist/design-system-ui.css": { "import": "./dist/design-system-ui.css", "require": "./dist/design-system-ui.css" } }, "scripts": { "preinstall": "npx -y only-allow pnpm", "dev": "vite", "build": "rm -rf dist && vue-tsc && vite build", "preview": "vite preview", "lint": "eslint --ext .ts,vue --ignore-path .gitignore .", "format": "prettier -w -u . !./pnpm-lock.yaml", "save": "npm version patch --force", "version": "npm run build && git add .", "postversion": "git push && git push --tags && npm publish" }, // ... }
组件库main.ts代码
import './tailwind.css'; import type { App, Component } from 'vue'; import * as components from '@/lib-components'; type ComponentType = Component & { _name: string; }; export default { install: (app: App) => { for (const key in components) { const componentsObject = components as unknown as Record<string, ComponentType>; app.component( componentsObject[key].name ?? componentsObject[key]._name, componentsObject[key] ); } }, }; export * from './lib-components';
Nuxt项目nuxt.config.ts配置
export default defineNuxtConfig({ modules: [ '@nuxtjs/tailwindcss', '@pinia/nuxt', '@pinia-plugin-persistedstate/nuxt', ], devServer: { port: 8080, }, build: { transpile: ['my-design-system-example'], }, });
解决方案
问题根源
该错误是因为组件库的构建配置未适配SSR场景,或组件在服务端渲染时访问了浏览器专属API,导致Vue服务端渲染环境中无法找到内部依赖的createElement方法。
具体修复步骤
1. 修正package.json的exports映射错误
你当前的exports字段把import和require的指向搞反了,ES模块应该对应import,CommonJS模块对应require:
"exports": { ".": { "types": "./dist/main.d.ts", "import": "./dist/design-system-ui.es.js", "require": "./dist/design-system-ui.umd.js" }, "./dist/design-system-ui.css": { "import": "./dist/design-system-ui.css", "require": "./dist/design-system-ui.css" } },
2. 调整Vite构建配置适配SSR
移除rollupOptions中多余的input配置(库入口已通过lib.entry指定),避免混淆构建逻辑:
build: { cssCodeSplit: true, lib: { entry: path.resolve(__dirname, 'src/lib-components/index.ts'), name: 'MyDesignSystemExample', formats: ['es', 'cjs', 'umd'], fileName: (format) => `design-system-ui.${format}.js`, }, rollupOptions: { // 移除多余的input配置 external: ['vue'], output: { assetFileNames: (assetInfo) => { if (assetInfo.name === 'main.css') return 'design-system-ui.css'; return assetInfo.name; }, exports: 'named', globals: { vue: 'Vue', }, }, }, },
3. 移除CSS注入插件(可选)
cssInjectedByJsPlugin会将CSS嵌入JS,在SSR环境中可能导致样式渲染异常,建议改为单独输出CSS,然后在Nuxt中手动引入:
- 从vite.config.ts的plugins数组中移除
cssInjectedByJsPlugin() - 在Nuxt项目的
app.vue或nuxt.config.ts的head中引入组件库CSS:
// nuxt.config.ts export default defineNuxtConfig({ // ...其他配置 app: { head: { link: [{ rel: 'stylesheet', href: '/node_modules/my-design-system-example/dist/design-system-ui.css' }] } } });
4. 确保组件支持SSR
检查组件库中的所有组件:
- 不要在
setup、created等服务端会执行的钩子中访问window、document等浏览器API,如需使用,放在onMounted钩子中,或通过process.client判断环境:
// 示例:仅在客户端执行浏览器相关逻辑 if (process.client) { // 访问window或document的代码 }
- 避免在模板中使用仅浏览器支持的DOM特性
5. 重新构建并验证
- 执行
pnpm build重新构建组件库 - 更新Nuxt项目中的组件库依赖
- 启动Nuxt项目,检查SSR是否正常运行
内容的提问来源于stack exchange,提问作者Danilo Ribeiro
相关产品推荐
相关产品推荐

