Skip to content

Commit

Permalink
Adapter bundle (#1091)
Browse files Browse the repository at this point in the history
* tinkering

* lint

* simplify vercel adapter

* note to self

* expose @sveltejs/kit/install-fetch for adapters

* use install-fetch in vercel adapter

* update netlify adapter

* ignore netlify folders

* lint

* lint

* use install-fetch in adapter-node

* changesets
  • Loading branch information
Rich Harris authored Apr 18, 2021
1 parent 120f6e6 commit 7a4b351
Show file tree
Hide file tree
Showing 24 changed files with 143 additions and 143 deletions.
5 changes: 5 additions & 0 deletions .changeset/light-keys-mix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sveltejs/adapter-node': patch
---

Use install-fetch helper
5 changes: 5 additions & 0 deletions .changeset/smart-mugs-chew.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sveltejs/kit': patch
---

Expose install-fetch subpackage for adapters to use
6 changes: 6 additions & 0 deletions .changeset/smooth-shoes-mix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@sveltejs/adapter-netlify': patch
'@sveltejs/adapter-vercel': patch
---

Bundle serverless functions with esbuild
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ yarn.lock
/packages/create-svelte/template/CHANGELOG.md
.env
.vercel_build_output
.netlify
.svelte
1 change: 1 addition & 0 deletions packages/adapter-netlify/files/_redirects
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/* /.netlify/functions/render 200
Original file line number Diff line number Diff line change
@@ -1,14 +1,7 @@
'use strict';
import '@sveltejs/kit/install-fetch'; // eslint-disable-line import/no-unresolved

import { URLSearchParams } from 'url';
import { render } from './app.mjs'; // eslint-disable-line import/no-unresolved
import fetch, { Response, Request, Headers } from 'node-fetch';

// provide server-side fetch
globalThis.fetch = fetch;
globalThis.Response = Response;
globalThis.Request = Request;
globalThis.Headers = Headers;
// TODO hardcoding the relative location makes this brittle
import { render } from '../output/server/app.js'; // eslint-disable-line import/no-unresolved

export async function handler(event) {
const {
Expand Down
6 changes: 0 additions & 6 deletions packages/adapter-netlify/files/index.cjs

This file was deleted.

91 changes: 49 additions & 42 deletions packages/adapter-netlify/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const { existsSync, readFileSync, copyFileSync, writeFileSync, renameSync } = require('fs');
const { resolve } = require('path');
const { existsSync, readFileSync, writeFileSync } = require('fs');
const { join } = require('path');
const esbuild = require('esbuild');
const toml = require('toml');

module.exports = function () {
Expand All @@ -8,58 +9,64 @@ module.exports = function () {
name: '@sveltejs/adapter-netlify',

async adapt(utils) {
let netlify_config;

if (existsSync('netlify.toml')) {
try {
netlify_config = toml.parse(readFileSync('netlify.toml', 'utf-8'));
} catch (err) {
err.message = `Error parsing netlify.toml: ${err.message}`;
throw err;
}
} else {
// TODO offer to create one?
throw new Error(
'Missing a netlify.toml file. Consult https://github.com/sveltejs/kit/tree/master/packages/adapter-netlify#configuration'
);
}

if (
!netlify_config.build ||
!netlify_config.build.publish ||
!netlify_config.build.functions
) {
throw new Error(
'You must specify build.publish and build.functions in netlify.toml. Consult https://github.com/sveltejs/kit/tree/master/packages/adapter-netlify#configuration'
);
}

const publish = resolve(netlify_config.build.publish);
const functions = resolve(netlify_config.build.functions);
const { publish, functions } = validate_config().build;

utils.copy_static_files(publish);
utils.copy_client_files(publish);
utils.copy_server_files(`${functions}/render`);
utils.rimraf(publish);
utils.rimraf(functions);

// rename app to .mjs
renameSync(`${functions}/render/app.js`, `${functions}/render/app.mjs`);
const files = join(__dirname, 'files');

// copy the renderer
copyFileSync(resolve(__dirname, 'files/render.js'), `${functions}/render/handler.mjs`);
utils.log.minor('Generating serverless function...');
utils.copy(join(files, 'entry.js'), '.svelte/netlify/entry.js');

// copy the entry point
copyFileSync(resolve(__dirname, 'files/index.cjs'), `${functions}/render/index.js`);
await esbuild.build({
entryPoints: ['.svelte/netlify/entry.js'],
outfile: join(functions, 'index.js'),
bundle: true,
platform: 'node'
});

// create _redirects
writeFileSync(`${publish}/_redirects`, '/* /.netlify/functions/render 200');
writeFileSync(join(functions, 'package.json'), JSON.stringify({ type: 'commonjs' }));

// prerender
utils.log.info('Prerendering static pages...');
await utils.prerender({
dest: publish
});

utils.log.minor('Copying assets...');
utils.copy_static_files(publish);
utils.copy_client_files(publish);

utils.log.minor('Writing redirects...');
utils.copy(`${files}/_redirects`, `${publish}/_redirects`);
}
};

return adapter;
};

function validate_config() {
if (existsSync('netlify.toml')) {
let netlify_config;

try {
netlify_config = toml.parse(readFileSync('netlify.toml', 'utf-8'));
} catch (err) {
err.message = `Error parsing netlify.toml: ${err.message}`;
throw err;
}

if (!netlify_config.build || !netlify_config.build.publish || !netlify_config.build.functions) {
throw new Error(
'You must specify build.publish and build.functions in netlify.toml. Consult https://github.com/sveltejs/kit/tree/master/packages/adapter-netlify#configuration'
);
}

return netlify_config;
}

// TODO offer to create one?
throw new Error(
'Missing a netlify.toml file. Consult https://github.com/sveltejs/kit/tree/master/packages/adapter-netlify#configuration'
);
}
17 changes: 5 additions & 12 deletions packages/adapter-node/src/server.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,11 @@
import compression from 'compression';
import fs from 'fs';
import polka from 'polka';
import { dirname, join } from 'path';
import { fileURLToPath } from 'url';
import compression from 'compression';
import polka from 'polka';
import sirv from 'sirv';
import { URL, fileURLToPath } from 'url';
// eslint-disable-next-line import/no-unresolved
import { get_body } from '@sveltejs/kit/http';
import fetch, { Response, Request, Headers } from 'node-fetch';

// provide server-side fetch
globalThis.fetch = fetch;
globalThis.Response = Response;
globalThis.Request = Request;
globalThis.Headers = Headers;
import { get_body } from '@sveltejs/kit/http'; // eslint-disable-line import/no-unresolved
import '@sveltejs/kit/install-fetch'; // eslint-disable-line import/no-unresolved

// App is a dynamic file built from the application layer.

Expand Down
3 changes: 1 addition & 2 deletions packages/adapter-vercel/.gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
.DS_Store
node_modules
/files
node_modules
Original file line number Diff line number Diff line change
@@ -1,19 +1,12 @@
import { URL } from 'url';
// eslint-disable-next-line import/no-unresolved
import { get_body } from '@sveltejs/kit/http';
import fetch, { Response, Request, Headers } from 'node-fetch';
import { get_body } from '@sveltejs/kit/http'; // eslint-disable-line import/no-unresolved
import '@sveltejs/kit/install-fetch'; // eslint-disable-line import/no-unresolved

// provide server-side fetch
globalThis.fetch = fetch;
globalThis.Response = Response;
globalThis.Request = Request;
globalThis.Headers = Headers;
// TODO hardcoding the relative location makes this brittle
import { render } from '../output/server/app.js'; // eslint-disable-line import/no-unresolved

export default async (req, res) => {
const { pathname, searchParams } = new URL(req.url || '', 'http://localhost');

const { render } = await import('./server/app.mjs');

const rendered = await render({
method: req.method,
headers: req.headers,
Expand Down
9 changes: 9 additions & 0 deletions packages/adapter-vercel/files/routes.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[
{
"handle": "filesystem"
},
{
"src": "/.*",
"dest": ".vercel/functions/render"
}
]
68 changes: 34 additions & 34 deletions packages/adapter-vercel/index.js
Original file line number Diff line number Diff line change
@@ -1,51 +1,51 @@
const { writeFileSync, mkdirSync, renameSync } = require('fs');
const { resolve, join } = require('path');
const { writeFileSync } = require('fs');
const { join } = require('path');
const esbuild = require('esbuild');

module.exports = function () {
/** @type {import('@sveltejs/kit').Adapter} */
const adapter = {
name: '@sveltejs/adapter-vercel',

async adapt(utils) {
const vercel_output_directory = resolve('.vercel_build_output');
const config_directory = join(vercel_output_directory, 'config');
const static_directory = join(vercel_output_directory, 'static');
const lambda_directory = join(vercel_output_directory, 'functions', 'node', 'render');
const server_directory = join(lambda_directory, 'server');

utils.log.minor('Writing client application...');
utils.copy_static_files(static_directory);
utils.copy_client_files(static_directory);

utils.log.minor('Building lambda...');
utils.copy_server_files(server_directory);
renameSync(join(server_directory, 'app.js'), join(server_directory, 'app.mjs'));
const dir = '.vercel_build_output';
utils.rimraf(dir);

const files = join(__dirname, 'files');

const dirs = {
static: join(dir, 'static'),
lambda: join(dir, 'functions/node/render')
};

// TODO ideally we'd have something like utils.tmpdir('vercel')
// rather than hardcoding '.svelte/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
utils.log.minor('Generating serverless function...');
utils.copy(join(files, 'entry.js'), '.svelte/vercel/entry.js');

await esbuild.build({
entryPoints: ['.svelte/vercel/entry.js'],
outfile: join(dirs.lambda, 'index.js'),
bundle: true,
platform: 'node'
});

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

utils.log.minor('Prerendering static pages...');
await utils.prerender({
dest: static_directory
dest: dirs.static
});

utils.log.minor('Copying assets...');
utils.copy_static_files(dirs.static);
utils.copy_client_files(dirs.static);

utils.log.minor('Writing routes...');
try {
mkdirSync(config_directory);
} catch {
// directory already exists
}
writeFileSync(
join(config_directory, 'routes.json'),
JSON.stringify([
{
handle: 'filesystem'
},
{
src: '/.*',
dest: '.vercel/functions/render'
}
])
);
utils.copy(join(files, 'routes.json'), join(dir, 'config/routes.json'));
}
};

Expand Down
8 changes: 2 additions & 6 deletions packages/adapter-vercel/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,13 @@
"files"
],
"scripts": {
"dev": "rollup -cw",
"build": "rollup -c",
"lint": "eslint --ignore-path .gitignore \"**/*.{ts,js,svelte}\" && npm run check-format",
"format": "prettier --write . --config ../../.prettierrc --ignore-path .gitignore",
"check-format": "prettier --check . --config ../../.prettierrc --ignore-path .gitignore",
"prepublishOnly": "npm run build"
"check-format": "prettier --check . --config ../../.prettierrc --ignore-path .gitignore"
},
"devDependencies": {
"@sveltejs/kit": "workspace:*",
"rollup": "^2.41.1",
"sirv": "^1.0.11",
"esbuild": "^0.11.12",
"typescript": "^4.2.3"
}
}
4 changes: 0 additions & 4 deletions packages/adapter-vercel/src/index.cjs

