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

export should fail on timeouts #378

Merged
merged 1 commit into from
Aug 25, 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
57 changes: 36 additions & 21 deletions src/api/export.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,14 @@ import minify_html from './utils/minify_html';
import Deferred from './utils/Deferred';
import * as events from './interfaces';

export function exporter(opts: {}) {
type Opts = {
build: string,
dest: string,
basepath: string,
timeout: number | false
};

export function exporter(opts: Opts) {
const emitter = new EventEmitter();

execute(emitter, opts).then(
Expand All @@ -27,42 +34,38 @@ export function exporter(opts: {}) {
return emitter;
}

async function execute(emitter: EventEmitter, {
build = 'build',
dest = 'export',
basepath = ''
} = {}) {
const export_dir = path.join(dest, basepath);
async function execute(emitter: EventEmitter, opts: Opts) {
const export_dir = path.join(opts.dest, opts.basepath);

// Prep output directory
sander.rimrafSync(export_dir);

sander.copydirSync('assets').to(export_dir);
sander.copydirSync(build, 'client').to(export_dir, 'client');
sander.copydirSync(opts.build, 'client').to(export_dir, 'client');

if (sander.existsSync(build, 'service-worker.js')) {
sander.copyFileSync(build, 'service-worker.js').to(export_dir, 'service-worker.js');
if (sander.existsSync(opts.build, 'service-worker.js')) {
sander.copyFileSync(opts.build, 'service-worker.js').to(export_dir, 'service-worker.js');
}

if (sander.existsSync(build, 'service-worker.js.map')) {
sander.copyFileSync(build, 'service-worker.js.map').to(export_dir, 'service-worker.js.map');
if (sander.existsSync(opts.build, 'service-worker.js.map')) {
sander.copyFileSync(opts.build, 'service-worker.js.map').to(export_dir, 'service-worker.js.map');
}

const port = await ports.find(3000);

const origin = `http://localhost:${port}`;
const root = new URL(basepath || '', origin);
const root = new URL(opts.basepath || '', origin);

emitter.emit('info', {
message: `Crawling ${root.href}`
});

const proc = child_process.fork(path.resolve(`${build}/server.js`), [], {
const proc = child_process.fork(path.resolve(`${opts.build}/server.js`), [], {
cwd: process.cwd(),
env: Object.assign({
PORT: port,
NODE_ENV: 'production',
SAPPER_DEST: build,
SAPPER_DEST: opts.build,
SAPPER_EXPORT: 'true'
}, process.env)
});
Expand Down Expand Up @@ -117,7 +120,18 @@ async function execute(emitter: EventEmitter, {

const deferred = get_deferred(pathname);

const r = await fetch(url.href);
const timeout_deferred = new Deferred();
const timeout = setTimeout(() => {
timeout_deferred.reject(new Error(`Timed out waiting for ${url.href}`));
}, opts.timeout);

const r = await Promise.race([
fetch(url.href),
timeout_deferred.promise
]);

clearTimeout(timeout); // prevent it hanging at the end

const range = ~~(r.status / 100);

if (range === 2) {
Expand Down Expand Up @@ -152,11 +166,12 @@ async function execute(emitter: EventEmitter, {
}

return ports.wait(port)
.then(() => {
// TODO all static routes
return handle(root);
})
.then(() => proc.kill());
.then(() => handle(root))
.then(() => proc.kill())
.catch(err => {
proc.kill();
throw err;
});
}

function get_href(attrs: string) {
Expand Down
10 changes: 8 additions & 2 deletions src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,13 @@ prog.command('export [dest]')
.option('--build', '(Re)build app before exporting', true)
.option('--build-dir', 'Specify a custom temporary build directory', '.sapper/prod')
.option('--basepath', 'Specify a base path')
.action(async (dest = 'export', opts: { build: boolean, 'build-dir': string, basepath?: string }) => {
.option('--timeout', 'Milliseconds to wait for a page (--no-timeout to disable)', 5000)
.action(async (dest = 'export', opts: {
build: boolean,
'build-dir': string,
basepath?: string,
timeout: number | false
}) => {
process.env.NODE_ENV = 'production';
process.env.SAPPER_DEST = opts['build-dir'];

Expand All @@ -83,7 +89,7 @@ prog.command('export [dest]')
await exporter(dest, opts);
console.error(`\n> Finished in ${elapsed(start)}. Type ${colors.bold.cyan(`npx serve ${dest}`)} to run the app.`);
} catch (err) {
console.error(err ? err.details || err.stack || err.message || err : 'Unknown error');
console.error(colors.bold.red(`> ${err.message}`));
process.exit(1);
}
});
Expand Down
11 changes: 9 additions & 2 deletions src/cli/export.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,20 @@ function left_pad(str: string, len: number) {
return str;
}

export function exporter(export_dir: string, { basepath = '' }) {
export function exporter(export_dir: string, {
basepath = '',
timeout
}: {
basepath: string,
timeout: number | false
}) {
return new Promise((fulfil, reject) => {
try {
const emitter = _exporter({
build: locations.dest(),
dest: export_dir,
basepath
basepath,
timeout
});

emitter.on('file', event => {
Expand Down