You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: chapter12/chapter12.md
+41-39Lines changed: 41 additions & 39 deletions
Original file line number
Diff line number
Diff line change
@@ -2,19 +2,19 @@ Chapter 12
2
2
----------
3
3
# Modularizing Your Code and Publishing Node.js Modules to npm
4
4
5
-
One of the key factors that attributed to the rapid growth of the Node.js module ecosystem is its open-source nature and robust packaging systems (with registry). As of April 2013, JavaScript and Node.js had already surpassed any other language/platform in number of packages contributed per year ([source](http://caines.ca/blog/2013/04/13/the-node-dot-js-community-is-quietly-changing-the-face-of-open-source/)):
5
+
Two of the key factors that attributed to the rapid growth of the Node.js module ecosystem are its open-source nature and robust packaging systems (with registry). As of mid 2014, JavaScript and Node.js had surpassed any other language/platform in number of packages contributed per year ([source](http://caines.ca/blog/2013/04/13/the-node-dot-js-community-is-quietly-changing-the-face-of-open-source/)):
6
6
7
-
-Python: 1351 packages per year (29,720 packages in 22 years)
8
-
-Ruby: 3022 packages per year (54,385 packages in 18 years)
9
-
-Node.js: *6742 packages per year* (26,966 packages in 4 years)
7
+
-*Node.js*: *6742 packages per year* (26,966 packages in 4 years)
8
+
-*Python*: 1351 packages per year (29,720 packages in 22 years)
9
+
-*Ruby*: 3022 packages per year (54,385 packages in 18 years)
10
10
11
-
This year’s (2018) numbers are even higher with npm having over 620,000 packages. That's more than half a million! As you can see from the chart take from <http://modulecounts.com>, Node's npm surpassed other platforms' package repositories in absolute numbers. Maven Central (Java) and Packagist (PHP) try to catch up but fail miserably. npm and Node are the top dogs.
11
+
Recent numbers are even higher with npm having over 620,000 packages. That's more than half a million! As you can see from the chart taken from <http://modulecounts.com> (Figure 12-1), Node's npm surpassed other platforms' package repositories in absolute numbers. Maven Central (Java) and Packagist (PHP) try to catch up but fail miserably. npm and Node are the top dogs.
12
12
13
13

14
-
***Figure 12-1.** Node's npm is dominating by the number of modules since mid 2014*
14
+
***Figure 12-1.** Node's npm is dominating by the number of modules since mid 2014.*
15
15
16
16
17
-
Other factors that attribute to the Node.js popularity include:
17
+
Other factors that contribute to the Node.js's popularity include:
18
18
19
19
- Ability to share code between front-end/browser and server-side (with projects such as [browserify](http://browserify.org/) and [ender.js](https://github.com/ender-js/Ender))
20
20
- Philosophy of small (in terms of lines of code and functionality) functional modules vs. large, standard/core packages (i.e., granularity)
@@ -31,7 +31,7 @@ With this in mind, many Node.js enthusiasts find it rewarding to contribute to t
31
31
Recommended Folder Structure
32
32
============================
33
33
34
-
Here is an example of a good, structured npm module in which you have documentation, project manifest, starting file and a folder for dependencies:
34
+
Here is an example of a good, structured npm module in which you have documentation, project manifest, starting file, and a folder for dependencies:
35
35
36
36
```
37
37
webapp
@@ -42,7 +42,7 @@ webapp
42
42
README.md
43
43
```
44
44
45
-
The `index.js` file does the initialization whereas `lib/webapp.js` has all the principal logic.
45
+
The `index.js` file does the initialization, whereas `lib/webapp.js` has all the principal logic.
46
46
47
47
If you’re building a command-line tool, add the `bin` folder:
48
48
@@ -69,24 +69,24 @@ Also, for the CLI module, add the following to `package.json`:
69
69
70
70
The `webapp-cli.js` file starts with the line `#!/usr/bin/env node`, but then has normal Node.js code.
71
71
72
-
It’s a good idea to add unit tests to your external module, which increases confidence and the likelihood of other people using it. Some programmers go as far as not using a module that doesn’t have any tests! The added benefit is that tests serve as a poor man’s examples and
72
+
It’s a good idea to add unit tests to your external module, because it increases confidence and the likelihood of other people using it. Some programmers go as far as not using a module that doesn’t have any tests! The added benefit is that tests serve as a poor man’s examples and
73
73
documentation.
74
74
75
-
TravisCI, which we covered in previous chapters, allows free testing for open-source projects. Its badges, which turn from red to green, depending on the status of tests (failing or passing, became the de facto standard of quality and are often seen on the README pages of the most popular Node.js projects.
75
+
TravisCI, which we covered in previous chapters, allows free testing for open-source projects. Its badges, which turn from red to green, depending on the status of tests (failing or passing), became the de facto standard of quality and are often seen on the README pages of the most popular Node.js projects.
76
76
77
77
Modularizing Patterns
78
78
=================
79
79
80
-
Modularizing is the best practice because you can keep your application flexible and update different part independently of each other. It's totally fine to have bunch of module with only a single function in each one of them. In fact, a lot of module on npm are just that.
80
+
Modularizing is the best practice because you can keep your application flexible and update different parts independently of each other. It's totally fine to have bunch of modules with only a single function in each one of them. In fact, a lot of module on npm are just that—a single function.
81
81
82
-
There are a few common patterns for writing external (meant for use by other users, not just within your app) modules:
82
+
There are a few common patterns for writing external modules (meant for use by other users, not just within your app):
83
83
84
84
-`module.exports` as a function pattern (recommended)
85
85
-`module.exports` as a class pattern (not recommended)
86
86
-`module.exports` as an object pattern
87
-
-`exports.NAME` pattern; which could be an object or a function
87
+
-`exports.NAME` pattern, which could be an object or a function
88
88
89
-
Here is an example of the the `module.exports` as a function pattern:
89
+
Here is an example of the `module.exports` as a function pattern:
90
90
91
91
```js
92
92
let _privateAttribute ='A'
@@ -100,7 +100,7 @@ module.exports = function (options) {
100
100
}
101
101
```
102
102
103
-
And here is an example of an equivalent with a function declaration but this time we used named function which we exported via the global `module.exports`:
103
+
And here is an example of an equivalent with a function declaration, but this time we used named function that we exported via the global `module.exports`:
104
104
105
105
```js
106
106
module.exports= webapp
@@ -111,7 +111,7 @@ function webapp (options) {
111
111
}
112
112
```
113
113
114
-
**Tip** For info about named function expressions vs. function declarations, visit the comprehensive resource [Named function expressions demystified](http://kangax.github.io/nfe/#named-expr).
114
+
**Tip** For info about named function expressions vs. function declarations, refer to Chapter 1.
115
115
116
116
The file in which we include the module looks like this:
117
117
@@ -150,7 +150,7 @@ const wa = new Webapp()
150
150
151
151
The example of this `module.exports` as a class pattern is the OAuth module ([source code](https://github.com/ciaranj/node-oauth/blob/master/lib/oauth.js#L9)).
152
152
153
-
The `module.exports` as an object pattern similar to the first pattern (functional), only without the constructor. It may be useful for defining constants, locales, and other settings:
153
+
The `module.exports` as an object pattern is similar to the first pattern (functional), only without the constructor. It may be useful for defining constants, locales, and other settings:
154
154
155
155
```js
156
156
module.exports= {
@@ -172,7 +172,7 @@ const http = require('http')
172
172
http.globalAgent.maxSockets=webapp.sockets
173
173
```
174
174
175
-
**Note** The `require` method can read JSON files directly. The main difference is that JSON standard has mandatory double quotes (`"`) for wrapping property names.
175
+
**Note** The `require` method can read JSON files directly. The main difference is that the JSON standard has the mandatory double quotes (`"`) for wrapping property names.
176
176
177
177
The `exports.NAME` pattern is just a shortcut for `module.exports.NAME` when there’s no need for one constructor method. For example, we can have multiple routes defined this way:
178
178
@@ -222,11 +222,11 @@ Another mandatory part of an npm module is its `package.json` file. The easiest
222
222
}
223
223
```
224
224
225
-
The most important fields are `name` and `version`. The others are optional and self-explanatory, by name. The full list of supported keys is located at [the npm web site](https://www.npmjs.org/doc/json.html).
225
+
The most important fields are `name` and `version`. The others are optional and self-explanatory, by name. The full list of supported keys is located at [the npm web site](https://www.npmjs.org/doc/json.html): <https://www.npmjs.org/doc/json.html>.
226
226
227
227
**Warning**`package.json` must have double quotes around values and property names, unlike native JavaScript object literals.
228
228
229
-
Important feature which will benefit all projects (and more so large projects) is npm scripts. See that `scripts` property in the `package.json` file? Inside of it developers can define any commands which act as aliases. The left part is the alias and the right part (after the `:` colon) is the actual command:
229
+
npm scripts is an important feature that benefits all projects and more so large one. See that `scripts` property in the `package.json` file? Inside of it developers can define any commands, which act as aliases. The left part is the alias, and the right part (after the `:` colon) is the actual command:
230
230
231
231
```json
232
232
"scripts": {
@@ -238,7 +238,7 @@ Important feature which will benefit all projects (and more so large projects) i
238
238
}
239
239
```
240
240
241
-
To run the command, you use `npm run NAME`, e.g., `npm run build` or `npm run deploy`. The two names are special. The don't need `run`. They are `test` and `start`. That is to execute test or start, simply use `npm test` and `npm start`.
241
+
To run the command, you use `npm run NAME`, e.g., `npm run build` or `npm run deploy`. The two names are special. The don't need `run`. They are `test` and `start`. That is to execute `test` or `start`, simply use `npm test` and `npm start`.
242
242
243
243
It's possible to call other npm scripts from the right side (the values):
244
244
@@ -250,7 +250,7 @@ It's possible to call other npm scripts from the right side (the values):
250
250
}
251
251
```
252
252
253
-
Lastly, there are post and pre hook for each npm script. They are defined as pre and post prefixes to the names. For example, if I always want to build after the installation, I can set up `postinstall`:
253
+
Lastly, there are `post` and `pre` hooks for each npm script. They are defined as pre and post prefixes to the names. For example, if I always want to build after the installation, I can set up `postinstall`:
254
254
255
255
```json
256
256
"scripts": {
@@ -259,48 +259,50 @@ Lastly, there are post and pre hook for each npm script. They are defined as pre
259
259
}
260
260
```
261
261
262
-
npm scripts are very powerful. Some Node developers are even abandoning their build tools such as Grunt or Gulp or Webpack and implement their build pipelines with npm scripts and some low-level Node code. I sort of agree with them. Having to learn and depend on myriads of Grunt, Gulp or Webpack plugins is no fun. For more use cases of npm scripts, start at this page: <https://docs.npmjs.com/misc/scripts>.
262
+
npm scripts are very powerful. Some Node developers are even abandoning their build tools, such as Grunt or Gulp or Webpack, and implementing their build pipelines with npm scripts and some low-level Node code. I sort of agree with them. Having to learn and depend on myriads of Grunt, Gulp, or Webpack plugins is no fun. For more use cases of npm scripts, start at this page: <https://docs.npmjs.com/misc/scripts>.
263
263
264
264
It’s worth noting that `package.json` and npm do not limit their use. In other words, you are encouraged to add custom fields and devise new conventions for their cases.
265
265
266
266
Publishing to npm
267
267
=================
268
268
269
-
To publish to npm, we must have an account there. So first you need to proceed to the website npmjs.org and register there. Once you do that, you will have an account which mean you will have a username and password. The next step is to sign in on the command line. We do this by executing the following:
269
+
To publish to npm, you must have an account there. So first, you need to proceed to the website npmjs.org and register there. Once you do that, you will have an account, and you will have a username and password. The next step is to sign in on the command line. Do this by executing the following:
270
270
271
271
```
272
272
$ npm adduser
273
273
```
274
274
275
-
You just need to sign in with the npm CLI once. After you do it you are read to publish as many time as you wish. To publish a new module or an update to an already published module, simply execute from the project folder:
275
+
You just need to sign in with the npm CLI once. After you do it, you are read to publish as many times as you wish. To publish a new module or an update to an already published module, simply execute the following command from the module/package project folder:
276
276
277
277
```
278
278
$ npm publish
279
279
```
280
280
281
281
Some useful npm commands are as follows:
282
282
283
-
-`$ npm tag NAME@VERSION TAG`: tag a version
284
-
-`$ npm version SEMVERSION`: increment a version to the value of `SEMVERSION` ([semver](http://semver.org/)) and update `package.json`
285
-
-`$ npm version patch`: increment the last number in a version (e.g., 0.0.1 to 0.0.2) and update `package.json`
286
-
-`$ npm version minor`: increment a middle version number (e.g., 0.0.1 to 0.1.0 or 0.0.1 to 1.0.0) and update `package.json`
287
-
-`$ npm unpublish PACKAGE_NAME`: unpublish package from npm (take optional version with `@`)
288
-
-`$ npm owner ls PACKAGE_NAME`: list owners of this package
289
-
-`$ npm owner add USER PACKAGE_NAME`: add an owner
290
-
-`$ npm owner rm USER PACKAGE_NAME`: remove an owner
283
+
-`$ npm tag NAME@VERSION TAG`: Tag a version
284
+
-`$ npm version SEMVERSION`: Increment a version to the value of `SEMVERSION` ([semver](http://semver.org/)) and update `package.json`
285
+
-`$ npm version patch`: Increment the last number in a version (e.g., 0.0.1 to 0.0.2) and update `package.json`
286
+
-`$ npm version minor`: Increment a middle version number (e.g., 0.0.1 to 0.1.0 or 0.0.1 to 1.0.0) and update `package.json`
287
+
-`$ npm unpublish PACKAGE_NAME`: Unpublish package from npm (take optional version with `@`)
288
+
-`$ npm owner ls PACKAGE_NAME`: List owners of this package
289
+
-`$ npm owner add USER PACKAGE_NAME`: Add an owner
290
+
-`$ npm owner rm USER PACKAGE_NAME`: Remove an owner
291
291
292
292
Not-Locking Versions
293
293
================
294
294
295
-
The rule of thumb is that when we publish external modules, we don’t lock dependencies’ versions. However, when we deploy apps, we lock versions in `package.json`. You can ready more on why and how lock version in projects which are applications (i.e., not npm modules) in chapter 10. Then why not lock versions in the modules?
295
+
The rule of thumb is that when we publish external modules, we don’t lock dependencies’ versions. However, when we deploy apps, we lock versions in `package.json`. You can read more on why and how lock versions in projects that are applications (i.e., not npm modules) in Chapter 10.
296
296
297
-
The answer is that open source is often a part-time gig and an after thought for most people. It's not like you'll make millions and can spend 40 hours per week on your FOSS npm module. Let's say there's a security vulnerability or a something is outdated in a dependency of your npm module. Most likely, you'll be patching your app which is your main full-time daily job and not patching this poor little npm module. That's why it's a good idea no NOT lock the version but let it use a caret symbol `^` which means the patches will be updated in dependencies.
297
+
Then why not lock versions in the modules? The answer is that open source is often a part-time gig and an afterthought for most people. It's not like you'll make millions and can spend 40 hours per week on your FOSS npm module.
298
298
299
-
Yes. If someone depends on your npm module, they might get a bug when it pulls a newer dependency but the trade off worth it. Your module will have latest dependencies automatically without requiring your attention (the next time someone installs your module).
299
+
Let's say there's a security vulnerability or something is outdated in a dependency of your npm module. Most likely, you'll be patching your app that is your main full-time daily job, and not patching this poor little npm module. That's why it's a good idea to NOT lock the version but let it use a caret symbol `^`, which means the patches will be updated in dependencies.
300
300
301
-
That's the main reason why almost all popular npm modules such as Express, Webpack, and React do have `^` in package.json ([source](https://github.com/expressjs/express/blob/master/package.json), [source](https://github.com/webpack/webpack/blob/master/package.json) and [source](https://github.com/facebook/react/blob/master/package.json)).
301
+
Yes. If someone depends on your npm module, they may get a bug when it pulls a newer dependency, but the tradeoff is worth it. Your module will have the latest dependencies automatically, without requiring your attention (the next time someone installs your module).
302
+
303
+
That's the main reason why almost all popular npm modules such as Express, Webpack, and React do have `^` in package.json (<https://github.com/expressjs/express/blob/master/package.json>, <https://github.com/webpack/webpack/blob/master/package.json> and <https://github.com/facebook/react/blob/master/package.json>).
302
304
303
305
Summary
304
306
=======
305
307
306
-
Open-source factors have contributed to the success and widespread use of the Node.js platform. It’s relatively easy to publish a module and make a name for yourself (unlike other mature platforms with solid cores). We looked at the recommended patterns and structures, and explored a few commands to get started with publishing modules to npm.
308
+
Opensource factors have contributed to the success and widespread use of the Node.js platform. It’s relatively easy to publish a module and make a name for yourself (unlike other mature platforms with solid cores). We looked at the recommended patterns and structures, and explored a few commands to get started with publishing modules to npm.
0 commit comments