tsparticles / vue3

Vue.js tsParticles official component
MIT License
106 stars 6 forks source link

refactor: Use vue-demi w/ unbuild workflow #33

Closed Joepocalyptic closed 9 months ago

Joepocalyptic commented 10 months ago

This should make the component fully compatible with Vue 2 and Vue 3 by delegating interop to the vue-demi library. However, this required a refactor of the build step to use unbuild configured to skip compiling the Vue SFC.

The component is lumped into one @tsparticles/vue module now in preparation for hosting under that npm scope. If you'd like me to undo this, just let me know.

Ideally, we'd also have a testing ground for Vue 2 with Vite and/or Nuxt 2, but that seems to be pretty janky under a pnpm workspace from my testing due to dependency conflicts. I'll let you know if I find a solution that can keep those tests in the same repo. I did manually confirm the code to be building and running under Vue 2.7.

I also cleaned up the Nuxt and Vite examples a little further; all of the dependency bloat should be gone now.

matteobruni commented 10 months ago

I've given a fast look on the PR, the new package name is fine, but the Vue 2.x demos are missing, I'd like to keep them for testing new releases

matteobruni commented 10 months ago

The tsParticles package v3.0.0-beta.1 is out and can be used for this.

@tsparticles/engine is the package

Joepocalyptic commented 10 months ago

Are there any major changes this package should conform to? I updated and it seems the demos from tsparticles-demo-configs no longer work; I modified the demos to use one taken from the website.

The particlesInit function will probably disappear in the next major, for a function called once per application. It's something I'm still thinking to do.

Is this implemented yet? I noticed a second refresh parameter on loadFull; not sure if that correlates.

Joepocalyptic commented 10 months ago

There's quite a bit going on here:

I updated and it seems the demos from tsparticles-demo-configs no longer work

