The ultimate guide for building Vue 3 component libraries in 2023

Patrick Russ

by Patrick Russ

In the fast-paced world of web development, building reusable components can be a game-changer. Fortunately, Vue 3 and Vite have emerged as powerful tools that simplify the process of creating component libraries. In this tutorial, we'll take a closer look at how to build such a library. This will empower you to create efficient, modular, and shareable UI components. For our demonstration, we'll create a simple reusable button component that looks like this:

Button component

Prerequisites

Before diving into the tutorial, make sure you have Node.js installed. If you don't have it yet, you can find the installation instructions on the official website.

1. Set up your project

Let's kick things off by creating a new Vue 3 project using Vite. Open your terminal and run the following command:

npm create vite@latest

During project setup, you'll have the option to choose various configurations. We recommend selecting TypeScript and ESLint for better type safety and code quality. However, feel free to pick the options that suit your needs best. Once the project is created, navigate to the project directory and install the dependencies:

cd <project-name>
npm install

2. Create your first component

With your project all set up, it's time to create your very first Vue 3 component. Inside the src/components directory, create a new file named ReusableButton.vue. Here's what the code for this simple button component looks like:

<script setup lang="ts">
</script>

<template>
  <button class="button" type="button">
    <slot></slot>
  </button>
</template>

<style scoped>
.button {
  cursor: pointer;
  background-color: #555555;
  border: none;
  color: white;
  padding: 15px 32px;
  text-align: center;
  text-decoration: none;
  display: inline-block;
  font-size: 16px;
  border-radius: 6px;
}

.button:hover {
  background-color: #444444;
}
</style>

This code defines a styled button component with a slot for custom content. If you need a refresher on how to create robust Vue 3 components, you can check out this blog post.

3. Build your component library

To use your component library in other projects, you need to build it first. Vite makes this process straightforward with just a few configuration tweaks. Here are the files you need to change or add:

vite.config.ts

Update your vite.config.ts file as follows:

import { fileURLToPath, URL } from 'node:url'

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    vue(),
  ],
  build: {
    cssCodeSplit: true,
    lib: {
      entry: resolve(__dirname, 'src/index.ts'),
      name: 'component-library', // adapt to your library name
      fileName: 'component-library' // adapt to your library name
    },
    rollupOptions: {
      external: ['vue'],
      output: {
        exports: 'named',
        globals: {
          vue: 'Vue'
        }
      }
    }
  },
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url))
    }
  }
})

This configuration tells Vite how to handle your component library during development and the build process. Notably, the external option excludes Vue from the bundle since it will be provided by the consuming application. The resolve.alias option is used to resolve the @ alias, which can be used in the component library to import other components.

tsconfig.json

Update your tsconfig.json file as follows:

{
  "compilerOptions": {
    "target": "ES2020",
    "useDefineForClassFields": true,
    "module": "ESNext",
    "lib": ["ES2020", "DOM", "DOM.Iterable"],
    "skipLibCheck": true,
    "moduleResolution": "bundler",
    "allowImportingTsExtensions": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve",
    "outDir": "dist",
    "declaration": true,
    "declarationMap": true,
    "sourceMap": true,
    "esModuleInterop": true,
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"]
    },
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true,
    "forceConsistentCasingInFileNames": true
  },
  "exclude": ["src/App.vue", "src/main.ts"],
  "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue", "src/index.ts"]
}

This instructs TypeScript to

  • Output the declaration files and source maps to the dist directory.
  • Use the @ alias to resolve imports.
  • Exclude the src/App.vue and src/main.ts files from the build process.

You can safely delete the tsconfig.node.json and tsconfig.app.json files which were created during the project setup.

index.ts

Create an index.ts file inside your src directory. This file serves as the entry point of your component library, making all components and other files exported here available to the consuming application:

export { default as ReusableButton } from '@/components/ReusableButton.vue'

package.json

Finally, update or add the following sections in your package.json:

  ...
  "scripts": {
    "dev": "vite",
    "build": "run-p type-check build-only",
    "preview": "vite preview",
    "build-only": "vite build",
    "type-check": "vue-tsc --emitDeclarationOnly && tsc-alias -p tsconfig.json",
    "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
    "format": "prettier --write src/"
  },
  "type": "module",
  "files": [
    "dist"
  ],
  "main": "./dist/component-library.umd.cjs",
  "module": "./dist/component-library.js",
  "exports": {
    ".": {
      "types": "./dist/index.d.ts",
      "import": "./dist/component-library.js",
      "require": "./dist/component-library.umd.cjs"
    },
    "./index.css": "./dist/index.css"
  },
  "types": "./dist/index.d.ts",
  ...

For the tsc-alias command, which resolves aliases during the build process, make sure to install the tsc-alias package. Otherwise, the consuming application will not be able to correctly resolve the type definitions.

npm install --save-dev tsc-alias

With everything set up, you can now build your component library by running:

npm run build

The output will be placed in the dist directory.

4. Publish your component library

To share your component library with others, consider publishing it to a package registry like npm. First, ensure you have an npm account, and then run the following commands:

npm login
npm publish

5. Consume your component library

Now that your component library is published, you can consume it in other projects. Either install it via npm or by using a file path ("component-library": "file:../component-library", make sure to double-check the location). Then, import the components you need and use them in your application. Don't forget to import the index.css file as well.

<script setup lang="ts">
import { ReusableButton } from 'component-library'
import 'component-library/index.css'
</script>

<template>
  <ReusableButton>Click me</ReusableButton>
</template>

Congrats! You've successfully created, published and consumed your first Vue 3 component library!

Conclusion

Building a Vue 3 component library using Vite streamlines the process of creating and sharing reusable UI components. By following the steps outlined in this tutorial, you've learned how to create, register, and distribute your Vue components, enabling you to contribute to the Vue ecosystem and simplify development across multiple projects.

Source code

You can find the complete source code of the component library on GitHub.

If you need help with your Vue 3 component library or any other project, feel free to contact us for consultation.

More Articles

Keine Cookies, keine Probleme

Warum auf unserer Website keine Cookie-Banner zu finden sind.

Read more

How to design better APIs

15 language-agnostic, actionable tips on REST API design.

Read more

Tell us about your project

Our office

  • Wels
    Bauernstraße 11
    4600 Wels