Neelansh Mathur
Neelansh Mathur

Reputation: 716

How do I add types to a Vite library build?

I followed the vite documentation for using library mode and I am able to produce a working component library.
I created the project with the vue-ts preset and in my component I have defined props with their types, and used some interfaces. But when I build the library, there are no types included.

How do I add types for the final build, either inferred from components automatically or manually with definition files?

More information Here is some more information on my files:
tsconfig.json

{
  "name": "@mneelansh/test-lib",
  "private": false,
  "version": "0.0.2",
  "scripts": {
    "dev": "vite",
    "build": "vue-tsc --noEmit && vite build",
    "preview": "vite preview"
  },
  "emitDeclarationOnly": true, // testing
  "declaration": true, // testing
  "main": "./dist/lib.umd.js",
  "module": "./dist/lib.es.js",
  "types": "./dist/main.d.ts",
  "exports": {
    ".": {
      "import": "./dist/lib.es.js",
      "require": "./dist/lib.umd.js"
    },
    "./dist/style.css": "./dist/style.css"
  },
  "files": [
    "dist"
  ],
  "dependencies": {
    "@types/node": "^17.0.25",
    "vue": "^3.2.25"
  },
  "devDependencies": {
    "@vitejs/plugin-vue": "^2.3.1",
    "typescript": "^4.5.4",
    "vite": "^2.9.5",
    "vue-tsc": "^0.34.7"
  }
}

I added the emitDeclarationOnly and declaration properties but that didn't help.

My vite.config.ts:

import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";

const path = require("path");

// https://vitejs.dev/config/
export default defineConfig({
  build: {
    lib: {
      entry: path.resolve(__dirname, "src/index.ts"),
      name: "Button",
      fileName: (format) => `lib.${format}.js`,
    },
    rollupOptions: {
      external: ["vue"],
      output: {
        globals: {
          vue: "Vue",
        },
      },
    },
  },
  plugins: [vue()],
});

Upvotes: 45

Views: 48445

Answers (4)

Regan Karlewicz
Regan Karlewicz

Reputation: 206

You could write your own Vite plugin to leverage tsc at the buildEnd step to accomplish this. As other answers have suggested, you can use the flag emitDeclarationOnly.

See this simple example:

import { type Plugin } from 'vite';
import { exec } from 'child_process';

const dts: Plugin = {
  name: 'dts-generator',
  buildEnd: (error?: Error) => {
    if (!error) {
      return new Promise((res, rej) => {
        exec('tsc --emitDeclarationOnly', (err) => (err ? rej(err) : res()));
      });
    }
  },
};

Then add to your plugins field of your vite config

Upvotes: 3

BaronVonKaneHoffen
BaronVonKaneHoffen

Reputation: 1990

Personally I think a nicer way to do it is with vue-tsc:

vue-tsc --declaration --emitDeclarationOnly

See https://stackoverflow.com/a/70343443/398287

Upvotes: 4

Joyful
Joyful

Reputation: 1247

Usually with vite and typescript project you need add type checking before build, because vite doesn't do it by himself. Here I'm also using vite-plugin-dts as in post from Julien Kode, and for type checking rollup-plugin-typescript2.

Finally my vite.config.js:

import { defineConfig } from 'vite';
import Vue from '@vitejs/plugin-vue2';
import dts from 'vite-plugin-dts';
import rollupTs from 'rollup-plugin-typescript2';

export default defineConfig({
    plugins: [
        Vue(),
        dts({ insertTypesEntry: true }),
        // only for type checking
        {
            ...rollupTs({
                check: true,
                tsconfig: './tsconfig.json',
                tsconfigOverride: {
                    noEmits: true,
                },
            }),
            // run before build
            enforce: 'pre',
        },
    ],
    build: {
        sourcemap: true,
        lib: {
            entry: './src/index.ts',
            fileName: 'index',
        },
        rollupOptions: {
            // make sure to externalize deps that shouldn't be bundled
            // into your library
            external: [
                'vue',
                'vue-class-component',
                'vue-property-decorator',
                'vuex',
                'vuex-class',
            ],
            output: {
                // Provide global variables to use in the UMD build
                // for externalized deps
                globals: {
                    vue: 'Vue',
                },
            },
        },
    },
});

Upvotes: 4

Julien Kode
Julien Kode

Reputation: 5479

You can use vite-plugin-dts

import dts from "vite-plugin-dts";

export default defineConfig({
  plugins: [
    dts({
      insertTypesEntry: true,
    }),
  ],

Upvotes: 41

Related Questions