v-wave
v-wave copied to clipboard
Nuxt 3 Support
For people who are struggling using VWave with Nuxt 3
There are two problems with the current implementation:
- VWave needs to implement
getSSRProps
. - The method
serialize
does not exist in/nuxt/plugin.js
: https://github.com/justintaddei/v-wave/blob/34f26b639a306ef91b287c53785b8f4a38dbc642/nuxt/plugin.js#L4
So here is a workaround
- Create a new file in
plugins
folder, fe:plugins/vWave.directive.ts
- Paste this snippet:
import { defineNuxtPlugin } from '#app';
import VWave from 'v-wave';
// In this example, we rename the directive to `ripple`
const directiveName = 'ripple';
export default defineNuxtPlugin((app) => {
const { vWave, vWaveTrigger } = VWave.createLocalWaveDirective({}, app.vueApp);
app.vueApp.directive(directiveName, {
...vWave,
getSSRProps(binding, vnode) {
return {};
}
});
app.vueApp.directive(`${directiveName}-trigger`, {
...vWaveTrigger,
getSSRProps(binding, vnode) {
return {};
}
});
});
That's it. Touching nuxt.config.ts
is not needed.
Thank you for bringing this to my attention! I'll release support for Nuxt 3 in the next ~~day or two~~ week or two.
Hi @justintaddei, how is the progress going on supporting Nuxt 3?
@DamianGlowala delayed, but not forgotten. I haven't had a chance to work on this yet, but I plan to soon.
If anyone knows how to make this change with backwards compatibility for Nuxt 2 please let me know.
@justintaddei It's better you create another git repo for NuxT 3+ versions.
After some research, it seems impossible to support both Nuxt 2 and 3 in the same package.
Going forward:
- I will migrate to Nuxt 3 for
@latest
releases. This will be a breaking change and bump the version tov2.0.0
- Nuxt 2 support will continue in a separate branch and will continue to be released under
v1.x
version numbers and tagged with@nuxt2
to allow for easy installation in Nuxt 2 projects ($ npm install v-wave@nuxt2
). - Nuxt 2 and 3 versions will maintain feature parody.
-
v-wave
has always maintained backwards compatibility in the past. For future changes, this will be a requirement due to the use ofv1.x
for Nuxt 2 andv2.x
for Nuxt 3. Thev-wave
API has been stable for a long time now, so I don't see this causing any issues.
Migration to Nuxt 3 will take place sometime in the next few weeks, depending on my schedule.
Nice ! I am impatient to see that, your plugin is really usefull for me ! Thx for your work ❤️
@razorness Hey, do you have a working workaround for this project (https://github.com/justintaddei/v-shared-element/issues/244) as well (Should be the same issue)? Unfortunately, I can't get it to work myself :( It would be really awesome if that's possible. Many thanks in advance and best regards.
@yldshv I am not using Nuxt. Sorry.
But take a short look into the example. You can access the Vue app instance via app.vueApp
. Take another look into the install method of your wanted Vue 3 extension:
https://github.com/justintaddei/v-shared-element/blob/5ab337b02b669bcbbd029f842d41651df7a6356d/src/index.ts#L151-L156
Since v-shared-element is a little stingy with exports, I think you need to trick the install method by mocking an object which looks like a Vue 3 app instance to catch illusory
, $createIllusoryElement
and the result of insertedMounted()
. Then add this by yourself like the example above.
SharedElementRouteGuard
could be bound via defineNuxtRouteMiddleware
. Dont apply this guard in SSR context.
@yldshv I am not using Nuxt. Sorry.
But take a short look into the example. You can access the Vue app instance via
app.vueApp
. Take another look into the install method of your wanted Vue 3 extension:https://github.com/justintaddei/v-shared-element/blob/5ab337b02b669bcbbd029f842d41651df7a6356d/src/index.ts#L151-L156
Since v-shared-element is a little stingy with exports, I think you need to trick the install method by mocking an object which looks like a Vue 3 app instance to catch
illusory
,$createIllusoryElement
and the result ofinsertedMounted()
. Then add this by yourself like the example above.
SharedElementRouteGuard
could be bound viadefineNuxtRouteMiddleware
. Dont apply this guard in SSR context.
Thank you @razorness. I will give it a shot :D
Hey everyone! I just wanted to leave an update here. I haven't forgotten about this :)
Nuxt 3 support is still planned but I cannot give an ETA at this time. As soon as my schedule clears up, I will begin working on it.
Hi @justintaddei ! Did you have any news about a potential planification for Nuxt 3 support ? I'm a little impatient to implement it into my web site :3
@NtchPlayer tentatively planned for the first week of November!
Hi everyone!
I've had an idea that would allow for nuxt2 and nuxt3 installs with the same version of v-wave. This removes the necessity of the breaking change detailed in this comment.
I came up with this approach after not having much luck creating a nuxt module that can exist alongside a vanilla vue plugin. That is, I don't want to use nuxt's module builder because this isn't a nuxt module... it's a vue plugin with nuxt support. If anyone has more experience working with modules in nuxt 3 and knows how to achieve the same behavior that exists for nuxt 2, please enlighten me :)
!!! I'm not sure if this is a good solution. Please provide feedback if you don't like this approach !!!
You can test this locally by installing
v-wave@beta
:$ npm i v-wave@beta
nuxt@^2.x.x
installation steps remain the same and still use the @latest
release.
When installing v-wave
into a nuxt3 project, a postinstall
script is run that will create the necessary plugin files (this is all that is needed for v-wave
to work inside of nuxt because auto-import will pick these up):
The file that registers the plugin (this will also be where global v-wave
options are set):
// v-wave.client.ts
import vWave, { type IVWavePluginOptions } from 'v-wave'
export const options: Partial<IVWavePluginOptions> = {
// Place any global v-wave options here
}
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.use(vWave, options)
})
And a stub that is needed when registering directives:
(https://nuxt.com/docs/guide/directory-structure/plugins#vue-directives) If you register a Vue directive, you must register it on both client and server side unless you are only using it when rendering one side. If the directive only makes sense from a client side, you can always move it to ~/plugins/my-directive.client.ts and provide a 'stub' directive for the server in ~/plugins/my-directive.server.ts.
// v-wave.server.ts
import { options } from './v-wave.client';
export default defineNuxtPlugin(({ vueApp }) => {
vueApp.directive(options.directive ?? 'wave', {});
vueApp.directive(`${options.directive ?? 'wave'}-trigger`, {});
});
A fresh nuxt 3 project with v-wave installed:
So far the install script is as follows (this will need to be more robust before it's ready for a stable release, but it gets the point across at least):
const fs = require('fs')
const path = require('path')
const pkg = require(path.join(process.env.INIT_CWD, 'package.json'))
const nuxtVersion = pkg.dependencies?.nuxt ?? pkg.devDependencies?.nuxt
if (!nuxtVersion || /2\.\d+\.\d+/.test(nuxtVersion)) {
process.exit(0)
}
if (!fs.existsSync(path.join(process.env.INIT_CWD, 'plugins'))) {
fs.mkdirSync(path.join(process.env.INIT_CWD, 'plugins'))
}
try {
fs.copyFileSync(
path.join(__dirname, 'v-wave.client.ts'),
path.join(process.env.INIT_CWD, 'plugins', 'v-wave.client.ts'),
fs.constants.COPYFILE_EXCL
)
fs.copyFileSync(
path.join(__dirname, 'v-wave.server.ts'),
path.join(process.env.INIT_CWD, 'plugins', 'v-wave.server.ts'),
fs.constants.COPYFILE_EXCL
)
} catch (e) {
process.exit(0)
}
However, on second thought, the better approach might just be to provide the boilerplate for nuxt in the readme instead of dealing with the complexity of auto-generating the file.
What do you guys think?
Hum, I have any experience with Nuxt module creation :'( A create some directive for me (image lazy loading as exemple). I never take time to try to create my own plugin. I don't know if you can get more help on the [nuxt official discord server] ? (https://discord.com/invite/nuxt) (oh, I just see that you already join it today ^^)
I can say that, I use vue masonry on my project, and I have two configuration (one for the server side and one for client side like you suggest) because vue masonry works only on client side.
// @/plugins/vue-masonry.js
export default defineNuxtPlugin(async (nuxtApp) => {
if (process.server) {
nuxtApp.vueApp.directive('masonry', {})
nuxtApp.vueApp.directive('masonry-tile', {})
}
if (process.client) {
const { VueMasonryPlugin } = await import('vue-masonry')
nuxtApp.vueApp.use(VueMasonryPlugin)
}
})
Thanks @NtchPlayer. Yeah, I joined the discord and asked around but nothing useful has come of that yet.
Currently, what works for me perfectly fine is the following plugin:
import VWave from "v-wave";
const directiveName = "ripple";
export default defineNuxtPlugin((app) => {
const { vWave, vWaveTrigger } = VWave.createLocalWaveDirective(
{},
app.vueApp
);
app.vueApp.directive(directiveName, {
...vWave,
getSSRProps() {
return {};
}
});
app.vueApp.directive(`${directiveName}-trigger`, {
...vWaveTrigger,
getSSRProps() {
return {};
}
});
});
What about creating a Nuxt module which would inject a plugin file with the above content?
import { defineNuxtModule, addPlugin, createResolver } from '@nuxt/kit'
export default defineNuxtModule({
setup (options, nuxt) {
const { resolve } = createResolver(import.meta.url)
addPlugin(resolve('<path-to-plugin>'))
}
})
Hi everyone!
I've had an idea that would allow for nuxt2 and nuxt3 installs with the same version of v-wave. This removes the necessity of the breaking change detailed in this comment.
I came up with this approach after not having much luck creating a nuxt module that can exist alongside a vanilla vue plugin. That is, I don't want to use nuxt's module builder because this isn't a nuxt module... it's a vue plugin with nuxt support. If anyone has more experience working with modules in nuxt 3 and knows how to achieve the same behavior that exists for nuxt 2, please enlighten me :)
!!! I'm not sure if this is a good solution. Please provide feedback if you don't like this approach !!!
You can test this locally by installing
v-wave@beta
:$ npm i v-wave@beta
nuxt@^2.x.x
installation steps remain the same and still use the@latest
release.When installing
v-wave
into a nuxt3 project, apostinstall
script is run that will create the necessary plugin files (this is all that is needed forv-wave
to work inside of nuxt because auto-import will pick these up):The file that registers the plugin (this will also be where global
v-wave
options are set):// v-wave.client.ts import vWave, { type IVWavePluginOptions } from 'v-wave' export const options: Partial<IVWavePluginOptions> = { // Place any global v-wave options here } export default defineNuxtPlugin((nuxtApp) => { nuxtApp.vueApp.use(vWave, options) })
And a stub that is needed when registering directives:
(https://nuxt.com/docs/guide/directory-structure/plugins#vue-directives) If you register a Vue directive, you must register it on both client and server side unless you are only using it when rendering one side. If the directive only makes sense from a client side, you can always move it to ~/plugins/my-directive.client.ts and provide a 'stub' directive for the server in ~/plugins/my-directive.server.ts.
// v-wave.server.ts import { options } from './v-wave.client'; export default defineNuxtPlugin(({ vueApp }) => { vueApp.directive(options.directive ?? 'wave', {}); vueApp.directive(`${options.directive ?? 'wave'}-trigger`, {}); });
A fresh nuxt 3 project with v-wave installed:
So far the install script is as follows (this will need to be more robust before it's ready for a stable release, but it gets the point across at least):
const fs = require('fs') const path = require('path') const pkg = require(path.join(process.env.INIT_CWD, 'package.json')) const nuxtVersion = pkg.dependencies?.nuxt ?? pkg.devDependencies?.nuxt if (!nuxtVersion || /2\.\d+\.\d+/.test(nuxtVersion)) { process.exit(0) } if (!fs.existsSync(path.join(process.env.INIT_CWD, 'plugins'))) { fs.mkdirSync(path.join(process.env.INIT_CWD, 'plugins')) } try { fs.copyFileSync( path.join(__dirname, 'v-wave.client.ts'), path.join(process.env.INIT_CWD, 'plugins', 'v-wave.client.ts'), fs.constants.COPYFILE_EXCL ) fs.copyFileSync( path.join(__dirname, 'v-wave.server.ts'), path.join(process.env.INIT_CWD, 'plugins', 'v-wave.server.ts'), fs.constants.COPYFILE_EXCL ) } catch (e) { process.exit(0) }
is this a guide on how to setup v-wave in Nuxt 3 ? I dont get the last code that is in your reply, If you could add some instructions for nuxt 3 to the document would be a very big help :) I really appriciate it
@amirsafaricg it's not a guide... just an idea for how I might move forward with the upgrade. I have a working solution for Nuxt 3 that I finished today. It should be backwards compatible with Nuxt 2 as well but I need to wait until tomorrow before I can test that. Either way, expect a release with Nuxt 3 support tomorrow or Wednesday!
@amirsafaricg in the mean time this will get you up and running with v-wave in Nuxt 3:
npm install v-wave@beta && rm -rf ./node_modules/v-wave/dist/cjs
All other steps are the same as is described in the current docs
That's really great to hear ! I'm really happy to hear that ! Ill wait until Wednesday its definitely worth the wait. The v-wave directive is too useful to be rushed. Ill wait until you finish it ;)
Thanks really !
Nuxt 3 support added in #593.
Release v2.0.0
is live on npm. Please use npm i v-wave@latest
to update your projects.
The breaking change is due v-wave@^2.0.0
not being backward compatible with Nuxt 2. Installation and usage of v-wave@^2.0.0
in a Nuxt 3 project is identical to v-wave@^1.0.0
in a Nuxt 2 project.
If you have any issues getting it to work in your project, please feel free to open another issue!
I just install version 2.0.0 and it's work perfectly ! Thx you for your work 😄