diff --git a/CHANGES.md b/CHANGES.md index 77810caa..0f587620 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -60,6 +60,8 @@ **Added:** +- The entry point for apps and npm module UMD builds can now be specified as an argument to [`build` and `serve` commands](https://github.com/insin/nwb/blob/v0.11.0/docs/Commands.md#project-type-specific-commands). The default is still `src/index.js`. [[#115](https://github.com/insin/nwb/issues/115)] +- The directory web apps are built into can now be specified as an argument to [`build`, `clean` and `serve` commands](https://github.com/insin/nwb/blob/v0.11.0/docs/Commands.md#project-type-specific-commands). The default is still `dist/`. - Added [`webpack.compat` config](https://github.com/insin/nwb/blob/v0.11.0/docs/Configuration.md#compat-object) to enable compatibility tweaks for modules which are known to be problematic with Webpack - initially this includes support for Enzyme, Moment.js and Sinon.js 1.x [[#108](https://github.com/insin/nwb/issues/108)] - Added [`webpack.postcss` config](https://github.com/insin/nwb/blob/v0.11.0/docs/Configuration.md#postcss-object) to customise the PostCSS plugins applied to each style pipeline [[#57](https://github.com/insin/nwb/issues/57)] - Added [`webpack.vendorBundle` config](https://github.com/insin/nwb/blob/v0.11.0/docs/Configuration.md#vendorbundle-boolean) to disable automatically extracting anything imported from `node_modules/` out into a separate `vendor` chunk [[#106](https://github.com/insin/nwb/issues/106)] diff --git a/README.md b/README.md index a6ba2306..e1a9822d 100644 --- a/README.md +++ b/README.md @@ -132,24 +132,30 @@ This video shows the resulting example of using nwb to create a new React projec ## Usage ``` -Usage: nwb +Usage: + nwb [options] Options: -h, --help display this help message -v, --version print nwb's version Project creation commands: - init [name] + init [name] initialise a project in the current directory - new + new create a project in a new directory - -f, --force force project creation, don't ask questions - -g, --global global variable name to export in the UMD build - --no-jsnext disable npm ES6 modules build - --no-umd disable npm UMD module build - --react version of React to install for React apps and components + Positional arguments: + project_type project type - see the list below + name project name [default: current directory name] + + Options: + -f, --force force project creation, don't ask questions + -g, --global global variable name to export in the UMD build + --no-jsnext disable npm ES6 modules build + --no-umd disable npm UMD module build + --react version of React to install for React apps & components Project types: react-app a React app @@ -157,7 +163,10 @@ Project creation commands: web-app a plain JavaScript app web-module a plain JavaScript module -Development commands: +Generic development commands: + Positional arguments for these commands depend on the type of project they're + being run in. See the applicable project-type-specific commands below. + build clean and build the project @@ -166,43 +175,62 @@ Development commands: serve serve an app, or a component's demo app, with hot reloading - --auto-install auto install missing npm dependencies - --fallback serve the index page from any path - --host hostname to bind the dev server to (default: localhost) - --info show webpack module info - --port port to run the dev server on (default: 3000) - --reload auto reload the page if hot reloading fails + + Options: + --auto-install auto install missing npm dependencies + --fallback serve the index page from any path + --host hostname to bind the dev server to [default: localhost] + --info show webpack module info + --port port to run the dev server on [default: 3000] + --reload auto reload the page if hot reloading fails test run unit tests - --coverage create a code coverage report - --server keep running tests on every change -Project type-specific commands: + Options: + --coverage create a code coverage report + --server keep running tests on every change + +Project-type-specific commands: build-demo build a demo app from demo/src/index.js to demo/dist/ + build-module create an ES5 build for an npm module (ES6 modules build requires config) - build-react-app - build a react app from src/index.js to dist/ - build-umd - create a UMD build for an npm module (requires config) - build-web-app - build a web app from src/index.js to dist/ - clean-app - delete dist/ + + build-react-app [entry] [dist_dir] + build a React app from entry to dist_dir + + build-umd [entry] + create a UMD build for an npm module from entry (requires config) + + build-web-app [entry] [dist_dir] + build a web app from entry to dist_dir + + clean-app [dist_dir] + delete dist_dir + clean-demo delete demo/dist/ + clean-module - delete coverage/, es6/ and lib/ + delete coverage/, es6/ and lib/ + clean-umd delete umd/ - serve-react-app - serve a React app from src/index.js + + serve-react-app [entry] + serve a React app from entry + serve-react-demo serve a React demo app from demo/src/index.js - serve-web-app - serve a web app from src/index.js + + serve-web-app [entry] + serve a web app from entry + + Positional arguments: + entry entry point [default: src/index.js] + dist_dir build output directory [default: dist/] ``` ## Versioning diff --git a/docs/Commands.md b/docs/Commands.md index d2d2d57d..7f1d9908 100644 --- a/docs/Commands.md +++ b/docs/Commands.md @@ -7,7 +7,7 @@ These are optional, but they're a quick way to get started with a new project us #### `new` - create a new project ``` -nwb new +nwb new ``` Creates a new directory and initialises a project skeleton in it. @@ -63,7 +63,7 @@ Creates a skeleton for a web module with the given name, with an optional UMD bu #### `init` - initialise a project in the current directory ``` -nwb init [name] +nwb init [name] ``` This is the same as `new`, except the `name` argument is optional and the new project is initialised in the current directory. @@ -77,7 +77,7 @@ The following commands require a `nwb.config.js` file to be present to specify t #### `serve` - serve an app ``` -nwb serve +nwb serve [entry] ``` Starts a development server which serves an app with hot module reloading. @@ -86,6 +86,8 @@ Starts a development server which serves an app with hot module reloading. * Syntax errors made while the development server is running will appear as an overlay in your browser. * Rendering errors in React components will also appear as an overlay. +Passing an argument for `entry` allows you to customise the entry point for your React or web app. + **Flags:** * `--auto-install` - automatically install missing npm dependencies and save them to your app's package.json, for convenience during initial development/prototyping @@ -116,18 +118,18 @@ Having a demo which uses your component is also a great way to test it as you pr #### `build` - create builds ``` -nwb build +nwb build [entry] [dist_dir] ``` Builds the project. **In React/web apps:** -A static build will be created in `dist/`, with `app.js` and `app.css` files plus any other resources used. - -By default, separate `vendor.js` and `vendor.css` files will be built for any dependencies used from `node_modules/`. +Default behaviour: -By default, static builds are created in production mode. Code will be minified and have dead code elimination performed on it (for example to remove unreachable, or development-mode only, code). +* A static build will be created in `dist/`, with `app.js` and `app.css` files plus any other resources used. +* Separate `vendor.js` and `vendor.css` files will be built for any dependencies used from `node_modules/`. +* Static builds are created in production mode. Code will be minified and have dead code elimination performed on it (for example to remove unreachable, or development-mode only, code). To create a development build, set the `NODE_ENV` environment variable to `'development'` when running the `build` command; nwb supports a cross-platform way of doing this, using [argv-set-env](https://github.com/kentcdodds/argv-set-env): @@ -139,6 +141,8 @@ nwb build --set-env-NODE_ENV=development NODE_ENV=development nwb build ``` +Passing arguments for `entry` and `dist_dir` allows you to customise the entry point for your app and the directory it gets build into. + **In React apps only:** In production mode builds, the Babel 5 [constant-elements](https://github.com/babel/babel.github.io/blob/862b43db93e48762671267034a50c30c00e433e2/docs/advanced/transformers/optimisation/react/constant-elements.md) and [inline-elements](https://github.com/babel/babel.github.io/blob/862b43db93e48762671267034a50c30c00e433e2/docs/advanced/transformers/optimisation/react/inline-elements.md) React optimisation transforms will be used. @@ -153,14 +157,18 @@ Builds the component in preparation for publishing to npm. If the module has a `demo/` directory, running `build` will also create a static build of its demo app in `demo/dist/`. +Passing an argument for `entry` allows you to customise the entry point for the UMD build of your app. + #### `clean` - clean up ``` -nwb clean +nwb clean [dist_dir] ``` Deletes all built resource directories. +For React and web apps, passing an argument for `dist_dir` allows you to customise the output directory which will be deleted. + ### Project commands The following commands don't require an `nwb.config.js` file to specify a project type, but it may be required for other configuration depending on the command. @@ -182,19 +190,30 @@ Runs unit tests. Running the test server in tandem with a hot reloading demo app, you can quickly protoype and test your components. -#### Project Type-specific Commands +#### Project-type-specific Commands -Project type-specific versions of the generic `build`, `clean` and `serve` commands are also available to run directly - if you use the generic commands, you will see nwb calling these for you: +Project-type-specific versions of the generic `build`, `clean` and `serve` commands are also available to run directly - if you use the generic commands, you will see nwb calling these for you: * `build-demo` - build a demo app from `demo/src/index.js` to `demo/dist/` + * `build-module` - create an ES5 build for an npm module -* `build-react-app` - build a react app from `src/index.js` to `dist/` -* `build-umd` - create a UMD build for an npm module (this command itself requires configuration, so is useless without a config file) -* `build-web-app` - build a web app from `src/index.js` to `dist/` -* `clean-app` - delete `dist/` + +* `build-react-app [entry] [dist_dir]` - build a react app from `entry` (default: `src/index.js`) to `dist_dir` (default: `dist/`) + +* `build-umd [entry]` - create a UMD build for an npm module starting from `entry` (default: `src/index.js`) (this command requires configuration) + +* `build-web-app [entry] [dist_dir]` - build a web app from `entry` (default: `src/index.js`) to `dist_dir` (default: `dist/`) + +* `clean-app [dist_dir]` - delete `dist_dir` (default: `dist/`) + * `clean-demo` - delete `demo/dist/` + * `clean-module` - delete `coverage/`, `es6/` and `lib/ + * `clean-umd` - delete `umd/` -* `serve-react-app` - serve a React app from `src/index.js` + +* `serve-react-app [entry]` - serve a React app from `entry` (default: `src/index.js`) + * `serve-react-demo` - serve a React demo app from `demo/src/index.js` -* `serve-web-app` - serve a web app from `src/index.js` + +* `serve-web-app [entry]` - serve a web app from `entry` (default: `src/index.js`) diff --git a/docs/Middleware.md b/docs/Middleware.md index 74970b8f..fa5ecb3d 100644 --- a/docs/Middleware.md +++ b/docs/Middleware.md @@ -19,6 +19,7 @@ Your app's version of the Express module must be passed as the first argument. ###### `options` * `autoInstall` - automatically install missing npm dependencies. Default: `false` +* `entry` - entry point for the app. Default: `src/index.js` * `info` - print info about Webpack modules after rebuilds. Default: `false` #### Example diff --git a/express.js b/express.js index 974e86a0..97d28b7e 100644 --- a/express.js +++ b/express.js @@ -20,14 +20,16 @@ module.exports = function(express, options) { if (!options) options = {} // Use options to create an object equivalent to CLI args parsed by minimist - var args = {} - args.info = !!options.info - args['auto-install'] = !!options.autoInstall + var args = { + _: ['serve-react-app', options.entry], + 'auto-install': !!options.autoInstall, + info: !!options.info + } var webpackConfig = createServerWebpackConfig( args, createServeReactAppBuildConfig( - createServeReactAppConfig() + createServeReactAppConfig(args) ) ) diff --git a/src/cli.js b/src/cli.js index 9aaf97e6..a42d7d2d 100644 --- a/src/cli.js +++ b/src/cli.js @@ -20,24 +20,30 @@ export default function(argv, cb) { } if (args.help || !command || /^h(elp)?$/.test(command)) { - console.log(`Usage: ${green('nwb')} ${yellow('')} + console.log(`Usage: + ${green('nwb')} ${yellow('')} ${cyan('[options]')} Options: ${cyan('-h, --help')} display this help message ${cyan('-v, --version')} print nwb's version Project creation commands: - ${green('init')} ${yellow('')} ${cyan('[name]')} + ${green('init')} ${yellow('')} ${cyan('[name]')} initialise a project in the current directory - ${green('new')} ${yellow(' ')} + ${green('new')} ${yellow(' ')} create a project in a new directory - ${cyan('-f, --force')} force project creation, don't ask questions - ${cyan('-g, --global')} global variable name to export in the UMD build - ${cyan('--no-jsnext')} disable npm ES6 modules build - ${cyan('--no-umd')} disable npm UMD module build - ${cyan('--react')} version of React to install for React apps and components + Positional arguments: + ${cyan('project_type')} project type - see the list below + ${cyan('name')} project name ${cyan('[default: current directory name]')} + + Options: + ${cyan('-f, --force')} force project creation, don't ask questions + ${cyan('-g, --global')} global variable name to export in the UMD build + ${cyan('--no-jsnext')} disable npm ES6 modules build + ${cyan('--no-umd')} disable npm UMD module build + ${cyan('--react')} version of React to install for React apps & components Project types: ${cyan('react-app')} a React app @@ -46,6 +52,9 @@ Project creation commands: ${cyan('web-module')} a plain JavaScript module Generic development commands: + Positional arguments for these commands depend on the type of project they're + being run in. See the applicable project-type-specific commands below. + ${green('build')} clean and build the project @@ -54,43 +63,62 @@ Generic development commands: ${green('serve')} serve an app, or a component's demo app, with hot reloading - ${cyan('--auto-install')} auto install missing npm dependencies - ${cyan('--fallback')} serve the index page from any path - ${cyan('--host')} hostname to bind the dev server to ${cyan('(default: localhost)')} - ${cyan('--info')} show webpack module info - ${cyan('--port')} port to run the dev server on ${cyan('(default: 3000)')} - ${cyan('--reload')} auto reload the page if hot reloading fails + + Options: + ${cyan('--auto-install')} auto install missing npm dependencies + ${cyan('--fallback')} serve the index page from any path + ${cyan('--host')} hostname to bind the dev server to ${cyan('[default: localhost]')} + ${cyan('--info')} show webpack module info + ${cyan('--port')} port to run the dev server on ${cyan('[default: 3000]')} + ${cyan('--reload')} auto reload the page if hot reloading fails ${green('test')} run unit tests - ${cyan('--coverage')} create a code coverage report - ${cyan('--server')} keep running tests on every change -Project type-specific commands: + Options: + ${cyan('--coverage')} create a code coverage report + ${cyan('--server')} keep running tests on every change + +Project-type-specific commands: ${green('build-demo')} build a demo app from demo/src/index.js to demo/dist/ + ${green('build-module')} create an ES5 build for an npm module (ES6 modules build requires config) - ${green('build-react-app')} - build a react app from src/index.js to dist/ - ${green('build-umd')} - create a UMD build for an npm module (requires config) - ${green('build-web-app')} - build a web app from src/index.js to dist/ - ${green('clean-app')} - delete dist/ + + ${green('build-react-app')} ${cyan('[entry] [dist_dir]')} + build a React app from ${cyan('entry')} to ${cyan('dist_dir')} + + ${green('build-umd')} ${cyan('[entry]')} + create a UMD build for an npm module from ${cyan('entry')} (requires config) + + ${green('build-web-app')} ${cyan('[entry] [dist_dir]')} + build a web app from ${cyan('entry')} to ${cyan('dist_dir')} + + ${green('clean-app')} ${cyan('[dist_dir]')} + delete ${cyan('dist_dir')} + ${green('clean-demo')} delete demo/dist/ + ${green('clean-module')} - delete coverage/, es6/ and lib/ + delete coverage/, es6/ and lib/ + ${green('clean-umd')} delete umd/ - ${green('serve-react-app')} - serve a React app from src/index.js + + ${green('serve-react-app')} ${cyan('[entry]')} + serve a React app from ${cyan('entry')} + ${green('serve-react-demo')} serve a React demo app from demo/src/index.js - ${green('serve-web-app')} - serve a web app from src/index.js + + ${green('serve-web-app')} ${cyan('[entry]')} + serve a web app from ${cyan('entry')} + + Positional arguments: + ${cyan('entry')} entry point ${cyan('[default: src/index.js]')} + ${cyan('dist_dir')} build output directory ${cyan('[default: dist/]')} `) process.exit(args.help || command ? 0 : 1) } diff --git a/src/commands/build-react-app.js b/src/commands/build-react-app.js index 1c26ec28..e03c5003 100644 --- a/src/commands/build-react-app.js +++ b/src/commands/build-react-app.js @@ -7,15 +7,18 @@ import webpackBuild from '../webpackBuild' // Use a config function, as this won't be called until after NODE_ENV has been // set by webpackBuild() and we don't want these optimisations in development // builds. -let buildConfig = () => { +let buildConfig = (args) => { + let entry = args._[1] || 'src/index.js' + let dist = args._[2] || 'dist' + let config = { devtool: 'source-map', entry: { - app: path.resolve('src/index.js') + app: path.resolve(entry) }, output: { filename: '[name].js', - path: path.resolve('dist'), + path: path.resolve(dist), publicPath: '/' }, plugins: { @@ -41,10 +44,11 @@ let buildConfig = () => { } export default function(args, cb) { - require('./clean-app')(args) + let dist = args._[2] || 'dist' - copyPublicDir('public', 'dist') + require('./clean-app')({_: ['clean-app', dist]}) console.log('nwb: build-react-app') + copyPublicDir('public', dist) webpackBuild(args, buildConfig, cb) } diff --git a/src/commands/build-umd.js b/src/commands/build-umd.js index 36449a62..078509c2 100644 --- a/src/commands/build-umd.js +++ b/src/commands/build-umd.js @@ -1,4 +1,3 @@ -import assert from 'assert' import path from 'path' import getUserConfig from '../getUserConfig' @@ -15,14 +14,13 @@ export default function(args, cb) { if (!build.umd) { return cb(new UserError( - 'nwb: the UMD build for this module hasn\'t been enabled in nwb.config.js' + "nwb: the UMD build for this module hasn't been enabled in nwb.config.js" )) } - assert(build.global, 'build.global config is required to create a UMD build') - + let entry = args._[1] || 'src/index.js' let buildConfig = { - entry: path.resolve('src/index.js'), + entry: path.resolve(entry), output: { filename: `${pkg.name}.js`, library: build.global, diff --git a/src/commands/build-web-app.js b/src/commands/build-web-app.js index 741c5e01..97e284a3 100644 --- a/src/commands/build-web-app.js +++ b/src/commands/build-web-app.js @@ -6,19 +6,21 @@ import {copyPublicDir} from '../utils' import webpackBuild from '../webpackBuild' export default function(args, cb) { - require('./clean-app')(args) + let entry = args._[1] || 'src/index.js' + let dist = args._[2] || 'dist' - copyPublicDir('public', 'dist') + require('./clean-app')({_: ['clean-app', dist]}) console.log('nwb: build-web-app') + copyPublicDir('public', dist) webpackBuild(args, { devtool: 'source-map', entry: { - app: path.resolve('src/index.js') + app: path.resolve(entry) }, output: { filename: '[name].js', - path: path.resolve('dist'), + path: path.resolve(dist), publicPath: '/' }, plugins: { diff --git a/src/commands/clean-app.js b/src/commands/clean-app.js index 55352ff6..02eb55d6 100644 --- a/src/commands/clean-app.js +++ b/src/commands/clean-app.js @@ -1,6 +1,8 @@ import exec from '../exec' export default function(args) { + let dist = args._[1] || 'dist' + console.log('nwb: clean-app') - exec('rimraf', ['coverage', 'dist']) + exec('rimraf', ['coverage', dist]) } diff --git a/src/commands/serve-react-app.js b/src/commands/serve-react-app.js index cf8f9f9f..d349f527 100644 --- a/src/commands/serve-react-app.js +++ b/src/commands/serve-react-app.js @@ -3,5 +3,5 @@ import createServeReactAppConfig from '../createServeReactAppConfig' export default function(args, cb) { console.log('nwb: serve-react-app') - serveReact(args, createServeReactAppConfig(), cb) + serveReact(args, createServeReactAppConfig(args), cb) } diff --git a/src/commands/serve-react-demo.js b/src/commands/serve-react-demo.js index ac53b19e..9189b4b7 100644 --- a/src/commands/serve-react-demo.js +++ b/src/commands/serve-react-demo.js @@ -7,6 +7,7 @@ import serveReact from '../serveReact' */ export default function(args, cb) { let pkg = require(path.resolve('package.json')) + console.log('nwb: serve-react-demo') serveReact(args, { entry: path.resolve('demo/src/index.js'), diff --git a/src/commands/serve-web-app.js b/src/commands/serve-web-app.js index 3c052782..0bb4e0aa 100644 --- a/src/commands/serve-web-app.js +++ b/src/commands/serve-web-app.js @@ -4,11 +4,14 @@ import {getDefaultHTMLConfig} from '../appConfig' import webpackServer from '../webpackServer' export default function(args, cb) { + let entry = args._[1] || 'src/index.js' + let dist = args._[2] || 'dist' + console.log('nwb: serve-web-app') webpackServer(args, { - entry: path.resolve('src/index.js'), + entry: path.resolve(entry), output: { - path: path.resolve('dist'), + path: path.resolve(dist), filename: 'app.js', publicPath: '/' }, diff --git a/src/createServeReactAppConfig.js b/src/createServeReactAppConfig.js index 7dbb7a42..6892829d 100644 --- a/src/createServeReactAppConfig.js +++ b/src/createServeReactAppConfig.js @@ -7,11 +7,14 @@ import path from 'path' import {getDefaultHTMLConfig} from './appConfig' -export default function() { +export default function(args) { + let entry = path.resolve(args._[1] || 'src/index.js') + let dist = path.resolve(args._[2] || 'dist') + return { - entry: path.resolve('src/index.js'), + entry: path.resolve(entry), output: { - path: path.resolve('dist'), + path: path.resolve(dist), filename: 'app.js', publicPath: '/' }, diff --git a/src/webpackBuild.js b/src/webpackBuild.js index 476ae868..6b4ac985 100644 --- a/src/webpackBuild.js +++ b/src/webpackBuild.js @@ -22,7 +22,7 @@ export default function webpackBuild(args, buildConfig = {}, cb) { let userConfig = getUserConfig(args) let pluginConfig = getPluginConfig() if (typeof buildConfig == 'function') { - buildConfig = buildConfig() + buildConfig = buildConfig(args) } let webpackConfig = createWebpackConfig({