:white_check_mark: The Node.js best practices list (March 2021)

Overview

Node.js Best Practices

Node.js Best Practices


102 items Last update: March 27, 2021 Updated for Node 14.0.0

nodepractices Follow us on Twitter! @nodepractices


Read in a different language: CNCN, BRBR, RURU, PLPL, JAJA, EUEU (ESES, FRFR, HEHE, KRKR and TRTR in progress! )


Built and maintained by our Steering Committee and Collaborators

Latest Best Practices and News

  • EU Basque translation!: wow even our Basque readers can read in their mother-tongue language! Courtesy of Ane Diaz de Tuesta who did this all by her self

  • ๐Ÿ‡ฏ๐Ÿ‡ต Japanese translation: Our guide is now also translated to Japanese! Courtesy of the amazing YukiOta and Yuta Azumi

  • ๐ŸŽŠ 60,000 stars!: Our repo was starred and trusted by 60,100 developers. We're speechless



Welcome! 3 Things You Ought To Know First

1. You are reading dozens of the best Node.js articles - this repository is a summary and curation of the top-ranked content on Node.js best practices, as well as content written here by collaborators

2. It is the largest compilation, and it is growing every week - currently, more than 80 best practices, style guides, and architectural tips are presented. New issues and pull requests are created every day to keep this live book updated. We'd love to see you contributing here, whether that is fixing code mistakes, helping with translations, or suggesting brilliant new ideas. See our writing guidelines here

3. Best practices have additional info - most bullets include a ๐Ÿ”— Read More link that expands on the practice with code examples, quotes from selected blogs, and more information



Table of Contents

  1. Project Structure Practices (5)
  2. Error Handling Practices (12)
  3. Code Style Practices (12)
  4. Testing And Overall Quality Practices (13)
  5. Going To Production Practices (19)
  6. Security Practices (25)
  7. Performance Practices (2) (Work In Progress๏ธ โœ๏ธ )
  8. Docker Practices (15)



1. Project Structure Practices

โœ” 1.1 Structure your solution by components

TL;DR: The worst large applications pitfall is maintaining a huge code base with hundreds of dependencies - such a monolith slows down developers as they try to incorporate new features. Instead, partition your code into components, each gets its folder or a dedicated codebase, and ensure that each unit is kept small and simple. Visit 'Read More' below to see examples of correct project structure

Otherwise: When developers who code new features struggle to realize the impact of their change and fear to break other dependent components - deployments become slower and riskier. It's also considered harder to scale-out when all the business units are not separated

๐Ÿ”— Read More: structure by components



โœ” 1.2 Layer your components, keep the web layer within its boundaries

TL;DR: Each component should contain 'layers' - a dedicated object for the web, logic, and data access code. This not only draws a clean separation of concerns but also significantly eases mocking and testing the system. Though this is a very common pattern, API developers tend to mix layers by passing the web layer objects (e.g. Express req, res) to business logic and data layers - this makes your application dependent on and accessible only by specific web frameworks

Otherwise: App that mixes web objects with other layers cannot be accessed by testing code, CRON jobs, triggers from message queues, etc

๐Ÿ”— Read More: layer your app



โœ” 1.3 Wrap common utilities as npm packages

TL;DR: In a large app that constitutes a large codebase, cross-cutting-concern utilities like a logger, encryption and alike, should be wrapped by your code and exposed as private npm packages. This allows sharing them among multiple codebases and projects

Otherwise: You'll have to invent your deployment and the dependency wheel

๐Ÿ”— Read More: Structure by feature



โœ” 1.4 Separate Express 'app' and 'server'

TL;DR: Avoid the nasty habit of defining the entire Express app in a single huge file - separate your 'Express' definition to at least two files: the API declaration (app.js) and the networking concerns (WWW). For even better structure, locate your API declaration within components

Otherwise: Your API will be accessible for testing via HTTP calls only (slower and much harder to generate coverage reports). It probably won't be a big pleasure to maintain hundreds of lines of code in a single file

๐Ÿ”— Read More: separate Express 'app' and 'server'



โœ” 1.5 Use environment aware, secure and hierarchical config

TL;DR: A perfect and flawless configuration setup should ensure (a) keys can be read from file AND from environment variable (b) secrets are kept outside committed code (c) config is hierarchical for easier findability. There are a few packages that can help tick most of those boxes like rc, nconf, config, and convict.

Otherwise: Failing to satisfy any of the config requirements will simply bog down the development or DevOps team. Probably both

๐Ÿ”— Read More: configuration best practices




โฌ† Return to top

2. Error Handling Practices

โœ” 2.1 Use Async-Await or promises for async error handling

TL;DR: Handling async errors in callback style is probably the fastest way to hell (a.k.a the pyramid of doom). The best gift you can give to your code is using a reputable promise library or async-await instead which enables a much more compact and familiar code syntax like try-catch

Otherwise: Node.js callback style, function(err, response), is a promising way to un-maintainable code due to the mix of error handling with casual code, excessive nesting, and awkward coding patterns

๐Ÿ”— Read More: avoiding callbacks



โœ” 2.2 Use only the built-in Error object

TL;DR: Many throw errors as a string or as some custom type โ€“ this complicates the error handling logic and the interoperability between modules. Whether you reject a promise, throw an exception or emit an error โ€“ using only the built-in Error object (or an object that extends the built-in Error object) will increase uniformity and prevent loss of information. There is no-throw-literal ESLint rule that strictly checks that (although it have some limitations which can be solved when using TypeScript and setting the @typescript-eslint/no-throw-literal rule)

Otherwise: When invoking some component, being uncertain which type of errors come in return โ€“ it makes proper error handling much harder. Even worse, using custom types to describe errors might lead to loss of critical error information like the stack trace!

๐Ÿ”— Read More: using the built-in error object



โœ” 2.3 Distinguish operational vs programmer errors

TL;DR: Operational errors (e.g. API received an invalid input) refer to known cases where the error impact is fully understood and can be handled thoughtfully. On the other hand, programmer error (e.g. trying to read an undefined variable) refers to unknown code failures that dictate to gracefully restart the application

Otherwise: You may always restart the application when an error appears, but why let ~5000 online users down because of a minor, predicted, operational error? the opposite is also not ideal โ€“ keeping the application up when an unknown issue (programmer error) occurred might lead to an unpredicted behavior. Differentiating the two allows acting tactfully and applying a balanced approach based on the given context

๐Ÿ”— Read More: operational vs programmer error



โœ” 2.4 Handle errors centrally, not within a middleware

TL;DR: Error handling logic such as mail to admin and logging should be encapsulated in a dedicated and centralized object that all endpoints (e.g. Express middleware, cron jobs, unit-testing) call when an error comes in

Otherwise: Not handling errors within a single place will lead to code duplication and probably to improperly handled errors

๐Ÿ”— Read More: handling errors in a centralized place



โœ” 2.5 Document API errors using Swagger or GraphQL

TL;DR: Let your API callers know which errors might come in return so they can handle these thoughtfully without crashing. For RESTful APIs, this is usually done with documentation frameworks like Swagger. If you're using GraphQL, you can utilize your schema and comments as well.

Otherwise: An API client might decide to crash and restart only because it received back an error it couldnโ€™t understand. Note: the caller of your API might be you (very typical in a microservice environment)

๐Ÿ”— Read More: documenting API errors in Swagger or GraphQL



โœ” 2.6 Exit the process gracefully when a stranger comes to town

TL;DR: When an unknown error occurs (a developer error, see best practice 2.3) - there is uncertainty about the application healthiness. Common practice suggests restarting the process carefully using a process management tool like Forever or PM2

Otherwise: When an unfamiliar exception occurs, some object might be in a faulty state (e.g. an event emitter which is used globally and not firing events anymore due to some internal failure) and all future requests might fail or behave crazily

๐Ÿ”— Read More: shutting the process



โœ” 2.7 Use a mature logger to increase error visibility

TL;DR: A set of mature logging tools like Pino or Log4js, will speed-up error discovery and understanding. So forget about console.log

Otherwise: Skimming through console.logs or manually through messy text file without querying tools or a decent log viewer might keep you busy at work until late

๐Ÿ”— Read More: using a mature logger



โœ” 2.8 Test error flows using your favorite test framework

TL;DR: Whether professional automated QA or plain manual developer testing โ€“ Ensure that your code not only satisfies positive scenarios but also handles and returns the right errors. Testing frameworks like Mocha & Chai can handle this easily (see code examples within the "Gist popup")

Otherwise: Without testing, whether automatically or manually, you canโ€™t rely on your code to return the right errors. Without meaningful errors โ€“ thereโ€™s no error handling

๐Ÿ”— Read More: testing error flows



โœ” 2.9 Discover errors and downtime using APM products

TL;DR: Monitoring and performance products (a.k.a APM) proactively gauge your codebase or API so they can automagically highlight errors, crashes, and slow parts that you were missing

Otherwise: You might spend great effort on measuring API performance and downtimes, probably youโ€™ll never be aware which are your slowest code parts under real-world scenario and how these affect the UX

๐Ÿ”— Read More: using APM products



โœ” 2.10 Catch unhandled promise rejections

TL;DR: Any exception thrown within a promise will get swallowed and discarded unless a developer didnโ€™t forget to explicitly handle it. Even if your code is subscribed to process.uncaughtException! Overcome this by registering to the event process.unhandledRejection

Otherwise: Your errors will get swallowed and leave no trace. Nothing to worry about

๐Ÿ”— Read More: catching unhandled promise rejection



โœ” 2.11 Fail fast, validate arguments using a dedicated library

TL;DR: Assert API input to avoid nasty bugs that are much harder to track later. The validation code is usually tedious unless you are using a very cool helper library like ajv and Joi

Otherwise: Consider this โ€“ your function expects a numeric argument โ€œDiscountโ€ which the caller forgets to pass, later on, your code checks if Discount!=0 (amount of allowed discount is greater than zero), then it will allow the user to enjoy a discount. OMG, what a nasty bug. Can you see it?

๐Ÿ”— Read More: failing fast



โœ” 2.12 Always await promises before returning to avoid a partial stacktrace

TL;DR: Always do return await when returning a promise to benefit full error stacktrace. If a function returns a promise, that function must be declared as async function and explicitly await the promise before returning it

Otherwise: The function that returns a promise without awaiting won't appear in the stacktrace. Such missing frames would probably complicate the understanding of the flow that leads to the error, especially if the cause of the abnormal behavior is inside of the missing function

๐Ÿ”— Read More: returning promises




โฌ† Return to top

3. Code Style Practices

โœ” 3.1 Use ESLint

