diff --git a/.changeset/big-trainers-love.md b/.changeset/big-trainers-love.md new file mode 100644 index 000000000000..166f2fc7f91b --- /dev/null +++ b/.changeset/big-trainers-love.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/adapter-node': patch +--- + +Bundle non-production dependencies with esbuild diff --git a/packages/adapter-node/README.md b/packages/adapter-node/README.md index a7e7ed52bbdb..80dc3d2a98d7 100644 --- a/packages/adapter-node/README.md +++ b/packages/adapter-node/README.md @@ -140,12 +140,14 @@ app.listen(3000, () => { ## Deploying -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 +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 ```bash node build ``` +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`. + ## Changelog [The Changelog for this package is available on GitHub](https://github.com/sveltejs/kit/blob/master/packages/adapter-node/CHANGELOG.md). diff --git a/packages/adapter-node/ambient.d.ts b/packages/adapter-node/ambient.d.ts index 537f7cc041d1..15d55418239b 100644 --- a/packages/adapter-node/ambient.d.ts +++ b/packages/adapter-node/ambient.d.ts @@ -1,8 +1,16 @@ -declare module 'SERVER' { - export { Server } from '@sveltejs/kit'; +declare module 'ENV' { + export function env(key: string, fallback?: any): string; +} + +declare module 'HANDLER' { + export const handler: import('polka').Middleware; } declare module 'MANIFEST' { import { SSRManifest } from '@sveltejs/kit'; export const manifest: SSRManifest; } + +declare module 'SERVER' { + export { Server } from '@sveltejs/kit'; +} diff --git a/packages/adapter-node/index.js b/packages/adapter-node/index.js index ef6e8adab00b..48a0ac5c38a8 100644 --- a/packages/adapter-node/index.js +++ b/packages/adapter-node/index.js @@ -1,5 +1,6 @@ -import { writeFileSync } from 'fs'; +import { readFileSync, writeFileSync } from 'fs'; import { fileURLToPath } from 'url'; +import * as esbuild from 'esbuild'; const files = fileURLToPath(new URL('./files', import.meta.url).href); @@ -19,33 +20,54 @@ export default function (opts = {}) { name: '@sveltejs/adapter-node', async adapt(builder) { + const tmp = builder.getBuildDirectory('adapter-node'); + builder.rimraf(out); + builder.rimraf(tmp); + builder.mkdirp(tmp); builder.log.minor('Copying assets'); builder.writeClient(`${out}/client`); - builder.writeServer(`${out}/server`); builder.writePrerendered(`${out}/prerendered`); + if (precompress) { + builder.log.minor('Compressing assets'); + await builder.compress(`${out}/client`); + await builder.compress(`${out}/prerendered`); + } + + builder.log.minor('Building server'); + + builder.writeServer(tmp); + writeFileSync( - `${out}/manifest.js`, - `export const manifest = ${builder.generateManifest({ - relativePath: './server' - })};\n` + `${tmp}/manifest.js`, + `export const manifest = ${builder.generateManifest({ relativePath: './' })};` ); + const pkg = JSON.parse(readFileSync('package.json', 'utf8')); + + await esbuild.build({ + platform: 'node', + sourcemap: 'linked', + target: 'es2022', + entryPoints: [`${tmp}/index.js`, `${tmp}/manifest.js`], + outdir: `${out}/server`, + splitting: true, + format: 'esm', + bundle: true, + external: [...Object.keys(pkg.dependencies || {})] + }); + builder.copy(files, out, { replace: { - SERVER: './server/index.js', - MANIFEST: './manifest.js', + ENV: './env.js', + HANDLER: './handler.js', + MANIFEST: './server/manifest.js', + SERVER: `./server/index.js`, ENV_PREFIX: JSON.stringify(envPrefix) } }); - - if (precompress) { - builder.log.minor('Compressing assets'); - await builder.compress(`${out}/client`); - await builder.compress(`${out}/prerendered`); - } } }; } diff --git a/packages/adapter-node/package.json b/packages/adapter-node/package.json index 9e563907553a..86cf0cf1e103 100644 --- a/packages/adapter-node/package.json +++ b/packages/adapter-node/package.json @@ -43,5 +43,8 @@ "sirv": "^2.0.2", "typescript": "^4.7.4", "uvu": "^0.5.3" + }, + "dependencies": { + "esbuild": "^0.14.48" } } diff --git a/packages/adapter-node/rollup.config.js b/packages/adapter-node/rollup.config.js index 9bd5c9970fab..6384234b220a 100644 --- a/packages/adapter-node/rollup.config.js +++ b/packages/adapter-node/rollup.config.js @@ -1,19 +1,35 @@ import { nodeResolve } from '@rollup/plugin-node-resolve'; import commonjs from '@rollup/plugin-commonjs'; import json from '@rollup/plugin-json'; +import { builtinModules } from 'module'; export default [ { - input: { - index: 'src/index.js', - handler: 'src/handler.js', - shims: 'src/shims.js' + input: 'src/index.js', + output: { + file: 'files/index.js', + format: 'esm' }, + plugins: [nodeResolve(), commonjs(), json()], + external: ['ENV', 'HANDLER', ...builtinModules] + }, + { + input: 'src/env.js', output: { - dir: 'files', + file: 'files/env.js', format: 'esm' }, plugins: [nodeResolve(), commonjs(), json()], - external: ['SERVER', 'MANIFEST', ...require('module').builtinModules] + external: ['HANDLER', ...builtinModules] + }, + { + input: 'src/handler.js', + output: { + file: 'files/handler.js', + format: 'esm', + inlineDynamicImports: true + }, + plugins: [nodeResolve(), commonjs(), json()], + external: ['ENV', 'MANIFEST', 'SERVER', ...builtinModules] } ]; diff --git a/packages/adapter-node/src/handler.js b/packages/adapter-node/src/handler.js index d90bce52d996..b0951fccdc30 100644 --- a/packages/adapter-node/src/handler.js +++ b/packages/adapter-node/src/handler.js @@ -6,7 +6,7 @@ import { fileURLToPath } from 'url'; import { getRequest, setResponse } from '@sveltejs/kit/node'; import { Server } from 'SERVER'; import { manifest } from 'MANIFEST'; -import { env } from './env.js'; +import { env } from 'ENV'; /* global ENV_PREFIX */ @@ -19,7 +19,7 @@ const address_header = env('ADDRESS_HEADER', '').toLowerCase(); const protocol_header = env('PROTOCOL_HEADER', '').toLowerCase(); const host_header = env('HOST_HEADER', 'host').toLowerCase(); -const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const dir = path.dirname(fileURLToPath(import.meta.url)); /** * @param {string} path @@ -132,9 +132,9 @@ function get_origin(headers) { export const handler = sequence( [ - serve(path.join(__dirname, '/client'), true), - serve(path.join(__dirname, '/static')), - serve(path.join(__dirname, '/prerendered')), + serve(path.join(dir, 'client'), true), + serve(path.join(dir, 'static')), + serve(path.join(dir, 'prerendered')), ssr ].filter(Boolean) ); diff --git a/packages/adapter-node/src/index.js b/packages/adapter-node/src/index.js index 5832b244a51e..ea3feee05860 100644 --- a/packages/adapter-node/src/index.js +++ b/packages/adapter-node/src/index.js @@ -1,5 +1,5 @@ -import { handler } from './handler.js'; -import { env } from './env.js'; +import { handler } from 'HANDLER'; +import { env } from 'ENV'; import polka from 'polka'; export const path = env('SOCKET_PATH', false); diff --git a/packages/kit/types/index.d.ts b/packages/kit/types/index.d.ts index f5033d642bea..a4b9cb024db4 100644 --- a/packages/kit/types/index.d.ts +++ b/packages/kit/types/index.d.ts @@ -99,7 +99,7 @@ export interface Builder { /** * @param {string} directory Path to the directory containing the files to be compressed */ - compress(directory: string): void; + compress(directory: string): Promise; } export interface Config { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 45616a3e91a5..53aea2e2a00c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -120,6 +120,7 @@ importers: '@sveltejs/kit': workspace:* '@types/node': ^16.11.36 c8: ^7.11.3 + esbuild: ^0.14.48 node-fetch: ^3.2.4 polka: ^1.0.0-next.22 rimraf: ^3.0.2 @@ -127,6 +128,8 @@ importers: sirv: ^2.0.2 typescript: ^4.7.4 uvu: ^0.5.3 + dependencies: + esbuild: 0.14.54 devDependencies: '@rollup/plugin-json': 4.1.0_rollup@2.75.7 '@sveltejs/kit': link:../kit