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 compiler bug in production #168

Open
HugoRCD opened this issue Mar 18, 2024 · 20 comments
Open

Nuxt compiler bug in production #168

HugoRCD opened this issue Mar 18, 2024 · 20 comments

Comments

@HugoRCD
Copy link

HugoRCD commented Mar 18, 2024

After deploying my project on Vercel, I often encounter this error. Each time, I end up having to redeploy the project to fix it. I was wondering if you might have any insights on what could be causing this issue.

CleanShot 2024-03-18 at 10 51 12@2x

Here is all piece of code related:

resendService.ts

import { useCompiler } from '#vue-email';
import { Resend } from "resend";

const resend = new Resend(process.env.NUXT_PRIVATE_RESEND_API_KEY);

export async function sendOtp(email: string, otp: string) {
  const runtimeConfig = useRuntimeConfig();
  const siteUrl = runtimeConfig.public.siteUrl;
  const template = await useCompiler('verify-otp.vue', {
    props: {
      otp,
      redirectUrl: `${siteUrl}/login?email=${email}&otp=${otp}`,
    }
  });

  try {
    await resend.emails.send({
      from: "HugoRCD <contact@hrcd.fr>",
      to: [email],
      subject: "Welcome to Shelve!",
      html: template.html,
    });
  } catch (error) {
    console.error(error);
  }
}

./emails/verify-otp.vue

<script setup lang="ts">
defineProps({
  otp: {
    type: String,
    required: true
  },
  redirectUrl: {
    type: String,
    required: true
  }
});
</script>

<template>
  <ETailwind>
    <EHtml>
      <EHead />
      <EPreview>
        Here is your code to access Shelve
      </EPreview>
      <EBody class="m-auto bg-white font-sans">
        <EContainer class="mx-auto my-[40px] max-w-[465px] rounded border border-solid border-[#eaeaea] p-[20px] md:p-7">
          <EHeading class="mb-4 text-center text-2xl font-bold text-[#000000] md:text-3xl">
            Welcome to Shelve
          </EHeading>
          <EText class="mb-4 text-center text-[#000000]">
            Your OTP is:
          </EText>
          <EText class="mb-4 text-center text-[36px] font-bold text-[#000000]">
            <span class="text-[#2C3BF5]">{{ otp }}</span>
          </EText>
          <EText class="mb-4 text-center text-[#000000]">
            Use this OTP to verify your account
          </EText>
          <ESection class="my-[32px] text-center">
            <EButton px="20" py="12" class="rounded bg-[#000000] text-center text-[12px] font-semibold text-white no-underline" :href="redirectUrl">
              Go to Shelve
            </EButton>
          </ESection>
          <EText class="text-[14px] leading-[24px] text-black">
            or copy and paste this URL into your browser:
            <ELink :href="redirectUrl" class="text-[#2C3BF5]">
              {{ redirectUrl }}
            </ELink>
          </EText>
          <EHr class="mx-0 my-[26px] w-full border border-solid border-[#eaeaea]" />
          <EText class="text-[12px] leading-[24px] text-[#666666]">
            If you were not expecting this invitation, you can ignore this email. If you are concerned about your account's safety, please reply to this email to get in touch
            with us.
          </EText>
        </EContainer>
      </EBody>
    </EHtml>
  </ETailwind>
</template>

<style scoped>

</style>
@letstri
Copy link
Contributor

letstri commented Mar 27, 2024

Have the same problem but with config from @vue-email/compiler

@eliabieri
Copy link

I'm facing the exact same problem

@dcln00
Copy link

dcln00 commented Apr 11, 2024

I'm also facing the exact same problem

@GerryWilko
Copy link

This issue appears to be that the compile function's tries to resolve packages with cjs so the error that comes through is actually:

Error: Cannot find module '/Users/gerard/Developer/ignite/auth-service/apps/auth-service/.output/server/node_modules/vue-email/dist/index.cjs'
    at createEsmNotFoundErr (node:internal/modules/cjs/loader:1181:15)
    at finalizeEsmResolution (node:internal/modules/cjs/loader:1169:15)
    at resolveExports (node:internal/modules/cjs/loader:591:14)
    at Module._findPath (node:internal/modules/cjs/loader:668:31)
    at Module._resolveFilename (node:internal/modules/cjs/loader:1130:27)
    at Module._load (node:internal/modules/cjs/loader:985:27)
    at Module.require (node:internal/modules/cjs/loader:1235:19)
    at require (node:internal/modules/helpers:176:18)
    at /Users/gerard/Developer/ignite/auth-service/apps/auth-service/.output/server/node_modules/import-string/dist/YEEztG6s8DrZXPhaeh8D1.js:36:24
    at Script.runInContext (node:vm:133:12) 

