18
Build a typescript component library with Vite
Example repo at: https://github.com/josip2312/typescript-lib-vite
Vite ships with a pre-configured build command that has many performance optimizations out of the box. It uses Rollup under the hood and provides an abstraction over the default rollup configuration. This makes it way easier to set up the build step without knowing all the internals of rollup.
For the sake of the example, I'm going to create a simple button component, but the build step remains the same for any number of components. In this example, I'm using the <script setup>
syntax.
Component code:
<script setup lang="ts">
import { reactive } from "vue";
interface Props {
primary?: boolean;
}
const props = withDefaults(defineProps<Props>(), {
primary: false,
});
const { primary } = reactive(props);
</script>
<template>
<button class="btn" :class="{ primary }">
<slot />
</button>
</template>
<style scoped>
.btn {
padding: 0.5rem 1rem;
}
.btn.primary {
background: hsl(239, 100%, 27%);
color: #fff;
}
</style>
Next, I'm going to create the entry file for the library where all the components will be exported.
// src/index.ts
export { default as MyButton } from "./MyButton";
Vite is a fast new build tool that is intended for modern web projects. It uses native ES modules and provides a blazing-fast dev server and hot module replacement. Learn more about it on the official website.
Vite is framework agnostic which means you can use it with most frontend frameworks, and the build config is pretty much the same. There is a section on the official website which describes different build modes, our interest is in the library mode build.
So we need to add the following to our vite.config.ts
(or .js
).
// vite.config.ts
const path = require("path");
const { defineConfig } = require("vite");
module.exports = defineConfig({
build: {
lib: {
entry: path.resolve(__dirname, "src/index.ts"),
name: "MyComponentLib",
fileName: (format) => `my-component-lib.${format}.js`,
},
rollupOptions: {
// make sure to externalize deps that shouldn't be bundled
// into your library
external: ["vue"],
output: {
// Provide global variables to use in the UMD build
// for externalized deps
globals: {
vue: "Vue",
},
},
},
},
});
If you now run npm run build
you should get the output in the dist
folder.
If you're getting an error regarding
__dirname
orpath
you need to install node type declarations
npm i -D @types/node
Before testing our build output we need to configure the package.json
to point at correct built files. We are defining the entry point to the library.
You can learn more about what each option does by hovering the properties in VS Code.
// "my-component-lib" should match the "name" field in your package.json
{
"files": ["dist"],
"main": "./dist/my-component-lib.umd.js",
"module": "./dist/my-component-lib.es.js",
"exports": {
".": {
"import": "./dist/my-component-lib.es.js",
"require": "./dist/my-component-lib.umd.js"
}
}
}
To test the library locally we can zip the dist file, before running the below change the name
field in your package.json
to your preferred library name.
Run the following:
npm pack
This command provides us with a zipped file that we can map to the library dependency in the package.json
. After running this add the following to the dependencies
field:
"dependencies": {
"my-component-lib": "my-component-lib-0.0.0.tgz"
},
After importing the library it should now work.
If you run into dependency errors try deleting the zipped file and packing it again, or deleting the
package.lock.json
andnode_modules
and runningnpm install
again.
<script setup lang="ts">
import { MyButton } from "my-component-lib";
import "/node_modules/my-component-lib/dist/style.css";
</script>
However, you'll notice we get an error regarding missing declaration files, we will solve this in the next step.
To solve the typescript declarations error, we need to generate type declaration files for the components. We will do this using the vue-tsc
package.
Make sure to update
vue-tsc
to a newer version since thecreate-vue
CLI defaults to an older version.
You need to add the following to tsconfig.json
:
{
"outDir": "dist",
"declaration": true
}
Change the build script to the following:
{
"build": "vite build && vue-tsc --emitDeclarationOnly && mv dist/src dist/types"
}
Lastly, set the path for the type declarations inside package.json
{
"types": "./dist/types/index.d.ts"
}
The last command in the build script moves the types to a types
directory, by default they would be in a src
directory since that is our target inside the tsconfig
.
If you now repeat the build and pack process, the type error should not be there.
If it's still there try deleting your
node_modules
andpackage.lock.json
and installing the packages again.
Everything is already set up for publishing, you can just authenticate with npm and publish.
npm login # authenticate
npm publish # publish
Vite makes it incredibly easy to build a component library with a very slim config. Coupled with the amazing development experience it provides I can conclude it is the next big thing in frontend development.
18