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

Cannot import { runCommand } from 'nuxi' since 3.9.2 #331

Closed
fabianwohlfart opened this issue Jan 22, 2024 · 14 comments
Closed

Cannot import { runCommand } from 'nuxi' since 3.9.2 #331

fabianwohlfart opened this issue Jan 22, 2024 · 14 comments

Comments

@fabianwohlfart
Copy link

fabianwohlfart commented Jan 22, 2024

Environment

  • Operating System: Darwin
  • Node Version: v18.19.0
  • Nuxt Version: 3.9.3
  • CLI Version: 3.10.0
  • Nitro Version: 2.8.1
  • Package Manager: npm@10.2.3
  • Builder: -
  • User Config: -
  • Runtime Modules: -
  • Build Modules: -

Reproduction

import { runCommand } from 'nuxi'
https://stackblitz.com/edit/github-ebvksd?file=server%2Fapi%2Fgenerate.js

Describe the bug

Since Nuxt 3.9.2 I cannot import runCommand from nuxi anylonger.

Additional context

No response

Logs

This module cannot be importedin server runtime. [importing nuxi from server/api/generate.get.js]
Copy link

Would you be able to provide a reproduction? 🙏

More info

Why do I need to provide a reproduction?

Reproductions make it possible for us to triage and fix issues quickly with a relatively small team. It helps us discover the source of the problem, and also can reveal assumptions you or we might be making.

What will happen?

If you've provided a reproduction, we'll remove the label and try to reproduce the issue. If we can, we'll mark it as a bug and prioritize it based on its severity and how many people we think it might affect.

If needs reproduction labeled issues don't receive any substantial activity (e.g., new comments featuring a reproduction link), we'll close them. That's not because we don't care! At any point, feel free to comment with a reproduction and we'll reopen it.

How can I create a reproduction?

We have a couple of templates for starting with a minimal reproduction:

👉 https://stackblitz.com/github/nuxt/starter/tree/v3-stackblitz
👉 https://codesandbox.io/s/github/nuxt/starter/v3-codesandbox

A public GitHub repository is also perfect. 👌

Please ensure that the reproduction is as minimal as possible. See more details in our guide.

You might also find these other articles interesting and/or helpful:

Copy link

stackblitz bot commented Jan 22, 2024

Fix this issue in StackBlitz Codeflow Start a new pull request in StackBlitz Codeflow.

@pi0 pi0 transferred this issue from nuxt/nuxt Jan 22, 2024
@pi0
Copy link
Member

pi0 commented Jan 22, 2024

Hi. The runCommand export is available in latest nuxi builds only please consider that it is an ESM only package made for build time. You should not import it from runtime files (composables or server/directory). For CommonJS, you might use await import('nuxi')

See this example: https://github.com/unjs/docs/blob/main/src/cli.ts#L41

@pi0 pi0 closed this as not planned Won't fix, can't repro, duplicate, stale Jan 22, 2024
@fabianwohlfart
Copy link
Author

Hello! But wait, why? It was possible all the time since Nuxt 3.0.0, and I already built some websites utilizing this, so they run in build and making a snapshots via runCommand('generate'). Why should I not do it? It works perfectly?!

@pi0
Copy link
Member

pi0 commented Jan 22, 2024

I'm not sure to understand how it was supposed to work. CLI is used to itself build a Nuxt/Nitro application and generate etc. Importing CLI itself in runtime is not intended to be done (even if it was working before by any chance, it was chance!)

If you would explain more context of your usecase (why you need a server route that itself runs generate command) and how you deploy such usage, i might be able to give an alternative solution.

@fabianwohlfart
Copy link
Author

The idea is simple: If you run a nuxt website in build you can easily add functionality that makes use of server routes, for example generating a pdf, catching open-graph data or resizing media. The media endpoint for example is very important; if you are connected to a CMS you can easily build a system where you have live previews of the content. That would be impossible in generate. On the other side I want to have a statically generated website in production.
So the solution is, that I use build to have a staging website, connected to my CMS, with live previews etc.
Once the editor hit's publish, in the CMS, the website generates and deploys itself to any host.

To be able to directly import runCommand is the better alternative, otherwise I would need to spawn a child process with the same cli command. And side-effects are my problem anyways, so I would speak out for keeping the option, but maybe with a warning. But let me know why it's not intended to be available in runtime?! I think it's a plus to use these commands programmatically in routes.

@pi0
Copy link
Member