TL;DR: ESLint is the de-facto standard for checking possible code errors and fixing code style, not only to identify nitty-gritty spacing issues but also to detect serious code anti-patterns like developers throwing errors without classification. Though ESLint can automatically fix code styles, other tools like prettier and beautify are more powerful in formatting the fix and work in conjunction with ESLint

Otherwise: Developers will focus on tedious spacing and line-width concerns and time might be wasted overthinking the project's code style

๐Ÿ”— Read More: Using ESLint and Prettier



โœ” 3.2 Node.js specific plugins

TL;DR: On top of ESLint standard rules that cover vanilla JavaScript, add Node.js specific plugins like eslint-plugin-node, eslint-plugin-mocha and eslint-plugin-node-security

Otherwise: Many faulty Node.js code patterns might escape under the radar. For example, developers might require(variableAsPath) files with a variable given as a path which allows attackers to execute any JS script. Node.js linters can detect such patterns and complain early



โœ” 3.3 Start a Codeblock's Curly Braces on the Same Line

TL;DR: The opening curly braces of a code block should be on the same line as the opening statement

Code Example

// Do
function someFunction() {
  // code block
}

// Avoid
function someFunction() {
  // code block
}

Otherwise: Deferring from this best practice might lead to unexpected results, as seen in the StackOverflow thread below:

๐Ÿ”— Read more: "Why do results vary based on curly brace placement?" (StackOverflow)



โœ” 3.4 Separate your statements properly

No matter if you use semicolons or not to separate your statements, knowing the common pitfalls of improper linebreaks or automatic semicolon insertion, will help you to eliminate regular syntax errors.

TL;DR: Use ESLint to gain awareness about separation concerns. Prettier or Standardjs can automatically resolve these issues.

Otherwise: As seen in the previous section, JavaScript's interpreter automatically adds a semicolon at the end of a statement if there isn't one, or considers a statement as not ended where it should, which might lead to some undesired results. You can use assignments and avoid using immediately invoked function expressions to prevent most of the unexpected errors.

Code example

// Do
function doThing() {
    // ...
}

doThing()

// Do

const items = [1, 2, 3]
items.forEach(console.log)

// Avoid โ€” throws exception
const m = new Map()
const a = [1,2,3]
[...m.values()].forEach(console.log)
> [...m.values()].forEach(console.log)
>  ^^^
> SyntaxError: Unexpected token ...

// Avoid โ€” throws exception
const count = 2 // it tries to run 2(), but 2 is not a function
(function doSomething() {
  // do something amazing
}())
// put a semicolon before the immediate invoked function, after the const definition, save the return value of the anonymous function to a variable or avoid IIFEs altogether

๐Ÿ”— Read more: "Semi ESLint rule" ๐Ÿ”— Read more: "No unexpected multiline ESLint rule"



โœ” 3.5 Name your functions

TL;DR: Name all functions, including closures and callbacks. Avoid anonymous functions. This is especially useful when profiling a node app. Naming all functions will allow you to easily understand what you're looking at when checking a memory snapshot

Otherwise: Debugging production issues using a core dump (memory snapshot) might become challenging as you notice significant memory consumption from anonymous functions



โœ” 3.6 Use naming conventions for variables, constants, functions and classes

TL;DR: Use lowerCamelCase when naming constants, variables and functions and UpperCamelCase (capital first letter as well) when naming classes. This will help you to easily distinguish between plain variables/functions, and classes that require instantiation. Use descriptive names, but try to keep them short

Otherwise: JavaScript is the only language in the world that allows invoking a constructor ("Class") directly without instantiating it first. Consequently, Classes and function-constructors are differentiated by starting with UpperCamelCase

3.6 Code Example

// for class name we use UpperCamelCase
class SomeClassExample {}

// for const names we use the const keyword and lowerCamelCase
const config = {
  key: "value",
};

// for variables and functions names we use lowerCamelCase
let someVariableExample = "value";
function doSomething() {}



โœ” 3.7 Prefer const over let. Ditch the var

TL;DR: Using const means that once a variable is assigned, it cannot be reassigned. Preferring const will help you to not be tempted to use the same variable for different uses, and make your code clearer. If a variable needs to be reassigned, in a for loop, for example, use let to declare it. Another important aspect of let is that a variable declared using it is only available in the block scope in which it was defined. var is function scoped, not block-scoped, and shouldn't be used in ES6 now that you have const and let at your disposal

Otherwise: Debugging becomes way more cumbersome when following a variable that frequently changes

๐Ÿ”— Read more: JavaScript ES6+: var, let, or const?



โœ” 3.8 Require modules first, not inside functions

TL;DR: Require modules at the beginning of each file, before and outside of any functions. This simple best practice will not only help you easily and quickly tell the dependencies of a file right at the top but also avoids a couple of potential problems

Otherwise: Requires are run synchronously by Node.js. If they are called from within a function, it may block other requests from being handled at a more critical time. Also, if a required module or any of its dependencies throw an error and crash the server, it is best to find out about it as soon as possible, which might not be the case if that module is required from within a function



โœ” 3.9 Require modules by folders, as opposed to the files directly

TL;DR: When developing a module/library in a folder, place an index.js file that exposes the module's internals so every consumer will pass through it. This serves as an 'interface' to your module and eases future changes without breaking the contract

Otherwise: Changing the internal structure of files or the signature may break the interface with clients

3.9 Code example

// Do
module.exports.SMSProvider = require("./SMSProvider");
module.exports.SMSNumberResolver = require("./SMSNumberResolver");

// Avoid
module.exports.SMSProvider = require("./SMSProvider/SMSProvider.js");
module.exports.SMSNumberResolver = require("./SMSNumberResolver/SMSNumberResolver.js");



โœ” 3.10 Use the === operator

TL;DR: Prefer the strict equality operator === over the weaker abstract equality operator ==. == will compare two variables after converting them to a common type. There is no type conversion in ===, and both variables must be of the same type to be equal

Otherwise: Unequal variables might return true when compared with the == operator

3.10 Code example

"" == "0"; // false
0 == ""; // true
0 == "0"; // true

false == "false"; // false
false == "0"; // true

false == undefined; // false
false == null; // false
null == undefined; // true

" \t\r\n " == 0; // true

All statements above will return false if used with ===



โœ” 3.11 Use Async Await, avoid callbacks

TL;DR: Node 8 LTS now has full support for Async-await. This is a new way of dealing with asynchronous code which supersedes callbacks and promises. Async-await is non-blocking, and it makes asynchronous code look synchronous. The best gift you can give to your code is using async-await which provides a much more compact and familiar code syntax like try-catch

Otherwise: Handling async errors in callback style are probably the fastest way to hell - this style forces to check errors all over, deal with awkward code nesting, and makes it difficult to reason about the code flow

๐Ÿ”— Read more: Guide to async-await 1.0



โœ” 3.12 Use arrow function expressions (=>)

TL;DR: Though it's recommended to use async-await and avoid function parameters when dealing with older APIs that accept promises or callbacks - arrow functions make the code structure more compact and keep the lexical context of the root function (i.e. this)

Otherwise: Longer code (in ES5 functions) is more prone to bugs and cumbersome to read

๐Ÿ”— Read more: Itโ€™s Time to Embrace Arrow Functions




โฌ† Return to top

4. Testing And Overall Quality Practices

โœ” 4.1 At the very least, write API (component) testing

TL;DR: Most projects just don't have any automated testing due to short timetables or often the 'testing project' ran out of control and was abandoned. For that reason, prioritize and start with API testing which is the easiest way to write and provides more coverage than unit testing (you may even craft API tests without code using tools like Postman). Afterward, should you have more resources and time, continue with advanced test types like unit testing, DB testing, performance testing, etc

Otherwise: You may spend long days on writing unit tests to find out that you got only 20% system coverage



โœ” 4.2 Include 3 parts in each test name

TL;DR: Make the test speak at the requirements level so it's self-explanatory also to QA engineers and developers who are not familiar with the code internals. State in the test name what is being tested (unit under test), under what circumstances, and what is the expected result

Otherwise: A deployment just failed, a test named โ€œAdd productโ€ failed. Does this tell you what exactly is malfunctioning?

๐Ÿ”— Read More: Include 3 parts in each test name



โœ” 4.3 Structure tests by the AAA pattern

TL;DR: Structure your tests with 3 well-separated sections: Arrange, Act & Assert (AAA). The first part includes the test setup, then the execution of the unit under test, and finally the assertion phase. Following this structure guarantees that the reader spends no brain CPU on understanding the test plan

Otherwise: Not only you spend long daily hours on understanding the main code, but now also what should have been the simple part of the day (testing) stretches your brain

๐Ÿ”— Read More: Structure tests by the AAA pattern



โœ” 4.4 Detect code issues with a linter

TL;DR: Use a code linter to check the basic quality and detect anti-patterns early. Run it before any test and add it as a pre-commit git-hook to minimize the time needed to review and correct any issue. Also check Section 3 on Code Style Practices

Otherwise: You may let pass some anti-pattern and possible vulnerable code to your production environment.



โœ” 4.5 Avoid global test fixtures and seeds, add data per-test

TL;DR: To prevent test coupling and easily reason about the test flow, each test should add and act on its own set of DB rows. Whenever a test needs to pull or assume the existence of some DB data - it must explicitly add that data and avoid mutating any other records

Otherwise: Consider a scenario where deployment is aborted due to failing tests, team is now going to spend precious investigation time that ends in a sad conclusion: the system works well, the tests however interfere with each other and break the build

๐Ÿ”— Read More: Avoid global test fixtures



โœ” 4.6 Constantly inspect for vulnerable dependencies

TL;DR: Even the most reputable dependencies such as Express have known vulnerabilities. This can get easily tamed using community and commercial tools such as ๐Ÿ”— npm audit and ๐Ÿ”— snyk.io that can be invoked from your CI on every build

Otherwise: Keeping your code clean from vulnerabilities without dedicated tools will require to constantly follow online publications about new threats. Quite tedious



โœ” 4.7 Tag your tests

TL;DR: Different tests must run on different scenarios: quick smoke, IO-less, tests should run when a developer saves or commits a file, full end-to-end tests usually run when a new pull request is submitted, etc. This can be achieved by tagging tests with keywords like #cold #api #sanity so you can grep with your testing harness and invoke the desired subset. For example, this is how you would invoke only the sanity test group with Mocha: mocha --grep 'sanity'

Otherwise: Running all the tests, including tests that perform dozens of DB queries, any time a developer makes a small change can be extremely slow and keeps developers away from running tests



