Skip to content
This repository has been archived by the owner on Feb 18, 2024. It is now read-only.

Commit

Permalink
Pull webpack actions out of Neutrino class.
Browse files Browse the repository at this point in the history
  • Loading branch information
jaridmargolin committed Mar 20, 2017
1 parent 09d78db commit d71fee5
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 159 deletions.
74 changes: 12 additions & 62 deletions docs/api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@ path is specified, it will be resolved relative to `process.cwd()`; absolute pat
```js
new Neutrino({
// if not specified, defaults to process.cwd()

// relative, resolves to process.cwd() + ./website
root: './website',

// absolute
root: '/code/website'
})
Expand All @@ -55,10 +55,10 @@ If a relative path is specified, it will be resolved relative to `options.root`;
```js
new Neutrino({
// if not specified, defaults to options.root + src

// relative, resolves to options.root + ./lib
source: './lib',

// absolute
source: '/code/website/lib'
})
Expand All @@ -72,10 +72,10 @@ If a relative path is specified, it will be resolved relative to `options.root`;
```js
new Neutrino({
// if not specified, defaults to options.root + build

// relative, resolves to options.root + ./dist
output: './dist',

// absolute
output: '/code/website/dist'
})
Expand All @@ -89,10 +89,10 @@ If a relative path is specified, it will be resolved relative to `options.root`;
```js
new Neutrino({
// if not specified, defaults to options.root + test

// relative, resolves to options.root + ./testing
tests: './testing',

// absolute
tests: '/code/website/testing'
})
Expand All @@ -106,10 +106,10 @@ If a relative path is specified, it will be resolved relative to `options.source
```js
new Neutrino({
// if not specified, defaults to options.source + index.js

// relative, resolves to options.source + ./entry.js
entry: './entry.js',

// absolute
entry: '/code/website/lib/entry.js'
})
Expand All @@ -124,10 +124,10 @@ used as-is.
```js
new Neutrino({
// if not specified, defaults to options.root + node_modules

// relative, resolves to options.root + ./modules
node_modules: './modules',

// absolute
node_modules: '/code/website/modules'
})
Expand Down Expand Up @@ -325,53 +325,3 @@ neutrino.on('custom-event', (args, payload) => {
});

```

### `handleErrors(err, stats)`

This method is used internally to create a consistent console output when errors occur in the build. It will
log the `err` property and any errors from `stats` if applicable, and return `true` or `false` depending on if there
_were_ errors.

This method returns a Boolean.

```js
const failed = api.handleErrors(err, stats);

if (failed) {
console.log('The build failed!');
}
```

### `devServer()`

This method is used internally to generate an instance of webpack-dev-server when using `start()`. It returns a promise
that resolves when the process receives a `SIGINT` event to stop.

```js
api
.devServer()
.then(() => console.log('Exiting process...'));
```

### `builder()`

This method is used internally to generate an instance of a Webpack compiler when using `build()`. It returns a promise
that resolves when the Webpack build has completed, or rejects if the build fails.

```js
api
.builder()
.then(() => console.log('Exiting process...'))
.catch(() => console.error('Build failed!'));
```

### `watcher()`

This method is used internally to generate an instance of a Webpack source watcher when using `start()`. It returns a promise
that resolves when the process receives a `SIGINT` event to stop and the watcher has closed.

```js
api
.watcher()
.then(() => console.log('Exiting process, done watching...'));
```
106 changes: 9 additions & 97 deletions packages/neutrino/src/neutrino.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
const { join, isAbsolute } = require('path');
const { EventEmitter } = require('events');
const DevServer = require('webpack-dev-server');
const webpack = require('webpack');
const Config = require('webpack-chain');
const ora = require('ora');
const merge = require('deepmerge');
const { defaultTo } = require('ramda');
const { defaultTo, identity } = require('ramda');
const requireMiddleware = require('./requireMiddleware');
const build = require('./webpack/build');
const develop = require('./webpack/develop');
const watch = require('./webpack/watch');

const normalizePath = (path, root) => (isAbsolute(path) ? path : join(root, path));

