vuejs / vue-cli

🛠️ webpack-based tooling for Vue.js Development
https://cli.vuejs.org/
MIT License
29.76k stars 6.33k forks source link

Duplicated Vue runtime while loading vue library modules with npm link #4271

Closed J-Rojas closed 5 years ago

J-Rojas commented 5 years ago

Version

3.9.2

Environment info

Environment Info:

  System:
    OS: Linux 4.15 Linux Mint 19 (Tara)
    CPU: (8) x64 Intel(R) Core(TM) i7-3630QM CPU @ 2.40GHz
  Binaries:
    Node: 10.15.3 - /usr/bin/node
    Yarn: 1.16.0 - /usr/bin/yarn
    npm: 6.4.1 - /usr/bin/npm
  Browsers:
    Chrome: Not Found
    Firefox: 67.0
  npmPackages:
    @vue/babel-helper-vue-jsx-merge-props:  1.0.0 
    @vue/babel-plugin-transform-vue-jsx:  1.0.0 
    @vue/babel-preset-app:  3.9.2 
    @vue/babel-preset-jsx:  1.0.0 
    @vue/babel-sugar-functional-vue:  1.0.0 
    @vue/babel-sugar-inject-h:  1.0.0 
    @vue/babel-sugar-v-model:  1.0.0 
    @vue/babel-sugar-v-on:  1.0.0 
    @vue/cli-overlay:  3.9.0 
    @vue/cli-plugin-babel: ^3.6.0 => 3.9.2 
    @vue/cli-plugin-eslint: ^3.6.0 => 3.9.2 
    @vue/cli-service: ^3.6.0 => 3.9.2 
    @vue/cli-shared-utils:  3.9.0 
    @vue/component-compiler-utils:  2.6.0 
    @vue/preload-webpack-plugin:  1.1.0 
    @vue/web-component-wrapper:  1.2.0 
    eslint-plugin-vue: ^5.0.0 => 5.2.3 
    vue: ^2.6.10 => 2.6.10 (2.6.10)
    vue-eslint-parser:  2.0.3 
    vue-hot-reload-api:  2.3.3 
    vue-loader:  15.7.0 
    vue-localstorage: ^0.6.2 => 0.6.2 
    vue-style-loader:  4.1.2 
    vue-template-compiler: ^2.5.21 => 2.6.10 
    vue-template-es2015-compiler:  1.9.1 
    vuetify: ^1.5.13 => 1.5.16 
  npmGlobalPackages:
    @vue/cli: 3.9.2

Steps to reproduce

You will need two Vue projects, one will need be a library, the other a standard Vue project.

1) Build the Vue library project (--target lib) 2) Run npm link within the library project folder. 3) Run npm link within the standard project folder. 4) In the standard project, ensure that symlink resolution is disabled in webpack

configureWebpack: {
    resolve: {
      symlinks: false,
    }
  }

5) Build a Vue project using the library project as a dependency with npm run serve (Using Webpack HMR dev-server) 6) Load webpage dev console, you will notice multiple messages: 'You are running Vue in development mode. Make sure to turn on production mode when deploying for production. See more tips at https://vuejs.org/guide/deployment.html'

This indicates more than one Vue instance is running.

What is expected?

Only one Vue instance should be running.

What is actually happening?

Multiple Vue instances are loaded (one runtime within the library, one runtime within the standard project).


This issue affects global variable assignment on the Vue instance. If the library expects global variables to be installed on the Vue instance, they will not be shared between the library and the standard project due to the Vue module runtime being loaded twice and essentially being two different objects.

I worked around the issue by deleting the 'vue.runtime.esm.js' file in the library project's node_modules directory. This isn't ideal of course. It seems like the vue-cli that runs Webpack should exclude the second runtime somehow. I was not able to figure out how to do this with the webpack configuration within Vue.config.js.

