Vue + Vuetify : Custom Component Library
Tags: vue, vuetify
Published: 2021-07-16 08:27:46

There is great support for [Material Design](https://material.io/design/) in Vue.js. One of the libraries available for Vue.js is [Vuetify](https://vuetifyjs.com/). It is easy to incorporate into your Vue.js app and the result is appealing to the users’ eyes and most importantly Vuetify has plenty of components.

But there are few cases that you want to common design or style and serve for multiple products. Vue has great support for creating App, Library, and Web components. You choose the type at the time of building. In this post, we are going to look at how to create a custom library using Vue.


So here is my setup
```
Windows 10 21H1
Node.js v12.22.1.
@vue/cli 4.5.13
```

To start building the app, we have to install the Vue CLI. We do 
this by running:

###### if you don't have Vue CLI try this below step to run. if you already had Vue CLI skip this step
```
npm install -g @vue/cli
```
Once you install Vue CLI you start creating project
```
vue create --default custom-lib
```
after the command execute go to custom-lib and install Vuetify
```
npm i --save --save-exact vuetify
```
###### The reason we are using npm I instead of Vue add Vuetify is that when building as a library you need the dependencies inside the component
and install the required dependencies to build.
```
npm i sass@~1.32 sass-loader@^10.1.1 deepmerge -D
```
Here your base setup is done.
Next, you need to create custom components. I recommend creating components inside `src\components`. I am creating a component name `customButton.vue`. Find the code for `customButton.vue`
```
<template>
  <v-btn color="orange"> I am custom button </v-btn>
</template>

<script>
import { VBtn } from "vuetify/lib";
export default {
  name: "custom-button",
  components: { VBtn },
};
</script>
<style lang="scss" scoped>
</style>
```
###### * templates are HTML that can be parsed by spec-compliant browsers and HTML parsers.
###### * script holds the logic of the component
###### * styles used style property of the component

Note: The name inside the script is used to access the component.

Once the component is created I recommended you create a `wrapper.js` file inside a component. so that can control components that we may add or remove without deleting the `.vue` file

Here is my `wrapper.js` code
```
export { default as customButton } from './customButton.vue'
```
###### you can add as much as you want without affecting existing code

Then create an `index.js` in `src\index.js`. We register all the components in `index.js` that we do need to import every time in an application.
Here is my `index.js`.
```
import * as components from './components/wrapper';

const vueWrapper = {
    install(Vue) {
        componentRegistration(Vue);
    }
}

const componentRegistration = function (Vue) {
    for (let item in components) {
        Vue.component(components[item].name || "idx-test", components[item]);
    }
}


// Auto-install when vue is found (eg. in browser via <script> tag)
let GlobalVue = null;
if (typeof window !== 'undefined') {
    GlobalVue = window.Vue;
} else if (typeof global !== 'undefined') {
    GlobalVue = global.Vue;
}
if (GlobalVue) {
    GlobalVue.use(vueWrapper);
}

export * from './components/wrapper';
export default vueWrapper;
```
###### if you want to learn more try [Component Registration](https://vuejs.org/v2/guide/components-registration.html)

Hooray!. Our library is ready. All we need to do is build and test.
After all this Setup your library files look like this 

![Library file](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i0bom20vog8zrhqcd54j.png)

To build the project as the library you need to add some configuration in `package.json`

First, you need to run the script that [convert project as library](https://cli.vuejs.org/guide/build-targets.html#library).

So, I am adding a script to build as the library

```
"scripts": {
   "lib":"vue-cli-service build --target lib --inline-vue --name customLib ./src/index.js",
   "serve": "vue-cli-service serve"
 },
```
By Default, Vue builds lib for CommonJS and UMD. We just need to mention which file to take when we load in node/browser.
We can do this by specifying main, module, unpack, and files in package.json.

```
"main": "dist/customLib.umd.js",
"module": "dist/customLib.esm.js",
"unpkg": "dist/customLib.min.js",
"files": [
  "dist/*"
],
```

Now run `npm run lib` and you will get files like the below one.
```
 File                         Size                                                                Gzipped

  dist\customLib.umd.min.js    113.30 KiB                                                          39.58 KiB
  dist\customLib.umd.js        320.29 KiB                                                          87.29 KiB
  dist\customLib.common.js     319.90 KiB                                                          87.17 KiB
  dist\customLib.css           279.52 KiB                                                          32.71 KiB
```
So here you have created a library 🥳.

###### Tips: if you don't want seperate css file then you have to add ```
module.exports = {
  css: {
    extract: false
  }
}
``` in `vue.config.js`.

and now it's time to check the library. For that, I am going to create a new project called application and use `npm link`. you can also deploy and check from NPM. you can Learn more in [npm link](https://docs.npmjs.com/cli/v7/commands/npm-link)

First I am making the library a global package by using 
```
npm link
```
Then Go to the application and add map lib to the application using
```
npm link custom-lib
```
and install the library as a dependency by
```
npm i ../custom-lib
```
###### if you clone this project just run `npm run link`

After all the above steps are done navigate to `main.js` in the application and import and use the library by
```
import library from 'custom-lib'
import 'custom-lib/dist/customLib.css'
Vue.use(library);
```
Then go to `App.vue` and call the component we created in a template like
```
<template>
 <custom-button></custom-button>
</template>
```
and run. you will get output in `http://localhost:8080/` and it looks like 
![Application output](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p8arho8m2gjtn3tdmjgt.png)
That's all.


###### if you face error in eslint. try to remove `"eslint:recommended"` from `package.json`, run `npm i`and try again.

Find the source code at
[github](https://github.com/vishnubhadri/vue-vuetify-library)