โœ” 4.8 Check your test coverage, it helps to identify wrong test patterns

TL;DR: Code coverage tools like Istanbul/NYC are great for 3 reasons: it comes for free (no effort is required to benefit this reports), it helps to identify a decrease in testing coverage, and last but not least it highlights testing mismatches: by looking at colored code coverage reports you may notice, for example, code areas that are never tested like catch clauses (meaning that tests only invoke the happy paths and not how the app behaves on errors). Set it to fail builds if the coverage falls under a certain threshold

Otherwise: There won't be any automated metric telling you when a large portion of your code is not covered by testing



โœ” 4.9 Inspect for outdated packages

TL;DR: Use your preferred tool (e.g. npm outdated or npm-check-updates) to detect installed outdated packages, inject this check into your CI pipeline and even make a build fail in a severe scenario. For example, a severe scenario might be when an installed package is 5 patch commits behind (e.g. local version is 1.3.1 and repository version is 1.3.8) or it is tagged as deprecated by its author - kill the build and prevent deploying this version

Otherwise: Your production will run packages that have been explicitly tagged by their author as risky



โœ” 4.10 Use production-like environment for e2e testing

TL;DR: End to end (e2e) testing which includes live data used to be the weakest link of the CI process as it depends on multiple heavy services like DB. Use an environment which is as close to your real production environment as possible like a-continue (Missed -continue here, needs content. Judging by the Otherwise clause, this should mention docker-compose)

Otherwise: Without docker-compose, teams must maintain a testing DB for each testing environment including developers' machines, keep all those DBs in sync so test results won't vary across environments



โœ” 4.11 Refactor regularly using static analysis tools

TL;DR: Using static analysis tools helps by giving objective ways to improve code quality and keeps your code maintainable. You can add static analysis tools to your CI build to fail when it finds code smells. Its main selling points over plain linting are the ability to inspect quality in the context of multiple files (e.g. detect duplications), perform advanced analysis (e.g. code complexity), and follow the history and progress of code issues. Two examples of tools you can use are Sonarqube (2,600+ stars) and Code Climate (1,500+ stars).

Otherwise: With poor code quality, bugs and performance will always be an issue that no shiny new library or state of the art features can fix

๐Ÿ”— Read More: Refactoring!



โœ” 4.12 Carefully choose your CI platform (Jenkins vs CircleCI vs Travis vs Rest of the world)

TL;DR: Your continuous integration platform (CICD) will host all the quality tools (e.g. test, lint) so it should come with a vibrant ecosystem of plugins. Jenkins used to be the default for many projects as it has the biggest community along with a very powerful platform at the price of a complex setup that demands a steep learning curve. Nowadays, it has become much easier to set up a CI solution using SaaS tools like CircleCI and others. These tools allow crafting a flexible CI pipeline without the burden of managing the whole infrastructure. Eventually, it's a trade-off between robustness and speed - choose your side carefully

Otherwise: Choosing some niche vendor might get you blocked once you need some advanced customization. On the other hand, going with Jenkins might burn precious time on infrastructure setup

๐Ÿ”— Read More: Choosing CI platform

โœ” 4.13 Test your middlewares in isolation

TL;DR: When a middleware holds some immense logic that spans many requests, it is worth testing it in isolation without waking up the entire web framework. This can be easily achieved by stubbing and spying on the {req, res, next} objects

Otherwise: A bug in Express middleware === a bug in all or most requests

๐Ÿ”— Read More: Test middlewares in isolation




โฌ† Return to top

5. Going To Production Practices

โœ” 5.1. Monitoring

TL;DR: Monitoring is a game of finding out issues before customers do โ€“ obviously this should be assigned unprecedented importance. The market is overwhelmed with offers thus consider starting with defining the basic metrics you must follow (my suggestions inside), then go over additional fancy features and choose the solution that ticks all boxes. Click โ€˜The Gistโ€™ below for an overview of the solutions

Otherwise: Failure === disappointed customers. Simple

๐Ÿ”— Read More: Monitoring!



โœ” 5.2. Increase transparency using smart logging

TL;DR: Logs can be a dumb warehouse of debug statements or the enabler of a beautiful dashboard that tells the story of your app. Plan your logging platform from day 1: how logs are collected, stored and analyzed to ensure that the desired information (e.g. error rate, following an entire transaction through services and servers, etc) can really be extracted

Otherwise: You end up with a black box that is hard to reason about, then you start re-writing all logging statements to add additional information

๐Ÿ”— Read More: Increase transparency using smart logging



โœ” 5.3. Delegate anything possible (e.g. gzip, SSL) to a reverse proxy

TL;DR: Node is awfully bad at doing CPU intensive tasks like gzipping, SSL termination, etc. You should use โ€˜realโ€™ middleware services like nginx, HAproxy or cloud vendor services instead

Otherwise: Your poor single thread will stay busy doing infrastructural tasks instead of dealing with your application core and performance will degrade accordingly

๐Ÿ”— Read More: Delegate anything possible (e.g. gzip, SSL) to a reverse proxy



โœ” 5.4. Lock dependencies

TL;DR: Your code must be identical across all environments, but amazingly npm lets dependencies drift across environments by default โ€“ when you install packages at various environments it tries to fetch packagesโ€™ latest patch version. Overcome this by using npm config files, .npmrc, that tell each environment to save the exact (not the latest) version of each package. Alternatively, for finer grained control use npm shrinkwrap. *Update: as of NPM5, dependencies are locked by default. The new package manager in town, Yarn, also got us covered by default

Otherwise: QA will thoroughly test the code and approve a version that will behave differently in production. Even worse, different servers in the same production cluster might run different code

๐Ÿ”— Read More: Lock dependencies



โœ” 5.5. Guard process uptime using the right tool

TL;DR: The process must go on and get restarted upon failures. For simple scenarios, process management tools like PM2 might be enough but in today's โ€˜dockerizedโ€™ world, cluster management tools should be considered as well

Otherwise: Running dozens of instances without a clear strategy and too many tools together (cluster management, docker, PM2) might lead to DevOps chaos

๐Ÿ”— Read More: Guard process uptime using the right tool



โœ” 5.6. Utilize all CPU cores

TL;DR: At its basic form, a Node app runs on a single CPU core while all others are left idling. Itโ€™s your duty to replicate the Node process and utilize all CPUs โ€“ For small-medium apps you may use Node Cluster or PM2. For a larger app consider replicating the process using some Docker cluster (e.g. K8S, ECS) or deployment scripts that are based on Linux init system (e.g. systemd)

Otherwise: Your app will likely utilize only 25% of its available resources(!) or even less. Note that a typical server has 4 CPU cores or more, naive deployment of Node.js utilizes only 1 (even using PaaS services like AWS beanstalk!)

๐Ÿ”— Read More: Utilize all CPU cores



โœ” 5.7. Create a โ€˜maintenance endpointโ€™

TL;DR: Expose a set of system-related information, like memory usage and REPL, etc in a secured API. Although itโ€™s highly recommended to rely on standard and battle-tests tools, some valuable information and operations are easier done using code

Otherwise: Youโ€™ll find that youโ€™re performing many โ€œdiagnostic deploysโ€ โ€“ shipping code to production only to extract some information for diagnostic purposes

๐Ÿ”— Read More: Create a โ€˜maintenance endpointโ€™



โœ” 5.8. Discover errors and downtime using APM products

TL;DR: Application monitoring and performance products (a.k.a. APM) proactively gauge codebase and API so they can auto-magically go beyond traditional monitoring and measure the overall user-experience across services and tiers. For example, some APM products can highlight a transaction that loads too slow on the end-user's side while suggesting the root cause

Otherwise: You might spend great effort on measuring API performance and downtimes, probably youโ€™ll never be aware which is your slowest code parts under real-world scenario and how these affect the UX

๐Ÿ”— Read More: Discover errors and downtime using APM products



โœ” 5.9. Make your code production-ready

TL;DR: Code with the end in mind, plan for production from day 1. This sounds a bit vague so Iโ€™ve compiled a few development tips that are closely related to production maintenance (click Gist below)

Otherwise: A world champion IT/DevOps guy wonโ€™t save a system that is badly written

๐Ÿ”— Read More: Make your code production-ready



โœ” 5.10. Measure and guard the memory usage

TL;DR: Node.js has controversial relationships with memory: the v8 engine has soft limits on memory usage (1.4GB) and there are known paths to leak memory in Nodeโ€™s code โ€“ thus watching Nodeโ€™s process memory is a must. In small apps, you may gauge memory periodically using shell commands but in medium-large apps consider baking your memory watch into a robust monitoring system

Otherwise: Your process memory might leak a hundred megabytes a day like how it happened at Walmart

๐Ÿ”— Read More: Measure and guard the memory usage



โœ” 5.11. Get your frontend assets out of Node

TL;DR: Serve frontend content using dedicated middleware (nginx, S3, CDN) because Node performance really gets hurt when dealing with many static files due to its single-threaded model

Otherwise: Your single Node thread will be busy streaming hundreds of html/images/angular/react files instead of allocating all its resources for the task it was born for โ€“ serving dynamic content

๐Ÿ”— Read More: Get your frontend assets out of Node



โœ” 5.12. Be stateless, kill your servers almost every day

TL;DR: Store any type of data (e.g. user sessions, cache, uploaded files) within external data stores. Consider โ€˜killingโ€™ your servers periodically or use โ€˜serverlessโ€™ platform (e.g. AWS Lambda) that explicitly enforces a stateless behavior

Otherwise: Failure at a given server will result in application downtime instead of just killing a faulty machine. Moreover, scaling-out elasticity will get more challenging due to the reliance on a specific server

๐Ÿ”— Read More: Be stateless, kill your Servers almost every day



โœ” 5.13. Use tools that automatically detect vulnerabilities

TL;DR: Even the most reputable dependencies such as Express have known vulnerabilities (from time to time) that can put a system at risk. This can be easily tamed using community and commercial tools that constantly check for vulnerabilities and warn (locally or at GitHub), some can even patch them immediately

Otherwise: Keeping your code clean from vulnerabilities without dedicated tools will require you to constantly follow online publications about new threats. Quite tedious

๐Ÿ”— Read More: Use tools that automatically detect vulnerabilities



โœ” 5.14. Assign a transaction id to each log statement

Also known as correlation id / transit id / tracing id / request id / request context / etc.

TL;DR: Assign the same identifier, transaction-id: {some value}, to each log entry within a single request. Then when inspecting errors in logs, easily conclude what happened before and after. Until version 14 of Node, this was not easy to achieve due to Node's async nature, but since AsyncLocalStorage came to town, this became possible and easy than ever. see code examples inside

