Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: added vue 2 backwards compatibility for @vue-flow/background #1188

Conversation

michealroberts
Copy link

@michealroberts michealroberts commented Nov 9, 2023

refactor: migrated vue 2 backwards compatibility for @vue-flow/background


Description

This MR refactors the @vue-flow/background package to be entirely SFC independent, allowing for backwards compatibility with Vue 2.7.* as well as continuing support for Vue 3.

Essentially, these changes should be able to be merged into master / main without any trouble at all for the existing package.

Testing 🔧

Vue 2 App Example (with just the background component rendered*):

Screenshot 2023-11-09 at 17 08 33

Vue 3 Vite App Example:

Screenshot 2023-11-09 at 17 06 06

Copy link

changeset-bot bot commented Nov 9, 2023

🦋 Changeset detected

Latest commit: 5a4ce17

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@vue-flow/background Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Copy link

vercel bot commented Nov 9, 2023

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
vue-flow-docs ✅ Ready (Inspect) Visit Preview 💬 Add feedback Nov 10, 2023 0:22am
vue-flow-typedoc ✅ Ready (Inspect) Visit Preview 💬 Add feedback Nov 10, 2023 0:22am

Copy link

vercel bot commented Nov 9, 2023

Someone is attempting to deploy a commit to a Personal Account owned by @bcakmakoglu on Vercel.

@bcakmakoglu first needs to authorize it.

@vercel vercel bot temporarily deployed to Preview – vue-flow-typedoc November 9, 2023 17:39 Inactive
@michealroberts michealroberts force-pushed the refactor/backward/vue-2-backwards-compat branch from b634310 to c0f5e57 Compare November 9, 2023 17:41
@vercel vercel bot temporarily deployed to Preview – vue-flow-typedoc November 9, 2023 17:42 Inactive
@michealroberts michealroberts force-pushed the refactor/backward/vue-2-backwards-compat branch from c0f5e57 to e2850ce Compare November 9, 2023 17:51
@vercel vercel bot temporarily deployed to Preview – vue-flow-typedoc November 9, 2023 17:51 Inactive
.changeset/thick-moles-smash.md Outdated Show resolved Hide resolved
.changeset/thick-moles-smash.md Outdated Show resolved Hide resolved
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As previously mentioned, please don't remove current component and instead add new ones.

Replacing components can still be done at a later point.

