Skip to content

Commit ccb8825

Browse files
author
Rich Harris
authored
Final (I think) stepping stone PR towards #519/#626 (#893)
* create separate _load_error method * make error component available to renderer * include root layout in route manifests * note to self * allow unspecified adapter * gah whoops * smarter chunking * fix chunking * update tests
1 parent 567e5e2 commit ccb8825

File tree

16 files changed

+153
-112
lines changed

16 files changed

+153
-112
lines changed

packages/kit/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
},
1010
"devDependencies": {
1111
"@rollup/plugin-replace": "^2.4.1",
12+
"@sveltejs/kit": "workspace:*",
1213
"@types/amphtml-validator": "^1.0.1",
1314
"@types/mime": "^2.0.3",
1415
"@types/node": "^14.14.33",

packages/kit/src/core/build/index.js

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -98,15 +98,18 @@ async function build_client({
9898

9999
/** @type {Record<string, string>} */
100100
const input = {
101-
start: path.resolve(cwd, client_entry_file),
102-
layout: path.resolve(cwd, manifest.layout),
103-
error: path.resolve(cwd, manifest.error)
101+
start: path.resolve(cwd, client_entry_file)
104102
};
105103

104+
// This step is optional — Vite/Rollup will create the necessary chunks
105+
// for everything regardless — but it means that entry chunks reflect
106+
// their location in the source code, which is helpful for debugging
106107
manifest.components.forEach((file) => {
107108
const resolved = path.resolve(cwd, file);
108109
const relative = path.relative(config.kit.files.routes, resolved);
109-
input[path.join('pages', relative)] = resolved;
110+
111+
const name = relative.startsWith('..') ? path.basename(file) : path.join('pages', relative);
112+
input[name] = resolved;
110113
});
111114

112115
/** @type {any} */
@@ -152,7 +155,7 @@ async function build_client({
152155

153156
/** @type {ClientManifest} */
154157
const client_manifest = JSON.parse(fs.readFileSync(client_manifest_file, 'utf-8'));
155-
fs.unlinkSync(client_manifest_file);
158+
fs.renameSync(client_manifest_file, `${output_dir}/manifest.json`); // inspectable but not shipped
156159

157160
return client_manifest;
158161
}
@@ -200,6 +203,7 @@ async function build_server(
200203
function find_deps(file, js_deps, css_deps) {
201204
const chunk = client_manifest[file];
202205

206+
if (js_deps.has(chunk.file)) return;
203207
js_deps.add(chunk.file);
204208

205209
if (chunk.css) {
@@ -214,8 +218,7 @@ async function build_server(
214218
/** @type {Record<string, { entry: string, css: string[], js: string[], styles: string[] }>} */
215219
const metadata_lookup = {};
216220

217-
// TODO include layout and error in manifest.components
218-
[manifest.layout, manifest.error, ...manifest.components].forEach((file) => {
221+
manifest.components.forEach((file) => {
219222
const js_deps = new Set();
220223
const css_deps = new Set();
221224

@@ -305,7 +308,7 @@ async function build_server(
305308
const hooks = get_hooks(user_hooks);
306309
307310
const module_lookup = {
308-
${[manifest.layout, manifest.error, ...manifest.components].map(file => `${s(file)}: () => import(${s(app_relative(file))})`)}
311+
${manifest.components.map(file => `${s(file)}: () => import(${s(app_relative(file))})`)}
309312
};
310313
311314
const metadata_lookup = ${s(metadata_lookup)};

packages/kit/src/core/create_app/index.js

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -89,25 +89,22 @@ function generate_client_manifest(manifest_data, base) {
8989
.filter(Boolean)
9090
.join(', ');
9191
92-
return `// ${route.parts[route.parts.length - 1]}\n\t[${tuple}]`;
92+
return `// ${route.parts[route.parts.length - 1]}\n\t\t[${tuple}]`;
9393
} else {
94-
return `// ${route.file}\n\t[${route.pattern}]`;
94+
return `// ${route.file}\n\t\t[${route.pattern}]`;
9595
}
9696
})
97-
.join(',\n\n\t')}
97+
.join(',\n\n\t\t')}
9898
]`.replace(/^\t/gm, '');
9999

100100
return trim(`
101-
import * as layout from ${s(get_path(manifest_data.layout))};
102-
103101
const components = ${components};
104102
105103
const d = decodeURIComponent;
106-
const empty = () => ({});
107104
108105
export const routes = ${routes};
109106
110-
export { layout };
107+
export const fallback = [components[0](), components[1]()];
111108
`);
112109
}
113110

@@ -133,9 +130,11 @@ function generate_app(manifest_data, base) {
133130

134131
let pyramid = `<svelte:component this={components[${l}]} {...(props_${l} || {})}/>`;
135132

136-
while (l-- > 1) {
133+
while (l--) {
137134
pyramid = `
138-
<svelte:component this={components[${l}]} {...(props_${l} || {})}>
135+
<svelte:component this={components[${l}]} {...(props_${l} || {})}${
136+
l === 1 ? ' {status} {error}' : '' // TODO this is awkward
137+
}>
139138
{#if components[${l + 1}]}
140139
${pyramid.replace(/\n/g, '\n\t\t\t\t\t')}
141140
{/if}
@@ -145,13 +144,10 @@ function generate_app(manifest_data, base) {
145144
.trim();
146145
}
147146

148-
const error_file = path.relative(base, manifest_data.error);
149-
150147
return trim(`
151148
<!-- This file is generated by @sveltejs/kit — do not edit it! -->
152149
<script>
153150
import { setContext, afterUpdate, onMount } from 'svelte';
154-
import ErrorComponent from ${s(error_file)};
155151
156152
// error handling
157153
export let status = undefined;
@@ -164,8 +160,6 @@ function generate_app(manifest_data, base) {
164160
export let components;
165161
${levels.map((l) => `export let props_${l} = null;`).join('\n\t\t\t')}
166162
167-
const Layout = components[0];
168-
169163
setContext('__svelte__', stores);
170164
171165
$: stores.page.set(page);
@@ -188,13 +182,7 @@ function generate_app(manifest_data, base) {
188182
});
189183
</script>
190184
191-
<Layout {...(props_0 || {})}>
192-
{#if error}
193-
<ErrorComponent {status} {error}/>
194-
{:else}
195-
${pyramid.replace(/\n/g, '\n\t\t\t\t')}
196-
{/if}
197-
</Layout>
185+
${pyramid.replace(/\n/g, '\n\t\t')}
198186
199187
{#if mounted}
200188
<div id="svelte-announcer" aria-live="assertive" aria-atomic="true">

packages/kit/src/core/create_manifest_data/index.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,9 @@ export default function create_manifest_data({ config, output, cwd = process.cwd
182182
const layout = find_layout('$layout', base) || default_layout;
183183
const error = find_layout('$error', base) || default_error;
184184

185-
walk(config.kit.files.routes, [], [], []);
185+
components.push(layout, error);
186+
187+
walk(config.kit.files.routes, [], [], [layout]);
186188

187189
const assets_dir = config.kit.files.assets;
188190

packages/kit/src/core/create_manifest_data/index.spec.js

Lines changed: 34 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,14 @@ const create = (dir, extensions = ['.svelte']) => {
2424
appDir: '_app'
2525
}
2626
},
27-
cwd
27+
cwd,
28+
output: cwd
2829
});
2930
};
3031

32+
const layout = 'components/layout.svelte';
33+
const error = 'components/error.svelte';
34+
3135
test('creates routes', () => {
3236
const { components, routes } = create('samples/basic');
3337

@@ -36,21 +40,21 @@ test('creates routes', () => {
3640
const blog = 'samples/basic/blog/index.svelte';
3741
const blog_$slug = 'samples/basic/blog/[slug].svelte';
3842

39-
assert.equal(components, [index, about, blog, blog_$slug]);
43+
assert.equal(components, [layout, error, index, about, blog, blog_$slug]);
4044

4145
assert.equal(routes, [
4246
{
4347
type: 'page',
4448
pattern: /^\/$/,
4549
params: [],
46-
parts: [index]
50+
parts: [layout, index]
4751
},
4852

4953
{
5054
type: 'page',
5155
pattern: /^\/about\/?$/,
5256
params: [],
53-
parts: [about]
57+
parts: [layout, about]
5458
},
5559

5660
{
@@ -64,7 +68,7 @@ test('creates routes', () => {
6468
type: 'page',
6569
pattern: /^\/blog\/?$/,
6670
params: [],
67-
parts: [blog]
71+
parts: [layout, blog]
6872
},
6973

7074
{
@@ -78,7 +82,7 @@ test('creates routes', () => {
7882
type: 'page',
7983
pattern: /^\/blog\/([^/]+?)\/?$/,
8084
params: ['slug'],
81-
parts: [blog_$slug]
85+
parts: [layout, blog_$slug]
8286
}
8387
]);
8488
});
@@ -92,21 +96,21 @@ test('creates routes with layout', () => {
9296
const foo = 'samples/basic-layout/foo/index.svelte';
9397

9498
assert.equal(layout, $layout);
95-
assert.equal(components, [index, foo_$layout, foo]);
99+
assert.equal(components, [layout, error, index, foo_$layout, foo]);
96100

97101
assert.equal(routes, [
98102
{
99103
type: 'page',
100104
pattern: /^\/$/,
101105
params: [],
102-
parts: [index]
106+
parts: [layout, index]
103107
},
104108

105109
{
106110
type: 'page',
107111
pattern: /^\/foo\/?$/,
108112
params: [],
109-
parts: [foo_$layout, foo]
113+
parts: [layout, foo_$layout, foo]
110114
}
111115
]);
112116
});
@@ -121,6 +125,8 @@ test('encodes invalid characters', () => {
121125
// const question_mark = 'samples/encoding/?.svelte';
122126

123127
assert.equal(components, [
128+
layout,
129+
error,
124130
// quote,
125131
hash
126132
// question_mark
@@ -142,22 +148,22 @@ test('sorts routes correctly', () => {
142148
assert.equal(
143149
routes.map((p) => (p.type === 'page' ? p.parts : p.file)),
144150
[
145-
['samples/sorting/index.svelte'],
146-
['samples/sorting/about.svelte'],
147-
['samples/sorting/post/index.svelte'],
148-
['samples/sorting/post/bar.svelte'],
149-
['samples/sorting/post/foo.svelte'],
151+
[layout, 'samples/sorting/index.svelte'],
152+
[layout, 'samples/sorting/about.svelte'],
153+
[layout, 'samples/sorting/post/index.svelte'],
154+
[layout, 'samples/sorting/post/bar.svelte'],
155+
[layout, 'samples/sorting/post/foo.svelte'],
150156
'samples/sorting/post/f[zz].ts',
151-
['samples/sorting/post/f[xx].svelte'],
152-
['samples/sorting/post/f[yy].svelte'],
153-
['samples/sorting/post/[id].svelte'],
157+
[layout, 'samples/sorting/post/f[xx].svelte'],
158+
[layout, 'samples/sorting/post/f[yy].svelte'],
159+
[layout, 'samples/sorting/post/[id].svelte'],
154160
'samples/sorting/[endpoint].js',
155-
['samples/sorting/[wildcard].svelte'],
156-
['samples/sorting/[...rest]/deep/[...deep_rest]/xyz.svelte'],
157-
['samples/sorting/[...rest]/deep/[...deep_rest]/index.svelte'],
158-
['samples/sorting/[...rest]/deep/index.svelte'],
159-
['samples/sorting/[...rest]/abc.svelte'],
160-
['samples/sorting/[...rest]/index.svelte']
161+
[layout, 'samples/sorting/[wildcard].svelte'],
162+
[layout, 'samples/sorting/[...rest]/deep/[...deep_rest]/xyz.svelte'],
163+
[layout, 'samples/sorting/[...rest]/deep/[...deep_rest]/index.svelte'],
164+
[layout, 'samples/sorting/[...rest]/deep/index.svelte'],
165+
[layout, 'samples/sorting/[...rest]/abc.svelte'],
166+
[layout, 'samples/sorting/[...rest]/index.svelte']
161167
]
162168
);
163169
});
@@ -241,21 +247,21 @@ test('works with custom extensions', () => {
241247
const blog = 'samples/custom-extension/blog/index.svelte';
242248
const blog_$slug = 'samples/custom-extension/blog/[slug].beebop';
243249

244-
assert.equal(components, [index, about, blog, blog_$slug]);
250+
assert.equal(components, [layout, error, index, about, blog, blog_$slug]);
245251

246252
assert.equal(routes, [
247253
{
248254
type: 'page',
249255
pattern: /^\/$/,
250256
params: [],
251-
parts: [index]
257+
parts: [layout, index]
252258
},
253259

254260
{
255261
type: 'page',
256262
pattern: /^\/about\/?$/,
257263
params: [],
258-
parts: [about]
264+
parts: [layout, about]
259265
},
260266

261267
{
@@ -269,7 +275,7 @@ test('works with custom extensions', () => {
269275
type: 'page',
270276
pattern: /^\/blog\/?$/,
271277
params: [],
272-
parts: [blog]
278+
parts: [layout, blog]
273279
},
274280

275281
{
@@ -283,7 +289,7 @@ test('works with custom extensions', () => {
283289
type: 'page',
284290
pattern: /^\/blog\/([^/]+?)\/?$/,
285291
params: ['slug'],
286-
parts: [blog_$slug]
292+
parts: [layout, blog_$slug]
287293
}
288294
]);
289295
});

packages/kit/src/core/dev/index.js

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -218,9 +218,6 @@ class Watcher extends EventEmitter {
218218
},
219219
manifest: this.manifest,
220220
load_component: async (id) => {
221-
// if (id === 'layout') id = this.manifest.layout;
222-
// if (id === 'error') id = this.manifest.error;
223-
224221
const url = path.resolve(this.cwd, id);
225222

226223
const module = /** @type {SSRComponent} */ (await this.vite.ssrLoadModule(url));

packages/kit/src/core/load_config/index.spec.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ test('fills in defaults', () => {
1111
compilerOptions: null,
1212
extensions: ['.svelte'],
1313
kit: {
14-
adapter: [null],
14+
adapter: null,
1515
amp: false,
1616
appDir: '_app',
1717
files: {
@@ -93,7 +93,7 @@ test('fills in partial blanks', () => {
9393
compilerOptions: null,
9494
extensions: ['.svelte'],
9595
kit: {
96-
adapter: [null],
96+
adapter: null,
9797
amp: false,
9898
appDir: '_app',
9999
files: {

packages/kit/src/core/load_config/options.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ const options = {
3737
children: {
3838
adapter: {
3939
type: 'leaf',
40-
default: [null],
40+
default: null,
4141
validate: (option, keypath) => {
4242
if (typeof option !== 'object' || !option.adapt) {
4343
let message = `${keypath} should be an object with an "adapt" method`;

packages/kit/src/core/load_config/test/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ test('load default config', async () => {
1818
compilerOptions: null,
1919
extensions: ['.svelte'],
2020
kit: {
21-
adapter: [null],
21+
adapter: null,
2222
amp: false,
2323
appDir: '_app',
2424
files: {

0 commit comments

Comments
 (0)