Skip to content

Commit

Permalink
[breaking] do a single bundling with Vite removing esbuild
Browse files Browse the repository at this point in the history
  • Loading branch information
benmccann committed Oct 27, 2021
1 parent 52c0f99 commit 68c21fe
Show file tree
Hide file tree
Showing 20 changed files with 116 additions and 166 deletions.
9 changes: 9 additions & 0 deletions .changeset/tidy-pets-tan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
'@sveltejs/adapter-cloudflare-workers': patch
'@sveltejs/adapter-netlify': patch
'@sveltejs/adapter-node': patch
'@sveltejs/adapter-vercel': patch
'@sveltejs/kit': patch
---

[breaking] do a single bundling with Vite removing esbuild
1 change: 1 addition & 0 deletions documentation/docs/80-adapter-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export default function (options) {
/** @type {import('@sveltejs/kit').Adapter} */
return {
name: 'adapter-package-name',
serverEntryPoint: 'adapter-package-name/entry',
async adapt({ utils, config }) {
// adapter implementation
}
Expand Down
4 changes: 2 additions & 2 deletions examples/hn.svelte.dev/svelte.config.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import netlify from '@sveltejs/adapter-netlify';
import adapter from '@sveltejs/adapter-netlify';

export default {
kit: {
adapter: netlify(),
adapter: adapter(),
target: '#svelte'
}
};
5 changes: 3 additions & 2 deletions packages/adapter-cloudflare-workers/files/entry.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// TODO hardcoding the relative location makes this brittle
import { init, render } from '../output/server/app.js';
// $server-build doesn't exist until the app is built
// @ts-ignore
import { init, render } from '$server-build';
import { getAssetFromKV, NotFoundError } from '@cloudflare/kv-asset-handler';

init();
Expand Down
5 changes: 3 additions & 2 deletions packages/adapter-netlify/files/entry.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// TODO hardcoding the relative location makes this brittle
import { init, render } from '../output/server/app.js';
// $server-build doesn't exist until the app is built
// @ts-ignore
import { init, render } from '$server-build';

init();

Expand Down
27 changes: 3 additions & 24 deletions packages/adapter-netlify/index.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
import { appendFileSync, existsSync, readFileSync, writeFileSync } from 'fs';
import { join, resolve } from 'path';
import { fileURLToPath } from 'url';
import esbuild from 'esbuild';
import toml from '@iarna/toml';

/**
* @typedef {import('esbuild').BuildOptions} BuildOptions
*/

/** @type {import('.')} */
export default function (options) {
export default function () {
return {
name: '@sveltejs/adapter-netlify',
serverEntryPoint: '@sveltejs/adapter-netlify/entry',

async adapt({ utils }) {
// "build" is the default publish directory when Netlify detects SvelteKit
Expand All @@ -24,24 +20,7 @@ export default function (options) {
const files = fileURLToPath(new URL('./files', import.meta.url));

utils.log.minor('Generating serverless function...');
utils.copy(join(files, 'entry.js'), '.svelte-kit/netlify/entry.js');

/** @type {BuildOptions} */
const default_options = {
entryPoints: ['.svelte-kit/netlify/entry.js'],
// Any functions in ".netlify/functions-internal" are bundled in addition to user-defined Netlify functions.
// See https://github.com/netlify/build/pull/3213 for more details
outfile: '.netlify/functions-internal/__render.js',
bundle: true,
inject: [join(files, 'shims.js')],
platform: 'node'
};

const build_options =
options && options.esbuild ? await options.esbuild(default_options) : default_options;

await esbuild.build(build_options);

utils.copy(files, '.netlify');
writeFileSync(join('.netlify', 'package.json'), JSON.stringify({ type: 'commonjs' }));

utils.log.minor('Prerendering static pages...');
Expand Down
6 changes: 4 additions & 2 deletions packages/adapter-netlify/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
".": {
"import": "./index.js"
},
"./entry": {
"import": "./files/entry.js"
},
"./package.json": "./package.json"
},
"main": "index.js",
Expand All @@ -26,8 +29,7 @@
"check-format": "prettier --check . --config ../../.prettierrc --ignore-path .gitignore"
},
"dependencies": {
"@iarna/toml": "^2.2.5",
"esbuild": "^0.13.4"
"@iarna/toml": "^2.2.5"
},
"devDependencies": {
"@sveltejs/kit": "workspace:*"
Expand Down
14 changes: 6 additions & 8 deletions packages/adapter-node/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,13 @@ export default {
adapter: adapter({
// default options are shown
out: 'build',
precompress: false,
env: {
host: 'HOST',
port: 'PORT'
}
precompress: false
})
}
};
```

## Options
## Build Options

### entryPoint

Expand All @@ -39,15 +35,17 @@ The directory to build the server to. It defaults to `build` — i.e. `node buil

Enables precompressing using gzip and brotli for assets and prerendered pages. It defaults to `false`.

### env
## Runtime Options

### Environment variables

By default, the server will accept connections on `0.0.0.0` using port 3000. These can be customised with the `PORT` and `HOST` environment variables:

```
HOST=127.0.0.1 PORT=4000 node build
```

You can specify different environment variables if necessary using the `env` option.
You can also specify `SOCKET_PATH` if you'd like to use a Unix domain socket or Windows named pipe.

## Middleware

Expand Down
74 changes: 8 additions & 66 deletions packages/adapter-node/index.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,5 @@
import esbuild from 'esbuild';
import {
createReadStream,
createWriteStream,
existsSync,
readFileSync,
statSync,
writeFileSync
} from 'fs';
import { join, resolve } from 'path';
import { createReadStream, createWriteStream, existsSync, statSync, writeFileSync } from 'fs';
import { join } from 'path';
import { pipeline } from 'stream';
import glob from 'tiny-glob';
import { fileURLToPath } from 'url';
Expand All @@ -16,22 +8,19 @@ import zlib from 'zlib';

const pipe = promisify(pipeline);

/**
* @typedef {import('esbuild').BuildOptions} BuildOptions
*/

/** @type {import('.')} */
export default function ({
entryPoint = '.svelte-kit/node/index.js',
// TODO: add ability to customize entry point to build/index.js
// entryPoint = '.svelte-kit/node/index.js',
out = 'build',
precompress,
env: { path: path_env = 'SOCKET_PATH', host: host_env = 'HOST', port: port_env = 'PORT' } = {},
esbuild: esbuild_config
env: { path: path_env = 'SOCKET_PATH', host: host_env = 'HOST', port: port_env = 'PORT' } = {}
} = {}) {
return {
name: '@sveltejs/adapter-node',
serverEntryPoint: '@sveltejs/adapter-node/entry',

async adapt({ utils, config }) {
async adapt({ utils }) {
utils.rimraf(out);

utils.log.minor('Copying assets');
Expand All @@ -58,54 +47,7 @@ export default function ({
)}] || (!path && 3000);`
);

/** @type {BuildOptions} */
const defaultOptions = {
entryPoints: ['.svelte-kit/node/middlewares.js'],
outfile: join(out, 'middlewares.js'),
bundle: true,
external: Object.keys(JSON.parse(readFileSync('package.json', 'utf8')).dependencies || {}),
format: 'esm',
platform: 'node',
target: 'node14',
inject: [join(files, 'shims.js')],
define: {
APP_DIR: `"/${config.kit.appDir}/"`
}
};
const build_options = esbuild_config ? await esbuild_config(defaultOptions) : defaultOptions;
await esbuild.build(build_options);

utils.log.minor('Building SvelteKit server');
/** @type {BuildOptions} */
const default_options_ref_server = {
entryPoints: [entryPoint],
outfile: join(out, 'index.js'),
bundle: true,
format: 'esm',
platform: 'node',
target: 'node14',
// external exclude workaround, see https://github.com/evanw/esbuild/issues/514
plugins: [
{
name: 'fix-middlewares-exclude',
setup(build) {
// Match an import of "middlewares.js" and mark it as external
const internal_middlewares_path = resolve('.svelte-kit/node/middlewares.js');
const build_middlewares_path = resolve(out, 'middlewares.js');
build.onResolve({ filter: /\/middlewares\.js$/ }, ({ path, resolveDir }) => {
const resolved = resolve(resolveDir, path);
if (resolved === internal_middlewares_path || resolved === build_middlewares_path) {
return { path: './middlewares.js', external: true };
}
});
}
}
]
};
const build_options_ref_server = esbuild_config
? await esbuild_config(default_options_ref_server)
: default_options_ref_server;
await esbuild.build(build_options_ref_server);
utils.copy('.svelte-kit/output/server/', 'build/');

utils.log.minor('Prerendering static pages');
await utils.prerender({
Expand Down
15 changes: 8 additions & 7 deletions packages/adapter-node/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,20 @@
},
"homepage": "https://kit.svelte.dev",
"type": "module",
"main": "index.js",
"types": "index.d.ts",
"exports": {
".": {
"import": "./index.js"
},
"./entry": {
"import": "./files/index.js"
},
"./middlewares": {
"import": "./files/middlewares.js"
},
"./package.json": "./package.json"
},
"main": "index.js",
"types": "index.d.ts",
"files": [
"files",
"index.d.ts"
],
"scripts": {
"dev": "rollup -cw",
"build": "rollup -c",
Expand All @@ -30,7 +32,6 @@
"prepublishOnly": "npm run build"
},
"dependencies": {
"esbuild": "^0.13.4",
"tiny-glob": "^0.2.9"
},
"devDependencies": {
Expand Down
4 changes: 2 additions & 2 deletions packages/adapter-node/rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export default [
sourcemap: true
},
plugins: [nodeResolve(), commonjs(), json()],
external: ['../output/server/app.js', ...require('module').builtinModules]
external: ['$server-build', ...require('module').builtinModules]
},
{
input: 'src/index.js',
Expand All @@ -21,7 +21,7 @@ export default [
sourcemap: true
},
plugins: [nodeResolve(), commonjs(), json()],
external: ['./middlewares.js', './env.js', ...require('module').builtinModules]
external: ['./middlewares.js', '$server-build', ...require('module').builtinModules]
},
{
input: 'src/shims.js',
Expand Down
16 changes: 9 additions & 7 deletions packages/adapter-node/src/index.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
// @ts-ignore
import { path, host, port } from './env.js';
import { assetsMiddleware, kitMiddleware, prerenderedMiddleware } from './middlewares.js';
import './shims';
import { assetsMiddleware, kitMiddleware, prerenderedMiddleware } from './middlewares';
import compression from 'compression';
import polka from 'polka';

// options
const path = process.env['SOCKET_PATH'] || false;
const host = process.env['HOST'] || '0.0.0.0';
const port = process.env['PORT'] || (!path && 3000);

const server = polka().use(
// https://github.com/lukeed/polka/issues/173
// @ts-ignore - nothing we can do about so just ignore it
// @ts-expect-error - nothing we can do about so just ignore it
compression({ threshold: 0 }),
assetsMiddleware,
kitMiddleware,
prerenderedMiddleware
);

const listenOpts = { path, host, port };

server.listen(listenOpts, () => {
server.listen({ path, host, port }, () => {
console.log(`Listening on ${path ? path : host + ':' + port}`);
});

Expand Down
6 changes: 2 additions & 4 deletions packages/adapter-node/src/middlewares.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
// TODO hardcoding the relative location makes this brittle
// Also, we need most of the logic in another file for testing because
// ../output/server/app.js doesn't exist when we run the tests
// $server-build doesn't exist until the app is built
// @ts-ignore
import { init, render } from '../output/server/app.js';
import { init, render } from '$server-build';
import { create_kit_middleware } from './kit-middleware.js';

import fs from 'fs';
Expand Down
18 changes: 10 additions & 8 deletions packages/adapter-node/src/shims.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { createRequire } from 'module';
export { fetch, Response, Request, Headers } from '@sveltejs/kit/install-fetch';
import { fetch, Response, Request, Headers } from '@sveltejs/kit/install-fetch';

// esbuild automatically renames "require"
// So we still have to use Object.defineProperty here
Object.defineProperty(globalThis, 'require', {
enumerable: true,
value: createRequire(import.meta.url)
});
if (!globalThis.fetch) {
// @ts-expect-error
globalThis.fetch = fetch;
// @ts-expect-error
globalThis.Response = Response;
// @ts-expect-error
globalThis.Request = Request;
globalThis.Headers = Headers;
}
6 changes: 3 additions & 3 deletions packages/adapter-vercel/files/entry.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// $server-build doesn't exist until the app is built
// @ts-ignore
import { init, render } from '$server-build';
import { getRawBody } from '@sveltejs/kit/node';

// TODO hardcoding the relative location makes this brittle
import { init, render } from '../output/server/app.js';

init();

export default async (req, res) => {
Expand Down
8 changes: 3 additions & 5 deletions packages/adapter-vercel/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,9 @@ export default function (options) {
lambda: join(dir, 'functions/node/render')
};

// TODO ideally we'd have something like utils.tmpdir('vercel')
// rather than hardcoding '.svelte-kit/vercel/entry.js', and the
// relative import from that file to output/server/app.js
// would be controlled. at the moment we're exposing
// implementation details that could change
// TODO ideally we'd have something like utils.tmpdir('vercel') rather
// than hardcoding '.svelte-kit/vercel/entry.js'. At the moment we're
// exposing implementation details that could change
utils.log.minor('Generating serverless function...');
utils.copy(join(files, 'entry.js'), '.svelte-kit/vercel/entry.js');

Expand Down
Loading

0 comments on commit 68c21fe

Please sign in to comment.