DEV Community

siegerts
siegerts

Posted on • Originally published at xiegerts.com on

Creating a Vue.js component library: Part III - Consolidating into a Plugin

At this point, we have a structured approach for creating new Vue.js components and consolidating them into a single module export. Awesome! Next, we'll bundle the components into a plugin to be registered on a Vue instance.

Remember that the Vue CLI creates a main.js entry point file in the root of the /src directory during the project initialization. Usually, that's used as the entry point for a new Vue application. We'll modify this to create the plugin.

If you're landing on this post without reading the series introduction, jump there first.

main.js entry point

Starting off, let's remove the generated code. We'll replace with the differences below.

// main.js

- import Vue from 'vue'
- import App from './App.vue'

- Vue.config.productionTip = false

- new Vue({
-  render: h => h(App),
- }).$mount('#app')

+ import * as components from './components'
+
+ const ComponentLibrary = {
+  install(Vue, options = {}) {
+    // components
+    for (const componentName in components) {
+      const component = components[componentName]
+
+      Vue.component(component.name, component)
+    }
+  }
+ }
+
+ export default ComponentLibrary
+
+ if (typeof window !== 'undefined' && window.Vue) {
+  window.Vue.use(ComponentLibrary)
+ }
Enter fullscreen mode Exit fullscreen mode

The file should look like:

// main.js

import * as components from './components'

const ComponentLibrary = {
  install(Vue, options = {}) {
    // components
    for (const componentName in components) {
      const component = components[componentName]

      Vue.component(component.name, component)
    }
  }
}

export default ComponentLibrary

if (typeof window !== 'undefined' && window.Vue) {
  window.Vue.use(ComponentLibrary)
}
Enter fullscreen mode Exit fullscreen mode

Let's step through this πŸ‘€.

  • Import the components from src/components. This will grab the components from the exports in index.js. That's the file that imports(collects) the components that we want to include in the library.

  • Now, we'll create the Vue plugin and expose an install method. According to the Vue plugin documentation:

A Vue.js plugin should expose an install method...The method will be called with the Vue constructor as the first argument, along with possible options

  • In the install method, iterate through the imported components and assign each component to the const component. The componentName is used as a key get the component out of the components object.

  • Register each component with Vue.component(). The component.name is the name attribute from the component and the component as the component. When the plugin is registered in a Vue project, our components will be globally available.

In the above, componentName is not the same as component.name.

  • Export the component library plugin as the default. This allows for importing into another file as import ComponentLibrary from ... syntax:
import Vue from 'vue'
import ComponentLibrary from './main.js'

Vue.use(ComponentLibrary)

...
Enter fullscreen mode Exit fullscreen mode
  • Lastly, auto-register the plugin in situations where a Vue instance exists in the window and a module system is not used. We'll give this a test when we publish the library to a content delivery network (CDN) and include it on a page after the included Vue tag. This is covered in the Vue Getting Started Guide and is an option when adopting Vue into an existing application that may not use a build system.

Currently, the above set up does one thing - registering components. That's all we need it to do now but there are different patterns for plugin creation and the library entry point, main.js, in this case.

A few examples include:

  • Adding directives, filters, and mixins
  • Adding instance properties with Vue.prototype
  • Importing style dependencies
  • Merge user-defined options into the plugin registration with options = {}

The outline prescribed in the Vue documentation for writing a plugin is:

// 1. add global method or property
Vue.myGlobalMethod = function () {
  // some logic ...
}

// 2. add a global asset
Vue.directive('my-directive', {
  bind (el, binding, vnode, oldVnode) {
    // some logic ...
  }
  ...
})

// 3. inject some component options
Vue.mixin({
  created: function () {
    // some logic ...
  }
  ...
})

// 4. add an instance method
Vue.prototype.$myMethod = function (methodOptions) {
  // some logic ...
}
Enter fullscreen mode Exit fullscreen mode

Source: https://vuejs.org/v2/guide/plugins.html#Writing-a-Plugin

One last tip

Also, always remember to populate a name attribute in your components if using the Vue.component and component.name approach above. The registration will throw an error if component.name doesn't exist.

<template>
  <div>
    <slot></slot>
  </div>
</template>

<script>
  export default {
    name: 'name-of-your-component' // :point_left:
  }
</script>

<style></style>
Enter fullscreen mode Exit fullscreen mode

Give your components a name ☝️

Next up, tightening the feedback loop plus a hint of amazing documentation with VuePress πŸŒ‹.

Subscribe to get my latest content by email -> Newsletter

Top comments (1)

Collapse
 
gugig profile image
μ •μž¬ν›ˆ

Hello! been enjoying these posts so far, but I have a question.

In the install function, if you register every component as the global component, wouldn't it make the end-user's app's final bundle bigger than it needs to be?
If the library contains hundreds of vue components for example, and an end-user is only using around a dozen of them, I'm not sure wheather the rest of the components would be tree-shaken later.