1 | # Neutrino Node.js Preset
|
2 |
|
3 | `@neutrinojs/node` is a Neutrino preset that supports building Node.js applications.
|
4 |
|
5 | [![NPM version][npm-image]][npm-url]
|
6 | [![NPM downloads][npm-downloads]][npm-url]
|
7 | [![Join the Neutrino community on Spectrum][spectrum-image]][spectrum-url]
|
8 |
|
9 | ## Features
|
10 |
|
11 | - Zero upfront configuration necessary to start developing and building a Node.js project
|
12 | - Modern Babel compilation supporting ES modules, Node.js 6.10+, async functions, and dynamic imports
|
13 | - Supports automatically-wired sourcemaps
|
14 | - Tree-shaking to create smaller bundles
|
15 | - Hot Module Replacement with source-watching during development
|
16 | - Chunking of external dependencies apart from application code
|
17 | - Easily extensible to customize your project as needed
|
18 |
|
19 | ## Requirements
|
20 |
|
21 | - Node.js v6 LTS, v8, v9
|
22 | - Yarn v1.2.1+, or npm v5.4+
|
23 | - Neutrino v8
|
24 |
|
25 | ## Installation
|
26 |
|
27 | `@neutrinojs/node` can be installed via the Yarn or npm clients. Inside your project, make sure
|
28 | `neutrino` and `@neutrinojs/node` are development dependencies.
|
29 |
|
30 | #### Yarn
|
31 |
|
32 | ```bash
|
33 | ❯ yarn add --dev neutrino @neutrinojs/node
|
34 | ```
|
35 |
|
36 | #### npm
|
37 |
|
38 | ```bash
|
39 | ❯ npm install --save-dev neutrino @neutrinojs/node
|
40 | ```
|
41 |
|
42 | If you want to have automatically wired sourcemaps added to your project, add `source-map-support`:
|
43 |
|
44 | #### Yarn
|
45 |
|
46 | ```bash
|
47 | ❯ yarn add source-map-support
|
48 | ```
|
49 |
|
50 | #### npm
|
51 |
|
52 | ```bash
|
53 | ❯ npm install --save source-map-support
|
54 | ```
|
55 |
|
56 | ## Project Layout
|
57 |
|
58 | `@neutrinojs/node` follows the standard [project layout](https://neutrino.js.org/project-layout) specified by Neutrino. This
|
59 | means that by default all project source code should live in a directory named `src` in the root of the
|
60 | project. This includes JavaScript files that would be available to your compiled project.
|
61 |
|
62 | ## Quickstart
|
63 |
|
64 | The fastest way to get started is by using the `create-project` scaffolding tool.
|
65 | Don’t want to use the CLI helper? No worries, we have you covered with the [manual installation](#manual-installation).
|
66 |
|
67 | ### create-project
|
68 |
|
69 | Run the following command to start the process. Substitute `<directory-name>` with the directory name you wish to create
|
70 | for this project.
|
71 |
|
72 |
|
73 | #### Yarn
|
74 |
|
75 | ```
|
76 | ❯ yarn create @neutrinojs/project <directory-name>
|
77 | ```
|
78 |
|
79 | _Note: The `create` command is a shorthand that helps you do two things at once. See the [Yarn create docs](https://yarnpkg.com/lang/en/docs/cli/create) for more details._
|
80 |
|
81 | #### npm/npx
|
82 |
|
83 | [`npx`](https://github.com/zkat/npx) comes pre-installed with `npm`. If you’re running an older version of `npm`, then
|
84 | `npm install -g npm` to update to the latest version.
|
85 |
|
86 | ```
|
87 | ❯ npx @neutrinojs/create-project <directory-name>
|
88 | ```
|
89 |
|
90 | The CLI helper will prompt for the project to scaffold, and will offer to set
|
91 | up a test runner as well as linting to your project. Refer to the [Create new project](../create-project) section
|
92 | for details on all available options.
|
93 |
|
94 | ### Manual Installation
|
95 |
|
96 | After installing Neutrino and the Node.js preset, add a new directory named `src` in the root of the project, with
|
97 | a single JS file named `index.js` in it.
|
98 |
|
99 | ```bash
|
100 | ❯ mkdir src && touch src/index.js
|
101 | ```
|
102 |
|
103 | Edit your `src/index.js` file with the following:
|
104 |
|
105 | ```js
|
106 | import { createServer } from 'http';
|
107 |
|
108 | const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
|
109 | const port = process.env.PORT || 3000;
|
110 |
|
111 | createServer(async (req, res) => {
|
112 | await delay(500);
|
113 | console.log('Request!');
|
114 | res.end('hi!');
|
115 | })
|
116 | .listen(port, () => console.log(`Server running on port ${port}`));
|
117 | ```
|
118 |
|
119 | Now edit your project's package.json to add commands for starting and building the application.
|
120 |
|
121 | ```json
|
122 | {
|
123 | "scripts": {
|
124 | "start": "neutrino start --use @neutrinojs/node",
|
125 | "build": "neutrino build --use @neutrinojs/node"
|
126 | }
|
127 | }
|
128 | ```
|
129 |
|
130 | If you are using `.neutrinorc.js`, add this preset to your use array instead of `--use` flags:
|
131 |
|
132 | ```js
|
133 | module.exports = {
|
134 | use: ['@neutrinojs/node']
|
135 | };
|
136 | ```
|
137 |
|
138 | Start the app, then either open a browser to http://localhost:3000 or use curl from another terminal window:
|
139 |
|
140 | #### Yarn
|
141 |
|
142 | ```bash
|
143 | ❯ yarn start
|
144 | Server running on port 3000
|
145 | ```
|
146 |
|
147 | ```bash
|
148 | ❯ curl http://localhost:3000
|
149 | hi!
|
150 | ```
|
151 |
|
152 | #### npm
|
153 |
|
154 | ```bash
|
155 | ❯ npm start
|
156 | Server running on port 3000
|
157 | ```
|
158 |
|
159 | ```bash
|
160 | ❯ curl http://localhost:3000
|
161 | hi!
|
162 | ```
|
163 |
|
164 | ## Building
|
165 |
|
166 | `@neutrinojs/node` builds assets to the `build` directory by default when running `neutrino build`. Using the
|
167 | quick start example above as a reference:
|
168 |
|
169 | ```bash
|
170 | ❯ yarn build
|
171 |
|
172 | Hash: 89e4fb250fc535920ba4
|
173 | Version: webpack 3.5.6
|
174 | Time: 424ms
|
175 | Asset Size Chunks Chunk Names
|
176 | index.js 4.29 kB 0 [emitted] index
|
177 | index.js.map 3.73 kB 0 [emitted] index
|
178 | ✨ Done in 1.51s.
|
179 | ```
|
180 |
|
181 | You can either serve or deploy the contents of this `build` directory as a Node.js module, server, or tool. For Node.js
|
182 | this usually means adding a `main` property to package.json pointing to the primary main built entry point. Also when
|
183 | publishing your project to npm, consider excluding your `src` directory by using the `files` property to whitelist
|
184 | `build`, or via `.npmignore` to blacklist `src`.
|
185 |
|
186 | ```json
|
187 | {
|
188 | "main": "build/index.js",
|
189 | "files": [
|
190 | "build"
|
191 | ]
|
192 | }
|
193 | ```
|
194 |
|
195 | _Note: While this preset works well for many types of Node.js applications, it's important to make the distinction
|
196 | between applications and libraries. This preset will not work optimally out of the box for creating distributable
|
197 | libraries, and will take a little extra customization to make them suitable for that purpose._
|
198 |
|
199 | ## Hot Module Replacement
|
200 |
|
201 | While `@neutrinojs/node` supports Hot Module Replacement for your app, it does require some application-specific
|
202 | changes in order to operate. Your application should define split points for which to accept modules to reload using
|
203 | `module.hot`:
|
204 |
|
205 | For example:
|
206 |
|
207 | ```js
|
208 | import { createServer } from 'http';
|
209 | import app from './app';
|
210 |
|
211 | if (module.hot) {
|
212 | module.hot.accept('./app');
|
213 | }
|
214 |
|
215 | createServer((req, res) => {
|
216 | res.end(app('example'));
|
217 | }).listen(/* */);
|
218 | ```
|
219 |
|
220 | Or for all paths:
|
221 |
|
222 | ```js
|
223 | import { createServer } from 'http';
|
224 | import app from './app';
|
225 |
|
226 | if (module.hot) {
|
227 | module.hot.accept();
|
228 | }
|
229 |
|
230 | createServer((req, res) => {
|
231 | res.end(app('example'));
|
232 | }).listen(/* */);
|
233 | ```
|
234 |
|
235 | Using dynamic imports with `import()` will automatically create split points and hot replace those modules upon
|
236 | modification during development.
|
237 |
|
238 | ## Debugging
|
239 |
|
240 | You can start the Node.js server in `inspect` mode to debug the process by setting `neutrino.options.debug` to `true`.
|
241 | This can be done from the [API](https://neutrino.js.org/api#optionsdebug) or the [CLI using `--debug`](https://neutrino.js.org/cli#-debug).
|
242 |
|
243 | ## Preset options
|
244 |
|
245 | You can provide custom options and have them merged with this preset's default options to easily affect how this
|
246 | preset builds. You can modify Node.js preset settings from `.neutrinorc.js` by overriding with an options object. Use
|
247 | an array pair instead of a string to supply these options in `.neutrinorc.js`.
|
248 |
|
249 | The following shows how you can pass an options object to the Node.js preset and override its options, showing the
|
250 | defaults:
|
251 |
|
252 | ```js
|
253 | module.exports = {
|
254 | use: [
|
255 | ['@neutrinojs/node', {
|
256 | // Enables Hot Module Replacement. Set to false to disable
|
257 | hot: true,
|
258 |
|
259 | polyfills: {
|
260 | // Enables fast-async polyfill. Set to false to disable
|
261 | async: true
|
262 | },
|
263 |
|
264 | // Target specific versions via babel-preset-env
|
265 | targets: {
|
266 | node: '6.10'
|
267 | },
|
268 |
|
269 | // Remove the contents of the output directory prior to building.
|
270 | // Set to false to disable cleaning this directory
|
271 | clean: {
|
272 | paths: [neutrino.options.output]
|
273 | },
|
274 |
|
275 | // Add additional Babel plugins, presets, or env options
|
276 | babel: {
|
277 | // Override options for babel-preset-env, showing defaults:
|
278 | presets: [
|
279 | ['babel-preset-env', {
|
280 | targets: { node: '6.10' },
|
281 | modules: false,
|
282 | useBuiltIns: true,
|
283 | // These are excluded when using polyfills.async. Disabling the async polyfill
|
284 | // will remove these from the exclusion list
|
285 | exclude: ['transform-regenerator', 'transform-async-to-generator']
|
286 | }]
|
287 | ]
|
288 | }
|
289 | }]
|
290 | ]
|
291 | };
|
292 | ```
|
293 |
|
294 | _Example: Override the Node.js Babel compilation target to Node.js v8:_
|
295 |
|
296 | ```js
|
297 | module.exports = {
|
298 | use: [
|
299 | ['@neutrinojs/node', {
|
300 | // Add additional Babel plugins, presets, or env options
|
301 | babel: {
|
302 | // Override options for babel-preset-env
|
303 | presets: [
|
304 | ['babel-preset-env', {
|
305 | // Passing in targets to babel-preset-env will replace them
|
306 | // instead of merging them
|
307 | targets: {
|
308 | node: '8.0'
|
309 | }
|
310 | }]
|
311 | ]
|
312 | }
|
313 | }]
|
314 | ]
|
315 | };
|
316 | ```
|
317 |
|
318 | ## Customizing
|
319 |
|
320 | To override the build configuration, start with the documentation on [customization](https://neutrino.js.org/customization).
|
321 | `@neutrinojs/node` creates some conventions to make overriding the configuration easier once you are ready to make
|
322 | changes.
|
323 |
|
324 | By default Neutrino, and therefore this preset, creates a single **main** `index` entry point to your application, and this
|
325 | maps to the `index.*` file in the `src` directory. This means that this preset is optimized toward a single main entry
|
326 | to your application. Code not imported in the hierarchy of the `index` entry will not be output to the bundle. To overcome
|
327 | this you must either define more mains via [`options.mains`](https://neutrino.js.org/customization#optionsmains), import
|
328 | the code path somewhere along the `index` hierarchy, or define multiple configurations in your `.neutrinorc.js`.
|
329 |
|
330 | ### Vendoring
|
331 |
|
332 | This preset automatically vendors all external dependencies into a separate chunk based on their inclusion in your
|
333 | package.json. No extra work is required to make this work.
|
334 |
|
335 | ### Rules
|
336 |
|
337 | The following is a list of rules and their identifiers which can be overridden:
|
338 |
|
339 | | Name | Description | Environments and Commands |
|
340 | | --- | --- | --- |
|
341 | | `compile` | Compiles JS files from the `src` directory using Babel. Contains a single loader named `babel` | all |
|
342 |
|
343 | ### Plugins
|
344 |
|
345 | The following is a list of plugins and their identifiers which can be overridden:
|
346 |
|
347 | _Note: Some plugins are only available in certain environments. To override them, they should be modified conditionally._
|
348 |
|
349 | | Name | Description | Environments and Commands |
|
350 | | --- | --- | --- |
|
351 | | `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 |
|
352 | | `copy` | Copies all files from `src/static` to `build` when using `neutrino build`. | `build` command |
|
353 | | `clean` | Clears the contents of `build` prior to creating a production bundle. | `build` command |
|
354 | | `start-server` | Start a Node.js for the first configured main entry point. | `start` command |
|
355 | | `hot` | Enables Hot Module Replacement. | `start` command |
|
356 | | `named-modules` | Enables named modules for improved debugging and console output. From `@neutrinojs/hot`. | `start` command |
|
357 | | `module-concat` | Concatenate the scope of all your modules into one closure and allow for your code to have a faster execution time in the browser. | `NODE_ENV production` |
|
358 |
|
359 | ### Override configuration
|
360 |
|
361 | By following the [customization guide](https://neutrino.js.org/customization) and knowing the rule, loader, and plugin IDs above,
|
362 | you can override and augment the build by by providing a function to your `.neutrinorc.js` use array. You can also
|
363 | make these changes from the Neutrino API in custom middleware.
|
364 |
|
365 | _Example: Allow importing modules with a `.esm` extension._
|
366 |
|
367 | ```js
|
368 | module.exports = {
|
369 | use: [
|
370 | '@neutrinojs/node',
|
371 | (neutrino) => neutrino.config.resolve.extensions.add('.esm')
|
372 | ]
|
373 | };
|
374 | ```
|
375 |
|
376 | ## Contributing
|
377 |
|
378 | This preset is part of the [neutrino-dev](https://github.com/mozilla-neutrino/neutrino-dev) repository, a monorepo
|
379 | containing all resources for developing Neutrino and its core presets and middleware. Follow the
|
380 | [contributing guide](https://neutrino.js.org/contributing) for details.
|
381 |
|
382 | [npm-image]: https://img.shields.io/npm/v/@neutrinojs/node.svg
|
383 | [npm-downloads]: https://img.shields.io/npm/dt/@neutrinojs/node.svg
|
384 | [npm-url]: https://npmjs.org/package/@neutrinojs/node
|
385 | [spectrum-image]: https://withspectrum.github.io/badge/badge.svg
|
386 | [spectrum-url]: https://spectrum.chat/neutrino
|