const Background = /* #__PURE__ */ defineComponent({
name: 'Background',
compatConfig: { MODE: 2 },
props: {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alas, I thought this might be the result of the syntax change, which imo, increases maintenance a lot.

Instead of defineProps<Props>() we now end up with this mess :(

I assume due to Vue 2 compatibility using the defineComponent<Props, Emits>({ ... }) will not work here, will it?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Functional components are, I am pretty sure, Vue 2 compatible and seeing as these are stateless, I don't see why a refactor to stateful components (which in Vue 2 come with more overhead than in Vue 3, so there it would make much less a difference though)

},
},
setup(props: DotPatternProps) {
const radius = computed(() => props.radius)
Copy link
Owner

@bcakmakoglu bcakmakoglu Nov 9, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be I'm mistaken about available APIs in Vue 2 but:

  1. computed comes with caching, which produces overhead and therefore has better usage when it comes to expensive computations, not when returning a prop or doing simple equality comparisons like prop.hello === 'world'
    Can be replaced by toRef which doesnt produce the same overhead

  2. Props should still be reactive, even without wrapping them in extra reactive variables.
    Meaning, if you do return () => h('div', props.label) and update the label prop, it will still re-render appropriately without wrapping props.label in computed or toRef.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you Can open a separate repository for Vue2

@michealroberts michealroberts force-pushed the refactor/backward/vue-2-backwards-compat branch from e2850ce to 7897750 Compare November 9, 2023 18:00
@bcakmakoglu
Copy link
Owner

I'd tag this change as a feature instead of a refactor request as that's more in line with what's actually happening.

@vercel vercel bot temporarily deployed to Preview – vue-flow-typedoc November 9, 2023 18:00 Inactive
@michealroberts
Copy link
Author

I'd tag this change as a feature instead of a refactor request as that's more in line with what's actually happening.

Cool. I think the changesets will need the appropriate minor bump too. Do you want me to take care of this?

@bcakmakoglu bcakmakoglu changed the base branch from master to feat/vue2 November 9, 2023 18:01
@bcakmakoglu
Copy link
Owner

Changed the base branch to feat/vue2 so changes can be collected in there before release.

@bcakmakoglu
Copy link
Owner

I'm wondering how we could run the test suites for the Vue 2 components as well 🤔

@michealroberts michealroberts force-pushed the refactor/backward/vue-2-backwards-compat branch from 7897750 to 66f9a88 Compare November 9, 2023 18:51
@michealroberts
Copy link
Author

I'm wondering how we could run the test suites for the Vue 2 components as well 🤔

What is your current test setup? Cypress?

@vercel vercel bot temporarily deployed to Preview – vue-flow-typedoc November 9, 2023 18:52 Inactive
@michealroberts
Copy link
Author

michealroberts commented Nov 9, 2023

I'd tag this change as a feature instead of a refactor request as that's more in line with what's actually happening.

Cool. I think the changesets will need the appropriate minor bump too. Do you want me to take care of this?

Taken care of the changesets.

@bcakmakoglu
Copy link
Owner

Yeah, tests are done with cypress component testing

@bcakmakoglu
Copy link
Owner

Could you possibly add a Vue 2 example App to the examples folder, so that this can be tried out?

@michealroberts michealroberts changed the title refactor: added vue 2 backwards compatibility for @vue-flow/background feat: added vue 2 backwards compatibility for @vue-flow/background Nov 9, 2023
@michealroberts
Copy link
Author

michealroberts commented Nov 9, 2023

Could you possibly add a Vue 2 example App to the examples folder, so that this can be tried out?

So I have added one locally, and it works well (not much use to you, granted) ... but we would need to migrate @vue-flow/core before we have full compatibility ...

*To get the Vue 2 app working locally, I have to strip the dependency in background on core, and hardest the values return by the useVlueFlow() composable.

@bcakmakoglu
Copy link
Owner

Why would you need to strip that? The app can use a different vue version without the whole repo using the same ^^

@bcakmakoglu
Copy link
Owner

You'd probably just need to remove the peerDepedency

name: 'Background',
compatConfig: { MODE: 2 },
setup(props: BackgroundProps, { slots }) {
const initialPatternColor = props.patternColor
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why aren't we allowing dynamic colors for patterns?

Users would expect changes to this prop to be reflected in the pattern color

Comment on lines +44 to +116
const height = computed(() => {
return props.height || 100
})

const width = computed(() => {
return props.width || 100
})
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct me if I'm wrong but if toRef is available in Vue 2 a simple toRef(() => props.height || 100) should be fine here as well?

},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be mandatory?

"peerDependencies": {
"@vue-flow/core": "^1.23.0",
"vue": "^3.3.0"
"@vue/composition-api": "^1.0.0-rc.1",
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why rc.1? Why not pick 1.0.0, the actual release?

Copy link
Owner

@bcakmakoglu bcakmakoglu Nov 9, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If compat mode is set to 2 does the compiled out put of this SFC work in Vue 2 as well?
Imo this is a lot easier to maintain and read than the regular .ts file since the h syntax requires a lot of terniaries, making it look like a jsx mess.

The Background.ts file would also not emit any usable types atm (just doing props: SomeProps is not enough), giving the proposed implementation no auto-completion support

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried it out and, alas, it does not work with the SFC, which sucks 😢

I guess the type issue could be circumvented by force casting the exposed components prop, emit and slot types.

Something like this, I believe? Could compare to what Volar outputs with the current roll strategy.

export const VueFlow = /* ...  */ as {
	$props: FlowProps
	// ...
}

@bcakmakoglu bcakmakoglu added the enhancement New feature or request label Nov 9, 2023
@michealroberts michealroberts force-pushed the refactor/backward/vue-2-backwards-compat branch from 66f9a88 to 474b5ba Compare November 10, 2023 09:46
@vercel vercel bot temporarily deployed to Preview – vue-flow-typedoc November 10, 2023 09:47 Inactive
@michealroberts michealroberts force-pushed the refactor/backward/vue-2-backwards-compat branch from 474b5ba to c03a27e Compare November 10, 2023 09:49
@vercel vercel bot temporarily deployed to Preview – vue-flow-typedoc November 10, 2023 09:50 Inactive
@bcakmakoglu
Copy link
Owner

bcakmakoglu commented Nov 10, 2023

So after a bit of playing around, it turns out you can do defineComponent<Props>, which will roll up the proper types for the component and is usable in Vue 2.

const Background = /* #__PURE__ */ defineComponent<BackgroundProps>({
	// rest here...
})

That is a massive W tbh and should make this a lot easier.

Though defining default values for props is still a hassle 😄

Editor: My bad, it does roll types with no error but the types aren't recognized by Volar properly import("vue-demi").PropType<SomeType> sadly does not work, though import("vue").PropType<SomeType> does

Not the W I hoped for.

@michealroberts
Copy link
Author

defineComponent<BackgroundProps>

Yeh this is a really strange one ... I'm wondering if this is a bug with Volar ... 🤔

@michealroberts michealroberts force-pushed the refactor/backward/vue-2-backwards-compat branch from c03a27e to e7b4e09 Compare November 10, 2023 11:15
@vercel vercel bot temporarily deployed to Preview – vue-flow-typedoc November 10, 2023 11:16 Inactive
@michealroberts michealroberts force-pushed the refactor/backward/vue-2-backwards-compat branch from e7b4e09 to e2ab4d4 Compare November 10, 2023 11:22
@vercel vercel bot temporarily deployed to Preview – vue-flow-typedoc November 10, 2023 11:22 Inactive
@bcakmakoglu
Copy link
Owner

No idea :/

@michealroberts michealroberts force-pushed the refactor/backward/vue-2-backwards-compat branch from e2ab4d4 to 7f756d7 Compare November 10, 2023 11:25
@vercel vercel bot temporarily deployed to Preview – vue-flow-typedoc November 10, 2023 11:25 Inactive
feat: migrated vue 2 backwards compatibility for @vue-flow/background
@michealroberts michealroberts force-pushed the refactor/backward/vue-2-backwards-compat branch from 7f756d7 to 95d49a0 Compare November 10, 2023 12:09
@vercel vercel bot temporarily deployed to Preview – vue-flow-typedoc November 10, 2023 12:09 Inactive
@bcakmakoglu
Copy link
Owner

Btw, appending + force pushing every commit you make messes up the comments on existing pieces of code ^^

You can just Squash the commits at the end instead of just forcing each time to preserve 1 commit

"peerDependencies": {
"@vue-flow/core": "^1.23.0",
"vue": "^3.3.0"
"@vue/composition-api": "^1.7.2",
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't this unnecessarily force composition api to be installed for Vue 3 users who don't even need this package?

Still think this should be optional: false instead

@michealroberts
Copy link
Author

@bcakmakoglu Yeh fair, sorry. Will squash at the end.

So some of my testing has found some quirky things to make this Vue 2 & Vue 3 compatible:

  • toRef doesn't work as expected with Vue 3, we have to use computed for Vue 2 to work reactively (I want to see if props are "reactive" inside render functions for both, will investigate this).
  • props need to be explicitly stated otherwise, Vue 2 does not pass them though correctly.
  • there is still a typing issue in the imported package, I am going to attempt to understand this today and reach out to the Volar team.

Comment on lines 4 to 5
import UserSelection from '../../components/UserSelection/UserSelection.vue'
import NodesSelection from '../../components/NodesSelection/NodesSelection.vue'
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no index file to import from so this would atm cause an error

fix: remove accidental push
@vercel vercel bot temporarily deployed to Preview – vue-flow-typedoc November 10, 2023 12:16 Inactive
@vercel vercel bot temporarily deployed to Preview – vue-flow-typedoc November 10, 2023 12:22 Inactive
@bcakmakoglu
Copy link
Owner

toRef doesn't work as expected with Vue 3, we have to use computed for Vue 2 to work reactively (I want to see if props are "reactive" inside render functions for both, will investigate this).

Bummer but should be fine for now

props need to be explicitly stated otherwise, Vue 2 does not pass them though correctly.

Yeah, seems so - though for maintenance it might be better to define the props object in another file? iirc you can import object prop definitions

there is still a typing issue in the imported package, I am going to attempt to understand this today and reach out to the Volar team.

"a typing" issue or is it that the types aren't properly hinted in general?

@michealroberts
Copy link
Author

Bummer but should be fine for now

I'll continue to dig into why this is, and understand the cause in the API disparity.

Yeah, seems so - though for maintenance it might be better to define the props object in another file? iirc you can import object prop definitions

Yeh I think we can do something like:

export default {
  props: {
    title: String,
    likes: Number
  }
}

"a typing" issue or is it that the types aren't properly hinted in general?

Yeh the hints is non-existing, and in the template usage where most of the mistakes will inevitably happen. I've reached out to the core team for some advice. I'm just not 100% sure ...

@bcakmakoglu
Copy link
Owner

I'll continue to dig into why this is, and understand the cause in the API disparity.

Well, toRef from @vueuse/core would probably work - I think the whole concept of MaybeRefOrGetter doesn't exist, even in Vue 2.7, making toRef(() => {} unusable anyway if I'm not mistaken.

toValue doesn't exist in Vue 2 either (which accepts a MaybeRefOrGetter type), which is another bummer.
This one was added pretty recently to the Vue 3 core API so no surprise here. Though this one is imported from @vueuse/core as I was using it even before it was part of the core API and atm there's an amigious export issue in the examples when I switch the import to vue (still investigating the reason for this problem)

Yeh the hints is non-existing, and in the template usage where most of the mistakes will inevitably happen. I've reached out to the core team for some advice. I'm just not 100% sure ...

Alright, let's wait and see :)

@michealroberts
Copy link
Author

@Braks Closing this one as I will refactor on top of the core migrated PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants