Skip to content

Commit

Permalink
Dev server improvements (#762)
Browse files Browse the repository at this point in the history
* Improve dev server output

* fred attempt

* fix bad spacing on http url line of header

* add proxy message

* add build watch message similar to dev

* updates

Co-authored-by: Fred K. Schott <fkschott@gmail.com>
  • Loading branch information
drwpow and FredKSchott authored Aug 13, 2020
1 parent 8e1c815 commit 610fb9d
Show file tree
Hide file tree
Showing 14 changed files with 229 additions and 400 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"@types/jest": "^26.0.4",
"jest": "^26.2.2",
"snowpack": "^2.7.7",
"svelte-check": "^0.1.59",
"svelte-check": "^1.0.0",
"svelte-preprocess": "^4.0.8",
"typescript": "^3.9.7"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"watch": "$1 --watch"
}
],
["@snowpack/plugin-run-script", {"cmd": "svelte-check"}]
["@snowpack/plugin-run-script", {"cmd": "svelte-check --output human", "watch": "$1 --watch", "output": "stream"}]
],
"installOptions": {
"installTypes": true
Expand Down
2 changes: 1 addition & 1 deletion packages/@snowpack/app-template-svelte/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"@testing-library/svelte": "^3.0.0",
"jest": "^26.2.2",
"snowpack": "^2.7.7",
"svelte-check": "^0.1.59"
"svelte-check": "^1.0.0"
},
"gitHead": "a01616bb0787d56cd782f94cecf2daa12c7594e4"
}
33 changes: 16 additions & 17 deletions packages/@snowpack/plugin-build-script/plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,25 @@ function buildScriptPlugin(_, {input, output, cmd}) {
input: input,
output: output,
},
async load({filePath, log}) {
async load({filePath}) {
const cmdWithFile = cmd.replace('$FILE', filePath);
const contents = await fs.readFile(filePath, 'utf-8');
try {
const {stdout, stderr} = await execa.command(cmdWithFile, {
env: npmRunPath.env(),
extendEnv: true,
shell: true,
input: contents,
cwd,
});
if (stderr) {
log('WORKER_MSG', {level: 'warn', msg: stderr});
}
return {[output[0]]: stdout};
} catch (err) {
log('WORKER_MSG', {level: 'error', msg: err.stderr});
log('WORKER_UPDATE', {state: ['ERROR', 'red']});
return null;
const {stdout, stderr, exitCode} = await execa.command(cmdWithFile, {
env: npmRunPath.env(),
extendEnv: true,
shell: true,
input: contents,
cwd,
});
// If the command failed, fail the plugin as well.
if (exitCode !== 0) {
throw new Error(stderr || stdout);
}
// If the plugin output tp stderr, how it to the user.
if (stderr) {
throw new Error(stderr);
}
return {[output[0]]: stdout};
},
};
}
Expand Down
9 changes: 5 additions & 4 deletions packages/@snowpack/plugin-run-script/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ Supply any CLI command in `cmd`. Note that this is the same as running the comma

## Plugin Options

| Name | Type | Description |
| :------ | :------: | :-------------------------------------------------------------------------- |
| `cmd` | `string` | The CLI command to run. Note that this will run **before** Snowpack builds. |
| `watch` | `string` | (optional) A watch command to run during the dev server. |
| Name | Type | Description |
| :------ | :------: | :---------------------------------------------------------------------------- |
| `cmd` | `string` | The CLI command to run. Note that this will run **before** Snowpack builds. |
| `watch` | `string` | (optional) A watch command to run during the dev server. |
| `output` | `"stream" | "dashboard"` | (optional) Set how the output should be recorded during dev. |
54 changes: 28 additions & 26 deletions packages/@snowpack/plugin-run-script/plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ const execa = require('execa');
const npmRunPath = require('npm-run-path');
const cwd = process.cwd();