Another developer ran into this problem without there being a satisfactory solution: https://github.com/vuejs/vuex/issues/842 https://stackoverflow.com/questions/52048395/using-vuex-store-with-npm-link-in-vue-cli-3-project-loses-store

J-Rojas commented 5 years ago

@lbogdan suggested on the forums that I look into Yarn 'peer dependencies' as a workaround for this problem.

LinusBorg commented 5 years ago

I have built couple of plugins with Vue CLI, did pretty much what you describe and didn't have a problem so it might be necessary to provide a runnable reproduction (as is required anyway by the issue rules).

But generally, the lib should have Vue as a peerDependency, not a normal dependency

vue-bot commented 5 years ago

Hello! This issue has gone quiet. Spooky quiet. 👻

We get a lot of issues, so we currently close issues requiring feedback after 20 days of inactivity. It’s been at least 10 days since the last update here. If we missed this issue or if you want to keep it open, please reply here. (A maintainer can also add the label not stale to keep this issue open.)

Thanks for being a part of the Vue community! 💪💚️

vue-bot commented 5 years ago

Hey again! 😸️

It’s been 20 days since anything happened on this issue, so our friendly neighborhood robot (that’s me!) is going to close it. Please keep in mind that I’m only a robot, so if I’ve closed this issue in error, I’m HUMAN_EMOTION_SORRY. 🤖 Please feel free to reopen this issue or create a new one if you need anything else.

Thanks again for being part of the Vue community! 💚️

MarkL4YG commented 5 years ago

Ran into this too. Having a dependency that imports vue as a non-peer-dependency itself will cause Vue to be loaded multiple times causing all kind of issues. @LinusBorg thank you for the clarification.

luzimingx commented 4 years ago

I have ran into this problem too. I add "peerDependents":{"vue": "^2.6.6"} in the library‘s package.json, and it worked. @LinusBorg is right, thank you. At last I noticed that vue-cli is not very suitable for developing a library compared to an app althouth it privide a library build target. It did not privide an api like 'vue create my-library' and init the directory structure for a library.

LeBenLeBen commented 4 years ago

I think this issue is caused by how Vue CLI aliases Vue in Webpack's config:

resolve: {
  alias: {
    vue$: 'vue/dist/vue.runtime.esm.js',
  },
},

In one case this path is relative to the library node_modules and in the other case to the project node_modules.

I therefor overridded it in the vue.config.js of the project to make it absolute:

const path = require('path');

module.exports = {
  configureWebpack: {
    resolve: {
      alias: {
        vue$: path.resolve('./node_modules/vue/dist/vue.runtime.esm.js'),
      },
    },
  },
};

With this change Vue is present only once in my project bundle.

Note that this cannot be fixed by moving Vue to peerDependencies in the library. I need Vue in development for the library to work properly.

calvinchoy commented 2 years ago

Does anyone know how to solve this problem in case a library was built with --inline-vue and then loaded async using a script tag?

I didn't face issue when using vue2, but the same library and method is now causing all kinds of issues in vue3. I tried removing --inline-vue but this caused method undefined for methods like defineComponent etc., probably because the library cannot find the host's vue instance during runtime.

RenanRossiDias commented 2 years ago

I think this issue is caused by how Vue CLI aliases Vue in Webpack's config:

resolve: {
  alias: {
    vue$: 'vue/dist/vue.runtime.esm.js',
  },
},

In one case this path is relative to the library node_modules and in the other case to the project node_modules.

I therefor overridded it in the vue.config.js of the project to make it absolute:

const path = require('path');

module.exports = {
  configureWebpack: {
    resolve: {
      alias: {
        vue$: path.resolve('./node_modules/vue/dist/vue.runtime.esm.js'),
      },
    },
  },
};

With this change Vue is present only once in my project bundle.

Note that this cannot be fixed by moving Vue to peerDependencies in the library. I need Vue in development for the library to work properly.

Saved our heads, buddy. Thanks!