This file was deleted.

2 changes: 1 addition & 1 deletion packages/create-svelte/templates/default/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"version": "0.0.1",
"scripts": {
"dev": "svelte-kit dev",
"build": "svelte-kit build",
"build": "svelte-kit build --verbose",
"start": "svelte-kit start"
},
"devDependencies": {
Expand Down
8 changes: 1 addition & 7 deletions packages/create-svelte/templates/default/svelte.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,7 @@ const config = {

kit: {
// hydrate the <div id="svelte"> element in src/app.html
target: '#svelte',

vite: {
ssr: {
noExternal: Object.keys(pkg.dependencies || {})
}
}
target: '#svelte'
}
};

Expand Down
3 changes: 3 additions & 0 deletions packages/kit/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@
"./http": {
"import": "./dist/http.js"
},
"./install-fetch": {
"import": "./dist/install-fetch.js"
},
"./types": "./types/index.d.ts"
},
"types": "types/index.d.ts",
Expand Down
3 changes: 2 additions & 1 deletion packages/kit/rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ export default [
input: {
cli: 'src/cli.js',
ssr: 'src/runtime/server/index.js',
http: 'src/core/http/index.js'
http: 'src/core/http/index.js',
'install-fetch': 'src/install-fetch.js'
},
output: {
dir: 'dist',
Expand Down
2 changes: 1 addition & 1 deletion packages/kit/src/core/adapt/prerender.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { readFileSync, writeFileSync } from 'fs';
import { dirname, join, resolve as resolve_path } from 'path';
import { parse, pathToFileURL, resolve } from 'url';
import { mkdirp } from '../filesystem/index.js';
import '../node-fetch-global.js';
import '../../install-fetch.js';

/** @param {string} html */
function clean_html(html) {
Expand Down
Loading

1 comment on commit 7a4b351

@vercel
Copy link

@vercel vercel bot commented on 7a4b351 Apr 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.