Skip to content

Commit

Permalink
Module build config must now be provided in a "build" object.
Browse files Browse the repository at this point in the history
Missing build config is now defaulted.

nwb 0.8 is backwards-compatible with the old config format.

#44
  • Loading branch information
insin committed Jan 14, 2016
1 parent 5656885 commit 295682f
Show file tree
Hide file tree
Showing 14 changed files with 190 additions and 81 deletions.
27 changes: 25 additions & 2 deletions CHANGES.md
@@ -1,6 +1,29 @@
**Changed:**

- Development instructions in project templates were moved from `README.md` to a `CONTRIBUTING.md`, and are now documented using `npm` and `npm run` commands instead of global `nwb` commands.
- `nwb.config.js` consistency changes: Babel and Karma config is currently specified in `babel` and `karma` objects. Other configuration must now be specified in similar objects for consistency. nwb v0.8 will support the old format and display warning messages about the changes required to config; support for the old format will be removed in nwb v0.9.
- React component and vanilla JS module npm build configuration must now be specificed as a `build` object:
```
// < v0.9
module.exports = {
externals: {react: 'React'},
global: 'MyComponent',
jsNext: true,
umd: true
}
```
```
// v0.9
module.exports = {
build: {
externals: {react: 'React'},
global: 'MyComponent',
jsNext: true,
umd: true
}
}
```
- Development instructions in project templates were moved from `README.md` to a `CONTRIBUTING.md` file, and are now documented using `npm` and `npm run` commands instead of global `nwb` commands.
- A `test:watch` npm script was added to the project templates.
- All commands are now run in the current working directory - you no longer need to `require.resolve()` full paths to extra Babel plugins configured in `nwb.config.js`, just use their names as Babel will now be able to import them.

