How should one go about creating an npm package out of a vuejs component and testing it locally?

Initially, I created a vuejs project as a test container using vue-cli. Next, I developed an npm package named "vue-npm-example" from a Vuejs component in my local environment and then imported it into the aforementioned testing project.

Within the package,

I executed npm link and in the project I ran npm link vue-npm-example,

Example.vue

<template>
    <div id="vue-npm-example">
        <h1>{{ msg }}</h1>
    </div>
</template>

<script>
    export default {
        name: 'vue-npm-example',
        data() {
            return {
                msg: "Welcome to Your Vue.js App"
            }
        },
        mounted() {
            console.log('this is in compoennt file')
        }
    };
</script>

<style lang="scss">
</style>

main.js

import Example from './components/Example.vue'
export function install(Vue, options) {
    options = {
        installComponents: true
      }
    if (options.installComponents) {
        Vue.component('vuejs-example', Example)
    }    
}
export default Example

webpack.config.js

let path = require('path')
let webpack = require('webpack')
function resolve (dir) {
    return path.join(__dirname, '..', dir)
  }

module.exports = {
    entry: './src/main.js',
    output: {
        path: path.resolve(__dirname, './dist'),
        publicPath: '/dist/',
        filename: 'index.js'
    },
    module: {
        rules: [
            {
                test: /\.css$/,
                use: [
                    'vue-style-loader',
                    'css-loader'
                ]
            },
            {
                test: /\.scss$/,
                use: [
                    'vue-style-loader',
                    'css-loader',
                    'sass-loader'
                ]
            },
            {
                test: /\.sass$/,
                use: [
                    'vue-style-loader',
                    'css-loader',
                    'sass-loader?indentedSyntax'
                ]
            },
            {
                test: /\.vue$/,
                loader: 'vue-loader',
                options: {
                    loaders: {
                        // Since sass-loader (weirdly) has SCSS as its default parse mode, we map
                        // the "scss" and "sass" values for the lang attribute to the right configs here.
                        // other preprocessors should work out of the box, no loader config like this necessary.
                        'scss': [
                            'vue-style-loader',
                            'css-loader',
                            'sass-loader'
                        ],
                        'sass': [
                            'vue-style-loader',
                            'css-loader',
                            'sass-loader?indentedSyntax'
                        ]
                    }
                    // other vue-loader options go here
                }
            },
            {
                test: /\.js$/,
                loader: 'babel-loader',
                exclude: /node_modules/
            },
            {
                test: /\.(png|jpg|gif|svg)$/,
                loader: 'file-loader',
                options: {
                    name: '[name].[ext]?[hash]'
                }
            }
        ]
    },
    resolve: {
        alias: {
            'vue$': 'vue/dist/vue.common.js',
            '@': resolve('src')
        },
        extensions: ['*', '.js', '.vue', '.json']
    },
    devServer: {
        historyApiFallback: true,
        noInfo: true,
        overlay: true
    },
    performance: {
        hints: false
    },
    devtool: '#eval-source-map',
    node: {
        fs: 'empty'
    },
    watch: true
}

if (process.env.NODE_ENV === 'production') {
    module.exports.devtool = '#source-map'
    // http://vue-loader.vuejs.org/en/workflow/production.html
    module.exports.plugins = (module.exports.plugins || []).concat([
        new webpack.DefinePlugin({
            'process.env': {
                NODE_ENV: '"production"'
            }
        }),
      	new webpack.LoaderOptionsPlugin({
           minimize: true
        })
    ])
}

Subsequently, in the testing project I performed

import Vue from 'vue'
import Example from 'vue-npm-example'
Vue.component('example', Example)

and utilized it as follows

<example></example>

An error was encountered:

[Vue warn]: Failed to mount component: template or render function not defined.

In order to resolve this issue, I set the vue alias in the webpack configuration files for both the package and project. The package was successfully integrated since when logging with console.log() in the package's main.js, it displayed within the testing project. However, despite numerous attempts, the component in the package continued to malfunction in the testing project.

Any recommendations?

Answer №1

When using npm link to create a symlink, the local npm package must have the full address specified when importing it. For example, instead of just importing 'custom-component', I need to do

import customComponent from './node_modules/custom-component/dist/index.js'

Answer №2

To locally test your npm package, it is recommended to use npm pack instead of npm link. The downsides of using npm link are discussed in this article:

Steps to follow:

In the package directory, run npm pack

In the project directory:

Run

npm install (path-to-package)/package-name-0.0.0.tgz

Next, import or install the package in your main.js:

import MyPackage from 'package-name'

// This line registers your component globally with Vue.component(...)
Vue.use(MyPackage);

Here are some useful links for packaging and publishing Vue components:

Packaging Vue components for npm: https://v2.vuejs.org/v2/cookbook/packaging-sfc-for-npm.html

Vue npm walkthrough: https://www.telerik.com/blogs/vuejs-how-to-build-your-first-package-publish-it-on-npm

Global component registration: https://v2.vuejs.org/v2/guide/components-registration.html#Global-Registration

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

You cannot convert a function to a string while utilizing axios get in nuxtServerInit

