Guide on developing and releasing a Vuejs component on NPM

I have been diving deep into vue lately and incorporating it into all of the projects at my workplace. As a result, I have developed various components, particularly autocomplete. Although there are plenty of existing options out there, none seem to fulfill all of my requirements. This has led me to a dilemma - every time I start a new project and need to use the same component, I find myself either recreating it from scratch or simply copying and pasting it.

This brought me to question how I could create my own component, publish it on npmjs so that whenever I need it, I can simply do a npm install --save ..., while also being able to contribute back to the community.

Answer №1

Latest Update

Attention all Vue.js developers! Please be advised that with the recent release of vue-loader 15.x, the previous method outlined in this guide will no longer be applicable. For an updated approach, kindly refer to this resource:


If you're looking to create and publish your very own Vue.js library/component from the ground up, then you've come to the right place.

This comprehensive guide will walk you through each step and command necessary to successfully develop and deploy your custom Vue.js component on NPM.

Once published, like most libraries, installation can be done using a simple command:

npm install --save your-component 

Followed by importing the component into your application:

import something from 'your-component'

To kickstart the process of creating our first component, start by creating a new folder named vuejs-hello-app (or any other preferred name) and execute the following within it:

npm init

Proceed through the interactive setup by pressing 'Enter' until completion. This will generate a file named package.json within the folder containing the provided code snippet.

(Note: The description and version have been altered for demonstration purposes)

{
  "name": "vuejs-hello-app",
  "version": "0.1.0",
  "description": "vuejs library demo",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

Following this, we'll proceed to install the required dependencies for our library.

These dependencies are classified into two categories: dependency and devDependency

dependency:
This pertains to external libraries essential for the operation of our component. When users install your component, npm ensures the existence or installation of these dependencies first. Given that we are developing a Vue component, it is crucial to have Vue as a requirement. Hence, install it using:

npm install --save vue

devDependency:
Comprising libraries utilized solely for development purposes. These facilitate building and/or transpiling tasks. The installation process for dev dependencies involves adding the suffix -dev to --save

Let's now install the basic dev dependencies necessary for our component:

npm install --save-dev babel-core
npm install --save-dev babel-loader
npm install --save-dev babel-preset-env
npm install --save-dev cross-env
npm install --save-dev css-loader
npm install --save-dev file-loader
npm install --save-dev node-sass
npm install --save-dev sass-loader
npm install --save-dev vue-loader
npm install --save-dev vue-template-compiler
npm install --save-dev webpack
npm install --save-dev webpack-dev-server

With the libraries successfully installed, the package.json file will be updated accordingly.

{
  "name": "vuejs-hello-app",
  "version": "0.1.0",
  "description": "vuejs library demo",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack -p"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "babel-core": "^6.26.0",
    "babel-loader": "^7.1.2",
    "babel-preset-env": "^1.6.1",
    "cross-env": "^5.1.1",
    "css-loader": "^0.28.7",
    "file-loader": "^1.1.5",
    "node-sass": "^4.7.2",
    "sass-loader": "^6.0.6",
    "vue-loader": "^13.5.0",
    "vue-template-compiler": "^2.5.9",
    "webpack": "^3.10.0",
    "webpack-dev-server": "^2.9.7"
  },
  "dependencies": {
    "vue": "^2.5.9"
  }
}

(note: To build our library with webpack, I included "build": "webpack -p")

As of now, the groundwork has been laid out, and preparations have been made. By creating a dist folder within the root directory and configuring a webpack.config.js file, progress is moving forward.

All files established are intended for configuration and organizational tasks. For end-users interacting with your app, two crucial files must reside within the src/ directory.

Include a main.js and VuejsHelloApp.vue at the following locations: ./src/main.js and

./src/components/VuejsHelloApp.vue

A sample project structure might resemble:

dist
node_modules
src
  main.js
  components
    VuejsHelloApp.vue
.babelrc
.eslintignore
.gitignore
.npmignore
.travis.yml
CONTRIBUTING
LICENSE
package.json
README.md
webpack.config.js

Evaluating the listed files, here's what each serves in its respective role:

/dist houses a transpiled, minified, non-ES6 rendition of your code

node_modules Self-explanatory, nothing noteworthy here

src/ marks the root directory of your library

