Create the project directory and initialize an npm project
mkdir my-plugin && cd my-plugin
npm init -y
Install 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-compiler
Optionally (recommended) if you want to use vue class-based components syntax
vue-class-component vue-property-decorator
Create 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"