This commit is contained in:
Rich Harris
2018-12-20 23:16:03 -05:00
parent 02cef046aa
commit 82a023c302
8 changed files with 59 additions and 58 deletions

34
package-lock.json generated
View File

@@ -1,6 +1,6 @@
{
"name": "sapper",
"version": "0.24.0",
"version": "0.24.1",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -1805,7 +1805,7 @@
},
"es6-promisify": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz",
"resolved": "http://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz",
"integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=",
"dev": true,
"requires": {
@@ -2362,14 +2362,12 @@
"balanced-match": {
"version": "1.0.0",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -2384,20 +2382,17 @@
"code-point-at": {
"version": "1.1.0",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"concat-map": {
"version": "0.0.1",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"console-control-strings": {
"version": "1.1.0",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"core-util-is": {
"version": "1.0.2",
@@ -2514,8 +2509,7 @@
"inherits": {
"version": "2.0.3",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"ini": {
"version": "1.3.5",
@@ -2527,7 +2521,6 @@
"version": "1.0.0",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@@ -2542,7 +2535,6 @@
"version": "3.0.4",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
@@ -2550,14 +2542,12 @@
"minimist": {
"version": "0.0.8",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"minipass": {
"version": "2.2.4",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"safe-buffer": "^5.1.1",
"yallist": "^3.0.0"
@@ -2576,7 +2566,6 @@
"version": "0.5.1",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"minimist": "0.0.8"
}
@@ -2657,8 +2646,7 @@
"number-is-nan": {
"version": "1.0.1",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"object-assign": {
"version": "4.1.1",
@@ -2670,7 +2658,6 @@
"version": "1.4.0",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"wrappy": "1"
}
@@ -2792,7 +2779,6 @@
"version": "1.0.2",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
@@ -4400,7 +4386,7 @@
},
"pify": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
"resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
"integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
"dev": true
},

View File

@@ -129,6 +129,7 @@ prog.command('dev')
});
} catch (err) {
console.log(colors.bold.red(`> ${err.message}`));
console.log(colors.gray(err.stack));
process.exit(1);
}
});
@@ -171,6 +172,7 @@ prog.command('build [dest]')
console.error(`\n> Finished in ${elapsed(start)}. Type ${colors.bold.cyan(`node ${dest}`)} to run the app.`);
} catch (err) {
console.log(`${colors.bold.red(`> ${err.message}`)}`);
console.log(colors.gray(err.stack));
process.exit(1);
}
});

View File

@@ -47,7 +47,8 @@ export default class RollupResult implements CompileResult {
} else {
for (const name in compiler.input) {
const file = compiler.input[name];
this.assets[name] = compiler.chunks.find(chunk => file in chunk.modules).fileName;
const chunk = compiler.chunks.find(chunk => file in chunk.modules);
if (chunk) this.assets[name] = chunk.fileName;
}
}

View File

