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

Nuxt 3 Support #351

Closed
razorness opened this issue Jul 25, 2022 · 24 comments
Closed

Nuxt 3 Support #351

razorness opened this issue Jul 25, 2022 · 24 comments
Assignees
Milestone

Comments

@razorness
Copy link

For people who are struggling using VWave with Nuxt 3

There are two problems with the current implementation:

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.

@justintaddei justintaddei self-assigned this Jul 26, 2022
@justintaddei
Copy link
Owner

justintaddei commented Jul 26, 2022

Thank you for bringing this to my attention! I'll release support for Nuxt 3 in the next day or two week or two.

@DamianGlowala
Copy link
Contributor

Hi @justintaddei, how is the progress going on supporting Nuxt 3?

@justintaddei
Copy link
Owner

@DamianGlowala delayed, but not forgotten. I haven't had a chance to work on this yet, but I plan to soon.

@justintaddei
Copy link
Owner

If anyone knows how to make this change with backwards compatibility for Nuxt 2 please let me know.

@RejownAhmed
Copy link

@justintaddei It's better you create another git repo for NuxT 3+ versions.

@justintaddei
Copy link
Owner

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 to v2.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 of v1.x for Nuxt 2 and v2.x for Nuxt 3. The v-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.

@NtchPlayer
Copy link

Nice ! I am impatient to see that, your plugin is really usefull for me ! Thx for your work ❤️

@yldshv
Copy link

yldshv commented Aug 16, 2023

@razorness
Hey, do you have a working workaround for this project (justintaddei/v-shared-element#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.

@razorness
Copy link
Author

@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
Copy link

yldshv commented Aug 17, 2023

@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.

Thank you @razorness. I will give it a shot :D

@justintaddei
Copy link
Owner

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.

@NtchPlayer
Copy link

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

@justintaddei
Copy link
Owner

@NtchPlayer tentatively planned for the first week of November!

@justintaddei
Copy link
Owner

justintaddei commented Nov 7, 2023

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:
image

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)
}

@justintaddei
Copy link
Owner

justintaddei commented Nov 7, 2023

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?

@NtchPlayer
Copy link

NtchPlayer commented Nov 7, 2023

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)
  }
})

@justintaddei
Copy link
Owner

Thanks @NtchPlayer. Yeah, I joined the discord and asked around but nothing useful has come of that yet.

@DamianGlowala
Copy link
Contributor

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>'))
  }
})

@amirsafaricg
Copy link

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: image

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

@justintaddei
Copy link
Owner

@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!

@justintaddei
Copy link
Owner

@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

@amirsafaricg
Copy link

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 !

@justintaddei
Copy link
Owner

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!

@NtchPlayer
Copy link

I just install version 2.0.0 and it's work perfectly ! Thx you for your work 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants