From 83bbeca983cea76a698f1949101f963a919fdbe9 Mon Sep 17 00:00:00 2001 From: Vitor Capretz Date: Mon, 18 Nov 2024 13:37:02 -0300 Subject: [PATCH] feat: Use dynamic import for `@react-email/render` (#438) --- package.json | 4 ++-- pnpm-lock.yaml | 34 +++++++++++++++++----------------- src/batch/batch.ts | 18 ++++++++++++++---- src/emails/emails.ts | 19 +++++++++++++++---- 4 files changed, 48 insertions(+), 27 deletions(-) diff --git a/package.json b/package.json index 7bd395c2..5df12f4c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "resend", - "version": "4.0.0", + "version": "4.0.1-alpha.0", "description": "Node.js library for the Resend API", "main": "./dist/index.js", "module": "./dist/index.mjs", @@ -42,7 +42,7 @@ }, "homepage": "https://github.com/resendlabs/resend-node#readme", "dependencies": { - "@react-email/render": "0.0.17" + "@react-email/render": "1.0.1" }, "devDependencies": { "@biomejs/biome": "1.9.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 88349078..e1fac673 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@react-email/render': - specifier: 0.0.17 - version: 0.0.17(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + specifier: 1.0.1 + version: 1.0.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) devDependencies: '@biomejs/biome': specifier: 1.9.4 @@ -523,12 +523,12 @@ packages: resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} - '@react-email/render@0.0.17': - resolution: {integrity: sha512-xBQ+/73+WsGuXKY7r1U73zMBNV28xdV0cp9cFjhNYipBReDHhV97IpA6v7Hl0dDtDzt+yS/72dY5vYXrF1v8NA==} + '@react-email/render@1.0.1': + resolution: {integrity: sha512-W3gTrcmLOVYnG80QuUp22ReIT/xfLsVJ+n7ghSlG2BITB8evNABn1AO2rGQoXuK84zKtDAlxCdm3hRyIpZdGSA==} engines: {node: '>=18.0.0'} peerDependencies: - react: ^18.2.0 - react-dom: ^18.2.0 + react: ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^18.0 || ^19.0 || ^19.0.0-rc '@selderee/plugin-htmlparser2@0.11.0': resolution: {integrity: sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ==} @@ -1542,10 +1542,10 @@ packages: queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - react-dom@18.2.0: - resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==} + react-dom@18.3.1: + resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==} peerDependencies: - react: ^18.2.0 + react: ^18.3.1 react-is@18.3.1: resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} @@ -1553,8 +1553,8 @@ packages: react-promise-suspense@0.3.4: resolution: {integrity: sha512-I42jl7L3Ze6kZaq+7zXWSunBa3b1on5yfvUW6Eo/3fFOj6dZ5Bqmcd264nJbTK/gn1HjjILAjSwnZbV4RpSaNQ==} - react@18.2.0: - resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==} + react@18.3.1: + resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} engines: {node: '>=0.10.0'} readdirp@3.6.0: @@ -2421,12 +2421,12 @@ snapshots: '@pkgjs/parseargs@0.11.0': optional: true - '@react-email/render@0.0.17(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@react-email/render@1.0.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: html-to-text: 9.0.5 js-beautify: 1.15.1 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) react-promise-suspense: 0.3.4 '@selderee/plugin-htmlparser2@0.11.0': @@ -3609,10 +3609,10 @@ snapshots: queue-microtask@1.2.3: {} - react-dom@18.2.0(react@18.2.0): + react-dom@18.3.1(react@18.3.1): dependencies: loose-envify: 1.4.0 - react: 18.2.0 + react: 18.3.1 scheduler: 0.23.2 react-is@18.3.1: {} @@ -3621,7 +3621,7 @@ snapshots: dependencies: fast-deep-equal: 2.0.1 - react@18.2.0: + react@18.3.1: dependencies: loose-envify: 1.4.0 diff --git a/src/batch/batch.ts b/src/batch/batch.ts index 367e0fa4..e0dc97d0 100644 --- a/src/batch/batch.ts +++ b/src/batch/batch.ts @@ -1,4 +1,3 @@ -import { renderAsync } from '@react-email/render'; import type * as React from 'react'; import type { Resend } from '../resend'; import type { @@ -9,6 +8,7 @@ import type { } from './interfaces/create-batch-options.interface'; export class Batch { + private renderAsync?: (component: React.ReactElement) => Promise; constructor(private readonly resend: Resend) {} async send( @@ -24,9 +24,19 @@ export class Batch { ): Promise { for (const email of payload) { if (email.react) { - email.html = await renderAsync(email.react as React.ReactElement); - // biome-ignore lint/performance/noDelete: - delete email.react; + if (!this.renderAsync) { + try { + const { renderAsync } = await import('@react-email/render'); + this.renderAsync = renderAsync; + } catch (error) { + throw new Error( + 'Failed to render React component. Make sure to install `@react-email/render`', + ); + } + } + + email.html = await this.renderAsync(email.react as React.ReactElement); + email.react = undefined; } } diff --git a/src/emails/emails.ts b/src/emails/emails.ts index a9de4d6e..952aff3b 100644 --- a/src/emails/emails.ts +++ b/src/emails/emails.ts @@ -1,4 +1,3 @@ -import { renderAsync } from '@react-email/render'; import type * as React from 'react'; import type { Resend } from '../resend'; import type { @@ -22,6 +21,7 @@ import type { } from './interfaces/update-email-options.interface'; export class Emails { + private renderAsync?: (component: React.ReactElement) => Promise; constructor(private readonly resend: Resend) {} async send( @@ -36,9 +36,20 @@ export class Emails { options: CreateEmailRequestOptions = {}, ): Promise { if (payload.react) { - payload.html = await renderAsync(payload.react as React.ReactElement); - // biome-ignore lint/performance/noDelete: - delete payload.react; + if (!this.renderAsync) { + try { + const { renderAsync } = await import('@react-email/render'); + this.renderAsync = renderAsync; + } catch (error) { + throw new Error( + 'Failed to render React component. Make sure to install `@react-email/render`', + ); + } + } + + payload.html = await this.renderAsync( + payload.react as React.ReactElement, + ); } const data = await this.resend.post(