What is the process of including types in a Vite library build?

After following the documentation on Vite for implementing library mode, I successfully created a functional component library.
Utilizing the vue-ts preset, I defined props with their respective types and utilized interfaces within my components. However, upon building the library, I noticed that the types were not included.

How can I incorporate types into the final build, either by automatically inferring them from components or manually creating definition files?

Additional Details: Here is some context regarding 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 tried adding the emitDeclarationOnly and declaration properties, but they did not resolve the issue.

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()],
});

Answer №1

If you need to generate declaration files for Vite, consider using the vite-plugin-dts plugin.

import dts from "vite-plugin-dts";

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

Answer №2

In my opinion, a more elegant solution would be to utilize vue-tsc:

vue-tsc --declaration --emitDeclarationOnly

You can find more information at

Answer №3

When working on a project with vite and typescript, it's important to include type checking before the build process, as vite doesn't handle it automatically. I've followed Julien Kode's advice by using vite-plugin-dts and for type checking, I'm utilizing rollup-plugin-typescript2.

Below is my version of 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: {
            external: [
                'vue',
                'vue-class-component',
                'vue-property-decorator',
                'vuex',
                'vuex-class',
            ],
            output: {
                globals: {
                    vue: 'Vue',
                },
            },
         },
      },
    });
 

Answer №4

If you want to achieve this, one option is to create your own custom Vite plugin that utilizes the tsc tool during the buildEnd phase. This approach has been recommended by other responses and involves using the emitDeclarationOnly flag.

Here is a basic example to guide you:

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()));
      });
    }
  },
};

Don't forget to include this plugin in the plugins section of your Vite configuration file.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

"If you use jQuery.inArray, you can always expect it to return

My current shopping list is displayed below: To allow the user to delete a product from thelist by clicking on a trash can icon, I have implemented the following code: $(document).ready(function() { var selectedproducts = new Array(); //List of select ...

Cypress fails to log requests in the Command Log

I'm having trouble intercepting requests to the Backend using Cypress. Strangely, I can't see some of the XHR requests in the DevTools, even though they are there. To help illustrate the issue, I've included a screenshot with arrows. https:/ ...

Failure to prompt for authentication when accessing secure URLs via the $.ajax function

Whenever I work remotely, accessing URLs for our development servers always requires basic authentication. This means that every time a web page includes a script or link tag pointing to our development server, we encounter an authentication prompt. Recen ...

Encountering issues with innerHTML displaying undefined results while trying to retrieve and showcase data from a database through the use

This is a sample script for fetching data from a database using AJAX. <!DOCTYPE html> <html> <head> <script type="text/javascript"> function loadJSON() { var data_file = "http://www.example.com/data/connect.php"; var xmlhttp; ...

JavaScript for Acrobat

I am currently creating a form in Adobe Acrobat and incorporating additional functionality using JavaScript. I have been searching for information on the control classes for the form, such as the member variables of a CheckBox, but haven't found any c ...

A step-by-step guide on sending a JSON string from a Controller to the success event in

Passing the string "recentlyupgraded" from the controller to the ajax success event and checking it at the ajax success event is my current objective. Here's the code in My Controller: [HttpPost] [AuthorizeEnum(UserRole.Normal, UserRole.Power)] publi ...

Change the local date and time to UTC in the format of yy:mm:dd H:M

I must change the date format from local time to UTC or ISO as yy:mm:dd H:M, or calculate the difference between local date times with 03:30 as yy:mm:dd H:M 2016-10-22T04:30:00.000Z convert this to 2016-10-22T01:00:00.000Z ...

Determine which checkbox is currently selected in Vue and send corresponding data based on the checked status

A radio form that is conditionally disabled by another checkbox. One radio button can send either true or false and the other has an input that sends some data. How can I determine which radio button is checked and decide whether to send true/false or the ...

Ways to transfer data from a component to the Vue store?

One thing I am struggling with is setting data from my component to the store. methods: { // Inside my component ...mapMutations('lists', ['setContactListName']),// Importing function from the store viewHandler ...

Tips on how to resize, position, and scale an object effectively using three.js

Recently delving into the world of three.js, I decided to experiment with importing models using the gltf loader. Upon loading a specific 3D model, my scene transformed to showcase a mesmerizing view, as depicted https://i.sstatic.net/l4jNy.png. However, ...

Tips for recognizing when the user has reached the bottom of the window

Is there a way to ensure that an action is only executed when the user scrolls down vertically, and not when they scroll from end to start? if( $(window).scrollTop() + $(window).height() == $(document).height() ) { //do stuff } This is the code I h ...

JQuery retrieves the text content without taking into account the class

I'm struggling with my code and encountering an issue fetching text while excluding the menu-list-count class which displays a value next to the text. Here's what I've attempted: var mailfolder = $(this).not('[class="menu-list-cou ...

Achieving a transparent background in WebGLRender: A guide

I've been experimenting with placing objects in front of CSS3DObjects using the THREE.NoBlending hack. However, in the latest revisions (tested on r65 and r66), I only see the black plane without the CSS3DObject. Here is a small example I created: in ...

Another option instead of using jQuery to retrieve the active element in the

My goal was to determine when the user is interacting with an INPUT or TEXTAREA element and set a flag variable to true during this engagement. Once the user clicks out of these elements, the flag should be set back to false. To achieve this, I utilized j ...

Cleve js does not include delimiters in its date output

In my Vue.js project, I decided to implement a date input field using cleave.js. After passing the following options: options="{date: true, delimiter: '/', datePattern: ['m', 'd', 'Y']}" I encountered an issue wh ...

Having trouble sending ajax requests in Node.js?

I am currently utilizing a nodejs server for my website, and I am looking to have the backend server initiate a call to an api on an external server. My initial attempt at achieving this was through the following simple and direct method: router.post(&apo ...

The error message "VueRouter does not have a property named 'history'" is common in Vue with TypeScript

In my typescript vue application, I encountered an error within a component while trying to access a parameter passed into the route. Here is the relevant code snippet: properties = getModule(PropertiesModule, this.$store); mounted() { id = this.$router. ...

Creating resizable rows of DIVs using jQuery

I'm currently developing a scheduling widget concept. The main idea is to create a row of DIVs for each day of the week. Every row consists of a set number of time periods represented by DIVs. My goal is to enable the resizing of each DIV by dragging ...

Implementing CSS loading in Vue 3's shadow DOM for nested components

I'm currently working on building an embeddable widget using a custom element with Vue. In order to achieve this, I've created a file called Widget.ce.vue and enabled style loading in the component's shadow root. However, I've run into ...

Retrieve the value of a variable by using either an HTTP GET or POST request

Here's the HTML code snippet that I'm working with: <head> <h1>Sample Page</h1> </head> <body> <form method="POST" action=""> Enter Keyword <input type="text" name="key"> ...