vue-email: Nuxt compiler bug in production

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>

About this issue

  • Original URL
  • State: open
  • Created 3 months ago
  • Reactions: 7
  • Comments: 16 (1 by maintainers)

Most upvoted comments

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

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.