Skip to content

Commit 1a47335

Browse files
committed
feat(react-email): Build preview app and run it built instead of as dev (#1537)
1 parent 9a5fd78 commit 1a47335

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+1107
-301
lines changed

.changeset/five-humans-dream.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"react-email": major
3+
---
4+
5+
Use a built version of preview app when running `email dev`
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[{"totalTime":8845.356213999998,"min":257.0071020000005,"max":319.35606000000007,"hz":3.3916101595227413,"period":294.84520713333325,"samples":[257.0071020000005,276.31168399999933,277.8366240000005,278.36899300000005,279.8632340000004,280.18767300000036,283.69530099999974,286.4888599999995,287.58407500000067,287.7977950000004,289.39708399999927,291.81965800000035,291.9046179999996,292.2597029999997,292.3085950000004,294.1774999999998,296.8327389999995,297.5627690000001,299.2934530000002,300.22787700000026,303.2054509999998,303.5775389999999,306.54038500000024,306.82987799999864,308.2782050000005,310.00733799999944,312.97863099999995,316.5017769999995,317.1556129999999,319.35606000000007],"mean":294.84520713333325,"variance":204.35218189519136,"sd":14.295180372950576,"sem":2.6099309179567145,"df":29,"critical":2.045,"moe":5.3373087272214805,"rme":1.8102070503753762,"p75":306.54038500000024,"p99":319.35606000000007,"p995":319.35606000000007,"p999":319.35606000000007},{"totalTime":9229.163527000006,"min":278.92011600000114,"max":338.5425720000021,"hz":3.250565439894386,"period":307.6387842333335,"samples":[278.92011600000114,280.9813119999999,281.1812970000028,284.78353400000015,286.64387200000056,288.7482779999991,288.77580899999884,288.9057730000004,291.04829099999915,295.8136080000004,298.98449400000027,305.3271000000004,305.4814900000001,308.1779970000007,310.16959099999804,312.03674300000057,312.0498269999989,313.014357,314.328571,316.69610199999806,317.86852,319.14333100000295,319.43929600000047,319.8494759999994,321.66192500000034,327.3214680000001,332.60930400000143,334.8082780000004,335.8511949999993,338.5425720000021],"mean":307.6387842333335,"variance":316.7371375953306,"sd":17.797110372061262,"sem":3.249292936395704,"df":29,"critical":2.045,"moe":6.644804054929215,"rme":2.1599370415822983,"p75":319.43929600000047,"p99":338.5425720000021,"p995":338.5425720000021,"p999":338.5425720000021}]
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"name": "@benchmarks/preview-server",
3+
"private": true,
4+
"version": "0.0.0",
5+
"scripts": {
6+
"local-vs-2.1.7-canary.2": "tsx ./src/local-vs-2.1.7-canary.2.ts",
7+
"local-vs-2.1.7-canary.2-on-startup": "tsx ./src/local-vs-2.1.7-canary.2-on-startup.ts"
8+
},
9+
"license": "MIT",
10+
"repository": {
11+
"type": "git",
12+
"url": "https://github.com/resend/react-email.git",
13+
"directory": "benchmarks/preview-server"
14+
},
15+
"engines": {
16+
"node": ">=18.0.0"
17+
},
18+
"dependencies": {
19+
"react-email": "workspace:*",
20+
"react-email-canary": "npm:[email protected]",
21+
"tinybench": "2.5.1"
22+
},
23+
"devDependencies": {
24+
"eslint-config-custom": "workspace:*",
25+
"tsconfig": "workspace:*",
26+
"tsx": "4.7.1",
27+
"typescript": "5.1.6"
28+
}
29+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import path from "node:path";
2+
import { Bench } from "tinybench";
3+
import { runServerAndFetchPreviewPage } from "./utils/run-server-and-fetch-preview-page";
4+
import { promises as fs } from "node:fs";
5+
import { runServer } from "./utils/run-server";
6+
7+
const pathToCanaryCliScript = path.resolve(
8+
__dirname,
9+
"../",
10+
"./node_modules/react-email-canary/cli/index.js",
11+
);
12+
13+
const pathToLocalCliScript = path.resolve(
14+
__dirname,
15+
"../",
16+
"./node_modules/react-email/dist/cli/index.js",
17+
);
18+
19+
(async () => {
20+
const bench = new Bench({
21+
iterations: 30,
22+
});
23+
24+
bench
25+
.add("startup on local", async () => {
26+
const server = await runServer(pathToLocalCliScript);
27+
await fetch(`${server.url}/preview/magic-links/notion-magic-link`);
28+
server.subprocess.kill();
29+
})
30+
.add("startup on 2.1.7-canary.2", async () => {
31+
const server = await runServer(pathToCanaryCliScript);
32+
await fetch(`${server.url}/preview/magic-links/notion-magic-link`);
33+
server.subprocess.kill();
34+
});
35+
36+
await bench.run();
37+
38+
await fs.writeFile(
39+
"startup-bench-results-30-iterations.json",
40+
JSON.stringify(bench.results),
41+
"utf8",
42+
);
43+
})();
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import path from "node:path";
2+
import { Bench } from "tinybench";
3+
import { runServerAndFetchPreviewPage } from "./utils/run-server-and-fetch-preview-page";
4+
import { promises as fs } from "node:fs";
5+
import { runServer } from "./utils/run-server";
6+
7+
const pathToCanaryCliScript = path.resolve(
8+
__dirname,
9+
"../",
10+
"./node_modules/react-email-canary/cli/index.js",
11+
);
12+
13+
const pathToLocalCliScript = path.resolve(
14+
__dirname,
15+
"../",
16+
"./node_modules/react-email/dist/cli/index.js",
17+
);
18+
19+
(async () => {
20+
const bench = new Bench({
21+
iterations: 30,
22+
});
23+
24+
const localServer = await runServer(pathToLocalCliScript);
25+
const canaryServer = await runServer(pathToCanaryCliScript);
26+
bench
27+
.add("local", async () => {
28+
await fetch(`${localServer.url}/preview/magic-links/notion-magic-link`);
29+
})
30+
.add("2.1.7-canary.2", async () => {
31+
await fetch(`${canaryServer.url}/preview/magic-links/notion-magic-link`);
32+
});
33+
34+
await fetch(`${localServer.url}/preview/magic-links/notion-magic-link`);
35+
await fetch(`${canaryServer.url}/preview/magic-links/notion-magic-link`);
36+
37+
await bench.run();
38+
39+
localServer.subprocess.kill();
40+
canaryServer.subprocess.kill();
41+
42+
await fs.writeFile(
43+
"bench-results-30-iterations.json",
44+
JSON.stringify(bench.results),
45+
"utf8",
46+
);
47+
})();
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import path from "node:path";
2+
import { spawn } from "node:child_process";
3+
4+
const decoder = new TextDecoder();
5+
6+
export function runServerAndFetchPreviewPage(pathToCliScript: string) {
7+
return new Promise<void>((resolve, reject) => {
8+
const node = spawn("node", [pathToCliScript, "dev"], {
9+
cwd: path.resolve(__dirname, "../../../../apps/demo"),
10+
});
11+
12+
node.stdout.on("data", (data) => {
13+
const content = decoder.decode(data);
14+
if (content.includes("Running preview at")) {
15+
const url = /http:\/\/localhost:[\d]+/.exec(content)?.[0];
16+
if (url) {
17+
fetch(`${url}/preview/magic-links/notion-magic-link`)
18+
.then(async () => {
19+
node.kill();
20+
resolve();
21+
})
22+
.catch(() => {
23+
node.kill();
24+
reject();
25+
});
26+
} else {
27+
node.kill();
28+
reject(
29+
new Error(
30+
"URL was non existant in the same line, maybe we changed the way this is displayed?",
31+
{
32+
cause: { content, pathToCliScript },
33+
},
34+
),
35+
);
36+
}
37+
}
38+
});
39+
});
40+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import path from "node:path";
2+
import { ChildProcessWithoutNullStreams, spawn } from "node:child_process";
3+
4+
const decoder = new TextDecoder();
5+
6+
export interface Server {
7+
subprocess: ChildProcessWithoutNullStreams;
8+
url: string;
9+
}
10+
11+
export function runServer(pathToCliScript: string) {
12+
return new Promise<Server>((resolve, reject) => {
13+
const node = spawn("node", [pathToCliScript, "dev"], {
14+
cwd: path.resolve(__dirname, "../../../../apps/demo"),
15+
});
16+
17+
node.stdout.on("data", (data) => {
18+
const content = decoder.decode(data);
19+
if (content.includes("Running preview at")) {
20+
const url = /http:\/\/localhost:[\d]+/.exec(content)?.[0];
21+
if (url) {
22+
resolve({
23+
subprocess: node,
24+
url,
25+
});
26+
} else {
27+
node.kill();
28+
reject(
29+
new Error(
30+
"URL was non existant in the same line, maybe we changed the way this is displayed?",
31+
{
32+
cause: { content, pathToCliScript },
33+
},
34+
),
35+
);
36+
}
37+
}
38+
});
39+
});
40+
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
[
2+
{
3+
"totalTime": 27012.250436999995,
4+
"min": 875.3278339999997,
5+
"max": 975.2659800000001,
6+
"hz": 1.1106072065327641,
7+
"period": 900.4083478999999,
8+
"samples": [
9+
875.3278339999997,
10+
876.8766680000008,
11+
878.4021300000004,
12+
879.6970989999973,
13+
879.9013220000006,
14+
880.0440200000012,
15+
881.0134880000005,
16+
882.6672519999993,
17+
882.8309769999996,
18+
886.5787479999999,
19+
888.0713489999998,
20+
893.9997390000008,
21+
895.6862419999998,
22+
896.5675049999991,
23+
897.884775999999,
24+
900.0767889999997,
25+
900.9051619999991,
26+
900.9183460000004,
27+
901.6665190000003,
28+
902.7904479999997,
29+
904.4112889999997,
30+
905.2584070000012,
31+
906.7178459999996,
32+
908.5994840000001,
33+
909.5589759999966,
34+
916.7231540000002,
35+
926.0553790000013,
36+
938.2442230000015,
37+
939.509286,
38+
975.2659800000001
39+
],
40+
"mean": 900.4083478999999,
41+
"variance": 485.695494365056,
42+
"sd": 22.03850027486117,
43+
"sem": 4.023661244708422,
44+
"df": 29,
45+
"critical": 2.045,
46+
"moe": 8.228387245428722,
47+
"rme": 0.9138506172915419,
48+
"p75": 906.7178459999996,
49+
"p99": 975.2659800000001,
50+
"p995": 975.2659800000001,
51+
"p999": 975.2659800000001
52+
},
53+
{
54+
"totalTime": 192389.31467999995,
55+
"min": 5532.170213000005,
56+
"max": 11331.693837999992,
57+
"hz": 0.15593381602246897,
58+
"period": 6412.977155999998,
59+
"samples": [
60+
5532.170213000005,
61+
5613.012570999999,
62+
5668.327381999989,
63+
5683.154505999992,
64+
5687.472905000002,
65+
5709.162072000006,
66+
5710.284887999995,
67+
5766.092444000002,
68+
5780.493889000005,
69+
5827.005907999999,
70+
5863.191644999999,
71+
5883.012165000022,
72+
5930.652871999999,
73+
5945.572227999997,
74+
5955.837523000002,
75+
5973.8704309999885,
76+
5979.267296000005,
77+
6043.029130999988,
78+
6157.551157000009,
79+
6169.924976999988,
80+
6239.261752999999,
81+
6249.798458000005,
82+
6261.157174000007,
83+
6290.244798999978,
84+
6312.954878999997,
85+
6343.798106000002,
86+
6420.7047809999785,
87+
9763.792740999997,
88+
10296.821947999997,
89+
11331.693837999992
90+
],
91+
"mean": 6412.977155999998,
92+
"variance": 1989010.8753359944,
93+
"sd": 1410.3229684494238,
94+
"sem": 257.48856772913206,
95+
"df": 29,
96+
"critical": 2.045,
97+
"moe": 526.5641210060751,
98+
"rme": 8.21091527689944,
99+
"p75": 6261.157174000007,
100+
"p99": 11331.693837999992,
101+
"p995": 11331.693837999992,
102+
"p999": 11331.693837999992
103+
}
104+
]

packages/create-email/template/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
},
1010
"dependencies": {
1111
"@react-email/components": "workspace:0.0.23-canary.2",
12-
"react-email": "workspace:2.1.7-canary.2",
12+
"react-email": "workspace:2.2.0-alpha-fa7021659-20240814",
1313
"react-dom": "19.0.0-rc.0",
1414
"react": "19.0.0-rc.0"
1515
},

packages/react-email/.npmignore

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
.react-email
2-
emails
3-
.next
4-
static
2+
./emails
3+
./emails/static
54
node_modules
65
.turbo
76
src/cli

0 commit comments

Comments
 (0)