- 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:
- 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
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 thewebpack
module.
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
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'
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 can be provided in a webpack
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 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.css
files 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.css
files required fromnode_modules/
, with the same set of chained loaders ascss-pipeline
but with avendor-
prefix in their id.Default config:
{include: /node_modules/}
-
graphics
- handles.gif
and.png
files using using url-loaderDefault config:
{limit: 10240}
-
jpeg
- handles.jpeg
files using file-loader -
fonts
- handles.otf
,.svg
,.ttf
,.woff
and.woff2
files using url-loaderDefault config:
{limit: 10240}
-
eot
- handles.eot
files using file-loader -
json
- handles.json
files using json-loader
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 test
from).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__/ } } } }
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)
}
}
}
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
}
}
}
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 template
config 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
name
from your app'spackage.json
-
mountId
- theid
for 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'
}
}
}
Configures options for NpmInstallPlugin
, which will be used if you pass --auto-install
flag to nwb serve
.
Setting this to false
disables extraction of anything imported from node_modules/
into a vendor
bundle.
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.
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:
Set to true
for Enzyme compatibility - this assumes you're using the latest version of React (v15).
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.
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 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 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 configuration is defined in a karma
object, using the following fields:
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'
}
}
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.
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')
]
}
}
A list of plugins to be loaded by Karma - this should be used in combination with frameworks
and reporters
as necessary.
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'
}
}
}
}
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:
Determines whether or not nwb will create a UMD build when you run nwb build
for a React component or web module.
The name of the global variable the UMD build will export.
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'
}
}
}
A banner comment added to UMD builds will use as many of the following package.json
fields as are present:
name
version
homepage
license
If all fields are present the banner will be in this format:
/*!
* nwb 0.6.0 - https://github.com/insin/nwb
* MIT Licensed
*/
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
}
}