Skip to content

Commit 828e4d8

Browse files
committed
rewrite build system to not have to run npm install
1 parent 45a42da commit 828e4d8

File tree

3 files changed

+57
-72
lines changed

3 files changed

+57
-72
lines changed

packages/react-email/src/cli/commands/build.ts

Lines changed: 54 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { cliPackageLocation } from '../utils';
1212

1313
interface Args {
1414
dir: string;
15-
packageManager: string;
15+
packageManager?: string;
1616
}
1717

1818
const buildPreviewApp = (absoluteDirectory: string) => {
@@ -40,12 +40,13 @@ const buildPreviewApp = (absoluteDirectory: string) => {
4040

4141
const setNextEnvironmentVariablesForBuild = async (
4242
emailsDirRelativePath: string,
43-
builtPreviewAppPath: string,
43+
userProjectPath: string,
44+
modifiedPreviewAppPath: string,
4445
) => {
4546
const nextConfigContents = `
4647
const path = require('path');
4748
const emailsDirRelativePath = path.normalize('${emailsDirRelativePath}');
48-
const userProjectLocation = path.resolve(process.cwd(), '../');
49+
const userProjectLocation = '${userProjectPath}';
4950
/** @type {import('next').NextConfig} */
5051
module.exports = {
5152
env: {
@@ -78,7 +79,7 @@ module.exports = {
7879
}`;
7980

8081
await fs.promises.writeFile(
81-
path.resolve(builtPreviewAppPath, './next.config.js'),
82+
path.resolve(modifiedPreviewAppPath, './next.config.js'),
8283
nextConfigContents,
8384
'utf8',
8485
);
@@ -170,61 +171,25 @@ const updatePackageJson = async (builtPreviewAppPath: string) => {
170171
};
171172
packageJson.scripts.build = 'next build';
172173
packageJson.scripts.start = 'next start';
173-
delete packageJson.scripts.postbuild;
174174

175175
packageJson.name = 'preview-server';
176-
// We remove this one to avoid having resolve issues on our demo build process.
177-
// This is only used in the `export` command so it's irrelevant to have it here.
178-
//
179-
// See `src/actions/render-email-by-path` for more info on how we render the
180-
// email templates without `@react-email/render` being installed.
181-
delete packageJson.devDependencies['@react-email/render'];
182-
delete packageJson.devDependencies['@react-email/components'];
183-
delete packageJson.scripts.prepare;
184176
await fs.promises.writeFile(
185177
packageJsonPath,
186178
JSON.stringify(packageJson),
187179
'utf8',
188180
);
189181
};
190182

191-
const npmInstall = async (
192-
builtPreviewAppPath: string,
193-
packageManager: string,
194-
) => {
195-
return new Promise<void>((resolve, reject) => {
196-
const childProc = spawn(
197-
packageManager,
198-
[
199-
'install',
200-
packageManager === 'deno' ? '' : '--include=dev',
201-
packageManager === 'deno' ? '--quiet' : '--silent',
202-
],
203-
{
204-
cwd: builtPreviewAppPath,
205-
shell: true,
206-
},
207-
);
208-
childProc.stdout.pipe(process.stdout);
209-
childProc.stderr.pipe(process.stderr);
210-
childProc.on('close', (code) => {
211-
if (code === 0) {
212-
resolve();
213-
} else {
214-
reject(
215-
new Error(
216-
`Unable to install the dependencies and it exited with code: ${code}`,
217-
),
218-
);
219-
}
220-
});
221-
});
222-
};
223-
224183
export const build = async ({
225184
dir: emailsDirRelativePath,
226185
packageManager,
227186
}: Args) => {
187+
if (packageManager !== undefined) {
188+
console.warn(
189+
'The --packageManager flag is deprecated and is currently ignored. It will be removed in the next major version',
190+
);
191+
}
192+
228193
try {
229194
const spinner = ora({
230195
text: 'Starting build process...',
@@ -240,61 +205,81 @@ export const build = async ({
240205
const emailsDirPath = path.join(process.cwd(), emailsDirRelativePath);
241206
const staticPath = path.join(emailsDirPath, 'static');
242207

208+
const modifiedPreviewAppPath = path.resolve(
209+
cliPackageLocation,
210+
'../.react-email',
211+
);
212+
if (fs.existsSync(modifiedPreviewAppPath)) {
213+
spinner.text = 'Deleting pre-existing modified preview app folder';
214+
await fs.promises.rm(modifiedPreviewAppPath, { recursive: true });
215+
}
243216
const builtPreviewAppPath = path.join(process.cwd(), '.react-email');
244-
245217
if (fs.existsSync(builtPreviewAppPath)) {
246-
spinner.text = 'Deleting pre-existing `.react-email` folder';
218+
spinner.text = 'Deleting pre-existing .react-email folder';
247219
await fs.promises.rm(builtPreviewAppPath, { recursive: true });
248220
}
249221

250-
spinner.text = 'Copying preview app from CLI to `.react-email`';
251-
await fs.promises.cp(cliPackageLocation, builtPreviewAppPath, {
222+
spinner.text = 'Copying preview app from CLI to modify it';
223+
await fs.promises.cp(cliPackageLocation, modifiedPreviewAppPath, {
252224
recursive: true,
253225
filter: (source: string) => {
254-
// do not copy the CLI files
255226
return (
256227
!/(\/|\\)cli(\/|\\)?/.test(source) &&
257228
!/(\/|\\)\.next(\/|\\)?/.test(source) &&
258-
!/(\/|\\)\.turbo(\/|\\)?/.test(source) &&
259-
!/(\/|\\)node_modules(\/|\\)?$/.test(source)
229+
!/(\/|\\)\.turbo(\/|\\)?/.test(source)
260230
);
261231
},
262232
});
263233

264234
if (fs.existsSync(staticPath)) {
265-
spinner.text =
266-
'Copying `static` folder into `.react-email/public/static`';
267-
const builtStaticDirectory = path.resolve(
268-
builtPreviewAppPath,
235+
spinner.text = 'Copying static directory';
236+
const modifiedPreviewAppStaticDirectory = path.resolve(
237+
modifiedPreviewAppPath,
269238
'./public/static',
270239
);
271-
await fs.promises.cp(staticPath, builtStaticDirectory, {
240+
await fs.promises.cp(staticPath, modifiedPreviewAppStaticDirectory, {
272241
recursive: true,
273242
});
274243
}
275244

276-
spinner.text =
277-
'Setting Next environment variables for preview app to work properly';
245+
spinner.text = 'Setting Next environment variables';
278246
await setNextEnvironmentVariablesForBuild(
279247
emailsDirRelativePath,
280-
builtPreviewAppPath,
248+
process.cwd(),
249+
modifiedPreviewAppPath,
281250
);
282251

283-
spinner.text = 'Setting server side generation for the email preview pages';
284-
await forceSSGForEmailPreviews(emailsDirPath, builtPreviewAppPath);
252+
spinner.text = 'Setting up server side generation';
253+
await forceSSGForEmailPreviews(emailsDirPath, modifiedPreviewAppPath);
285254

286255
spinner.text = "Updating package.json's build and start scripts";
287-
await updatePackageJson(builtPreviewAppPath);
288-
289-
spinner.text = 'Installing dependencies on `.react-email`';
290-
await npmInstall(builtPreviewAppPath, packageManager);
256+
await updatePackageJson(modifiedPreviewAppPath);
291257

292258
spinner.stopAndPersist({
293-
text: 'Successfully prepared `.react-email` for `next build`',
259+
text: 'Ready for next build',
294260
symbol: logSymbols.success,
295261
});
262+
await buildPreviewApp(modifiedPreviewAppPath);
263+
264+
await fs.promises.mkdir(builtPreviewAppPath);
265+
await fs.promises.cp(
266+
path.join(modifiedPreviewAppPath, '.next'),
267+
path.join(builtPreviewAppPath, '.next'),
268+
{
269+
recursive: true,
270+
},
271+
);
272+
await fs.promises.cp(
273+
path.join(modifiedPreviewAppPath, 'public'),
274+
path.join(builtPreviewAppPath, 'public'),
275+
{
276+
recursive: true,
277+
},
278+
);
296279

297-
await buildPreviewApp(builtPreviewAppPath);
280+
await fs.promises.rm(modifiedPreviewAppPath, {
281+
recursive: true,
282+
});
298283
} catch (error) {
299284
console.log(error);
300285
process.exit(1);

packages/react-email/src/cli/commands/start.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@ export const start = async () => {
1616
process.exit(1);
1717
}
1818

19-
const nextStart = spawn('npm', ['start'], {
19+
const nextStart = spawn('npx', ['next', 'start'], {
2020
cwd: builtPreviewPath,
21+
shell: true,
2122
stdio: 'inherit',
2223
});
2324

packages/react-email/src/cli/index.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,7 @@ program
2626
.option('-d, --dir <path>', 'Directory with your email templates', './emails')
2727
.option(
2828
'-p --packageManager <name>',
29-
'Package name to use on installation on `.react-email`',
30-
'npm',
29+
'Package manager to use when installing in .react-email (deprecated)',
3130
)
3231
.action(build);
3332

0 commit comments

Comments
 (0)