While attempting to connect my app to the backend using Udemy's Nuxt.js course, I encountered a GET http://localhost:3000/ 500 (Internal Server Error) on the client side with the following code: import Vuex from 'vuex'; import axios from &a ...

Activate the service function within the identical service

Currently, I am facing an issue while trying to call a function within the same AngularJS service. In my controller, I am able to successfully call the 'geocoding' function without any problems. However, within the 'geocoding' functio ...

Is it possible to modify the default port from 8080 to a different value within Vue?

Currently, I've been using Vue.js and Node.js to develop my app. By default, Vue runs on port 8080 while Node runs on port 3008. However, due to specific circumstances, I need to change the port for Vue from 8080 to something else like 8086 or 3005. ...

Personalize your message in a JavaScript alert using Bootstrap notifications

On numerous websites, a new visitor landing on the page is greeted with an alert notification that pops up in either the bottom right or left corner. The code below functions perfectly fine, except for my unsuccessful attempts to change the message text w ...

Error encountered when attempting to insert data into database due to incompatible data types

I am experiencing an issue with Vue multiselect. I am trying to save the id of selected options in a database, but it seems that I am encountering an error related to Array to string conversion. I have declared both site_id and administrator in fillables. ...

Creating a div that becomes fixed at the top of the page after scrolling down a certain distance is a great way to improve user experience on a

I am struggling to create a fixed navigation bar that sticks to the top of the page after scrolling 500px, but without using position: fixed. Despite trying various solutions, none seem to work due to the unique layout of my navigation bar. Strangely enoug ...

Tips for effectively utilizing the display: inline property in conjunction with ng-repeat

I am struggling to create a timeline with a broken structure on my website. I suspect that the issue lies in using display:inline. When attempting to apply this to my site: https://i.stack.imgur.com/4Ur7k.png the layout gets distorted: https://i.stack.i ...

Utilizing Promises with Chained .then() Functions

I am struggling with simplifying the readability of my code. I have separated it into two main functions, but I am still dealing with nested .then() statements. I am looking for advice on how to structure these functions more effectively. It is important ...

Display content from an external HTML page within a div using Ionic

Currently, I am facing an issue where I am utilizing [innerHtml] to populate content from an external HTML page within my Ionic app. However, instead of loading the desired HTML page, only the URL is being displayed on the screen. I do not wish to resort t ...

Error in Google reCaptcha 2: "a is null" occurs when grecaptcha.reset function is executed

I am currently working on a registration page that utilizes AJAX for validation on both the client and server sides. If the server side validation fails, the AJAX function returns the errors to the screen and tries to reset the reCAPTCHA using grecaptcha. ...

Creating efficient computed properties in React: a step-by-step guide

Currently, I am facing an issue with creating a table that contains checkboxes. This problem is quite frustrating, as demonstrated in the following example: I have a list of items in the format {id, value}. For each item, I generate a div element containi ...

Tips for handling ajax errors in a production environment

My typical approach in development looks something like this: fetchFaqData() { this.$http.get('/services/getfaq').then((response) => { this.faqs = response.data; }, (response) => { console.log(response); }); } While this metho ...

What is the process for running the test suite prior to every build?

My current process involves running npm test followed by npm build. Is there a way to merge the test command into the build command so that it automatically runs every time I build? Here is my package.json configuration: "scripts": { " ...

``Why is my setFeatureState function not updating the value in my Mapbox map

I've been attempting to change the stroke of a circle upon clicking it on mapbox. Despite following mapbox's documentation, the values don't seem to update. The console is also clear. t.map.addLayer({ id: id, type: 'circle&apo ...

What is the best way to include additional columns in a multiselect dropdown using jQuery select2?

I have implemented a multiselect dropdown feature using the jQuery select2 JavaScript library. The list items in this dropdown pertain to various medical drugs. I am looking to enhance this feature by adding a new column next to each selected drug, where ...

Symfony2: Using Ajax to send data to a controller

I have implemented a search input on my website that allows users to search for content within my database. I want this search input to function similarly to the search bar on Facebook, using Ajax for instant searching. Despite trying various code snippets ...

Google Chrome does not support inlined sources when it comes to source maps

Greetings to all who venture across the vast expanse of the internet! I am currently delving into the realm of typescript-code and transcending it into javascript. With the utilization of both --inlineSourceMap and --inlineSources flags, I have observed t ...

Utilizing the Vue feature of dynamic route naming within a component's function

Currently, I am working on creating a dynamic view rendering using Vue and Laravel. However, I am facing difficulty in understanding how to pass the dynamic parameter to the component function. Router.map({ '/cms-admin/:page': { comp ...

What is the best location in my redux store to store my socket connection?

As a beginner in the world of Redux, I've been using slices and redux-thunks to manage my redux store. However, I've come to realize that storing my socket connection in the state is not ideal. This connection is critical across multiple componen ...

Are the shadows in the scene being affected by a problem between DirectionalLightHelper and CameraHelper?

Currently, I am working on a complex static render in the browser using three.js and I have encountered an issue while trying to produce accurate shadows with a single THREE.DirectionalLight that represents the sun in my scene. All the geometry in another ...