Create the project directory and initialize an npm project
mkdir my-plugin && cd my-plugin
npm init -yInstall vue
npm i --save vue
Install dependencies required by webpack to build typescript and .vue files.
npm i --save-dev typescript webpack ts-loader css-loader vue-loader vue-template-compilerOptionally (recommended) if you want to use vue class-based components syntax
vue-class-component vue-property-decoratorCreate the following tsconfig.json
{
    "compilerOptions": {
        "outDir": "./dist/",
        "sourceMap": true,
        "strict": true,
        "noImplicitReturns": true,      
        "experimentalDecorators": true,
        "allowSyntheticDefaultImports": true,
        "noImplicitAny": false,
        "module": "es2015",
        "declaration": true,
        "moduleResolution": "node",
        "target": "es5",
        "lib": [
            "dom",
            "es5",
            "es2015.promise"
        ]
    },
    "include": [
        "./src/**/*"
    ]
}Créer un fichier de config webpack.config.js
var path = require('path')
var webpack = require('webpack')
const { VueLoaderPlugin } = require('vue-loader')
 
module.exports = {
  entry: './src/index.ts',
  output: {
    path: path.resolve(__dirname, './dist'),
    publicPath: '/dist/',
    filename: 'index.js',
    libraryTarget: 'umd',
    libraryExport: 'default' //<-- make export accessible to global scope
  },
  module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader',
        options: {
          loaders: {
            'scss': 'vue-style-loader!css-loader!sass-loader',
            'sass': 'vue-style-loader!css-loader!sass-loader?indentedSyntax',
          }
        }
      },
      {
        test: /\.tsx?$/,
        loader: 'ts-loader',
        exclude: /node_modules/,
        options: {
          appendTsSuffixTo: [/\.vue$/],
        }
      },
      {
        test: /\.(png|jpg|gif|svg)$/,
        loader: 'file-loader',
        options: {
          name: '[name].[ext]?[hash]'
        }
      }
    ]
  },
  resolve: {
    extensions: ['.ts', '.js', '.vue', '.json'],
    alias: {
      'vue$': 'vue/dist/vue.esm.js'
    }
  },
  devServer: {
    historyApiFallback: true,
    noInfo: true
  },
  performance: {
    hints: false
  },
  plugins: [
    // make sure to include the plugin for the magic
    new VueLoaderPlugin()
  ]
}At the very least Vue expect your plugin to have an install() method, in which you can register components or add properties to Vue instances.
See Vue.js / typescript official documentation, including how to structure plugin
With the current webpack configuration, your project must contains an src/index.ts file, that export your plugin's declarations.
import { VueConstructor } from 'vue/types/umd'
import HelloTarget from './components/HelloTarget.vue'
export default {
    /**
     * Function that will be used by Vue to install your plugin.
     * It is called when you do Vue.use(MyPlugin)
     */
    install(Vue: VueConstructor, options?: {target?: string}) {
        // add custom property $target to all vue instances
        Vue.prototype.$target = (options && options.target) || "everyone"
        // register your first component
        Vue.component('hello-world', HelloTarget)
    }
}Augment Vue by redeclaring it ???
Create the files typings/vue/index.d.ts
// Augment Vue with custom property $target
// https://stackoverflow.com/questions/50909703/augmenting-vue-js-in-typescript
declare module 'vue/types/vue' {
    interface Vue { 
        $target: string
    }
}Your linter might complains that it doesn't know how to process .vue files.
To solve this issue, create a src/vue-shim.d.ts with the following content
declare module "*.vue" {
  import Vue from 'vue'
  export default Vue
}Create a HelloTarget template in src/components/HelloTarget.vue, that uses the custom property created prevously...
<template>
  <h1>{{ message }}</h1>
</template>
<script lang="ts">
import Vue from "vue";
export default Vue.extend({
  computed: {
    message() {
      return `Hello ${this.$target}!`;
    },
  },
});
</script>Set apropriate values for your package in package.json, and add the following fields to it.
{
  "main": "dist/index.js",
  "types": "dist/index.d.ts",
  "scripts": {
    "build": "webpack",
    "watch": "webpack --watch"
  }
}npm run build
Create a vue project and switch to it.
vue create my-project && cd my-project
Then install your package from local filesystem.
npm install ../path/to/my-plugin
and add the followings rows in main.ts / main.js (to keep it simple).
import Vue from 'vue'
import MyPlugin from 'my-plugin'
Vue.use(MyPlugin)
// or
Vue.use(MyPlugin, {target: 'world'})Then in any .vue template, you can use your plugin.
For example, edit the default App.vue like this.
<template>
  <hello-target/>
</template>And run
npm run serve
- No ESLint configuration found
 
In my-project, create a .eslintignore file containing
../path/to/my-plugin
The issue is due to the fact that installing local package using npm result in all file being copied, whereas these files doesn't exists when your package is hosted on npm.
Start a project with vue/typescript/webpack
Vue typescript official documentation, include create plugin
vue-loader was used without the corresponding plugin. Make sure to include VueLoaderPlugin in your webpack config.
Solution
The vue-loader plugin is not automatically used by webpack. In order to load it, add this section to webpack.config.js
const { VueLoaderPlugin } = require('vue-loader')
{
    plugins: [
        // make sure to include the plugin for the magic
        new VueLoaderPlugin()
    ]
}When running webpack --reload, typing files (.d.ts) are not generated in the build.
Solution
Add the "declaration": true to tsconfig.json
{
    "compilerOptions": {
        "declaration": true,
        ...
}https://vuejs.org/v2/cookbook/adding-instance-properties.html
Solution
Add the types field to package.json
    "main": "dist/index.js",
    "types": "dist/index.d.ts"