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

Commit

Permalink
Merge pull request #158 from sveltejs/logging
Browse files Browse the repository at this point in the history
vastly better logging
  • Loading branch information
Rich-Harris authored Mar 4, 2018
2 parents 0165c14 + 368e6d5 commit e91955f
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 78 deletions.
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"mkdirp": "^0.5.1",
"mri": "^1.1.0",
"node-fetch": "^1.7.3",
"pretty-ms": "^3.1.0",
"relative": "^3.0.2",
"require-relative": "^0.8.7",
"rimraf": "^2.6.2",
Expand All @@ -39,7 +40,8 @@
"source-map-support": "^0.5.3",
"tslib": "^1.8.1",
"url-parse": "^1.2.0",
"walk-sync": "^0.3.2"
"walk-sync": "^0.3.2",
"webpack-format-messages": "^1.0.1"
},
"devDependencies": {
"@std/esm": "^0.19.7",
Expand All @@ -55,6 +57,7 @@
"nightmare": "^2.10.0",
"npm-run-all": "^4.1.2",
"rollup": "^0.53.0",
"rollup-plugin-commonjs": "^8.3.0",
"rollup-plugin-json": "^2.3.0",
"rollup-plugin-string": "^2.0.2",
"rollup-plugin-typescript": "^0.8.1",
Expand Down
2 changes: 2 additions & 0 deletions rollup.config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import typescript from 'rollup-plugin-typescript';
import string from 'rollup-plugin-string';
import json from 'rollup-plugin-json';
import commonjs from 'rollup-plugin-commonjs';
import pkg from './package.json';

const external = [].concat(
Expand All @@ -18,6 +19,7 @@ const plugins = [
include: '**/*.md'
}),
json(),
commonjs(),
typescript({
typescript: require('typescript')
})
Expand Down
206 changes: 130 additions & 76 deletions src/cli/dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import * as child_process from 'child_process';
import * as http from 'http';
import mkdirp from 'mkdirp';
import rimraf from 'rimraf';
import format_messages from 'webpack-format-messages';
import prettyMs from 'pretty-ms';
import { wait_for_port } from './utils';
import { dest } from '../config';
import { create_compilers, create_app, create_routes, create_serviceworker } from 'sapper/core.js';
Expand Down Expand Up @@ -69,13 +71,12 @@ function create_hot_update_server(port: number, interval = 10000) {
}

export default async function dev() {
const dir = dest();
process.env.NODE_ENV = 'development';

const dir = dest();
rimraf.sync(dir);
mkdirp.sync(dir);

const chokidar = require('chokidar');

// initial build
const dev_port = await require('get-port')(10000);

Expand All @@ -84,20 +85,6 @@ export default async function dev() {

const hot_update_server = create_hot_update_server(dev_port);

// TODO watch the configs themselves?
const compilers = create_compilers();

function watch_files(pattern: string, events: string[], callback: () => void) {
const watcher = chokidar.watch(pattern, {
persistent: true,
ignoreInitial: true
});

events.forEach(event => {
watcher.on(event, callback);
});
}

watch_files('routes/**/*', ['add', 'unlink'], () => {
const routes = create_routes();
create_app({ routes, dev_port });
Expand All @@ -116,31 +103,106 @@ export default async function dev() {
client: deferred()
};

const times = {
client_start: Date.now(),
server_start: Date.now(),
serviceworker_start: Date.now()
let restarting = false;
let build = {
unique_warnings: new Set(),
unique_errors: new Set()
};

compilers.server.plugin('invalid', () => {
times.server_start = Date.now();
// TODO print message
deferreds.server = deferred();
});
function restart_build(filename) {
if (restarting) return;

compilers.server.watch({}, (err: Error, stats: any) => {
if (err) {
console.error(chalk.red(err.message));
} else if (stats.hasErrors()) {
// print errors. TODO notify client
stats.toJson().errors.forEach((error: Error) => {
console.error(error); // TODO make this look nice
});
} else {
console.log(`built server in ${Date.now() - times.server_start}ms`); // TODO prettify
restarting = true;
build = {
unique_warnings: new Set(),
unique_errors: new Set()
};

process.nextTick(() => {
restarting = false;
});

console.log(`\n${chalk.bold.cyan(path.relative(process.cwd(), filename))} changed. rebuilding...`);
}

// TODO watch the configs themselves?
const compilers = create_compilers();

function watch(compiler: any, { name, invalid = noop, error = noop, result }: {
name: string,
invalid?: (filename: string) => void;
error?: (error: Error) => void;
result: (stats: any) => void;
}) {
compiler.plugin('invalid', (filename: string) => {
invalid(filename);
});

compiler.watch({}, (err: Error, stats: any) => {
if (err) {
console.error(chalk.red(`✗ ${name}`));
console.error(chalk.red(err.message));
error(err);
} else {
const messages = format_messages(stats);
const info = stats.toJson();

if (messages.errors.length > 0) {
console.log(chalk.bold.red(`✗ ${name}`));

const server_info = stats.toJson();
fs.writeFileSync(path.join(dir, 'server_info.json'), JSON.stringify(server_info, null, ' '));
const filtered = messages.errors.filter((message: string) => {
return !build.unique_errors.has(message);
});

filtered.forEach((message: string) => {
build.unique_errors.add(message);
console.log(message);
});

const hidden = messages.errors.length - filtered.length;
if (hidden > 0) {
console.log(`${hidden} duplicate ${hidden === 1 ? 'error' : 'errors'} hidden\n`);
}
} else {
if (messages.warnings.length > 0) {
console.log(chalk.bold.yellow(`• ${name}`));

const filtered = messages.warnings.filter((message: string) => {
return !build.unique_warnings.has(message);
});

filtered.forEach((message: string) => {
build.unique_warnings.add(message);
console.log(`${message}\n`);
});

const hidden = messages.warnings.length - filtered.length;
if (hidden > 0) {
console.log(`${hidden} duplicate ${hidden === 1 ? 'warning' : 'warnings'} hidden\n`);
}
} else {
console.log(`${chalk.bold.green(`✔ ${name}`)} ${chalk.grey(`(${prettyMs(info.time)})`)}`);
}

result(info);
}
}
});
}

watch(compilers.server, {
name: 'server',

invalid: filename => {
restart_build(filename);
// TODO print message
deferreds.server = deferred();
},

result: info => {
// TODO log compile errors/warnings

fs.writeFileSync(path.join(dir, 'server_info.json'), JSON.stringify(info, null, ' '));

deferreds.client.promise.then(() => {
function restart() {
Expand All @@ -162,32 +224,23 @@ export default async function dev() {
}
});

compilers.client.plugin('invalid', (filename: string) => {
times.client_start = Date.now();
watch(compilers.client, {
name: 'client',

deferreds.client = deferred();
invalid: filename => {
restart_build(filename);
deferreds.client = deferred();

// TODO we should delete old assets. due to a webpack bug
// i don't even begin to comprehend, this is apparently
// quite difficult
});
// TODO we should delete old assets. due to a webpack bug
// i don't even begin to comprehend, this is apparently
// quite difficult
},

compilers.client.watch({}, (err: Error, stats: any) => {
if (err) {
console.error(chalk.red(err.message));
} else if (stats.hasErrors()) {
// print errors. TODO notify client
stats.toJson().errors.forEach((error: Error) => {
console.error(error); // TODO make this look nice
});
} else {
console.log(`built client in ${Date.now() - times.client_start}ms`); // TODO prettify

const client_info = stats.toJson();
fs.writeFileSync(path.join(dir, 'client_info.json'), JSON.stringify(client_info, null, ' '));
result: info => {
fs.writeFileSync(path.join(dir, 'client_info.json'), JSON.stringify(info, null, ' '));
deferreds.client.fulfil();

const client_files = client_info.assets.map((chunk: { name: string }) => `/client/${chunk.name}`);
const client_files = info.assets.map((chunk: { name: string }) => `/client/${chunk.name}`);

deferreds.server.promise.then(() => {
hot_update_server.send({
Expand All @@ -208,27 +261,28 @@ export default async function dev() {
? function() {
watch_serviceworker = noop;

compilers.serviceworker.plugin('invalid', (filename: string) => {
times.serviceworker_start = Date.now();
});

compilers.serviceworker.watch({}, (err: Error, stats: any) => {
if (err) {
// TODO notify client
} else if (stats.hasErrors()) {
// print errors. TODO notify client
stats.toJson().errors.forEach((error: Error) => {
console.error(error); // TODO make this look nice
});
} else {
console.log(`built service worker in ${Date.now() - times.serviceworker_start}ms`); // TODO prettify
watch(compilers.serviceworker, {
name: 'service worker',

const serviceworker_info = stats.toJson();
fs.writeFileSync(path.join(dir, 'serviceworker_info.json'), JSON.stringify(serviceworker_info, null, ' '));
result: info => {
fs.writeFileSync(path.join(dir, 'serviceworker_info.json'), JSON.stringify(info, null, ' '));
}
});
}
: noop;
}

function noop() {}
function noop() {}

function watch_files(pattern: string, events: string[], callback: () => void) {
const chokidar = require('chokidar');

const watcher = chokidar.watch(pattern, {
persistent: true,
ignoreInitial: true
});

events.forEach(event => {
watcher.on(event, callback);
});
}
2 changes: 1 addition & 1 deletion test/common/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ Nightmare.action('init', function(done) {

function run(env) {
describe(`env=${env}`, function () {
this.timeout(20000);
this.timeout(30000);

let PORT;
let proc;
Expand Down

0 comments on commit e91955f

Please sign in to comment.