Otherwise: Looking at a production error log without the context โ€“ what happened before โ€“ makes it much harder and slower to reason about the issue

๐Ÿ”— Read More: Assign โ€˜TransactionIdโ€™ to each log statement



โœ” 5.15. Set NODE_ENV=production

TL;DR: Set the environment variable NODE_ENV to โ€˜productionโ€™ or โ€˜developmentโ€™ to flag whether production optimizations should get activated โ€“ many npm packages determine the current environment and optimize their code for production

Otherwise: Omitting this simple property might greatly degrade performance. For example, when using Express for server-side rendering omitting NODE_ENV makes it slower by a factor of three!

๐Ÿ”— Read More: Set NODE_ENV=production



โœ” 5.16. Design automated, atomic and zero-downtime deployments

TL;DR: Research shows that teams who perform many deployments lower the probability of severe production issues. Fast and automated deployments that donโ€™t require risky manual steps and service downtime significantly improve the deployment process. You should probably achieve this using Docker combined with CI tools as they became the industry standard for streamlined deployment

Otherwise: Long deployments -> production downtime & human-related error -> team unconfident in making deployment -> fewer deployments and features



โœ” 5.17. Use an LTS release of Node.js

TL;DR: Ensure you are using an LTS version of Node.js to receive critical bug fixes, security updates and performance improvements

Otherwise: Newly discovered bugs or vulnerabilities could be used to exploit an application running in production, and your application may become unsupported by various modules and harder to maintain

๐Ÿ”— Read More: Use an LTS release of Node.js



โœ” 5.18. Don't route logs within the app

TL;DR: Log destinations should not be hard-coded by developers within the application code, but instead should be defined by the execution environment the application runs in. Developers should write logs to stdout using a logger utility and then let the execution environment (container, server, etc.) pipe the stdout stream to the appropriate destination (i.e. Splunk, Graylog, ElasticSearch, etc.).

Otherwise: Application handling log routing === hard to scale, loss of logs, poor separation of concerns

๐Ÿ”— Read More: Log Routing



โœ” 5.19. Install your packages with npm ci

TL;DR: You have to be sure that production code uses the exact version of the packages you have tested it with. Run npm ci to strictly do a clean install of your dependencies matching package.json and package-lock.json. Using this command is recommended in automated environments such as continuous integration pipelines.

Otherwise: QA will thoroughly test the code and approve a version that will behave differently in production. Even worse, different servers in the same production cluster might run different code.

๐Ÿ”— Read More: Use npm ci




โฌ† Return to top

6. Security Best Practices

54 items

โœ” 6.1. Embrace linter security rules

TL;DR: Make use of security-related linter plugins such as eslint-plugin-security to catch security vulnerabilities and issues as early as possible, preferably while they're being coded. This can help catching security weaknesses like using eval, invoking a child process or importing a module with a string literal (e.g. user input). Click 'Read more' below to see code examples that will get caught by a security linter

Otherwise: What could have been a straightforward security weakness during development becomes a major issue in production. Also, the project may not follow consistent code security practices, leading to vulnerabilities being introduced, or sensitive secrets committed into remote repositories

๐Ÿ”— Read More: Lint rules



โœ” 6.2. Limit concurrent requests using a middleware

TL;DR: DOS attacks are very popular and relatively easy to conduct. Implement rate limiting using an external service such as cloud load balancers, cloud firewalls, nginx, rate-limiter-flexible package, or (for smaller and less critical apps) a rate-limiting middleware (e.g. express-rate-limit)

Otherwise: An application could be subject to an attack resulting in a denial of service where real users receive a degraded or unavailable service.

๐Ÿ”— Read More: Implement rate limiting



โœ” 6.3 Extract secrets from config files or use packages to encrypt them

TL;DR: Never store plain-text secrets in configuration files or source code. Instead, make use of secret-management systems like Vault products, Kubernetes/Docker Secrets, or using environment variables. As a last resort, secrets stored in source control must be encrypted and managed (rolling keys, expiring, auditing, etc). Make use of pre-commit/push hooks to prevent committing secrets accidentally

Otherwise: Source control, even for private repositories, can mistakenly be made public, at which point all secrets are exposed. Access to source control for an external party will inadvertently provide access to related systems (databases, apis, services, etc).

๐Ÿ”— Read More: Secret management



โœ” 6.4. Prevent query injection vulnerabilities with ORM/ODM libraries

TL;DR: To prevent SQL/NoSQL injection and other malicious attacks, always make use of an ORM/ODM or a database library that escapes data or supports named or indexed parameterized queries, and takes care of validating user input for expected types. Never just use JavaScript template strings or string concatenation to inject values into queries as this opens your application to a wide spectrum of vulnerabilities. All the reputable Node.js data access libraries (e.g. Sequelize, Knex, mongoose) have built-in protection against injection attacks.

Otherwise: Unvalidated or unsanitized user input could lead to operator injection when working with MongoDB for NoSQL, and not using a proper sanitization system or ORM will easily allow SQL injection attacks, creating a giant vulnerability.

๐Ÿ”— Read More: Query injection prevention using ORM/ODM libraries



โœ” 6.5. Collection of generic security best practices

TL;DR: This is a collection of security advice that is not related directly to Node.js - the Node implementation is not much different than any other language. Click read more to skim through.

๐Ÿ”— Read More: Common security best practices



โœ” 6.6. Adjust the HTTP response headers for enhanced security

TL;DR: Your application should be using secure headers to prevent attackers from using common attacks like cross-site scripting (XSS), clickjacking and other malicious attacks. These can be configured easily using modules like helmet.

Otherwise: Attackers could perform direct attacks on your application's users, leading to huge security vulnerabilities

๐Ÿ”— Read More: Using secure headers in your application



โœ” 6.7. Constantly and automatically inspect for vulnerable dependencies

TL;DR: With the npm ecosystem it is common to have many dependencies for a project. Dependencies should always be kept in check as new vulnerabilities are found. Use tools like npm audit or snyk to track, monitor and patch vulnerable dependencies. Integrate these tools with your CI setup so you catch a vulnerable dependency before it makes it to production.

Otherwise: An attacker could detect your web framework and attack all its known vulnerabilities.

๐Ÿ”— Read More: Dependency security



โœ” 6.8. Protect Users' Passwords/Secrets using bcrypt or scrypt

TL;DR: Passwords or secrets (e.g. API keys) should be stored using a secure hash + salt function like bcrypt,scrypt, or worst case pbkdf2.

Otherwise: Passwords and secrets that are stored without using a secure function are vulnerable to brute forcing and dictionary attacks that will lead to their disclosure eventually.

๐Ÿ”— Read More: User Passwords



โœ” 6.9. Escape HTML, JS and CSS output

TL;DR: Untrusted data that is sent down to the browser might get executed instead of just being displayed, this is commonly referred as a cross-site-scripting (XSS) attack. Mitigate this by using dedicated libraries that explicitly mark the data as pure content that should never get executed (i.e. encoding, escaping)

Otherwise: An attacker might store malicious JavaScript code in your DB which will then be sent as-is to the poor clients

๐Ÿ”— Read More: Escape output



โœ” 6.10. Validate incoming JSON schemas

TL;DR: Validate the incoming requests' body payload and ensure it meets expectations, fail fast if it doesn't. To avoid tedious validation coding within each route you may use lightweight JSON-based validation schemas such as jsonschema or joi

Otherwise: Your generosity and permissive approach greatly increases the attack surface and encourages the attacker to try out many inputs until they find some combination to crash the application

๐Ÿ”— Read More: Validate incoming JSON schemas



โœ” 6.11. Support blocklisting JWTs

TL;DR: When using JSON Web Tokens (for example, with Passport.js), by default there's no mechanism to revoke access from issued tokens. Once you discover some malicious user activity, there's no way to stop them from accessing the system as long as they hold a valid token. Mitigate this by implementing a blocklist of untrusted tokens that are validated on each request.

Otherwise: Expired, or misplaced tokens could be used maliciously by a third party to access an application and impersonate the owner of the token.

๐Ÿ”— Read More: Blocklist JSON Web Tokens



โœ” 6.12. Prevent brute-force attacks against authorization

TL;DR: A simple and powerful technique is to limit authorization attempts using two metrics:

  1. The first is number of consecutive failed attempts by the same user unique ID/name and IP address.
  2. The second is number of failed attempts from an IP address over some long period of time. For example, block an IP address if it makes 100 failed attempts in one day.

Otherwise: An attacker can issue unlimited automated password attempts to gain access to privileged accounts on an application

๐Ÿ”— Read More: Login rate limiting



โœ” 6.13. Run Node.js as non-root user

TL;DR: There is a common scenario where Node.js runs as a root user with unlimited permissions. For example, this is the default behaviour in Docker containers. It's recommended to create a non-root user and either bake it into the Docker image (examples given below) or run the process on this user's behalf by invoking the container with the flag "-u username"

Otherwise: An attacker who manages to run a script on the server gets unlimited power over the local machine (e.g. change iptable and re-route traffic to his server)

๐Ÿ”— Read More: Run Node.js as non-root user



โœ” 6.14. Limit payload size using a reverse-proxy or a middleware

TL;DR: The bigger the body payload is, the harder your single thread works in processing it. This is an opportunity for attackers to bring servers to their knees without tremendous amount of requests (DOS/DDOS attacks). Mitigate this limiting the body size of incoming requests on the edge (e.g. firewall, ELB) or by configuring express body parser to accept only small-size payloads

Otherwise: Your application will have to deal with large requests, unable to process the other important work it has to accomplish, leading to performance implications and vulnerability towards DOS attacks

๐Ÿ”— Read More: Limit payload size



โœ” 6.15. Avoid JavaScript eval statements

TL;DR: eval is evil as it allows executing custom JavaScript code during run time. This is not just a performance concern but also an important security concern due to malicious JavaScript code that may be sourced from user input. Another language feature that should be avoided is new Function constructor. setTimeout and setInterval should never be passed dynamic JavaScript code either.

Otherwise: Malicious JavaScript code finds a way into text passed into eval or other real-time evaluating JavaScript language functions, and will gain complete access to JavaScript permissions on the page. This vulnerability is often manifested as an XSS attack.

๐Ÿ”— Read More: Avoid JavaScript eval statements



โœ” 6.16. Prevent evil RegEx from overloading your single thread execution