function runScriptPlugin(_, {cmd, watch}) {
const cmdProgram = cmd.split(' ')[0];
function runScriptPlugin(_, {cmd, watch, output}) {
const [cmdProgram] = cmd.split(' ');
const watchCmd = watch && watch.replace('$1', cmd);

return {
name: `run:${cmdProgram}`,
name: cmdProgram,
async run({isDev, log}) {
const workerPromise = execa.command(isDev ? watchCmd || cmd : cmd, {
env: npmRunPath.env(),
Expand All @@ -16,33 +16,35 @@ function runScriptPlugin(_, {cmd, watch}) {
cwd,
});
const {stdout, stderr} = workerPromise;
stdout &&
stdout.on('data', (b) => {
let stdOutput = b.toString();
if (stdOutput.includes('\u001bc') || stdOutput.includes('\x1Bc')) {
log('WORKER_RESET', {});
function dataListener(chunk) {
let stdOutput = chunk.toString();
if (output === 'stream') {
log('CONSOLE_INFO', {id: cmdProgram, msg: stdOutput});
return;
}
if (stdOutput.includes('\u001bc') || stdOutput.includes('\x1Bc')) {
log('WORKER_RESET', {});
log('WORKER_UPDATE', {state: ['RUNNING', 'yellow']});
stdOutput = stdOutput.replace(/\x1Bc/, '').replace(/\u001bc/, '');
}
if (cmdProgram === 'tsc') {
if (/Watching for file changes./gm.test(stdOutput)) {
log('WORKER_UPDATE', {state: ['RUNNING', 'yellow']});
stdOutput = stdOutput.replace(/\x1Bc/, '').replace(/\u001bc/, '');
}
if (cmdProgram === 'tsc') {
if (/Watching for file changes./gm.test(stdOutput)) {
log('WORKER_UPDATE', {state: ['RUNNING', 'yellow']});
}
const errorMatch = stdOutput.match(/Found (\d+) error/);
if (errorMatch) {
if (errorMatch[1] === '0') {
log('WORKER_UPDATE', {state: ['OK', 'green']});
} else {
log('WORKER_UPDATE', {state: ['ERROR', 'red']});
}
const errorMatch = stdOutput.match(/Found (\d+) error/);
if (errorMatch) {
if (errorMatch[1] === '0') {
log('WORKER_UPDATE', {state: ['OK', 'green']});
stdOutput = stdOutput.trim();
} else {
log('WORKER_UPDATE', {state: ['ERROR', 'red']});
}
}
log('WORKER_MSG', {level: 'log', msg: stdOutput});
});
stderr &&
stderr.on('data', (err) => {
log('WORKER_MSG', {level: 'error', msg: err.toString()});
});
}
log('WORKER_MSG', {level: 'log', msg: stdOutput});
}
stdout && stdout.on('data', dataListener);
stderr && stderr.on('data', dataListener);
return workerPromise;
},
};
Expand Down
31 changes: 30 additions & 1 deletion packages/@snowpack/plugin-vue/plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,34 @@ const path = require('path');
const hashsum = require('hash-sum');
const compiler = require('@vue/compiler-sfc');

/** Friendly error display */
function displayError({contents, filePath, error}) {
const pad = (number, pad) => `${Array.from(new Array(pad + 1)).join(' ')}${number}`;

let output = [`${error.toString()}`, `[${filePath}]`];
if (error.loc) {
output[1] += ` Line ${error.loc.start.line}, Column ${error.loc.start.column}`;
const lineNo = (number) =>
' ' +
pad(number, (error.loc.end.line + 1).toString().length - number.toString().length) +
' | ';
output.push('');
const allLines = ['', ...contents.split('\n')];
let currentLine = error.loc.start.line;
output.push(lineNo(currentLine - 1) + allLines[currentLine - 1]);
while (currentLine <= error.loc.end.line) {
output.push(lineNo(currentLine) + allLines[currentLine]);
currentLine++;
}
output.push(
Array.from(new Array(error.loc.start.column + lineNo(currentLine - 1).length)).join(' ') +
'^',
);
output.push(lineNo(currentLine) + allLines[currentLine]);
}
return output.join('\n');
}

module.exports = function plugin(snowpackConfig) {
return {
name: '@snowpack/plugin-vue',
Expand All @@ -17,8 +45,9 @@ module.exports = function plugin(snowpackConfig) {
const contents = fs.readFileSync(filePath, 'utf-8');
const {descriptor, errors} = compiler.parse(contents, {filename: filePath});

// display errors
if (errors && errors.length > 0) {
console.error(JSON.stringify(errors));
throw new Error(displayError({error: errors[0], contents, filePath}));
}

const output = {
Expand Down
35 changes: 16 additions & 19 deletions packages/snowpack/src/build/build-pipeline.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {EventEmitter} from 'events';
import {promises as fs} from 'fs';
import path from 'path';
import pino from 'pino';
Expand All @@ -10,11 +11,12 @@ const logger = createLogger({name: 'snowpack'});
const pluginLoggers: Record<string, pino.Logger> = {}; // save created loggers

export interface BuildFileOptions {
plugins: SnowpackPlugin[];
devMessageBus?: EventEmitter;
isDev: boolean;
isHmrEnabled: boolean;
sourceMaps: boolean;
logLevel?: pino.Level;
plugins: SnowpackPlugin[];
sourceMaps: boolean;
}

export function getInputsFromOutput(fileLoc: string, plugins: SnowpackPlugin[]) {
Expand Down Expand Up @@ -43,7 +45,7 @@ export function getInputsFromOutput(fileLoc: string, plugins: SnowpackPlugin[])
*/
async function runPipelineLoadStep(
srcPath: string,
{plugins, isDev, isHmrEnabled, logLevel = 'info', sourceMaps}: BuildFileOptions,
{devMessageBus, isDev, isHmrEnabled, logLevel = 'info', plugins, sourceMaps}: BuildFileOptions,
): Promise<SnowpackBuildMap> {
const srcExt = getExt(srcPath).baseExt;
for (const step of plugins) {
Expand All @@ -65,10 +67,6 @@ async function runPipelineLoadStep(
filePath: srcPath,
isDev,
isHmrEnabled,
// @ts-ignore: internal API only
log: (msg, data: any = {}) => {
if (data && data.msg) pluginLogger.info(`${data.msg} [${debugPath}]`);
},
});
pluginLogger.debug(`load() successful [${debugPath}]`);

Expand Down Expand Up @@ -96,11 +94,13 @@ async function runPipelineLoadStep(
if (!sourceMaps) result[ext].map = undefined;
});
return result;
} else {
continue;
}
} catch (err) {
pluginLogger.error(err);
if (devMessageBus && isDev) {
devMessageBus.emit('CONSOLE_ERROR', {id: step.name, msg: err.toString() || err});
} else {
pluginLogger.error(err);
}
}
}

Expand All @@ -121,7 +121,7 @@ async function runPipelineLoadStep(
async function runPipelineTransformStep(
output: SnowpackBuildMap,
srcPath: string,
{plugins, isDev, logLevel = 'info', sourceMaps}: BuildFileOptions,
{devMessageBus, isDev, logLevel = 'info', plugins, sourceMaps}: BuildFileOptions,
): Promise<SnowpackBuildMap> {
const srcExt = getExt(srcPath).baseExt;
const rootFileName = path.basename(srcPath).replace(srcExt, '');
Expand All @@ -146,28 +146,25 @@ async function runPipelineTransformStep(
fileExt: destExt,
filePath,
isDev,
// @ts-ignore: internal API only
log: (msg, data: any = {}) => {
if (data && data.msg)
pluginLogger.info(`${data.msg} [${path.relative(process.cwd(), filePath)}]`);
},
// @ts-ignore: Deprecated
urlPath: `./${path.basename(rootFileName + destExt)}`,
});
pluginLogger.debug(`transform() successful [${debugPath}]`);

// if step returned a value, only update code (don’t touch .map)
if (typeof result === 'string') {
output[destExt].code = result;
} else if (result && typeof result === 'object' && (result as {result: string}).result) {
output[destExt].code = (result as {result: string}).result;
}

// if source maps disabled, don’t return any
if (!sourceMaps) output[destExt].map = undefined;
}
} catch (err) {
pluginLogger.error(err);
if (devMessageBus && isDev) {
devMessageBus.emit('CONSOLE_ERROR', {id: step.name, msg: err.toString() || err});
} else {
pluginLogger.error(err);
}
}
}

Expand Down
2 changes: 2 additions & 0 deletions packages/snowpack/src/commands/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -406,12 +406,14 @@ export async function command(commandOptions: CommandOptions) {

// "--watch" mode - Start watching the file system.
// Defer "chokidar" loading to here, to reduce impact on overall startup time
logger.info(colors.cyan('Watching for changes...'));
const chokidar = await import('chokidar');

function onDeleteEvent(fileLoc: string) {
delete buildPipelineFiles[fileLoc];
}
async function onWatchEvent(fileLoc: string) {
logger.info(colors.cyan('File changed...'));
const [fromDisk, dirDest] =
mountedDirectories.find(([fromDisk]) => fileLoc.startsWith(fromDisk)) || [];
if (!fromDisk || !dirDest) {
Expand Down
Loading

1 comment on commit 610fb9d

@vercel
Copy link

@vercel vercel bot commented on 610fb9d Aug 13, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.