From b73e5eaa8eb33311d6964563680f4c16fef7aa22 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Sat, 3 Mar 2018 12:09:06 -0500 Subject: [PATCH 1/2] sapper build defaults to build dir, sapper export defaults to export dir (#133) --- .gitignore | 4 +++- src/cli/build.ts | 20 +++++++++----------- src/cli/dev.ts | 18 ++++++++++-------- src/cli/export.ts | 28 ++++++++++++++++------------ src/cli/index.ts | 12 +++++++----- src/config.ts | 13 +++---------- src/core/create_app.ts | 17 ++++++++--------- src/core/create_routes.ts | 6 ++---- src/core/create_serviceworker.ts | 3 +-- src/middleware/index.ts | 14 +++++++------- src/webpack/index.ts | 8 ++++---- 11 files changed, 70 insertions(+), 73 deletions(-) diff --git a/.gitignore b/.gitignore index f589ba679..2a97c41f4 100644 --- a/.gitignore +++ b/.gitignore @@ -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 \ No newline at end of file +webpack/config.js.map +yarn-error.log \ No newline at end of file diff --git a/src/cli/build.ts b/src/cli/build.ts index fb1f77edb..5d0f4642c 100644 --- a/src/cli/build.ts +++ b/src/cli/build.ts @@ -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); diff --git a/src/cli/dev.ts b/src/cli/dev.ts index 92857da77..4fe6ea6fb 100644 --- a/src/cli/dev.ts +++ b/src/cli/dev.ts @@ -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(); diff --git a/src/cli/export.ts b/src/cli/export.ts index 50960bc39..802c8b288 100644 --- a/src/cli/export.ts +++ b/src/cli/export.ts @@ -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' +export default async function exporter(export_dir: string) { + const build_dir = dest(); + // Prep output directory - sander.rimrafSync(OUTPUT_DIR); + sander.rimrafSync(export_dir); - 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'); + 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); } }); diff --git a/src/cli/index.ts b/src/cli/index.ts index f53523f1f..dc8c51f35 100755 --- a/src/cli/index.ts +++ b/src/cli/index.ts @@ -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 { diff --git a/src/config.ts b/src/config.ts index 310f7f054..db59d02db 100644 --- a/src/config.ts +++ b/src/config.ts @@ -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'); diff --git a/src/core/create_app.ts b/src/core/create_app.ts index fdab1f935..38a02d19c 100644 --- a/src/core/create_app.ts +++ b/src/core/create_app.ts @@ -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} }`; diff --git a/src/core/create_routes.ts b/src/core/create_routes.ts index aa1a93485..26d534235 100644 --- a/src/core/create_routes.ts +++ b/src/core/create_routes.ts @@ -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; diff --git a/src/core/create_serviceworker.ts b/src/core/create_serviceworker.ts index 8f6168db1..6aeb5c8c3 100644 --- a/src/core/create_serviceworker.ts +++ b/src/core/create_serviceworker.ts @@ -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 }); diff --git a/src/middleware/index.ts b/src/middleware/index.ts index bc5ff66be..5d44c1ae5 100644 --- a/src/middleware/index.ts +++ b/src/middleware/index.ts @@ -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; diff --git a/src/webpack/index.ts b/src/webpack/index.ts index 6725a501b..773deadde 100644 --- a/src/webpack/index.ts +++ b/src/webpack/index.ts @@ -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' From 17d7ca36f15c455db4b58343087b89a843a29c29 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Sat, 3 Mar 2018 12:20:46 -0500 Subject: [PATCH 2/2] update test --- test/common/test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/common/test.js b/test/common/test.js index 297c8d5b5..4c86aed79 100644 --- a/test/common/test.js +++ b/test/common/test.js @@ -422,7 +422,7 @@ function run(env) { if (env === 'production') { describe('export', () => { it('export all pages', () => { - const dest = path.resolve(__dirname, '../app/dist'); + const dest = path.resolve(__dirname, '../app/export'); // Pages that should show up in the extraction directory. const expectedPages = [