pi0 commented Jan 22, 2024

Thanks for explaining your use-case.

As a much better alternative, I suggest you try the hybrid rendering with caching rules that is available in Nuxt 3. This method gives the flexibility of caching on demand and generating content from a CMS source and removing the limitations of traditional generate command.

I explained before. CLI or non of Nuxt build dependencies (such as @nuxt/kit) are built to build your application not run inside it. It can cause lots of many unpredictable behaviors and regressions we wouln't be able to support you in the future.

If finally you want to keep your architecture as-is (while I really would advice against), you have two options:

  • Spawn process within server routes as you suggested -- it might be little safer!
  • Trick Nuxt to bypass the limitation -- because you can do it! (on your own risk!)
export default defineEventHandler(async (event) => {
  // Use absolutely on YOUR OWN RISK!
  const _pkg = 'nuxi';
  const { runCommand } = await import(_pkg);
  return true;
});

@fabianwohlfart
Copy link
Author

And thanks for going along with me :)

The thing with hybrid rendering is that it needs a specific hosting (node). Reality strikes as not all my clients can do this, despite the fact that hosting in Germany (and probably EU) is a mess and still all about php… On the other hand if you use the system described above you can host the staging website on your own servers and deploy a statically generate website to any host or CDN, regardless of your clients IT infrastructure, and that's nice and easy. This works for me for quite some time now (~5years), already with Nuxt 2 I had a similar approach to scope with all the non-streamlined hosting-providers. I never had any major problems. If you change buildDirs and output.dirs regarding the process, then generate will have it's own dirs and be completely encapsulated.

Thanks for the work-arounds, will use them on my very own risk!

@manniL
Copy link
Member

manniL commented Jan 22, 2024

@pi0 Do you think that's something the Nitro Task API could "cover" later one?

@pi0
Copy link
Member

pi0 commented Jan 22, 2024

The thing with hybrid rendering is that it needs a specific hosting (node).

Actually... You can :) You can have hybrid rendering in ANY hosting and storage method that complies with your regulations. All you have to do is to configure cache storage mount point for the storage provider (which can be and by default is fs. effectively same as generate command)

Yes generate is sweet but it had enough limitations in the past that others made ISR and we made Nuxt 3 with hybrid rendering. If any time later you wanted to give it a try or had any specific concerns, feel free to reach me out via Discord (pi0). Nuxt Labs also has consulting services to help you on this path.

Do you think that's something the nitrojs/nitro#1974 could "cover" later one?

@manniL It seems tempting and a similar somehow but unfortunately No. Tasks API are still a "Runtime" API. Running a build-time CLI still shared same.

We might think of a programmatic API that populates the hybrid rendering cache though using Tasks API but it is nothing we can't today with a protected route. But with upcoming Tasks API would be easier to do.

@fabianwohlfart
Copy link
Author

I think there is a missunderstanding. I mean in an environment where it's not possible to run any node command, so not run build nor run generate, so no nuxt mode despite the finally statically generated website will run there, or do I miss something?

@pi0
Copy link
Member

pi0 commented Jan 22, 2024

Hybrid rendering does not requires node command. generate (or using nuxi) requires Node.js runtime as nuxi is a Node.js CLI app.

@fabianwohlfart
Copy link
Author

The only point I am trying to make is that it's nice to generate a static website from a website which runs in build,
so I can send (or pull via webhook) my static website to a hosting environment where no Node.js is available.

I think conceptually it is not contradictory that you have tools that are built to build an application and run inside this application. One can see this more as an export as static, like in that you open a word doc and export as pdf while having the word doc open. As I understand Nuxt, the goal is to make a .output dir that deploys to any server, so it should not be a problem to have multiple parallel .output dirs, as they are encapsulated anyways. (that's what I am doing with a dynamic nitro.output.dir at the moment and never had a problem so far).
I would even go so far and say it would be great to have a command that generates a single static page of a website from a complete website in build. e.g. think about a landing-page-generator where you manage landing pages from different clients. you hit export and the landing page gets generated and is send to the clients server.

@pi0
Copy link
Member

pi0 commented Jan 22, 2024

You might use a pure Nitro server for this webhook handling which has not (Nuxt) default import protections like nuxi and deploy it to a standalone Node.js hosting 👍🏼 (although nuxi CLI is still not designed for such scenario and you should handle build dependency installation for example in your builder server but it is possible if you really still want to push for this model)

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

3 participants