vue-email / nuxt

💚 Official Nuxt module for Vue Email. Build email templates with Vue components.
https://vuemail.net/getting-started/nuxt-nitro
MIT License
109 stars 3 forks source link

Nuxt - Template not found when compiling from serverside on Netlify build #38

Closed ColinTravis closed 7 months ago

ColinTravis commented 7 months ago

Running a simple email compilation, using this exact example code:

// server/api/send-email.post.ts
import { Resend } from 'resend'
import { useCompiler } from '#vue-email'

const resend = new Resend('RESEND_KEY')

export default defineEventHandler(async (event) => {
  const template = await useCompiler('SuccessEmail.vue', {
    props: {
      url: 'https://vuemail.net/',
    }
  })

  const options = {
    from: 'you@example.com',
    to: 'user@gmail.com',
    subject: 'hello world',
    html: template.html,
  }

  await resend.emails.send(options)
  return { message: 'Email sent' }
})

I have my SuccessEmail.vue located in ~/emails

Currently this all works on dev. However, when deploying to netlify, when the server function runs I'm returned with this error server-side:

Mar 8, 03:41:07 PM: 7cf8b042 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:1356:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1414:10)
    at Module.load (node:internal/modules/cjs/loader:1197:32)
    at Module._load (node:internal/modules/cjs/loader:1013:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:128:12)Mar 8, 03:41:07 PM: 7cf8b042 
ERROR  [nuxt] [request error] [unhandled] [500] Error rendering template SuccessEmail: Error: Component SuccessEmail not found
  at templateRender (./node_modules/@vue-email/compiler/dist/index.mjs:57021:11)  
  at async useCompiler (./chunks/routes/api/send-email.post.mjs:30:20)  
  at async Object.handler (./chunks/routes/api/send-email.post.mjs:49:20)  
  at async Object.handler (./chunks/runtime.mjs:2980:19)  
  at async toNodeHandle (./chunks/runtime.mjs:3246:7)  
  at async ufetch (./chunks/runtime.mjs:3973:17)  
  at async $fetchRaw2 (./chunks/runtime.mjs:3845:26)  
  at async $fetch2 (./chunks/runtime.mjs:3887:15)  
  at async Object.handler (./chunks/routes/api/sweepstakes-form-submit.mjs:54:5)  
  at async Object.handler (./chunks/runtime.mjs:2980:19)

I'm not certain the esbuild error effects this, but I'm not certain why my SuccessEmail component isn't being found.

I can see it in my deployed files:

image

Here's my nuxt.config file:

export default defineNuxtConfig({
  devtools: { enabled: true },
  modules: [
    '@vue-email/nuxt',
  ],
  css: ['@/assets/css/fonts.css'],
  vueEmail: {
    autoImport: false,
    baseUrl: 'BASE_URL'
  },
})
Flowko commented 7 months ago

is it netlify edge ? if no, can you please share a snippet from your email tempalte, just the script tag content if you can

ColinTravis commented 7 months ago

It is netlify edge, and it seems to also be the same issue as #35. Switching to pnpm from bun has fixed it for the time being. For kicks, here's the template (with some images/copy obfuscated):

<script lang="ts" setup>
const main = {
    backgroundColor: '#fff',
    fontFamily: '-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif',
}

const paragraph = {
    padding: '0 20px',
    fontSize: '18px',
    color: '#ffffff',
    fontFamily: '"Helvetica Neue", Arial, sans-serif',
}

const container = {
    width: '600px',
}

const containerButton = {
    display: 'flex',
    justifyContent: 'center',
    width: '100%',
}

const button = {
    margin: '0 auto',
    backgroundColor: '#FFC422',
    padding: '15px 30px',
    borderRadius: '999px',
    color: '#003C71',
    fontSize: '16px',
    textTransform: 'uppercase',
    fontWeight: 'bold',
    cursor: 'pointer',
    fontFamily: '"Helvetica Neue", Arial, sans-serif',
}

const content = {
    backgroundColor: '#003C71',
    overflow: 'hidden',
}

const boxInfos = {
    padding: '20px 40px',
}

const sectionFooter = {
    margin: '0 auto',
    backgroundColor: '#0093DA',
    padding: '5px 0 27px 0',
    textAlign: 'center',
}
</script>

<template>
    <EHtml>
        <EHead />
        <EPreview>Header</EPreview>
        <EBody :style="main">
            <EContainer width="600" :style="container">
                <ESection :style="content">
                    <ERow>
                        <EColumn align="center">
                            <EImg style="width:100%" width="600"
                                src="<HEADERIMAGE>" />
                        </EColumn>
                    </ERow>

                    <ERow :style="{
            ...boxInfos,
            paddingBottom: 0,
        }">
                        <EColumn align="center">
                            <EImg width="380" alt=""
                                src="<HEADERLOGO>" />

                            <EText
                                style="margin-top: 36px; margin-bottom: 25px; padding-left: 10px; padding-right: 10px; text-align: center; "
                                :style="paragraph">BODY</EText>
                        </EColumn>
                    </ERow>
                    <ERow>
                        <EColumn align="center" :style="containerButton" col-span="{2}">
                            <EButton px="20" py="12" :style="button"
                                href="#">BUTTON</EButton>
                        </EColumn>
                    </ERow>
                    <ERow>
                        <EColumn align="center">
                            <EImg width="600"
                                src="<FOOTERIMAGE>" />
                        </EColumn>
                    </ERow>
                </ESection>

                <ESection :style="sectionFooter">
                    <ERow>
                        <EColumn align="right" style="width: 33.333%; padding-right: 8px">
                            <ELink href="#">
                                <EImg width="32" alt="Facebook Icon"
                                    src="<ICONIMAGE>" />
                            </ELink>
                        </EColumn>
                        <EColumn align="center" style="width: 33.333%; padding-left: 8px">
                            <ELink href="#">
                                <EImg width="32" alt="Instagram Icon"
                                    src="<ICONIMAGE>" />
                            </ELink>
                        </EColumn>
                        <EColumn align="left" style="width: 33.333%; padding-left: 8px">
                            <ELink href="#">
                                <EImg width="32" alt="TikTok Icon"
                                    src="<ICONIMAGE>" />
                            </ELink>
                        </EColumn>
                    </ERow>
                </ESection>
            </EContainer>
        </EBody>
    </EHtml>
</template>
Flowko commented 7 months ago

okay thank you, glad it worked