Isak Berglind

Isak Berglind

Publish a Vue component to npm

Isak Berglind • June 6, 2019

javascript vue npm

The other day, I wanted to publish a component I had made to npm. I thought to myself - This can't be that hard? There are literary hundreds of Vue components and plugins out there already. This must be a piece of cake!

As it turns out, it wasn't as straight forward as I had hoped. There are some tutorials out there, but either they didn't match my requirements or didn't explain all the steps good enough for me to understand them. So I struggled.. But finally, after publishing 12 versions to npm - I managed to ship a working component! Great success!

But really.. That is 11 versions too much. Therefore, I decided to write the tutorial I wish I'd had. Hopefully it will help someone :)

This tutorial will cover creating a package scaffold using Vue cli, configuring the build process, and publishing the component to npm.

We'll be building a simple component that will count down how many more characters you're allowed to type, like in a tweet. We'll keep the package as minimal and bare bones as possible and focus on only the viable parts.

The requirements I had were:

First of all - we need Vue cli. If you haven't got it installed already, run the following command:

$ npm install -g @vue/cli

Which will install Vue cli globally.

To verify that everything went OK, run the following:

$ vue --version

.. And you should get a version number. in my case 3.5.0.

Now its time to create the actual projekt. We'll call it vue-charleft.

$ vue create vue-charleft

You'll be guided through the scaffold process. I made a custom build using only babel to keep it minimal.

Open the vue-charleft folder in your editor of choice, and you should see the following structure:

Initial stucture

First - delete everything in the /src folder as well as the entire public folder. Then, in the /src folder, let's create our component and call it "VueCharleft.vue".

Paste in the following code:

<template>
    <i :style="{color: textColor}">
        ({{ charactersLeft }} characters left)
    </i>
</template>

<script>

    export default {
        props: {
            text: {
                type: String,
                required: false,
                default: '',
            },
            maxChars: {
                type: Number,
                required: true,
            }
        },

        mounted() {
            this.fireLimitReachedEvent();
        },

        watch: {
            textTooLong(text) {
                this.fireLimitReachedEvent();
            },
        },

        computed: {
            charactersLeft() {
                return this.maxChars - this.text.length;
            },
            textColor() {
                return this.textTooLong ? 'red' : 'green';
            },
            textTooLong() {
                return this.charactersLeft < 0;
            }
        },

        methods: {
            fireLimitReachedEvent() {
                this.$emit('limit-reached', this.textTooLong)
            },
        }
    }

</script>

Okay! We're making good progress! And that's actually all the code we need to write!

Note! If we were making a plugin instead of a component, we would have needed to add an install function. However, this is a simple component, so this right here is all we need :)

Now we need to configure webpack to transpile our component to a UMD format that everyone can use. Luckily for us - Vue cli got us covered.

The build command has a library target option which we can take advantage of. In package.json. Add the following row inside the scripts block.

"build-lib": "vue-cli-service build --target lib --name Charleft ./src/Charleft.js"

This names the transpiled files "Charleft", as well as setting ./src/Charleft.js as the starting point for webpack.

Time to see if it works!

Run:

$ npm run build-lib

You should have the following:

Final stucture

Good times! All that's left now is to prepare our package for npm. We're gonna shift our focus to the package.json file, which is required to be able to publish something to npm. The only fields required are the name and version fields. The name needs to be unique and the version need to follow semantic versioning. However, we need a few more for our package to work correctly. Paste in the following:

{
  "name": "vue-charleft",
  "version": "0.1.0",
  "description": "A vue component to display how many more characters you can type",
  "author": "Isak Berglind",
  "license": "MIT",
  "main": "dist/Charleft.umd.min.js",
  "files": [
    "dist/*",
    "*.json",
    "*.js"
  ],
  "keywords": [
    "vue",
    "component"
  ],
  "scripts": {
    "build-lib": "vue-cli-service build --target lib --name Charleft ./src/index.js"
  },
  "dependencies": {
    "core-js": "^2.6.5",
    "vue": "^2.6.10"
  },
  "devDependencies": {
    "@vue/cli-plugin-babel": "^3.8.0",
    "@vue/cli-service": "^3.8.0",
    "vue-template-compiler": "^2.6.10"
  },
  "browserslist": [
    "> 1%",
    "last 2 versions"
  ]
}

Most fields are quite self explanatory, but some might need some clarification.

Which file to provide when the end consumer imports your package.

Which files to actually push to npm. The end user probably doesn't need the source code, it's only going to muddy up his/her node_modules even further, so let's include only the bare minimal.

Alrighty! Time to push this bad boy to npm. To be able to do so, we need an account.

Pop open your terminal and run:

$ npm adduser

Enter a name, password and email and that's it. It will automagically log you in.

Now, we have arrived at the final step! The one command to make our creation available to the whole world! Proudly type the following:

$ npm publish

And that's it! Our plugin is now publicly available for anyone to use. They simply need to import it and use it as any other component.

import Charleft from 'vue-charleft'

Vue.component('charleft', Charleft)

There are of course more to be done for this to be a good usable component for other people to use. The readme.md should describe the project and include installation instructions and some examples of how to use the component, there is no license file and so on. That is out of scope for this tutorial. The aim for this one is only to show how to publish a working Vue component :)

I hope you enjoyed this post and that it helped you in any way. If it did, or you found errors or some better way to do something - hit me up on twitter!