Browse Source

Pull webpack actions out of Neutrino class.

v6-dev
Jarid Margolin 8 years ago
parent
commit
d71fee588d
  1. 74
      docs/api/README.md
  2. 106
      packages/neutrino/src/neutrino.js
  3. 10
      packages/neutrino/src/webpack/build.js
  4. 28
      packages/neutrino/src/webpack/develop.js
  5. 22
      packages/neutrino/src/webpack/utils.js
  6. 15
      packages/neutrino/src/webpack/watch.js

74
docs/api/README.md

@ -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'
})
@ -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'
})
@ -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'
})
@ -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'
})
@ -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'
})
@ -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'
})
@ -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
packages/neutrino/src/neutrino.js

@ -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();
@ -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();
}
@ -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',
@ -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
packages/neutrino/src/webpack/build.js

@ -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
packages/neutrino/src/webpack/develop.js

@ -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
packages/neutrino/src/webpack/utils.js

@ -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
packages/neutrino/src/webpack/watch.js

@ -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));
});
Loading…
Cancel
Save