However the vue-email that is copied to the built output contains only the .mjs index file so this error is thrown.

Just investigating how it ends up only pulling over the .mjs file now or perhaps trying to force resolution to be ESModule.

@xlanex6
Copy link

xlanex6 commented Apr 12, 2024

So I'am

@GerryWilko
Copy link

So in my case this issue was caused by the imports in my email component. It seems you are unable to import vue-email inside here. When removing the vue-email imports e.g.

import {
  EBody,
  EButton,
  EColumn,
  EContainer,
  EHead,
  EHeading,
  EHtml,
  EImg,
  EPreview,
  ERow,
  ESection,
  EText,
} from 'vue-email'

Then I no longer have this error in production. Hope this helps someone!

@jonatandorozco
Copy link

@GerryWilko if you remove the imports, how do get the components? If you can share details about how you were able to solve than can be helpful

@GerryWilko
Copy link

They appear to be auto imported. Looking inside the compile function i noticed that they seemed to be part of the auto imported code. If you check the examples on the Vue-Email site it does show them without the explicit imports. I have a feeling this may be a recent change as I think I took one of the examples and modified it for my own use case and now they seem to have no imports in the examples. Or my IDE was trying to be helpful and added them automatically.

To be clear my email templates work fine in the IDE and in production with no imports so they arent needed and so seem to be the source of the error listed in this issue.

@Gugustinette
Copy link

Gugustinette commented Apr 12, 2024

Removing the imports didn't work on my side 😕
Still getting the exact same error on production.

Btw I'm on "@vue-email/nuxt": "^0.8.19"

Also, I'm really surprised this could have an impact on the error, as the components not being found are the Vue Mails we are writing, not the components imported inside.

@dcln00
Copy link

dcln00 commented Apr 12, 2024

What worked for me was deleting the node modules directory with package-lock.json file and running npm install again.

@Gugustinette
Copy link

Gugustinette commented Apr 13, 2024

So I digged some of the code :

The first esbuild-linux-64 error appears because of the catch here :

https://github.com/vue-email/compiler/blob/1267312f408b63b6d0ef1a27a94e890f932893fd/src/template.ts#L120-L133

async function loadComponent(name: string, source: string, verbose = false) {
  try {
    name = correctName(name)
    const compiledComponent = compile(name, source, verbose)
    const componentCode: Component = (await importModule(compiledComponent)).default


    return componentCode
  }
  catch (error) {
    console.error('Error loading component', error)
  }


  return null
}

Then the second error appears because the previous function returned null after the error catched :

https://github.com/vue-email/compiler/blob/1267312f408b63b6d0ef1a27a94e890f932893fd/src/template.ts#L45-L51

    const component = await loadComponent(name, code.source, verbose)


    if (verbose)
      console.warn(`${lightGreen('💌')} ${bold(blue('Generating output'))}`)


    if (!component)
      throw new Error(`Component ${name} not found`)

This seems to be related to the compile function from @vue/compiler-sfc throwing an error when not finding the esbuild-linux-64 (because esbuild is used here at runtime to compile the template).
So this is not directly related to a vue-email behavior. But we still don't know why is esbuild-linux-64 not installed in the vercel context.

@Gugustinette
Copy link

Sooo I didn't sleep BUT I FIXED IT.

esbuild Source Code

Here is the piece of code from esbuild that crashes when vue is rendering the template. Obviously, it tries to resolve the package dynamically, and it just isn't found in the vercel context.
However, it's pretty weird to me as it should be something like ${pkg}-${subpath} in this version but anyway.
https://www.npmjs.com/package/esbuild/v/0.15.18?activeTab=code
Capture d’écran 2024-04-13 à 07 22 14

The issue

I was digging a lot on how the package couldn't be found, even when we were trying to force install the esbuild-linux-64 package. Even adding it locally on your repo won't fix the issue.

This is basically because Nuxt won't include it in the built node_modules folder when running nuxt build with the vercel preset, that compiles to serverless functions. I digged a lot about how that damn node_modules folder should look (and where it should be) in serverless functions and found some information here : https://vercel.com/docs/build-output-api/v3/primitives#config-example

Capture d’écran 2024-04-13 à 07 29 00

Every serverless function should have the node_modules folder at its root. However, Nitro (which powers Nuxt) compiles to only one serverless function called __nitro.func. Which means esbuild-linux-64 package was just missing from .vercel/output/functions/__nitro.func/node_modules.

