Neutrino Node.js Preset¶
@neutrinojs/node
is a Neutrino preset that supports building Node.js applications.
Features¶
- Zero upfront configuration necessary to start developing and building a Node.js project
- Modern Babel compilation supporting ES modules, async functions, and dynamic imports
- By default targets the version of Node.js used to run webpack
- Supports automatically-wired sourcemaps
- Tree-shaking to create smaller bundles
- Hot Module Replacement with source-watching during development
- Chunking of external dependencies apart from application code
- Easily extensible to customize your project as needed
Requirements¶
- Node.js v8.3+
- Yarn v1.2.1+, or npm v5.4+
- Neutrino v8
Installation¶
@neutrinojs/node
can be installed via the Yarn or npm clients. Inside your project, make sure
neutrino
and @neutrinojs/node
are development dependencies.
Yarn¶
❯ yarn add --dev neutrino @neutrinojs/node
npm¶
❯ npm install --save-dev neutrino @neutrinojs/node
If you want to have automatically wired sourcemaps added to your project, add source-map-support
:
Yarn¶
❯ yarn add source-map-support
npm¶
❯ npm install --save source-map-support
Project Layout¶
@neutrinojs/node
follows the standard project layout specified by Neutrino. This
means that by default all project source code should live in a directory named src
in the root of the
project. This includes JavaScript files that would be available to your compiled project.
Quickstart¶
The fastest way to get started is by using the create-project
scaffolding tool.
Don’t want to use the CLI helper? No worries, we have you covered with the manual installation.
create-project¶
Run the following command to start the process. Substitute <directory-name>
with the directory name you wish to create
for this project.
Yarn¶
❯ yarn create @neutrinojs/project <directory-name>
Note: The create
command is a shorthand that helps you do two things at once. See the Yarn create docs for more details.
npm/npx¶
npx
comes pre-installed with npm
. If you’re running an older version of npm
, then
npm install -g npm
to update to the latest version.
❯ npx @neutrinojs/create-project <directory-name>
The CLI helper will prompt for the project to scaffold, and will offer to set up a test runner as well as linting to your project. Refer to the Create new project section for details on all available options.
Manual Installation¶
After installing Neutrino and the Node.js preset, add a new directory named src
in the root of the project, with
a single JS file named index.js
in it.
❯ mkdir src && touch src/index.js
Edit your src/index.js
file with the following:
import { createServer } from 'http'; const delay = ms => new Promise(resolve => setTimeout(resolve, ms)); const port = process.env.PORT || 3000; createServer(async (req, res) => { await delay(500); console.log('Request!'); res.end('hi!'); }) .listen(port, () => console.log(`Server running on port ${port}`));
Now edit your project's package.json to add commands for starting and building the application.
{ "scripts": { "start": "neutrino start --use @neutrinojs/node", "build": "neutrino build --use @neutrinojs/node" } }
If you are using .neutrinorc.js
, add this preset to your use array instead of --use
flags:
module.exports = { use: ['@neutrinojs/node'] };
Start the app, then either open a browser to http://localhost:3000 or use curl from another terminal window:
Yarn¶
❯ yarn start
Server running on port 3000
❯ curl http://localhost:3000 hi!
npm¶
❯ npm start
Server running on port 3000
❯ curl http://localhost:3000 hi!
Building¶
@neutrinojs/node
builds assets to the build
directory by default when running neutrino build
. Using the
quick start example above as a reference:
❯ yarn build Hash: 89e4fb250fc535920ba4 Version: webpack 3.5.6 Time: 424ms Asset Size Chunks Chunk Names index.js 4.29 kB 0 [emitted] index index.js.map 3.73 kB 0 [emitted] index ✨ Done in 1.51s.
You can either serve or deploy the contents of this build
directory as a Node.js module, server, or tool. For Node.js
this usually means adding a main
property to package.json pointing to the primary main built entry point. Also when
publishing your project to npm, consider excluding your src
directory by using the files
property to whitelist
build
, or via .npmignore
to blacklist src
.
{ "main": "build/index.js", "files": [ "build" ] }
Note: While this preset works well for many types of Node.js applications, it's important to make the distinction between applications and libraries. This preset will not work optimally out of the box for creating distributable libraries, and will take a little extra customization to make them suitable for that purpose.
Hot Module Replacement¶
While @neutrinojs/node
supports Hot Module Replacement for your app, it does require some application-specific
changes in order to operate. Your application should define split points for which to accept modules to reload using
module.hot
:
For example:
import { createServer } from 'http'; import app from './app'; if (module.hot) { module.hot.accept('./app'); } createServer((req, res) => { res.end(app('example')); }).listen(/* */);
Or for all paths:
import { createServer } from 'http'; import app from './app'; if (module.hot) { module.hot.accept(); } createServer((req, res) => { res.end(app('example')); }).listen(/* */);
Using dynamic imports with import()
will automatically create split points and hot replace those modules upon
modification during development.
Debugging¶
You can start the Node.js server in inspect
mode to debug the process by setting neutrino.options.debug
to true
.
This can be done from the API or the CLI using --debug
.
Preset options¶
You can provide custom options and have them merged with this preset's default options to easily affect how this
preset builds. You can modify Node.js preset settings from .neutrinorc.js
by overriding with an options object. Use
an array pair instead of a string to supply these options in .neutrinorc.js
.
The following shows how you can pass an options object to the Node.js preset and override its options, showing the defaults:
module.exports = { use: [ ['@neutrinojs/node', { // Enables Hot Module Replacement. Set to false to disable hot: true, // Target specific versions via @babel/preset-env targets: { node: '8.3' }, // Remove the contents of the output directory prior to building. // Set to false to disable cleaning this directory clean: { paths: [neutrino.options.output] }, // Add additional Babel plugins, presets, or env options babel: { // Override options for @babel/preset-env, showing defaults: presets: [ ['@babel/preset-env', { // Targets the version of Node.js used to run webpack. targets: { node: 'current' }, modules: false, useBuiltIns: true, }] ] } }] ] };
Example: Override the Node.js Babel compilation target to Node.js v6:
module.exports = { use: [ ['@neutrinojs/node', { // Target specific versions via @babel/preset-env targets: { node: '6.0' } }] ] };
Customizing¶
To override the build configuration, start with the documentation on customization.
@neutrinojs/node
creates some conventions to make overriding the configuration easier once you are ready to make
changes.
By default Neutrino, and therefore this preset, creates a single main index
entry point to your application, and this
maps to the index.*
file in the src
directory. This means that this preset is optimized toward a single main entry
to your application. Code not imported in the hierarchy of the index
entry will not be output to the bundle. To overcome
this you must either define more mains via options.mains
, import
the code path somewhere along the index
hierarchy, or define multiple configurations in your .neutrinorc.js
.
Vendoring¶
This preset automatically vendors all external dependencies into a separate chunk based on their inclusion in your package.json. No extra work is required to make this work.
Rules¶
The following is a list of rules and their identifiers which can be overridden:
Name | Description | Environments and Commands |
---|---|---|
compile |
Compiles JS files from the src directory using Babel. Contains a single loader named babel |
all |
Plugins¶
The following is a list of plugins and their identifiers which can be overridden:
Note: Some plugins are only available in certain environments. To override them, they should be modified conditionally.
Name | Description | Environments and Commands |
---|---|---|
banner |
Injects source-map-support into the mains (entry points) of your application if detected in dependencies or devDependencies of your package.json. |
Only when source-map-support is installed |
clean |
Clears the contents of build prior to creating a production bundle. |
build command |
start-server |
Start a Node.js for the first configured main entry point. | start command |
hot |
Enables Hot Module Replacement. | start command |
Override configuration¶
By following the customization guide and knowing the rule, loader, and plugin IDs above,
you can override and augment the build by by providing a function to your .neutrinorc.js
use array. You can also
make these changes from the Neutrino API in custom middleware.
Example: Allow importing modules with a .esm
extension.
module.exports = { use: [ '@neutrinojs/node', (neutrino) => neutrino.config.resolve.extensions.add('.esm') ] };
Contributing¶
This preset is part of the neutrino-dev repository, a monorepo containing all resources for developing Neutrino and its core presets and middleware. Follow the contributing guide for details.