TL;DR: Regular Expressions, while being handy, pose a real threat to JavaScript applications at large, and the Node.js platform in particular. A user input for text to match might require an outstanding amount of CPU cycles to process. RegEx processing might be inefficient to an extent that a single request that validates 10 words can block the entire event loop for 6 seconds and set the CPU on ๐Ÿ”ฅ . For that reason, prefer third-party validation packages like validator.js instead of writing your own Regex patterns, or make use of safe-regex to detect vulnerable regex patterns

Otherwise: Poorly written regexes could be susceptible to Regular Expression DoS attacks that will block the event loop completely. For example, the popular moment package was found vulnerable with malicious RegEx usage in November of 2017

๐Ÿ”— Read More: Prevent malicious RegEx



โœ” 6.17. Avoid module loading using a variable

TL;DR: Avoid requiring/importing another file with a path that was given as parameter due to the concern that it could have originated from user input. This rule can be extended for accessing files in general (i.e. fs.readFile()) or other sensitive resource access with dynamic variables originating from user input. Eslint-plugin-security linter can catch such patterns and warn early enough

Otherwise: Malicious user input could find its way to a parameter that is used to require tampered files, for example, a previously uploaded file on the file system, or access already existing system files.

๐Ÿ”— Read More: Safe module loading



โœ” 6.18. Run unsafe code in a sandbox

TL;DR: When tasked to run external code that is given at run-time (e.g. plugin), use any sort of 'sandbox' execution environment that isolates and guards the main code against the plugin. This can be achieved using a dedicated process (e.g. cluster.fork()), serverless environment or dedicated npm packages that act as a sandbox

Otherwise: A plugin can attack through an endless variety of options like infinite loops, memory overloading, and access to sensitive process environment variables

๐Ÿ”— Read More: Run unsafe code in a sandbox



โœ” 6.19. Take extra care when working with child processes

TL;DR: Avoid using child processes when possible and validate and sanitize input to mitigate shell injection attacks if you still have to. Prefer using child_process.execFile which by definition will only execute a single command with a set of attributes and will not allow shell parameter expansion.

Otherwise: Naive use of child processes could result in remote command execution or shell injection attacks due to malicious user input passed to an unsanitized system command.

๐Ÿ”— Read More: Be cautious when working with child processes



โœ” 6.20. Hide error details from clients

TL;DR: An integrated express error handler hides the error details by default. However, great are the chances that you implement your own error handling logic with custom Error objects (considered by many as a best practice). If you do so, ensure not to return the entire Error object to the client, which might contain some sensitive application details

Otherwise: Sensitive application details such as server file paths, third party modules in use, and other internal workflows of the application which could be exploited by an attacker, could be leaked from information found in a stack trace

๐Ÿ”— Read More: Hide error details from client



โœ” 6.21. Configure 2FA for npm or Yarn

TL;DR: Any step in the development chain should be protected with MFA (multi-factor authentication), npm/Yarn are a sweet opportunity for attackers who can get their hands on some developer's password. Using developer credentials, attackers can inject malicious code into libraries that are widely installed across projects and services. Maybe even across the web if published in public. Enabling 2-factor-authentication in npm leaves almost zero chances for attackers to alter your package code.

Otherwise: Have you heard about the eslint developer whose password was hijacked?



โœ” 6.22. Modify session middleware settings

TL;DR: Each web framework and technology has its known weaknessesโ€Š-โ€Štelling an attacker which web framework we use is a great help for them. Using the default settings for session middlewares can expose your app to module- and framework-specific hijacking attacks in a similar way to the X-Powered-By header. Try hiding anything that identifies and reveals your tech stack (E.g. Node.js, express)

Otherwise: Cookies could be sent over insecure connections, and an attacker might use session identification to identify the underlying framework of the web application, as well as module-specific vulnerabilities

๐Ÿ”— Read More: Cookie and session security



โœ” 6.23. Avoid DOS attacks by explicitly setting when a process should crash

TL;DR: The Node process will crash when errors are not handled. Many best practices even recommend to exit even though an error was caught and got handled. Express, for example, will crash on any asynchronous errorโ€Š-โ€Šunless you wrap routes with a catch clause. This opens a very sweet attack spot for attackers who recognize what input makes the process crash and repeatedly send the same request. There's no instant remedy for this but a few techniques can mitigate the pain: Alert with critical severity anytime a process crashes due to an unhandled error, validate the input and avoid crashing the process due to invalid user input, wrap all routes with a catch and consider not to crash when an error originated within a request (as opposed to what happens globally)

Otherwise: This is just an educated guess: given many Node.js applications, if we try passing an empty JSON body to all POST requestsโ€Š-โ€Ša handful of applications will crash. At that point, we can just repeat sending the same request to take down the applications with ease



โœ” 6.24. Prevent unsafe redirects

TL;DR: Redirects that do not validate user input can enable attackers to launch phishing scams, steal user credentials, and perform other malicious actions.

Otherwise: If an attacker discovers that you are not validating external, user-supplied input, they may exploit this vulnerability by posting specially-crafted links on forums, social media, and other public places to get users to click it.

๐Ÿ”— Read More: Prevent unsafe redirects



โœ” 6.25. Avoid publishing secrets to the npm registry

TL;DR: Precautions should be taken to avoid the risk of accidentally publishing secrets to public npm registries. An .npmignore file can be used to ignore specific files or folders, or the files array in package.json can act as an allow list.

Otherwise: Your project's API keys, passwords or other secrets are open to be abused by anyone who comes across them, which may result in financial loss, impersonation, and other risks.

๐Ÿ”— Read More: Avoid publishing secrets


โฌ† Return to top

7. Draft: Performance Best Practices

Our contributors are working on this section. Would you like to join?



โœ” 7.1. Don't block the event loop

TL;DR: Avoid CPU intensive tasks as they will block the mostly single-threaded Event Loop and offload those to a dedicated thread, process or even a different technology based on the context.

Otherwise: As the Event Loop is blocked, Node.js will be unable to handle other request thus causing delays for concurrent users. 3000 users are waiting for a response, the content is ready to be served, but one single request blocks the server from dispatching the results back

๐Ÿ”— Read More: Do not block the event loop




โœ” 7.2. Prefer native JS methods over user-land utils like Lodash

TL;DR: It's often more penalising to use utility libraries like lodash and underscore over native methods as it leads to unneeded dependencies and slower performance. Bear in mind that with the introduction of the new V8 engine alongside the new ES standards, native methods were improved in such a way that it's now about 50% more performant than utility libraries.

Otherwise: You'll have to maintain less performant projects where you could have simply used what was already available or dealt with a few more lines in exchange of a few more files.

๐Ÿ”— Read More: Native over user land utils




โฌ† Return to top

8. Docker Best Practices

๐Ÿ… Many thanks to Bret Fisher from whom we learned many of the following practices



โœ” 8.1 Use multi-stage builds for leaner and more secure Docker images

TL;DR: Use multi-stage build to copy only necessary production artifacts. A lot of build-time dependencies and files are not needed for running your application. With multi-stage builds these resources can be used during build while the runtime environment contains only what's necessary. Multi-stage builds are an easy way to get rid of overweight and security threats.

Otherwise: Larger images will take longer to build and ship, build-only tools might contain vulnerabilities and secrets only meant for the build phase might be leaked.

Example Dockerfile for multi-stage builds

FROM node:14.4.0 AS build

COPY . .
RUN npm ci && npm run build

FROM node:slim-14.4.0

USER node
EXPOSE 8080

COPY --from=build /home/node/app/dist /home/node/app/package.json /home/node/app/package-lock.json ./
RUN npm ci --production

CMD [ "node", "dist/app.js" ]

๐Ÿ”— Read More: Use multi-stage builds




โœ” 8.2. Bootstrap using node command, avoid npm start

TL;DR: use CMD ['node','server.js'] to start your app, avoid using npm scripts which don't pass OS signals to the code. This prevents problems with child-processes, signal handling, graceful shutdown and having zombie processes.

Otherwise: When no signals are passed, your code will never be notified about shutdowns. Without this, it will lose its chance to close properly possibly losing current requests and/or data.

Read More: Bootstrap container using node command, avoid npm start




โœ” 8.3. Let the Docker runtime handle replication and uptime

TL;DR: When using a Docker run time orchestrator (e.g., Kubernetes), invoke the Node.js process directly without intermediate process managers or custom code that replicate the process (e.g. PM2, Cluster module). The runtime platform has the highest amount of data and visibility for making placement decision - It knows best how many processes are needed, how to spread them and what to do in case of crashes

Otherwise: Container keeps crashing due to lack of resources will get restarted indefinitely by the process manager. Should Kubernetes be aware of that, it could relocate it to a different roomy instance

๐Ÿ”— Read More: Let the Docker orchestrator restart and replicate processes




โœ” 8.4. Use .dockerignore to prevent leaking secrets

TL;DR: Include a .dockerignore file that filters out common secret files and development artifacts. By doing so, you might prevent secrets from leaking into the image. As a bonus the build time will significantly decrease. Also, ensure not to copy all files recursively rather explicitly choose what should be copied to Docker

Otherwise: Common personal secret files like .env, .aws and .npmrc will be shared with anybody with access to the image (e.g. Docker repository)

๐Ÿ”— Read More: Use .dockerignore




โœ” 8.5. Clean-up dependencies before production

TL;DR: Although Dev-Dependencies are sometimes needed during the build and test life-cycle, eventually the image that is shipped to production should be minimal and clean from development dependencies. Doing so guarantees that only necessary code is shipped and the amount of potential attacks (i.e. attack surface) is minimized. When using multi-stage build (see dedicated bullet) this can be achieved by installing all dependencies first and finally running npm ci --production

Otherwise: Many of the infamous npm security breaches were found within development packages (e.g. eslint-scope)

๐Ÿ”— Read More: Remove development dependencies




โœ” 8.6. Shutdown smartly and gracefully

TL;DR: Handle the process SIGTERM event and clean-up all existing connection and resources. This should be done while responding to ongoing requests. In Dockerized runtimes shutting down containers is not a rare event, rather a frequent occurrence that happen as part of routine work. Achieving this demands some thoughtful code to orchestrate several moving parts: The load balancer, keep-alive connections, the HTTP server and other resources

Otherwise: Dying immediately means not responding to thousands of disappointed users

๐Ÿ”— Read More: Graceful shutdown




โœ” 8.7. Set memory limits using both Docker and v8

TL;DR: Always configure a memory limit using both Docker and the JavaScript runtime flags. The Docker limit is needed to make thoughtful container placement decision, the --v8's flag max-old-space is needed to kick off the GC on time and prevent under utilization of memory. Practically, set the v8's old space memory to be a just bit less than the container limit