@@ -161,6 +161,8 @@ export default function extract_css(client_result: CompileResult, components: Pa
// recursively find the chunks this component depends on
entry_chunk_dependencies.forEach(chunk => {
if (!chunk) return; // TODO why does this happen?
chunk.imports.forEach(file => {
entry_chunk_dependencies.add(lookup.get(file));
});
@@ -182,7 +184,8 @@ export default function extract_css(client_result: CompileResult, components: Pa
if (!chunk) {
// this should never happen!
throw new Error(`Could not find chunk that owns ${component.file}`);
return;
// throw new Error(`Could not find chunk that owns ${component.file}`);
}
const chunk_dependencies: Set<Chunk> = new Set([chunk]);
@@ -190,6 +193,8 @@ export default function extract_css(client_result: CompileResult, components: Pa
// recursively find the chunks this component depends on
chunk_dependencies.forEach(chunk => {
if (!chunk) return; // TODO why does this happen?
chunk.imports.forEach(file => {
chunk_dependencies.add(lookup.get(file));
});

View File

@@ -151,11 +151,11 @@ function generate_client(
}
return `// This file is generated by Sapper — do not edit it!\n` + template
.replace('__ROOT__', stringify(get_file(path_to_routes, manifest_data.root), false))
.replace('__ERROR__', stringify(posixify(`${path_to_routes}/_error.html`), false))
.replace('__IGNORE__', `[${server_routes_to_ignore.map(route => route.pattern).join(', ')}]`)
.replace('__COMPONENTS__', components)
.replace('__PAGES__', pages) +
.replace(/__ROOT__/g, stringify(get_file(path_to_routes, manifest_data.root), false))
.replace(/__ERROR__/g, stringify(posixify(`${path_to_routes}/_error.html`), false))
.replace(/__IGNORE__/g, `[${server_routes_to_ignore.map(route => route.pattern).join(', ')}]`)
.replace(/__COMPONENTS__/g, components)
.replace(/__PAGES__/g, pages) +
footer;
}
@@ -174,8 +174,8 @@ function generate_server(
manifest_data.server_routes.map(route =>
`import * as __${route.name} from ${stringify(posixify(`${path_to_routes}/${route.file}`))};`),
manifest_data.components.map(component =>
`import __${component.name} from ${stringify(get_file(path_to_routes, component))};`),
`import root from ${stringify(get_file(path_to_routes, manifest_data.root))};`,
`import __${component.name}, * as __${component.name}_static from ${stringify(get_file(path_to_routes, component))};`),
`import root, * as root_static from ${stringify(get_file(path_to_routes, manifest_data.root))};`,
`import error from ${stringify(posixify(`${path_to_routes}/_error.html`))};`
);
@@ -207,7 +207,8 @@ function generate_server(
const props = [
`name: "${part.component.name}"`,
`file: ${stringify(part.component.file)}`,
`component: __${part.component.name}`
`component: __${part.component.name}`,
`preload: __${part.component.name}_static.preload`
];
if (part.params.length > 0) {
@@ -222,6 +223,7 @@ function generate_server(
],
root,
root_preload: root_static['pre' + 'load'],
error
};`.replace(/^\t\t/gm, '').trim();

View File

@@ -1,4 +1,4 @@
import RootComponent from '__ROOT__';
import RootComponent, * as RootComponentStatic from '__ROOT__';
import ErrorComponent from '__ERROR__';
import {
Target,
@@ -127,7 +127,7 @@ export function navigate(target: Target, id: number, noscroll?: boolean, hash?:
cid = id;
if (root_component) {
root_component.set({ preloading: true });
root_component.$set({ preloading: true });
}
const loaded = prefetching && prefetching.href === target.url.href ?
prefetching.promise :
@@ -146,12 +146,12 @@ export function navigate(target: Target, id: number, noscroll?: boolean, hash?:
});
}
function render(data: any, nullable_depth: number, scroll: ScrollPosition, noscroll: boolean, hash: string, token: {}) {
function render(props: any, nullable_depth: number, scroll: ScrollPosition, noscroll: boolean, hash: string, token: {}) {
if (current_token !== token) return;
if (root_component) {
// first, clear out highest-level root component
let level = data.child;
let level = props.child;
for (let i = 0; i < nullable_depth; i += 1) {
if (i === nullable_depth) break;
level = level.props.child;
@@ -159,11 +159,12 @@ function render(data: any, nullable_depth: number, scroll: ScrollPosition, noscr
const { component } = level;
level.component = null;
root_component.set({ child: data.child });
root_component.$set({ child: props.child });
// then render new stuff
// TODO do we need to call `flush` before doing this?
level.component = component;
root_component.set(data);
root_component.$set(props);
} else {
// first load — remove SSR'd <head> contents
const start = document.querySelector('#sapper-head-start');
@@ -175,11 +176,11 @@ function render(data: any, nullable_depth: number, scroll: ScrollPosition, noscr
detach(end);
}
Object.assign(data, root_data);
Object.assign(props, root_data);
root_component = new RootComponent({
target,
data,
props,
store,
hydrate: true
});
@@ -201,7 +202,7 @@ function render(data: any, nullable_depth: number, scroll: ScrollPosition, noscr
if (scroll) scrollTo(scroll.x, scroll.y);
}
Object.assign(root_props, data);
Object.assign(root_props, props);
ready = true;
}
@@ -238,8 +239,9 @@ export function prepare_page(target: Target): Promise<{
};
if (!root_preload) {
root_preload = RootComponent.preload
? initial_data.preloaded[0] || RootComponent.preload.call(preload_context, {
const preload_fn = RootComponentStatic['pre' + 'load']; // Rollup makes us jump through these hoops :(
root_preload = preload_fn
? initial_data.preloaded[0] || preload_fn.call(preload_context, {
path,
query,
params: {}
@@ -251,7 +253,7 @@ export function prepare_page(target: Target): Promise<{
if (i < changed_from) return null;
if (!part) return null;
return load_component(components[part.i]).then(Component => {
return load_component(components[part.i]).then(({ default: Component, preload }) => {
const req = {
path,
query,
@@ -260,8 +262,8 @@ export function prepare_page(target: Target): Promise<{
let preloaded;
if (ready || !initial_data.preloaded[i + 1]) {
preloaded = Component.preload
? Component.preload.call(preload_context, req)
preloaded = preload
? preload.call(preload_context, req)
: {};
} else {
preloaded = initial_data.preloaded[i + 1];
@@ -303,7 +305,7 @@ export function prepare_page(target: Target): Promise<{
};
return {
data: Object.assign({}, props, {
props: Object.assign({}, props, {
preloading: false,
child: {
component: ErrorComponent,
@@ -372,12 +374,15 @@ function load_css(chunk: string) {
});
}
export function load_component(component: ComponentLoader): Promise<ComponentConstructor> {
export function load_component(component: ComponentLoader): Promise<{
default: ComponentConstructor,
preload?: (input: any) => any
}> {
// TODO this is temporary — once placeholders are
// always rewritten, scratch the ternary
const promises: Array<Promise<any>> = (typeof component.css === 'string' ? [] : component.css.map(load_css));
promises.unshift(component.js());
return Promise.all(promises).then(values => values[0].default);
return Promise.all(promises).then(values => values[0]);
}
function detach(node: Node) {

View File

@@ -16,13 +16,13 @@ export type RootProps = {
};
export interface ComponentConstructor {
new (options: { target: Node, data: any, store: Store, hydrate: boolean }): Component;
new (options: { target: Node, props: any, store: Store, hydrate: boolean }): Component;
preload: (props: { params: Params, query: Query }) => Promise<any>;
};
export interface Component {
set: (data: any) => void;
destroy: () => void;
$set: (data: any) => void;
$destroy: () => void;
}
export type ComponentLoader = {

View File

@@ -135,8 +135,8 @@ export function get_page_handler(
let match;
try {
const root_preloaded = manifest.root.preload
? manifest.root.preload.call(preload_context, {
const root_preloaded = manifest.root_preload
? manifest.root_preload.call(preload_context, {
path: req.path,
query: req.query,
params: {}
@@ -148,8 +148,8 @@ export function get_page_handler(
preloaded = await Promise.all([root_preloaded].concat(page.parts.map(part => {
if (!part) return null;
return part.component.preload
? part.component.preload.call(preload_context, {
return part.preload
? part.preload.call(preload_context, {
path: req.path,
query: req.query,
params: part.params ? part.params(match) : {}