Configuration.md
July 6, 2016 · View on GitHub
Configuration
What's Configurable?
- Babel 5 settings
- Webpack settings
- Default sets of loaders and plugins are provided and made configurable
- Additional CSS preprocessors can be added as nwb plugins
- Extra config can be deep-merged into the generated Webpack config
- Karma settings
- Additional plugins, frameworks and reporters can be configured
- Extra config can be deep-merged into the generated Webpack config
- Project layout
- Entry point for apps and UMD builds [default:
src/index.js] - Directory apps are built to [default:
dist/] - HTML template for apps [default:
src/index.html], falling back to a default template if none is provided.
- Entry point for apps and UMD builds [default:
Not Configurable... Yet
- Project layout
- Source is assumed to be under
src/ - Static resources for apps are assumed to be in
public/ - The entry point for React component demo apps is assumed to be
demo/src/index.js, with built resources indemo/dist/
- Source is assumed to be under
Configuration File
nwb will look for an nwb.config.js file in the current working directory for project-specific configuration, or you can specify a configuration file using the --config option.
This file should export either a configuration object or a function which creates a configuration object when called. If a function is exported, it will be passed an object containing the following properties:
command: the name of the nwb command currently being executed.webpack: nwb's version of thewebpackmodule.
The configuration object created by your nwb config can use the following fields:
- nwb Configuration
- Babel Configuration
- Webpack Configuration
- Karma Configuration
- npm Build Configuration
build- UMD build config
build.jsNext
type: String (required for generic build commands)
nwb uses this field to determine which type of project it's working with when generic build commands like build are used.
It must be one of:
'react-app''react-component''web-app''web-module'
Babel Configuration
babel: Object
Use this object to provide your own options for Babel (version 5) - see the Babel 5 options documentation.
e.g. to use async/await transforms, you will need to configure Babel's stage and optional settings:
module.exports = {
babel: {
stage: 0,
optional: ['runtime']
}
}
nwb commands are run in the current working directory, so if you need to configure additional Babel plugins, you can just use their names and let Babel import them.
e.g. to install and use the babel-plugin-react-html-attrs plugin:
npm install babel-plugin-react-html-attrs@1.x
module.exports = {
babel: {
plugins: ['react-html-attrs']
}
}
If provided, Babel config will also be used to configure the babel-loader Webpack loader if there isn't any other configuration specified for it in webpack.loaders.
Webpack Configuration
webpack: Object
Webpack configuration can be provided in a webpack object.
loaders: Object
Each Webpack loader configured by default has a unique id you can use to customise it.
To customise a loader, add a prop to the loaders object matching its id with a configuration object.
Refer to each loader's documentation (linked to for each default loader documented below) for configuration options which can be set.
Generic loader options such as include and exclude can be configured alongside loader-specific query options - you can also use an explicit query object if necessary to separate this configuration.
e.g. to enable CSS Modules for your app's CSS, the following loader configs are equivalent:
module.exports = {
webpack: {
loaders: {
css: {
modules: true,
localIdentName: '[hash:base64:5]'
}
}
}
}
module.exports = {
webpack: {
loaders: {
css: {
query: {
modules: true,
localIdentName: '[hash:base64:5]'
}
}
}
}
}
If a loader supports configuration via a top-level webpack configuration property, this can be provided as a config prop. This is primarily for loaders which can't be configured via query parameters as they have configuration which can't be serialised, such as instances of plugins.
e.g. to use the nib plugin with the Stylus preprocessor provided by nwb-stylus:
var nib = require('nib')
module.exports = {
webpack: {
loaders: {
stylus: {
config: {
use: [nib()]
}
}
}
}
}
Alternatively, you can also add new properties directly to the top-level Webpack config using extra
Default Loaders
Default loaders configured by nwb and the ids it gives them are:
-
babel- handles.js(and.jsx) files with babel-loaderDefault config:
{exclude: /node_modules/} -
css-pipeline- handles your app's own.cssfiles by chaining together a number of loaders:Default config:
{exclude: /node_modules/}Chained loaders are:
style- (only when serving) applies styles using style-loadercss- handles URLs, minification and CSS Modules using css-loaderpostcss- processes CSS with PostCSS plugins using postcss-loader; by default, this is configured to automatically add vendor prefixes to CSS using autoprefixer
-
vendor-css-pipeline- handles.cssfiles required fromnode_modules/, with the same set of chained loaders ascss-pipelinebut with avendor-prefix in their id.Default config:
{include: /node_modules/} -
graphics- handles.gifand.pngfiles using using url-loaderDefault config:
{limit: 10240} -
jpeg- handles.jpegfiles using file-loader -
fonts- handles.otf,.svg,.ttf,.woffand.woff2files using url-loaderDefault config:
{limit: 10240} -
eot- handles.eotfiles using file-loader -
json- handles.jsonfiles using json-loader
Test loaders
When running Karma tests with coverage enabled, the following loader will be added:
-
isparta- handles instrumentation of source files for coverage analysis using isparta-loaderDefault config:
{include: path.join(cwd, 'src')}(where cwd is the directory you rannwb testfrom).You may need to tweak this loader if you're changing where Karma looks for tests - e.g. if you're colocating tests in
__tests__directories, you will want to configure isparta-loader to ignore these:module.exports = { webpack: { loaders: { isparta: { exclude: /__tests__/ } } } }
define: Object
By default, nwb will use Webpack's DefinePlugin to replace all occurances of process.env.NODE_ENV with a string containing NODE_ENV's current value.
You can configure a define object to add your own constant values.
e.g. to replace all occurrences of __VERSION__ with a string containing your app's version from its package.json:
module.exports = {
webpack: {
define: {
__VERSION__: JSON.stringify(require('./package.json').version)
}
}
}
extractText: Object
Configures options for ExtractTextWebpackPlugin.
This can be used to control whether or not CSS is extracted from all chunks in an app which uses code splitting, or only the initial chunk:
module.exports = {
webpack: {
extractText: {
allChunks: true
}
}
}
html: Object
For apps, nwb will look for a src/index.html template to inject <link> and <script> tags into for each CSS and JavaScript bundle generated by Webpack.
Use templateconfig if you have an HTML file elsewhere you want to use:
module.exports = {
webpack: {
html: {
template: 'html/index.html'
}
}
}
If you don't have a template at src/index.html or specify one via template, nwb will fall back to using a basic template which has the following properties you can configure:
-
title- contents for<title>Default: the value of
namefrom your app'spackage.json -
mountId- theidfor the<div>provided for your app to mount itself intoDefault:
'app'
module.exports = {
webpack: {
html: {
mountId: 'root',
title: 'Unimaginative documentation example'
}
}
}
Oher HtmlWebpackPlugin options can also be used. e.g. if you have a favicon.ico in your src/ directory, you can include it in the index.html generated when your app is built and have it copied to the output directory like so:
module.exports = {
webpack: {
html: {
favicon: 'src/favicon.ico'
}
}
}
install: Object
Configures options for NpmInstallPlugin, which will be used if you pass --auto-install flag to nwb serve.
vendorBundle: Boolean
Setting this to false disables extraction of anything imported from node_modules/ into a vendor bundle.
postcss: Array | Object
By default, nwb configures the postcss-loader in each style pipeline to automatically add vendor prefixes to CSS rules.
Use postcss configuration to provide your own list of PostCSS plugins to be used for each pipeline, which will completely overwrite nwb's default configuration.
If you're only configuring PostCSS plugins for your app's own CSS, you can just provide a list:
module.exports = {
webpack: {
postcss: [
require('precss')(),
require('autoprefixer')(),
require('cssnano')()
]
}
}
Use an object if you're configuring other style pipelines. When using an object, PostCSS plugins for the default style pipeline (applied to your app's own CSS) must be configured using a defaults property:
var autoprefixer = require('autoprefixer')
module.exports = {
webpack: {
postcss: {
defaults: [
require('precss')(),
autoprefixer(),
require('cssnano')()
],
vendor: [
autoprefixer({add: false})
]
}
}
}
Plugins for other style pipelines are configured using their prefix as a property name: vendor for anything imported out of node_modules/, sass if you're using the nwb-sass preprocessor plugin, etc.
Your app is responsible for managing its own PostCSS plugin dependencies - between the size of the PostCSS ecosystem and the number of different configuration options postcss-loader supports, PostCSS could do with its own equivalent of nwb to manage dependencies and configuration!
It's recommended to create instances of PostCSS plugins in your config, as opposed to passing a module, in case you ever need to make use of debug output (enabled by setting a DEBUG environment variable to nwb) to examine generated config.
compat: Object
Certain libraries require specific configuration to play nicely with Webpack - nwb can take care of the details for you if you use a compat object to tell it when you're using them. The following libraries are supported:
enzyme: Boolean
Set to true for Enzyme compatibility - this assumes you're using the latest version of React (v15).
moment: Object
If you use Moment.js in a Webpack build, all the locales it supports will be imported by default. Provide an object with a locales Array specifying language codes for the locales you want to load.
sinon: Boolean
Set to true for Sinon.js 1.x compatibility.
Here's an example config showing the use of every compat setting:
module.exports = {
webpack: {
compat: {
enzyme: true,
moment: {
locales: ['de', 'en-gb', 'es', 'fr', 'it']
},
sinon: true
}
}
}
extra: Object
Extra configuration to be merged into the generated Webpack configuration using webpack-merge - see the Webpack configuration docs for the available fields.
Note that you must use Webpack's own config structure in this object - e.g. to add an extra loader which isn't managed by nwb's own webpack.loaders config, you would need to provide a list of loaders at webpack.extra.module.loaders.
var path = require('path')
module.exports = function(nwb) {
return {
type: 'react-app',
webpack: {
extra: {
// Example of adding an extra loader which isn't managed by nwb,
// assuming you've installed html-loader in your project.
module: {
loaders: [
{test: /\.html$/, loader: 'html'}
]
},
// Allow the use of require('images/blah.png') to require from an
// src/images from anywhere in the the app.
resolve: {
alias: {
'images': path.resolve('src/images')
}
},
// Example of adding an extra plugin which isn't managed by nwb
plugins: [
new nwb.webpack.optimize.MinChunkSizePlugin({
minChunkSize: 1024
})
]
}
}
}
}
Karma Configuration
Karma defaults to using the Mocha framework and reporter plugins, but it's possible to configure your own, as well as where it looks for tests.
karma: Object
Karma configuration is defined in a karma object, using the following fields:
tests: String
By default, Karma will attempt to run tests from 'tests/**/*-test.js' - you can configure this using the tests property.
e.g. if you want to colocate your tests with your source:
module.exports = {
karma: {
tests: 'src/**/*-test.js'
}
}
frameworks: Array<String | Plugin>
You must provide the plugin for any custom framework you want to use and manage it as a dependency yourself. Customise the testing framework plugin(s) Karma uses with the frameworks and plugins props:
npm install --save-dev karma-tap
module.exports = {
karma: {
frameworks: ['tap'],
plugins: [
require('karma-tap')
]
}
}
nwb can also determine the correct framework name given the plugin itself, so the following is functionally identical to the configuration above:
module.exports = {
karma: {
frameworks: [
require('karma-tap')
]
}
}
If a plugin module provides multiple plugins, nwb will only infer the name of the first plugin it provides, so pass it using plugins instead and list all the frameworks you want to use, for clarity:
module.exports = {
karma: {
frameworks: ['mocha', 'chai', 'chai-as-promised'],
plugins: [
require('karma-chai-plugins') // Provides chai, chai-as-promised, ...
]
}
}
If you're configuring frameworks and you want to use the Mocha framework managed by nwb, just pass its name as in the above example.
reporters: Array<String | Plugin>
Customising reporters follows the same principle as frameworks, just using the reporters prop instead.
For built-in reporters, or nwb's versfon of the Mocha reporter, just pass a name:
module.exports = {
karma: {
reporters: ['progress']
}
}
For custom reporters, install and provide the plugin:
npm install --save-dev karma-tape-reporter
module.exports = {
karma: {
reporters: [
require('karma-tape-reporter')
]
}
}
plugins: Array<Plugin>
A list of plugins to be loaded by Karma - this should be used in combination with frameworks and reporters as necessary.
extra: Object
Extra configuration to be merged into the generated Karma configuration using webpack-merge.
Note that you must use Karma's own config structure in this object.
e.g. to tweak the configuration of the default Mocha reporter:
module.exports = {
karma: {
extra: {
mochaReporter: {
divider: '°º¤ø,¸¸,ø¤º°`°º¤ø,¸,ø¤°º¤ø,¸¸,ø¤º°`°º¤ø,¸',
output: 'autowatch'
}
}
}
}
npm Build Configuration
build: Object
By default, nwb build creates an ES5 build of your React component or vanilla JS module's code for publishing to npm. Additional npm build configuration is defined in a build object, using the following fields:
umd: Boolean
Determines whether or not nwb will create a UMD build when you run nwb build for a React component or web module.
global: String (required for UMD build)
The name of the global variable the UMD build will export.
externals: Object (for UMD build)
A mapping from peerDependency module names to the global variables they're expected to be available as for use by the UMD build.
e.g. if you're creating a React component which also depends on React Router, this configuration would ensure they're not included in the UMD build:
module.exports = {
build: {
umd: true,
global: 'MyComponent',
externals: {
'react': 'React',
'react-router': 'ReactRouter'
}
}
}
package.json UMD Banner Configuration
A banner comment added to UMD builds will use as many of the following package.json fields as are present:
nameversionhomepagelicense
If all fields are present the banner will be in this format:
/*!
* nwb 0.6.0 - https://github.com/insin/nwb
* MIT Licensed
*/
jsNext: Boolean
Determines whether or not nwb will create an ES6 modules build for tree-shaking module bundlers when you run nwb build for a React component or web module.
module.exports = {
build: {
jsNext: true
}
}