Skip to content
This repository has been archived by the owner on Jan 11, 2023. It is now read-only.

move app logic into templates (#444) #453

Merged
merged 8 commits into from
Oct 1, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ node_modules
cypress/screenshots
test/app/.sapper
test/app/src/manifest
__sapper__
test/app/export
test/app/build
sapper
Expand Down
1 change: 1 addition & 0 deletions index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1,013 changes: 624 additions & 389 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
"name": "sapper",
"version": "0.21.1",
"description": "Military-grade apps, engineered by Svelte",
"main": "dist/middleware.js",
"bin": {
"sapper": "./sapper"
},
Expand Down Expand Up @@ -32,6 +31,7 @@
"@types/mocha": "^5.2.5",
"@types/node": "^10.7.1",
"@types/rimraf": "^2.0.2",
"agadoo": "^1.0.1",
"cheap-watch": "^0.3.0",
"compression": "^1.7.1",
"cookie": "^0.3.1",
Expand Down
26 changes: 17 additions & 9 deletions rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,45 @@ import json from 'rollup-plugin-json';
import resolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import pkg from './package.json';
import { builtinModules } from 'module';

const external = [].concat(
Object.keys(pkg.dependencies),
Object.keys(process.binding('natives')),
'sapper/core.js'
);

export default [
{
input: `src/runtime/index.ts`,
function template(kind, external) {
return {
input: `templates/src/${kind}/index.ts`,
output: {
file: `runtime.js`,
file: `templates/dist/${kind}.js`,
format: 'es'
},
external,
plugins: [
resolve(),
commonjs(),
string({
include: '**/*.md'
}),
typescript({
typescript: require('typescript'),
target: "ES2017"
})
]
},
};
}

export default [
template('client', ['__ROOT__', '__ERROR__']),
template('server', builtinModules),

{
input: [
`src/api.ts`,
`src/cli.ts`,
`src/core.ts`,
`src/middleware.ts`,
`src/rollup.ts`,
`src/webpack.ts`
],
Expand All @@ -42,9 +53,6 @@ export default [
},
external,
plugins: [
string({
include: '**/*.md'
}),
json(),
resolve(),
commonjs(),
Expand Down
1 change: 0 additions & 1 deletion runtime/README.md

This file was deleted.

2 changes: 0 additions & 2 deletions runtime/app.js

This file was deleted.

11 changes: 4 additions & 7 deletions src/api/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,16 @@ import * as path from 'path';
import mkdirp from 'mkdirp';
import rimraf from 'rimraf';
import { EventEmitter } from 'events';
import * as codec from 'sourcemap-codec';
import hash from 'string-hash';
import minify_html from './utils/minify_html';
import { create_compilers, create_main_manifests, create_manifest_data, create_serviceworker_manifest } from '../core';
import * as events from './interfaces';
import { copy_shimport } from './utils/copy_shimport';
import { Dirs, PageComponent } from '../interfaces';
import { CompileResult } from '../core/create_compilers/interfaces';
import { Dirs } from '../interfaces';
import read_template from '../core/read_template';

type Opts = {
legacy: boolean;
bundler: string;
bundler: 'rollup' | 'webpack';
};

export function build(opts: Opts, dirs: Dirs) {
Expand Down Expand Up @@ -58,7 +55,7 @@ async function execute(emitter: EventEmitter, opts: Opts, dirs: Dirs) {
// create src/manifest/client.js and src/manifest/server.js
create_main_manifests({ bundler: opts.bundler, manifest_data });

const { client, server, serviceworker } = await create_compilers(opts.bundler, dirs);
const { client, server, serviceworker } = await create_compilers(opts.bundler);

const client_result = await client.compile();
emitter.emit('build', <events.BuildEvent>{
Expand All @@ -71,7 +68,7 @@ async function execute(emitter: EventEmitter, opts: Opts, dirs: Dirs) {

if (opts.legacy) {
process.env.SAPPER_LEGACY_BUILD = 'true';
const { client } = await create_compilers(opts.bundler, dirs);
const { client } = await create_compilers(opts.bundler);

const client_result = await client.compile();

Expand Down
6 changes: 3 additions & 3 deletions src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ prog.command('build [dest]')
.option('--bundler', 'Specify a bundler (rollup or webpack, blank for auto)')
.option('--legacy', 'Create separate legacy build')
.example(`build custom-dir -p 4567`)
.action(async (dest = 'build', opts: {
.action(async (dest = '__sapper__/build', opts: {
port: string,
legacy: boolean,
bundler?: string
Expand Down Expand Up @@ -80,12 +80,12 @@ prog.command('start [dir]')
prog.command('export [dest]')
.describe('Export your app as static files (if possible)')
.option('--build', '(Re)build app before exporting', true)
.option('--build-dir', 'Specify a custom temporary build directory', '.sapper/prod')
.option('--build-dir', 'Specify a custom temporary build directory', '__sapper__/build')
.option('--basepath', 'Specify a base path')
.option('--timeout', 'Milliseconds to wait for a page (--no-timeout to disable)', 5000)
.option('--legacy', 'Create separate legacy build')
.option('--bundler', 'Specify a bundler (rollup or webpack, blank for auto)')
.action(async (dest = 'export', opts: {
.action(async (dest = '__sapper__/export', opts: {
build: boolean,
legacy: boolean,
bundler?: string,
Expand Down
2 changes: 1 addition & 1 deletion src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ export const locations = {
src: () => path.resolve(process.env.SAPPER_BASE || '', process.env.SAPPER_SRC || 'src'),
static: () => path.resolve(process.env.SAPPER_BASE || '', process.env.SAPPER_STATIC || 'static'),
routes: () => path.resolve(process.env.SAPPER_BASE || '', process.env.SAPPER_ROUTES || 'src/routes'),
dest: () => path.resolve(process.env.SAPPER_BASE || '', process.env.SAPPER_DEST || `.sapper/${dev() ? 'dev' : 'prod'}`)
dest: () => path.resolve(process.env.SAPPER_BASE || '', process.env.SAPPER_DEST || `__sapper__/${dev() ? 'dev' : 'build'}`)
};
115 changes: 62 additions & 53 deletions src/core/create_manifests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export function create_main_manifests({ bundler, manifest_data, dev_port }: {
manifest_data: ManifestData;
dev_port?: number;
}) {
const manifest_dir = path.join(locations.src(), 'manifest');
const manifest_dir = '__sapper__';
if (!fs.existsSync(manifest_dir)) fs.mkdirSync(manifest_dir);

const path_to_routes = path.relative(manifest_dir, locations.routes());
Expand Down Expand Up @@ -55,7 +55,7 @@ export function create_serviceworker_manifest({ manifest_data, client_files }: {
export const routes = [\n\t${manifest_data.pages.map((r: Page) => `{ pattern: ${r.pattern} }`).join(',\n\t')}\n];
`.replace(/^\t\t/gm, '').trim();

write_if_changed(`${locations.src()}/manifest/service-worker.js`, code);
write_if_changed(`__sapper__/service-worker.js`, code);
}

function generate_client(
Expand All @@ -64,92 +64,100 @@ function generate_client(
bundler: string,
dev_port?: number
) {
const template_file = path.resolve(__dirname, '../templates/dist/client.js');
const template = fs.readFileSync(template_file, 'utf-8');

const page_ids = new Set(manifest_data.pages.map(page =>
page.pattern.toString()));

const server_routes_to_ignore = manifest_data.server_routes.filter(route =>
!page_ids.has(route.pattern.toString()));

let code = `
// This file is generated by Sapper — do not edit it!
import root from ${stringify(get_file(path_to_routes, manifest_data.root))};
import error from ${stringify(posixify(`${path_to_routes}/_error.html`))};

const d = decodeURIComponent;
const component_indexes: Record<string, number> = {};

${manifest_data.components.map(component => {
const components = `[
${manifest_data.components.map((component, i) => {
const annotation = bundler === 'webpack'
? `/* webpackChunkName: "${component.name}" */ `
: '';

const source = get_file(path_to_routes, component);

return `const ${component.name} = {
component_indexes[component.name] = i;

return `{
js: () => import(${annotation}${stringify(source)}),
css: "__SAPPER_CSS_PLACEHOLDER:${stringify(component.file, false)}__"
};`;
}).join('\n')}

export const manifest = {
ignore: [${server_routes_to_ignore.map(route => route.pattern).join(', ')}],

pages: [
${manifest_data.pages.map(page => `{
// ${page.parts[page.parts.length - 1].component.file}
pattern: ${page.pattern},
parts: [
${page.parts.map(part => {
if (part === null) return 'null';

if (part.params.length > 0) {
const props = part.params.map((param, i) => `${param}: d(match[${i + 1}])`);
return `{ component: ${part.component.name}, params: match => ({ ${props.join(', ')} }) }`;
}

return `{ component: ${part.component.name} }`;
}).join(',\n\t\t\t\t\t\t')}
]
}`).join(',\n\n\t\t\t\t')}
],

root,

error
};
}`;
}).join(',\n\t\t')}
]`.replace(/^\t/gm, '').trim();

let needs_decode = false;

let pages = `[
${manifest_data.pages.map(page => `{
// ${page.parts[page.parts.length - 1].component.file}
pattern: ${page.pattern},
parts: [
${page.parts.map(part => {
if (part === null) return 'null';

if (part.params.length > 0) {
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(', ')} }) }`;
}

return `{ i: ${component_indexes[part.component.name]} }`;
}).join(',\n\t\t\t\t')}
]
}`).join(',\n\n\t\t')}
]`.replace(/^\t/gm, '').trim();

if (needs_decode) {
pages = `(d => ${pages})(decodeURIComponent)`
}

// this is included for legacy reasons
export const routes = {};`.replace(/^\t\t/gm, '').trim();
let footer = '';

if (dev()) {
const sapper_dev_client = posixify(
path.resolve(__dirname, '../sapper-dev-client.js')
);

code += `
footer = `

import(${stringify(sapper_dev_client)}).then(client => {
client.connect(${dev_port});
});`.replace(/^\t{3}/gm, '');
}

return code;
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) +
footer;
}

function generate_server(
manifest_data: ManifestData,
path_to_routes: string
) {
const template_file = path.resolve(__dirname, '../templates/dist/server.js');
const template = fs.readFileSync(template_file, 'utf-8');

const imports = [].concat(
manifest_data.server_routes.map(route =>
`import * as ${route.name} from ${stringify(posixify(`${path_to_routes}/${route.file}`))};`),
`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 __${component.name} from ${stringify(get_file(path_to_routes, component))};`),
`import root from ${stringify(get_file(path_to_routes, manifest_data.root))};`,
`import error from ${stringify(posixify(`${path_to_routes}/_error.html`))};`
);

let code = `
// This file is generated by Sapper — do not edit it!
${imports.join('\n')}

const d = decodeURIComponent;
Expand All @@ -159,7 +167,7 @@ function generate_server(
${manifest_data.server_routes.map(route => `{
// ${route.file}
pattern: ${route.pattern},
handlers: ${route.name},
handlers: __${route.name},
params: ${route.params.length > 0
? `match => ({ ${route.params.map((param, i) => `${param}: d(match[${i + 1}])`).join(', ')} })`
: `() => ({})`}
Expand All @@ -177,7 +185,7 @@ function generate_server(
const props = [
`name: "${part.component.name}"`,
`file: ${stringify(part.component.file)}`,
`component: ${part.component.name}`
`component: __${part.component.name}`
];

if (part.params.length > 0) {
Expand All @@ -194,12 +202,13 @@ function generate_server(
root,

error
};

// this is included for legacy reasons
export const routes = {};`.replace(/^\t\t/gm, '').trim();
};`.replace(/^\t\t/gm, '').trim();

return code;
return `// This file is generated by Sapper — do not edit it!\n` + template
.replace('__BUILD__DIR__', JSON.stringify(locations.dest()))
.replace('__SRC__DIR__', JSON.stringify(locations.src()))
.replace('__DEV__', dev() ? 'true' : 'false')
.replace(/const manifest = __MANIFEST__;/, code);
}

function get_file(path_to_routes: string, component: PageComponent) {
Expand Down
Loading