diff --git a/package-lock.json b/package-lock.json index b6b895e..b51052d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -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 }, diff --git a/src/cli.ts b/src/cli.ts index d3e8667..43e4d45 100755 --- a/src/cli.ts +++ b/src/cli.ts @@ -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); } }); diff --git a/src/core/create_compilers/RollupResult.ts b/src/core/create_compilers/RollupResult.ts index 1c44c2c..adbfeb0 100644 --- a/src/core/create_compilers/RollupResult.ts +++ b/src/core/create_compilers/RollupResult.ts @@ -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; } } diff --git a/src/core/create_compilers/extract_css.ts b/src/core/create_compilers/extract_css.ts index a60d848..47bf99e 100644 --- a/src/core/create_compilers/extract_css.ts +++ b/src/core/create_compilers/extract_css.ts @@ -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 = 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)); }); diff --git a/src/core/create_manifests.ts b/src/core/create_manifests.ts index 3ff7a95..5ce21f0 100644 --- a/src/core/create_manifests.ts +++ b/src/core/create_manifests.ts @@ -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(); diff --git a/templates/src/client/app.ts b/templates/src/client/app.ts index 8461d3d..a99df92 100644 --- a/templates/src/client/app.ts +++ b/templates/src/client/app.ts @@ -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 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 { +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> = (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) { diff --git a/templates/src/client/types.ts b/templates/src/client/types.ts index 2a28582..d3388c3 100644 --- a/templates/src/client/types.ts +++ b/templates/src/client/types.ts @@ -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; }; export interface Component { - set: (data: any) => void; - destroy: () => void; + $set: (data: any) => void; + $destroy: () => void; } export type ComponentLoader = { diff --git a/templates/src/server/middleware/get_page_handler.ts b/templates/src/server/middleware/get_page_handler.ts index 802ee0f..f156dde 100644 --- a/templates/src/server/middleware/get_page_handler.ts +++ b/templates/src/server/middleware/get_page_handler.ts @@ -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) : {}