# 0.7.1 / 2016-01-10
Expand Down Expand Up @@ -109,7 +132,7 @@
- Reorganised and coloured `nwb help` output.
- Commands which create files now log details of what they've created [[#26](https://github.com/insin/nwb/issues/26)]
- The ES6 modules build for npm modules is now optional, controlled by a `jsNext` setting in `nwb.config.js`, defaulting to `true` [[#27](https://github.com/insin/nwb/issues/27)]
- nwb 0.6 will default `jsNext` to `true` and log a warning when it's missing from a config file - this behaviour will be removed in nwb 0.7.
- nwb 0.6 will default `jsNext` to `true` and log a warning when it's missing from a config file - this behaviour will be removed in nwb v0.7.

**Dependencies:**

Expand Down
60 changes: 35 additions & 25 deletions docs/Configuration.md
Expand Up @@ -25,11 +25,13 @@ The object exported or returned by your nwb config can use the following fields:
* [`karma.reporters`](#reporters-arraystring--plugin)
* [`karma.plugins`](#plugins-arrayplugin)
* npm Build Configuration
* [`jsNext`](#jsnext-boolean)
* [`umd`](#umd-boolean)
* [`global`](#global-string-required-for-umd-build)
* [`externals`](#externals-object-for-umd-build)
* [`package.json` fields](#packagejson-umd-banner-configuration)
* [`build`](#build-object)
* UMD build config
* [`build.umd`](#umd-boolean)
* [`build.global`](#global-string-required-for-umd-build)
* [`build.externals`](#externals-object-for-umd-build)
* [`package.json` fields](#packagejson-umd-banner-configuration)
* [`build.jsNext`](#jsnext-boolean)

#### `type`: `String` (required)

Expand All @@ -46,7 +48,7 @@ It must be one of:

#### `babel`: `Object`

Use this field to provide your own options for Babel (version 5) - [see the Babel 5 options documentation](https://github.com/babel/babel.github.io/blob/862b43db93e48762671267034a50c30c00e433e2/docs/usage/options.md).
Use this object to provide your own options for Babel (version 5) - [see the Babel 5 options documentation](https://github.com/babel/babel.github.io/blob/862b43db93e48762671267034a50c30c00e433e2/docs/usage/options.md).

e.g. to use `async`/`await` transforms, you will need to configure Babel's `stage` and `optional` settings:

Expand Down Expand Up @@ -304,51 +306,47 @@ A list of plugins to be loaded by Karma - this should be used in combination wit

### npm Build Configuration

The following fields are used to configure what gets built in addition to the ES5 build created for React components and other modules which will be published to npm.
#### `build`: `Object`

#### `jsNext`: `Boolean`
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 an ES6 modules build for tree-shaking module bundlers when you run `nwb build` for a React component or web module.

Defaults to `true` when you are prompted to onfigure this by `nwb new`.

#### `umd`: `Boolean`
##### `umd`: `Boolean`

Determines whether or not nwb will create a UMD build when you run `nwb build` for a React component or web module.

Defaults to `true` when you are prompted to onfigure this by `nwb new`, or if you provide a UMD global variable as a command-line argument.

#### `global`: `String` (*required* for UMD build)
##### `global`: `String` (*required* for UMD build)

The name of the global variable the UMD build will export.

You will be prompted to configure this if you choose to enable a UMD build when creating a React component or web module with `nwb new`.

#### `externals`: `Object` (for UMD build)
##### `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](https://github.com/rackt/react-router):
e.g. if you're creating a React component which also depends on [React Router](https://github.com/rackt/react-router), this configuration would ensure they're not included in the UMD build:

```js
module.exports = {
externals: {
'react': 'React',
'react-router': 'ReactRouter'
build: {
umd: true,
global: 'MyComponent',
externals: {
'react': 'React',
'react-router': 'ReactRouter'
}
}
}
```

#### `package.json` UMD Banner Configuration

The banner comment added to UMD builds will use as many of the following `package.json` fields as are present:
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 look like this:
If all fields are present the banner will be in this format:

```js
/*!
Expand All @@ -357,6 +355,18 @@ If all fields are present the banner will look like this:
*/
```

##### `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.

```js
module.exports = {
build: {
jsNext: true
}
}
```

[autoprefixer-loader]: https://github.com/passy/autoprefixer-loader/
[babel-loader]: https://github.com/babel/babel-loader
[CSS Modules]: https://github.com/css-modules/css-modules
Expand Down
2 changes: 1 addition & 1 deletion src/commands/build-module.js
Expand Up @@ -31,7 +31,7 @@ export default function(args) {
console.log('nwb: build-module (es5)')
exec('babel', babelArgs, {cwd})

if (userConfig.jsNext) {
if (userConfig.build.jsNext) {
babelArgs[2] = es6
babelArgs = [...babelArgs, '--blacklist=es6.modules']
console.log('nwb: build-module (es6)')
Expand Down
14 changes: 8 additions & 6 deletions src/commands/build-umd.js
Expand Up @@ -11,23 +11,25 @@ import webpackBuild from '../webpackBuild'
*/
export default function(args, cb) {
let pkg = require(path.resolve('package.json'))
let userConfig = getUserConfig(args)
let {build} = getUserConfig(args)

if (!userConfig.umd) {
return cb(new UserError(`nwb: the UMD build for this module is disabled by nwb.config.js (umd = ${userConfig.umd})`))
if (!build.umd) {
return cb(new UserError(
`nwb: the UMD build for this module is disabled by nwb.config.js (build.umd = ${build.umd})`
))
}

assert(userConfig.global, 'global config is required to create a UMD build')
assert(build.global, 'build.global config is required to create a UMD build')

let buildConfig = {
entry: path.resolve('src/index.js'),
output: {
filename: `${pkg.name}.js`,
library: userConfig.global,
library: build.global,
libraryTarget: 'umd',
path: path.resolve('umd')
},
externals: createWebpackExternals(userConfig.externals),
externals: createWebpackExternals(build.externals),
plugins: {
banner: createBanner(pkg)
}
Expand Down
2 changes: 1 addition & 1 deletion src/commands/build.js
Expand Up @@ -19,7 +19,7 @@ export default function(args, cb) {
}
else if (userConfig.type === REACT_COMPONENT || userConfig.type === WEB_MODULE) {
require('./build-module')(args)
if (userConfig.umd) {
if (userConfig.build.umd) {
require('./build-umd')(args, () => buildDemo(args, cb))
}
else {
Expand Down
43 changes: 43 additions & 0 deletions src/getUserConfig.js
@@ -1,11 +1,23 @@
import path from 'path'

import chalk from 'chalk'
import glob from 'glob'

import {PROJECT_TYPES} from './constants'
import debug from './debug'
import {UserError} from './errors'

const DEFAULT_BUILD_CONFIG = {
externals: {},
global: '',
jsNext: false,
umd: false
}

// TODO Remove in nwb 0.9
const BUILD_CONFIG_PROPS = Object.keys(DEFAULT_BUILD_CONFIG)
let warnedAboutBuildConfig = false

export default function getUserConfig(args = {}) {
// Try to load default user config, or user a config file path we were given
let userConfig = {}
Expand Down Expand Up @@ -50,6 +62,37 @@ export default function getUserConfig(args = {}) {
}
}

// TODO Remove in nwb 0.9
if (BUILD_CONFIG_PROPS.some(prop => prop in userConfig)) {
if (!warnedAboutBuildConfig) {
console.warn(chalk.magenta([
'nwb: the top level of your nwb config contains npm module build configuration',
'nwb: nwb >= 0.9 will require this to be moved into a "build" object'
].join('\n')))
warnedAboutBuildConfig = true
}
let buildConfig = {...DEFAULT_BUILD_CONFIG}
BUILD_CONFIG_PROPS.forEach(prop => {
if (prop in userConfig) {
buildConfig[prop] = userConfig[prop]
delete userConfig[prop]
}
})
userConfig.build = buildConfig
}

// Set defaults for npm build config
if (!('build' in userConfig)) {
userConfig.build = {...DEFAULT_BUILD_CONFIG}
}
else {
BUILD_CONFIG_PROPS.forEach(prop => {
if (!(prop in userConfig.build)) {
userConfig.build[prop] = DEFAULT_BUILD_CONFIG[prop]
}
})
}

debug('final user config: %o', userConfig)

return userConfig
Expand Down
1 change: 0 additions & 1 deletion templates/react-app/nwb.config.js
@@ -1,4 +1,3 @@
module.exports = {
// Let nwb know this is a React app when generic build commands are used
type: 'react-app'
}
26 changes: 8 additions & 18 deletions templates/react-component/nwb.config.js
@@ -1,21 +1,11 @@
module.exports = {
// Let nwb know this is a React component module when generic build commands
// are used.
type: 'react-component',

// Should nwb create a UMD build for this module?
umd: {{umd}},
// The name of the global variable the UMD build of this module will export
global: '{{globalVariable}}',
// Mapping from the npm package names of this module's peerDependencies to the
// global variables they're expected to be available as for use by the UMD
// build.
externals: {
'react': 'React'
},

// Should nwb create a build with untranspiled ES6 modules for tree-shaking
// module bundlers? If you change your mind later, add or remove this line in
// package.json: "jsnext:main": "es6/index.js"
jsNext: {{jsNext}}
build: {
externals: {
'react': 'React'
},
global: '{{globalVariable}}',
jsNext: {{jsNext}},
umd: {{umd}}
}
}
1 change: 0 additions & 1 deletion templates/web-app/nwb.config.js
@@ -1,4 +1,3 @@
module.exports = {
// Let nwb know this is a web app when generic build commands are used
type: 'web-app'
}
21 changes: 6 additions & 15 deletions templates/web-module/nwb.config.js
@@ -1,18 +1,9 @@
module.exports = {
// Let nwb know this is a web module when generic build commands are used
type: 'web-module',

// Should nwb create a UMD build for this module?
umd: {{umd}},
// The name of the global variable the UMD build of this module will export
global: '{{globalVariable}}',
// A mapping from the npm package names of this module's peerDependencies - if
// it has any - to the global variables they're expected to be available as
// for use by the UMD build, e.g. {'react': 'React'}
externals: {},

// Should nwb create a build with untranspiled ES6 modules for tree-shaking
// module bundlers? If you change your mind later, add or remove this line in
// package.json: "jsnext:main": "es6/index.js"
jsNext: {{jsNext}}
build: {
externals: {},
global: '{{globalVariable}}',
jsNext: {{jsNext}},
umd: {{umd}},
}
}
20 changes: 12 additions & 8 deletions tests/commands/new-init-test.js
Expand Up @@ -77,10 +77,12 @@ function reactComponentAssertions(dir, name, err, done) {
let config = require(path.resolve(dir, 'nwb.config.js'))
expect(config).toEqual({
type: 'react-component',
umd: false,
global: '',
externals: {react: 'React'},
jsNext: true
build: {
externals: {react: 'React'},
global: '',
jsNext: true,
umd: false
}
})
done()
}
Expand Down Expand Up @@ -138,10 +140,12 @@ function webModuleAssertions(dir, name, err, done) {
let config = require(path.resolve(dir, 'nwb.config.js'))
expect(config).toEqual({
type: 'web-module',
umd: false,
global: '',
externals: {},
jsNext: true
build: {
externals: {},
global: '',
jsNext: true,
umd: false
}
})
done()
}
Expand Down
7 changes: 7 additions & 0 deletions tests/fixtures/0.8-build-config-compat.js
@@ -0,0 +1,7 @@
module.exports = {
type: 'react-component',
externals: {react: 'React'},
global: 'Test',
jsNext: true,
umd: true
}
7 changes: 7 additions & 0 deletions tests/fixtures/partial-build-config.js
@@ -0,0 +1,7 @@
module.exports = {
type: 'web-module',
build: {
umd: true,
global: 'Test'
}
}

0 comments on commit 295682f

Please sign in to comment.