So esbuild-linux-64 is correctly installed when running npm install during Vercel build time. It is just not included by Nitro on build step.

The solution

I still don't know how to solve it correctly using Nitro config.
But here is the dirty solution I used during my debugging time :
package.json

{
...
"scripts": {
    "build": "nuxt build && cp -r ./node_modules/esbuild-linux-64 ./.vercel/output/functions/__nitro.func/node_modules/esbuild-linux-64",
  },
...
}

Basically modify your build command to manually copy the missing package from the "build node_modules" to the "serverless node_modules".

I'm sure there is a way to just tell Nitro to include the package, but for now I'm too lazy and need to sleep. 🥹

@CernyMatej
Copy link

I feel like Tailwind doesn't really work with this solution, does it?

@Gugustinette
Copy link

I feel like Tailwind doesn't really work with this solution, does it?

who tf uses Tailwind anyway

Joke aside, are you facing the issue even with the fix ?
Did you try to remove Tailwind to see if it was really breaking it ? Any errors ?

Maybe there's also an error with Tailwind not being included in the node_modules, which would require to also cp -r your Tailwind dependencies.
But I don't know much about how Tailwind source/build will behave in this context as I've never used it.

@CernyMatej
Copy link

CernyMatej commented Apr 16, 2024

Well if I understand it correctly, this module converts tailwind classes to inline styles at some point so I don't know whether it actually needs the tw source or not. Maybe it is missing from the node_modules...

When I removed the explicit component imports & used your build copy command the mails do send. It's only the styles that are missing.

I'll experiment with it when I have some time

@xlanex6
Copy link

xlanex6 commented Apr 20, 2024

I feel like Tailwind doesn't really work with this solution, does it?

who tf uses Tailwind anyway

Joke aside, are you facing the issue even with the fix ? Did you try to remove Tailwind to see if it was really breaking it ? Any errors ?

Maybe there's also an error with Tailwind not being included in the node_modules, which would require to also cp -r your Tailwind dependencies. But I don't know much about how Tailwind source/build will behave in this context as I've never used it.

@Gugustinette

I try to modify the build command but it still not work
I use Tailwind also

@JeremyMees
Copy link

I get the same error using Netlify.

@Gugustinette
Copy link

@JeremyMees

Can you provide logs ?

I don't know much about Netlify, if you are deploying to a serverless environment, the solution could be similar to Vercel :

{
...
"scripts": {
    "build": "nuxt build && cp -r ./node_modules/esbuild-linux-64 ./.vercel/output/functions/__nitro.func/node_modules/esbuild-linux-64",
  },
...
}

(Of course, directories will probably be named differently)

@JeremyMees
Copy link

@Gugustinette

These are the logs i get from Netlify

May 29, 12:55:05 PM: 1b92f110 ERROR  Error loading component Error: The package "esbuild-linux-64" could not be found, and is needed by esbuild.

If you are installing esbuild with npm, make sure that you don't specify the
"--no-optional" or "--omit=optional" flags. The "optionalDependencies" feature
of "package.json" is used by esbuild to install the correct binary executable
for your current platform.
    at generateBinPath (/var/task/node_modules/esbuild/lib/main.js:1819:15)
    at esbuildCommandAndArgs (/var/task/node_modules/esbuild/lib/main.js:1886:33)
    at ensureServiceIsRunning (/var/task/node_modules/esbuild/lib/main.js:2051:25)
    at startSyncServiceWorker (/var/task/node_modules/esbuild/lib/main.js:2261:19)
    at Object.<anonymous> (/var/task/node_modules/esbuild/lib/main.js:2302:3)
    at Module._compile (node:internal/modules/cjs/loader:1358:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1416:10)
    at Module.load (node:internal/modules/cjs/loader:1208:32)
    at Module._load (node:internal/modules/cjs/loader:1024:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:174:12)May 29, 12:55:05 PM: 1b92f110 ERROR  [nuxt] [request error] [unhandled] [500] Error rendering template ReservationSuccess: Error: Component ReservationSuccess not found
  at Object.handler (./chunks/routes/api/index.post.mjs:61:11)  
  at async Object.handler (./chunks/runtime.mjs:3084:19)  
  at async toNodeHandle (./chunks/runtime.mjs:3350:7)  
  at async lambda (./chunks/runtime.mjs:16990:13)

@Gugustinette
Copy link

@JeremyMees

As far as I know from Netlify, this could be solved with this build command :

nuxt build && cp -r ./node_modules/esbuild-linux-64 ./.netlify/functions-internal/server/node_modules/esbuild-linux-64

@Flowko Flowko mentioned this issue Jun 4, 2024
3 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants