Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to publish a Vue plugin into NPM?

I wrote a very simple plugin for Voca.js by Typescript. You can find the source code 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 npm package I use this 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"
  ]
}

But after using the npm package in another project I got an error. VueVoca does not recognize and Typescript can not work with it well.

enter image description here

enter image description here

enter image description here

enter image description here

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 anyone help me to write a correct plugin with a correct npm package?

like image 356
HamedFathi Avatar asked Jan 28 '26 21:01

HamedFathi


1 Answers

The issue here is that you have written your plugin in TypeScript. So at a minimum, there are two type definitions:

  • index.d.ts - Contains type definitions for index.ts file after compilation
  • vue.d.ts - Contains your Vue.js module augmentation code for the Vue plugin.

Now your package.json has types/typings field is pointing to vue.d.ts. For TypeScript, when this library is imported, it infers the module augmentation code. It can never find at index.d.ts file. So, in your Vue component, this.$voca() will work with TS but not import { VueCoca } from 'vue-coca';

As a solution, set your types field to <PATH>/index.d.ts file. Also, rename vue.d.ts to augment.d.ts for the sake of brevity. The caller of this library should then write his own typings file - *.d.ts file where he will import this file like:

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

Alternately, you can also import this augmentation file inside your plugin's main index.ts file. With this approach, users of this library will not have to include it separately.

like image 96
Harshal Patil Avatar answered Jan 30 '26 13:01

Harshal Patil



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!