Otherwise: The docker definition is needed to perform thoughtful scaling decision and prevent starving other citizens. Without also defining the v8's limits, it will under utilize the container resources - Without explicit instructions it crashes when utilizing ~50-60% of its host resources

๐Ÿ”— Read More: Set memory limits using Docker only




โœ” 8.8. Plan for efficient caching

TL;DR: Rebuilding a whole docker image from cache can be nearly instantaneous if done correctly. The less updated instructions should be at the top of your Dockerfile and the ones constantly changing (like app code) should be at the bottom.

Otherwise: Docker build will be very long and consume lot of resources even when making tiny changes

๐Ÿ”— Read More: Leverage caching to reduce build times




โœ” 8.9. Use explicit image reference, avoid latest tag

TL;DR: Specify an explicit image digest or versioned label, never refer to latest. Developers are often led to believe that specifying the latest tag will provide them with the most recent image in the repository however this is not the case. Using a digest guarantees that every instance of the service is running exactly the same code.

In addition, referring to an image tag means that the base image is subject to change, as image tags cannot be relied upon for a deterministic install. Instead, if a deterministic install is expected, a SHA256 digest can be used to reference an exact image.

Otherwise: A new version of a base image could be deployed into production with breaking changes, causing unintended application behaviour.

๐Ÿ”— Read More: Understand image tags and use the "latest" tag with caution




โœ” 8.10. Prefer smaller Docker base images

TL;DR: Large images lead to higher exposure to vulnerabilities and increased resource consumption. Using leaner Docker images, such as Slim and Alpine Linux variants, mitigates this issue.

Otherwise: Building, pushing, and pulling images will take longer, unknown attack vectors can be used by malicious actors and more resources are consumed.

๐Ÿ”— Read More: Prefer smaller images




โœ” 8.11. Clean-out build-time secrets, avoid secrets in args

TL;DR: Avoid secrets leaking from the Docker build environment. A Docker image is typically shared in multiple environment like CI and a registry that are not as sanitized as production. A typical example is an npm token which is usually passed to a dockerfile as argument. This token stays within the image long after it is needed and allows the attacker indefinite access to a private npm registry. This can be avoided by coping a secret file like .npmrc and then removing it using multi-stage build (beware, build history should be deleted as well) or by using Docker build-kit secret feature which leaves zero traces

Otherwise: Everyone with access to the CI and docker registry will also get access to some precious organization secrets as a bonus

๐Ÿ”— Read More: Clean-out build-time secrets




โœ” 8.12. Scan images for multi layers of vulnerabilities

TL;DR: Besides checking code dependencies vulnerabilities also scan the final image that is shipped to production. Docker image scanners check the code dependencies but also the OS binaries. This E2E security scan covers more ground and verifies that no bad guy injected bad things during the build. Consequently, it is recommended running this as the last step before deployment. There are a handful of free and commercial scanners that also provide CI/CD plugins

Otherwise: Your code might be entirely free from vulnerabilities. However it might still get hacked due to vulnerable version of OS-level binaries (e.g. OpenSSL, TarBall) that are commonly being used by applications

๐Ÿ”— Read More: Scan the entire image before production




โœ” 8.13 Clean NODE_MODULE cache

TL;DR: After installing dependencies in a container remove the local cache. It doesn't make any sense to duplicate the dependencies for faster future installs since there won't be any further installs - A Docker image is immutable. Using a single line of code tens of MB (typically 10-50% of the image size) are shaved off

Otherwise: The image that will get shipped to production will weigh 30% more due to files that will never get used

๐Ÿ”— Read More: Clean NODE_MODULE cache




โœ” 8.14. Generic Docker practices

TL;DR: This is a collection of Docker advice that is not related directly to Node.js - the Node implementation is not much different than any other language. Click read more to skim through.

๐Ÿ”— Read More: Generic Docker practices




โœ” 8.15. Lint your Dockerfile

TL;DR: Linting your Dockerfile is an important step to identify issues in your Dockerfile which differ from best practices. By checking for potential flaws using a specialised Docker linter, performance and security improvements can be easily identified, saving countless hours of wasted time or security issues in production code.

Otherwise: Mistakenly the Dockerfile creator left Root as the production user, and also used an image from unknown source repository. This could be avoided with with just a simple linter.

๐Ÿ”— Read More: Lint your Dockerfile




โฌ† Return to top

Milestones

To maintain this guide and keep it up to date, we are constantly updating and improving the guidelines and best practices with the help of the community. You can follow our milestones and join the working groups if you want to contribute to this project


Translations

All translations are contributed by the community. We will be happy to get any help with either completed, ongoing or new translations!

Completed translations

Translations in progress



Steering Committee

Meet the steering committee members - the people who work together to provide guidance and future direction to the project. In addition, each member of the committee leads a project tracked under our GitHub projects.

Yoni Goldberg

Independent Node.js consultant who works with customers in the USA, Europe, and Israel on building large-scale Node.js applications. Many of the best practices above were first published at goldbergyoni.com. Reach Yoni at @goldbergyoni or [email protected]


Bruno Scheufler

๐Ÿ’ป full-stack web engineer, Node.js & GraphQL enthusiast


Kyle Martin

Full Stack Developer & Site Reliability Engineer based in New Zealand, interested in web application security, and architecting and building Node.js applications to perform at global scale.


Kevyn Bruyere

Independent full-stack developer with a taste for Ops and automation.


Steering Committee Emeriti

Sagir Khan

Deep specialist in JavaScript and its ecosystem โ€” React, Node.js, TypeScript, GraphQL, MongoDB, pretty much anything that involves JS/JSON in any layer of the system โ€” building products using the web platform for the worldโ€™s most recognized brands. Individual Member of the Node.js Foundation.


Collaborators

Thank you to all our collaborators! ๐Ÿ™

Our collaborators are members who are contributing to the repository on a regular basis, through suggesting new best practices, triaging issues, reviewing pull requests and more. If you are interested in helping us guide thousands of people to craft better Node.js applications, please read our contributor guidelines ๐ŸŽ‰

Ido Richter (Founder) Keith Holliday

Collaborator Emeriti

Refael Ackermann

Contributing

If you've ever wanted to contribute to open source, now is your chance! See the contributing docs for more information.

Contributors โœจ

Thanks goes to these wonderful people who have contributed to this repository!


Kevin Rambaud

๐Ÿ–‹

Michael Fine

๐Ÿ–‹

Shreya Dahal

๐Ÿ–‹

Matheus Cruz Rocha

๐Ÿ–‹

Yog Mehta

๐Ÿ–‹

Kudakwashe Paradzayi

๐Ÿ–‹

t1st3

๐Ÿ–‹

mulijordan1976

๐Ÿ–‹

Matan Kushner

๐Ÿ–‹

Fabio Hiroki

๐Ÿ–‹

James Sumners

๐Ÿ–‹

Dan Gamble

๐Ÿ–‹

PJ Trainor

๐Ÿ–‹

Remek Ambroziak

๐Ÿ–‹

Yoni Jah

๐Ÿ–‹

Misha Khokhlov

๐Ÿ–‹

Evgeny Orekhov

๐Ÿ–‹

-

๐Ÿ–‹

Isaac Halvorson

๐Ÿ–‹

Vedran Karaฤiฤ‡

๐Ÿ–‹

lallenlowe

๐Ÿ–‹

Nathan Wells

๐Ÿ–‹

Paulo Reis

๐Ÿ–‹

syzer

๐Ÿ–‹

David Sancho

๐Ÿ–‹

Robert Manolea

๐Ÿ–‹

Xavier Ho

๐Ÿ–‹

Aaron

๐Ÿ–‹

Jan Charles Maghirang Adona

๐Ÿ–‹

Allen

๐Ÿ–‹

Leonardo Villela

๐Ÿ–‹

Michaล‚ Zaล‚ฤ™cki

๐Ÿ–‹

Chris Nicola

๐Ÿ–‹

Alejandro Corredor

๐Ÿ–‹

cwar

๐Ÿ–‹

Yuwei

๐Ÿ–‹

Utkarsh Bhatt

๐Ÿ–‹

Duarte Mendes

๐Ÿ–‹

Jason Kim

๐Ÿ–‹

Mitja O.

๐Ÿ–‹

Sandro Miguel Marques

๐Ÿ–‹

Gabe

๐Ÿ–‹

Ron Gross

๐Ÿ–‹

Valeri Karpov

๐Ÿ–‹

Sergio Bernal

๐Ÿ–‹

Nikola Telkedzhiev

๐Ÿ–‹

Vitor Godoy

๐Ÿ–‹

Manish Saraan

๐Ÿ–‹

Sangbeom Han

๐Ÿ–‹

blackmatch

๐Ÿ–‹

Joe Reeve

๐Ÿ–‹

Ryan Busby

๐Ÿ–‹

Iman Mohamadi

๐Ÿ–‹

Sergii Paryzhskyi

๐Ÿ–‹

Kapil Patel

๐Ÿ–‹

่ฟทๆธก

๐Ÿ–‹

Hozefa

๐Ÿ–‹

Ethan

๐Ÿ–‹

Sam

๐Ÿ–‹

Arlind

๐Ÿ–‹

Teddy Toussaint

๐Ÿ–‹

Lewis

๐Ÿ–‹

Gabriel Lidenor

๐Ÿ–‹

Roman

๐Ÿ–‹

Francozeira

๐Ÿ–‹

Invvard

๐Ÿ–‹

Rรดmulo Garofalo

๐Ÿ–‹

Tho Q Luong

๐Ÿ–‹

Burak Shen

๐Ÿ–‹

Martin Muzatko

๐Ÿ–‹

Jared Collier

๐Ÿ–‹

Hilton Meyer

๐Ÿ–‹

ChangJoo Park(๋ฐ•์ฐฝ์ฃผ)

๐Ÿ–‹

Masahiro Sakaguchi

๐Ÿ–‹

Keith Holliday

๐Ÿ–‹

coreyc

๐Ÿ–‹

Maximilian Berkmann

๐Ÿ–‹

Douglas Mariano Valero

๐Ÿ–‹

Marcelo Melo

๐Ÿ–‹

Mehmet Perk

๐Ÿ–‹

ryan ouyang

๐Ÿ–‹

Shabeer

๐Ÿ–‹

Eduard Kyvenko

๐Ÿ–‹

Deyvison Rocha

๐Ÿ–‹

George Mamer

๐Ÿ–‹

Konstantinos Leimonis

๐Ÿ–‹

Oliver Lluberes

๐ŸŒ

Tien Do

๐Ÿ–‹

Ranvir Singh

๐Ÿ–‹

Vadim Nicolaev

๐Ÿ–‹ ๐ŸŒ

