
By the end of 2015, JavaScript developers had a huge amount of tools at their disposal. In this ecosystem it is easy to get lost, so successful teams follow the rules that were developed, which allow not to waste time and keep projects healthy. Under the cut, the translation of the 2016 article from the Heroku team, in which they talk about the ten habits of web developers who have everything working and nothing hurts. Most likely you already know 80% of what is written - the more interesting it will be to read about the remaining two tricks!
1. Start a new project with the npm init command.
This command will immediately create the correct
package.json based on the name of the project directory and your answers to the wizard questions:
')
$ mkdir my-awesome-app $ cd my-awesome-app $ npm init --yes
Using the
--yes flag allows you not to answer wizard questions, and in the
engines field of the resulting
package.json, you can immediately install the correct version of the node (
node -v ):
"engines": { "node": "4.2.1" }
2. Use "smart" .npmrc
By default,
npm does not write down the installed dependencies in
package.json (and you should always keep track of dependencies!)
If you use the
--save flag to automatically update
package.json , then
npm will save the name of the dependency with the prefix
^ . Semantic versioning puts your dependencies at risk, as with a clean installation, other versions of dependencies may be installed in the project, and who knows what bugs and problems may be in them. This method is good during development, but not in production. One solution is to keep the exact version of the dependency:
$ npm install foobar --save --save-exact
Better yet, change the
npm global settings in
~ / .npmrc so that everything happens automatically:
$ npm config set save=true $ npm config set save-exact=true $ cat ~/.npmrc
With this configuration, installing dependencies will save the exact version and your project will never overtake the creepy “version drift”!
If you prefer the latest versions of dependencies during development, plus a freeze for sales, you can use the
shrinkwrap function. Such a configuration will require a little more effort, but will allow for a more flexible approach to versioning dependencies.
3. Do not miss the outgoing train ES6
Starting with the 4th version of Node.js, you can use many features of ES6. Start using simple and convenient syntax improvements that will make your code simpler and clearer:
let user = users.find(u => u.id === ID); console.log(`Hello, ${ user.name }!`);
4. Stick to lower case
Some languages ​​recommend naming files in the same way as classes. For example, the file implementing
MyClass is proposed to be called
MyClass.js . Do not do so in node. Use lower case:
let MyClass = require('my-class');
Node.js is a rare example of a Linux program with excellent cross-platform support. Although OSX and Windows will treat the
myclass.js and
MyClass.js files
as the same file, Linux will not consider this. If you want to write cross-platform code, you need to name the files in the same register that you use to
require .
The easiest way to do it right is to use lower case, that is,
my-class.js (
translator's note : or
my_class.js , which is still more popular among programmers than css notation).
5. Cluster your application.
Since the node process is limited to one core and one and a half gigabytes of RAM, deploying a nonclustered application to a powerful server is a waste of useful resources. To use multiple cores and a lot of memory, add clustering support to your application. Even if you are now running an application on a single-core vps with gig memory, adding clustering will be a good start for the future.
The best way to find the optimal number of processes is, of course, testing. But for a start, the default value offered by the platform will do. Well, adequate fallback, of course:
const CONCURRENCY = process.env.WEB_CONCURRENCY || 1;
Using clustering allows you to not reinvent the wheel flow control. If you like the separation of files on the “master” and “worker”, then try
forky . If you prefer a single entry point, then
throng .
6. Watch for environment variables.
Use environment variables instead of config files. To do this, install
node-foreman :
$ npm install --save --save-exact foreman
Then create a
Procfile to specify the type of application:
web: bin/web worker: bin/worker
And set the alias to run:
"scripts": { "start": "nf start" }
Now, to change the environment settings, just create (and add to
.gitore ) a file named
.env , which
node-foreman will automatically load:
DATABASE_URL='postgres://localhost/foobar' HTTP_TIMEOUT=10000
With these settings, one
npm start command is enough to start the
web and
worker processes, and then configure settings for them in accordance with the environment variables. This is much easier than 'config / abby-dev.js', 'config / brian-dev.js', 'config / qa1.js', 'config / qa2.js', 'config / prod.js', etc. .
7. Avoid trash.
Node.js (as represented by the V8 engine) uses a “lazy” and “greedy” garbage collector. With a default limit of one and a half gigabytes, it often waits until the last, before freeing up unused memory. If your memory gradually grows, it may not be a leak, but quite regular behavior of the node garbage collector.
For better control of the garbage collector, you can put commands for the V8 engine in
Procfile :
web: node
This is especially important if your application is running on a machine with less than one and a half gigs of available memory. For example, for a container with 512 megabytes of memory, the string of arguments might look like this:
web: node
8. Use hooks
“Lifecycle scripts” in node.js provide extensive automation options. For example, if you need to run something before building the application, you can use the
preinstall script. Need to collect assets using grunt, gulp, browserify or webpack? Use the
postinstall script. All these scripts can be set directly in
package.json :
"scripts": { "postinstall": "bower install && grunt build", "start": "nf start" }
And of course you can use environment variables to control scripts:
"postinstall": "if $BUILD_ASSETS; then npm run build-assets; fi", "build-assets": "bower install && grunt build"
If the scripts are too complex, transfer them to the files:
"postinstall": "scripts/postinstall.sh"
Important : The scripts in
package.json are executed with
./node_modules/.bin automatically added to the
PATH , so you can directly call locally installed npm packages, such as webpack. This allows you not to install packages globally.
9. Only git the important bits
I liked this title so much that I left it without translation. Beautiful play on words - “gut only important bits” = “add only what is important to git”. Most applications consist of two types of files: which can or cannot be generated automatically. When you use a version control system, avoid adding files that can be generated automatically.
For example, your application has a
node_modules directory with established dependencies. Yes, there are people who add it to the version control system! Don't do that. Specifying the necessary dependency versions in
package.json is much more reliable, since
npm install does not clear
node_modules , and if there already are files from the version control system, trouble may happen.
Also adding generated files produces a lot of unnecessary noise in the logs and notifications of your repository. Moreover, some dependencies require compilation during installation, so adding the installed version to the repository makes your application non-portable and can lead to strange errors.
For the same reasons, do not add
bower_components or compiled grunt assets. If in the project the
node_modules directory
has already been added to the version control system, then it can always be removed, for example, like this:
$ echo 'node_modules' >> .gitignore $ git rm -r --cached node_modules $ git commit -am 'ignore node_modules'
Also I usually add npm logs to the blacklist so as not to litter the code:
$ echo 'npm-debug.log' >> .gitignore $ git commit -am 'ignore npm-debug'
Ignoring these less important files, you reduce the size of the repository, simplify commits and do not get merge conflicts.
10. Simplify
Predictions in IT are ungrateful. But I still do one thing. I predict that for JavaScript, 2016 will be a year of simplification.
More and more programmers simplify the architecture of their decisions. Monolithic MVC solutions are replaced by a static frontend, which is so convenient to distribute via CDN, and a Node.js backend for dynamic data.
We also began to notice how complex build systems complicate our projects. At the cutting edge of progress, developers simplify these solutions, in particular, using npm scripts instead of bower, gulp and grunt.
And finally, in 2016, we will simplify the code we write. In some cases, this will be a rejection of unnecessary features, as Douglas Crockford showed in his
The Better Parts . Or, on the contrary, simplification will come from adding new functionality. Like my favorite async and await. They are not in the node yet, but you can always use a transpiler such as BabelJS.
Try not to compete with each other in how many new technologies can be crammed into one project, but focus on simplifying your work.