You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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. 重新构建并验证

  1. 执行pnpm build重新构建组件库
  2. 更新Nuxt项目中的组件库依赖
  3. 启动Nuxt项目,检查SSR是否正常运行

内容的提问来源于stack exchange,提问作者Danilo Ribeiro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 01:50:03