German Gamboa Gonzalez

๐Ÿ–‹

Hafez

๐Ÿ–‹

Chandiran

๐Ÿ–‹

VinayaSathyanarayana

๐Ÿ–‹

Kim Kern

๐Ÿ–‹

Kenneth Freitas

๐Ÿ–‹

songe

๐Ÿ–‹

Kirill Shekhovtsov

๐Ÿ–‹

Serge

๐Ÿ–‹

keyrwinz

๐Ÿ–‹

Dmitry Nikitenko

๐Ÿ–‹

bushuai

๐Ÿ‘€ ๐Ÿ–‹

Benjamin Gruenbaum

๐Ÿ–‹

Ezequiel

๐ŸŒ

Juan Josรฉ Rodrรญguez

๐ŸŒ

Or Bin

๐Ÿ–‹

Andreo Vieira

๐Ÿ–‹

Michael Solomon

๐Ÿ–‹

Jimmy Callin

๐Ÿ–‹

Siddharth

๐Ÿ–‹

Ryan Smith

๐Ÿ–‹

Tom Boettger

๐Ÿ–‹

Joaquรญn Ormaechea

๐ŸŒ

dfrzuz

๐ŸŒ

Victor Homyakov

๐Ÿ–‹

Josh

๐Ÿ–‹ ๐Ÿ›ก๏ธ

Alec Francis

๐Ÿ–‹

arjun6610

๐Ÿ–‹

Jan Osch

๐Ÿ–‹

Thiago Rotondo Sampaio

๐ŸŒ

Alexsey

๐Ÿ–‹

Luis A. Acurero

๐ŸŒ

Lucas Romano

๐ŸŒ

Denise Case

๐Ÿ–‹

Nick Ribal

๐Ÿ–‹ ๐Ÿ‘€

0xflotus

๐Ÿ–‹

Jonathan Chen

๐Ÿ–‹

Dilan Srilal

๐Ÿ–‹

vladthelittleone

๐ŸŒ

Nik Osvalds

๐Ÿ–‹

Daniel Kiss

๐Ÿ“–

Forresst

๐Ÿ–‹

Jonathan Svenheden

๐Ÿ–‹

AustrisC

๐Ÿ–‹

kyeongtae kim

๐ŸŒ

007

๐Ÿ–‹

Ane Diaz de Tuesta

๐ŸŒ ๐Ÿ–‹

YukiOta

๐ŸŒ

Frazer Smith

๐Ÿ–‹

Raz Luvaton

๐Ÿ–‹

Yuta Azumi

๐Ÿ–‹

andrewjbarbour

๐Ÿ–‹

mr

๐Ÿ–‹

Aleksandar

๐Ÿ–‹

Owl

๐Ÿ–‹

Yedidya Schwartz

๐Ÿ–‹ ๐Ÿ’ก

ari

๐Ÿ–‹

Thomas Kรถnig

๐Ÿ–‹

Kalle Lรคmsรค

๐Ÿ–‹

Wyatt

๐Ÿ–‹

KHADIR Tayeb

