0

I am getting the following error in my Nuxt(Vue.js) app:

[Vue warn]: $attrs is readonly.
[...]
[Vue warn]: $listeners is readonly.
[...]
[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value.

From what I gather online this is due to a mismatch between Vue instances.

I am importing a component library (using a Webpack alias) from a Nuxt project. How can I make sure that the same instance is used? I've already changed the webpack alias in the library to that of the error messages (runtime.esm.js) but i still get error messages.

Stack Call before and after changing the Vue.js alias:

Stack Call Stack Call

The code of the component being called is pretty straightforward:

import Vue from 'vue';
import Renderer from '../Renderer';
import {default as Attributes} from '../attributes/main';

const renderer = new Renderer();

renderer.registerAttributeType(Attributes.Bold);
renderer.registerAttributeType(Attributes.Color);

export default Vue.extend(
    {
        name: 'RenderPlane',
        props: {
            parsed: {
                type: Array,
                required: true
            }
        },

        render: function (createElement) {
            return createElement(renderer.render(this.parsed), null);
        }
    });

And this is my Webpack configuration for the component library:

const path = require('path');
const {VueLoaderPlugin} = require('vue-loader')

module.exports = () => {
    return {
        mode: 'development',
        context: path.resolve(__dirname, 'source'),
        entry: {
            main: './main.ts',
            compiler: './renderer/main.ts',
            formatter: './formatter/main.ts',
            highlighter: './highlighter/main.ts',
            parser: './parser/main.ts'
        },

        output: {
            path: path.resolve(__dirname, 'build'),
            clean: true,
            library: {
                type: 'umd',
                name: 'Minerva'
            }
        },

        target: 'web',
        devtool: 'source-map',

        module: {
            rules: [
                {
                    test: /\.tsx?$/,
                    use: 'ts-loader',
                    exclude: /node_modules/,
                },
                {
                    test: /\.pegjs$/,
                    use: 'pegjs-loader'
                },
                {
                    test: /\.vue$/,
                    loader: 'vue-loader'
                }
            ],
        },

        resolve: {
            extensions: ['.pegjs', '.vue', '.ts', '.js'],
            alias: {
                'vue$': 'vue/dist/vue.runtime.esm.js'
            }
        },

        plugins: [
            new VueLoaderPlugin()
        ],
    }
}

Any help is greatly appreciated. I'm out of ideas. Thank you.

  • Does this answer your question? ["$attrs is readonly","$listeners is readonly","Avoid mutating a prop directly"](https://stackoverflow.com/questions/49585845/attrs-is-readonly-listeners-is-readonly-avoid-mutating-a-prop-directly) – Michal Levý Apr 20 '21 at 07:18
  • 1
    To be more specific - there are multiple ways how that can happen. One way (your case imho) is that some component library have Vue included. When you include this lib into Vue/Nuxt project, you now have two instances of Vue. As a general rule, library should always [exclude](https://stackoverflow.com/a/55159346/381282) Vue – Michal Levý Apr 20 '21 at 07:22
  • @MichalLevý I have tried adding vue to the externals in the webpack configuration as `externals: { vue: 'vue'}` but it's still not working. Do I need to register my component library as a Vue plugin maybe? – Riccardo Fagiolo Apr 20 '21 at 08:01
  • Try `vue: 'Vue'` instead – Michal Levý Apr 20 '21 at 08:09
  • https://webpack.js.org/configuration/externals/#externals – Michal Levý Apr 20 '21 at 08:11
  • @MichalLevý I had already tried that, but in the build of the Nuxt project I'm getting `This dependency was not found: Vue in ../minerva/build/main.js ` so I tried using the lowercase version. – Riccardo Fagiolo Apr 20 '21 at 08:17
  • Hmm ok. That might be something related to Nuxt. As for "normal" Vue apps this should work - see [this great comment](https://github.com/vuetifyjs/vuetify/discussions/4068#discussioncomment-24984) – Michal Levý Apr 20 '21 at 08:22
  • @MichalLevý I will read on that. Thanks so much for all the help! – Riccardo Fagiolo Apr 20 '21 at 08:26
  • As your lib is build with `output.library.type = 'umd'` (which exposes your lib as CommonJS, AMD and as global variable) your externals config should probably include all cases : `vue: { commonjs: 'vue', commonjs2: 'vue', amd: 'vue', root: 'Vue' },` – Michal Levý Apr 20 '21 at 08:31
  • @MichalLevý Already changed that, but still doesn't work. Pretty weird. – Riccardo Fagiolo Apr 20 '21 at 08:33
  • @MichalLevý I just noticed that the message `You are running Vue in development mode` is printed twice, the second time from `webpack:///../minerva/node_modules/vue/dist/vue.runtime.esm.js?73c1` which would be the library! I have added the exact same externals line that you suggested, so why is webpack still bundling an external module? I have even tried deleting all the build directories and reinstalling the packages. – Riccardo Fagiolo Apr 20 '21 at 08:44
  • Did you try to change the `package.config` of your lib and move Vue from `dependencies` to `peerDependencies` ? – Michal Levý Apr 20 '21 at 08:47
  • @MichalLevý I have tried that but it still doesn't work. I have tried re-organizing the entire library using `vue-cli` and not my webpack config, but it still doesn't work. At this point I think it might be related to the fact that the library is included in the project using `npm link` which somehow breaks everything. Does it sound like a reasonable hypothesis to you? – Riccardo Fagiolo Apr 20 '21 at 09:23

0 Answers0