I used the Among Us example, and the background "star" particles disappear after the first character slides off the screen. You can run dev in apps/nuxt3 to reproduce this. I'm assuming this is an issue with the upstream @tsparticles/engine. I also tried a config from my old portfolio website and it wasn't working at all (https://portfolio-rose-ten.vercel.app/particlesjs-config.json).

Let me know if you have any questions or thoughts.

matteobruni commented 10 months ago

Are there any major changes this package should conform to? I updated and it seems the demos from tsparticles-demo-configs no longer work; I modified the demos to use one taken from the website.

The particlesInit function will probably disappear in the next major, for a function called once per application. It's something I'm still thinking to do.

Is this implemented yet? I noticed a second refresh parameter on loadFull; not sure if that correlates.

All packages called tsparticles- are now renamed to @tsparticles/, all version 3.0.0-beta.1

The particlesInit function is part of the component, we need to get rid of it in this version. The refresh parameter is not necessary here, the function will be called by the component user, and it's better to call it with the default true value. It's useful when you have to load multiple plugins at once, you can pass true only to the last load call, so the refresh will happen only once.

Other breaking changes are in the options, all the deprecated values are removed from the options management, so values with _ in the name, are not working anymore.

Joepocalyptic commented 10 months ago

The particlesInit function is part of the component, we need to get rid of it in this version. The refresh parameter is not necessary here, the function will be called by the component user, and it's better to call it with the default true value. It's useful when you have to load multiple plugins at once, you can pass true only to the last load call, so the refresh will happen only once.

So if I'm understanding this correctly, it's entirely up to the end user now to call loadFull or similar in the right place now? If so, will this be automated in some way, or just added as an installation instruction in the documentation?

Also, @tsparticles/demo-configs currently only has 3.0.0-alpha.1 published.

matteobruni commented 10 months ago

The particlesInit function is part of the component, we need to get rid of it in this version. The refresh parameter is not necessary here, the function will be called by the component user, and it's better to call it with the default true value. It's useful when you have to load multiple plugins at once, you can pass true only to the last load call, so the refresh will happen only once.

So if I'm understanding this correctly, it's entirely up to the end user now to call loadFull or similar in the right place now? If so, will this be automated in some way, or just added as an installation instruction in the documentation?

Also, @tsparticles/demo-configs currently only has 3.0.0-alpha.1 published.

loadFull or other plugins are already external to the component, that’s why the particlesInit is there.

I forgot, the configs package is @tsparticles/configs

Joepocalyptic commented 10 months ago

That does create some weird implications specifically for Vue, then. Vue doesn't support running blocking async code before a child component (like <Particles>) is mounted. In this case, you would have to use top-level await inside of a component whose parent is a <Suspense> boundary, so this would have to be documented. The alternative is to escape the Vue context by running await loadFull(tsParticles) before mounting the entire Vue app, but this obviously isn't ideal for performance.

Nuxt 3 handles this pretty cleanly because the entire app is already inside of a <Suspense> boundary, so you can use top-level await anywhere (see apps/nuxt3 for an example of this). However, I think this could be greatly simplified for most use-cases with Nuxt 3. I built a little Nuxt module (Joepocalyptic/nuxt-particles) which utilizes Nuxt's useState composable to lazy-load the library without any extra work, with the option to fall back to loading the library before the Vue app is mounted like I described earlier.

You're free to advertise this module for Nuxt 3 users if you'd like. Alternatively, I'd be happy to integrate it into this monorepo in another PR if that's alright with you (maybe we could expose it as something like @tsparticles/nuxt?).

matteobruni commented 10 months ago

That's why I was thinking of migrating the particlesInit out of the component, some kind of plugin setup, a function to call in the app file, or something like that, that's a change I want to make for all the frameworks supported. I had this issue with Astro and I started thinking about moving this away for all packages

matteobruni commented 10 months ago

I thought sometimes to create a Nuxt module (also for Next) but I always thought that the Vue (or React) component was enough. If you think that a Nuxt module would be a benefit, it can be added, I think I can create two repositories, tsparticles/vue for the generic package, migrating this PR there, and tsparticles/nuxt (supporting both 2 and 3?)

Joepocalyptic commented 10 months ago

Is there any reason you'd be opposed to keeping the Nuxt module in the same monorepo as the Vue implementation? That's how most Vue libraries work from what I've seen, and it'd likely make more sense for end users imo.

The reason a Nuxt-specific module would be useful is because while hoisting the library loading to a once-per-app function on the client is probably the best solution, that's going to look different for every framework (and metaframework) depending on how it structures its application. Even for the module I created, I found 2 options for Nuxt 3 specifically: unconditionally loading the library before the Vue app is mounted through a Nuxt client plugin (most obvious), and lazy-loading the library on-demand once a <NuxtParticles> component is loaded for the first time (most performant).

I set up both of those options to use a global config (the particles key in nuxt.config.ts) by default, since that would work for the majority of applications unless they're really pushing the library and how it's loaded to its limits. It's really just a matter of DX, which Nuxt really focuses on (many Nuxt modules like that one are created just to convert relatively complex boilerplate into a plug-and-play solution).

matteobruni commented 10 months ago

No I always thought it wasn't necessary because of the existing Vue.js library, I don't use Nuxt, Next or similar framework every day, so I think it's mainly lack of knowledge.

I've created the Vue.js repository here: https://github.com/tsparticles/vue

We can have both libraries here Vue.js and Nuxt, with the global readme describing both, and every library readme more specific.

Is the Nuxt package using the Vue package, or are they two independent implementations?

Joepocalyptic commented 10 months ago

Right now, the Nuxt module is running a custom implementation so that I didn't have to wait for the new version of vue3-particles to be released to update the API. With the current changes on dev, though, I should be able to refactor it to use @tsparticles/vue as a base.

It currently only has Nuxt 3 support because I'm not familiar with developing modules for Nuxt 2, but it's theoretically possible to use the same module for both versions of Nuxt (especially now that we're using vue-demi). I'll see what I can do!

On another note, I noticed an old PR where you expressed interest in remaking the website. It looks like the current tech stack is rather outdated, but I'm quite familiar with developing documentation sites with Nuxt and Docus (I've developed many internal projects that utilize it for technical docs at a corporation, plus 99% of the code is still Markdown). If you're open to switching up the stack, maybe I could give a rewrite a go in my spare time? A docs overhaul would likely be a great accompaniment for v3.

matteobruni commented 10 months ago

I want to keep the website vanilla because the main engine is made like that. Any rework of the website is welcome

matteobruni commented 9 months ago

Closing this here, since the tsparticles/vue repository is live, empty but it can be used for this PR and a single package for all Vue versions