๐Ÿ–‹
Comments
  • All contributors bot implementation

    All contributors bot implementation

    NOTE: Why am I tagged in this issue?

    If you have been tagged in this issue, it is due to us migrating our previous flowers/stars contribution model to using the all-contributors specification. This notification will only happen once.


    This issue tracks the remaining work items required for adding https://allcontributors.org/ spec and bot to this project.

    • [x] create a CONTRIBUTORS.md file. This will be the new place where the main contributor table lives
    • [x] update each language README.md to link to the new CONTRIBUTORS.md file
    • [x] update our existing .operations/CONTRIBUTORS.md file to include instructions for how the new bot is used
    • [x] remove existing flowers/stars, and use the bot to add contributors back in the new format.

    Most of our existing flowers can be content or translation contributions, and stars are ideas https://allcontributors.org/docs/en/emoji-key.

    As there is currently no way to bulk add contributors, there will be a process of many PR's to get this working initially, i.e. @bot please add 1 for x, @bot please add 2 for x.

    This will be great for our workflow, which has become a bit difficult to manage~

    opened by js-kyle 173
  • Security best practices - kicking off

    Security best practices - kicking off

    @BrunoScheufler @lirantal

    I'm excited to Kick-off the security best practices section. Our goal is to reach a 20+ bullets security checklist that is highly comprehensive and curated. We work on this branch that already contains 14 titles

    I suggest the following workflow:

    A. TOC first: Write the bullets title โ€“ each can add, remark on the titles themselves until we reach a comprehensive list that is MECE (mutually exclusive and collaboratively exhausting). Note that going by our content guidelines we donโ€™t include general security principle that can be found easily in many articles โ€“ we focus on bullets that can be correlated directly to Node. Generic security advice are grouped under a single bullet

    B. Finalize the bibliography โ€“ gather a list of 5-10 great sources that explain the topics. This is needed to quote articles and include nice visuals. Liranโ€™s book is, of course, a great candidate as a primary source for great content

    @Liran โ€“ we shall soon add a bibliography section to the repo, your book can appear there if you will

    C. Write the content (inner pages) โ€“ assign topics to write, each writes as many topics that he can (0-20 ๐Ÿ˜Š)

    D. Language proof โ€“ Bruno will revise the content grammar and the overall lexical quality

    E. Promotion โ€“ publish as medium/hacker-noon article, SEO tricks, send to Node weekly, Node Twitter, reddit and many other techniques we constantly use successfully

    How does this plan sounds like?

    new best practice 
    opened by goldbergyoni 77
  • Spanish translation (buena suerte)

    Spanish translation (buena suerte)

    https://github.com/i0natan/nodebestpractices/blob/spanish-translation/README.md

    @eduardomontalvo - Spanish translation can be officially kicked-off. You're the lead! I'll be at your disposal should you need anything. A branch was created (link below), you should have permissions to it, everyone else must PR before changing anything there.

    I would ask/recommend only 2 important guidelines:

    Keep the same content & formatting - the focus is on translation, should anyone want to modify the content or the graphics - let's PR first in English and them translate to Spanish Duplicate pages - the content should be translated over a page duplication. Readme.MD became Readme.spanish.MD, all other files should be duplicated similarly. So the number of English & Spanish pages should be the same. Will create a bold link from the English home page to the Spanish home page (with bold credit of course...)

    https://github.com/i0natan/nodebestpractices/blob/spanish-translation/README.md

    translation stale 
    opened by goldbergyoni 70
  • Performance & diagnostics best practices - call for ideas

    Performance & diagnostics best practices - call for ideas

    We're kicking off the performance best practices section. Any idea regarding performance best practices or great bibliography to extract ideas from (youtube, blog post, etc)?

    This issue will summarize all the ideas and bibliography and serve as a TOC for the writers. This is also a call for write or would like to learn by practicing, discussing and writing.

    @sagirk @BrunoScheufler @js-kyle

    new best practice writer-needed performance stale 
    opened by goldbergyoni 58
  • Turkish translation HoลŸgeldiniz

    Turkish translation HoลŸgeldiniz

    @grafiktr - Turkish translation can be officially kicked-off. You're the lead! I'll be at your disposal should you need anything. Please create a branch for this work and PR to master once it's 100% done. Once we load it, will put your name on top of the Turkish page

    I would ask/recommend only 2 important guidelines (if something isn't clear - please let us know and will be glad to do it for you):

    Keep the same content & formatting - the focus is on translation, should anyone want to modify the content or the graphics - let's PR first in English and them translate to Turkish Duplicate pages - the content should be translated over a page duplication. Readme.MD became Readme.turkish.MD, all other files should be duplicated similarly. So the number of English & Turkish pages should be the same. Will create a bold link from the English home page to the Turkish home page (with bold credit of course...).

    translation stale 
    opened by goldbergyoni 41
  • Security best practices section

    Security best practices section

    I'd like to work on the security best practices section. Apart from independent modules/npm solutions already stated in the main README what do you think would be further important aspects? I think of adding important tips for the crypto core module first.

    help wanted revisitInFuture 
    opened by BrunoScheufler 41
  • Hebrew translation ืชื™ืจื’ื•ื ืœืขื‘ืจื™ืช

    Hebrew translation ืชื™ืจื’ื•ื ืœืขื‘ืจื™ืช

    Call for Hebrew translator who are willing to contribute and translate the guide to Hebrew.

    Branch was created here: https://github.com/i0natan/nodebestpractices/blob/hebrew-translation/README.hebrew.md

    cc @idori

    translation stale 
    opened by goldbergyoni 40
  • Some of the performance items

    Some of the performance items

    I've written these simply (at work atm), so you'd have to reword them if you're going to add it to the README.

    • There is significant overhead when accessing environment variables during runtime, so avoid referencing process.env per HTTP request in your server code.

    • Don't transpile your code in-memory at runtime (e.g. with transpilers like babel-register or ts-node), as they have to transpile everything and consume a lot of memory. Rather, pre-transpile your code before pushing to production.

    help wanted stale 
    opened by gerardmrk 36
  • Static vs Constructor approach

    Static vs Constructor approach

    I've been looking on the web but I could not find any good advice on whether it could be considered a good practice to use constructors (new MyClass(...params).myMethod()) over classes with only static methods (MyClass.myMethod(...params)), or the opposite.

    I would guess that the solution depends on the situation. If that is the case, could we draw some general guidance on when it is a good practice to use a constructor, and when to use the static methods approach?

    question General JS stale 
    opened by ilDon 30
  • Performance section pool of ideas

    Performance section pool of ideas

    This is our list of performance best practice ideas. Here we filter and finalize the list of items to write about.

    Based upon the discussion in https://github.com/i0natan/nodebestpractices/issues/256, this is an issue to track what bullets are approved, and/or who is working on them.

    | Title | Approved | Assigned to | Gist |---|---|---|---| | Don't block the event loop | Yes | @TheHollidayInn | Use dedicated libs, minimize CPU-bound | Use text compression | No (Generic) | | Compress static assets | Monitoring: prioritize customer-facing metrics | |@i0natan | Focus on API metrics like latency, the golden signals | Avoid synchronous functions | | |? | Replicate the Node process, for example using a cluster |Yes | | Multi-core can run even IO-only code faster! Use any replication techniques like K8S, PM2 | Use a version of node that ships with new TurboFan JIT compiler |Yes | | | Deal with database and external APIs in batches | No (Generic)| | | Benchmark slow db calls | No (Generic)| | | Use factories or constructors to ensure objects are created using the same schema so the v8 won't have to generate hidden classes on runtime | Yes| | | Analyze repeated API Calls/Database Queries to cache them | No (Generic)| | | Debounce and Throttle | | |? | Benchmarking your code with professional testing tools | Yes| | Constantly load test your app, Apache AB, Auto-canon | Analyzing and monitoring cpu bottlenecks or memory leaks with Node Clinic/Prometheus | Yes| | | Serve static assets from a CDN | No (Generic)| | | Use HTTP/2 | | |? why | Tree shaking dependencies || |? How this affects performance? | Generic performance advice |Yes | |Various performance advice that are not Node specific | Minimize the bootstrap phase ||| The process load time should be minimized, no code outside functions but declarations, measure using a tracer | When using DB ORMs/helpers, Query DB in lean mode |Yes|| Most ORMs support returning the raw DB result without spending precious time without decorating each row with custom JS prototype (huge save) | Prefer native JS methods over user-land utils like Lodash |Yes|| methods like concat & join for example, show perf diff graphs, Great article here, eslint-plugin-here, thank you @Berkmann18

    stale 
    opened by js-kyle 25
  • docs: add new section: 2.12 Always await promises before returning

    docs: add new section: 2.12 Always await promises before returning

    TL;DR: In order to have full stacktraces

    1. Always prefer return await over return when returning promises
    2. Any function that is returning a promise must be declared as async

    Issue

    opened by Alexsey 24
  • Translations status

    Translations status

    I've created a draft script to check the translation status for this repository translation-checker

    Here is a quick recap:

    • Missing 24 of 88 translation files for Brazilian Portuguese ( 21.12% )
    • Missing 36 of 88 translation files for Chinese ( 31.68% )
    • Missing 87 of 88 translation files for Indonesian ( 76.56% )
    • Missing 3 of 88 translation files for Japanese ( 2.64% )
    • Missing 50 of 88 translation files for Korean ( 44.00% )
    • Missing 22 of 88 translation files for Polish ( 19.36% )
    • Missing 19 of 88 translation files for Russian ( 16.72% )

    Basque and French seem to be ok, Japanese can probably be fixed in a short time.

    Here's the complete output with the markdown files that are currently missing per each language on master.

    Some other little misalignments that came up:

    • thincomponents.[LANGUAGE].md can probably be deleted in favor of breakintcompoentns.[LANGUAGE].md already mentioned here
    • 5 languages use userpasswords.[LANGUAGE].md and 5 languages use bcryptpasswords.[LANGUAGE].md for the password encryption topic
    • writing-guidelines.indonesia.md should be renamed in writing-guidelines.indonesian.md

    I'm not able to review these translations' contents but this may be a starting point to improve the translation workflow.

    opened by mauroaccornero 0
  • Easy to translate advice

    Easy to translate advice

    It's a great repository, no doubt. I have some suggestions that I hope will help it benefit more people.

    I think it's probably best to minimize the use of .gif or videos (e.g. here>>), because it might make it difficult for the translator to start translating (e.g. there is no translation here>>), Perhaps use multiple images instead, so that the translator can at least use Photoshop to tweak the image.

    If you need to draw some flow charts or mind maps, maybe use some of the popular tools to draw them, then export them to JSON or XML format and explain the tools used, so that the translator can easily import the format file into the tool for translation, like this>>

    I think these are necessary for a repository of 80K+ stars โญ, don't you think?

    Perhaps add these "easily translatable format suggestions" above to the writing-Guidelines.

    opened by itabbot 1
Owner
Yoni Goldberg
An independent consultant who works with 500 fortune corporates and garage startups on polishing their JS & Node.js applications www.GoldbergYoni.com
Yoni Goldberg
Chrome extension that uses vulnerabilities CVE-2021-33044 and CVE-2021-33045 to log in to Dahua cameras without authentication.

DahuaLoginBypass Chrome extension that uses vulnerability CVE-2021-33044 to log in to Dahua IP cameras and VTH/VTO (video intercom) devices without au

null 71 Nov 26, 2022
In this project, I implement a Simple To Do List with the CRUD (create, read, update, delete) methods. I followed the JavaScript, CSS, HTML, DRY, KISS and YAGNI Best practices.

To Do list: add & remove In this project, I implement a Simple To Do List with the CRUD (create, read, update, delete) methods. All the elements of th

Olivier 6 Nov 20, 2022
In this project, I built a to-do list app, which is inspired by the minimalist website. Build withHTML/CSS & JavaScript best practices: Correct use of tags, elements, properties and syntax.

Webpack Exercise In this project, I built a to-do list app, which is inspired by the minimalist website. Built With HTML/CSS & JavaScript best practic

Vanessa Oliveros 3 Oct 11, 2022
A simple CLI to patch the Fitbit OS Simulator with the new SSL certificate - March 2022

patch-fitbit-simulator Only for Mac OS currently A simple CLI to patch the Fitbit OS Simulator certificate with the new SSL certificate for the Device

Brandon Him 2 Mar 28, 2022
An IoT bottle that tracks water consumption. Winner of Best Health Hack, MLH's Best Hardware Hack, and QB3's Best Big Data for the Improvement of Health Care Winner at CruzHacks 2022.

An IoT bottle that tracks water consumption. Winner of Best Health Hack, MLH's Best Hardware Hack, and QB3's Best Big Data for the Improvement of Health Care Winner at CruzHacks 2022.

Nathanael Garza 2 Jan 21, 2022
Mongoose Node.js Express TypeScript application boilerplate with best practices for API development.

Node TypeScript Boilerplate Mongoose The main purpose of this repository is to show a good end-to-end project setup and workflow for writing a Mongoos

Chirag Mehta 20 Dec 13, 2022
A set of best practices for JavaScript projects

ไธญๆ–‡็‰ˆ | ๆ—ฅๆœฌ่ชž็‰ˆ | ํ•œ๊ตญ์–ด | ะ ัƒััะบะธะน | Portuguรชs Project Guidelines ยท While developing a new project is like rolling on a green field for you, maintaining it is

Elsewhen 28.4k Jan 1, 2023
Best practices for modern web development

Web Fundamentals on DevSite Welcome to the new WebFundamentals! An effort to showcase best practices and tools for modern Web Development. What's chan

Google 13.7k Dec 30, 2022
An easy-to-read, quick reference for JS best practices, accepted coding standards, and links around the Web

Feel free to contribute! Where? http://www.jstherightway.org Why? Today we have a bunch of websites running JavaScript. I think we need a place to put

BrazilJS 8.5k Jan 1, 2023
Enforcing best practices for Effector

eslint-plugin-effector Enforcing best practices for Effector This plugin uses TypeScript for more precise results, but JavaScript is supported too. In

effector โ˜„๏ธ 89 Dec 15, 2022
A website made using ReactJS library which displays all the best selling books of 2021 and a feature to check them on amazon.

Getting Started with Create React App This project was bootstrapped with Create React App. Available Scripts In the project directory, you can run: np

Sumanth Krishna 3 Dec 30, 2021
Some HTML, CSS and JS best practices.

Frontend Guidelines HTML Semantics HTML5 provides us with lots of semantic elements aimed to describe precisely the content. Make sure you benefit fro

Benjamin De Cock 8.1k Jan 1, 2023
A solid create-remix app, that applies best practices into a clean, batteries included template. SQLite version. Deploys to Fly.io

Remix Barebones Stack npx create-remix --template dev-xo/barebones-stack A solid create-remix app, that follows community guidelines and applies best

Dev XO 97 Dec 30, 2022
Algorithms and Data Structures implemented in TypeScript for beginners, following best practices.

The Algorithms - TypeScript TypeScript Repository of TheAlgorithms, which implements various algorithms and data structures in TypeScript. These imple

The Algorithms 166 Dec 31, 2022
Do i follow JS best practices?

To-Do-List-code-review Do i follow JS best practices? Built With HTML CSS JavaScript ES6 Webpack Live Demo (https://kelvin-ben.github.io/To-Do-list/)

Kelvin Benjamin 3 Oct 10, 2022
HITB SECCONF EDU CTF 2021. Developed with โค๏ธ by Hackerdom team and HITB.

HITB SECCCONF EDU CTF 2021 SECCONF EDU CTF is an online international challenge in information security. Developed by Hackerdom team for HITB SECCONF

HITB+ CyberWeek 18 Sep 3, 2022
ๆฑ‚ๆ˜ฏๆฝฎๆŠ€ๆœฏ 2021 ็ง‹็บณไบŒ้ข่ฏ•้ข˜

Contributor๏ผš@ๅทจ็กฌ 2021 Fall Round Two ๆญๅ–œๆ‚จ๏ผŒไปŽไผ—ๅคšzjuerไธญ่„ฑ้ข–่€Œๅ‡บ๏ผŒ้€š่ฟ‡ไบ†ๆˆ‘ไปฌ็š„็ฌฌไธ€่ฝฎ่€ƒ้ชŒใ€‚็Žฐๅœจ๏ผŒๆ‚จ่ฟ˜้œ€่ฆ่ทจ่ฟ‡ๆœ€ๅŽไธ€ไธชๅ…ณๅกโ€”โ€”โ€”โ€”่ฟ™้“ๅฐๅฐ็š„ไบŒ้ข้ข˜ใ€‚ ๆˆ‘ไปฌไธบๆ‚จ็ฒพๅฟƒๅ‡†ๅค‡ไบ†ๅ››้“่ฏ•้ข˜๏ผŒๅฎƒไปฌ้šพๅบฆไธไธ€ใ€็ฑปๅž‹ๅ„ๅผ‚ใ€‚ๆˆ‘ไปฌๅธŒๆœ›ๆ‚จ่‡ณๅฐ‘ๆŒ‘้€‰ไธ€้“ๅฎŒๆˆ๏ผŒๆฅๅ‘ๆˆ‘ไปฌๅฑ•็คบๆ‚จ่งฃๅ†ณ้—ฎ้ข˜็š„ๆ™บๆ…งๅ’Œ

ๆฑ‚ๆ˜ฏๆฝฎๆŠ€ๆœฏ็ ”ๅ‘ไธญๅฟƒ 19 Sep 22, 2022
2021 Portfolio, built with Next.js

This is a Next.js project bootstrapped with create-next-app. Getting Started First, run the development server: npm run dev # or yarn dev Open http://

Muhammad Azmi 1 Oct 9, 2022
All five assignments and the final group project is done in class CSCI5410 (Serverless Data Processing) Fall 2021 of MACS at Dalhousie University.

Dalhousie University | Fall 2021 | CSCI5410 | SDP (Serverless Data Processing) All five assignments and the final group project is done in class CSCI5

Dhrumil Shah 1 Dec 26, 2021