vuejs / vue

This is the repo for Vue 2. For Vue 3, go to https://github.com/vuejs/core
http://v2.vuejs.org
MIT License
207.7k stars 33.66k forks source link

Building to Vue 2 and 3: Version mismatch error from vue-template-compiler #11828

Closed privatenumber closed 3 years ago

privatenumber commented 3 years ago

What problem does this feature solve?

vue-template-compiler runs a version check against the vue specifier Node.js resolves as soon as it's imported here.

Because of this:

  1. I'm getting a vue-loader recommendation in a rollup build
  2. I can't have a setup that builds to both Vue 2 and 3. I think it's important to support this use-case for the eco-system as more apps migrate to Vue 3.

I'm interested in building a component to both Vue 2 and 3, but the version mismatch error from above gets thrown as soon as rollup-plugin-vue@5 is imported.

Screen Shot 2020-12-16 at 3 06 55 PM

My package.json looks like this:

{
  ...,
  "devDependencies": {
    "@vue/compiler-sfc": "^3.0.4",
    "rollup": "^2.35.1",
    "rollup-plugin-vue2": "npm:rollup-plugin-vue@^5.1.9",
    "rollup-plugin-vue3": "npm:rollup-plugin-vue@^6.0.0",
    "vue": "^3.0.4",
    "vue-template-compiler": "^2.6.12",
    "vue2": "npm:vue@^2.6.12"
  }
}

My rollup.config.js looks like this:

import vue2 from 'rollup-plugin-vue2';
import vue3 from 'rollup-plugin-vue3';

const rollupConfig = [
    {
        input: 'src/MyComponent.vue',
        plugins: [
            vue3(),
        ],
        output: {
            format: 'es',
            file: 'dist/my-component.vue3.esm.js',
        },
    },
    {
        input: 'src/MyComponent.vue',
        plugins: [
            vue2(),
        ],
        output: {
            format: 'es',
            file: 'dist/my-component.vue2.esm.js',
        },
    },
];

export default rollupConfig;

What does the proposed API look like?

Wondering if this can be changed to a run-time check or moved to the appropriate loader/plugin.

A run-time check might be a good idea as I'm sure a lot of people may be accidentally trying to import Vue 2 components into a Vue 3 app and vice-versa.

posva commented 3 years ago

In your specific scenario, you could swap vue2 and vue to have vue point to Vue 2 and vue3 to point to Vue 3. Moving the error to runtime would just delay the error but still happen. Note it's not a problem in applications as they will only run one version of Vue.

Maybe you have a PR proposal and I think it's worth exploring but, in general, I would say it's easier to handle different versions of the package for different versions of Vue if you need to compile templates. If you don't need to compile templates, you can install only one version of it like https://github.com/posva/vue-promised

privatenumber commented 3 years ago

You're right, that worked for my use-case. Thanks @posva!

I have a few component repos I want to start supporting Vue 3 for as well, but I don't think it's a great dev experience for everyone to need to make a breaking release to support Vue 3. Phasing Vue 2 out will be a long process so I'd still like to support Vue 2 users without maintaining two different branches.

I'm also considering exporting SFCs via vue-compile.

Moving the error to runtime would just delay the error but still happen.

Yes, I think the error should still happen. I'm suggesting that the error be shown to the component user rather than the builder.

Note it's not a problem in applications as they will only run one version of Vue.

I think it will be as we migrate to Vue 3. eg. I work in a very large Vue 2 codebase and we won't be able to immediately upgrade everything to Vue 3. We're waiting on the compat build, but I'm working on vue-2-3 as a potential solution to this problem.

posva commented 3 years ago

Closing as the recommended solution would be to use vue-demi