1

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:

  1. [Vue warn]: Invalid VNode type: Symbol(Fragment) (symbol)
  2. [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

Tom
  • 59
  • 7
  • You can check what's going on in `/dist/[PACKAGE_NAME].*`, this should be obvious based on bundle size. And node_modules/PACKAGE_NAME/node_modules . I'd expect that `vue` is not bundled into dist bundles because of rollupOptions, and there's no nested node_modules/vue because of peerDependencies – Estus Flask Mar 22 '23 at 10:57
  • @EstusFlask thanks - there is no node modules generated inside `node_modules/PACKAGE_NAME` as there are no other dependencies – Tom Mar 22 '23 at 11:12

0 Answers0