Tips for distributing a Vue plugin on NPM

I developed a straightforward plugin for Voca.js using Typescript. The source code can be found here.

index.ts

import VueVoca from './vue-voca';
export {
    VueVoca
};

vue-voca.ts

import vue from 'vue';

export default {
  install(Vue: typeof vue) {
    Vue.prototype.$voca = require('voca');
  }
};

vue.d.ts

import Vue from 'vue';
import vc from 'voca';
declare module 'vue/types/vue' {
  export interface Vue {
    $voca: vc.VocaStatic;
  }
}

To create an npm package, I used the following command

vue-cli-service build --name vue-voca --entry ./src/index.ts --target lib
and npm pack.

package.json

{
  "name": "vue-voca",
  "version": "1.0.0",
  "private": false,
  "scripts": {
    "serve": "vue-cli-service serve ./example/main.ts --open",
    "build": "vue-cli-service build --name vue-voca --entry ./src/index.ts --target lib",
    "prepublishOnly": "npm run build"
  },
  "dependencies": {
    "@types/voca": "^1.4.0",
    "voca": "^1.4.0",
    "vue": "^2.6.7"
  },
  "devDependencies": {
    "@vue/cli-plugin-typescript": "^3.4.1",
    "@vue/cli-service": "^3.4.1",
    "fibers": "^3.1.1",
    "sass": "^1.17.2",
    "sass-loader": "^7.1.0",
    "typescript": "^3.3.3333",
    "vue-cli-plugin-component": "^1.10.5",
    "vue-template-compiler": "^2.6.7"
  },
  "files": [
    "dist/*.css",
    "dist/*.map",
    "dist/*.js",
    "src/*"
  ],
  "keywords": [
    "vue",
    "component"
  ],
  "types": "src/vue.d.ts",
  "typings": "src/vue.d.ts",
  "main": "dist/vue-services.umd.js",
  "module": "dist/vue-services.common.js"
}

tsconfig

{
  "compilerOptions": {
    "target": "es5",
    "module": "esnext",
    "strict": true,
    "jsx": "preserve",
    "declaration": true,  
    "importHelpers": true,
    "moduleResolution": "node",
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "sourceMap": true,
    "baseUrl": ".",
    "types": [
      "webpack-env"
    ],
    "paths": {
      "@/*": [
        "src/*"
      ]
    },
    "lib": [
      "esnext",
      "dom",
      "dom.iterable",
      "scripthost"
    ]
  },
  "include": [
    "src/**/*.ts",
    "src/**/*.tsx",
    "src/**/*.vue",
    "tests/**/*.ts",
    "tests/**/*.tsx"
  ],
  "exclude": [
    "node_modules"
  ]
}

However, when implementing the npm package in another project, I encountered an error where VueVoca was not recognized and Typescript could not work with it properly.

https://i.sstatic.net/66Zw1.png

https://i.sstatic.net/G8EKl.png

https://i.sstatic.net/b72Hz.png

https://i.sstatic.net/st0Va.png

webpack-internal:///./node_modules/vue/dist/vue.runtime.esm.js:620 [Vue warn]: Error in render: "TypeError: Cannot read property 'swapCase' of undefined"

found in

---> <HelloWorld> at src/components/HelloWorld.vue
       <App> at src/App.vue
         <Root>

Can someone assist me in developing a correct plugin with a proper npm package?

Answer №1

The issue at hand arises from the fact that your plugin was developed in TypeScript. Consequently, there exist two essential type definitions:

  • index.d.ts - This file contains type definitions for the index.ts file post-compilation.
  • vue.d.ts - Within this file lies the Vue.js module augmentation code specific to your Vue plugin.

Currently, your package.json specifies that the types/typings field points to the vue.d.ts file. As a result, when this library is imported in TypeScript, it automatically infers the module augmentation code from there and fails to locate the index.d.ts file. This means that while this.$voca() will function properly with TS, importing via

import { VueCoca } from 'vue-coca';
may not.

To resolve this issue, adjust the types field to point to the <PATH>/index.d.ts file instead. Additionally, consider renaming the vue.d.ts file to augment.d.ts for brevity's sake. Furthermore, users of this library should create their own typings file (*.d.ts) where they import this file as follows:

import 'vue-coca/<PATH>/augment.d';

An alternative solution involves importing the augmentation file directly within your plugin's main index.ts file. This way, users won't need to include it separately when utilizing this library.

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

After updating React and Next.js to the latest versions, encountering a re-hydration error when refreshing a page? Looking for possible solutions to resolve this issue?

Encountered an unexpected Runtime Error Error: The hydration process failed because the initial UI does not align with the server-rendered content <div> <p> Gender : <span >{gender}</sp ...

The transition() function in Angular 2.1.0 is malfunctioning

