bootstrap-vue icon indicating copy to clipboard operation
bootstrap-vue copied to clipboard

feat(compat): add Vue 3 support via @vue/compat, round 2 (fixes #5196)

Open xanf opened this issue 4 years ago • 37 comments

image

:question: What is it?

Version of Bootstrap-Vue which works for Vue 2 and Vue 3 (using @vue/compat) Helps people with #5196

Demo using Vue 2 Demo using Vue 3

Additionally, it passes all (well, almost all, tiny fraction of tests are disabled because they are irrelevant for vue 3) tests in the test suite (it would be literally impossible to do this migration without a test suite)

This package uses vue 3 by default. If you want to run tests, build, etc. using vue 2 pass USE_VUE2=1 environment variable

:exclamation: How is this possible?

The heart of this PR consists of two parts:

:wrench: How could I run it?

If you want just to play around - you can clone https://github.com/xanf/bootstrap-vue3-demo which has all required setup. If you want to try it on your own project, there is some setup required.

I'm skipping setup of @vue/compat, it is described in migration guide

You will need to monkey patch your Vue 3 a bit somewhere early in your app:

  const originalVModelDynamicCreated = Vue.vModelDynamic.created;
  const originalVModelDynamicBeforeUpdate = Vue.vModelDynamic.beforeUpdate;
  Vue.vModelDynamic.created = function (el, binding, vnode) {
    originalVModelDynamicCreated.call(this, el, binding, vnode);
    if (!el._assign) {
      el._assign = () => {};
    }
  };
  Vue.vModelDynamic.beforeUpdate = function (el, binding, vnode) {
    originalVModelDynamicBeforeUpdate.call(this, el, binding, vnode);
    if (!el._assign) {
      el._assign = () => {};
    }
  };

See https://github.com/vuejs/vue-next/pull/4121 for details

If your intention is to run your app in { MODE: 2 } (default @vue/compat) you're done. If you want to have { MODE: 3 } (so all compats are disabled by default), additional setup is needed:

  • if https://github.com/vuejs/vue-next/pull/4974 is not yet merged - you need to build @vue/compat build with this fix included. https://github.com/xanf/bootstrap-vue3-demo already has patch inside patches folder for that, installed by patch-package
  • Certain compat flags required to be enabled globally ATM and can't be disabled in this release (which maintains Vue 2 and Vue 3 compatibility):
    • GLOBAL_EXTEND, GLOBAL_MOUNT - for using new Vue inside bootstrap-vue
    • COMPONENT_FUNCTIONAL, RENDER_FUNCTION
    • CUSTOM_DIR (anywhere where you use bootstrap-vue directive)

If you use portal-vue (which is still used for tooltips, etc.) you will need:

  • GLOBAL_SET

If you use old (for Vue 2) version of vue-router you will need:

  • CONFIG_OPTION_MERGE_STRATS
  • GLOBAL_PRIVATE_UTIL
  • GLOBAL_PROTOTYPE
  • INSTANCE_EVENT_HOOKS
  • OPTIONS_DESTROYED
  • INSTANCE_EVENT_EMITTER

:bomb: What might not work

  • Docs. I've tried to make Nuxt run using newer Nuxt 3, bridge, etc. but it was very problematic. So I wrote a script, which extracted demos from docs and generated https://github.com/xanf/bootstrap-vue3-demo with all demos
  • Build. It might or might not work, I didn't have an opportunity to test it yet

:arrow_upper_right: What's next?

Let's treat this one as "bridge" version Based on this branch I will create another one, which will be focused solely on full vue 3 compatibility (without using @vue/compat). While this will definitely take time, right now I do not see any major obstacles in gradual migration

:hugs: That's cool, how could I say "thank you"?

You're welcome, it's all about opensource. However, there are certain things, where your help will be appreciated:

  • Help me spread the word about vue-test-utils-compat. You can retweet me or just drop a link to your friend who could be interested
  • Check deployed versions of https://github.com/xanf/bootstrap-vue3-demo (links inside) and report about any issues you find out in Vue 3 version (it is very time consuming to test all possible scenarios)

PR checklist

What kind of change does this PR introduce? (check at least one)

  • [ ] Bugfix (fixes a boo-boo in the code) - fix(...), requires a patch version update
  • [x] Feature (adds a new feature to BootstrapVue) - feat(...), requires a minor version update
  • [ ] Enhancement (augments an existing feature) - feat(...), requires a minor version update
  • [ ] ARIA accessibility (fixes or improves ARIA accessibility) - fix(...), requires a patch or minor version update
  • [ ] Documentation update (improves documentation or typo fixes) - chore(docs), requires a patch version update
  • [x] Other: major update

Does this PR introduce a breaking change? (check one)

  • [x] No (I know it's hard to believe)
  • [ ] Yes (please describe since breaking changes require a minor version update)

The PR fulfills these requirements:

  • [x] It's submitted to the dev branch, not the master branch
  • [x] When resolving a specific issue, it's referenced in the PR's title (i.e. [...] (fixes #xxx[,#xxx]), where "xxx" is the issue number)
  • [x] It should address only one issue or feature. If adding multiple features or fixing a bug and adding a new feature, break them into separate PRs if at all possible.
  • [x] The title should follow the Conventional Commits naming convention (i.e. fix(alert): not alerting during SSR render, docs(badge): update pill examples, chore(docs): fix typo in README, etc.). This is very important, as the CHANGELOG is generated from these messages, and determines the next version type (patch or minor).

If new features/enhancement/fixes are added or changed:

  • [ ] Includes documentation updates
  • [ ] Includes component package.json meta section updates (prop, slot and event changes/updates)
  • [ ] Includes any needed TypeScript declaration file updates
  • [ ] New/updated tests are included and passing (required for new features and enhancements)
  • [x] Existing test suites are passing
  • [x] CodeCov for patch has met target (all changes/updates have been tested)
  • [x] The changes have not impacted the functionality of other components or directives
  • [ ] ARIA Accessibility has been taken into consideration (Does it affect screen reader users or keyboard only users? Clickable items should be in the tab index, etc.)

If adding a new feature, or changing the functionality of an existing feature, the PR's description above includes:

  • [x] A convincing reason for adding this feature (to avoid wasting your time, it's best to open a suggestion issue first and wait for approval before working on it)

xanf avatar Jan 28 '22 15:01 xanf

This pull request is being automatically deployed with Vercel (learn more).
To see the status of your deployment, click below or on the icon next to each commit.

🔍 Inspect: https://vercel.com/bootstrap-vue/bootstrap-vue/AP9rnnFFga1HMqX9GxTngzbShiMk
✅ Preview: https://bootstrap-vue-git-vue3-compat-build-bootstrap-vue.vercel.app

vercel[bot] avatar Jan 28 '22 15:01 vercel[bot]

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit 6ef2ba4cc161125a703c8953975bd68020ab3807:

Sandbox Source
BootstrapVue Starter Project Configuration
BootstrapVue Nuxt.js Starter Project Configuration

codesandbox-ci[bot] avatar Jan 28 '22 15:01 codesandbox-ci[bot]

Codecov Report

Merging #6905 (6ef2ba4) into dev (debe660) will not change coverage. The diff coverage is 100.00%.

@@            Coverage Diff             @@
##               dev     #6905    +/-   ##
==========================================
  Coverage   100.00%   100.00%            
==========================================
  Files          299       305     +6     
  Lines        10265     10452   +187     
  Branches      2527      2550    +23     
==========================================
+ Hits         10265     10452   +187     
Flag Coverage Δ
unittests 100.00% <100.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
src/components/form-group/form-group.js 100.00% <ø> (ø)
src/components/layout/col.js 100.00% <ø> (ø)
src/components/layout/row.js 100.00% <ø> (ø)
src/directives/scrollspy/scrollspy.js 100.00% <ø> (ø)
src/components/alert/alert.js 100.00% <100.00%> (ø)
src/components/aspect/aspect.js 100.00% <100.00%> (ø)
src/components/avatar/avatar-group.js 100.00% <100.00%> (ø)
src/components/avatar/avatar.js 100.00% <100.00%> (ø)
src/components/badge/badge.js 100.00% <100.00%> (ø)
src/components/breadcrumb/breadcrumb-item.js 100.00% <100.00%> (ø)
... and 180 more

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

codecov[bot] avatar Jan 28 '22 15:01 codecov[bot]

What does this need to be merged? Looking forward to restart using bootstrap-vue with vue 3!

mariusa avatar Feb 17 '22 09:02 mariusa

If you visit b-popover-advanced demo and click on button then we get below error: Screenshot from 2022-02-17 18-19-26

I am also getting the same error in a few other areas in my project.

Thanks.

jd-solanki avatar Feb 17 '22 12:02 jd-solanki

Please merge and publish this PR to npm but with next channel, everyone should be able to install and test it.

ankurk91 avatar Feb 26 '22 07:02 ankurk91

https://6253cfb04272251095ef217a--clever-dasik-1a4bcc.netlify.app/

just update @vue/compat, @vitejs/plugin-vue and @vue/compiler-sfc and only use vue3 mode and only use this patch code, not patch-package module for patch @vue/compat

 const originalVModelDynamicCreated = Vue.vModelDynamic.created;
  const originalVModelDynamicBeforeUpdate = Vue.vModelDynamic.beforeUpdate;
  Vue.vModelDynamic.created = function (el, binding, vnode) {
    originalVModelDynamicCreated.call(this, el, binding, vnode);
    if (!el._assign) {
      el._assign = () => {};
    }
  };
  Vue.vModelDynamic.beforeUpdate = function (el, binding, vnode) {
    originalVModelDynamicBeforeUpdate.call(this, el, binding, vnode);
    if (!el._assign) {
      el._assign = () => {};
    }
  };

Some components are still not run properly I did not check most of the components, I only saw these problems

  • toast-advanced
  • popover-advanced
  • bootstrap 5.0.0 (current version 5.1.3 and 5.2.0 is coming) use @popper/core not popper.js is deprecated

sadeghbarati avatar Apr 11 '22 08:04 sadeghbarati

@sadeghbarati thank you for givin this a try and catching couple bugs! I'm going to take a look ath them soon

However, rewrite to bootstrap v5 is totally separate topic

xanf avatar Apr 11 '22 08:04 xanf

@xanf

one thing I forgot to mention: I think the portal-vue force this project to use @vue/compat? @vue/compat performance is same as vue2&3 ?

Although there is a small performance/size overhead


If your team separate vue 2&3 of bootstrap-vue would be so better because first time I use compat version and Compatibility table seem have many incompatibles and caveats even ssr problem for this project

I do not expect much from you at this time because I am a little aware of the situation you are in now in Ukraine

These are my thoughts ppl can easily contribute and help ur team along:

  1. bootstrap-vue & vue 2 & portal-vue & bootstrap 4
  2. bootstrap-vue & vue 2 & portal-vue & bootstrap 5
  3. bootstrap-vue & vue 3 & builtin Teleport & bootstrap 4
  4. bootstrap-vue & vue 3 & builtin Teleport & bootstrap 5

sadeghbarati avatar Apr 11 '22 10:04 sadeghbarati

How can I help moving this over the finish line? :)

sebo avatar Apr 12 '22 12:04 sebo

Seems to me that it would be easier to create a separate project for vue3+bootstrap5 instead of creating this frankenstein thing trying to update existing code. Leave the current project as is and don't worry about cross compatibility. That's my 2 cents anyways.

sdwru avatar Apr 29 '22 13:04 sdwru

Seems to me that it would be easier to create a separate project for vue3+bootstrap5 instead of creating this frankenstein thing trying to update existing code. Leave the current project as is and don't worry about cross compatibility. That's my 2 cents anyways.

@sdwru, a project has been started: https://github.com/cdmoro/bootstrap-vue-3

messenjer avatar Apr 29 '22 14:04 messenjer

Seems to me that it would be easier to create a separate project for vue3+bootstrap5 instead of creating this frankenstein thing trying to update existing code. Leave the current project as is and don't worry about cross compatibility. That's my 2 cents anyways.

What about the people that are already using this on their project?

ultimaweapon avatar Apr 29 '22 17:04 ultimaweapon

Seems to me that it would be easier to create a separate project for vue3+bootstrap5 instead of creating this frankenstein thing trying to update existing code. Leave the current project as is and don't worry about cross compatibility. That's my 2 cents anyways.

What about the people that are already using this on their project?

What about them? They can keep on using it.

sdwru avatar Apr 29 '22 18:04 sdwru

That mean they are going to stuck with Vue 2 forever. They can't upgrade to Vue 3 due to Bootstrap Vue is not compatible and they can't switch to that new library too due to it is Vue 3.

ultimaweapon avatar Apr 29 '22 18:04 ultimaweapon

That mean they are going to stuck with Vue 2 forever. They can't upgrade to Vue 3 due to Bootstrap Vue is not compatible and they can't switch to that new library too due to it is Vue 3.

No it doesn't. It will most likely be just as much work upgrading an existing project to a separate fork of this project than it would be if this project tried to create some frankenstein that tries to be cross compatible. As it stands now there hasn't been much progress going down the current path for over 2 years now. People are moving on. Nobody starting a new project is going to use this.

sdwru avatar Apr 29 '22 19:04 sdwru

Well I'm one of the affected users. My current application is large and deeply integrated with Bootstrap Vue and switching it to another framework + Vue 3 in a single shot is a tremendous task. I need this compatible build in order to upgrade my project to Vue 3 as a first step.

ultimaweapon avatar Apr 29 '22 19:04 ultimaweapon

Well I'm one of the affected users. My current application is large and deeply integrated with Bootstrap Vue and switching it to another framework + Vue 3 in a single shot is a tremendous task. I need this compatible build in order to upgrade my project to Vue 3 as a first step.

Like I said, it will be just as much work either way. Believe it or don't. If you think that you will be able to just type npm upgrade and your project will magically upgrade everything to Vue3+Bootstrap 5 or even just Vue3, you are sadly mistaken.

sdwru avatar Apr 29 '22 19:04 sdwru

Yes it much work but it can be splitting. Just dealing with Vue 2 to Vue 3 is already a huge amount of task. If we don't have this compatible build it need to fix both Vue 3 and framework compatibility issue in a single upgrade. But if we have this compatible build we can just dealing with Vue 3 first without worrying with framework issues.

ultimaweapon avatar Apr 29 '22 19:04 ultimaweapon

Let me jump into this discussion and explain my rationale

This "frankenstein" has the only purpose: to allow people iterate while we're rewriting bootstrap-vue to Vue3 (bootstrap 5 will be addressed later)

This frankenstein also serves second, not-so-obvious support - this potentially will be "reference" rendering which will be used to check that rewrite renders the same HTML as original version

I've heard "it's easier to do it from scratch" multiple times in my career (and initiated it multiple times). Unfortunately success rate of such efforts was lower than I wanted. So my strategy is definitely to stand on the shoulder of giants for this rewrite

Let me explain my rationale:

  • rewriting Vue2 -> Vue 3 + bootstrap-vue -> put your favorte alternate implementation here basically violates main rule "touch one thing at once", because it involves three (Vue3, bootstrap v5 and js). This is pure insanity for any mid- to large-scale project
  • bootstrap-vue is feature rich. And implementing all these features is identical in terms of complexity no matter if it is rewrite or "from scratch". But keeping compatibility is far more easier if considered from early start
  • bootstrap-vue has quite good codebase. It might look insane and weird, but it is pretty high quality. I've understood a lot of nuances while working on this MR and now utilizing this knowledge on rewrite

I'm planning to work on this MR release as bootstrap-vue@compat within next 3 days, right now deep into BTable vue3 version

Thanks everyone for patience!

xanf avatar Apr 29 '22 23:04 xanf

Nobody is suggesting a rewrite from scratch. (-‸ლ)

There is no reason you can't reuse code when it makes sense to do so. There is no reason to believe dropping cross-compatibility will make porting an existing project to new code more difficult either. It's going to be lots of work regardless because Vue3 + Bootstrap 5 have too many changes.

People have been asking for an update for over 2 years now and it's just not happening. The current project is too outdated for anyone to consider it for new projects and there is no indication that is changing anytime soon. Also, the only thing being discussed right now is updating to Vue3. That's still not good enough to compel anyone to use it for a new project. Not until it's updated to Bootstrap 5 and at the current rate of progress there will probably be a Bootstrap 6 by them.

sdwru avatar Apr 30 '22 17:04 sdwru

@sdwru thank you for taking time to explain your position. I believe the biggest opensource strength (and, well, sometimes, flaw) is that there are many aprroaches, so people can choose the best one for them

Like I said, I see the bootstrap-vue as powerful library with no match between other clones, so I will continue working on bringing Vue3 and Bootstrap5 to it

xanf avatar Apr 30 '22 18:04 xanf

Please be patient. @xanf is living in Ukraine, which is currently attacked by Russia.

ultimaweapon avatar May 17 '22 07:05 ultimaweapon

There appears to be an incompatibility with how Vue 3 handles template refs.

https://github.com/bootstrap-vue/bootstrap-vue/blob/dev/src/components/tabs/tabs.js#L420 https://github.com/bootstrap-vue/bootstrap-vue/blob/dev/src/components/tabs/tabs.js#L592

this.$refs.buttons ends up pointing to a single button (it's not an array as expected) with the Vue 3 compat, specifically when the title slot is used.

<b-tabs>
    <b-tab active>
        <template #title>
            Test
        </template>
        Hello World
    </b-tab>
</b-tabs>

image

Title attribute is working just fine:

<b-tabs>
    <b-tab title="Test" active>
        Hello World
    </b-tab>
</b-tabs>

mattsteve avatar May 18 '22 01:05 mattsteve

There appears to be an incompatibility with how Vue 3 handles template refs.

The v-for Array Refs migration strategy seems to work, for my fork of this branch, with the b-time component which relies on using ref in v-for similarly to b-tabs.

It is pretty straightforward to implement, but not sure if there are any pitfalls to the approach. I haven't yet tested this in a build.

jakedolan avatar May 19 '22 22:05 jakedolan

Inherited attributes don't appear to be working on at least some components, like <b-alert>.

Template:

<b-alert data-foo="bar"></b-alert>

Actual Rendered Markup:

<div class="alert" role="alert" aria-live="polite" aria-atomic="true""></div>

Expected Rendered Markup:

<div class="alert" role="alert" aria-live="polite" aria-atomic="true"" data-foo="bar"></div>

mattsteve avatar May 26 '22 20:05 mattsteve

The getInstanceFromVNode method requires a development build of Vue 3 compat in order to work. Otherwise, you'll run into issues like popovers not closing.

https://github.com/bootstrap-vue/bootstrap-vue/blob/vue3-compat-build/src/utils/get-instance-from-vnode.js#L4

The library will need to be reorganized to not rely on this function.

mattsteve avatar Jun 07 '22 18:06 mattsteve

@mattsteve whoa, thank you. I was considering that, but probably failed in my testing (I'm about getInstanceFromVNode)

regarding inherited attributes - that should be easy fixable

Status update

I understand there is not that much movement here. It's hard for me to find balance between war-related activities (sigh), work and opensource. However I hope to release this MR this month (huge cudos for everyone who is testing)

Also I'm working on finalizing BTable (entire one with all features). No code to share yet, just a spoiler:

image

I will release this as soon as BTable will be functional (hope to do this month also). I estimate this as one of the hardest (not the biggest, hello calendar, but hardest) component for rewrite :)

xanf avatar Jun 07 '22 19:06 xanf

@xanf Is there any progress? If not, I plan to use my spare time to develop a new version for vue3 based on this repository

kimmy-wang avatar Jun 08 '22 08:06 kimmy-wang

@see https://github.com/bootstrap-vue/bootstrap-vue/pull/6905#issuecomment-1149083451 is from vue3 version of BTable :), not compat one :)

xanf avatar Jun 08 '22 09:06 xanf