class Neutrino extends EventEmitter {
module.exports = class Neutrino extends EventEmitter {
constructor(options = {}) {
super();

Expand All @@ -37,27 +37,6 @@ class Neutrino extends EventEmitter {
return requireMiddleware(middleware, this.options);
}

handleErrors(err, stats) {
if (err) {
console.error(err.stack || err);

if (err.details) {
console.error(err.details);
}

return true;
}

const jsonStats = stats.toJson();

if (jsonStats.errors.length) {
jsonStats.errors.map(err => console.error(err));
return true;
}

return false;
}

getWebpackConfig() {
return this.config.toConfig();
}
Expand All @@ -67,18 +46,18 @@ class Neutrino extends EventEmitter {
}

build(args) {
return this.runCommand('build', args, () => this.builder());
return this.runCommand('build', args, build);
}

start(args) {
return this.runCommand('start', args, () => (this.getWebpackOptions().devServer ? this.devServer() : this.watcher()));
return this.runCommand('start', args, this.getWebpackConfig().devServer ? develop : watch);
}

test(args) {
return this.runCommand('test', args);
}

runCommand(command, args = {}, fn) {
runCommand(command, args = {}, fn = identity) {
process.env.NODE_ENV = defaultTo({
build: 'production',
start: 'development',
Expand All @@ -87,74 +66,7 @@ class Neutrino extends EventEmitter {

return this
.emitForAll(`pre${command}`, args)
.then(fn)
.then(() => fn(this.getWebpackConfig()))
.then(() => this.emitForAll(command, args));
}

devServer() {
return new Promise((resolve) => {
const starting = ora('Starting development server').start();
const config = this.getWebpackOptions();
const protocol = config.devServer.https ? 'https' : 'http';
const host = config.devServer.host || 'localhost';
const port = config.devServer.port || 5000;

config.devServer.noInfo = true;

const compiler = webpack(config);
const server = new DevServer(compiler, config.devServer);
const building = ora('Waiting for initial build to finish').start();

process.on('SIGINT', resolve);
server.listen(port, host, () => {
starting.succeed(`Development server running on: ${protocol}://${host}:${port}`);
compiler.plugin('compile', () => {
building.text = 'Source changed, re-compiling';
building.start();
});
compiler.plugin('done', () => building.succeed('Build completed'));
});
});
}

watcher() {
return new Promise((resolve) => {
const building = ora('Waiting for initial build to finish').start();
const config = this.getWebpackOptions();
const compiler = webpack(config);
const watcher = compiler.watch(config.watchOptions || {}, (err, stats) => {
building.succeed('Build completed');
this.handleErrors(err, stats);
});

process.on('SIGINT', () => watcher.close(resolve));
});
}

builder() {
return new Promise((resolve, reject) => {
const config = this.getWebpackOptions();
const compiler = webpack(config);

// eslint-disable-next-line consistent-return
compiler.run((err, stats) => {
const failed = this.handleErrors(err, stats);

if (failed) {
return reject();
}

// eslint-disable-next-line no-console
console.log(stats.toString({
colors: true,
chunks: false,
children: false
}));

resolve();
});
});
}
}

module.exports = Neutrino;
10 changes: 10 additions & 0 deletions packages/neutrino/src/webpack/build.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
const webpack = require('webpack');
const { handle, logErrors, logStats } = require('./utils');

module.exports = config => new Promise((resolve, reject) => {
const compiler = webpack(config);

compiler.run(handle((errors, stats) => (
errors.length ? reject(logErrors(errors)) : resolve(logStats(stats))
)));
});
28 changes: 28 additions & 0 deletions packages/neutrino/src/webpack/develop.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
const ora = require('ora');
const merge = require('deepmerge');
const webpack = require('webpack');
const DevServer = require('webpack-dev-server');

module.exports = _config => new Promise((resolve) => {
const defaultDevServer = { host: 'localhost', port: 5000, noInfo: true };
const config = merge({ deverServer: defaultDevServer }, _config);
const protocol = config.devServer.https ? 'https' : 'http';
const { host, port } = config.devServer;

const starting = ora('Starting development server').start();
const compiler = webpack(config);
const server = new DevServer(compiler, config.devServer);
const building = ora('Waiting for initial build to finish').start();

server.listen(port, host, () => {
starting.succeed(`Development server running on: ${protocol}://${host}:${port}`);

compiler.plugin('done', () => building.succeed('Build completed'));
compiler.plugin('compile', () => {
building.text = 'Source changed, re-compiling';
building.start();
});
});

process.on('SIGINT', resolve);
});
22 changes: 22 additions & 0 deletions packages/neutrino/src/webpack/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
module.exports.handle = fn => (err, stats) => fn(err ? [err] : stats.toJson().errors, stats);

module.exports.logStats = (stats) => {
console.log(stats.toString({
colors: true,
chunks: false,
children: false
}));

return stats;
};

module.exports.logErrors = (errors) => {
errors.forEach((err) => {
console.error(err.stack || err);
if (err.details) {
console.error(err.details);
}
});

return errors;
};
15 changes: 15 additions & 0 deletions packages/neutrino/src/webpack/watch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const webpack = require('webpack');
const ora = require('ora');
const { handle, logErrors } = require('./utils');

module.exports = config => new Promise((resolve) => {
const compiler = webpack(config);
const building = ora('Waiting for initial build to finish').start();

const watcher = compiler.watch(config.watchOptions || {}, handle((errors) => {
building.succeed('Build completed');
logErrors(errors);
}));

process.on('SIGINT', () => watcher.close(resolve));
});

0 comments on commit d71fee5

Please sign in to comment.