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

Expose vite/webpack client config #14534

Open
3 of 4 tasks
ZachJW34 opened this issue Aug 10, 2022 · 13 comments
Open
3 of 4 tasks

Expose vite/webpack client config #14534

ZachJW34 opened this issue Aug 10, 2022 · 13 comments

Comments

@ZachJW34
Copy link

Describe the feature

Exposing the vite/webpack client config would enable external tools (such a Cypress Component Testing) to integrate with Nuxt.

For context, Cypress supports component testing Nuxt 2 components by utilizing the getWebpackConfig function. We grab the config, modify it and spin up a dev-server to serve spec files that can mount and interact with components.

With Nuxt 3, there is no longer a standalone, exported function that can be utilized.

The current implementation couples the sourcing of the config with the compilation/dev-server:

  • For Vite, bundle creates a base config and then calls bundleClient that extends the base config and starts the vite dev-server
  • For Webpack, bundle sources the client webpack config and invokes webpack.compile

Exposing the sourcing of the config as a standalone function would enable external devtools to utilize Nuxt's setup. This could be useful outside of Cypress Component Testing, such as a user wanting to test components using Vitest. Reading through the code, it looks like there would only need to be some small tweaks to consolidate the config sourcing, and we (the Cypress team) would be happy to contribute if this is something the Nuxt team would consider!

Additional information

  • Would you be willing to help implement this feature?
  • Could this feature be implemented as a module?

Final checks

@lmiller1990
Copy link

lmiller1990 commented Aug 11, 2022

Over the years of working on Test Utils, many people have reported issues trying to test components that rely on Nuxt patterns that is not available in Test Utils (such as the automatic component resolution, automatically calling asyncData etc). My understanding Nuxt 3 also injects composables, too, which means anything attempting to consume these components outside of the Nuxt pipeline would not have access to those.

