sapper build defaults to build dir, sapper export defaults to export dir (#133)

This commit is contained in:
Rich Harris
2018-03-03 12:09:06 -05:00
parent d9cb572271
commit b73e5eaa8e
11 changed files with 71 additions and 74 deletions

4
.gitignore vendored
View File

@@ -4,6 +4,7 @@ node_modules
cypress/screenshots
test/app/.sapper
test/app/app/manifest
test/app/export
runtime.js
runtime.js.map
cli.js
@@ -13,4 +14,5 @@ middleware.js.map
core.js
core.js.map
webpack/config.js
webpack/config.js.map
webpack/config.js.map
yarn-error.log

View File

@@ -2,18 +2,16 @@ import * as fs from 'fs';
import * as path from 'path';
import mkdirp from 'mkdirp';
import rimraf from 'rimraf';
import { create_compilers, create_app, create_routes, create_serviceworker } from 'sapper/core.js';
import { create_compilers, create_app, create_routes, create_serviceworker } from 'sapper/core.js'
import { src, dest, dev } from '../config';
export default async function build({ src, dest, dev, entry }: {
src: string;
dest: string;
dev: boolean;
entry: { client: string, server: string }
}) {
mkdirp.sync(dest);
rimraf.sync(path.join(dest, '**/*'));
export default async function build() {
const output = dest();
const routes = create_routes({ src });
mkdirp.sync(output);
rimraf.sync(path.join(output, '**/*'));
const routes = create_routes();
// create app/manifest/client.js and app/manifest/server.js
create_app({ routes, src, dev });
@@ -21,7 +19,7 @@ export default async function build({ src, dest, dev, entry }: {
const { client, server, serviceworker } = create_compilers();
const client_stats = await compile(client);
fs.writeFileSync(path.join(dest, 'client_info.json'), JSON.stringify(client_stats.toJson()));
fs.writeFileSync(path.join(output, 'client_info.json'), JSON.stringify(client_stats.toJson()));
await compile(server);

View File

@@ -7,6 +7,7 @@ import * as http from 'http';
import mkdirp from 'mkdirp';
import rimraf from 'rimraf';
import { wait_for_port } from './utils';
import { dest } from '../config';
import { create_compilers, create_app, create_routes, create_serviceworker, create_template } from 'sapper/core.js';
type Deferred = {
@@ -66,7 +67,9 @@ function create_hot_update_server(port: number, interval = 10000) {
return { send };
}
export default async function dev(src: string, dir: string) {
export default async function dev() {
const dir = dest();
rimraf.sync(dir);
mkdirp.sync(dir);
@@ -75,8 +78,8 @@ export default async function dev(src: string, dir: string) {
// initial build
const dev_port = await require('get-port')(10000);
const routes = create_routes({ src });
create_app({ routes, src, dev: true, dev_port });
const routes = create_routes();
create_app({ routes, dev_port });
const hot_update_server = create_hot_update_server(dev_port);
@@ -94,8 +97,8 @@ export default async function dev(src: string, dir: string) {
}
watch_files('routes/**/*.+(html|js|mjs)', () => {
const routes = create_routes({ src });
create_app({ routes, src, dev: true, dev_port });
const routes = create_routes();
create_app({ routes, dev_port });
});
watch_files('app/template.html', () => {
@@ -190,9 +193,8 @@ export default async function dev(src: string, dir: string) {
});
create_serviceworker({
routes: create_routes({ src }),
client_files,
src
routes: create_routes(),
client_files
});
watch_serviceworker();

View File

@@ -6,8 +6,7 @@ import cheerio from 'cheerio';
import URL from 'url-parse';
import fetch from 'node-fetch';
import { wait_for_port } from './utils';
const { OUTPUT_DIR = 'dist' } = process.env;
import { dest } from '../config';
const app = express();
@@ -15,19 +14,24 @@ function read_json(file: string) {
return JSON.parse(sander.readFileSync(file, { encoding: 'utf-8' }));
}
export default async function exporter(dir: string) { // dir === '.sapper'
// Prep output directory
sander.rimrafSync(OUTPUT_DIR);
export default async function exporter(export_dir: string) {
const build_dir = dest();
sander.copydirSync('assets').to(OUTPUT_DIR);
sander.copydirSync(dir, 'client').to(OUTPUT_DIR, 'client');
sander.copyFileSync(dir, 'service-worker.js').to(OUTPUT_DIR, 'service-worker.js');
// Prep output directory
sander.rimrafSync(export_dir);
sander.copydirSync('assets').to(export_dir);
sander.copydirSync(build_dir, 'client').to(export_dir, 'client');
if (sander.existsSync(build_dir, 'service-worker.js')) {
sander.copyFileSync(build_dir, 'service-worker.js').to(export_dir, 'service-worker.js');
}
const port = await require('get-port')(3000);
const origin = `http://localhost:${port}`;
const proc = child_process.fork(path.resolve(`${dir}/server.js`), [], {
const proc = child_process.fork(path.resolve(`${build_dir}/server.js`), [], {
cwd: process.cwd(),
env: {
PORT: port,
@@ -48,11 +52,11 @@ export default async function exporter(dir: string) { // dir === '.sapper'
saved.add(url.pathname);
if (message.type === 'text/html') {
const dest = `${OUTPUT_DIR}/${url.pathname}/index.html`;
sander.writeFileSync(dest, message.body);
const file = `${export_dir}/${url.pathname}/index.html`;
sander.writeFileSync(file, message.body);
} else {
const dest = `${OUTPUT_DIR}/${url.pathname}`;
sander.writeFileSync(dest, message.body);
const file = `${export_dir}/${url.pathname}`;
sander.writeFileSync(file, message.body);
}
});

View File

@@ -5,7 +5,6 @@ import build from './build';
import exporter from './export';
import dev from './dev';
import upgrade from './upgrade';
import { dest, entry, src } from '../config';
import * as pkg from '../../package.json';
const opts = mri(process.argv.slice(2), {
@@ -31,8 +30,9 @@ const start = Date.now();
if (cmd === 'build') {
process.env.NODE_ENV = 'production';
process.env.SAPPER_DEST = opts._[1] || 'build';
build({ dest, dev: false, entry, src })
build()
.then(() => {
const elapsed = Date.now() - start;
console.error(`built in ${elapsed}ms`); // TODO beautify this, e.g. 'built in 4.7 seconds'
@@ -43,8 +43,10 @@ if (cmd === 'build') {
} else if (cmd === 'export') {
process.env.NODE_ENV = 'production';
build({ dest, dev: false, entry, src })
.then(() => exporter(dest))
const export_dir = opts._[1] || 'export';
build()
.then(() => exporter(export_dir))
.then(() => {
const elapsed = Date.now() - start;
console.error(`extracted in ${elapsed}ms`); // TODO beautify this, e.g. 'built in 4.7 seconds'
@@ -53,7 +55,7 @@ if (cmd === 'build') {
console.error(err ? err.details || err.stack || err.message || err : 'Unknown error');
});
} else if (cmd === 'dev') {
dev(src, dest);
dev();
} else if (cmd === 'upgrade') {
upgrade();
} else {

View File

@@ -1,12 +1,5 @@
import * as path from 'path';
export const isDev = () => process.env.NODE_ENV !== 'production';
export const templates = path.resolve(process.env.SAPPER_TEMPLATES || 'templates');
export const src = path.resolve(process.env.SAPPER_ROUTES || 'routes');
export const dest = path.resolve(process.env.SAPPER_DEST || '.sapper');
export const entry = {
client: path.resolve(templates, '.main.rendered.js'),
server: path.resolve(dest, 'server-entry.js')
};
export const dev = () => process.env.NODE_ENV !== 'production';
export const src = () => path.resolve(process.env.SAPPER_ROUTES || 'routes');
export const dest = () => path.resolve(process.env.SAPPER_DEST || '.sapper');

View File

@@ -3,21 +3,20 @@ import * as path from 'path';
import mkdirp from 'mkdirp';
import create_routes from './create_routes';
import { fudge_mtime, posixify, write } from './utils';
import { dev } from '../config';
import { Route } from '../interfaces';
export default function create_app({ routes, src, dev, dev_port }: {
export default function create_app({ routes, dev_port }: {
routes: Route[];
src: string;
dev: boolean;
dev_port: number;
}) {
mkdirp.sync('app/manifest');
write('app/manifest/client.js', generate_client(routes, src, dev, dev_port));
write('app/manifest/server.js', generate_server(routes, src));
write('app/manifest/client.js', generate_client(routes, dev_port));
write('app/manifest/server.js', generate_server(routes));
}
function generate_client(routes: Route[], src: string, dev: boolean, dev_port?: number) {
function generate_client(routes: Route[], dev_port?: number) {
let code = `
// This file is generated by Sapper — do not edit it!
export const routes = [
@@ -42,7 +41,7 @@ function generate_client(routes: Route[], src: string, dev: boolean, dev_port?:
.join(',\n\t')}
];`.replace(/^\t\t/gm, '').trim();
if (dev) {
if (dev()) {
const hmr_client = posixify(
path.resolve(__dirname, 'hmr-client.js')
);
@@ -59,7 +58,7 @@ function generate_client(routes: Route[], src: string, dev: boolean, dev_port?:
return code;
}
function generate_server(routes: Route[], src: string) {
function generate_server(routes: Route[]) {
let code = `
// This file is generated by Sapper — do not edit it!
${routes
@@ -74,7 +73,7 @@ function generate_server(routes: Route[], src: string) {
export const routes = [
${routes
.map(route => {
const file = posixify(`${src}/${route.file}`);
const file = posixify(`../../${route.file}`);
if (route.id === '_4xx' || route.id === '_5xx') {
return `{ error: '${route.id.slice(1)}', module: ${route.id} }`;

View File

@@ -1,11 +1,9 @@
import * as path from 'path';
import glob from 'glob';
import { src } from '../config';
import { Route } from '../interfaces';
export default function create_routes({ src, files = glob.sync('**/*.+(html|js|mjs)', { cwd: src }) }: {
src: string;
files?: string[];
}) {
export default function create_routes({ files } = { files: glob.sync('**/*.+(html|js|mjs)', { cwd: src() }) }) {
const routes: Route[] = files
.map((file: string) => {
if (/(^|\/|\\)_/.test(file)) return;

View File

@@ -5,10 +5,9 @@ import create_routes from './create_routes';
import { fudge_mtime, posixify, write } from './utils';
import { Route } from '../interfaces';
export default function create_serviceworker({ routes, client_files, src }: {
export default function create_serviceworker({ routes, client_files }: {
routes: Route[];
client_files: string[];
src: string;
}) {
const assets = glob.sync('**', { cwd: 'assets', nodir: true });

View File

@@ -7,14 +7,12 @@ import rimraf from 'rimraf';
import serialize from 'serialize-javascript';
import escape_html from 'escape-html';
import { create_routes, templates, create_compilers, create_template } from 'sapper/core.js';
import { dest, entry, isDev, src } from '../config';
import { dest } from '../config';
import { Route, Template } from '../interfaces';
import sourceMapSupport from 'source-map-support';
sourceMapSupport.install();
const dev = isDev();
type RouteObject = {
id: string;
type: 'page' | 'route';
@@ -43,12 +41,14 @@ interface Req extends ClientRequest {
export default function middleware({ routes }: {
routes: RouteObject[]
}) {
const client_info = JSON.parse(fs.readFileSync(path.join(dest, 'client_info.json'), 'utf-8'));
const output = dest();
const client_info = JSON.parse(fs.readFileSync(path.join(output, 'client_info.json'), 'utf-8'));
const template = create_template();
const shell = try_read(path.join(dest, 'index.html'));
const serviceworker = try_read(path.join(dest, 'service-worker.js'));
const shell = try_read(path.join(output, 'index.html'));
const serviceworker = try_read(path.join(output, 'service-worker.js'));
const middleware = compose_handlers([
(req: Req, res: ServerResponse, next: () => void) => {
@@ -76,7 +76,7 @@ export default function middleware({ routes }: {
const type = 'application/javascript'; // TODO might not be, if using e.g. CSS plugin
// TODO cache?
const rs = fs.createReadStream(path.join(dest, req.pathname.slice(1)));
const rs = fs.createReadStream(path.join(output, req.pathname.slice(1)));
rs.on('error', error => {
res.statusCode = 404;

View File

@@ -1,7 +1,7 @@
import { dest, isDev, entry } from '../config';
import { dest, dev } from '../config';
export default {
dev: isDev(),
dev: dev(),
client: {
entry: () => {
@@ -17,7 +17,7 @@ export default {
output: () => {
return {
path: `${dest}/client`,
path: `${dest()}/client`,
filename: '[hash]/[name].js',
chunkFilename: '[hash]/[name].[id].js',
publicPath: '/client/'
@@ -34,7 +34,7 @@ export default {
output: () => {
return {
path: `${dest}`,
path: `${dest()}`,
filename: '[name].js',
chunkFilename: '[hash]/[name].[id].js',
libraryTarget: 'commonjs2'