mirror of
https://github.com/kevin-DL/sapper.git
synced 2026-01-19 22:05:20 +00:00
golf things down a bit
This commit is contained in:
@@ -35,7 +35,7 @@ function template(kind, external) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default [
|
export default [
|
||||||
template('client', []),
|
template('client', ['__ROOT__', '__ERROR__']),
|
||||||
template('server', builtinModules),
|
template('server', builtinModules),
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -75,62 +75,57 @@ function generate_client(
|
|||||||
|
|
||||||
const component_indexes: Record<string, number> = {};
|
const component_indexes: Record<string, number> = {};
|
||||||
|
|
||||||
let code = `
|
const components = `[
|
||||||
import root from ${stringify(get_file(path_to_routes, manifest_data.root))};
|
${manifest_data.components.map((component, i) => {
|
||||||
import error from ${stringify(posixify(`${path_to_routes}/_error.html`))};
|
const annotation = bundler === 'webpack'
|
||||||
|
? `/* webpackChunkName: "${component.name}" */ `
|
||||||
|
: '';
|
||||||
|
|
||||||
const d = decodeURIComponent;
|
const source = get_file(path_to_routes, component);
|
||||||
|
|
||||||
const components = [
|
component_indexes[component.name] = i;
|
||||||
${manifest_data.components.map((component, i) => {
|
|
||||||
const annotation = bundler === 'webpack'
|
|
||||||
? `/* webpackChunkName: "${component.name}" */ `
|
|
||||||
: '';
|
|
||||||
|
|
||||||
const source = get_file(path_to_routes, component);
|
return `{
|
||||||
|
js: () => import(${annotation}${stringify(source)}),
|
||||||
|
css: "__SAPPER_CSS_PLACEHOLDER:${stringify(component.file, false)}__"
|
||||||
|
}`;
|
||||||
|
}).join(',\n\t\t')}
|
||||||
|
]`.replace(/^\t/gm, '').trim();
|
||||||
|
|
||||||
component_indexes[component.name] = i;
|
let needs_decode = false;
|
||||||
|
|
||||||
return `{
|
let pages = `[
|
||||||
js: () => import(${annotation}${stringify(source)}),
|
${manifest_data.pages.map(page => `{
|
||||||
css: "__SAPPER_CSS_PLACEHOLDER:${stringify(component.file, false)}__"
|
// ${page.parts[page.parts.length - 1].component.file}
|
||||||
}`;
|
pattern: ${page.pattern},
|
||||||
}).join(',\n\t\t\t')}
|
parts: [
|
||||||
];
|
${page.parts.map(part => {
|
||||||
|
if (part === null) return 'null';
|
||||||
|
|
||||||
const manifest = {
|
if (part.params.length > 0) {
|
||||||
ignore: [${server_routes_to_ignore.map(route => route.pattern).join(', ')}],
|
needs_decode = true;
|
||||||
|
const props = part.params.map((param, i) => `${param}: d(match[${i + 1}])`);
|
||||||
|
return `{ i: ${component_indexes[part.component.name]}, params: match => ({ ${props.join(', ')} }) }`;
|
||||||
|
}
|
||||||
|
|
||||||
pages: [
|
return `{ i: ${component_indexes[part.component.name]} }`;
|
||||||
${manifest_data.pages.map(page => `{
|
}).join(',\n\t\t\t\t')}
|
||||||
// ${page.parts[page.parts.length - 1].component.file}
|
]
|
||||||
pattern: ${page.pattern},
|
}`).join(',\n\n\t\t')}
|
||||||
parts: [
|
]`.replace(/^\t/gm, '').trim();
|
||||||
${page.parts.map(part => {
|
|
||||||
if (part === null) return 'null';
|
|
||||||
|
|
||||||
if (part.params.length > 0) {
|
if (needs_decode) {
|
||||||
const props = part.params.map((param, i) => `${param}: d(match[${i + 1}])`);
|
pages = `(d => ${pages})(decodeURIComponent)`
|
||||||
return `{ component: components[${component_indexes[part.component.name]}], params: match => ({ ${props.join(', ')} }) }`;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return `{ component: components[${component_indexes[part.component.name]}] }`;
|
let footer = '';
|
||||||
}).join(',\n\t\t\t\t\t\t')}
|
|
||||||
]
|
|
||||||
}`).join(',\n\n\t\t\t\t')}
|
|
||||||
],
|
|
||||||
|
|
||||||
root,
|
|
||||||
|
|
||||||
error
|
|
||||||
};`.replace(/^\t\t/gm, '').trim();
|
|
||||||
|
|
||||||
if (dev()) {
|
if (dev()) {
|
||||||
const sapper_dev_client = posixify(
|
const sapper_dev_client = posixify(
|
||||||
path.resolve(__dirname, '../sapper-dev-client.js')
|
path.resolve(__dirname, '../sapper-dev-client.js')
|
||||||
);
|
);
|
||||||
|
|
||||||
code += `
|
footer = `
|
||||||
|
|
||||||
import(${stringify(sapper_dev_client)}).then(client => {
|
import(${stringify(sapper_dev_client)}).then(client => {
|
||||||
client.connect(${dev_port});
|
client.connect(${dev_port});
|
||||||
@@ -138,7 +133,12 @@ function generate_client(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return `// This file is generated by Sapper — do not edit it!\n` + template
|
return `// This file is generated by Sapper — do not edit it!\n` + template
|
||||||
.replace(/const manifest = __MANIFEST__;/, code);
|
.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) +
|
||||||
|
footer;
|
||||||
}
|
}
|
||||||
|
|
||||||
function generate_server(
|
function generate_server(
|
||||||
|
|||||||
@@ -1,7 +1,20 @@
|
|||||||
import { Manifest, Target, ScrollPosition, Component, Redirect, ComponentLoader, ComponentConstructor, RootProps } from './types';
|
import RootComponent from '__ROOT__';
|
||||||
|
import ErrorComponent from '__ERROR__';
|
||||||
|
import {
|
||||||
|
Target,
|
||||||
|
ScrollPosition,
|
||||||
|
Component,
|
||||||
|
Redirect,
|
||||||
|
ComponentLoader,
|
||||||
|
ComponentConstructor,
|
||||||
|
RootProps,
|
||||||
|
Page
|
||||||
|
} from './types';
|
||||||
import goto from './goto';
|
import goto from './goto';
|
||||||
|
|
||||||
export const manifest: Manifest = __MANIFEST__;
|
const ignore = __IGNORE__;
|
||||||
|
export const components: ComponentLoader[] = __COMPONENTS__;
|
||||||
|
export const pages: Page[] = __PAGES__;
|
||||||
|
|
||||||
let ready = false;
|
let ready = false;
|
||||||
let root_component: Component;
|
let root_component: Component;
|
||||||
@@ -61,16 +74,16 @@ export { _history as history };
|
|||||||
export const scroll_history: Record<string, ScrollPosition> = {};
|
export const scroll_history: Record<string, ScrollPosition> = {};
|
||||||
|
|
||||||
export function select_route(url: URL): Target {
|
export function select_route(url: URL): Target {
|
||||||
if (url.origin !== window.location.origin) return null;
|
if (url.origin !== location.origin) return null;
|
||||||
if (!url.pathname.startsWith(initial_data.baseUrl)) return null;
|
if (!url.pathname.startsWith(initial_data.baseUrl)) return null;
|
||||||
|
|
||||||
const path = url.pathname.slice(initial_data.baseUrl.length);
|
const path = url.pathname.slice(initial_data.baseUrl.length);
|
||||||
|
|
||||||
// avoid accidental clashes between server routes and pages
|
// avoid accidental clashes between server routes and pages
|
||||||
if (manifest.ignore.some(pattern => pattern.test(path))) return;
|
if (ignore.some(pattern => pattern.test(path))) return;
|
||||||
|
|
||||||
for (let i = 0; i < manifest.pages.length; i += 1) {
|
for (let i = 0; i < pages.length; i += 1) {
|
||||||
const page = manifest.pages[i];
|
const page = pages[i];
|
||||||
|
|
||||||
const match = page.pattern.exec(path);
|
const match = page.pattern.exec(path);
|
||||||
if (match) {
|
if (match) {
|
||||||
@@ -88,8 +101,8 @@ export function select_route(url: URL): Target {
|
|||||||
|
|
||||||
export function scroll_state() {
|
export function scroll_state() {
|
||||||
return {
|
return {
|
||||||
x: window.scrollX,
|
x: scrollX,
|
||||||
y: window.scrollY
|
y: scrollY
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,7 +172,7 @@ function render(data: any, nullable_depth: number, scroll: ScrollPosition, token
|
|||||||
|
|
||||||
Object.assign(data, root_data);
|
Object.assign(data, root_data);
|
||||||
|
|
||||||
root_component = new manifest.root({
|
root_component = new RootComponent({
|
||||||
target,
|
target,
|
||||||
data,
|
data,
|
||||||
store,
|
store,
|
||||||
@@ -168,7 +181,7 @@ function render(data: any, nullable_depth: number, scroll: ScrollPosition, token
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (scroll) {
|
if (scroll) {
|
||||||
window.scrollTo(scroll.x, scroll.y);
|
scrollTo(scroll.x, scroll.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.assign(root_props, data);
|
Object.assign(root_props, data);
|
||||||
@@ -195,7 +208,7 @@ export function prepare_page(target: Target): Promise<{
|
|||||||
|
|
||||||
const preload_context = {
|
const preload_context = {
|
||||||
store,
|
store,
|
||||||
fetch: (url: string, opts?: any) => window.fetch(url, opts),
|
fetch: (url: string, opts?: any) => fetch(url, opts),
|
||||||
redirect: (statusCode: number, location: string) => {
|
redirect: (statusCode: number, location: string) => {
|
||||||
if (redirect && (redirect.statusCode !== statusCode || redirect.location !== location)) {
|
if (redirect && (redirect.statusCode !== statusCode || redirect.location !== location)) {
|
||||||
throw new Error(`Conflicting redirects`);
|
throw new Error(`Conflicting redirects`);
|
||||||
@@ -208,8 +221,8 @@ export function prepare_page(target: Target): Promise<{
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (!root_preload) {
|
if (!root_preload) {
|
||||||
root_preload = manifest.root.preload
|
root_preload = RootComponent.preload
|
||||||
? initial_data.preloaded[0] || manifest.root.preload.call(preload_context, {
|
? initial_data.preloaded[0] || RootComponent.preload.call(preload_context, {
|
||||||
path,
|
path,
|
||||||
query,
|
query,
|
||||||
params: {}
|
params: {}
|
||||||
@@ -221,7 +234,7 @@ export function prepare_page(target: Target): Promise<{
|
|||||||
if (i < changed_from) return null;
|
if (i < changed_from) return null;
|
||||||
if (!part) return null;
|
if (!part) return null;
|
||||||
|
|
||||||
return load_component(part.component).then(Component => {
|
return load_component(components[part.i]).then(Component => {
|
||||||
const req = {
|
const req = {
|
||||||
path,
|
path,
|
||||||
query,
|
query,
|
||||||
@@ -276,7 +289,7 @@ export function prepare_page(target: Target): Promise<{
|
|||||||
data: Object.assign({}, props, {
|
data: Object.assign({}, props, {
|
||||||
preloading: false,
|
preloading: false,
|
||||||
child: {
|
child: {
|
||||||
component: manifest.error,
|
component: ErrorComponent,
|
||||||
props
|
props
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export default function goto(href: string, opts = { replaceState: false }) {
|
|||||||
promise = navigate(target, null).then(() => {});
|
promise = navigate(target, null).then(() => {});
|
||||||
if (history) history[opts.replaceState ? 'replaceState' : 'pushState']({ id: cid }, '', href);
|
if (history) history[opts.replaceState ? 'replaceState' : 'pushState']({ id: cid }, '', href);
|
||||||
} else {
|
} else {
|
||||||
window.location.href = href;
|
location.href = href;
|
||||||
promise = new Promise(f => {}); // never resolves
|
promise = new Promise(f => {}); // never resolves
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
import { manifest, load_component } from "../app";
|
import { components, pages, load_component } from "../app";
|
||||||
|
|
||||||
export default function prefetchRoutes(pathnames: string[]) {
|
export default function prefetchRoutes(pathnames: string[]) {
|
||||||
if (!manifest) throw new Error(`You must call init() first`);
|
return pages
|
||||||
|
|
||||||
return manifest.pages
|
|
||||||
.filter(route => {
|
.filter(route => {
|
||||||
if (!pathnames) return true;
|
if (!pathnames) return true;
|
||||||
return pathnames.some(pathname => route.pattern.test(pathname));
|
return pathnames.some(pathname => route.pattern.test(pathname));
|
||||||
})
|
})
|
||||||
.reduce((promise: Promise<any>, route) => promise.then(() => {
|
.reduce((promise: Promise<any>, route) => promise.then(() => {
|
||||||
return Promise.all(route.parts.map(part => part && load_component(part.component)));
|
return Promise.all(route.parts.map(part => part && load_component(components[part.i])));
|
||||||
}), Promise.resolve());
|
}), Promise.resolve());
|
||||||
}
|
}
|
||||||
@@ -26,15 +26,15 @@ export default function start(opts: {
|
|||||||
set_target(opts.target);
|
set_target(opts.target);
|
||||||
if (opts.store) set_store(opts.store);
|
if (opts.store) set_store(opts.store);
|
||||||
|
|
||||||
window.addEventListener('click', handle_click);
|
addEventListener('click', handle_click);
|
||||||
window.addEventListener('popstate', handle_popstate);
|
addEventListener('popstate', handle_popstate);
|
||||||
|
|
||||||
// prefetch
|
// prefetch
|
||||||
window.addEventListener('touchstart', trigger_prefetch);
|
addEventListener('touchstart', trigger_prefetch);
|
||||||
window.addEventListener('mousemove', handle_mousemove);
|
addEventListener('mousemove', handle_mousemove);
|
||||||
|
|
||||||
return Promise.resolve().then(() => {
|
return Promise.resolve().then(() => {
|
||||||
const { hash, href } = window.location;
|
const { hash, href } = location;
|
||||||
|
|
||||||
const deep_linked = hash && document.getElementById(hash.slice(1));
|
const deep_linked = hash && document.getElementById(hash.slice(1));
|
||||||
scroll_history[uid] = deep_linked ?
|
scroll_history[uid] = deep_linked ?
|
||||||
@@ -44,7 +44,7 @@ export default function start(opts: {
|
|||||||
history.replaceState({ id: uid }, '', href);
|
history.replaceState({ id: uid }, '', href);
|
||||||
|
|
||||||
if (!initial_data.error) {
|
if (!initial_data.error) {
|
||||||
const target = select_route(new URL(window.location.href));
|
const target = select_route(new URL(location.href));
|
||||||
if (target) return navigate(target, uid);
|
if (target) return navigate(target, uid);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -83,7 +83,7 @@ function handle_click(event: MouseEvent) {
|
|||||||
const svg = typeof a.href === 'object' && a.href.constructor.name === 'SVGAnimatedString';
|
const svg = typeof a.href === 'object' && a.href.constructor.name === 'SVGAnimatedString';
|
||||||
const href = String(svg ? (<SVGAElement>a).href.baseVal : a.href);
|
const href = String(svg ? (<SVGAElement>a).href.baseVal : a.href);
|
||||||
|
|
||||||
if (href === window.location.href) {
|
if (href === location.href) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -99,7 +99,7 @@ function handle_click(event: MouseEvent) {
|
|||||||
const url = new URL(href);
|
const url = new URL(href);
|
||||||
|
|
||||||
// Don't handle hash changes
|
// Don't handle hash changes
|
||||||
if (url.pathname === window.location.pathname && url.search === window.location.search) return;
|
if (url.pathname === location.pathname && url.search === location.search) return;
|
||||||
|
|
||||||
const target = select_route(url);
|
const target = select_route(url);
|
||||||
if (target) {
|
if (target) {
|
||||||
@@ -122,17 +122,17 @@ function handle_popstate(event: PopStateEvent) {
|
|||||||
scroll_history[cid] = scroll_state();
|
scroll_history[cid] = scroll_state();
|
||||||
|
|
||||||
if (event.state) {
|
if (event.state) {
|
||||||
const url = new URL(window.location.href);
|
const url = new URL(location.href);
|
||||||
const target = select_route(url);
|
const target = select_route(url);
|
||||||
if (target) {
|
if (target) {
|
||||||
navigate(target, event.state.id);
|
navigate(target, event.state.id);
|
||||||
} else {
|
} else {
|
||||||
window.location.href = window.location.href;
|
location.href = location.href;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// hashchange
|
// hashchange
|
||||||
set_uid(uid + 1);
|
set_uid(uid + 1);
|
||||||
set_cid(uid);
|
set_cid(uid);
|
||||||
history.replaceState({ id: cid }, '', window.location.href);
|
history.replaceState({ id: cid }, '', location.href);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -33,7 +33,7 @@ export type ComponentLoader = {
|
|||||||
export type Page = {
|
export type Page = {
|
||||||
pattern: RegExp;
|
pattern: RegExp;
|
||||||
parts: Array<{
|
parts: Array<{
|
||||||
component: ComponentLoader;
|
i: number;
|
||||||
params?: (match: RegExpExecArray) => Record<string, string>;
|
params?: (match: RegExpExecArray) => Record<string, string>;
|
||||||
}>;
|
}>;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user