I am struggling to implement animations in my Angular 2 application. I attempted to use an example I found online and did some research, but unfortunately, I have not been successful. Can anyone please assist me? import {Component, trigger, state, anima ...

Merging Dates Array transforms the date located at the final index of the array

I have created a function that takes a Date object and a count as arguments and returns an array of Date objects starting from the given 'date' for 'count' times. However, I encountered an issue while working on the next part of the cod ...

Node.js is raising an error because it cannot locate the specified module, even though the path

Currently in the process of developing my own npm package, I decided to create a separate project for testing purposes. This package is being built in typescript and consists of a main file along with several additional module files. In the main file, I ha ...

Encountered an error while attempting to update data with file upload in Laravel and InertiaJs, response data failed to

I'm currently working on a Single Page Application (SPA) using Laravel 8 and InertiaJs, and I've encountered an issue when trying to update records that have an uploaded file. Storing data works fine, but updating with a file upload seems to be c ...

Troubleshooting: Angular Custom Elements malfunction on Firefox, Microsoft Edge, and Internet Explorer

Experimented with the Angular Elements Demo After downloading, installing, and building the demo locally. Implemented the following code: <!doctype html> <html lang="en> <head> <meta charset="utf-8> <title>Angular Eleme ...

What is the best way to align the variables in this JavaScript file with the variables in Flask/Python?

I have a JavaScript file that enables dynamic drop-down menus (i.e. selecting one option affects the others). However, I hard-coded the starting variables in this file to HTML elements 'inverter_oem' and 'inverter_model_name'. Now, I ne ...

Saving div data to a database using Ajax techniques

I have a project where I need to store div content in a database. The content looks like this: <span>name:</span><input type="text" id="inputid" value="John"><br /> To fetch this content successfully, I used innerHTML method and s ...

JavaScript and jQuery - Struggling to retrieve checkbox values

In my dynamically generated (ASP) photo gallery, I have multiple checkboxes. Each checkbox is labeled as 'photos' and contains a unique photo ID in its value attribute. Here's an example of how the checkboxes are structured: <form name=" ...

The filtering feature in the Row Group table of PrimeNG controls is malfunctioning and causing issues with the Dropdown

Within my Angular project, I have integrated PrimeNG controls version 11.4.4. Utilizing the Table control, I've structured tabular data to display rows in a grouped fashion with collapsible functionality. I've recently introduced a textbox and d ...

Tips for retrieving the value of dynamically added input fields

I am facing some challenges with JavaScript. I want to dynamically add a form to my HTML document when the user clicks on a button. Here is the code I have written: plusBtn.addEventListener('click', () => { const newLine = document.createE ...

Issue with Videogular: hh:mm:ss Date filter not functioning properly

I am currently working on integrating Videogular into my audio player application. Below are the settings provided in the example code on this particular page: <vg-time-display>{{ currentTime | date:'mm:ss' }}</vg-time-display> ...

Leveraging webpack for CSS bundling

I'm currently working on bundling some NPM modules using webpack instead of utilizing a CDN. While I've successfully managed to integrate the .js files, I'm facing challenges with including the .css files for these modules. One example is ...

Ways to convert JavaScript object to hashmap

I am attempting to generate a map of type <String, Array()> from a JSON object. Suppose I have the following JSON structure: [ { "userId": "123123", "password": "fafafa", "age": "21" }, { "userId": "321321 ...

Email attachments not working in Node Mailgun

I am facing an issue with my code that is designed to send emails using Mailgun in Node. The code functions as expected and sends the email successfully; however, it fails to attach the specified files. // pdfA and pdfB are both buffers defined earlier le ...

Apologies, the system is unable to locate the specified module './linters/rubocop'

When attempting to run the command npm run lint ("npx lint "src/**/*.{js,jsx,ts,tsx,html}" --quiet --fix")I encounter the following error: Error: Module './linters/rubocop' not found. Require stack: /usr/local/lib/node_modu ...

Halt the adhesion of the Bootstrap column when it hits the div section

I have a simple bootstrap row containing two columns: <div class="row"> <div class="col-xs-7"> <p>Walking together</p> </div> <div class="col-xs-5" id="stay"> <p>Joyful journey</p> </div ...

Unable to change the filename when utilizing Angular.js ng-file-upload

After uploading a file using Angular.js ng-file-upload, I am attempting to rename the file. However, when I remove the properties ngf-min-height="400" ngf-resize="{width: 400, height:400}", I encounter an issue. Below is my code: <input type="file" dat ...

Encountering challenges with reusing modules in Angular2

I am currently working on an angular2 website with a root module and a sub level module. However, I have noticed that whatever modules I include in the root module must also be re-included in the sub level module, making them not truly reusable. This is w ...

What are the correct steps for integrating C3JS into WebPack efficiently?

Currently, I am attempting to incorporate C3JS into my VUEJS/WebPack project (based on the boilerplate found here). D3JS is successfully loaded by npm installing it and including it as a webpack plugin. However, the same approach does not seem to work for ...