Skip to content

Commit ab663f1

Browse files
authored
Bundle non-prod dependencies with esbuild (#6372)
* bundle non-prod dependencies with esbuild - closes #3176 * changeset * update README
1 parent b26329c commit ab663f1

File tree

10 files changed

+90
-31
lines changed

10 files changed

+90
-31
lines changed

.changeset/big-trainers-love.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@sveltejs/adapter-node': patch
3+
---
4+
5+
Bundle non-production dependencies with esbuild

packages/adapter-node/README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,12 +140,14 @@ app.listen(3000, () => {
140140

141141
## Deploying
142142

143-
You will need the output directory (`build` by default), the project's `package.json`, and the production dependencies in `node_modules` to run the application. Production dependencies can be generated with `npm ci --prod`, you can also skip this step if your app doesn't have any dependencies. You can then start your app with
143+
You will need the output directory (`build` by default), the project's `package.json`, and the production dependencies in `node_modules` to run the application. Production dependencies can be generated with `npm ci --prod` (you can skip this step if your app doesn't have any dependencies). You can then start your app with
144144

145145
```bash
146146
node build
147147
```
148148

149+
Development dependencies will be bundled into your app using `esbuild`. To control whether a given package is bundled or externalised, place it in `devDependencies` or `dependencies` respectively in your `package.json`.
150+
149151
## Changelog
150152

151153
[The Changelog for this package is available on GitHub](https://github.com/sveltejs/kit/blob/master/packages/adapter-node/CHANGELOG.md).

packages/adapter-node/ambient.d.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
1-
declare module 'SERVER' {
2-
export { Server } from '@sveltejs/kit';
1+
declare module 'ENV' {
2+
export function env(key: string, fallback?: any): string;
3+
}
4+
5+
declare module 'HANDLER' {
6+
export const handler: import('polka').Middleware;
37
}
48

59
declare module 'MANIFEST' {
610
import { SSRManifest } from '@sveltejs/kit';
711
export const manifest: SSRManifest;
812
}
13+
14+
declare module 'SERVER' {
15+
export { Server } from '@sveltejs/kit';
16+
}

packages/adapter-node/index.js

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
import { writeFileSync } from 'fs';
1+
import { readFileSync, writeFileSync } from 'fs';
22
import { fileURLToPath } from 'url';
3+
import * as esbuild from 'esbuild';
34

45
const files = fileURLToPath(new URL('./files', import.meta.url).href);
56

@@ -19,33 +20,54 @@ export default function (opts = {}) {
1920
name: '@sveltejs/adapter-node',
2021

2122
async adapt(builder) {
23+
const tmp = builder.getBuildDirectory('adapter-node');
24+
2225
builder.rimraf(out);
26+
builder.rimraf(tmp);
27+
builder.mkdirp(tmp);
2328

2429
builder.log.minor('Copying assets');
2530
builder.writeClient(`${out}/client`);
26-
builder.writeServer(`${out}/server`);
2731
builder.writePrerendered(`${out}/prerendered`);
2832

33+
if (precompress) {
34+
builder.log.minor('Compressing assets');
35+
await builder.compress(`${out}/client`);
36+
await builder.compress(`${out}/prerendered`);
37+
}
38+
39+
builder.log.minor('Building server');
40+
41+
builder.writeServer(tmp);
42+
2943
writeFileSync(
30-
`${out}/manifest.js`,
31-
`export const manifest = ${builder.generateManifest({
32-
relativePath: './server'
33-
})};\n`
44+
`${tmp}/manifest.js`,
45+
`export const manifest = ${builder.generateManifest({ relativePath: './' })};`
3446
);
3547

48+
const pkg = JSON.parse(readFileSync('package.json', 'utf8'));
49+
50+
await esbuild.build({
51+
platform: 'node',
52+
sourcemap: 'linked',
53+
target: 'es2022',
54+
entryPoints: [`${tmp}/index.js`, `${tmp}/manifest.js`],
55+
outdir: `${out}/server`,
56+
splitting: true,
57+
format: 'esm',
58+
bundle: true,
59+
external: [...Object.keys(pkg.dependencies || {})]
60+
});
61+
3662
builder.copy(files, out, {
3763
replace: {
38-
SERVER: './server/index.js',
39-
MANIFEST: './manifest.js',
64+
ENV: './env.js',
65+
HANDLER: './handler.js',
66+
MANIFEST: './server/manifest.js',
67+
SERVER: `./server/index.js`,
4068
ENV_PREFIX: JSON.stringify(envPrefix)
4169
}
4270
});
43-
44-
if (precompress) {
45-
builder.log.minor('Compressing assets');
46-
await builder.compress(`${out}/client`);
47-
await builder.compress(`${out}/prerendered`);
48-
}
4971
}
5072
};
5173
}

packages/adapter-node/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,5 +43,8 @@
4343
"sirv": "^2.0.2",
4444
"typescript": "^4.7.4",
4545
"uvu": "^0.5.3"
46+
},
47+
"dependencies": {
48+
"esbuild": "^0.14.48"
4649
}
4750
}
Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,35 @@
11
import { nodeResolve } from '@rollup/plugin-node-resolve';
22
import commonjs from '@rollup/plugin-commonjs';
33
import json from '@rollup/plugin-json';
4+
import { builtinModules } from 'module';
45

56
export default [
67
{
7-
input: {
8-
index: 'src/index.js',
9-
handler: 'src/handler.js',
10-
shims: 'src/shims.js'
8+
input: 'src/index.js',
9+
output: {
10+
file: 'files/index.js',
11+
format: 'esm'
1112
},
13+
plugins: [nodeResolve(), commonjs(), json()],
14+
external: ['ENV', 'HANDLER', ...builtinModules]
15+
},
16+
{
17+
input: 'src/env.js',
1218
output: {
13-
dir: 'files',
19+
file: 'files/env.js',
1420
format: 'esm'
1521
},
1622
plugins: [nodeResolve(), commonjs(), json()],
17-
external: ['SERVER', 'MANIFEST', ...require('module').builtinModules]
23+
external: ['HANDLER', ...builtinModules]
24+
},
25+
{
26+
input: 'src/handler.js',
27+
output: {
28+
file: 'files/handler.js',
29+
format: 'esm',
30+
inlineDynamicImports: true
31+
},
32+
plugins: [nodeResolve(), commonjs(), json()],
33+
external: ['ENV', 'MANIFEST', 'SERVER', ...builtinModules]
1834
}
1935
];

packages/adapter-node/src/handler.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { fileURLToPath } from 'url';
66
import { getRequest, setResponse } from '@sveltejs/kit/node';
77
import { Server } from 'SERVER';
88
import { manifest } from 'MANIFEST';
9-
import { env } from './env.js';
9+
import { env } from 'ENV';
1010

1111
/* global ENV_PREFIX */
1212

@@ -19,7 +19,7 @@ const address_header = env('ADDRESS_HEADER', '').toLowerCase();
1919
const protocol_header = env('PROTOCOL_HEADER', '').toLowerCase();
2020
const host_header = env('HOST_HEADER', 'host').toLowerCase();
2121

22-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
22+
const dir = path.dirname(fileURLToPath(import.meta.url));
2323

2424
/**
2525
* @param {string} path
@@ -132,9 +132,9 @@ function get_origin(headers) {
132132

133133
export const handler = sequence(
134134
[
135-
serve(path.join(__dirname, '/client'), true),
136-
serve(path.join(__dirname, '/static')),
137-
serve(path.join(__dirname, '/prerendered')),
135+
serve(path.join(dir, 'client'), true),
136+
serve(path.join(dir, 'static')),
137+
serve(path.join(dir, 'prerendered')),
138138
ssr
139139
].filter(Boolean)
140140
);

packages/adapter-node/src/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { handler } from './handler.js';
2-
import { env } from './env.js';
1+
import { handler } from 'HANDLER';
2+
import { env } from 'ENV';
33
import polka from 'polka';
44

55
export const path = env('SOCKET_PATH', false);

packages/kit/types/index.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ export interface Builder {
9999
/**
100100
* @param {string} directory Path to the directory containing the files to be compressed
101101
*/
102-
compress(directory: string): void;
102+
compress(directory: string): Promise<void>;
103103
}
104104

105105
export interface Config {

pnpm-lock.yaml

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)