Exposing these kinds of internals (even if it's not officially documented) could let third party solutions that are focused on testing take the burden off the Nuxt maintainers, and also allow for a more vibrant ecosystem of solutions. We experimented with something similar Vue core by exposing some specific, undocumented APIs for testing. This lets a separate team focus on maintaining a testing solution, so Evan can focus on the core functionality.

It looks like Nuxt already has some recommendations around testing. Curious as to what's coming for testing in a browser? This is something we are solving at Cypress - I wonder if we can work together on this? We definitely can (and do) make accommodations for framework specific patterns.

It feels like this could be a net-win for everyone - especially the users who use Nuxt to build things.

@pi0
Copy link
Member

pi0 commented Aug 11, 2022

Hi, @ZachJW34 @lmiller1990 I appreciate your ideas and am willing to contribute to improve browser testing with Nuxt 3 and Cypress 🚀

As @lmiller1990 mentioned, exposing bundler (vite and webpack) configuration is probably not enough for a stable environment testing Nuxt components. Nuxt 3 is a full stack framework with quite complex setup for auto imports, virtual filesystem and server isolation powered by Nitro.

We are working on new idea called "Component Islands" starting with adding server component islands (#5689) but this architecture could be extended to Client Component Islands as well. This gives external testing framework such as Cypress an API to both server render a component and mount it in a browser environment for unit testing. While ensuring exactly same Nuxt setup and environment is provided. This is a new opportunity we have with Nuxt 3 design to overcome main limitations in Nuxt 2 and making cypress nuxt module.

BTW out of curiosity, I made a working POC using @nuxt/kit to resolve the vite configuration:

https://stackblitz.com/edit/nuxt-starter-yk8get?file=nuxt-vite-config.mjs

@ZachJW34
Copy link
Author

The work for testing component islands looks really interesting! For our Cypress Nuxt 2 support, we never had the ability to incorporate any server-side features so the possibility that we can bring these new features into our Nuxt 3 support is really exciting. Your POC is also very helpful, will try to hook it up into a spike I was working on (looks like I can use the same logic for grabbing webpack as well)

@danielroe
Copy link
Member

Linking this here just in case it's useful: https://github.com/histoire-dev/histoire/blob/main/packages/histoire-plugin-nuxt/src/index.ts#L56

@tobiasdiez
Copy link
Contributor

Is there also a way to get the vite config from a running nuxt process, e.g. something like useNuxt().getViteConfig()? The problem with the above approach is that the vite:extendConfig hook has already been called in my case, so useNuxt().hook('vite:extendConfig', ...) is not working.

Copy link
Member

@tobiasdiez A lot of experimentation is happening at the moment in https://github.com/danielroe/nuxt-vitest - it might be interesting for your own efforts to check out what we're trying there.

@tobiasdiez
Copy link
Contributor

Thanks for the pointer. I was actually using the code from nuxt-vitest to get the vite config. It works great if you do this from a new process. But if you try to reuse an existing nuxt instance (provided via tryUseNuxt), then this part https://github.com/danielroe/nuxt-vitest/blob/3090ccf5152351e704486b3c2b79e20e361bf5dc/packages/nuxt-vitest/src/config.ts#L33-L43 doesn't work.

Or were you referring to a different part of nuxt-vitest?

@floroz
Copy link

floroz commented Feb 4, 2023

@tobiasdiez A lot of experimentation is happening at the moment in https://github.com/danielroe/nuxt-vitest - it might be interesting for your own efforts to check out what we're trying there.

is there any experimentation about making Nuxt 3 compatible with Cypress Component Testing?

@manniL
Copy link
Member

manniL commented Feb 5, 2023

@tobiasdiez A lot of experimentation is happening at the moment in danielroe/nuxt-vitest - it might be interesting for your own efforts to check out what we're trying there.

is there any experimentation about making Nuxt 3 compatible with Cypress Component Testing?

I'd suggest to create a new dedicated issue for that if it does not exist.

@lmiller1990
Copy link

There is an issue in Cypress for this: cypress-io/cypress#23619

Due to recent events, our team has limited resources and this is not something we are actively working on.

To make Nuxt 3 work with Cypress (or Vitest, or anything), you need some way to do the Nuxt injections (like Vue imports, etc). In Cypress, this basically means passing a custom Vite config (I assume this is how Nuxt works - using a Vite/webpack config under the hood to handle the injections).

There's some info here https://docs.cypress.io/guides/component-testing/vue/overview#Vite-Configuration

Basically, it'll be something like:

// cypress.config.ts
const { defineConfig } = require('cypress')

module.exports = defineConfig({
  component: {
    devServer: {
      framework: 'vue',
      bundler: 'vite',
      viteConfig: async () => {
        // get Nuxt vite config
        // return it
      }
    },
  },
})

This should be all we need to do. That's why the original issue was created - if we can grab the config (which looks like it's possible, in some fashion) it should all "just work" - at least all the client side code (not sure about handling code that needs to run on the server, or SSR - has anyone got this working, in Vitest or any test runner?)

@danielroe
Copy link
Member

We don't plan to include a utility for this within Nuxt, but more than happy to document how to do it for integrations; I do completely understand that they need to have access to Nuxt's vite/webpack config.

Some examples:

And, elegantly, from @pi0:

import { loadNuxt, buildNuxt } from '@nuxt/kit';

// https://github.com/nuxt/framework/issues/6496
async function getViteConfig() {
  const nuxt = await loadNuxt({ cwd: process.cwd(), dev: false, ssr: false });
  return new Promise((resolve, reject) => {
    nuxt.hook('vite:extendConfig', (config) => {
      resolve(config);
      throw new Error('_stop_');
    });
    buildNuxt(nuxt).catch((err) => {
      if (!err.toString().includes('_stop_')) {
        reject(err);
      }
    });
  }).finally(() => nuxt.close());
}

const viteConfig = await getViteConfig();
console.log(viteConfig);

PR opened to add this to the docs: #18812.

@danielroe danielroe closed this as not planned Won't fix, can't repro, duplicate, stale Feb 6, 2023
@danielroe danielroe reopened this Feb 6, 2023
@floroz
Copy link

floroz commented Feb 6, 2023

Moving this discussion to the Cypress team: cypress-io/cypress#25719

@lmiller1990
Copy link

lmiller1990 commented Feb 6, 2023

Thanks for at least making the decision clear @danielroe. Is there a similar snippet for webpack?

Also, any recommendation around how we might test components with SSR behavior? Without starting the Nuxt server, this might not be practical/possible - I guess E2E tests?

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