.babelrc stores your Babel options, where certain presets may need alteration

{
  "presets": [
    [
      "env",
      {
        "modules": false
      }
    ]
  ]
}

.eslintignore Commands ESLint to ignore linting for specific files

build/*.js 

.gitignore Excludes designated files from Git tracking

.npmignore Similar to .gitignore but applies to NPM repository

.travis.yml Facilitates continuous integration setups via Travis CI

CONTRIBUTING Optional contributor guidelines document

LICENSE Includes pertinent licensing information

package.json Vital project metadata file

README.md Houses descriptive README content

webpack.config.js Crucial configuration file for achieving browser compatibility

Given the context of your app, below is a simplified illustration of how the configuration might appear:

var path = require('path')
var webpack = require('webpack')

module.exports = {
  entry: './src/main.js',

  module: {
    rules: [
      { test: /\.js$/, use: 'babel-loader' },
      { test: /\.vue$/, use: 'vue-loader' }
    ]
  },

  context: __dirname,

  output: {
    path: path.resolve(__dirname, './dist'),
    filename: 'vuejs-hello-app.js'
  }
}

if (process.env.NODE_ENV === 'production') {
  module.exports.devtool = '#source-map'
  module.exports.plugins = (module.exports.plugins || []).concat([
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: '"production"'
      }
    }),
    new webpack.optimize.UglifyJsPlugin({
      sourceMap: true,
      compress: {
        warnings: false
      }
    }),
    new webpack.LoaderOptionsPlugin({
      minimize: true
    })
  ])
}

Focusing especially on the directives entry and output, you can delve deeper into webpack documentation for further customization details.

We're almost set to conclude preparations, awaiting only the actual implementation. Within

/src/components/VuejsHelloApp.vue
, insert a simplistic app segment featuring a button that shifts positions upon hovering.

<template>
  <div>
    <button @mouseover='move($event)'> I'm alive </button>
  </div>
</template>

<script>
export default {
  data () {
   return {}
  },

  methods: {
    move (event) {
        let pos = event.target.style.float; 
      if(pos === 'left'){
        event.target.style.float = 'right'
      }else{
        event.target.style.float = 'left'
      }
    }
  }
}

</script>

<style scoped>

</style>

Lastly, navigate to ./src/main.js and export your app as follows:

import VuejsHelloApp from './components/VuejsHelloApp.vue'
export default VuejsHelloApp

In your package.json file, update "main: "index.js", to instead bear "main": "src/main.js",

To finalize, initiate the subsequent commands for building and publishing your app:

npm run build
git add .
git commit -m "initial commit"
git push -u origin master
npm login 
npm publish

How to Import and Utilize the Library

If everything unfolds seamlessly, proceed to install your app as showcased below:

npm install --save vuejs-hello-app

Then incorporate it into your Vue structure similarly to this:

<template>
  <div>
    <VuejsHelloApp> </VuejsHelloApp>
  </div>
</template>

<script>
import VuejsHelloApp from 'vuejs-hello-app'
export default {
  name: 'HelloWorld',
  components: { VuejsHelloApp }
}
</script>

A live working example developed throughout this tutorial can be accessed on GitHub at https://github.com/samayo/vuejs-hello-app. It provides additional clarity on the technicalities implemented within the code.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Error: The configuration object provided for initializing Webpack does not adhere to the correct API schema in Next.js. This results in a ValidationError due to the invalid configuration

When I used create-next-app to set up my next.js project, everything seemed fine until I tried running npm run dev and encountered this error: ValidationError: Invalid configuration object. Webpack has been initialized using a configuration object that doe ...

Tips for showcasing an image on an HTML page

I am encountering an issue with my HTML page that includes a Button. When clicked, it is supposed to display an image using an Ajax call. The functionality works properly in Postman Rest Client. However, when accessed through a browser, it only shows raw ...

Finding the absolute root path of a npm package in Node.js

Objective I am on a quest to find a reliable method to ascertain the absolute root path of an npm package that has been installed in Node.js. Challenge Although I am aware of require.resolve, it only provides the entry point (path to the main module) an ...

Using Vue.js, pull information from a database to populate input fields using a datalist feature

I'm currently working on a project utilizing Laravel 8 and Vue 3, and I have a Student Component. Within this component, there is a datalist that allows me to search for existing students. When I select a student from the list, I want the correspondin ...

The HTML generated by Selenium using Javascript is still missing some elements, despite accessing the document.body.innerHTML

Attempting to retrieve the HTML from a webpage that undergoes modification by JavaScript post-loading. Followed directions in this guide, executing the command below in my Python script after initial page load: html = browser.execute_script("return docume ...

Error in Layout of Navigation Panel and Tabbed Pages

Working on a school project, I encountered a challenge. I found two useful solutions from the W3 website - a sticky navigation bar and the ability to include tabs on a single page for a cleaner presentation of information. However, when trying to implement ...

"Exploring the wonders of hosting Vue js Single Page

Can anyone recommend a user-friendly tutorial for hosting a vue.js SPA application? I've already uploaded the entire project to the server using Filezilla, but I forgot to run npm run build before hosting it. Is it possible to run npm run build locall ...

What could be the reason my vue.js button is not generating a fresh textarea?

I am currently developing my first Web App with vue.js and I'm trying to implement a feature where clicking a button will generate a new textarea. It seemed to be functioning correctly when tested on jsfiddle, but once I tried running it in visual stu ...

Custom container width causes animation to crash when scrolling

I'm having trouble with my header. When the containers change with scrolling, an animation takes place. Everything works fine with native Bootstrap CSS, but when I customize the width of the container in my custom CSS (the width set to 1140px), the an ...

What are some ways to ensure your node server stays active indefinitely?

I've experimented with various methods to sustain a node server on a Linux environment, but unfortunately, none seem to work consistently. Sometimes the server stays operational for only 4-5 hours, other times it extends to 10-12 hours before shutting ...

Node.js - npm command to create/remove database

I am looking to streamline my workflow by automating the process of managing my test database using an npm script, but I have encountered some challenges. My First Attempt: "drop-db:local": "psql postgres \"drop database blog_db; create database blo ...

Sharing information with Vue.js component

Currently, I am in the process of developing a component and need to pass two properties (item & brokerageID) to this particular component. Below is the HTML code snippet that illustrates how these properties are passed: {{brokerageID}} <holiday-compon ...

When copying text from React-PDF Display, the values may appear altered or varied

This snippet of text was excerpted from a brief SHA provided at the git summit. Generated using React-pdf, this is a PDF document with some interesting quirks. Although the displayed text reads as 4903677, it changes to •G07THH when copied. The font ...

navigating a collection of objects and retrieving individual property values

I am having trouble extracting values from an array of objects, specifically only the values from the first object in each sub-array. Here is how my array of objects looks: items [ [ {id: 1, title: "title1", imgUrl: "https://someimage1"}, {id: 2 ...

Ensuring all Npm packages are up-to-date

I have numerous outdated packages that I need to update. Following the steps outlined in the npm documentation by running `npm update --depth 9999 -dev`, the update process took a significant amount of time only to fail at the end. Despite multiple attempt ...

Exploring intricate designs using HTML and Javascript

After extensive experience with both WPF and HTML5 JavaScript, one thing that stands out to me is the clear organization provided by XAML's defined panels. Grid, StackPanel, DockPanel, WrapPanel, and others offer a straightforward way to achieve consi ...

Steps to configure the npm registry exclusively for a particular project

Currently, I am utilizing a private npm registry for one of my npm packages, while also referring to a couple of other packages from the default npm registry. The method I am currently employing involves setting the registry globally using the following co ...

A step-by-step guide on bringing in objects in JavaScript and Node.js

Let's say we have a file called main2.js exports.obj = { x: 10, setX: function(y) { this.x = y; }, getX: function() { return this.x; } }; Now, we also have two other files: abc.js const obj = require("./main2").o ...

Implementing a pull-to-refresh feature in React Native using Redux

I need to implement pull to refresh functionality, but I'm unsure of what to call from _Refresh(). My actions, constants, and reducers are stored on another page. How can I trigger the API again? Thank you in advance for your assistance. class Homewo ...

Navigating to the most recent item within ng-repeat (AngularJS or JavaScript)

I am working on a feature where posts are displayed using ng-repeat in a div, and users can enter new posts in an input box. The posts are sorted so that the latest one appears at the bottom. After adding a new post, I want to automatically scroll down t ...