I am trying to create a UI library which stores components and exports them to be used in multiple projects. Some components render without any issues, however, some components will not render and receive either of the following errors:
[Vue warn]: Invalid VNode type: Symbol(Fragment) (symbol)
[Vue warn]: Invalid VNode type: Symbol(Comment) (symbol)
After looking into this, I understand that this error may be caused due to multiple instances of Vue (see resources at the bottom) - None of these fixes seem to work.
This is my process to export a component via NPM packages:
Export components
export.js
import Paragraph from "./stories/Paragraph/Paragraph.vue";
import Title from "./stories/Title/Title.vue";
export {
Paragraph,
Title,
};
vite.config
import path from "path";
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
export default (args) => {
const isProduction = args.mode === "production";
return defineConfig({
root: "src",
server: {
port: 3000,
},
build: {
sourcemap: true,
outDir: "../dist",
lib: {
entry: path.resolve(__dirname, "/export.js"),
name: "[PACKAGE_NAME]",
},
},
rollupOptions: {
external: ["vue"],
output: {
globals: {
vue: "Vue",
},
},
},
css: {
modules: {
localsConvention: "camelCase",
generateScopedName: isProduction ? "[hash:base64:6]" : "[local]_[hash:base64:2]",
},
},
plugins: [vue()],
});
};
package.json
"type": "module",
"main": "./dist/[PACKAGE_NAME].js",
"module": "./dist/[PACKAGE_NAME].umd.cjs",
"style": "./dist/style.css",
"exports": {
".": {
"import": "./dist/[PACKAGE_NAME].js",
"require": "./dist/[PACKAGE_NAME].umd.cjs"
}
},
"files": [
"dist/*",
"src/*"
],
"scripts": {
"build": "vite build",
},
"peerDependencies": {
"vue": "^3.2.45"
},
Build and publish
pnpm run build
npm publish
Title.vue
<script setup>
import titleCss from "./title.module.css";
import { requiredString } from "../../utils/propConstants";
const props = defineProps({
text: requiredString,
});
</script>
<template>
<h3 :class="titleCss.pageTitle">{{ props.text }}</h3>
</template>
Paragraph.vue
<script setup>
import paragraphCss from "./paragraph.module.css";
import { optionalString, requiredArray } from "../../utils/propConstants";
const props = defineProps({
paragraphs: requiredArray,
smallPrint: optionalString,
});
</script>
<template>
<div :class="paragraphCss.pageParagraph">
<p v-for="(paragraph, i) in props.paragraphs" :key="i">
{{ paragraph }}
</p>
<p v-if="props.smallPrint" :class="paragraphCss.smallPrint">
{{ props.smallPrint }}
</p>
</div>
</template>
Import the component
import { Video, Title, Paragraph } from "[PACKAGE_NAME]";
...
<Title :text="'Test Title'" /> <!-- WORKS FINE -->
<Paragraph :paragraphs="paragraphs" :smallPrint="smallPrint" /> <!-- ERROR -->
Additional Info
I notice that Invalid VNode type: Symbol(Comment)
shows when there is a v-if
present inside the code which hides some of the template... then once I remove the v-if
the error then shows Invalid VNode type: Symbol(Fragment) (symbol)
Resources
- Almost identical issue, fix didn't work: Vue 3 Invalid VNode type
- https://vitejs.dev/guide/build.html#library-mode