@sveltejs/adapter-netlify 1.0.0-next.51 → 1.0.0-next.52
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -4
- package/index.d.ts +2 -1
- package/index.js +185 -90
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -6,10 +6,8 @@ If you're using [adapter-auto](../adapter-auto), you don't need to install this
|
|
|
6
6
|
|
|
7
7
|
## Installation
|
|
8
8
|
|
|
9
|
-
> ⚠️ For the time being, the latest version of adapter-netlify is at the @next tag. If you get the error `config.kit.adapter should be an object with an "adapt" method.`, this is a sign that you are using the wrong version (eg `1.0.0-next.0` instead of `1.0.0-next.9`).
|
|
10
|
-
|
|
11
9
|
```bash
|
|
12
|
-
npm i -D @sveltejs/adapter-netlify
|
|
10
|
+
npm i -D @sveltejs/adapter-netlify
|
|
13
11
|
```
|
|
14
12
|
|
|
15
13
|
You can then configure it inside of `svelte.config.js`:
|
|
@@ -19,9 +17,15 @@ import adapter from '@sveltejs/adapter-netlify';
|
|
|
19
17
|
|
|
20
18
|
export default {
|
|
21
19
|
kit: {
|
|
20
|
+
// default options are shown
|
|
22
21
|
adapter: adapter({
|
|
22
|
+
// if true, will create a Netlify Edge Function rather
|
|
23
|
+
// than using standard Node-based functions
|
|
24
|
+
edge: false,
|
|
25
|
+
|
|
23
26
|
// if true, will split your app into multiple functions
|
|
24
|
-
// instead of creating a single one for the entire app
|
|
27
|
+
// instead of creating a single one for the entire app.
|
|
28
|
+
// if `edge` is true, this option cannot be used
|
|
25
29
|
split: false
|
|
26
30
|
})
|
|
27
31
|
}
|
|
@@ -38,6 +42,10 @@ Then, make sure you have a [netlify.toml](https://docs.netlify.com/configure-bui
|
|
|
38
42
|
|
|
39
43
|
If the `netlify.toml` file or the `build.publish` value is missing, a default value of `"build"` will be used. Note that if you have set the publish directory in the Netlify UI to something else then you will need to set it in `netlify.toml` too, or use the default value of `"build"`.
|
|
40
44
|
|
|
45
|
+
## Netlify Edge Functions (beta)
|
|
46
|
+
|
|
47
|
+
SvelteKit supports the beta release of Netlify Edge Functions. If you pass the option `edge: true` to the `adapter` function, server-side rendering will happen in a Deno-based edge function that's deployed close to the site visitor. If set to `false` (the default), the site will deploy to standard Node-based Netlify Functions.
|
|
48
|
+
|
|
41
49
|
## Netlify alternatives to SvelteKit functionality
|
|
42
50
|
|
|
43
51
|
You may build your app using functionality provided directly by SvelteKit without relying on any Netlify functionality. Using the SvelteKit versions of these features will allow them to be used in dev mode, tested with integration tests, and to work with other adapters should you ever decide to switch away from Netlify. However, in some scenarios you may find it beneficial to use the Netlify versions of these features. One example would be if you're migrating an app that's already hosted on Netlify to SvelteKit.
|
package/index.d.ts
CHANGED
package/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { appendFileSync, existsSync, readFileSync, writeFileSync } from 'fs';
|
|
2
|
-
import { join, resolve } from 'path';
|
|
2
|
+
import { join, resolve, posix } from 'path';
|
|
3
3
|
import { fileURLToPath } from 'url';
|
|
4
4
|
import glob from 'tiny-glob/sync.js';
|
|
5
5
|
import esbuild from 'esbuild';
|
|
@@ -12,10 +12,30 @@ import toml from '@iarna/toml';
|
|
|
12
12
|
* } & toml.JsonMap} NetlifyConfig
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
+
/**
|
|
16
|
+
* @typedef {{
|
|
17
|
+
* functions: Array<
|
|
18
|
+
* | {
|
|
19
|
+
* function: string;
|
|
20
|
+
* path: string;
|
|
21
|
+
* }
|
|
22
|
+
* | {
|
|
23
|
+
* function: string;
|
|
24
|
+
* pattern: string;
|
|
25
|
+
* }
|
|
26
|
+
* >;
|
|
27
|
+
* version: 1;
|
|
28
|
+
* }} HandlerManifest
|
|
29
|
+
*/
|
|
30
|
+
|
|
15
31
|
const files = fileURLToPath(new URL('./files', import.meta.url).href);
|
|
32
|
+
const src = fileURLToPath(new URL('./src', import.meta.url).href);
|
|
33
|
+
const edgeSetInEnvVar =
|
|
34
|
+
process.env.NETLIFY_SVELTEKIT_USE_EDGE === 'true' ||
|
|
35
|
+
process.env.NETLIFY_SVELTEKIT_USE_EDGE === '1';
|
|
16
36
|
|
|
17
37
|
/** @type {import('.')} */
|
|
18
|
-
export default function ({ split = false } = {}) {
|
|
38
|
+
export default function ({ split = false, edge = edgeSetInEnvVar } = {}) {
|
|
19
39
|
return {
|
|
20
40
|
name: '@sveltejs/adapter-netlify',
|
|
21
41
|
|
|
@@ -26,99 +46,26 @@ export default function ({ split = false } = {}) {
|
|
|
26
46
|
const publish = get_publish_directory(netlify_config, builder) || 'build';
|
|
27
47
|
|
|
28
48
|
// empty out existing build directories
|
|
29
|
-
builder.rimraf(
|
|
49
|
+
builder.rimraf('.netlify/edge-functions');
|
|
30
50
|
builder.rimraf('.netlify/functions-internal');
|
|
31
51
|
builder.rimraf('.netlify/server');
|
|
32
52
|
builder.rimraf('.netlify/package.json');
|
|
33
53
|
builder.rimraf('.netlify/handler.js');
|
|
34
54
|
|
|
35
|
-
builder.mkdirp('.netlify/functions-internal');
|
|
36
|
-
|
|
37
55
|
builder.log.minor(`Publishing to "${publish}"`);
|
|
38
56
|
|
|
39
|
-
builder.writeServer('.netlify/server');
|
|
40
|
-
|
|
41
57
|
// for esbuild, use ESM
|
|
42
58
|
// for zip-it-and-ship-it, use CJS until https://github.com/netlify/zip-it-and-ship-it/issues/750
|
|
43
59
|
const esm = netlify_config?.functions?.node_bundler === 'esbuild';
|
|
44
60
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
if (esm) {
|
|
53
|
-
builder.copy(`${files}/esm`, '.netlify', { replace });
|
|
61
|
+
if (edge) {
|
|
62
|
+
if (split) {
|
|
63
|
+
throw new Error('Cannot use `split: true` alongside `edge: true`');
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
await generate_edge_functions({ builder });
|
|
54
67
|
} else {
|
|
55
|
-
|
|
56
|
-
const filepath = `.netlify/server/${file}`;
|
|
57
|
-
const input = readFileSync(filepath, 'utf8');
|
|
58
|
-
const output = esbuild.transformSync(input, { format: 'cjs', target: 'node12' }).code;
|
|
59
|
-
writeFileSync(filepath, output);
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
builder.copy(`${files}/cjs`, '.netlify', { replace });
|
|
63
|
-
writeFileSync(join('.netlify', 'package.json'), JSON.stringify({ type: 'commonjs' }));
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
if (split) {
|
|
67
|
-
builder.log.minor('Generating serverless functions...');
|
|
68
|
-
|
|
69
|
-
builder.createEntries((route) => {
|
|
70
|
-
const parts = [];
|
|
71
|
-
|
|
72
|
-
// Netlify's syntax uses '*' and ':param' as "splats" and "placeholders"
|
|
73
|
-
// https://docs.netlify.com/routing/redirects/redirect-options/#splats
|
|
74
|
-
for (const segment of route.segments) {
|
|
75
|
-
if (segment.rest) {
|
|
76
|
-
parts.push('*');
|
|
77
|
-
break; // Netlify redirects don't allow anything after a *
|
|
78
|
-
} else if (segment.dynamic) {
|
|
79
|
-
parts.push(`:${parts.length}`);
|
|
80
|
-
} else {
|
|
81
|
-
parts.push(segment.content);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
const pattern = `/${parts.join('/')}`;
|
|
86
|
-
const name = parts.join('-').replace(/[:.]/g, '_').replace('*', '__rest') || 'index';
|
|
87
|
-
|
|
88
|
-
return {
|
|
89
|
-
id: pattern,
|
|
90
|
-
filter: (other) => matches(route.segments, other.segments),
|
|
91
|
-
complete: (entry) => {
|
|
92
|
-
const manifest = entry.generateManifest({
|
|
93
|
-
relativePath: '../server',
|
|
94
|
-
format: esm ? 'esm' : 'cjs'
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
const fn = esm
|
|
98
|
-
? `import { init } from '../handler.js';\n\nexport const handler = init(${manifest});\n`
|
|
99
|
-
: `const { init } = require('../handler.js');\n\nexports.handler = init(${manifest});\n`;
|
|
100
|
-
|
|
101
|
-
writeFileSync(`.netlify/functions-internal/${name}.js`, fn);
|
|
102
|
-
|
|
103
|
-
redirects.push(`${pattern} /.netlify/functions/${name} 200`);
|
|
104
|
-
}
|
|
105
|
-
};
|
|
106
|
-
});
|
|
107
|
-
} else {
|
|
108
|
-
builder.log.minor('Generating serverless functions...');
|
|
109
|
-
|
|
110
|
-
const manifest = builder.generateManifest({
|
|
111
|
-
relativePath: '../server',
|
|
112
|
-
format: esm ? 'esm' : 'cjs'
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
const fn = esm
|
|
116
|
-
? `import { init } from '../handler.js';\n\nexport const handler = init(${manifest});\n`
|
|
117
|
-
: `const { init } = require('../handler.js');\n\nexports.handler = init(${manifest});\n`;
|
|
118
|
-
|
|
119
|
-
writeFileSync('.netlify/functions-internal/render.js', fn);
|
|
120
|
-
|
|
121
|
-
redirects.push('* /.netlify/functions/render 200');
|
|
68
|
+
await generate_lambda_functions({ builder, esm, split, publish });
|
|
122
69
|
}
|
|
123
70
|
|
|
124
71
|
builder.log.minor('Copying assets...');
|
|
@@ -126,11 +73,6 @@ export default function ({ split = false } = {}) {
|
|
|
126
73
|
builder.writeClient(publish);
|
|
127
74
|
builder.writePrerendered(publish);
|
|
128
75
|
|
|
129
|
-
builder.log.minor('Writing redirects...');
|
|
130
|
-
const redirect_file = join(publish, '_redirects');
|
|
131
|
-
builder.copy('_redirects', redirect_file);
|
|
132
|
-
appendFileSync(redirect_file, `\n\n${redirects.join('\n')}`);
|
|
133
|
-
|
|
134
76
|
builder.log.minor('Writing custom headers...');
|
|
135
77
|
const headers_file = join(publish, '_headers');
|
|
136
78
|
builder.copy('_headers', headers_file);
|
|
@@ -141,6 +83,159 @@ export default function ({ split = false } = {}) {
|
|
|
141
83
|
}
|
|
142
84
|
};
|
|
143
85
|
}
|
|
86
|
+
/**
|
|
87
|
+
* @param { object } params
|
|
88
|
+
* @param {import('@sveltejs/kit').Builder} params.builder
|
|
89
|
+
*/
|
|
90
|
+
async function generate_edge_functions({ builder }) {
|
|
91
|
+
// Don't match the static directory
|
|
92
|
+
const pattern = '^/.*$';
|
|
93
|
+
|
|
94
|
+
// Go doesn't support lookarounds, so we can't do this
|
|
95
|
+
// const pattern = appDir ? `^/(?!${escapeStringRegexp(appDir)}).*$` : '^/.*$';
|
|
96
|
+
|
|
97
|
+
/** @type {HandlerManifest} */
|
|
98
|
+
const edge_manifest = {
|
|
99
|
+
functions: [
|
|
100
|
+
{
|
|
101
|
+
function: 'render',
|
|
102
|
+
pattern
|
|
103
|
+
}
|
|
104
|
+
],
|
|
105
|
+
version: 1
|
|
106
|
+
};
|
|
107
|
+
const tmp = builder.getBuildDirectory('netlify-tmp');
|
|
108
|
+
|
|
109
|
+
builder.rimraf(tmp);
|
|
110
|
+
|
|
111
|
+
builder.mkdirp('.netlify/edge-functions');
|
|
112
|
+
|
|
113
|
+
builder.log.minor('Generating Edge Function...');
|
|
114
|
+
const relativePath = posix.relative(tmp, builder.getServerDirectory());
|
|
115
|
+
|
|
116
|
+
builder.copy(`${src}/edge_function.js`, `${tmp}/entry.js`, {
|
|
117
|
+
replace: {
|
|
118
|
+
'0SERVER': `${relativePath}/index.js`,
|
|
119
|
+
MANIFEST: './manifest.js'
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
const manifest = builder.generateManifest({
|
|
124
|
+
relativePath
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
writeFileSync(
|
|
128
|
+
`${tmp}/manifest.js`,
|
|
129
|
+
`export const manifest = ${manifest};\n\nexport const prerendered = new Set(${JSON.stringify(
|
|
130
|
+
builder.prerendered.paths
|
|
131
|
+
)});\n`
|
|
132
|
+
);
|
|
133
|
+
|
|
134
|
+
await esbuild.build({
|
|
135
|
+
entryPoints: [`${tmp}/entry.js`],
|
|
136
|
+
outfile: '.netlify/edge-functions/render.js',
|
|
137
|
+
bundle: true,
|
|
138
|
+
format: 'esm',
|
|
139
|
+
target: 'es2020',
|
|
140
|
+
platform: 'browser'
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
writeFileSync('.netlify/edge-functions/manifest.json', JSON.stringify(edge_manifest));
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* @param { object } params
|
|
147
|
+
* @param {import('@sveltejs/kit').Builder} params.builder
|
|
148
|
+
* @param { string } params.publish
|
|
149
|
+
* @param { boolean } params.split
|
|
150
|
+
* @param { boolean } params.esm
|
|
151
|
+
*/
|
|
152
|
+
function generate_lambda_functions({ builder, publish, split, esm }) {
|
|
153
|
+
builder.mkdirp('.netlify/functions-internal');
|
|
154
|
+
|
|
155
|
+
/** @type {string[]} */
|
|
156
|
+
const redirects = [];
|
|
157
|
+
builder.writeServer('.netlify/server');
|
|
158
|
+
|
|
159
|
+
const replace = {
|
|
160
|
+
'0SERVER': './server/index.js' // digit prefix prevents CJS build from using this as a variable name, which would also get replaced
|
|
161
|
+
};
|
|
162
|
+
if (esm) {
|
|
163
|
+
builder.copy(`${files}/esm`, '.netlify', { replace });
|
|
164
|
+
} else {
|
|
165
|
+
glob('**/*.js', { cwd: '.netlify/server' }).forEach((file) => {
|
|
166
|
+
const filepath = `.netlify/server/${file}`;
|
|
167
|
+
const input = readFileSync(filepath, 'utf8');
|
|
168
|
+
const output = esbuild.transformSync(input, { format: 'cjs', target: 'node12' }).code;
|
|
169
|
+
writeFileSync(filepath, output);
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
builder.copy(`${files}/cjs`, '.netlify', { replace });
|
|
173
|
+
writeFileSync(join('.netlify', 'package.json'), JSON.stringify({ type: 'commonjs' }));
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (split) {
|
|
177
|
+
builder.log.minor('Generating serverless functions...');
|
|
178
|
+
|
|
179
|
+
builder.createEntries((route) => {
|
|
180
|
+
const parts = [];
|
|
181
|
+
// Netlify's syntax uses '*' and ':param' as "splats" and "placeholders"
|
|
182
|
+
// https://docs.netlify.com/routing/redirects/redirect-options/#splats
|
|
183
|
+
for (const segment of route.segments) {
|
|
184
|
+
if (segment.rest) {
|
|
185
|
+
parts.push('*');
|
|
186
|
+
break; // Netlify redirects don't allow anything after a *
|
|
187
|
+
} else if (segment.dynamic) {
|
|
188
|
+
parts.push(`:${parts.length}`);
|
|
189
|
+
} else {
|
|
190
|
+
parts.push(segment.content);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const pattern = `/${parts.join('/')}`;
|
|
195
|
+
const name = parts.join('-').replace(/[:.]/g, '_').replace('*', '__rest') || 'index';
|
|
196
|
+
|
|
197
|
+
return {
|
|
198
|
+
id: pattern,
|
|
199
|
+
filter: (other) => matches(route.segments, other.segments),
|
|
200
|
+
complete: (entry) => {
|
|
201
|
+
const manifest = entry.generateManifest({
|
|
202
|
+
relativePath: '../server',
|
|
203
|
+
format: esm ? 'esm' : 'cjs'
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
const fn = esm
|
|
207
|
+
? `import { init } from '../handler.js';\n\nexport const handler = init(${manifest});\n`
|
|
208
|
+
: `const { init } = require('../handler.js');\n\nexports.handler = init(${manifest});\n`;
|
|
209
|
+
|
|
210
|
+
writeFileSync(`.netlify/functions-internal/${name}.js`, fn);
|
|
211
|
+
|
|
212
|
+
redirects.push(`${pattern} /.netlify/functions/${name} 200`);
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
});
|
|
216
|
+
} else {
|
|
217
|
+
builder.log.minor('Generating serverless functions...');
|
|
218
|
+
|
|
219
|
+
const manifest = builder.generateManifest({
|
|
220
|
+
relativePath: '../server',
|
|
221
|
+
format: esm ? 'esm' : 'cjs'
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
const fn = esm
|
|
225
|
+
? `import { init } from '../handler.js';\n\nexport const handler = init(${manifest});\n`
|
|
226
|
+
: `const { init } = require('../handler.js');\n\nexports.handler = init(${manifest});\n`;
|
|
227
|
+
|
|
228
|
+
writeFileSync('.netlify/functions-internal/render.js', fn);
|
|
229
|
+
redirects.push('* /.netlify/functions/render 200');
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
builder.log.minor('Writing redirects...');
|
|
233
|
+
const redirect_file = join(publish, '_redirects');
|
|
234
|
+
if (existsSync('_redirects')) {
|
|
235
|
+
builder.copy('_redirects', redirect_file);
|
|
236
|
+
}
|
|
237
|
+
appendFileSync(redirect_file, `\n\n${redirects.join('\n')}`);
|
|
238
|
+
}
|
|
144
239
|
|
|
145
240
|
function get_netlify_config() {
|
|
146
241
|
if (!existsSync('netlify.toml')) return null;
|
|
@@ -159,8 +254,8 @@ function get_netlify_config() {
|
|
|
159
254
|
**/
|
|
160
255
|
function get_publish_directory(netlify_config, builder) {
|
|
161
256
|
if (netlify_config) {
|
|
162
|
-
if (!netlify_config.build
|
|
163
|
-
builder.log.
|
|
257
|
+
if (!netlify_config.build?.publish) {
|
|
258
|
+
builder.log.minor('No publish directory specified in netlify.toml, using default');
|
|
164
259
|
return;
|
|
165
260
|
}
|
|
166
261
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sveltejs/adapter-netlify",
|
|
3
|
-
"version": "1.0.0-next.
|
|
3
|
+
"version": "1.0.0-next.52",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/sveltejs/kit",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"@rollup/plugin-commonjs": "^21.0.0",
|
|
32
32
|
"@rollup/plugin-json": "^4.1.0",
|
|
33
33
|
"@rollup/plugin-node-resolve": "^13.0.5",
|
|
34
|
-
"@sveltejs/kit": "1.0.0-next.
|
|
34
|
+
"@sveltejs/kit": "1.0.0-next.317",
|
|
35
35
|
"rimraf": "^3.0.2",
|
|
36
36
|
"rollup": "^2.58.0",
|
|
37
37
|
"typescript": "^4.6.2",
|