diff --git a/.all-contributorsrc b/.all-contributorsrc index 5daade303..8a9cc8163 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -1,9 +1,19 @@ { "files": [ - "README.md" + "README.basque.md", + "README.brazilian-portuguese.md", + "README.chinese.md", + "README.french.md", + "README.indonesian.md", + "README.japanese.md", + "README.korean.md", + "README.md", + "README.polish.md", + "README.russian.md" ], "imageSize": 100, "contributorsPerLine": 7, + "contributorTemplate": "\">\" width=\"<%= options.imageSize %>px;\" alt=\"<%= contributor.name %>\"style=\"max-width:<%= options.imageSize %>px;min-width:<%= options.imageSize %>px;\" />
<%= contributor.name %>

<%= contributions %>", "badgeTemplate": "[![All Contributors](https://img.shields.io/badge/all_contributors-<%= contributors.length %>-orange.svg?style=flat-square)](#contributors)", "contributors": [ { @@ -1131,7 +1141,8 @@ "avatar_url": "https://avatars3.githubusercontent.com/u/1078554?v=4", "profile": "http://stackoverflow.com/story/elektronik", "contributions": [ - "content" + "content", + "review" ] }, { @@ -1239,7 +1250,8 @@ "avatar_url": "https://avatars.githubusercontent.com/u/17216937?v=4", "profile": "http://www.anediaz.com", "contributions": [ - "translation" + "translation", + "content" ] }, { @@ -1323,11 +1335,427 @@ "content", "example" ] + }, + { + "login": "ariel-diaz", + "name": "ari", + "avatar_url": "https://avatars.githubusercontent.com/u/20423540?v=4", + "profile": "https://github.com/ariel-diaz", + "contributions": [ + "content" + ] + }, + { + "login": "Vispercept", + "name": "Thomas König", + "avatar_url": "https://avatars.githubusercontent.com/u/7080389?v=4", + "profile": "http://www.koenigthomas.de/", + "contributions": [ + "content" + ] + }, + { + "login": "coocos", + "name": "Kalle Lämsä", + "avatar_url": "https://avatars.githubusercontent.com/u/1397804?v=4", + "profile": "https://github.com/coocos", + "contributions": [ + "content" + ] + }, + { + "login": "ZhyMC", + "name": "Wyatt", + "avatar_url": "https://avatars.githubusercontent.com/u/10328430?v=4", + "profile": "http://math.cat", + "contributions": [ + "content" + ] + }, + { + "login": "tkhadir", + "name": "KHADIR Tayeb", + "avatar_url": "https://avatars.githubusercontent.com/u/45130488?v=4", + "profile": "http://libkhadir.fr", + "contributions": [ + "content" + ] + }, + { + "login": "shankarregmi", + "name": "Shankar Regmi", + "avatar_url": "https://avatars.githubusercontent.com/u/7703345?v=4", + "profile": "https://github.com/shankarregmi", + "contributions": [ + "content" + ] + }, + { + "login": "codebyshubham", + "name": "Shubham", + "avatar_url": "https://avatars.githubusercontent.com/u/10389723?v=4", + "profile": "https://github.com/codebyshubham", + "contributions": [ + "content" + ] + }, + { + "login": "lucalves", + "name": "Lucas Alves", + "avatar_url": "https://avatars.githubusercontent.com/u/17712401?v=4", + "profile": "http://lucalves.me/", + "contributions": [ + "content" + ] + }, + { + "login": "benjaminudoh10", + "name": "Benjamin", + "avatar_url": "https://avatars.githubusercontent.com/u/9018331?v=4", + "profile": "https://github.com/benjaminudoh10", + "contributions": [ + "content" + ] + }, + { + "login": "yjoer", + "name": "Yeoh Joer", + "avatar_url": "https://avatars.githubusercontent.com/u/47742486?v=4", + "profile": "https://www.yjoer.com", + "contributions": [ + "content" + ] + }, + { + "login": "Miigon", + "name": "Miigon", + "avatar_url": "https://avatars.githubusercontent.com/u/16161991?v=4", + "profile": "https://blog.miigon.net", + "contributions": [ + "content" + ] + }, + { + "login": "Egregor2011", + "name": "Rostislav Bogorad", + "avatar_url": "https://avatars.githubusercontent.com/u/3630318?v=4", + "profile": "http://brainstorage.me/Egregor2011", + "contributions": [ + "content" + ] + }, + { + "login": "Flouse", + "name": "Flouse", + "avatar_url": "https://avatars.githubusercontent.com/u/1297478?v=4", + "profile": "https://github.com/Flouse", + "contributions": [ + "content" + ] + }, + { + "login": "taranttini", + "name": "Tarantini Pereira", + "avatar_url": "https://avatars.githubusercontent.com/u/6922125?v=4", + "profile": "http://taranttini.com", + "contributions": [ + "content" + ] + }, + { + "login": "kzmat", + "name": "Kazuki Matsuo", + "avatar_url": "https://avatars.githubusercontent.com/u/34614358?v=4", + "profile": "https://github.com/kzmat", + "contributions": [ + "content" + ] + }, + { + "login": "burkybang", + "name": "Adam Smith", + "avatar_url": "https://avatars.githubusercontent.com/u/927886?v=4", + "profile": "https://github.com/burkybang", + "contributions": [ + "content" + ] + }, + { + "login": "k906506", + "name": "Dohyeon Ko", + "avatar_url": "https://avatars.githubusercontent.com/u/33795856?v=4", + "profile": "https://codekodo.tistory.com", + "contributions": [ + "content" + ] + }, + { + "login": "vlad99902", + "name": "Vladislav Legkov", + "avatar_url": "https://avatars.githubusercontent.com/u/67615003?v=4", + "profile": "https://github.com/vlad99902", + "contributions": [ + "content" + ] + }, + { + "login": "kerolloz", + "name": "Kerollos Magdy", + "avatar_url": "https://avatars.githubusercontent.com/u/36763164?v=4", + "profile": "http://kerolloz.github.io", + "contributions": [ + "content" + ] + }, + { + "login": "erezLieberman", + "name": "Erez Lieberman", + "avatar_url": "https://avatars.githubusercontent.com/u/3277260?v=4", + "profile": "https://www.linkedin.com/in/erez-lieberman-b90b7219/", + "contributions": [ + "content" + ] + }, + { + "login": "breno404", + "name": "Breno Macedo", + "avatar_url": "https://avatars.githubusercontent.com/u/48841329?v=4", + "profile": "https://www.linkedin.com/in/breno-macedo-ernani-de-s%C3%A1-110223158/", + "contributions": [ + "content" + ] + }, + { + "login": "JFernando122", + "name": "Fernando Flores", + "avatar_url": "https://avatars.githubusercontent.com/u/40414805?v=4", + "profile": "https://github.com/JFernando122", + "contributions": [ + "translation" + ] + }, + { + "login": "rafaelconcept", + "name": "Rafael Brito", + "avatar_url": "https://avatars.githubusercontent.com/u/43880669?v=4", + "profile": "https://www.linkedin.com/in/rafaelconcept/", + "contributions": [ + "translation" + ] + }, + { + "login": "emiperalta", + "name": "Emiliano Peralta", + "avatar_url": "https://avatars.githubusercontent.com/u/63617637?v=4", + "profile": "https://emiliano-peralta-portfolio.vercel.app/", + "contributions": [ + "translation" + ] + }, + { + "login": "lannex", + "name": "Shin, SJ", + "avatar_url": "https://avatars.githubusercontent.com/u/7369541?v=4", + "profile": "https://lannex.github.io", + "contributions": [ + "content" + ] + }, + { + "login": "e-e-e", + "name": "Benjamin Forster", + "avatar_url": "https://avatars.githubusercontent.com/u/12589522?v=4", + "profile": "http://www.benjaminforster.com", + "contributions": [ + "content" + ] + }, + { + "login": "DanieleFedeli", + "name": "Daniele Fedeli", + "avatar_url": "https://avatars.githubusercontent.com/u/37077048?v=4", + "profile": "https://github.com/DanieleFedeli", + "contributions": [ + "content" + ] + }, + { + "login": "djob195", + "name": "djob195", + "avatar_url": "https://avatars.githubusercontent.com/u/17146669?v=4", + "profile": "https://github.com/djob195", + "contributions": [ + "content" + ] + }, + { + "login": "antspk", + "name": "antspk", + "avatar_url": "https://avatars.githubusercontent.com/u/78955792?v=4", + "profile": "https://github.com/antspk", + "contributions": [ + "content" + ] + }, + { + "login": "jjy821", + "name": "정진영", + "avatar_url": "https://avatars.githubusercontent.com/u/88075341?v=4", + "profile": "https://jjy0821.tistory.com/", + "contributions": [ + "content" + ] + }, + { + "login": "kkk-cashwalk", + "name": "kkk-cashwalk", + "avatar_url": "https://avatars.githubusercontent.com/u/91455122?v=4", + "profile": "https://github.com/kkk-cashwalk", + "contributions": [ + "content" + ] + }, + { + "login": "apainintheneck", + "name": "apainintheneck", + "avatar_url": "https://avatars.githubusercontent.com/u/42982186?v=4", + "profile": "https://github.com/apainintheneck", + "contributions": [ + "content" + ] + }, + { + "login": "koyanyaroo", + "name": "Fajar Budhi Iswanda", + "avatar_url": "https://avatars.githubusercontent.com/u/9715368?v=4", + "profile": "https://github.com/koyanyaroo", + "contributions": [ + "content" + ] + }, + { + "login": "jutiger", + "name": "이주호", + "avatar_url": "https://avatars.githubusercontent.com/u/97490806?v=4", + "profile": "https://github.com/jutiger", + "contributions": [ + "content" + ] + }, + { + "login": "MisterSingh", + "name": "Singh", + "avatar_url": "https://avatars.githubusercontent.com/u/44462019?v=4", + "profile": "https://github.com/MisterSingh", + "contributions": [ + "content" + ] + }, + { + "login": "Alex-Dumitru", + "name": "Alex Dumitru", + "avatar_url": "https://avatars.githubusercontent.com/u/43738450?v=4", + "profile": "https://github.com/Alex-Dumitru", + "contributions": [ + "content" + ] + }, + { + "login": "lykhatskyi", + "name": "Anton Lykhatskyi", + "avatar_url": "https://avatars.githubusercontent.com/u/18104686?v=4", + "profile": "https://github.com/lykhatskyi", + "contributions": [ + "content" + ] + }, + { + "login": "EverythingAvailable", + "name": "sangwonlee", + "avatar_url": "https://avatars.githubusercontent.com/u/81002379?v=4", + "profile": "https://github.com/EverythingAvailable", + "contributions": [ + "content" + ] + }, + { + "login": "euberdeveloper", + "name": "Eugenio Berretta", + "avatar_url": "https://avatars.githubusercontent.com/u/33126163?v=4", + "profile": "https://github.com/euberdeveloper", + "contributions": [ + "content" + ] + }, + { + "login": "soranakk", + "name": "soranakk", + "avatar_url": "https://avatars.githubusercontent.com/u/3930307?v=4", + "profile": "https://github.com/soranakk", + "contributions": [ + "content" + ] + }, + { + "login": "backend-joonyoung", + "name": "고준영", + "avatar_url": "https://avatars.githubusercontent.com/u/94430145?v=4", + "profile": "https://github.com/backend-joonyoung", + "contributions": [ + "content", + "code" + ] + }, + { + "login": "GuilhermePortella", + "name": "Guilherme Portella ", + "avatar_url": "https://avatars.githubusercontent.com/u/59876059?v=4", + "profile": "https://github.com/GuilhermePortella", + "contributions": [ + "content" + ] + }, + { + "login": "Esser50K", + "name": "André Esser", + "avatar_url": "https://avatars.githubusercontent.com/u/18497570?v=4", + "profile": "https://www.youtube.com/channel/UCBxzOQd2v9wWfiMDrf_RQ7A", + "contributions": [ + "content" + ] + }, + { + "login": "ShiChenCong", + "name": "Scc", + "avatar_url": "https://avatars.githubusercontent.com/u/22486446?v=4", + "profile": "https://github.com/ShiChenCong", + "contributions": [ + "translation" + ] + }, + { + "login": "mauroaccornero", + "name": "Mauro Accornero", + "avatar_url": "https://avatars.githubusercontent.com/u/1875822?v=4", + "profile": "https://www.mauroaccornero.it", + "contributions": [ + "content" + ] + }, + { + "login": "no-yan", + "name": "no-yan", + "avatar_url": "https://avatars.githubusercontent.com/u/63000297?v=4", + "profile": "https://github.com/no-yan", + "contributions": [ + "content" + ] } ], "projectName": "nodebestpractices", "projectOwner": "goldbergyoni", "repoType": "github", "repoHost": "https://github.com", - "skipCi": true + "skipCi": true, + "commitConvention": "angular" } diff --git a/.github/workflows/automerge-prs.yml b/.github/workflows/automerge-prs.yml new file mode 100644 index 000000000..3f8333e46 --- /dev/null +++ b/.github/workflows/automerge-prs.yml @@ -0,0 +1,33 @@ +name: automerge +on: + pull_request: + types: + - labeled + - unlabeled + - synchronize + - opened + - edited + - ready_for_review + - reopened + - unlocked + pull_request_review: + types: + - submitted + check_suite: + types: + - completed + status: {} +jobs: + automerge: + runs-on: ubuntu-20.04 + steps: + - name: automerge + uses: "pascalgn/automerge-action@v0.15.5" + env: + GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + MERGE_LABELS: "auto-merge,!work in progress" + MERGE_REMOVE_LABELS: "auto-merge" + MERGE_FORKS: "false" + MERGE_RETRIES: "6" + MERGE_RETRY_SLEEP: "10000" + MERGE_DELETE_BRANCH: "true" diff --git a/.github/workflows/lint-and-generate-html-from-markdown.yml b/.github/workflows/lint-and-generate-html-from-markdown.yml new file mode 100644 index 000000000..9c62c5b4b --- /dev/null +++ b/.github/workflows/lint-and-generate-html-from-markdown.yml @@ -0,0 +1,30 @@ +name: Lint & Generate HTML from Markdown +on: + push: + branches: + - master + pull_request: + +defaults: + run: + shell: bash + working-directory: .operations + +jobs: + lint: + name: Lint + runs-on: ubuntu-20.04 + env: + NODE_ENV: test + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Setup Node.js environment + uses: actions/setup-node@v3 + with: + node-version: "18" + + - run: npm install + - run: npm run lint diff --git a/.github/workflows/update-date-in-last-update-badge.yml b/.github/workflows/update-date-in-last-update-badge.yml new file mode 100644 index 000000000..c440307be --- /dev/null +++ b/.github/workflows/update-date-in-last-update-badge.yml @@ -0,0 +1,39 @@ +name: Update date in last update badge +on: + push: + branches: + - master + +jobs: + run: + name: Update the date in last update badge to today + runs-on: ubuntu-20.04 + + # Limit this action to only run on the main repo and not on forks + if: github.repository_owner == 'goldbergyoni' + + steps: + - name: Checkout repo + uses: actions/checkout@v3 + + - name: Update last update badge + run: | + # Make file runnable + chmod +x "${GITHUB_WORKSPACE}/.github/workflows/update-last-update-badge.sh" + # Run script + "${GITHUB_WORKSPACE}/.github/workflows/update-last-update-badge.sh" "${GITHUB_WORKSPACE}/README.md" + + - name: Commit & Create Pull Request + uses: peter-evans/create-pull-request@v4 + with: + commit-message: update the last update badge to today [skip ci] + author: Update Last Update Badge Action <${{ github.actor }}@users.noreply.github.com> + branch: update-last-update-badge + delete-branch: true + title: 'Update last update badge to today [skip ci]' + labels: | + update-last-update-badge + auto-merge + + # Force empty body as the action have default body + body: '' diff --git a/.github/workflows/update-last-update-badge.sh b/.github/workflows/update-last-update-badge.sh new file mode 100755 index 000000000..4765439a8 --- /dev/null +++ b/.github/workflows/update-last-update-badge.sh @@ -0,0 +1,61 @@ +#!/bin/bash +set -e + +INPUT_FILE=$1 + +url_encode() { + # url_encode + local length="${#1}" + for (( i = 0; i < length; i++ )); do + local c="${1:i:1}" + case $c in + [a-zA-Z0-9.~_-]) printf "$c" ;; + *) printf '%%%02X' "'$c" ;; + esac + done +} + +is_there_last_update_badge() { + local input_file=$1 + local updated_badge_regex=$2 + + if grep -q "$updated_badge_regex" "$input_file"; then return 0 + else return 1 + fi +} + +is_last_update_badge_date_is_today() { + local input_file=$1 + local updated_badge=$2 + + if grep -q "$updated_badge" "$input_file"; then return 0 + else return 1 + fi +} + + +# We use already encoded string emoji because I'm on Windows and the calendar emoji failed to render +CALENDAR_EMOJI_ENCODED='%F0%9F%93%85' + +# Date format example: March 03, 2021 +CURRENT_DATE=`date +"%B %d, %Y"` + +# We explicitly matching the img.shields.io/badge because when we change the provider of the badge the input will be changed too +LAST_UPDATE_BADGE_REGEX='\"Last" + + +if ! is_there_last_update_badge "$INPUT_FILE" "$LAST_UPDATE_BADGE_REGEX"; then + # Print with red foreground + echo -e "\033[31mError: Can't find Last update badge\033[m" + exit 1 +fi + +if is_last_update_badge_date_is_today "$INPUT_FILE" "$UPDATED_LAST_UPDATE_BADGE"; then + echo "No need to update the $INPUT_FILE, the last update badge already pointing to today" + exit 0 +fi + +sed -i "s@$LAST_UPDATE_BADGE_REGEX@$UPDATED_LAST_UPDATE_BADGE@" "$INPUT_FILE" diff --git a/.operations/.env.example b/.operations/.env.example deleted file mode 100644 index 77e1c98da..000000000 --- a/.operations/.env.example +++ /dev/null @@ -1 +0,0 @@ -GITHUB_TOKEN=REPLACEME \ No newline at end of file diff --git a/.operations/CONTRIBUTING.md b/.operations/CONTRIBUTING.md index e4cc92119..2e9f76905 100644 --- a/.operations/CONTRIBUTING.md +++ b/.operations/CONTRIBUTING.md @@ -1,44 +1,61 @@ # Contribution guidelines -## What you should know first? - -### Lovely & friendly atmosphere +## Lovely & friendly atmosphere Our code of conduct is 5 words long: we are all friends here We recognize that being professional and kind are the same thing and strive to maximize our professionalism -### Maintenance work +## Handling issues and PRs -Our operations manual [can be found here](https://github.com/goldbergyoni/nodebestpractices/blob/master/.operations/operations-manual.md) +
+In a nutshell, every issue is an opprtunity to gain new knowledge and attract new contributor. Therefore we aim for vast response and welcoming words 💚 -### Writing guidelines +When merging a new PR, add the contributor to our credits list using the all-contributors bot. Just include this text as a PR comment: -Our content writing guidelines [can be found here](https://github.com/goldbergyoni/nodebestpractices/blob/master/.operations/writing-guidelines.md) +`@all-contributors please add @username for content` +The specific PR/issue resolustion depends on its kind: -## Contribution model +**A. New best practice or fundamental changes to existing content -** In that case, involve at least 1 other members to solicit enough feedback for this change. Start by greeting the contributor, ensure the formalities are fine, ensure it conforms to our [writing guidelines](./writing-guidelines.md), ensure enough information was provided and then get at least 1 more collaborators and allow at least a week for comments -### Steering committee 🏆 +**B. Plain text change (e.g. Grammar correctness) -** When super-simple wording edits are proposed (i.e. not new content rather language correctness), one can just greet, approve and merge immediately -Members of the steering committee work together to provide guidance and future direction to the project. Each committee member has a particular expertise which they share their knowledge on, and work to lead further improvements to the project in that area. The steering committee members are responsible for approving new best practices, and ensuring current best practices remain relevant. +**C. Translations to a new (not existing) language -** When offered to add new language, greet the person and paste our [translation guidelines](./common-answers.md) -### Collaborators 👍 +**D. Edits to existing translations -** If the change can be inferred by the reviewer (e.g., a change of a symbol, number or just date update) then feel free to merge alone. If familiarity with the language is needed, tag the original translator and ask for feedback. The translators name can be found in the home page under "Translations" -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. Along with the steering committee, each collaborator leads a project tracked under our Github projects. +**D. Dicussions and ideas -** When a technical discussion or just general conversation is brought into a new issue, apply your own judgements whether to tag other collaborators -The role is in place to help the steering committee ensure that the content provided is of a high standard, up-to-date with the industry, and available in many languages. Members who frequently participate in these activities will be invited to become a collaborator, based on the quality of their contributions. -The steering committee periodically reviews the collaborator list to identify inactive collaborators. Inactive collaborators can choose to either continue in or step down from their role, in which case they are acknowledged as a past collaborator. They may later request that the steering committee restore them to active status. +## Assets to be aware of -### Other contributions ✨ +- Our content writing guidelines [can be found here](./writing-guidelines.md) +- Common questions and answers to issues/PRs [can be found here](./common-answers.md) -This project follows the [All Contributors Specification](https://allcontributors.org/), which means we recognize all types of contributions, whether they are new suggested best practices/ideas, translations, or new content. +## Precommit -If you have contributed to the project in some way and aren't listed, please add an entry for yourself by using the @all-contributors-bot in a Pull Request or issue. Examples: +Before pushing, verify your Markdown passes [the linter](https://www.npmjs.com/package/markdownlint-cli) : -`@all-contributors-bot please add @js-kyle for code` +```bash +npm run lint +``` +For example fix basic errors : -`@all-contributors-bot please add @brunoscheufler for content` +```bash +npm run lint --fix +``` -Contribution types are listed [here](https://allcontributors.org/docs/en/emoji-key). +## Contribution model + +### Steering committee 🏆 + +Members of the steering committee work together to provide guidance and future direction to the project. Each committee member has a particular expertise which they share their knowledge on, and work to lead further improvements to the project in that area. The steering committee members are responsible for approving new best practices, and ensuring current best practices remain relevant. + +### Collaborators 👍 + +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. Along with the steering committee, each collaborator leads a project tracked under our Github projects. + +The role is in place to help the steering committee ensure that the content provided is of high standard, up-to-date with the industry, and available in many languages. Members who frequently participate in these activities will be invited to become a collaborator, based on the quality of their contributions. + +The steering committee periodically reviews the collaborator list to identify inactive collaborators. Inactive collaborators can choose to either continue in or step down from their role, in which case they are acknowledged as a past collaborator. They may later request that the steering committee restore them to active status. diff --git a/.operations/.common-answers.md b/.operations/common-answers.md similarity index 63% rename from .operations/.common-answers.md rename to .operations/common-answers.md index 184e8f16d..5cfa72f77 100644 --- a/.operations/.common-answers.md +++ b/.operations/common-answers.md @@ -1,17 +1,17 @@ **Welcoming new translators** -@name - Welcome aboard, it's great to have you here 🎆 +@name - Welcome aboard, it's great to have you here! 🎆 -Having A Slovak translation could be awesome! At the end, we can Tweet about this, put in our news section, include your name at the top of the translated language and also at the main home page contributors list +Having A Slovak translation could be awesome! At the end, we can Tweet about this, put in our news section, include your name at the top of the translated language and also at the main home page contributors list. Let's go for this? Few basic guideliness: -- Work on your own fork - Fork this repo, create a branch for yourself, translate & collaborate with other translators, then finally when ready create a PR +- Work on your own fork - Fork this repo, create a branch for yourself, translate & collaborate with other translators, then finally when ready create a PR. -- Focus on translation, not content editing - The focus is on translation, should you want to modify the content or the graphics - let's PR first in English and then translate to other languages. Also the format of the text should remain intact (same design) +- Focus on translation, not content editing - The focus is on translation, should you want to modify the content or the graphics - let's PR first in English and then translate to other languages. Also the format of the text should remain intact (same design). -- Duplicate the readme and the inner pages - Tthe content should be translated over a page duplication. Readme.MD became Readme.{translated-language}.MD (e.g. readme.french.md), all other files should be duplicated similarly. So the number of English & translated pages should be the same. You may see examples in currently translated languages +- Duplicate the readme and the inner pages - The content should be translated over a page duplication. readme.md became readme.{translated-language}.md (e.g. readme.french.md), all other files should be duplicated similarly. So the number of English & translated pages should be the same. You may see examples in currently translated languages. -Collaborate - once you do the basic setup (branch, duplicate pages), we can announce the work on a new language and get others involved and help you in translation (if you wish) +Collaborate - once you do the basic setup (branch, duplicate pages), we can announce the work on a new language and get others involved and help you in translation (if you wish). -We're here to help - let us know whether we can do anything to support you. We can Tweet about this work, put homepage banner or anything else +We're here to help - let us know whether we can do anything to support you. We can Tweet about this work, put homepage banner or anything else. diff --git a/.operations/gen-html.js b/.operations/gen-html.js deleted file mode 100644 index 6a4abd10b..000000000 --- a/.operations/gen-html.js +++ /dev/null @@ -1,226 +0,0 @@ -const path = require('path'); -const cheerio = require('cheerio'); -const showdown = require('showdown'); -const Repository = require('github-api/dist/components/Repository'); -const { readdir, readFile, writeFile } = require('graceful-fs'); - -const imagemin = require('imagemin'); -const imageminJpegtran = require('imagemin-jpegtran'); -const imageminPngquant = require('imagemin-pngquant'); - -const converter = new showdown.Converter(); - -const templateFilePath = './.operations/res/template.html'; - -const imageminOpts = { - plugins: [ - imageminJpegtran(), - imageminPngquant({ quality: '65-80' }) - ] -}; - -console.info(`Working in [${process.cwd()}]`); - -const { GITHUB_TOKEN, TRAVIS_BRANCH, TRAVIS, TRAVIS_REPO_SLUG } = process.env; -const isCI = !!TRAVIS; - -readDirPromise('./') - .then(async (fileNames) => { - const indexFileNames = fileNames.filter(fn => fn.includes('README.') && fn.includes('.md')); - - for (let fileName of indexFileNames) { - const startTime = new Date(); - console.info(`Beginning Generate Document [${fileName}] at [${startTime.toISOString()}]`); - try { - const templateHTML = await readFilePromise(templateFilePath); - const processedTemplateHTML = await inlineResources(templateHTML); - const outputHTML = await processMDFile(fileName, processedTemplateHTML); - console.info(`Completed Generation in [${(Date.now() - startTime) / 1000}s]`); - - const outFileName = path.parse(fileName).name + '.html'; - const outFilePath = path.join('.operations', 'out', outFileName); - console.info(`Writing output to [${outFilePath}]`); - await writeFilePromise(outFilePath, outputHTML); - - if (isCI && TRAVIS_BRANCH === 'master') { - const repo = new Repository(TRAVIS_REPO_SLUG, { - token: GITHUB_TOKEN - }); - - console.info(`Committing HTML file to branch [gh-pages]`); - await repo.writeFile('gh-pages', outFileName, outputHTML, ':loudspeaker: :robot: Automatically updating built HTML file', {}); - } - } catch (err) { - console.error(`Failed to generate from [${fileName}] in [${(Date.now() - startTime) / 1000}s]`, err); - process.exit(1); - } - } - }) - .then(() => { - console.log(`🎉 Finished gen-html 🎉`); - }) - - - -async function processMDFile(filePath = '/', templateHTML = null) { - let mdSrc; - try { - mdSrc = await readFilePromise(filePath); - } catch (err) { - console.warn(`Failed to read file [${filePath}], does it exist?`); - return ''; - } - const generatedHTML = converter.makeHtml(mdSrc); - let nexHTML = generatedHTML; - if (templateHTML) { - const $ = cheerio.load(templateHTML); - $('.content').html(generatedHTML); - nexHTML = $.html(); - } - - const fileDir = path.parse(filePath).dir.replace(process.cwd(), '/') || '/'; - - console.log(`Processing file [${filePath}]`); - const outHtml = await ( - inlineLocalReferences(nexHTML, fileDir) - .then((html) => fixMdReferences(html)) - .then((html) => fixHashAs(html)) - .then((html) => inlineAssets(html, fileDir)) - ); - - return outHtml; -} - -const internalRefRegExp = /^((?!http)(?!#)(?!\/\/).)*$/; // Doesn't start with 'http', '//', or '#' -async function inlineLocalReferences(html, filePath = '/') { - const $ = cheerio.load(html); - const as = $('a'); - const internalAs = as.toArray().filter((a) => internalRefRegExp.test(a.attribs.href) && !a.attribs.href.includes('README')); - - const processedInternalRefs = await Promise.all( - internalAs.map((a) => processMDFile(path.resolve(filePath, a.attribs.href))) - ); - - processedInternalRefs.forEach((processedHTML, index) => { - const originalA = $(internalAs[index]); - - const contentId = originalA.text().replace(/[^A-Za-z0-9]/g, '_'); - $('.references').append([ - $('
'), - $('
') - .addClass('reference-section') - .attr('id', contentId) - .html(processedHTML) - ]); - - originalA.attr('href', `#${contentId}`); - }); - - return $.html(); -} - -async function fixMdReferences(html) { // Primarily for links to translations - const $ = cheerio.load(html); - const as = $('a'); - const mdReferences = as.toArray().filter((a) => internalRefRegExp.test(a.attribs.href) && a.attribs.href.includes('.md')); - - mdReferences - .forEach((a) => { - const $a = $(a); - const href = $a.attr('href') - const newHref = href.replace('.md', '.html'); - $a.attr('href', './' + newHref); - }) - - return $.html(); -} - -async function inlineAssets(html, filePath = '/') { - const $ = cheerio.load(html); - const imgs = $('img'); - const internalImgs = imgs.toArray().filter((img) => internalRefRegExp.test(img.attribs.src)); - - for (let img of internalImgs) { - const ext = path.parse(img.attribs.src).ext.slice(1); // parse().ext includes '.' - const imgPath = path.resolve('/', filePath, img.attribs.src); - const imgBuffer = await readFilePromise(imgPath, null); - const compressedImgBuffer = await imagemin.buffer(imgBuffer, imageminOpts); - const base64 = compressedImgBuffer.toString('base64'); - const mediaUri = `data:image/${ext};base64,${base64}`; - const originalImg = $(img); - originalImg.attr('src', mediaUri); - } - - return $.html(); -} - -async function fixHashAs(html) { - const $ = cheerio.load(html); - const as = $('a'); - - const hashAs = as.toArray().filter((a) => a.attribs.href[0] === '#'); - hashAs.forEach(a => { - $(a).attr('href', a.attribs.href.replace(/-/g, '')); - }); - - return $.html() -} - - - -async function inlineResources(html, filePath = '/') { - const $ = cheerio.load(html); - const scripts = $('script[src]'); - const links = $('link[href]'); - - const internalScripts = scripts.toArray().filter((script) => internalRefRegExp.test(script.attribs.src)); - const internalLinks = links.toArray().filter((link) => internalRefRegExp.test(link.attribs.href)); - - for (let scriptEl of internalScripts) { - const scriptPath = path.resolve('/', filePath, scriptEl.attribs.src); - const scriptBuffer = await readFilePromise(scriptPath, null); - const base64 = scriptBuffer.toString('base64'); - const mediaUri = `data:text/javascript;base64,${base64}`; - $(scriptEl).attr('src', mediaUri); - } - - for (let linkEl of internalLinks) { - const linkPath = path.resolve('/', filePath, linkEl.attribs.href); - const linkBuffer = await readFilePromise(linkPath, null); - const base64 = linkBuffer.toString('base64'); - const mediaUri = `data:text/css;base64,${base64}`; - $(linkEl).attr('href', mediaUri); - } - - return $.html(); -} - - - - -function readFilePromise(filePath, encoding = 'utf8') { - return new Promise((resolve, reject) => { - readFile(path.resolve(process.cwd(), './' + filePath), encoding, (err, content) => { - if (err) reject(err); - else resolve(content); - }); - }); -} - -function writeFilePromise(filePath, encoding = 'utf8') { - return new Promise((resolve, reject) => { - writeFile(path.resolve(process.cwd(), './' + filePath), encoding, (err, content) => { - if (err) reject(err); - else resolve(content); - }); - }); -} - -function readDirPromise(dirPath) { - return new Promise((resolve, reject) => { - readdir(path.resolve(process.cwd(), dirPath), (err, files) => { - if (err) reject(err); - else resolve(files); - }); - }); -} \ No newline at end of file diff --git a/.operations/operations-manual.md b/.operations/operations-manual.md index f7b3fcb92..1c7595099 100644 --- a/.operations/operations-manual.md +++ b/.operations/operations-manual.md @@ -1,19 +1,19 @@ # Operations Manual - Organizing and Maximizing Our Work -Building a community and knowledge by efficiently handling issues +Building knowledge and a community by efficiently handling issues -## Handling issues and PR +## Handling issues and PRs
-In a nutshell, every issue and PR should get tagged by one of our core team and routed to the person who specializes in the related topic. This person then, will warmly welcome and kick the discussion shortly (hopefully within 48 hours). The goal of each issue/PR is to learn new thing that might improve our repo and try joining the opener to our forces. +In a nutshell, every issue and PR should get tagged by one of our core team and routed to the person who specializes in the related topic. This person then, will warmly welcome the contributor and then kick off the discussion (hopefully within 48 hours). The goal of each issue/PR is to learn new thing that might improve our repo and try to include the contributor in our army. There is no specific person on call who assigns inquiries rather we count on our core team to visit almost everyday and assign issues/PR - this way, the workflow is not depend upon any specific person rather on our entire team. -Any new content should conform to our [writing guidelines](https://github.com/goldbergyoni/nodebestpractices/blob/master/.operations/writing-guidelines.md) +Any new content should conform to our [writing guidelines](./writing-guidelines.md) ## Monthly maintenance
-Each month, a maintainer on call will open an issue for maintenance work and record within all the actions to perform by the end of the month (e.g. assign flower to a contributor). On the end of the corresponding month, the maintainer will run the following checklist +Each month, a maintainer on call will open an issue for a maintenance work checklist and write down all the actions to perform by the end of the month (e.g. assign flower to a contributor). At the end of the month, that maintainer will perform the tasks on the checklist. --- @@ -55,8 +55,8 @@ Each month, a maintainer on call will open an issue for maintenance work and rec | Topic | Examples | Assignee | |--------------------------|-----------------------------------------------------|------------------------------------| -| Code standards and fixes | Code typos, code standards, examples refinements | Bruno | -| Translations | Adding new language, merging language PRs | Monthly rotation October - Yoni | +| Code standards and fixes | Code typos, code standards, examples refinements | Bruno | +| Translations | Adding new language, merging language PRs | Monthly rotation October - Yoni | | General Writing quality | Typos, text clarify | Bruno | | Javascript runtime | JS runtime, syntax correctness | Sagir | | Devops | Monitoring, hardening a production site, deployment | Kyle | diff --git a/.operations/out/.gitignore b/.operations/out/.gitignore deleted file mode 100644 index d6b7ef32c..000000000 --- a/.operations/out/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!.gitignore diff --git a/.operations/res/github.css b/.operations/res/github.css deleted file mode 100644 index 791932b87..000000000 --- a/.operations/res/github.css +++ /dev/null @@ -1,99 +0,0 @@ -/* - -github.com style (c) Vasily Polovnyov - -*/ - -.hljs { - display: block; - overflow-x: auto; - padding: 0.5em; - color: #333; - background: #f8f8f8; -} - -.hljs-comment, -.hljs-quote { - color: #998; - font-style: italic; -} - -.hljs-keyword, -.hljs-selector-tag, -.hljs-subst { - color: #333; - font-weight: bold; -} - -.hljs-number, -.hljs-literal, -.hljs-variable, -.hljs-template-variable, -.hljs-tag .hljs-attr { - color: #008080; -} - -.hljs-string, -.hljs-doctag { - color: #d14; -} - -.hljs-title, -.hljs-section, -.hljs-selector-id { - color: #900; - font-weight: bold; -} - -.hljs-subst { - font-weight: normal; -} - -.hljs-type, -.hljs-class .hljs-title { - color: #458; - font-weight: bold; -} - -.hljs-tag, -.hljs-name, -.hljs-attribute { - color: #000080; - font-weight: normal; -} - -.hljs-regexp, -.hljs-link { - color: #009926; -} - -.hljs-symbol, -.hljs-bullet { - color: #990073; -} - -.hljs-built_in, -.hljs-builtin-name { - color: #0086b3; -} - -.hljs-meta { - color: #999; - font-weight: bold; -} - -.hljs-deletion { - background: #fdd; -} - -.hljs-addition { - background: #dfd; -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} diff --git a/.operations/res/highlight.pack.js b/.operations/res/highlight.pack.js deleted file mode 100644 index b64bd7d80..000000000 --- a/.operations/res/highlight.pack.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! highlight.js v9.13.1 | BSD3 License | git.io/hljslicense */ -!function(e){var n="object"==typeof window&&window||"object"==typeof self&&self;"undefined"!=typeof exports?e(exports):n&&(n.hljs=e({}),"function"==typeof define&&define.amd&&define([],function(){return n.hljs}))}(function(e){function n(e){return e.replace(/&/g,"&").replace(//g,">")}function t(e){return e.nodeName.toLowerCase()}function r(e,n){var t=e&&e.exec(n);return t&&0===t.index}function a(e){return k.test(e)}function i(e){var n,t,r,i,o=e.className+" ";if(o+=e.parentNode?e.parentNode.className:"",t=M.exec(o))return w(t[1])?t[1]:"no-highlight";for(o=o.split(/\s+/),n=0,r=o.length;r>n;n++)if(i=o[n],a(i)||w(i))return i}function o(e){var n,t={},r=Array.prototype.slice.call(arguments,1);for(n in e)t[n]=e[n];return r.forEach(function(e){for(n in e)t[n]=e[n]}),t}function c(e){var n=[];return function r(e,a){for(var i=e.firstChild;i;i=i.nextSibling)3===i.nodeType?a+=i.nodeValue.length:1===i.nodeType&&(n.push({event:"start",offset:a,node:i}),a=r(i,a),t(i).match(/br|hr|img|input/)||n.push({event:"stop",offset:a,node:i}));return a}(e,0),n}function u(e,r,a){function i(){return e.length&&r.length?e[0].offset!==r[0].offset?e[0].offset"}function c(e){l+=""}function u(e){("start"===e.event?o:c)(e.node)}for(var s=0,l="",f=[];e.length||r.length;){var g=i();if(l+=n(a.substring(s,g[0].offset)),s=g[0].offset,g===e){f.reverse().forEach(c);do u(g.splice(0,1)[0]),g=i();while(g===e&&g.length&&g[0].offset===s);f.reverse().forEach(o)}else"start"===g[0].event?f.push(g[0].node):f.pop(),u(g.splice(0,1)[0])}return l+n(a.substr(s))}function s(e){return e.v&&!e.cached_variants&&(e.cached_variants=e.v.map(function(n){return o(e,{v:null},n)})),e.cached_variants||e.eW&&[o(e)]||[e]}function l(e){function n(e){return e&&e.source||e}function t(t,r){return new RegExp(n(t),"m"+(e.cI?"i":"")+(r?"g":""))}function r(a,i){if(!a.compiled){if(a.compiled=!0,a.k=a.k||a.bK,a.k){var o={},c=function(n,t){e.cI&&(t=t.toLowerCase()),t.split(" ").forEach(function(e){var t=e.split("|");o[t[0]]=[n,t[1]?Number(t[1]):1]})};"string"==typeof a.k?c("keyword",a.k):B(a.k).forEach(function(e){c(e,a.k[e])}),a.k=o}a.lR=t(a.l||/\w+/,!0),i&&(a.bK&&(a.b="\\b("+a.bK.split(" ").join("|")+")\\b"),a.b||(a.b=/\B|\b/),a.bR=t(a.b),a.endSameAsBegin&&(a.e=a.b),a.e||a.eW||(a.e=/\B|\b/),a.e&&(a.eR=t(a.e)),a.tE=n(a.e)||"",a.eW&&i.tE&&(a.tE+=(a.e?"|":"")+i.tE)),a.i&&(a.iR=t(a.i)),null==a.r&&(a.r=1),a.c||(a.c=[]),a.c=Array.prototype.concat.apply([],a.c.map(function(e){return s("self"===e?a:e)})),a.c.forEach(function(e){r(e,a)}),a.starts&&r(a.starts,i);var u=a.c.map(function(e){return e.bK?"\\.?("+e.b+")\\.?":e.b}).concat([a.tE,a.i]).map(n).filter(Boolean);a.t=u.length?t(u.join("|"),!0):{exec:function(){return null}}}}r(e)}function f(e,t,a,i){function o(e){return new RegExp(e.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&"),"m")}function c(e,n){var t,a;for(t=0,a=n.c.length;a>t;t++)if(r(n.c[t].bR,e))return n.c[t].endSameAsBegin&&(n.c[t].eR=o(n.c[t].bR.exec(e)[0])),n.c[t]}function u(e,n){if(r(e.eR,n)){for(;e.endsParent&&e.parent;)e=e.parent;return e}return e.eW?u(e.parent,n):void 0}function s(e,n){return!a&&r(n.iR,e)}function p(e,n){var t=R.cI?n[0].toLowerCase():n[0];return e.k.hasOwnProperty(t)&&e.k[t]}function d(e,n,t,r){var a=r?"":j.classPrefix,i='',i+n+o}function h(){var e,t,r,a;if(!E.k)return n(k);for(a="",t=0,E.lR.lastIndex=0,r=E.lR.exec(k);r;)a+=n(k.substring(t,r.index)),e=p(E,r),e?(M+=e[1],a+=d(e[0],n(r[0]))):a+=n(r[0]),t=E.lR.lastIndex,r=E.lR.exec(k);return a+n(k.substr(t))}function b(){var e="string"==typeof E.sL;if(e&&!L[E.sL])return n(k);var t=e?f(E.sL,k,!0,B[E.sL]):g(k,E.sL.length?E.sL:void 0);return E.r>0&&(M+=t.r),e&&(B[E.sL]=t.top),d(t.language,t.value,!1,!0)}function v(){y+=null!=E.sL?b():h(),k=""}function m(e){y+=e.cN?d(e.cN,"",!0):"",E=Object.create(e,{parent:{value:E}})}function N(e,n){if(k+=e,null==n)return v(),0;var t=c(n,E);if(t)return t.skip?k+=n:(t.eB&&(k+=n),v(),t.rB||t.eB||(k=n)),m(t,n),t.rB?0:n.length;var r=u(E,n);if(r){var a=E;a.skip?k+=n:(a.rE||a.eE||(k+=n),v(),a.eE&&(k=n));do E.cN&&(y+=I),E.skip||E.sL||(M+=E.r),E=E.parent;while(E!==r.parent);return r.starts&&(r.endSameAsBegin&&(r.starts.eR=r.eR),m(r.starts,"")),a.rE?0:n.length}if(s(n,E))throw new Error('Illegal lexeme "'+n+'" for mode "'+(E.cN||"")+'"');return k+=n,n.length||1}var R=w(e);if(!R)throw new Error('Unknown language: "'+e+'"');l(R);var x,E=i||R,B={},y="";for(x=E;x!==R;x=x.parent)x.cN&&(y=d(x.cN,"",!0)+y);var k="",M=0;try{for(var C,A,S=0;;){if(E.t.lastIndex=S,C=E.t.exec(t),!C)break;A=N(t.substring(S,C.index),C[0]),S=C.index+A}for(N(t.substr(S)),x=E;x.parent;x=x.parent)x.cN&&(y+=I);return{r:M,value:y,language:e,top:E}}catch(O){if(O.message&&-1!==O.message.indexOf("Illegal"))return{r:0,value:n(t)};throw O}}function g(e,t){t=t||j.languages||B(L);var r={r:0,value:n(e)},a=r;return t.filter(w).filter(x).forEach(function(n){var t=f(n,e,!1);t.language=n,t.r>a.r&&(a=t),t.r>r.r&&(a=r,r=t)}),a.language&&(r.second_best=a),r}function p(e){return j.tabReplace||j.useBR?e.replace(C,function(e,n){return j.useBR&&"\n"===e?"
":j.tabReplace?n.replace(/\t/g,j.tabReplace):""}):e}function d(e,n,t){var r=n?y[n]:t,a=[e.trim()];return e.match(/\bhljs\b/)||a.push("hljs"),-1===e.indexOf(r)&&a.push(r),a.join(" ").trim()}function h(e){var n,t,r,o,s,l=i(e);a(l)||(j.useBR?(n=document.createElementNS("http://www.w3.org/1999/xhtml","div"),n.innerHTML=e.innerHTML.replace(/\n/g,"").replace(//g,"\n")):n=e,s=n.textContent,r=l?f(l,s,!0):g(s),t=c(n),t.length&&(o=document.createElementNS("http://www.w3.org/1999/xhtml","div"),o.innerHTML=r.value,r.value=u(t,c(o),s)),r.value=p(r.value),e.innerHTML=r.value,e.className=d(e.className,l,r.language),e.result={language:r.language,re:r.r},r.second_best&&(e.second_best={language:r.second_best.language,re:r.second_best.r}))}function b(e){j=o(j,e)}function v(){if(!v.called){v.called=!0;var e=document.querySelectorAll("pre code");E.forEach.call(e,h)}}function m(){addEventListener("DOMContentLoaded",v,!1),addEventListener("load",v,!1)}function N(n,t){var r=L[n]=t(e);r.aliases&&r.aliases.forEach(function(e){y[e]=n})}function R(){return B(L)}function w(e){return e=(e||"").toLowerCase(),L[e]||L[y[e]]}function x(e){var n=w(e);return n&&!n.disableAutodetect}var E=[],B=Object.keys,L={},y={},k=/^(no-?highlight|plain|text)$/i,M=/\blang(?:uage)?-([\w-]+)\b/i,C=/((^(<[^>]+>|\t|)+|(?:\n)))/gm,I="
",j={classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:void 0};return e.highlight=f,e.highlightAuto=g,e.fixMarkup=p,e.highlightBlock=h,e.configure=b,e.initHighlighting=v,e.initHighlightingOnLoad=m,e.registerLanguage=N,e.listLanguages=R,e.getLanguage=w,e.autoDetection=x,e.inherit=o,e.IR="[a-zA-Z]\\w*",e.UIR="[a-zA-Z_]\\w*",e.NR="\\b\\d+(\\.\\d+)?",e.CNR="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",e.BNR="\\b(0b[01]+)",e.RSR="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",e.BE={b:"\\\\[\\s\\S]",r:0},e.ASM={cN:"string",b:"'",e:"'",i:"\\n",c:[e.BE]},e.QSM={cN:"string",b:'"',e:'"',i:"\\n",c:[e.BE]},e.PWM={b:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/},e.C=function(n,t,r){var a=e.inherit({cN:"comment",b:n,e:t,c:[]},r||{});return a.c.push(e.PWM),a.c.push({cN:"doctag",b:"(?:TODO|FIXME|NOTE|BUG|XXX):",r:0}),a},e.CLCM=e.C("//","$"),e.CBCM=e.C("/\\*","\\*/"),e.HCM=e.C("#","$"),e.NM={cN:"number",b:e.NR,r:0},e.CNM={cN:"number",b:e.CNR,r:0},e.BNM={cN:"number",b:e.BNR,r:0},e.CSSNM={cN:"number",b:e.NR+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",r:0},e.RM={cN:"regexp",b:/\//,e:/\/[gimuy]*/,i:/\n/,c:[e.BE,{b:/\[/,e:/\]/,r:0,c:[e.BE]}]},e.TM={cN:"title",b:e.IR,r:0},e.UTM={cN:"title",b:e.UIR,r:0},e.METHOD_GUARD={b:"\\.\\s*"+e.UIR,r:0},e});hljs.registerLanguage("xml",function(s){var e="[A-Za-z0-9\\._:-]+",t={eW:!0,i:/`]+/}]}]}]};return{aliases:["html","xhtml","rss","atom","xjb","xsd","xsl","plist"],cI:!0,c:[{cN:"meta",b:"",r:10,c:[{b:"\\[",e:"\\]"}]},s.C("",{r:10}),{b:"<\\!\\[CDATA\\[",e:"\\]\\]>",r:10},{cN:"meta",b:/<\?xml/,e:/\?>/,r:10},{b:/<\?(php)?/,e:/\?>/,sL:"php",c:[{b:"/\\*",e:"\\*/",skip:!0},{b:'b"',e:'"',skip:!0},{b:"b'",e:"'",skip:!0},s.inherit(s.ASM,{i:null,cN:null,c:null,skip:!0}),s.inherit(s.QSM,{i:null,cN:null,c:null,skip:!0})]},{cN:"tag",b:"|$)",e:">",k:{name:"style"},c:[t],starts:{e:"",rE:!0,sL:["css","xml"]}},{cN:"tag",b:"|$)",e:">",k:{name:"script"},c:[t],starts:{e:"",rE:!0,sL:["actionscript","javascript","handlebars","xml"]}},{cN:"tag",b:"",c:[{cN:"name",b:/[^\/><\s]+/,r:0},t]}]}});hljs.registerLanguage("nginx",function(e){var r={cN:"variable",v:[{b:/\$\d+/},{b:/\$\{/,e:/}/},{b:"[\\$\\@]"+e.UIR}]},b={eW:!0,l:"[a-z/_]+",k:{literal:"on off yes no true false none blocked debug info notice warn error crit select break last permanent redirect kqueue rtsig epoll poll /dev/poll"},r:0,i:"=>",c:[e.HCM,{cN:"string",c:[e.BE,r],v:[{b:/"/,e:/"/},{b:/'/,e:/'/}]},{b:"([a-z]+):/",e:"\\s",eW:!0,eE:!0,c:[r]},{cN:"regexp",c:[e.BE,r],v:[{b:"\\s\\^",e:"\\s|{|;",rE:!0},{b:"~\\*?\\s+",e:"\\s|{|;",rE:!0},{b:"\\*(\\.[a-z\\-]+)+"},{b:"([a-z\\-]+\\.)+\\*"}]},{cN:"number",b:"\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}(:\\d{1,5})?\\b"},{cN:"number",b:"\\b\\d+[kKmMgGdshdwy]*\\b",r:0},r]};return{aliases:["nginxconf"],c:[e.HCM,{b:e.UIR+"\\s+{",rB:!0,e:"{",c:[{cN:"section",b:e.UIR}],r:0},{b:e.UIR+"\\s",e:";|{",rB:!0,c:[{cN:"attribute",b:e.UIR,starts:b}],r:0}],i:"[^\\s\\}]"}});hljs.registerLanguage("json",function(e){var i={literal:"true false null"},n=[e.QSM,e.CNM],r={e:",",eW:!0,eE:!0,c:n,k:i},t={b:"{",e:"}",c:[{cN:"attr",b:/"/,e:/"/,c:[e.BE],i:"\\n"},e.inherit(r,{b:/:/})],i:"\\S"},c={b:"\\[",e:"\\]",c:[e.inherit(r)],i:"\\S"};return n.splice(n.length,0,t,c),{c:n,k:i,i:"\\S"}});hljs.registerLanguage("javascript",function(e){var r="[A-Za-z$_][0-9A-Za-z$_]*",t={keyword:"in of if for while finally var new function do return void else break catch instanceof with throw case default try this switch continue typeof delete let yield const export super debugger as async await static import from as",literal:"true false null undefined NaN Infinity",built_in:"eval isFinite isNaN parseFloat parseInt decodeURI decodeURIComponent encodeURI encodeURIComponent escape unescape Object Function Boolean Error EvalError InternalError RangeError ReferenceError StopIteration SyntaxError TypeError URIError Number Math Date String RegExp Array Float32Array Float64Array Int16Array Int32Array Int8Array Uint16Array Uint32Array Uint8Array Uint8ClampedArray ArrayBuffer DataView JSON Intl arguments require module console window document Symbol Set Map WeakSet WeakMap Proxy Reflect Promise"},a={cN:"number",v:[{b:"\\b(0[bB][01]+)"},{b:"\\b(0[oO][0-7]+)"},{b:e.CNR}],r:0},n={cN:"subst",b:"\\$\\{",e:"\\}",k:t,c:[]},c={cN:"string",b:"`",e:"`",c:[e.BE,n]};n.c=[e.ASM,e.QSM,c,a,e.RM];var s=n.c.concat([e.CBCM,e.CLCM]);return{aliases:["js","jsx"],k:t,c:[{cN:"meta",r:10,b:/^\s*['"]use (strict|asm)['"]/},{cN:"meta",b:/^#!/,e:/$/},e.ASM,e.QSM,c,e.CLCM,e.CBCM,a,{b:/[{,]\s*/,r:0,c:[{b:r+"\\s*:",rB:!0,r:0,c:[{cN:"attr",b:r,r:0}]}]},{b:"("+e.RSR+"|\\b(case|return|throw)\\b)\\s*",k:"return throw case",c:[e.CLCM,e.CBCM,e.RM,{cN:"function",b:"(\\(.*?\\)|"+r+")\\s*=>",rB:!0,e:"\\s*=>",c:[{cN:"params",v:[{b:r},{b:/\(\s*\)/},{b:/\(/,e:/\)/,eB:!0,eE:!0,k:t,c:s}]}]},{b://,sL:"xml",c:[{b:/<\w+\s*\/>/,skip:!0},{b:/<\w+/,e:/(\/\w+|\w+\/)>/,skip:!0,c:[{b:/<\w+\s*\/>/,skip:!0},"self"]}]}],r:0},{cN:"function",bK:"function",e:/\{/,eE:!0,c:[e.inherit(e.TM,{b:r}),{cN:"params",b:/\(/,e:/\)/,eB:!0,eE:!0,c:s}],i:/\[|%/},{b:/\$[(.]/},e.METHOD_GUARD,{cN:"class",bK:"class",e:/[{;=]/,eE:!0,i:/[:"\[\]]/,c:[{bK:"extends"},e.UTM]},{bK:"constructor",e:/\{/,eE:!0}],i:/#(?!!)/}}); \ No newline at end of file diff --git a/.operations/res/normalize.css b/.operations/res/normalize.css deleted file mode 100644 index 81c6f31ea..000000000 --- a/.operations/res/normalize.css +++ /dev/null @@ -1,427 +0,0 @@ -/*! normalize.css v3.0.2 | MIT License | git.io/normalize */ - -/** - * 1. Set default font family to sans-serif. - * 2. Prevent iOS text size adjust after orientation change, without disabling - * user zoom. - */ - -html { - font-family: sans-serif; /* 1 */ - -ms-text-size-adjust: 100%; /* 2 */ - -webkit-text-size-adjust: 100%; /* 2 */ -} - -/** - * Remove default margin. - */ - -body { - margin: 0; -} - -/* HTML5 display definitions - ========================================================================== */ - -/** - * Correct `block` display not defined for any HTML5 element in IE 8/9. - * Correct `block` display not defined for `details` or `summary` in IE 10/11 - * and Firefox. - * Correct `block` display not defined for `main` in IE 11. - */ - -article, -aside, -details, -figcaption, -figure, -footer, -header, -hgroup, -main, -menu, -nav, -section, -summary { - display: block; -} - -/** - * 1. Correct `inline-block` display not defined in IE 8/9. - * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. - */ - -audio, -canvas, -progress, -video { - display: inline-block; /* 1 */ - vertical-align: baseline; /* 2 */ -} - -/** - * Prevent modern browsers from displaying `audio` without controls. - * Remove excess height in iOS 5 devices. - */ - -audio:not([controls]) { - display: none; - height: 0; -} - -/** - * Address `[hidden]` styling not present in IE 8/9/10. - * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22. - */ - -[hidden], -template { - display: none; -} - -/* Links - ========================================================================== */ - -/** - * Remove the gray background color from active links in IE 10. - */ - -a { - background-color: transparent; -} - -/** - * Improve readability when focused and also mouse hovered in all browsers. - */ - -a:active, -a:hover { - outline: 0; -} - -/* Text-level semantics - ========================================================================== */ - -/** - * Address styling not present in IE 8/9/10/11, Safari, and Chrome. - */ - -abbr[title] { - border-bottom: 1px dotted; -} - -/** - * Address style set to `bolder` in Firefox 4+, Safari, and Chrome. - */ - -b, -strong { - font-weight: bold; -} - -/** - * Address styling not present in Safari and Chrome. - */ - -dfn { - font-style: italic; -} - -/** - * Address variable `h1` font-size and margin within `section` and `article` - * contexts in Firefox 4+, Safari, and Chrome. - */ - -h1 { - font-size: 2em; - margin: 0.67em 0; -} - -/** - * Address styling not present in IE 8/9. - */ - -mark { - background: #ff0; - color: #000; -} - -/** - * Address inconsistent and variable font size in all browsers. - */ - -small { - font-size: 80%; -} - -/** - * Prevent `sub` and `sup` affecting `line-height` in all browsers. - */ - -sub, -sup { - font-size: 75%; - line-height: 0; - position: relative; - vertical-align: baseline; -} - -sup { - top: -0.5em; -} - -sub { - bottom: -0.25em; -} - -/* Embedded content - ========================================================================== */ - -/** - * Remove border when inside `a` element in IE 8/9/10. - */ - -img { - border: 0; -} - -/** - * Correct overflow not hidden in IE 9/10/11. - */ - -svg:not(:root) { - overflow: hidden; -} - -/* Grouping content - ========================================================================== */ - -/** - * Address margin not present in IE 8/9 and Safari. - */ - -figure { - margin: 1em 40px; -} - -/** - * Address differences between Firefox and other browsers. - */ - -hr { - -moz-box-sizing: content-box; - box-sizing: content-box; - height: 0; -} - -/** - * Contain overflow in all browsers. - */ - -pre { - overflow: auto; -} - -/** - * Address odd `em`-unit font size rendering in all browsers. - */ - -code, -kbd, -pre, -samp { - font-family: monospace, monospace; - font-size: 1em; -} - -/* Forms - ========================================================================== */ - -/** - * Known limitation: by default, Chrome and Safari on OS X allow very limited - * styling of `select`, unless a `border` property is set. - */ - -/** - * 1. Correct color not being inherited. - * Known issue: affects color of disabled elements. - * 2. Correct font properties not being inherited. - * 3. Address margins set differently in Firefox 4+, Safari, and Chrome. - */ - -button, -input, -optgroup, -select, -textarea { - color: inherit; /* 1 */ - font: inherit; /* 2 */ - margin: 0; /* 3 */ -} - -/** - * Address `overflow` set to `hidden` in IE 8/9/10/11. - */ - -button { - overflow: visible; -} - -/** - * Address inconsistent `text-transform` inheritance for `button` and `select`. - * All other form control elements do not inherit `text-transform` values. - * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. - * Correct `select` style inheritance in Firefox. - */ - -button, -select { - text-transform: none; -} - -/** - * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` - * and `video` controls. - * 2. Correct inability to style clickable `input` types in iOS. - * 3. Improve usability and consistency of cursor style between image-type - * `input` and others. - */ - -button, -html input[type="button"], /* 1 */ -input[type="reset"], -input[type="submit"] { - -webkit-appearance: button; /* 2 */ - cursor: pointer; /* 3 */ -} - -/** - * Re-set default cursor for disabled elements. - */ - -button[disabled], -html input[disabled] { - cursor: default; -} - -/** - * Remove inner padding and border in Firefox 4+. - */ - -button::-moz-focus-inner, -input::-moz-focus-inner { - border: 0; - padding: 0; -} - -/** - * Address Firefox 4+ setting `line-height` on `input` using `!important` in - * the UA stylesheet. - */ - -input { - line-height: normal; -} - -/** - * It's recommended that you don't attempt to style these elements. - * Firefox's implementation doesn't respect box-sizing, padding, or width. - * - * 1. Address box sizing set to `content-box` in IE 8/9/10. - * 2. Remove excess padding in IE 8/9/10. - */ - -input[type="checkbox"], -input[type="radio"] { - box-sizing: border-box; /* 1 */ - padding: 0; /* 2 */ -} - -/** - * Fix the cursor style for Chrome's increment/decrement buttons. For certain - * `font-size` values of the `input`, it causes the cursor style of the - * decrement button to change from `default` to `text`. - */ - -input[type="number"]::-webkit-inner-spin-button, -input[type="number"]::-webkit-outer-spin-button { - height: auto; -} - -/** - * 1. Address `appearance` set to `searchfield` in Safari and Chrome. - * 2. Address `box-sizing` set to `border-box` in Safari and Chrome - * (include `-moz` to future-proof). - */ - -input[type="search"] { - -webkit-appearance: textfield; /* 1 */ - -moz-box-sizing: content-box; - -webkit-box-sizing: content-box; /* 2 */ - box-sizing: content-box; -} - -/** - * Remove inner padding and search cancel button in Safari and Chrome on OS X. - * Safari (but not Chrome) clips the cancel button when the search input has - * padding (and `textfield` appearance). - */ - -input[type="search"]::-webkit-search-cancel-button, -input[type="search"]::-webkit-search-decoration { - -webkit-appearance: none; -} - -/** - * Define consistent border, margin, and padding. - */ - -fieldset { - border: 1px solid #c0c0c0; - margin: 0 2px; - padding: 0.35em 0.625em 0.75em; -} - -/** - * 1. Correct `color` not being inherited in IE 8/9/10/11. - * 2. Remove padding so people aren't caught out if they zero out fieldsets. - */ - -legend { - border: 0; /* 1 */ - padding: 0; /* 2 */ -} - -/** - * Remove default vertical scrollbar in IE 8/9/10/11. - */ - -textarea { - overflow: auto; -} - -/** - * Don't inherit the `font-weight` (applied by a rule above). - * NOTE: the default cannot safely be changed in Chrome and Safari on OS X. - */ - -optgroup { - font-weight: bold; -} - -/* Tables - ========================================================================== */ - -/** - * Remove most spacing between table cells. - */ - -table { - border-collapse: collapse; - border-spacing: 0; -} - -td, -th { - padding: 0; -} \ No newline at end of file diff --git a/.operations/res/skeleton.css b/.operations/res/skeleton.css deleted file mode 100644 index f28bf6c59..000000000 --- a/.operations/res/skeleton.css +++ /dev/null @@ -1,418 +0,0 @@ -/* -* Skeleton V2.0.4 -* Copyright 2014, Dave Gamache -* www.getskeleton.com -* Free to use under the MIT license. -* http://www.opensource.org/licenses/mit-license.php -* 12/29/2014 -*/ - - -/* Table of contents -–––––––––––––––––––––––––––––––––––––––––––––––––– -- Grid -- Base Styles -- Typography -- Links -- Buttons -- Forms -- Lists -- Code -- Tables -- Spacing -- Utilities -- Clearing -- Media Queries -*/ - - -/* Grid -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -.container { - position: relative; - width: 100%; - max-width: 960px; - margin: 0 auto; - padding: 0 20px; - box-sizing: border-box; } -.column, -.columns { - width: 100%; - float: left; - box-sizing: border-box; } - -/* For devices larger than 400px */ -@media (min-width: 400px) { - .container { - width: 85%; - padding: 0; } -} - -/* For devices larger than 550px */ -@media (min-width: 550px) { - .container { - width: 80%; } - .column, - .columns { - margin-left: 4%; } - .column:first-child, - .columns:first-child { - margin-left: 0; } - - .one.column, - .one.columns { width: 4.66666666667%; } - .two.columns { width: 13.3333333333%; } - .three.columns { width: 22%; } - .four.columns { width: 30.6666666667%; } - .five.columns { width: 39.3333333333%; } - .six.columns { width: 48%; } - .seven.columns { width: 56.6666666667%; } - .eight.columns { width: 65.3333333333%; } - .nine.columns { width: 74.0%; } - .ten.columns { width: 82.6666666667%; } - .eleven.columns { width: 91.3333333333%; } - .twelve.columns { width: 100%; margin-left: 0; } - - .one-third.column { width: 30.6666666667%; } - .two-thirds.column { width: 65.3333333333%; } - - .one-half.column { width: 48%; } - - /* Offsets */ - .offset-by-one.column, - .offset-by-one.columns { margin-left: 8.66666666667%; } - .offset-by-two.column, - .offset-by-two.columns { margin-left: 17.3333333333%; } - .offset-by-three.column, - .offset-by-three.columns { margin-left: 26%; } - .offset-by-four.column, - .offset-by-four.columns { margin-left: 34.6666666667%; } - .offset-by-five.column, - .offset-by-five.columns { margin-left: 43.3333333333%; } - .offset-by-six.column, - .offset-by-six.columns { margin-left: 52%; } - .offset-by-seven.column, - .offset-by-seven.columns { margin-left: 60.6666666667%; } - .offset-by-eight.column, - .offset-by-eight.columns { margin-left: 69.3333333333%; } - .offset-by-nine.column, - .offset-by-nine.columns { margin-left: 78.0%; } - .offset-by-ten.column, - .offset-by-ten.columns { margin-left: 86.6666666667%; } - .offset-by-eleven.column, - .offset-by-eleven.columns { margin-left: 95.3333333333%; } - - .offset-by-one-third.column, - .offset-by-one-third.columns { margin-left: 34.6666666667%; } - .offset-by-two-thirds.column, - .offset-by-two-thirds.columns { margin-left: 69.3333333333%; } - - .offset-by-one-half.column, - .offset-by-one-half.columns { margin-left: 52%; } - -} - - -/* Base Styles -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -/* NOTE -html is set to 62.5% so that all the REM measurements throughout Skeleton -are based on 10px sizing. So basically 1.5rem = 15px :) */ -html { - font-size: 62.5%; } -body { - font-size: 1.5em; /* currently ems cause chrome bug misinterpreting rems on body element */ - line-height: 1.6; - font-weight: 400; - font-family: "Raleway", "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif; - color: #222; } - - -/* Typography -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -h1, h2, h3, h4, h5, h6 { - margin-top: 0; - margin-bottom: 2rem; - font-weight: 300; } -h1 { font-size: 4.0rem; line-height: 1.2; letter-spacing: -.1rem;} -h2 { font-size: 3.6rem; line-height: 1.25; letter-spacing: -.1rem; } -h3 { font-size: 3.0rem; line-height: 1.3; letter-spacing: -.1rem; } -h4 { font-size: 2.4rem; line-height: 1.35; letter-spacing: -.08rem; } -h5 { font-size: 1.8rem; line-height: 1.5; letter-spacing: -.05rem; } -h6 { font-size: 1.5rem; line-height: 1.6; letter-spacing: 0; } - -/* Larger than phablet */ -@media (min-width: 550px) { - h1 { font-size: 5.0rem; } - h2 { font-size: 4.2rem; } - h3 { font-size: 3.6rem; } - h4 { font-size: 3.0rem; } - h5 { font-size: 2.4rem; } - h6 { font-size: 1.5rem; } -} - -p { - margin-top: 0; } - - -/* Links -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -a { - color: #1EAEDB; } -a:hover { - color: #0FA0CE; } - - -/* Buttons -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -.button, -button, -input[type="submit"], -input[type="reset"], -input[type="button"] { - display: inline-block; - height: 38px; - padding: 0 30px; - color: #555; - text-align: center; - font-size: 11px; - font-weight: 600; - line-height: 38px; - letter-spacing: .1rem; - text-transform: uppercase; - text-decoration: none; - white-space: nowrap; - background-color: transparent; - border-radius: 4px; - border: 1px solid #bbb; - cursor: pointer; - box-sizing: border-box; } -.button:hover, -button:hover, -input[type="submit"]:hover, -input[type="reset"]:hover, -input[type="button"]:hover, -.button:focus, -button:focus, -input[type="submit"]:focus, -input[type="reset"]:focus, -input[type="button"]:focus { - color: #333; - border-color: #888; - outline: 0; } -.button.button-primary, -button.button-primary, -input[type="submit"].button-primary, -input[type="reset"].button-primary, -input[type="button"].button-primary { - color: #FFF; - background-color: #33C3F0; - border-color: #33C3F0; } -.button.button-primary:hover, -button.button-primary:hover, -input[type="submit"].button-primary:hover, -input[type="reset"].button-primary:hover, -input[type="button"].button-primary:hover, -.button.button-primary:focus, -button.button-primary:focus, -input[type="submit"].button-primary:focus, -input[type="reset"].button-primary:focus, -input[type="button"].button-primary:focus { - color: #FFF; - background-color: #1EAEDB; - border-color: #1EAEDB; } - - -/* Forms -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -input[type="email"], -input[type="number"], -input[type="search"], -input[type="text"], -input[type="tel"], -input[type="url"], -input[type="password"], -textarea, -select { - height: 38px; - padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */ - background-color: #fff; - border: 1px solid #D1D1D1; - border-radius: 4px; - box-shadow: none; - box-sizing: border-box; } -/* Removes awkward default styles on some inputs for iOS */ -input[type="email"], -input[type="number"], -input[type="search"], -input[type="text"], -input[type="tel"], -input[type="url"], -input[type="password"], -textarea { - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; } -textarea { - min-height: 65px; - padding-top: 6px; - padding-bottom: 6px; } -input[type="email"]:focus, -input[type="number"]:focus, -input[type="search"]:focus, -input[type="text"]:focus, -input[type="tel"]:focus, -input[type="url"]:focus, -input[type="password"]:focus, -textarea:focus, -select:focus { - border: 1px solid #33C3F0; - outline: 0; } -label, -legend { - display: block; - margin-bottom: .5rem; - font-weight: 600; } -fieldset { - padding: 0; - border-width: 0; } -input[type="checkbox"], -input[type="radio"] { - display: inline; } -label > .label-body { - display: inline-block; - margin-left: .5rem; - font-weight: normal; } - - -/* Lists -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -ul { - list-style: circle inside; } -ol { - list-style: decimal inside; } -ol, ul { - padding-left: 0; - margin-top: 0; } -ul ul, -ul ol, -ol ol, -ol ul { - margin: 1.5rem 0 1.5rem 3rem; - font-size: 90%; } -li { - margin-bottom: 1rem; } - - -/* Code -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -code { - padding: .2rem .5rem; - margin: 0 .2rem; - font-size: 90%; - white-space: nowrap; - background: #F1F1F1; - border: 1px solid #E1E1E1; - border-radius: 4px; } -pre > code { - display: block; - padding: 1rem 1.5rem; - white-space: pre; } - - -/* Tables -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -th, -td { - padding: 12px 15px; - text-align: left; - border-bottom: 1px solid #E1E1E1; } -th:first-child, -td:first-child { - padding-left: 0; } -th:last-child, -td:last-child { - padding-right: 0; } - - -/* Spacing -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -button, -.button { - margin-bottom: 1rem; } -input, -textarea, -select, -fieldset { - margin-bottom: 1.5rem; } -pre, -blockquote, -dl, -figure, -table, -p, -ul, -ol, -form { - margin-bottom: 2.5rem; } - - -/* Utilities -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -.u-full-width { - width: 100%; - box-sizing: border-box; } -.u-max-full-width { - max-width: 100%; - box-sizing: border-box; } -.u-pull-right { - float: right; } -.u-pull-left { - float: left; } - - -/* Misc -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -hr { - margin-top: 3rem; - margin-bottom: 3.5rem; - border-width: 0; - border-top: 1px solid #E1E1E1; } - - -/* Clearing -–––––––––––––––––––––––––––––––––––––––––––––––––– */ - -/* Self Clearing Goodness */ -.container:after, -.row:after, -.u-cf { - content: ""; - display: table; - clear: both; } - - -/* Media Queries -–––––––––––––––––––––––––––––––––––––––––––––––––– */ -/* -Note: The best way to structure the use of media queries is to create the queries -near the relevant code. For example, if you wanted to change the styles for buttons -on small devices, paste the mobile query code up in the buttons section and style it -there. -*/ - - -/* Larger than mobile */ -@media (min-width: 400px) {} - -/* Larger than phablet (also point when grid becomes active) */ -@media (min-width: 550px) {} - -/* Larger than tablet */ -@media (min-width: 750px) {} - -/* Larger than desktop */ -@media (min-width: 1000px) {} - -/* Larger than Desktop HD */ -@media (min-width: 1200px) {} diff --git a/.operations/res/template.html b/.operations/res/template.html deleted file mode 100644 index 735d4f393..000000000 --- a/.operations/res/template.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - Node Best Practices - - - - - - -
-
-
-
- - - - - - - - - \ No newline at end of file diff --git a/.operations/writing-guidelines.basque.md b/.operations/writing-guidelines.basque.md index 97a36b0f7..f82b21180 100644 --- a/.operations/writing-guidelines.basque.md +++ b/.operations/writing-guidelines.basque.md @@ -1,10 +1,10 @@ -# Gure agiria edukia hobeto idazteko +# Gure agiriko edukia hobeto idazteko Nola hobetu gure bisitarien irakurtzeko eta ikasteko esperientzia ## 1. Sinplea ezin hobea da -Gure helburua da irakurketa eta ezagutzaren xurgaketa erraztea: edukia zaintzen dugu. Horrenbestez, saiatzen gara gai konplexu eta nekagarriak zerrenda erraztu bihurtzen, informazio astuna zati txikiagoetan eta zehaztasun gutxiagokoetan eratzen dugu, gai eztabaidagarri eta 'sukoiak' eta ekiditen ditugu, ideia subjektiboak sahiestuz eta orokorrean onartutako jarraibideak erabiliz +Gure helburua da irakurketa eta ezagutzaren xurgaketa erraztea: edukia zaintzen dugu. Horrenbestez, saiatzen gara gai konplexu eta nekagarriak zerrenda erraztu bihurtzen, informazio astuna zati txikiagoetan eta zehaztasun gutxiagokoetan eratzen dugu, gai eztabaidagarri eta 'sukoiak' ekiditen ditugu, ideia subjektiboak saihestuz eta orokorrean onartutako jarraibideak erabiliz ## 2. Oinarritu egitate frogatu eta fidagarrietan @@ -12,20 +12,20 @@ Gure irakurleek konfidantza handia izan behar dute irakurtzen duten informazioa ## 3. EEKS (Elkarrekiko Esklusiboa eta Kolektiboki Sakona) -Edukia ondo editatua eta fidagarria izateaz gain, haren irakurketak gaiaz bere osoan jabetzea bermatu behar du. Garrantzi gabeko azpigaiak batertuak izan behar dira +Edukia ondo editatua eta fidagarria izateaz gain, haren irakurketak gaiaz bere osoan jabetzea bermatu behar du. Ez da azpigai garrantzitsurik baztertu behar ## 4. Formatu koherentea Edukia txantiloi finkoak erabiliz dago aurkeztua, eta etorkizuneko beste edozein edukik txantiloi bera errespetatu behar du. Eduki berriak gehitu nahi izanez gero, kopiatu buleta formatua iada existitzen den bulet batetik eta moldatu zure beharretara. Informazio gehiago nahi izanez gero begiratu [txantiloi hau](../sections/template.basque.md) -## 5. Node.jsi buruz ari gara +## 5. Node.jsri buruz ari gara -Aholku bakoitzak zuzenean Node.jsekin erlazionatuta egon behar du, eta ez orokorrean software garapenarekin. Node.jsen eredu/arau generikoak ezartzea aholkatzen dugunean, edukiak Noderen ezarpenean ardaztuta egon behar da. Adibidez, eskaera sarrera guztiak onbideratzea aholkatzen dugunean, segurtasun arrazoiengatik, Node-lingo erabili behar da, ‘erabili middlewarea eskaera sarrera onbideratzeko‘. Gai batek Node.jsen ezarpenik ez badauka (esaterako Python & Jaban bezala), gehitu edukiontzi generiko batean, begiratu 6.5 gaia adibidetzat +Aholku bakoitzak zuzenean Node.jsrekin erlazionatuta egon behar du, eta ez orokorrean software garapenarekin. Node.jsren eredu/arau generikoak ezartzea aholkatzen dugunean, edukiak Noderen ezarpenean ardaztuta egon behar du. Adibidez, eskaera sarrera guztiak onbideratzea aholkatzen dugunean, segurtasun arrazoiengatik, Node-lingo erabili behar da, ‘erabili middlewarea eskaera sarrera onbideratzeko‘. Gai batek Node.jsren ezarpenik ez badauka (esaterako Python & Jaban bezala), gehitu edukiontzi generiko batean, begiratu 6.5 gaia adibidetzat ## 6. Hornitzaile nagusiak soilik Batzuetan, npm paketeak, open source tresnak edota produktu komertzialak bezalako zenbait erronka eta arazo abordatzen dituzten hornitzaileen izenak gehitzea erabilgarria da. Gainezka egiten duten zerrenda luzeak edota ospetsuak eta egonkorrak ez diren proiektuak ekiditeko, hurrengo arauak proposatzen ditugu: - Soilik 3 hornitzaile ezagunenak gomendatu behar dira: hitz gako batentzat bilaketa motore bateko (Google edo Github ospearen arabera ordenatua) lehenengo 3 emaitzetan agertzen den hornitzaile bat aipatu genezake gure gomendioetan -- npm pakete bat bada, batazbeste egunean, gutxienez, 750 aldiz deskargatua izan behar da +- npm pakete bat bada, batez beste egunean, gutxienez, 750 aldiz deskargatua izan behar da - Kode irekiko proiektu bat bada, azken 6 hilabeteetan gutxienez behin eguneratua izan behar da diff --git a/.operations/writing-guidelines.chinese.md b/.operations/writing-guidelines.chinese.md index f799ce2d4..97629cc69 100644 --- a/.operations/writing-guidelines.chinese.md +++ b/.operations/writing-guidelines.chinese.md @@ -1,31 +1,31 @@ -# 我们的内容写作声明 -如何提高访问者的阅读和学习体验 +# 我们创作内容的准则 -## 1. 越简单越好 +提高访问者的阅读和学习体验 -
-我们的使命, 我们管理内容是为了使阅读和吸收知识更容易。因此, 我们专注于将复杂和无趣的话题转化为一个简化的清单, 用缩短和不那么精确的细节来交易超载信息, 避免 ‘易燃’ 和有争议的话题, 摆脱主观想法, 赞成普遍接受做法 +## 1. 越简单越好 -
+我们的使命,是使知识更易于理解与吸收。因此,我们专注于将复杂和无趣的话题转化为一个简化的清单,用简短但细节相对不精确的列表,去避免超负荷的信息量。同时避免涉及”易爆炸“和有争议的话题。摆脱主观观点,赞成普遍接受的实践。 -## 2. 以证据为基础并且可靠 +## 2. 基于证据且可靠 -
-我们的读者应该有很大的信心, 他们浏览的内容是可靠的。我们通过包括引用、数据和本主题可用的其他资源等证据来实现这一点。实际上, 努力包括可靠来源的引用, 显示基准, 相关的设计模式或任何科学措施, 以证明您的主张 +我们应使得我们的内容能让读者充分信任其可靠性。为实现这一点,我们加入引用、数据和与主题相关的其他资源。实践上,通过努力包括来自可靠来源的引用话语,展示基准测试结果、相关的设计模式,或采用任何其他的科学手段以证明您的主张。 +## 3. MECE(不重不漏) -## 3. MECE (Mutually Exclusive and Collectively Exhaustive) -除了大量编辑和可靠的内容, 通过它略读也应该提供全面覆盖的主题。不应排除重要的子主题 +除了要精心编写和可靠,一个话题应该做到略读它之后能涉及到该话题的全部知识。任何重要的子话题都不能遗漏。 ## 4. 一致的格式 -内容是使用固定模板显示的。任何将来的内容都必须符合同一模板。如果希望添加新项目符号, 请从现有项目符号复制项目符号格式, 并将其扩展以满足您的需要。有关其他信息, 请查看[模版](https://github.com/goldbergyoni/nodebestpractices/blob/master/sections/template.md) -## 5. 关于Node.js -每个建议都应直接与Node.js相关, 而不是一般软件开发。当我们建议在Node.js中实现通用模式/规则时, 内容应该集中在Node的实现上。例如, 当我们建议将所有请求的输入为了安全原因进行处理时, 应使用Node行话 - '使用中间件来处理请求输入' +内容是使用固定模板显示的。任何新的内容都必须遵守这一模板。如果希望添加新项目符号,请从现有项目符号复制项目符号格式,并将其扩展以满足您的需要。有关其他信息,请查看[模版](../sections/template.md) + +## 5. Node.js 相关 + +每个建议都应直接与 Node.js 相关,而不能仅仅是一般的软件开发。当我们建议在 Node.js 中实现通用的模式/规则时,内容应该集中在 Node 的实现上。例如,当我们建议将所有请求的输入为了安全原因进行处理时,应使用 Node 行话——‘使用中间件来处理请求输入’,如果一个条目在 Node.js 中没有具体特别的实现(e.g. 在 Python 或 Java 中看起来一样)——则将其包含在一个通用的容器条目,例子请查看条目 6.5。 + +## 6. 仅限主要的厂商 -## 6. 仅限主要的vendor -有时, 包括可以解决某些挑战和问题 (如 npm 软件包、开源工具甚至商业产品) 的供应商名称是很有用的。为了避免极长的列表或推荐信誉不好和不稳定的项目, 我们提出了以下规则: +有时, 为解决某些问题和挑战,可以包含一些软件 (如 npm 软件包、开源工具甚至商业产品) 的厂商名。为了避免极长的列表,或推荐信誉不好或不稳定的项目,我们提出了以下规则: -- 只有排名前3的vendor应该被推荐 – 对于一个给定的相关关键词,如果某个vendor出现在搜索引擎结果中排名前3(谷歌或GitHub通过人气排序),那么它可以包含在我们的推荐里 -- 如果它是一个npm包,它必须平均一天下载至少750次 -- 如果它是一个开源项目,它必须在过去的6个月里至少更新一次 +- 只有排名前 3 的厂商应该被推荐 – 对于一个给定的相关关键词,如果某个厂商出现在搜索引擎结果中排名前3(谷歌或 GitHub 通过人气排序),那么它可以包含在我们的推荐里。 +- 如果它是一个 npm 包,平均日下载量应至少 750 次。 +- 如果它是一个开源项目,在过去的 6 个月里必须至少更新过一次。 diff --git a/.operations/writing-guidelines.french.md b/.operations/writing-guidelines.french.md new file mode 100644 index 000000000..2e46f05e2 --- /dev/null +++ b/.operations/writing-guidelines.french.md @@ -0,0 +1,31 @@ +# Notre manifeste de rédaction de contenu + +Comment nous améliorons l'expérience de lecture et l'apprentissage pour nos visiteurs. + +## 1. La simplicité vaut mieux que la perfection + +Faciliter la lecture et l'absorption des connaissances est notre mission, nous en organisons son contenu. En tant que tels, nous nous concentrons sur la transformation des sujets complexes et difficiles en une liste simplifiée, nous traitons les informations trop volumineuses avec du contenu plus courts et moins précis, nous évitons les sujets ‘qui mettent de l'huile sur le feu’ ou controversés et nous évitons les idées subjectives au profit de pratiques généralement acceptées. + +## 2. Se baser sur des faits probants et fiables + +Nos lecteurs doivent être persuadés que le contenu qu'ils parcourent est fiable. Pour ce faire, nous incluons des données probantes comme des références, des données et d'autres ressources disponibles à ce sujet. Dans la pratique, nous essayons d'inclure des citations provenant de sources fiables, de montrer des benchmarks, des modèles de conception connexes ou toute autre mesure scientifique pour prouver les affirmations. + +## 3. MECE (Mutuellement Exclusif Collectivement Exhaustif) + +En plus d'être d'une grande fiabilité et d'une grande qualité rédactionnelle, le fait de parcourir le contenu devrait également permettre de couvrir l'ensemble du sujet. Aucun sous-thème important ne doit être laissé de côté. + +## 4. Formatage cohérent + +Le contenu est présenté à l'aide de modèles prédéfinis. Tout contenu futur doit être conforme au même modèle. Si vous souhaitez ajouter de nouveaux points, copiez le format d'un point existant et complétez-le selon vos besoins. Pour plus d'informations, veuillez consulter [ce modèle](../sections/template.md). + +## 5. C'est à propos de Node.js + +Chaque conseil doit être directement lié à Node.js et non au développement de logiciels en général. Lorsque nous conseillons d'implémenter un modèle/une règle générique dans Node.js, le contenu doit se concentrer sur l'implémentation dans Node. Par exemple, lorsque nous conseillons de nettoyer toutes les requêtes saisies pour des raisons de sécurité, il convient d'utiliser Node-lingo - ‘Utiliser un middleware pour nettoyer les requêtes saisies’. Si un élément n'a pas d'implémentation spécifique dans Node.js (par exemple, il est identique dans Python & Java) - incluez-le dans un élément de conteneur générique, voir l'article 6.5 par exemple. + +## 6. Uniquement les fournisseurs majeurs + +Il est parfois utile d'inclure des noms de fournisseurs qui peuvent répondre à certains défis et problèmes comme les paquets npm, les outils open source ou même les produits commerciaux. Afin d'éviter des listes trop longues ou de recommander des projets peu fiables et instables, nous avons élaboré les règles suivantes : + +- Seuls les 3 premiers fournisseurs devraient être recommandés - un fournisseur qui apparaît dans les 3 premiers résultats d'un moteur de recherche (Google ou GitHub triés par popularité) pour un mot clé pertinent donné peut être inclus dans notre recommandation. +- S'il s'agit d'un paquet npm, il doit également être téléchargé au moins 750 fois par jour en moyenne. +- S'il s'agit d'un projet open-source, il doit avoir été mis à jour au moins une fois au cours des 6 derniers mois. diff --git a/.operations/writing-guidelines.indonesia.md b/.operations/writing-guidelines.indonesia.md index 3b65f7580..d33359121 100644 --- a/.operations/writing-guidelines.indonesia.md +++ b/.operations/writing-guidelines.indonesia.md @@ -16,7 +16,7 @@ Selain konten yang sangat diedit dan dapat diandalkan, membaca sekilas konten ju ## 4. Pemformatan yang konsisten -Konten disajikan menggunakan templat tetap. Setiap konten di masa mendatang harus sesuai dengan template yang sama. Jika Anda ingin menambahkan poin baru, salin format poin dari poin yang ada dan kembangkan sesuai kebutuhan Anda. Untuk informasi tambahan, silakan lihat [template ini] (https://github.com/goldbergyoni/nodebestpractices/blob/master/sections/template.md). +Konten disajikan menggunakan templat tetap. Setiap konten di masa mendatang harus sesuai dengan template yang sama. Jika Anda ingin menambahkan poin baru, salin format poin dari poin yang ada dan kembangkan sesuai kebutuhan Anda. Untuk informasi tambahan, silakan lihat [template ini] (/sections/template.md). ## 5. Ini Tentang Node.js @@ -28,4 +28,4 @@ Terkadang berguna untuk memasukkan nama vendor yang dapat mengatasi tantangan da - Hanya 3 vendor teratas yang disarankan - vendor yang muncul di 3 hasil teratas dari mesin pencari (Google atau GitHub diurutkan berdasarkan popularitas) untuk kata kunci relevan tertentu dapat dimasukkan dalam rekomendasi kami. - Jika ini adalah paket npm, itu juga harus diunduh setidaknya rata-rata 750 kali sehari. -- Jika ini adalah proyek sumber terbuka, itu harus diperbarui setidaknya sekali dalam 6 bulan terakhir. \ No newline at end of file +- Jika ini adalah proyek sumber terbuka, itu harus diperbarui setidaknya sekali dalam 6 bulan terakhir. diff --git a/.operations/writing-guidelines.japanese.md b/.operations/writing-guidelines.japanese.md index 155b6bafa..23cfc416a 100644 --- a/.operations/writing-guidelines.japanese.md +++ b/.operations/writing-guidelines.japanese.md @@ -16,7 +16,7 @@ Apart from the content being greatly edited and reliable, skimming through it sh ## 4. Consistent formatting -The content is presented using fixed templates. Any future content must conform to the same template. If you wish to add new bullets copy a bullet format from an existing bullet and extend it to your needs. For additional information please view [this template](https://github.com/goldbergyoni/nodebestpractices/blob/master/sections/template.md). +The content is presented using fixed templates. Any future content must conform to the same template. If you wish to add new bullets copy a bullet format from an existing bullet and extend it to your needs. For additional information please view [this template](../sections/template.md). ## 5. It's About Node.js diff --git a/.operations/writing-guidelines.md b/.operations/writing-guidelines.md index 155b6bafa..3b5163a35 100644 --- a/.operations/writing-guidelines.md +++ b/.operations/writing-guidelines.md @@ -16,11 +16,11 @@ Apart from the content being greatly edited and reliable, skimming through it sh ## 4. Consistent formatting -The content is presented using fixed templates. Any future content must conform to the same template. If you wish to add new bullets copy a bullet format from an existing bullet and extend it to your needs. For additional information please view [this template](https://github.com/goldbergyoni/nodebestpractices/blob/master/sections/template.md). +The content is presented using fixed templates. Any future content must conform to the same template. If you wish to add new bullets copy a bullet format from an existing bullet and extend it to your needs. For additional information please view [this template](../sections/template.md). ## 5. It's About Node.js -Each advice should be related directly to Node.js and not to software development in general. When we advise to implement generic pattern/rule in Node.js, the content should focus on the Node implementation. For example, when we advise to sanitize all requests input for security reasons, Node-lingo should be used - ‘Use middleware to sanitize request input’. If an item has no specific implementation in Node.js (e.g. it looks the same in Python & Jaba) - include it within a generic container item, see item 6.5 for example. +Each advice should be related directly to Node.js and not to software development in general. When we advise to implement generic pattern/rule in Node.js, the content should focus on the Node implementation. For example, when we advise to sanitize all requests input for security reasons, Node-lingo should be used - ‘Use middleware to sanitize request input’. If an item has no specific implementation in Node.js (e.g. it looks the same in Python & Java) - include it within a generic container item, see item 6.5 for example. ## 6. Leading vendors only diff --git a/.operations/writing-guidelines.polish.md b/.operations/writing-guidelines.polish.md index 471525ade..e7ad37f4b 100644 --- a/.operations/writing-guidelines.polish.md +++ b/.operations/writing-guidelines.polish.md @@ -16,7 +16,7 @@ Oprócz tego, że treść jest znacznie edytowana i niezawodna, przeglądanie w ## 4. Spójne formatowanie -Treść jest prezentowana przy użyciu stałych szablonów. Wszelkie przyszłe treści muszą być zgodne z tym samym szablonem. Jeśli chcesz dodać nowe punktory, skopiuj format punktora z istniejącego i rozszerz go do swoich potrzeb. Aby uzyskać dodatkowe informacje, zobacz [ten szablon](https://github.com/goldbergyoni/nodebestpractices/blob/master/sections/template.md). +Treść jest prezentowana przy użyciu stałych szablonów. Wszelkie przyszłe treści muszą być zgodne z tym samym szablonem. Jeśli chcesz dodać nowe punktory, skopiuj format punktora z istniejącego i rozszerz go do swoich potrzeb. Aby uzyskać dodatkowe informacje, zobacz [ten szablon](../sections/template.md). ## 5. To na temat Node.js diff --git a/.operations/writing-guidelines.russian.md b/.operations/writing-guidelines.russian.md index 0ef1389cf..8f42baff9 100644 --- a/.operations/writing-guidelines.russian.md +++ b/.operations/writing-guidelines.russian.md @@ -16,7 +16,7 @@ ## 4. Согласованное форматирование -Контент представлен с использованием фиксированных шаблонов. Любое будущее содержание должно соответствовать тому же шаблону. Если вы хотите добавить новые маркеры, скопируйте формат маркера из существующего маркера и расширьте его для своих нужд. Для получения дополнительной информации, пожалуйста, просмотрите [этот шаблон](https://github.com/goldbergyoni/nodebestpractices/blob/master/sections/template.md). +Контент представлен с использованием фиксированных шаблонов. Любое будущее содержание должно соответствовать тому же шаблону. Если вы хотите добавить новые маркеры, скопируйте формат маркера из существующего маркера и расширьте его для своих нужд. Для получения дополнительной информации, пожалуйста, просмотрите [этот шаблон](../sections/template.md). ## 5. Это про Node.js diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 624468fbd..000000000 --- a/.travis.yml +++ /dev/null @@ -1,10 +0,0 @@ -language: node_js -node_js: 8 -script: - - cd .operations - - npm i - - export PR=https://api.github.com/repos/$TRAVIS_REPO_SLUG/pulls/$TRAVIS_PULL_REQUEST - - export BRANCH=$(if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then echo $TRAVIS_BRANCH; else echo `curl -s $PR | jq -r .head.ref`; fi) - - echo "TRAVIS_BRANCH=$TRAVIS_BRANCH, PR=$PR, BRANCH=$BRANCH" - - npm run lint - - npm run build \ No newline at end of file diff --git a/README.arabic.md b/README.arabic.md new file mode 100644 index 000000000..719deba3c --- /dev/null +++ b/README.arabic.md @@ -0,0 +1,1977 @@ +
+ +# Node.js أفضل ممارسات + +

+ Node.js Best Practices +

+ +
+ +
+ 102 items Last update: July 19, 2023 Updated for Node 19.0.0 +
+ +
+ +[](https://twitter.com/nodepractices/) **Follow us on Twitter!** [**@nodepractices**](https://twitter.com/nodepractices/) + +
+ +Read in a different language: [![CN](./assets/flags/CN.png)**CN**](./README.chinese.md), [![FR](./assets/flags/FR.png)**FR**](./README.french.md), [![BR](./assets/flags/BR.png)**BR**](./README.brazilian-portuguese.md), [![RU](./assets/flags/RU.png)**RU**](./README.russian.md), [![PL](./assets/flags/PL.png)**PL**](./README.polish.md), [![JA](./assets/flags/JA.png)**JA**](./README.japanese.md), [![EU](./assets/flags/EU.png)**EU**](./README.basque.md) [(![ES](./assets/flags/ES.png)**ES**, ![HE](./assets/flags/HE.png)**HE**, ![KR](./assets/flags/KR.png)**KR** and ![TR](./assets/flags/TR.png)**TR** in progress! )](#translations) + +
+ +# 🎊 2023 edition is here! + +- **🛰 Modernized to 2023**: Tons of text edits, new recommended libraries, and some new best practices + +- **✨ Easily focus on new content**: Already visited before? Search for `#new` or `#updated` tags for new content only + +- **🔖 Curious to see examples? We have a starter**: Visit [Practica.js](https://github.com/practicajs/practica), our application example and boilerplate (beta) to see some practices in action + +

+ +# 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](./.operations/writing-guidelines.md) + +**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 + +

+ +# By Yoni Goldberg + +### Learn with me: As a consultant, I engage with worldwide teams on various activities like workshops and code reviews. 🎉AND... Hold on, I've just launched my [beyond-the-basics testing course, which is on a 🎁 limited-time sale](https://testjavascript.com/) until August 7th + +

+ +## Table of Contents + +
+ + 1. Project Architecture Practices (6) + + +  [1.1 Structure your solution by components `#strategic` `#updated`](#-11-structure-your-solution-by-business-components)
+  [1.2 Layer your components, keep the web layer within its boundaries `#strategic` `#updated`](#-12-layer-your-components-with-3-tiers-keep-the-web-layer-within-its-boundaries)
+  [1.3 Wrap common utilities as packages, consider publishing](#-13-wrap-common-utilities-as-packages-consider-publishing)
+  [1.4 Use environment aware, secure and hierarchical config `#updated`](#-14-use-environment-aware-secure-and-hierarchical-config)
+  [1.5 Consider all the consequences when choosing the main framework `#new`](#-15-consider-all-the-consequences-when-choosing-the-main-framework)
+  [1.6 Use TypeScript sparingly and thoughtfully `#new`](#-16-use-typescript-sparingly-and-thoughtfully)
+ +
+ +
+ + 2. Error Handling Practices (12) + + +  [2.1 Use Async-Await or promises for async error handling](#-21-use-async-await-or-promises-for-async-error-handling)
+  [2.2 Extend the built-in Error object `#strategic` `#updated`](#-22-extend-the-built-in-error-object)
+  [2.3 Distinguish operational vs programmer errors `#strategic` `#updated`](#-23-distinguish-catastrophic-errors-from-operational-errors)
+  [2.4 Handle errors centrally, not within a middleware `#strategic`](#-24-handle-errors-centrally-not-within-a-middleware)
+  [2.5 Document API errors using OpenAPI or GraphQL](#-25-document-api-errors-using-openapi-or-graphql)
+  [2.6 Exit the process gracefully when a stranger comes to town `#strategic`](#-26-exit-the-process-gracefully-when-a-stranger-comes-to-town)
+  [2.7 Use a mature logger to increase errors visibility `#updated`](#-27-use-a-mature-logger-to-increase-errors-visibility)
+  [2.8 Test error flows using your favorite test framework `#updated`](#-28-test-error-flows-using-your-favorite-test-framework)
+  [2.9 Discover errors and downtime using APM products](#-29-discover-errors-and-downtime-using-apm-products)
+  [2.10 Catch unhandled promise rejections `#updated`](#-210-catch-unhandled-promise-rejections)
+  [2.11 Fail fast, validate arguments using a dedicated library](#-211-fail-fast-validate-arguments-using-a-dedicated-library)
+  [2.12 Always await promises before returning to avoid a partial stacktrace `#new`](#-212-always-await-promises-before-returning-to-avoid-a-partial-stacktrace)
+  [2.13 Subscribe to event emitters 'error' event `#new`](#-213-subscribe-to-event-emitters-and-streams-error-event)
+ +
+ +
+ + 3. Code Style Practices (12) + + +  [3.1 Use ESLint `#strategic`](#-31-use-eslint)
+  [3.2 Use Node.js eslint extension plugins `#updated`](#-32-use-nodejs-eslint-extension-plugins)
+  [3.3 Start a Codeblock's Curly Braces on the Same Line](#-33-start-a-codeblocks-curly-braces-on-the-same-line)
+  [3.4 Separate your statements properly](#-34-separate-your-statements-properly)
+  [3.5 Name your functions](#-35-name-your-functions)
+  [3.6 Use naming conventions for variables, constants, functions and classes](#-36-use-naming-conventions-for-variables-constants-functions-and-classes)
+  [3.7 Prefer const over let. Ditch the var](#-37-prefer-const-over-let-ditch-the-var)
+  [3.8 Require modules first, not inside functions](#-38-require-modules-first-not-inside-functions)
+  [3.9 Set an explicit entry point to a module/folder `#updated`](#-39-set-an-explicit-entry-point-to-a-modulefolder)
+  [3.10 Use the === operator](#-310-use-the--operator)
+  [3.11 Use Async Await, avoid callbacks `#strategic`](#-311-use-async-await-avoid-callbacks)
+  [3.12 Use arrow function expressions (=>)](#-312-use-arrow-function-expressions-)
+  [3.13 Avoid effects outside of functions `#new`](#-313-avoid-effects-outside-of-functions)
+ +
+ +
+ + 4. Testing And Overall Quality Practices (13) + + +  [4.1 At the very least, write API (component) testing `#strategic`](#-41-at-the-very-least-write-api-component-testing)
+  [4.2 Include 3 parts in each test name `#new`](#-42-include-3-parts-in-each-test-name)
+  [4.3 Structure tests by the AAA pattern `#strategic`](#-43-structure-tests-by-the-aaa-pattern)
+  [4.4 Ensure Node version is unified `#new`](#-44-ensure-node-version-is-unified)
+  [4.5 Avoid global test fixtures and seeds, add data per-test `#strategic`](#-45-avoid-global-test-fixtures-and-seeds-add-data-per-test)
+  [4.6 Tag your tests `#advanced`](#-46-tag-your-tests)
+  [4.7 Check your test coverage, it helps to identify wrong test patterns](#-47-check-your-test-coverage-it-helps-to-identify-wrong-test-patterns)
+  [4.8 Use production-like environment for e2e testing](#-48-use-production-like-environment-for-e2e-testing)
+  [4.9 Refactor regularly using static analysis tools](#-49-refactor-regularly-using-static-analysis-tools)
+  [4.10 Mock responses of external HTTP services #advanced `#new` `#advanced`](#-410-mock-responses-of-external-http-services)
+  [4.11 Test your middlewares in isolation](#-411-test-your-middlewares-in-isolation)
+  [4.12 Specify a port in production, randomize in testing `#new`](#-412-specify-a-port-in-production-randomize-in-testing)
+  [4.13 Test the five possible outcomes #strategic `#new`](#-413-test-the-five-possible-outcomes)
+ +
+ +
+ + 5. Going To Production Practices (19) + + +  [5.1. Monitoring `#strategic`](#-51-monitoring)
+  [5.2. Increase the observability using smart logging `#strategic`](#-52-increase-the-observability-using-smart-logging)
+  [5.3. Delegate anything possible (e.g. gzip, SSL) to a reverse proxy `#strategic`](#-53-delegate-anything-possible-eg-gzip-ssl-to-a-reverse-proxy)
+  [5.4. Lock dependencies](#-54-lock-dependencies)
+  [5.5. Guard process uptime using the right tool](#-55-guard-process-uptime-using-the-right-tool)
+  [5.6. Utilize all CPU cores](#-56-utilize-all-cpu-cores)
+  [5.7. Create a ‘maintenance endpoint’](#-57-create-a-maintenance-endpoint)
+  [5.8. Discover the unknowns using APM products `#advanced` `#updated`](#-58-discover-the-unknowns-using-apm-products)
+  [5.9. Make your code production-ready](#-59-make-your-code-production-ready)
+  [5.10. Measure and guard the memory usage `#advanced`](#-510-measure-and-guard-the-memory-usage)
+  [5.11. Get your frontend assets out of Node](#-511-get-your-frontend-assets-out-of-node)
+  [5.12. Strive to be stateless `#strategic`](#-512-strive-to-be-stateless)
+  [5.13. Use tools that automatically detect vulnerabilities](#-513-use-tools-that-automatically-detect-vulnerabilities)
+  [5.14. Assign a transaction id to each log statement `#advanced`](#-514-assign-a-transaction-id-to-each-log-statement)
+  [5.15. Set NODE_ENV=production](#-515-set-node_envproduction)
+  [5.16. Design automated, atomic and zero-downtime deployments `#advanced`](#-516-design-automated-atomic-and-zero-downtime-deployments)
+  [5.17. Use an LTS release of Node.js](#-517-use-an-lts-release-of-nodejs)
+  [5.18. Log to stdout, avoid specifying log destination within the app `#updated`](#-518-log-to-stdout-avoid-specifying-log-destination-within-the-app)
+  [5.19. Install your packages with npm ci `#new`](#-519-install-your-packages-with-npm-ci)
+ +
+ +
+ + 6. Security Practices (25) + + +  [6.1. Embrace linter security rules](#-61-embrace-linter-security-rules)
+  [6.2. Limit concurrent requests using a middleware](#-62-limit-concurrent-requests-using-a-middleware)
+  [6.3 Extract secrets from config files or use packages to encrypt them `#strategic`](#-63-extract-secrets-from-config-files-or-use-packages-to-encrypt-them)
+  [6.4. Prevent query injection vulnerabilities with ORM/ODM libraries `#strategic`](#-64-prevent-query-injection-vulnerabilities-with-ormodm-libraries)
+  [6.5. Collection of generic security best practices](#-65-collection-of-generic-security-best-practices)
+  [6.6. Adjust the HTTP response headers for enhanced security](#-66-adjust-the-http-response-headers-for-enhanced-security)
+  [6.7. Constantly and automatically inspect for vulnerable dependencies `#strategic`](#-67-constantly-and-automatically-inspect-for-vulnerable-dependencies)
+  [6.8. Protect Users' Passwords/Secrets using bcrypt or scrypt `#strategic`](#-68-protect-users-passwordssecrets-using-bcrypt-or-scrypt)
+  [6.9. Escape HTML, JS and CSS output](#-69-escape-html-js-and-css-output)
+  [6.10. Validate incoming JSON schemas `#strategic`](#-610-validate-incoming-json-schemas)
+  [6.11. Support blocklisting JWTs](#-611-support-blocklisting-jwts)
+  [6.12. Prevent brute-force attacks against authorization `#advanced`](#-612-prevent-brute-force-attacks-against-authorization)
+  [6.13. Run Node.js as non-root user](#-613-run-nodejs-as-non-root-user)
+  [6.14. Limit payload size using a reverse-proxy or a middleware](#-614-limit-payload-size-using-a-reverse-proxy-or-a-middleware)
+  [6.15. Avoid JavaScript eval statements](#-615-avoid-javascript-eval-statements)
+  [6.16. Prevent evil RegEx from overloading your single thread execution](#-616-prevent-evil-regex-from-overloading-your-single-thread-execution)
+  [6.17. Avoid module loading using a variable](#-617-avoid-module-loading-using-a-variable)
+  [6.18. Run unsafe code in a sandbox](#-618-run-unsafe-code-in-a-sandbox)
+  [6.19. Take extra care when working with child processes `#advanced`](#-619-take-extra-care-when-working-with-child-processes)
+  [6.20. Hide error details from clients](#-620-hide-error-details-from-clients)
+  [6.21. Configure 2FA for npm or Yarn `#strategic`](#-621-configure-2fa-for-npm-or-yarn)
+  [6.22. Modify session middleware settings](#-622-modify-session-middleware-settings)
+  [6.23. Avoid DOS attacks by explicitly setting when a process should crash `#advanced`](#-623-avoid-dos-attacks-by-explicitly-setting-when-a-process-should-crash)
+  [6.24. Prevent unsafe redirects](#-624-prevent-unsafe-redirects)
+  [6.25. Avoid publishing secrets to the npm registry](#-625-avoid-publishing-secrets-to-the-npm-registry)
+  [6.26. 6.26 Inspect for outdated packages](#-626-inspect-for-outdated-packages)
+  [6.27. Import built-in modules using the 'node:' protocol `#new`](#-627-import-built-in-modules-using-the-node-protocol)
+ +
+ +
+ + 7. Performance Practices (2) (Work In Progress️ ✍️) + + +  [7.1. Don't block the event loop](#-71-dont-block-the-event-loop)
+  [7.2. Prefer native JS methods over user-land utils like Lodash](#-72-prefer-native-js-methods-over-user-land-utils-like-lodash)
+ +
+ +
+ + 8. Docker Practices (15) + + +  [8.1 Use multi-stage builds for leaner and more secure Docker images `#strategic`](#-81-use-multi-stage-builds-for-leaner-and-more-secure-docker-images)
+  [8.2. Bootstrap using node command, avoid npm start](#-82-bootstrap-using-node-command-avoid-npm-start)
+  [8.3. Let the Docker runtime handle replication and uptime `#strategic`](#-83-let-the-docker-runtime-handle-replication-and-uptime)
+  [8.4. Use .dockerignore to prevent leaking secrets](#-84-use-dockerignore-to-prevent-leaking-secrets)
+  [8.5. Clean-up dependencies before production](#-85-clean-up-dependencies-before-production)
+  [8.6. Shutdown smartly and gracefully `#advanced`](#-86-shutdown-smartly-and-gracefully)
+  [8.7. Set memory limits using both Docker and v8 `#advanced` `#strategic`](#-87-set-memory-limits-using-both-docker-and-v8)
+  [8.8. Plan for efficient caching](#-88-plan-for-efficient-caching)
+  [8.9. Use explicit image reference, avoid latest tag](#-89-use-explicit-image-reference-avoid-latest-tag)
+  [8.10. Prefer smaller Docker base images](#-810-prefer-smaller-docker-base-images)
+  [8.11. Clean-out build-time secrets, avoid secrets in args `#strategic #new`](#-811-clean-out-build-time-secrets-avoid-secrets-in-args)
+  [8.12. Scan images for multi layers of vulnerabilities `#advanced`](#-812-scan-images-for-multi-layers-of-vulnerabilities)
+  [8.13 Clean NODE_MODULE cache](#-813-clean-node_module-cache)
+  [8.14. Generic Docker practices](#-814-generic-docker-practices)
+  [8.15. Lint your Dockerfile `#new`](#-815-lint-your-dockerfile)
+ +
+ +

+ +# `1. Project Architecture Practices` + +## ![✔] 1.1 Structure your solution by business components + +### `📝 #updated` + +**TL;DR:** The root of a system should contain folders or repositories that represent reasonably sized business modules. Each component represents a product domain (i.e., bounded context), like 'user-component', 'order-component', etc. Each component has its own API, logic, and logical database. What is the significant merit? With an autonomous component, every change is performed over a granular and smaller scope - the mental overload, development friction, and deployment fear are much smaller and better. As a result, developers can move much faster. This does not necessarily demand physical separation and can be achieved using a Monorepo or with a multi-repo + +```bash +my-system +├─ apps (components) +│ ├─ orders +│ ├─ users +│ ├─ payments +├─ libraries (generic cross-component functionality) +│ ├─ logger +│ ├─ authenticator +``` + +**Otherwise:** when artifacts from various modules/topics are mixed together, there are great chances of a tightly-coupled 'spaghetti' system. For example, in an architecture where 'module-a controller' might call 'module-b service', there are no clear modularity borders - every code change might affect anything else. With this approach, developers who code new features struggle to realize the scope and impact of their change. Consequently, they fear breaking other modules, and each deployment becomes slower and riskier + +🔗 [**Read More: structure by components**](./sections/projectstructre/breakintcomponents.md) + +

+ +## ![✔] 1.2 Layer your components with 3-tiers, keep the web layer within its boundaries + +### `📝 #updated` + +**TL;DR:** Each component should contain 'layers' - a dedicated folder for common concerns: 'entry-point' where controller lives, 'domain' where the logic lives, and 'data-access'. The primary principle of the most popular architectures is to separate the technical concerns (e.g., HTTP, DB, etc) from the pure logic of the app so a developer can code more features without worrying about infrastructural concerns. Putting each concern in a dedicated folder, also known as the [3-Tier pattern](https://en.wikipedia.org/wiki/Multitier_architecture), is the _simplest_ way to meet this goal + +```bash +my-system +├─ apps (components) +│ ├─ component-a + │ ├─ entry-points + │ │ ├─ api # controller comes here + │ │ ├─ message-queue # message consumer comes here + │ ├─ domain # features and flows: DTO, services, logic + │ ├─ data-access # DB calls w/o ORM +``` + +**Otherwise:** It's often seen that developer pass web objects like request/response to functions in the domain/logic layer - this violates the separation principle and makes it harder to access later the logic code by other clients like testing code, scheduled jobs, message queues, etc + +🔗 [**Read More: layer your app**](./sections/projectstructre/createlayers.md) + +

+ +## ![✔] 1.3 Wrap common utilities as packages, consider publishing + +**TL;DR:** Place all reusable modules in a dedicated folder, e.g., "libraries", and underneath each module in its own folder, e.g., "/libraries/logger". Make the module an independent package with its own package.json file to increase the module encapsulation, and allows future publishing to a repository. In a Monorepo setup, modules can be consumed by 'npm linking' to their physical paths, using ts-paths or by publishing and installing from a package manager repository like the npm registry + +```bash +my-system +├─ apps (components) + │ ├─ component-a +├─ libraries (generic cross-component functionality) +│ ├─ logger +│ │ ├─ package.json +│ │ ├─ src +│ │ │ ├─ index.js + +``` + +**Otherwise:** Clients of a module might import and get coupled to internal functionality of a module. With a package.json at the root, one can set a package.json.main or package.json.exports to explicitly tell which files and functions are part of the public interface + +🔗 [**Read More: Structure by feature**](./sections/projectstructre/wraputilities.md) + +

+ +## ![✔] 1.4 Use environment aware, secure and hierarchical config + +### `📝 #updated` + +**TL;DR:** A 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 (d) typing support (e) validation for failing fast (f) Specify default for each key. There are a few packages that can help tick most of those boxes like [convict](https://www.npmjs.com/package/convict), [env-var](https://github.com/evanshortiss/env-var), [zod](https://github.com/colinhacks/zod), and others + +**Otherwise:** Consider a mandatory environment variable that wasn't provided. The app starts successfully and serve requests, some information is already persisted to DB. Then, it's realized that without this mandatory key the request can't complete, leaving the app in a dirty state + +🔗 [**Read More: configuration best practices**](./sections/projectstructre/configguide.md) + +

+ +## ![✔] 1.5 Consider all the consequences when choosing the main framework + +### `🌟 #new` + +**TL;DR:** When building apps and APIs, using a framework is mandatory. It's easy to overlook alternative frameworks or important considerations and then finally land on a sub optimal option. As of 2023/2024, we believe that these four frameworks are worth considering: [Nest.js](https://nestjs.com/), [Fastify](https://www.fastify.io/), [express](https://expressjs.com/), and [Koa](https://koajs.com/). Click read more below for a detailed pros/cons of each framework. Simplistically, we believe that Nest.js is the best match for teams who wish to go OOP and/or build large-scale apps that can't get partitioned into smaller _autonomous_ components. Fastify is our recommendation for apps with reasonably-sized components (e.g., Microservices) that are built around simple Node.js mechanics. Read our [full considerations guide here](./sections/projectstructre/choose-framework.md) + +**Otherwise:** Due to the overwhelming amount of considerations, it's easy to make decisions based on partial information and compare apples with oranges. For example, it's believed that Fastify is a minimal web-server that should get compared with express only. In reality, it's a rich framework with many official plugins that cover many concerns + +🔗 [**Read More: Choosing the right framework**](./sections/projectstructre/choose-framework.md) + +## ![✔] 1.6 Use TypeScript sparingly and thoughtfully + +### `🌟 #new` + +**TL;DR:** Coding without type safety is no longer an option, TypeScript is the most popular option for this mission. Use it to define variables and functions return types. With that, it is also a double edge sword that can greatly _encourage_ complexity with its additional ~ 50 keywords and sophisticated features. Consider using it sparingly, mostly with simple types, and utilize advanced features only when a real need arises + +**Otherwise:** [Researches](https://earlbarr.com/publications/typestudy.pdf) show that using TypeScript can help in detecting ~20% bugs earlier. Without it, also the developer experience in the IDE is intolerable. On the flip side, 80% of other bugs were not discovered using types. Consequently, typed syntax is valuable but limited. Only efficient tests can discover the whole spectrum of bugs, including type-related bugs. It might also defeat its purpose: sophisticated code features are likely to increase the code complexity, which by itself increases both the amount of bugs and the average bug fix time + +🔗 [**Read More: TypeScript considerations**](./sections/projectstructre/typescript-considerations.md) + +


+ +

⬆ 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 Promises with async-await 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**](./sections/errorhandling/asyncerrorhandling.md) + +

+ +## ![✔] 2.2 Extend the built-in Error object + +### `📝 #updated` + +**TL;DR:** Some libraries throw errors as a string or as some custom type – this complicates the error handling logic and the interoperability between modules. Instead, create app error object/class that extends the built-in Error object and use it whenever rejecting, throwing or emitting an error. The app error should add useful imperative properties like the error name/code and isCatastrophic. By doing so, all errors have a unified structure and support better error handling. There is `no-throw-literal` ESLint rule that strictly checks that (although it has some [limitations](https://eslint.org/docs/rules/no-throw-literal) 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**](./sections/errorhandling/useonlythebuiltinerror.md) + +

+ +## ![✔] 2.3 Distinguish catastrophic errors from operational errors + +### `📝 #updated` + +**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, catastrophic error (also known as programmer errors) refers to unusual 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 catastrophic 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**](./sections/errorhandling/operationalvsprogrammererror.md) + +

+ +## ![✔] 2.4 Handle errors centrally, not within a middleware + +**TL;DR:** Error handling logic such as logging, deciding whether to crash and monitoring metrics should be encapsulated in a dedicated and centralized object that all entry-points (e.g. APIs, cron jobs, scheduled jobs) 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**](./sections/errorhandling/centralizedhandling.md) + +

+ +## ![✔] 2.5 Document API errors using OpenAPI 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 OpenAPI. 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**](./sections/errorhandling/documentingusingswagger.md) + +

+ +## ![✔] 2.6 Exit the process gracefully when a stranger comes to town + +**TL;DR:** When an unknown error occurs (catastrophic error, see best practice 2.3) - there is uncertainty about the application healthiness. In this case, there is no escape from making the error observable, shutting off connections and exiting the process. Any reputable runtime framework like Dockerized services or cloud serverless solutions will take care to restart + +**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**](./sections/errorhandling/shuttingtheprocess.md) + +

+ +## ![✔] 2.7 Use a mature logger to increase errors visibility + +### `📝 #updated` + +**TL;DR:** A robust logging tools like [Pino](https://github.com/pinojs/pino) or [Winston](https://github.com/winstonjs/winston) increases the errors visibility using features like log-levels, pretty print coloring and more. Console.log lacks these imperative features and should be avoided. The best in class logger allows attaching custom useful properties to log entries with minimized serialization performance penalty. Developers should write logs to `stdout` and let the infrastructure pipe the stream to the appropriate log aggregator + +**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**](./sections/errorhandling/usematurelogger.md) + +

+ +## ![✔] 2.8 Test error flows using your favorite test framework + +### `📝 #updated` + +**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. On top of this, simulate deeper error flows like uncaught exceptions and ensure that the error handler treat these properly (see code examples within the "read more" section) + +**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**](./sections/errorhandling/testingerrorflows.md) + +

+ +## ![✔] 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**](./sections/errorhandling/apmproducts.md) + +

+ +## ![✔] 2.10 Catch unhandled promise rejections + +### `📝 #updated` + +**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**](./sections/errorhandling/catchunhandledpromiserejection.md) + +

+ +## ![✔] 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 modern validation library like [ajv](https://www.npmjs.com/package/ajv), [zod](https://github.com/colinhacks/zod), or [typebox](https://github.com/sinclairzx81/typebox) + +**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**](./sections/errorhandling/failfast.md) + +

+ +## ![✔] 2.12 Always await promises before returning to avoid a partial stacktrace + +### `🌟 #new` + +**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**](./sections/errorhandling/returningpromises.md) + +

+ +## ![✔] 2.13 Subscribe to event emitters and streams 'error' event + +### `🌟 #new` + +**TL;DR:** Unlike typical functions, a try-catch clause won't get errors that originate from Event Emitters and anything inherited from it (e.g., streams). Instead of try-catch, subscribe to an event emitter's 'error' event so your code can handle the error in context. When dealing with [EventTargets](https://nodejs.org/api/events.html#eventtarget-and-event-api) (the web standard version of Event Emitters) there are no 'error' event and all errors end in the process.on('error) global event - in this case, at least ensure that the process crash or not based on the desired context. Also, mind that error originating from _asynchronous_ event handlers are not get caught unless the event emitter is initialized with {captureRejections: true} + +**Otherwise:** Event emitters are commonly used for global and key application functionality such as DB or message queue connection. When this kind of crucial objects throw an error, at best the process will crash due to unhandled exception. Even worst, it will stay alive as a zombie while a key functionality is turned off + +


+ +

⬆ Return to top

+ +# `3. Code Patterns And Style Practices` + +## ![✔] 3.1 Use ESLint + +**TL;DR:** [ESLint](https://eslint.org) 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](https://www.npmjs.com/package/prettier) 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**](./sections/codestylepractices/eslint_prettier.md) + +

+ +## ![✔] 3.2 Use Node.js eslint extension plugins + +### `📝 #updated` + +**TL;DR:** On top of ESLint standard rules that cover vanilla JavaScript, add Node.js specific plugins like [eslint-plugin-node](https://www.npmjs.com/package/eslint-plugin-node), [eslint-plugin-mocha](https://www.npmjs.com/package/eslint-plugin-mocha) and [eslint-plugin-node-security](https://www.npmjs.com/package/eslint-plugin-security), [eslint-plugin-require](https://www.npmjs.com/package/eslint-plugin-require), [/eslint-plugin-jest](https://www.npmjs.com/package/eslint-plugin-jest) and other useful rules + +**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 + +```javascript +// 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)](https://stackoverflow.com/questions/3641519/why-does-a-results-vary-based-on-curly-brace-placement) + +

+ +## ![✔] 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](https://prettier.io/) or [Standardjs](https://standardjs.com/) 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 + +```javascript +// 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"](https://eslint.org/docs/rules/semi) +🔗 [**Read more:** "No unexpected multiline ESLint rule"](https://eslint.org/docs/rules/no-unexpected-multiline) + +

+ +## ![✔] 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, **_UpperCamelCase_** (capital first letter as well) when naming classes and **_UPPER_SNAKE_CASE_** when naming global or static variables. This will help you to easily distinguish between plain variables, functions, classes that require instantiation and variables declared at global module scope. 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 + +```javascript +// for global variables names we use the const/let keyword and UPPER_SNAKE_CASE +let MUTABLE_GLOBAL = "mutable value"; +const GLOBAL_CONSTANT = "immutable value"; +const CONFIG = { + key: "value", +}; + +// examples of UPPER_SNAKE_CASE convention in nodejs/javascript ecosystem +// in javascript Math.PI module +const PI = 3.141592653589793; + +// https://github.com/nodejs/node/blob/b9f36062d7b5c5039498e98d2f2c180dca2a7065/lib/internal/http2/core.js#L303 +// in nodejs http2 module +const HTTP_STATUS_OK = 200; +const HTTP_STATUS_CREATED = 201; + +// for class name we use UpperCamelCase +class SomeClassExample { + // for static class properties we use UPPER_SNAKE_CASE + static STATIC_PROPERTY = "value"; +} + +// for functions names we use lowerCamelCase +function doSomething() { + // for scoped variable names we use the const/let keyword and lowerCamelCase + const someConstExample = "immutable value"; + let someMutableExample = "mutable value"; +} +``` + +

+ +## ![✔] 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](https://hackernoon.com/why-you-shouldnt-use-var-anymore-f109a58b9b70) 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?** ](https://medium.com/javascript-scene/javascript-es6-var-let-or-const-ba58b8dcde75) + +

+ +## ![✔] 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 Set an explicit entry point to a module/folder + +### `📝 #updated` + +**TL;DR:** When developing a module/library, set an explicit root file that exports the public and interesting code. Discourage the client code from importing deep files and becoming familiar with the internal structure. With commonjs (require), this can be done with an index.js file at the folder's root or the package.json.main field. With ESM (import), if a package.json exists on the root, the field "exports" allow specifying the module's root file. If no package.json exists, you may put an index.js file on the root which re-exports all the public functionality + +**Otherwise:** Having an explicit root file acts like a public 'interface' that encapsulates the internal, directs the caller to the public code and facilitates future changes without breaking the contract + +### 3.9 Code example - avoid coupling the client to the module structure + +```javascript +// Avoid: client has deep familiarity with the internals + +// Client code +const SMSWithMedia = require("./SMSProvider/providers/media/media-provider.js"); + +// Better: explicitly export the public functions + +//index.js, module code +module.exports.SMSWithMedia = require("./SMSProvider/providers/media/media-provider.js"); + +// Client code +const { SMSWithMedia } = require("./SMSProvider"); +``` + +

+ +## ![✔] 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 + +```javascript +"" == "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:** Async-await is the simplest way to express an asynchronous flow as it makes asynchronous code look synchronous. Async-await will also result in much more compact code and support for try-catch. This technique now supersedes callbacks and promises in _most_ cases. Using it in your code is probably the best gift one can give to the code reader + +**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](https://github.com/yortus/asyncawait) + +

+ +## ![✔] 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**](https://medium.com/javascript-scene/familiarity-bias-is-holding-you-back-its-time-to-embrace-arrow-functions-3d37e1a9bb75) + +

+ +## ![✔] 3.13 Avoid effects outside of functions + +### `🌟 #new` + +**TL;DR:** Avoid putting code with effects like network or DB calls outside of functions. Such a code will be executed immediately when another file requires the file. This 'floating' code might get executed when the underlying system is not ready yet. It also comes with a performance penalty even when this module's functions will finally not be used in runtime. Last, mocking these DB/network calls for testing is harder outside of functions. Instead, put this code inside functions that should get called explicitly. If some DB/network code must get executed right when the module loads, consider using the factory or revealing module patterns + +**Otherwise:** A typical web framework sets error handler, environment variables and monitoring. When DB/network calls are made before the web framework is initialized, they won't be monitored or fail due to a lack of configuration data + +


+ +

⬆ Return to top

+ +# `4. Testing And Overall Quality Practices` + +\_We have dedicated guides for testing, see below. The best practices list here is a brief summary of these guides + +a. [JavaScript testing best practices](https://github.com/goldbergyoni/javascript-testing-best-practices) +b. [Node.js testing - beyond the basics](https://github.com/testjavascript/nodejs-integration-tests-best-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](https://www.getpostman.com/)). Afterwards, 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 + +### `🌟 #new` + +**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**](./sections/testingandquality/3-parts-in-name.md) + +

+ +## ![✔] 4.3 Structure tests by the AAA pattern + +### `🌟 #new` + +**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**](./sections/testingandquality/aaa.md) + +

+ +## ![✔] 4.4 Ensure Node version is unified + +### `🌟 #new` + +**TL;DR:** Use tools that encourage or enforce the same Node.js version across different environments and developers. Tools like [nvm](https://github.com/nvm-sh/nvm), and [Volta](https://volta.sh/) allow specifying the project's version in a file so each team member can run a single command to conform with the project's version. Optionally, this definition can be replicated to CI and the production runtime (e.g., copy the specified value to .Dockerfile build and to the CI declaration file) + +**Otherwise:** A developer might face or miss an error because she uses a different Node.js version than her teammates. Even worse - the production runtime might be different than the environment where tests were executed + +

+ +## ![✔] 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**](./sections/testingandquality/avoid-global-test-fixture.md) + +

+ +## ![✔] 4.6 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](https://mochajs.org/): 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.7 Check your test coverage, it helps to identify wrong test patterns + +**TL;DR:** Code coverage tools like [Istanbul](https://github.com/istanbuljs/istanbuljs)/[NYC](https://github.com/istanbuljs/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.8 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.9 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](https://www.sonarqube.org/) (2,600+ [stars](https://github.com/SonarSource/sonarqube)) and [Code Climate](https://codeclimate.com/) (1,500+ [stars](https://github.com/codeclimate/codeclimate)). + +**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!**](./sections/testingandquality/refactoring.md) + +

+ +## ![✔] 4.10 Mock responses of external HTTP services + +### `🌟 #new` + +**TL;DR:** Use network mocking tools to simulate responses of external collaborators' services that are approached over the network (e.g., REST, Graph). This is imperative not only to isolate the component under test but mostly to simulate non-happy path flows. Tools like [nock](https://github.com/nock/nock) (in-process) or [Mock-Server](https://www.mock-server.com/) allow defining a specific response of external service in a single line of code. Remember to simulate also errors, delays, timeouts, and any other event that is likely to happen in production + +**Otherwise:** Allowing your component to reach real external services instances will likely result in naive tests that mostly cover happy paths. The tests might also be flaky and slow + +🔗 [**Read More: Mock external services**](./sections/testingandquality/mock-external-services.md) + +## ![✔] 4.11 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**](./sections/testingandquality/test-middlewares.md) + +## ![✔] 4.12 Specify a port in production, randomize in testing + +### `🌟 #new` + +**TL;DR:** When testing against the API, it's common and desirable to initialize the web server inside the tests. Let the server randomize the web server port in testing to prevent collisions. If you're using Node.js http server (used by most frameworks), doing so demands nothing but passing a port number zero - this will randomize an available port + +**Otherwise:** Specifying a fixed port will prevent two testing processes from running at the same time. Most of the modern test runners run with multiple processes by default + +🔗 [**Read More: Randomize a port for testing**](./sections/testingandquality/randomize-port.md) + +## ![✔] 4.13 Test the five possible outcomes + +### `🌟 #new` + +**TL;DR:** When testing a flow, ensure to cover five potential categories. Any time some action is triggered (e.g., API call), a reaction occurs, a meaningful **outcome** is produced and calls for testing. There are five possible outcome types for every flow: a response, a visible state change (e.g., DB), an outgoing API call, a new message in a queue, and an observability call (e.g., logging, metric). See a [checklist here](https://testjavascript.com/wp-content/uploads/2021/10/the-backend-checklist.pdf). Each type of outcome comes with unique challenges and techniques to mitigate those challenges - we have a dedicated guide about this topic: [Node.js testing - beyond the basics](https://github.com/testjavascript/nodejs-integration-tests-best-practices) + +**Otherwise:** Consider a case when testing the addition of a new product to the system. It's common to see tests that assert on a valid response only. What if the product was failed to persist regardless of the positive response? what if when adding a new product demands calling some external service, or putting a message in the queue - shouldn't the test assert these outcomes as well? It's easy to overlook various paths, this is where a [checklist comes handy](https://testjavascript.com/wp-content/uploads/2021/10/the-backend-checklist.pdf) + +🔗 [**Read More: Test five outcomes**](./sections/testingandquality/test-five-outcomes.md) + +


+ +

⬆ 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. In any case, the 4 layers of observability must be covered: uptime, metrics with focus on user-facing symptoms and Node.js technical metrics like event loop lag, distributed flows measurement with Open Telemetry and logging. Click ‘Read More’ below for an overview of the solutions + +**Otherwise:** Failure === disappointed customers. Simple + +🔗 [**Read More: Monitoring!**](./sections/production/monitoring.md) + +

+ +## ![✔] 5.2. Increase the observability 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**](./sections/production/smartlogging.md) + +

+ +## ![✔] 5.3. Delegate anything possible (e.g. gzip, SSL) to a reverse proxy + +**TL;DR:** Node is quite bad at doing CPU intensive tasks like gzipping, SSL termination, etc. You should use specialized infrastructure 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**](./sections/production/delegatetoproxy.md) + +

+ +## ![✔] 5.4. Lock dependencies + +**TL;DR:** Your code must be identical across all environments, but without a special lockfile npm lets dependencies drift across environments. Ensure to commit your package-lock.json so all the environments will be identical + +**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**](./sections/production/lockdependencies.md) + +

+ +## ![✔] 5.5. Guard process uptime using the right tool + +**TL;DR:** The process must go on and get restarted upon failures. Modern runtime platforms like Docker-ized platforms (e.g. Kubernetes), and Serverless take care for this automatically. When the app is hosted on a bare metal server, one must take care for a process management tools like [systemd](https://systemd.io/). Avoid including a custom process management tool in a modern platform that monitors an app instance (e.g., Kubernetes) - doing so will hide failures from the infrastructure. When the underlying infrastructure is not aware of errors, it can't perform useful mitigation steps like re-placing the instance in a different location + +**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**](./sections/production/guardprocess.md) + +

+ +## ![✔] 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. Most of the modern run-times platform (e.g., Kubernetes) allow replicating instances of the app but they won't verify that all cores are utilized - this is your duty. If the app is hosted on a bare server, it's also your duty to use some process replication solution (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**](./sections/production/utilizecpu.md) + +

+ +## ![✔] 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-tested 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’**](./sections/production/createmaintenanceendpoint.md) + +

+ +## ![✔] 5.8. Discover the unknowns using APM products + +### `📝 #updated` + +**TL;DR:** Consider adding another safety layer to the production stack - APM. While the majority of symptoms and causes can be detected using traditional monitoring techniques, in a distributed system there is more than meets the eye. Application monitoring and performance products (a.k.a. APM) can auto-magically go beyond traditional monitoring and provide additional layer of discovery and developer-experience. For example, some APM products can highlight a transaction that loads too slow on the **end-user's side** while suggesting the root cause. APMs also provide more context for developers who try to troubleshoot a log error by showing what was the server busy with when the error occurred. To name a few example + +**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**](./sections/production/apmproducts.md) + +

+ +## ![✔] 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 'Read More') + +**Otherwise:** A world champion IT/DevOps guy won’t save a system that is badly written + +🔗 [**Read More: Make your code production-ready**](./sections/production/productioncode.md) + +

+ +## ![✔] 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](https://www.joyent.com/blog/walmart-node-js-memory-leak) + +🔗 [**Read More: Measure and guard the memory usage**](./sections/production/measurememory.md) + +

+ +## ![✔] 5.11. Get your frontend assets out of Node + +**TL;DR:** Serve frontend content using a specialized infrastructure (nginx, S3, CDN) because Node performance gets hurt when dealing with many static files due to its single-threaded model. One exception to this guideline is when doing server-side rendering + +**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**](./sections/production/frontendout.md) + +

+ +## ![✔] 5.12. Strive to be stateless + +**TL;DR:** Store any type of _data_ (e.g. user sessions, cache, uploaded files) within external data stores. When the app holds data in-process this adds additional layer of maintenance complexity like routing users to the same instance and higher cost of restarting a process. To enforce and encourage a stateless approach, most modern runtime platforms allows 'reapp-ing' instances periodically + +**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**](./sections/production/bestateless.md) + +

+ +## ![✔] 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**](./sections/production/detectvulnerabilities.md) + +

+ +## ![✔] 5.14. Assign a transaction id to each log statement + +**TL;DR:** Assign the same identifier, transaction-id: uuid(), to each log entry within a single request (also known as correlation-id/tracing-id/request-context). Then when inspecting errors in logs, easily conclude what happened before and after. Node has a built-in mechanism, [AsyncLocalStorage](https://nodejs.org/api/async_context.html), for keeping the same context across asynchronous calls. 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**](./sections/production/assigntransactionid.md) + +

+ +## ![✔] 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 – some npm packages determine the current environment and optimize their code for production + +**Otherwise:** Omitting this simple property might greatly degrade performance when dealing with some specific libraries like Express server-side rendering + +🔗 [**Read More: Set NODE_ENV=production**](./sections/production/setnodeenv.md) + +

+ +## ![✔] 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**](./sections/production/LTSrelease.md) + +

+ +## ![✔] 5.18. Log to stdout, avoid specifying log destination within the app + +### `📝 #updated` + +**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:** If developers set the log routing, less flexibility is left for the ops professional who wishes to customize it. Beyond this, if the app tries to log directly to a remote location (e.g., Elastic Search), in case of panic or crash - further logs that might explain the problem won't arrive + +🔗 [**Read More: Log Routing**](./sections/production/logrouting.md) + +

+ +## ![✔] 5.19. Install your packages with `npm ci` + +**TL;DR:** Run `npm ci` to strictly do a clean install of your dependencies matching package.json and package-lock.json. Obviously production code must use the exact version of the packages that were used for testing. While package-lock.json file sets strict version for dependencies, in case of mismatch with the file package.json, the command 'npm install' will treat package.json as the source of truth. On the other hand, the command 'npm ci' will exit with error in case of mismatch between these files + +**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**](./sections/production/installpackageswithnpmci.md) + +


+ +

⬆ 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](https://github.com/nodesecurity/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**](./sections/security/lintrules.md) + +

+ +## ![✔] 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](https://www.npmjs.com/package/rate-limiter-flexible) package, or (for smaller and less critical apps) a rate-limiting middleware (e.g. [express-rate-limit](https://www.npmjs.com/package/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**](./sections/security/limitrequests.md) + +

+ +## ![✔] 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**](./sections/security/secretmanagement.md) + +

+ +## ![✔] 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](https://github.com/sequelize/sequelize), [Knex](https://github.com/tgriesser/knex), [mongoose](https://github.com/Automattic/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**](./sections/security/ormodmusage.md) + +

+ +## ![✔] 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**](./sections/security/commonsecuritybestpractices.md) + +

+ +## ![✔] 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](https://www.npmjs.com/package/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**](./sections/security/secureheaders.md) + +

+ +## ![✔] 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](https://docs.npmjs.com/cli/audit) or [snyk](https://snyk.io/) 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**](./sections/security/dependencysecurity.md) + +

+ +## ![✔] 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**](./sections/security/userpasswords.md) + +

+ +## ![✔] 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**](./sections/security/escape-output.md) + +

+ +## ![✔] 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](https://www.npmjs.com/package/jsonschema) or [joi](https://www.npmjs.com/package/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**](./sections/security/validation.md) + +

+ +## ![✔] 6.11. Support blocklisting JWTs + + + +**TL;DR:** When using JSON Web Tokens (for example, with [Passport.js](https://github.com/jaredhanson/passport)), 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**](./sections/security/expirejwt.md) + +

+ +## ![✔] 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**](./sections/security/login-rate-limit.md) + +

+ +## ![✔] 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 their server) + +🔗 [**Read More: Run Node.js as non-root user**](./sections/security/non-root-user.md) + +

+ +## ![✔] 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](https://github.com/expressjs/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**](./sections/security/requestpayloadsizelimit.md) + +

+ +## ![✔] 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**](./sections/security/avoideval.md) + +

+ +## ![✔] 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](https://github.com/chriso/validator.js) instead of writing your own Regex patterns, or make use of [safe-regex](https://github.com/substack/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**](./sections/security/regex.md) + +

+ +## ![✔] 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](https://www.npmjs.com/package/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**](./sections/security/safemoduleloading.md) + +

+ +## ![✔] 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**](./sections/security/sandbox.md) + +

+ +## ![✔] 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**](./sections/security/childprocesses.md) + +

+ +## ![✔] 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**](./sections/security/hideerrors.md) + +

+ +## ![✔] 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?](https://medium.com/@oprearocks/eslint-backdoor-what-it-is-and-how-to-fix-the-issue-221f58f1a8c8) + +

+ +## ![✔] 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**](./sections/security/sessions.md) + +

+ +## ![✔] 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**](./sections/security/saferedirects.md) + +

+ +## ![✔] 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**](./sections/security/avoid_publishing_secrets.md) + +

+ +## ![✔] 6.26 Inspect for outdated packages + +**TL;DR:** Use your preferred tool (e.g. `npm outdated` or [npm-check-updates](https://www.npmjs.com/package/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 + +

+ +## ![✔] 6.27. Import built-in modules using the 'node:' protocol + +### `🌟 #new` + + + +**TL;DR:** Import or require built-in Node.js modules using the 'node protocol' syntax: + +```javascript +import { functionName } from "node:module"; // note that 'node:' prefix +``` + +For example: + +```javascript +import { createServer } from "node:http"; +``` + +This style ensures that there is no ambiguity with global npm packages and makes it clear for the reader that the code refers to a well-trusted official module. This style can be enforced with the eslint rule ['prefer-node-protocol'](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-node-protocol.md) + +**Otherwise:** Using the import syntax without 'node:' prefix opens the door for [typosquatting attacks](https://en.wikipedia.org/wiki/Typosquatting) where one could mistakenly mistype a module name (e.g., 'event' instead of 'events) and get a malicious package that was built only to trick users into installing them + +


+ +

⬆ Return to top

+ +# `7. Draft: Performance Best Practices` + +## Our contributors are working on this section. [Would you like to join?](https://github.com/goldbergyoni/nodebestpractices/issues/256) + +

+ +## ![✔] 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**](./sections/performance/block-loop.md) + +


+ +## ![✔] 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**](./sections/performance/nativeoverutil.md) + +


+ +

⬆ Return to top

+ +# `8. Docker Best Practices` + +🏅 Many thanks to [Bret Fisher](https://github.com/BretFisher) 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 + +```dockerfile +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**](./sections/docker/multi_stage_builds.md) + +


+ +## ![✔] 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 + +Update: [Starting from npm 7, npm claim](https://docs.npmjs.com/cli/v7/using-npm/changelog#706-2020-10-27) to pass signals. We follow and will update accordingly + +**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**](./sections/docker/bootstrap-using-node.md) + +


+ +## ![✔] 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**](./sections/docker/restart-and-replicate-processes.md) + +


+ +## ![✔] 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**](./sections/docker/docker-ignore.md) + +


+ +## ![✔] 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](https://eslint.org/blog/2018/07/postmortem-for-malicious-package-publishes)) + +🔗 Read More: [Remove development dependencies](./sections/docker/install-for-production.md) + +


+ +## ![✔] 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**](./sections/docker/graceful-shutdown.md) + +


+ +## ![✔] 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**](./sections/docker/memory-limit.md) + +


+ +## ![✔] 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**](./sections/docker/use-cache-for-shorter-build-time.md) + +


+ +## ![✔] 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**](./sections/docker/image-tags.md) + +


+ +## ![✔] 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**](./sections/docker/smaller_base_images.md) + +


+ +## ![✔] 8.11. Clean-out build-time secrets, avoid secrets in args + +### `🌟 #new` + +**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**](./sections/docker/avoid-build-time-secrets.md) + +


+ +## ![✔] 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**](./sections/docker/scan-images.md) + +


+ +## ![✔] 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**](./sections/docker/clean-cache.md) + +


+ +## ![✔] 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**](./sections/docker/generic-tips.md) + +


+ +## ![✔] 8.15. Lint your Dockerfile + +### `🌟 #new` + +**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**](./sections/docker/lint-dockerfile.md) + +


+ +

⬆ 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](https://github.com/goldbergyoni/nodebestpractices/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 + +- ![BR](./assets/flags/BR.png) [Brazilian Portuguese](./README.brazilian-portuguese.md) - Courtesy of [Marcelo Melo](https://github.com/marcelosdm) +- ![CN](./assets/flags/CN.png) [Chinese](./README.chinese.md) - Courtesy of [Matt Jin](https://github.com/mattjin) +- ![RU](./assets/flags/RU.png) [Russian](./README.russian.md) - Courtesy of [Alex Ivanov](https://github.com/contributorpw) +- ![PL](./assets/flags/PL.png) [Polish](./README.polish.md) - Courtesy of [Michal Biesiada](https://github.com/mbiesiad) +- ![JA](./assets/flags/JA.png) [Japanese](./README.japanese.md) - Courtesy of [Yuki Ota](https://github.com/YukiOta), [Yuta Azumi](https://github.com/YA21) +- ![EU](./assets/flags/EU.png) [Basque](README.basque.md) - Courtesy of [Ane Diaz de Tuesta](https://github.com/anediaz) & Joxefe Diaz de Tuesta + +### Translations in progress + +- ![FR](./assets/flags/FR.png) [French](./README.french.md) ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/129)) +- ![HE](./assets/flags/HE.png) [Hebrew](./README.hebrew.md) ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/156)) +- ![KR](./assets/flags/KR.png) [Korean](README.korean.md) - Courtesy of [Sangbeom Han](https://github.com/uronly14me) ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/94)) +- ![ES](./assets/flags/ES.png) [Spanish](https://github.com/goldbergyoni/nodebestpractices/blob/spanish-translation/README.spanish.md) ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/95)) +- ![TR](./assets/flags/TR.png) Turkish ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/139)) + +

+ +## 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](https://github.com/goldbergyoni/nodebestpractices/projects). + + + +[Yoni Goldberg](https://github.com/goldbergyoni) + + + +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](https://goldbergyoni.com). Reach Yoni at [@goldbergyoni](https://github.com/goldbergyoni) or [me@goldbergyoni.com](mailto:me@goldbergyoni.com) + +
+ +Josh Hemphill + +[Josh Hemphill](https://github.com/josh-hemphill) + + + + +Full Stack Software Engineer / Developer specializing in Security, DevOps/DevSecOps, and ERP Integrations. + +
+ +Raz Luvaton + +[Raz Luvaton](https://github.com/rluvaton) + + + +Full Stack Developer who knows how to exit from Vim and loves Architecture, Virtualization and Security. + +
+ +## Contributing + +If you've ever wanted to contribute to open source, now is your chance! See the [contributing docs](.operations/CONTRIBUTING.md) for more information. + +## Contributors ✨ + +Thanks goes to these wonderful people who have contributed to this repository! + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Kevin Rambaud
Kevin Rambaud

🖋
Michael Fine
Michael Fine

🖋
Shreya Dahal
Shreya Dahal

🖋
Matheus Cruz Rocha
Matheus Cruz Rocha

🖋
Yog Mehta
Yog Mehta

🖋
Kudakwashe Paradzayi
Kudakwashe Paradzayi

🖋
t1st3
t1st3

🖋
mulijordan1976
mulijordan1976

🖋
Matan Kushner
Matan Kushner

🖋
Fabio Hiroki
Fabio Hiroki

🖋
James Sumners
James Sumners

🖋
Dan Gamble
Dan Gamble

🖋
PJ Trainor
PJ Trainor

🖋
Remek Ambroziak
Remek Ambroziak

🖋
Yoni Jah
Yoni Jah

🖋
Misha Khokhlov
Misha Khokhlov

🖋
Evgeny Orekhov
Evgeny Orekhov

🖋
-
-

🖋
Isaac Halvorson
Isaac Halvorson

🖋
Vedran Karačić
Vedran Karačić

🖋
lallenlowe
lallenlowe

🖋
Nathan Wells
Nathan Wells

🖋
Paulo Reis
Paulo Reis

🖋
syzer
syzer

🖋
David Sancho
David Sancho

🖋
Robert Manolea
Robert Manolea

🖋
Xavier Ho
Xavier Ho

🖋
Aaron
Aaron

🖋
Jan Charles Maghirang Adona
Jan Charles Maghirang Adona

🖋
Allen
Allen

🖋
Leonardo Villela
Leonardo Villela

🖋
Michał Załęcki
Michał Załęcki

🖋
Chris Nicola
Chris Nicola

🖋
Alejandro Corredor
Alejandro Corredor

🖋
cwar
cwar

🖋
Yuwei
Yuwei

🖋
Utkarsh Bhatt
Utkarsh Bhatt

🖋
Duarte Mendes
Duarte Mendes

🖋
Jason Kim
Jason Kim

🖋
Mitja O.
Mitja O.

🖋
Sandro Miguel Marques
Sandro Miguel Marques

🖋
Gabe
Gabe

🖋
Ron Gross
Ron Gross

🖋
Valeri Karpov
Valeri Karpov

🖋
Sergio Bernal
Sergio Bernal

🖋
Nikola Telkedzhiev
Nikola Telkedzhiev

🖋
Vitor Godoy
Vitor Godoy

🖋
Manish Saraan
Manish Saraan

🖋
Sangbeom Han
Sangbeom Han

🖋
blackmatch
blackmatch

🖋
Joe Reeve
Joe Reeve

🖋
Ryan Busby
Ryan Busby

🖋
Iman Mohamadi
Iman Mohamadi

🖋
Sergii Paryzhskyi
Sergii Paryzhskyi

🖋
Kapil Patel
Kapil Patel

🖋
迷渡
迷渡

🖋
Hozefa
Hozefa

🖋
Ethan
Ethan

🖋
Sam
Sam

🖋
Arlind
Arlind

🖋
Teddy Toussaint
Teddy Toussaint

🖋
Lewis
Lewis

🖋
Gabriel Lidenor
Gabriel Lidenor

🖋
Roman
Roman

🖋
Francozeira
Francozeira

🖋
Invvard
Invvard

🖋
Rômulo Garofalo
Rômulo Garofalo

🖋
Tho Q Luong
Tho Q Luong

🖋
Burak Shen
Burak Shen

🖋
Martin Muzatko
Martin Muzatko

🖋
Jared Collier
Jared Collier

🖋
Hilton Meyer
Hilton Meyer

🖋
ChangJoo Park(박창주)
ChangJoo Park(박창주)

🖋
Masahiro Sakaguchi
Masahiro Sakaguchi

🖋
Keith Holliday
Keith Holliday

🖋
coreyc
coreyc

🖋
Maximilian Berkmann
Maximilian Berkmann

🖋
Douglas Mariano Valero
Douglas Mariano Valero

🖋
Marcelo Melo
Marcelo Melo

🖋
Mehmet Perk
Mehmet Perk

🖋
ryan ouyang
ryan ouyang

🖋
Shabeer
Shabeer

🖋
Eduard Kyvenko
Eduard Kyvenko

🖋
Deyvison Rocha
Deyvison Rocha

🖋
George Mamer
George Mamer

🖋
Konstantinos Leimonis
Konstantinos Leimonis

🖋
Oliver Lluberes
Oliver Lluberes

🌍
Tien Do
Tien Do

🖋
Ranvir Singh
Ranvir Singh

🖋
Vadim Nicolaev
Vadim Nicolaev

🖋 🌍
German Gamboa Gonzalez
German Gamboa Gonzalez

🖋
Hafez
Hafez

🖋
Chandiran
Chandiran

🖋
VinayaSathyanarayana
VinayaSathyanarayana

🖋
Kim Kern
Kim Kern

🖋
Kenneth Freitas
Kenneth Freitas

🖋
songe
songe

🖋
Kirill Shekhovtsov
Kirill Shekhovtsov

🖋
Serge
Serge

🖋
keyrwinz
keyrwinz

🖋
Dmitry Nikitenko
Dmitry Nikitenko

🖋
bushuai
bushuai

👀 🖋
Benjamin Gruenbaum
Benjamin Gruenbaum

🖋
Ezequiel
Ezequiel

🌍
Juan José Rodríguez
Juan José Rodríguez

🌍
Or Bin
Or Bin

🖋
Andreo Vieira
Andreo Vieira

🖋
Michael Solomon
Michael Solomon

🖋
Jimmy Callin
Jimmy Callin

🖋
Siddharth
Siddharth

🖋
Ryan Smith
Ryan Smith

🖋
Tom Boettger
Tom Boettger

🖋
Joaquín Ormaechea
Joaquín Ormaechea

🌍
dfrzuz
dfrzuz

🌍
Victor Homyakov
Victor Homyakov

🖋
Josh
Josh

🖋 🛡️
Alec Francis
Alec Francis

🖋
arjun6610
arjun6610

🖋
Jan Osch
Jan Osch

🖋
Thiago Rotondo Sampaio
Thiago Rotondo Sampaio

🌍
Alexsey
Alexsey

🖋
Luis A. Acurero
Luis A. Acurero

🌍
Lucas Romano
Lucas Romano

🌍
Denise Case
Denise Case

🖋
Nick Ribal
Nick Ribal

🖋 👀
0xflotus
0xflotus

🖋
Jonathan Chen
Jonathan Chen

🖋
Dilan Srilal
Dilan Srilal

🖋
vladthelittleone
vladthelittleone

🌍
Nik Osvalds
Nik Osvalds

🖋
Daniel Kiss
Daniel Kiss

📖
Forresst
Forresst

🖋
Jonathan Svenheden
Jonathan Svenheden

🖋
AustrisC
AustrisC

🖋
kyeongtae kim
kyeongtae kim

🌍
007
007

🖋
Ane Diaz de Tuesta
Ane Diaz de Tuesta

🌍 🖋
YukiOta
YukiOta

🌍
Frazer Smith
Frazer Smith

🖋
Raz Luvaton
Raz Luvaton

🖋
Yuta Azumi
Yuta Azumi

🖋
andrewjbarbour
andrewjbarbour

🖋
mr
mr

🖋
Aleksandar
Aleksandar

🖋
Owl
Owl

🖋
Yedidya Schwartz
Yedidya Schwartz

🖋 💡
ari
ari

🖋
Thomas König
Thomas König

🖋
Kalle Lämsä
Kalle Lämsä

🖋
Wyatt
Wyatt

🖋
KHADIR Tayeb
KHADIR Tayeb

🖋
Shankar Regmi
Shankar Regmi

🖋
Shubham
Shubham

🖋
Lucas Alves
Lucas Alves

🖋
Benjamin
Benjamin

🖋
Yeoh Joer
Yeoh Joer

🖋
Miigon
Miigon

🖋
Rostislav Bogorad
Rostislav Bogorad

🖋
Flouse
Flouse

🖋
Tarantini Pereira
Tarantini Pereira

🖋
Kazuki Matsuo
Kazuki Matsuo

🖋
Adam Smith
Adam Smith

🖋
Dohyeon Ko
Dohyeon Ko

🖋
Vladislav Legkov
Vladislav Legkov

🖋
Kerollos Magdy
Kerollos Magdy

🖋
Erez Lieberman
Erez Lieberman

🖋
Breno Macedo
Breno Macedo

🖋
Fernando Flores
Fernando Flores

🌍
Rafael Brito
Rafael Brito

🌍
Emiliano Peralta
Emiliano Peralta

🌍
Shin, SJ
Shin, SJ

🖋
Benjamin Forster
Benjamin Forster

🖋
Daniele Fedeli
Daniele Fedeli

🖋
djob195
djob195

🖋
antspk
antspk

🖋
정진영
정진영

🖋
kkk-cashwalk
kkk-cashwalk

🖋
apainintheneck
apainintheneck

🖋
Fajar Budhi Iswanda
Fajar Budhi Iswanda

🖋
이주호
이주호

🖋
Singh
Singh

🖋
Alex Dumitru
Alex Dumitru

🖋
Anton Lykhatskyi
Anton Lykhatskyi

🖋
sangwonlee
sangwonlee

🖋
Eugenio Berretta
Eugenio Berretta

🖋
soranakk
soranakk

🖋
고준영
고준영

🖋 💻
Guilherme Portella
Guilherme Portella

🖋
André Esser
André Esser

🖋
Scc
Scc

🌍
Mauro Accornero
Mauro Accornero

🖋
no-yan
no-yan

🖋
hodbauer
hodbauer

🌍
+ + + + + + +### Steering Committee Emeriti + +[Bruno Scheufler](https://github.com/BrunoScheufler) + + +💻 full-stack web engineer, Node.js & GraphQL enthusiast + +
+ + + +[Kyle Martin](https://github.com/js-kyle) + + + +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](https://github.com/kevynb) + + +Independent full-stack developer with a taste for Ops and automation. + +
+ + + +[Sagir Khan](https://github.com/sagirk) + + + + +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. +
diff --git a/README.basque.md b/README.basque.md index fb7ab29f2..eefa504a1 100644 --- a/README.basque.md +++ b/README.basque.md @@ -1,45 +1,44 @@ [✔]: assets/images/checkbox-small-blue.png -# Node.js-ren jardunbide egokiak +# Node.js-ren praktika onak

- Node.js-ren jardunbide egokiak + Node.js-ren praktika onak


- 102 items Azken eguneratzea: 2020ko azaroa Node 14.0.0rako eguneratua + 102 items Azken eguneratzea: 2020ko azaroa Node 14.0.0rako eguneratua

-[![nodepractices](/assets/images/twitter-s.png)](https://twitter.com/nodepractices/) **Hemen ere bagaude!** [**@nodepractices**](https://twitter.com/nodepractices/) +[![nodepractices](./assets/images/twitter-s.png)](https://twitter.com/nodepractices/) **Hemen ere bagaude!** [**@nodepractices**](https://twitter.com/nodepractices/)
-Irakurri beste hizkuntza batzuetan: [![CN](/assets/flags/CN.png)**CN**](/README.chinese.md), [![BR](/assets/flags/BR.png)**BR**](/README.brazilian-portuguese.md), [![RU](/assets/flags/RU.png)**RU**](/README.russian.md), [![PL](/assets/flags/PL.png)**PL**](/README.polish.md) [(![ES](/assets/flags/ES.png)**ES**, ![FR](/assets/flags/FR.png)**FR**, ![HE](/assets/flags/HE.png)**HE**, ![KR](/assets/flags/KR.png)**KR** eta ![TR](/assets/flags/TR.png)**TR** aribidean!)](#translations) +Irakurri beste hizkuntza batzuetan: [![EN](./assets/flags/EN.png)**EN**](./README.md), [![CN](./assets/flags/CN.png)**CN**](./README.chinese.md), [![BR](./assets/flags/BR.png)**BR**](./README.brazilian-portuguese.md), [![RU](./assets/flags/RU.png)**RU**](./README.russian.md), [![PL](./assets/flags/PL.png)**PL**](./README.polish.md),[![JA](./assets/flags/JA.png)**JA**](./README.japanese.md) [(![ES](./assets/flags/ES.png)**ES**, ![FR](./assets/flags/FR.png)**FR**, ![HE](./assets/flags/HE.png)**HE**, ![KR](./assets/flags/KR.png)**KR** eta ![TR](./assets/flags/TR.png)**TR** aribidean!)](#itzulpenak)
###### Gure [Zuzendaritza Batzordeak ](#zuzendaritza-batzordea) eta [laguntzaileek](#Languntzaileak) eraiki eta mantentzen dute webgune hau -# Azken jardunbide egokiak eta albisteak +# Azken praktika onak eta albisteak -- **✅ Jardunbide egoki berria:** [Alexsey](https://github.com/Alexsey)-ren 2.12 bulletak erakusten du funtzio asinkronikoen zain egon gabe itzultzeak pila aztarna partzialak uzten dituela. Hor arazo handia izan liteke salbuespenek eragindako arazoak konpontzean exekuzio fotogrametako batzuk ez dituzten produkzioetan +- **![EU](./assets/flags/EU.png) Euskarazko itzulpena!:** wow gure euskal irakurleek ere gida hau bere ama-hizkuntzan irakur dezakete! [Ane Diaz de Tuesta](https://github.com/anediaz) eta Joxefe Diaz de Tuestaren eskutik -- **✅ Jardunbide egoki berria:** Josh Hemphill-en 6.8 bulletak "Erabiltzaileen pasahitzak / sekretuak BCrypt edo Script erabiliz" babestea gomendatzen du. Azalpen sakona ematen du aukera bakoitza proiektu zehatz batera noiz eta zergatik egokitzen den jakiteko. Ez galdu gida labur hau hash-en aukeren azalpen labur bat eskaintzen duena +- **🇯🇵 Japonierazko itzulpena:** hemendik aurrera japonieraz erabili daiteke gure gida, [YukiOta](https://github.com/YukiOta) eta [Yuta Azumi](https://github.com/YA21) gure laguntzaile ikaragarriei esker -- **:whale: Node.js + Docker-en jardunbide egokiak:** Atal berri bat argitaratu berri dugu, 15 jardunbide egoki jasotze - dituena Dockerrekin erabili beharreko kodetze teknikei buruzkoak +- **🎊 60.000 izar!**: Gure biltegiak 60.100 garatzaileren aitortza eta konfiantza jaso ditu. Hitzik gabe gaude

# Ongi etorri! Hasi aurretik jakin beharreko 3 gauza -**1. Hemen dozenaka artikulu dauzkazu, onenetarikoak Node.jsri buruz egindakoetan:** alegia, bilduma honek Node.jsren jardunbide egokienak jasotzen ditu, edukien arabera sailkatuta +**1. Hemen dozenaka artikulu dauzkazu, onenetarikoak Node.jsri buruz egindakoetan:** alegia, bilduma honek Node.jsren praktika onak jasotzen ditu, edukien arabera sailkatuta -**2. Dagoen bildumarik handiena da, eta astetik astera handiagoa da:** une honetan 80tik gora jardunbide, estilo eskuliburu eta arkitektura aholku dauzkagu bilduta. Gustura asko jasoko genituzte zure ekarpenak bilduma hau eguneratuta edukitzeko, bai kode akatsak konponduz, bai itzulpenak eginez, bai ideia berriak proposatuz egin ditzakezunak: izan zaitez Node.jsren jardunbide egokienen liburuko partaide. Ikusi gure [idazketa jarraibideak](/.operations/writing-guidelines.basque.md) +**2. Dagoen bildumarik handiena da, eta astetik astera handiagoa da:** une honetan 80tik gora praktika, estilo eskuliburu eta arkitektura aholku dauzkagu bilduta. Gustura asko jasoko genituzke zure ekarpenak bilduma hau eguneratuta edukitzeko, bai kode akatsak konponduz, bai itzulpenak eginez, bai ideia berriak proposatuz egin ditzakezunak: izan zaitez Node.jsren praktika onen liburuko partaide. Ikusi gure [idazketa jarraibideak](./.operations/writing-guidelines.basque.md) **3. Jarraibide gehienek informazio gehigarria dute.** Jarraibideko puntu bakoitzaren ondoan **🔗Informazio gehiago** esteka aurkituko duzu, jarraibidea osatzen duena kode adibideekin, blogetako aipu hautatuekin eta informazio osagarri gehiagorekin @@ -48,13 +47,13 @@ Irakurri beste hizkuntza batzuetan: [![CN](/assets/flags/CN.png)**CN**](/README. ## Edukien aurkibidea 1. [Proiektuaren egitura (5)](#1-proiektuaren-egitura) -2. [Erroreen kudeaketa (11) ](#2-erroreen-kudeaketa) +2. [Erroreen kudeaketa (12) ](#2-erroreen-kudeaketa) 3. [Kode estiloa (12) ](#3-kode-estiloa) 4. [Probak eta kalitate orokorra (13) ](#4-probak-eta-kalitate-orokorra) 5. [Ekoizpena (19) ](#5-ekoizpena) 6. [Segurtasuna (25)](#6-segurtasuna) 7. [Errendimendua (2) (Aribidean ✍️)](#7-zirriborroa-errendimendua) -8. [Docker (15)](#8-docker) +8. [Docker, praktika onak (15)](#8-docker-praktika-onak)

@@ -64,9 +63,9 @@ Irakurri beste hizkuntza batzuetan: [![CN](/assets/flags/CN.png)**CN**](/README. **TL;PL:** aplikazio handien oztoporik handiena kode base erraldoi bat mantendu beharra da, ehundaka lotura eta menpekotasun dituena. Horrelako lan monolitikoek programatzaileen lana motelarazten dute, funtzionalitate berriak gehitzen saiatzen dira eta. Hori gerta ez dadin, zatitu zure kodea osagai txikiagotan, bakoitza bere datuekin karpeta banatan, eta bermatu osagai bakoitza laburra eta sinplea izatea. Bisitatu hemen behean dagoen “Informazio gehiago” esteka, proiektu egoki baten egitura zuzenaren adibideak ikusteko -**Bestela:** Bestela: funtzionalitate berriak programatzean, garatzaileek zailtasun handiak izaten dituzte aldaketa horien eragina antzemateko, eta beldur izaten dira funtzionalitateon menpeko osagaiak hautsiko ote dituzten. Ondorioz, inplementazioak motelagoak eta arriskutsuagoak izaten dira. Oro har, zailagoa izaten da aplikazio baten kodea luzatzea negozio unitateak banatuta ez daudenean +**Bestela:** funtzionalitate berriak programatzean, garatzaileek zailtasun handiak izaten dituzte aldaketa horien eragina atzemateko, eta beldur izaten dira funtzionalitateon menpeko osagaiak hautsiko ote dituzten. Ondorioz, inplementazioak motelagoak eta arriskutsuagoak izaten dira. Oro har, zailagoa izaten da aplikazio baten kodea luzatzea negozio unitateak banatuta ez daudenean -🔗 [**Informazio gehiago: antolatu zure proiektua osagai txikiagotan**](/sections/projectstructre/breakintcomponents.basque.md) +🔗 [**Informazio gehiago: antolatu zure proiektua osagai txikiagotan**](./sections/projectstructre/breakintcomponents.basque.md)

@@ -76,17 +75,17 @@ Irakurri beste hizkuntza batzuetan: [![CN](/assets/flags/CN.png)**CN**](/README. **Bestela:** aplikazio batean webeko objektuak beste geruzekin nahastuta badaude, ezingo da bertara sartu testak, CRON atazak eta Express middleware-ak baino erabiliz -🔗 [**Informazio gehiago: antolatu zure aplikazioa geruzatan**](/sections/projectstructre/createlayers.basque.md) +🔗 [**Informazio gehiago: antolatu zure aplikazioa geruzatan**](./sections/projectstructre/createlayers.basque.md)

-## ![✔] 1.3 Kokatu baliabide komunak NPM paketetan +## ![✔] 1.3 Kokatu baliabide komunak npm paketetan -**TL;PL:** data base askok osatzen duten aplikazio handi bat prestatzen dugunean, geruza guztietan lan egiten duten zeharkako tresna bakoitzak –erregistragailuak, zifragailuak eta beste– bere kodearen barruan egon behar du, NPM pakete pribatu moduan, tresna horiek hainbat proiektutan partekatu ahal izatea ahalbidetzen duena +**TL;PL:** datu base askok osatzen duten aplikazio handi bat prestatzen dugunean, geruza guztietan lan egiten duten zeharkako tresna bakoitzak –erregistragailuak, zifragailuak eta beste– bere kodearen barruan egon behar du, npm pakete pribatu moduan, tresna horiek hainbat proiektutan partekatu ahal izatea ahalbidetzen duena **Bestela:** zuk zeuk asmatu beharko duzu zeure inplementazioa eta menpekotasun gurpila -🔗 [**Informazio gehiago: antolatu funtzioen arabera**](/sections/projectstructre/wraputilities.basque.md) +🔗 [**Informazio gehiago: antolatu funtzioen arabera**](./sections/projectstructre/wraputilities.basque.md)

@@ -96,17 +95,17 @@ Irakurri beste hizkuntza batzuetan: [![CN](/assets/flags/CN.png)**CN**](/README. **Bestela:** probak egiteko, HTTP deien bidez baino ezingo da zure APIra sartu. Sarbide hori motelagoa da eta asko zailtzen du estaldura txostenak egitea. Gainera, ziur aski, ez da bat ere atsegina izango ehundaka lerro dituen kodea mantentzea -🔗 [**Informazio gehiago: banandu Express 'aplikazioa' eta 'zerbitzaria'**](/sections/projectstructre/separateexpress.basque.md) +🔗 [**Informazio gehiago: banandu Express 'aplikazioa' eta 'zerbitzaria'**](./sections/projectstructre/separateexpress.basque.md)

## ![✔] 1.5 Erabili ingurunea errespetatzen duen konfigurazio seguru eta hierarkiko bat -**TL;PL:** akatsik gabeko konfigurazio perfektu batek bermatu behar du (a) giltzak fitxategietatik eta inguruneko aldagaietatik irakurri ahal izatea, (b) sekretuak iturri kodetik kanpo gordeta egotea, eta, (c), bilaketak errazte aldera, konfigurazioa hierarkikoa izatea. Hori dena lortzeko badira paketeak, hala nola, rc](https://www.npmjs.com/package/rc), [nconf](https://www.npmjs.com/package/nconf), [config](https://www.npmjs.com/package/config) eta [convict](https://www.npmjs.com/package/convict). +**TL;PL:** akatsik gabeko konfigurazio perfektu batek bermatu behar du (a) giltzak fitxategietatik eta inguruneko aldagaietatik irakurri ahal izatea, (b) sekretuak iturri kodetik kanpo gordeta egotea, eta, (c), bilaketak errazte aldera, konfigurazioa hierarkikoa izatea. Hori dena lortzeko badira paketeak, hala nola, [rc](https://www.npmjs.com/package/rc), [nconf](https://www.npmjs.com/package/nconf), [config](https://www.npmjs.com/package/config) eta [convict](https://www.npmjs.com/package/convict) **Bestela:** konfiguazioa egitean baldintza horietarikoren bat betetzen ez baduzu, lana moteldu egingo da, bai garapen taldearena, bai devops taldearena -🔗 [**Informazio gehiago: konfigurazio jardunbide egokiak**](/sections/projectstructre/configguide.basque.md) +🔗 [**Informazio gehiago: konfigurazio praktika onak**](./sections/projectstructre/configguide.basque.md)


@@ -116,11 +115,11 @@ Irakurri beste hizkuntza batzuetan: [![CN](/assets/flags/CN.png)**CN**](/README. ## ![✔] 2.1 Erabili Async-Await edo errore asinkronoak kudeatzeko promesak -**TL;PL:** errore asinkronoak callback erabiliz kudeatzen badituzu, infernurako biderik azkarrena hartuko duzu edo galbiderako piramidean sartuko zara. Zure kodeari opari on bat egin nahi badiozu, erabili agintzen biblioteka ezagun bat edo async-await, try-catch erakoa adibidez kode sintaxis askoz trinkoago eta ohikoago bat eskaintzen duena +**TL;PL:** errore asinkronoak callback erabiliz kudeatzen badituzu, infernurako biderik azkarrena hartuko duzu edo galbiderako piramidean sartuko zara. Zure kodeari opari on bat egin nahi badiozu, erabili agintzen liburutegi ezagun bat edo async-await, try-catch erakoa adibidez kode sintaxis askoz trinkoago eta ohikoago bat eskaintzen duena -**Bestela:** Node.js-en callback teknika (“err, response” prozedura) erabiltzen baduzu, kode ez jasangarriak sortuko dituzu, batera suertatuko baitira kode arrunta duten erroreen kudeaketa, habiaratze sarriegiak eta kodetze eredu ez erosoak +**Bestela:** Node.jsren callback teknika (“err, response” prozedura) erabiltzen baduzu, kode ez jasangarriak sortuko dituzu, batera suertatuko baitira kode arrunta duten erroreen kudeaketa, habiaratze sarriegiak eta kodetze eredu ez erosoak -🔗 [**Informazio gehiago: ekidin callback prozedurak**](/sections/errorhandling/asyncerrorhandling.basque.md) +🔗 [**Informazio gehiago: ekidin callback prozedurak**](./sections/errorhandling/asyncerrorhandling.basque.md)

@@ -130,27 +129,27 @@ Irakurri beste hizkuntza batzuetan: [![CN](/assets/flags/CN.png)**CN**](/README. **Bestela:** osagairen bati deitzean erroreak zein motatakoak diren jakin gabe, askoz zailagoa da eurak kontrolatzea. Are okerrago, erroreak deskribatzeko modu pertsonalizatuak erabiltzeak errore kritikoen informazioa galtzea ekar dezake, pilaren aztarna, besteak beste -🔗 [**Informazio gehiago: erabili soilik “Errorea” objektu kapsulatua**](/sections/errorhandling/useonlythebuiltinerror.basque.md) +🔗 [**Informazio gehiago: erabili soilik “Errorea” objektu kapsulatua**](./sections/errorhandling/useonlythebuiltinerror.basque.md)

## ![✔] 2.3 Bereizi eragiketa erroreak eta programatze erroreak -**TL; DR:** errore operazionalek (adibidez, APIak balio gabeko sarrera jasotzea) agerian jartzen dituzten arazoak ezagunak izaten dira, eta, haien eragina guztiz ulertu eta kontuz kudeatzeko modukoak izaten dira. Bestetik, programatzaileen erroreak (adibidez, zehaztu gabeko aldagaia irakurtzen saiatzea) aplikazioa berrabiarazteko agindua ematen duten kode hutsegite ezezagunak izaten dira +**TL; PL:** eragiketa erroreek (adibidez, APIak balio gabeko sarrera jasotzea) agerian jartzen dituzten arazoak ezagunak izaten dira, eta, haien eragina guztiz ulertu eta kontuz kudeatzeko modukoak izaten dira. Bestetik, programatze erroreak (adibidez, zehaztu gabeko aldagaia irakurtzen saiatzea) aplikazioa berrabiarazteko agindua ematen duten kode hutsegite ezezagunak izaten dira -**Bestela:** eti berrabiaraz dezakezu aplikazioa errore bat agertzen denean. Baina zergatik utzi 5.000 erabiltzaile offline iragarri daitekeen errore funtzional txiki batengatik? Kontrakoa ere ez da egokia: arazo ezezagun bat gertatzen denean -programatzailearen errore bat, esaterako- aplikazioa martxan mantentzeak ezusteko jokaerak eragin ditzake. Biak bereizteak aukera ematen du kontuz jokatzeko eta ikuspegi orekatu bat aplikatzeko testuinguruan oinarrituz +**Bestela:** beti berrabiaraz dezakezu aplikazioa errore bat agertzen denean. Baina zergatik utzi 5.000 erabiltzaile offline iragarri daitekeen errore funtzional txiki batengatik? Kontrakoa ere ez da egokia: arazo ezezagun bat gertatzen denean -programatze errore bat, esaterako- aplikazioa martxan mantentzeak ezusteko jokaerak eragin ditzake. Biak bereizteak aukera ematen du kontuz jokatzeko eta ikuspegi orekatu bat aplikatzeko testuinguruan oinarrituz -🔗 [**Informazio gehiago: eragiketa erroreak vs programazio erroreak**](/sections/errorhandling/operationalvsprogrammererror.basque.md) +🔗 [**Informazio gehiago: eragiketa erroreak vs programatze erroreak**](./sections/errorhandling/operationalvsprogrammererror.basque.md)

## ![✔] 2.4 Kudeatu erroreak gune bakar batean, Express middleware erabili partez -**TL;PL:** erroreak kudeatzeko logika -hala nola, haien erregistroa eramatea eta administratzaileari mezuak bidaltzea- objektu dedikatu zentralizatu batean kapsulatu behar da, erroreren bat gertatzen denean helmuga guztiek (adibidez, Express middleware, cron atazak, atalkako egiaztatzeak) hara deitu dezaten +**TL;PL:** erroreak kudeatzeko logika -hala nola, haien erregistroa eramatea eta administratzaileari mezuak bidaltzea- objektu dedikatu zentralizatu batean kapsulatu behar da, erroreren bat gertatzen denean helmuga guztiek (adibidez, Express middlewarea, cron atazak, atalkako egiaztatzeak) hara deitu dezaten **Bestela:** erroreak toki bakarrean ez kudeatzeak kodea bikoiztea eragiten du eta, ziur aski, erroreak gaizki kudeatzea ere bai -🔗 [**Informazio gehiago: kudeatu erroreak gune bakar batean**](/sections/errorhandling/centralizedhandling.basque.md) +🔗 [**Informazio gehiago: kudeatu erroreak gune bakar batean**](./sections/errorhandling/centralizedhandling.basque.md)

@@ -160,37 +159,37 @@ Irakurri beste hizkuntza batzuetan: [![CN](/assets/flags/CN.png)**CN**](/README. **Bestela:** aplikazio baten bezeroak erabaki dezake aplikazioa itxi eta berrabiaraztea, ulertzen ez duen errore baten abisua jaso duelako soil-soilik. Oharra: zu zeu izan zaitezke zure aplikaziotik deitzen duena (oso ohikoa mikrozerbitzu inguruneetan) -🔗 [**Informazio gehiago: dokumentatu aplikazioaren akatsak Swagger edo GraphQLren laguntzarekin**](/sections/errorhandling/documentingusingswagger.basque.md) +🔗 [**Informazio gehiago: dokumentatu aplikazioaren erroreak Swagger edo GraphQLren laguntzarekin**](./sections/errorhandling/documentingusingswagger.basque.md)

## ![✔] 2.6 Irten prozesutik elegantziarekin kanpoko norbait iristen denean hirira -**TL;PL:** errore ezezagun bat gertatzen denean (programazio errore bat, ikusi 2.3 jardunbide egokia), zalantza izaten da era egokian lanean ote dabilen aplikazioa. Kasu horietan, oso ohikoa izaten da prozesuak kudeatzeko tresna bat erabiltzea [Forever](https://www.npmjs.com/package/forever), [PM2](http://pm2.keymetrics.io/) edo antzekoren bat– prozesua berriro hasteko +**TL;PL:** errore ezezagun bat gertatzen denean (programazio errore bat, ikusi 2.3 praktika ona), zalantza izaten da era egokian lanean ote dabilen aplikazioa. Kasu horietan, oso ohikoa izaten da prozesuak kudeatzeko tresna bat erabiltzea [Forever](https://www.npmjs.com/package/forever), [PM2](http://pm2.keymetrics.io/) edo antzekoren bat– prozesua berriro hasteko **Bestela:** ezagutzen ez duzun zerbait gertatzen denean, izan daiteke objekturen batzuk egoera txarrean daudelako (esaterako, globalki erabiltzen den gertaera igorle bat, barneko erroreren batengatik ondo ez dabilena) eta gerta daiteke aurrerantzean abisuek huts egitea edo modu ero samarrean funtzionatzea -🔗 [**Informazio gehiago: gelditu prozesua**](/sections/errorhandling/shuttingtheprocess.basque.md) +🔗 [**Informazio gehiago: gelditu prozesua**](./sections/errorhandling/shuttingtheprocess.basque.md)

## ![✔] 2.7 Erabili erregistratze tresna helduak erroreen ikusgaitasuna handitzeko -**TL;PL:** erregistratze tresna helduen sortak erabiltzen badituzu –[Pino](https://github.com/pinojs/pino) edo [Log4js](https://www.npmjs.com/package/log4js), adibidez–, erroreak lehenago antzeman eta ulertuko dituzu. Beraz, utzi alde batera console.log +**TL;PL:** erregistratze tresna helduen sortak erabiltzen badituzu –[Pino](https://github.com/pinojs/pino) edo [Log4js](https://www.npmjs.com/package/log4js), adibidez–, erroreak lehenago atzeman eta ulertuko dituzu. Beraz, utzi alde batera console.log **Bestela:** console.log-ak arakatu behar badituzu edo testua desordenatua duen artxibo batean erroreak eskuz, kontsulta tresnarik gabe edo erregistratze bisore ganorazkorik gabe bilatu behar badituzu, ordu asko emango dituzu lanean gaueko ordu txikiak arte -🔗 [**Informazio gehiago: erabili erregistratze tresna helduak**](/sections/errorhandling/usematurelogger.basque.md) +🔗 [**Informazio gehiago: erabili erregistratze tresna helduak**](./sections/errorhandling/usematurelogger.basque.md)

## ![✔] 2.8 Testeatu erroreen fluxua zure test framework gustukoena erabiliz -**TL;PL:** kalitate profesionaleko kontrol tresna automatizatu bat izan zein programatzaileentzako eskuzko test soil bat izan, bermatu zure kodeak ez duela egoera positiboetan bakarrik lan egiten, baizik eta errore zuzenak ere kudeatu eta birbidaltzen dituela. Mocha & Chai bezalako unitate test frameworkek erraz egin dezakete lan hori (ikusi “Gist leiho”ko kode adibideak) +**TL;PL:** kalitate profesionaleko kontrol tresna automatizatu bat izan zein programatzaileentzako eskuzko test soil bat izan, bermatu zure kodeak ez duela egoera positiboetan bakarrik lan egiten, baizik eta errore zuzenak ere kudeatu eta birbidaltzen dituela. Mocha eta Chai bezalako unitate test frameworkek erraz egin dezakete lan hori (ikusi “Gist leiho”ko kode adibideak) -**Bestela:** automatikoki zein eskuz probarik egin gabe ezin duzu konfiantzarik izan zure kodeak benetako erroreak antzemango dituen. Errore adierazgarririk gabe ez dago erroreak kudeatzerik +**Bestela:** automatikoki zein eskuz probarik egin gabe ezin duzu konfiantzarik izan zure kodeak benetako erroreak atzemango dituen. Errore adierazgarririk gabe ez dago erroreak kudeatzerik -🔗 [**Informazio gehiago: testeatu erroreen fluxua**](/sections/errorhandling/testingerrorflows.basque.md) +🔗 [**Informazio gehiago: testeatu erroreen fluxua**](./sections/errorhandling/testingerrorflows.basque.md)

@@ -200,7 +199,7 @@ Irakurri beste hizkuntza batzuetan: [![CN](/assets/flags/CN.png)**CN**](/README. **Bestela:** denbora asko pasa zenezake zure aplikazioaren errendimendua eta jardunik gabeko uneak neurtzen, eta, hala ere, ez zenuke aurkituko zeintzuk diren zure kodearen zatirik motelenak egoera errealetan eta ez zenuke inoiz jakingo nola eragiten dioten erabiltzailearen lanari -🔗 [**Informazio gehiago: APM produktuen erabilera**](/sections/errorhandling/apmproducts.basque.md) +🔗 [**Informazio gehiago: APM produktuen erabilera**](./sections/errorhandling/apmproducts.basque.md)

@@ -210,29 +209,27 @@ Irakurri beste hizkuntza batzuetan: [![CN](/assets/flags/CN.png)**CN**](/README. **Bestela:** zure erroreak xurgatuak izango dira eta ez da haien arrastorik geratuko. Ez duzu zertaz kezkatu -🔗 [**Informazio gehiago: atzeman kudeatu gabeko aginduen arbuioak**](/sections/errorhandling/catchunhandledpromiserejection.basque.md) +🔗 [**Informazio gehiago: atzeman kudeatu gabeko aginduen arbuioak**](./sections/errorhandling/catchunhandledpromiserejection.basque.md)

## ![✔] 2.11 Huts egin azkar, balidatu argudioak liburutegi dedikatu baten laguntzarekin -**TL;PL:** Express erabiltzen duzunean, zure jardunbide egokietako bat izan beharko litzateke aplikazioaren sarbidea kontrolatzea, ustegabeko erroreak ekiditeko, aurrerago erroreak atzematea askoz zailagoa izaten da eta. Balidazio kodea gogaikarria izan ohi da, [ajv](https://www.npmjs.com/package/ajv) eta [Joi](https://www.npmjs.com/package/joi) bezalako laguntza liburutegi moderno bat erabili ezean +**TL;PL:** Express erabiltzen duzunean, zure praktika onetako bat izan beharko litzateke aplikazioaren sarbidea kontrolatzea, ustegabeko erroreak ekiditeko, aurrerago erroreak atzematea askoz zailagoa izaten da eta. Balidazio kodea gogaikarria izan ohi da, [ajv](https://www.npmjs.com/package/ajv) eta [Joi](https://www.npmjs.com/package/joi) bezalako laguntza liburutegi moderno bat erabili ezean **Bestela:** pentsatu zure funtzioa agintza numeriko baten zain dagoela, adibidez «deskontua», eskatzaileak bidaltzea ahaztu duena; geroago, haren kodeak baieztatzen du « deskontua! = 0 (baimendutako deskontua zero baino handiagoa da)», eta horrek ahalmena ematen dio erabiltzaileari deskontua izateko. Ene, nolako errore arriskutsua! Konturatzen zara? -🔗 [**Informazio gehiago: huts egin azkar**](/sections/errorhandling/failfast.basque.md) +🔗 [**Informazio gehiago: huts eragin azkar**](./sections/errorhandling/failfast.basque.md)


-

⬆ Itzuli hasierara

- ## ![✔] 2.12 Agintzen zain egon beti itzuli aurretik, pilak arrastorik uztea saihesteko -**TL; DR:** beti egin `return await` promesa bat itzultzean, pila osoaren jarraipena egin ahal izateko. Funtzio batek promesa bat itzultzen badu, funtzio hori `async`, hau da, asinkronotzat jo behar da, eta esplizituki `await`, itxaron agintza, itzuli aurretik +**TL; PL:** beti egin `return await` promesa bat itzultzean, pila osoaren jarraipena egin ahal izateko. Funtzio batek promesa bat itzultzen badu, funtzio hori `async`, hau da, asinkronotzat jo behar da, eta esplizituki `await`, itxaron agintza, itzuli aurretik **Bestela:** itxaron gabe agintza itzultzen duen funtzioa ez da pilaren arrastoan agertuko. Galdutako fotograma horiek akatsa eragingo duen fluxua ulertzea zailduko lukete, batez ere portaera anormalaren zergatia falta den funtzioaren barruan baldin badago -🔗 [**Gehiago irakurri: agintzak itzultzea**](/sections/errorhandling/returningpromises.basque.md) +🔗 [**Informazio gehiago: agintzak itzultzea**](./sections/errorhandling/returningpromises.basque.md)


@@ -246,23 +243,23 @@ Irakurri beste hizkuntza batzuetan: [![CN](/assets/flags/CN.png)**CN**](/README. **Bestela:** garatzaileek arreta jarriko dute hain gogaikarriak diren arazo batzuk konpontzen –kodearen tarteak eta lerroaren luzera–, eta denbora gehiegi gal dezakete proiektuaren kode estiloa aztertzen -🔗 [**Informazio gehiago: erabili ESLint eta Prettier**](/sections/codestylepractices/eslint_prettier.basque.md) +🔗 [**Informazio gehiago: erabili ESLint eta Prettier**](./sections/codestylepractices/eslint_prettier.basque.md)

-## ![✔] 3.2 Node.jsentzako plugin espezifikoak +## ![✔] 3.2 Node.jsrentzako plugin espezifikoak -**TL;PL:** ESLintek JavaScript vainilla babesteko dituen arau estandarretatik aparte, komeni da Node.jsen osagai espeziko batzuk erabiltzea, hala nola [eslint-plugin-node](https://www.npmjs.com/package/eslint-plugin-node), [eslint-plugin-mocha](https://www.npmjs.com/package/eslint-plugin-mocha) eta [eslint-plugin-node-security](https://www.npmjs.com/package/eslint-plugin-security) +**TL;PL:** ESLintek Vanilla JavaScript babesteko dituen arau estandarretatik aparte, komeni da Node.jsren osagai espeziko batzuk erabiltzea, hala nola [eslint-plugin-node](https://www.npmjs.com/package/eslint-plugin-node), [eslint-plugin-mocha](https://www.npmjs.com/package/eslint-plugin-mocha) eta [eslint-plugin-node-security](https://www.npmjs.com/package/eslint-plugin-security) -**Bestela:** Node.jsen arau akastun batzuek radarraren kontrolari ihes egin ahal diote. Esaterako, garatzaileek sarbide moduan aldagai jakin baten beharra izan dezakete (require(variableCommeChemin)), edozein script JS erabiltzeko aukera ematen diena erasotzaileei. Node.jsen lintersek patroi horiek antzeman ditzakete eta garaiz jo alarma +**Bestela:** Node.jsren arau akastun batzuek radarraren kontrolari ihes egin ahal diote. Esaterako, garatzaileek sarbide moduan aldagai jakin baten beharra izan dezakete (require(variableCommeChemin)), edozein JS script erabiltzeko aukera ematen diena erasotzaileei. Node.jsren linterrek patroi horiek atzeman ditzakete eta garaiz jo alarma

-## ![✔] 3.3 Jarri kode multzo baten giltzak lerro bakar batean +## ![✔] 3.3 Jarri kode multzo baten giltzak lerro bakarrean **TL;PL:** kode bloke baten hasierako parentesiak irekiera instrukzioaren lerroan egon behar du -### Kodearen adibidea +### Kode adibidea ```javascript // Egin @@ -271,12 +268,13 @@ function edozeinFuntzio() { } // Baztertu -function edozeinFuntzio() { +function edozeinFuntzio() +{ // kode blokea } ``` -**Bestela:** jardunbide egoki hau ez erabiltzeak ustekabeko emaitzak eragin ditzake, behean dagoen StackOverflow-en eztabaida harian ikus daitekeen bezala: +**Bestela:** praktika on hau ez erabiltzeak ustekabeko emaitzak eragin ditzake, behean dagoen StackOverflow-en eztabaida harian ikus daitekeen bezala: 🔗 [**Informazio gehiago:** “Zergatik aldatzen dira emaitzak giltzen kokapenaren arabera?” (StackOverflow)](https://stackoverflow.com/questions/3641519/why-does-a-results-vary-based-on-curly-brace-placement) @@ -288,9 +286,9 @@ Ez dio axola instrukzioak bereizteko puntu eta koma erabiltzen duzun edo ez, ohi **TL;PL:** erabili ESLint bereizketetan izaten diren erroreez jabetzeko. [Prettier](https://prettier.io/) edo [Standardjs](https://standardjs.com/) erabiliz automatikoki konpon ditzakezu arazo horiek -**Bestela:** aurreko atalean esan bezala, JavaScripteko interpreteak automatikoki “puntu eta koma” gehitzen du instrukzio baten amaieran “punto eta koma”rik ez badago edo instrukzioa behar den tokian ez dela amaitu eta horrek okerreko emaitzak eragin ditzakeela pentsatzen badu. Ustekabeko errore gehienak ekiditeko, esleipenak erabil ditzakezu eta, horrela, berehala deitutako funtzio adierazpenak erabiltzea saihestuko duzu +**Bestela:** aurreko atalean esan bezala, JavaScripteko interpreteak automatikoki “puntu eta koma” gehitzen du instrukzio baten amaieran “puntu eta koma”rik ez badago edo instrukzioa behar den tokian ez dela amaitu eta horrek okerreko emaitzak eragin ditzakeela pentsatzen badu. Ustekabeko errore gehienak ekiditeko, esleipenak erabil ditzakezu eta, horrela, berehala deitutako funtzio adierazpenak erabiltzea saihestuko duzu -### Kodearen adibidea +### Kode Adibidea ```javascript // Egin @@ -305,7 +303,7 @@ eginZerbait() const items = [1, 2, 3] items.forEach(console.log) -// Baztertu — exception bat jaurtitzen du +// Baztertu — salbuespen bat jaurtitzen du const m = new Map() const a = [1,2,3] [...m.values()].forEach(console.log) @@ -313,7 +311,7 @@ const a = [1,2,3] > ^^^ > SyntaxError: Unexpected token ... -// egin zerbait — exception bat jaurtitzen du +// egin zerbait — salbuespen bat jaurtitzen du const count = 2 // 2() burutzen saiatzen da, baina 2() ez da funtzio bat (function egin zerbait() { // egin zerbait paregabea @@ -322,15 +320,15 @@ const count = 2 // 2() burutzen saiatzen da, baina 2() ez da funtzio bat ``` 🔗 [**Informazio gehiago:** "Semi ESLint araua"](https://eslint.org/docs/rules/semi) -🔗 [**Informazio gehiago:** "stekabeko ESLint arau lerroaniztunik ez"](https://eslint.org/docs/rules/no-unexpected-multiline) +🔗 [**Informazio gehiago:** "Ez dago ustekabeko ESLint arau lerroaniztunik"](https://eslint.org/docs/rules/no-unexpected-multiline)

## ![✔] 3.5 Izendatu funtzio guztiak -**TL;PL:** izendatu funtzio guztiak, itxierak eta deiak. Saihestu funtzio anonimoak. Hau bereziki erabilgarria da nodo aplikazio bat profilatzerakoan. Funtzio guztiak izendatzeak memoria argazkia egiaztatzean aukera emango dizu zer bilatzen ari zaren ulertzen +**TL;PL:** izendatu funtzio guztiak, itxierak eta deiak. Saihestu funtzio anonimoak. Hau bereziki erabilgarria da node aplikazio bat profilatzerakoan. Funtzio guztiak izendatzeak memoria argazkia egiaztatzean aukera emango dizu zer bilatzen ari zaren ulertzen -**Bestela:** zaila izan liteke produkzio arazoak araztea memoria erregistroak erabiliz (memoria argazkia), funtzio anonimoetako memoria kontsumoa handia denean +**Bestela:** zaila izan liteke ekoizpen arazoak araztea memoria erregistroak erabiliz (memoria argazkia), funtzio anonimoetako memoria kontsumoa handia denean

@@ -364,15 +362,15 @@ function eginZerbait() {} **Bestela:** arazketa askoz ere astunagoa da, maiz aldatzen den aldagai baten jarraipena egitean -🔗 [**Gehiago irakurri: JavaScript ES6 +: var, let, edo const?** ](https://medium.com/javascript-scene/javascript-es6-var-let-or-const-ba58b8dcde75) +🔗 [**Informazio gehiago: JavaScript ES6 +: var, let, edo const?** ](https://medium.com/javascript-scene/javascript-es6-var-let-or-const-ba58b8dcde75)

## ![✔] 3.8 Erabili moduluak lehenengo, barne funtzioen partez -**TL;PL:** moduluak fitxategi bakoitzaren hasieran erabili behar dira, edozein funtzioren aurretik eta kanpo. Jardunbide on eta sinple honek lagunduko dizu fitxategiaren menpekotasunak erraz eta azkar antzematen haren eskuineko goi aldean, baita arazo posible batzuk ekiditen ere +**TL;PL:** moduluak fitxategi bakoitzaren hasieran erabili behar dira, edozein funtzioren aurretik eta kanpo. Praktika on eta sinple honek lagunduko dizu fitxategiaren menpekotasunak erraz eta azkar atzematen haren eskuineko goi aldean, baita arazo posible batzuk ekiditen ere -**Bestela:** Node.js.k aldi berean exekutatzen ditu require-ak. Funtzio batek dei egiten badie, egoera kritikoago batean dauden beste eskaera batzuk blokea daitezke. Gainera, deitutako moduluetako batek edo haren menpeko ataza batek errore bat izanez gero, komeni da lehenbailehen haren berri jakitea, eta agian ezingo da hori egin, modulu horri funtzio batek deitzen badio +**Bestela:** Node.jsk aldi berean exekutatzen ditu require-ak. Funtzio batek dei egiten badie, egoera kritikoago batean dauden beste eskaera batzuk blokea daitezke. Gainera, deitutako moduluetako batek edo haren menpeko ataza batek errore bat izanez gero, komeni da lehenbailehen haren berri jakitea, eta agian ezingo da hori egin, modulu horri funtzio batek deitzen badio

@@ -382,7 +380,7 @@ function eginZerbait() {} **Bestela:** fitxategien barne egitura edo sinadura aldatzeak erabiltzaileen interfazea apur dezake -### 3.9 Kodearen adibidea +### 3.9 Kodea adibidea ```javascript // Egin @@ -400,9 +398,9 @@ module.exports.SMSNumberResolver = require("./SMSNumberResolver/SMSNumberResolve **TL;PL:** hobetsi berdintasunaren eragile zorrotza `===` berdintasun abstraktuaren eragile ahulagoa baino `==`. `==` eragileak bi aldagai alderatuko ditu, behin aldagai arrunt bihurtu ondoren. `===` eragileak ez du aldagai motaren bihurketarik egiten, eta bi aldagaiek mota berekoak izan behar dute berdinak izateko -**Bestela:** `==`eragileak, berdinak ez diren aldagaiak alderatuz gero, berdinak direlako mezua helaraz dezake +**Bestela:** `==` eragileak, berdinak ez diren aldagaiak alderatuz gero, berdinak direlako mezua helaraz dezake -### 3.10 Kodearen adibidea +### 3.10 Kode adibidea ```javascript "" == "0"; // false @@ -425,17 +423,17 @@ Aurreko azalpen guztiak faltsuak izango lirateke `===` eragilea erabili izan bal ## ![✔] 3.11 Erabili Async Await, ekidin callbackak -**TL;PL:** Node 8 LTS erabat bateragarria da orain Async-waitekin, eta, horrela kode asinkronikoa kudeatzeko aukera ematen du, callbackik eta agintzarik erabili gabe. Async-waitek ez du blokeorik eragiten, eta kode asinkronikoak sinkroniko bihurtzen ditu. Zure kodeari egin ahal diozun oparirik onena async-wait erabiltzea da, eskaintzen duen kode sintaxia askoz ere trinkoagoa eta ezagunagoa da eta +**TL;PL:** Node 8 LTS erabat bateragarria da orain Async-awaitekin, eta, horrela kode asinkronikoa kudeatzeko aukera ematen du, callbackik eta agintzarik erabili gabe. Async-awaitek ez du blokeorik eragiten, eta kode asinkronikoak sinkroniko bihurtzen ditu. Zure kodeari egin ahal diozun oparirik onena async-await erabiltzea da, eskaintzen duen kode sintaxia askoz ere trinkoagoa eta ezagunagoa da eta **Bestela:** gaizki pasatu eta infernura joateko biderik azkarrena hartu nahi baduzu, erabili callbackak errore asinkronoak kudeatzeko, seguruenik, infernura joateko biderik azkarrena aukeratuko duzu. Estilo honek gune guztietako erroreak egiaztatzera behartzen du, eta, gainera, kode habiaratze beti deserosoaren kudeaketa eta kode fluxua ulertzea zailtzen du -🔗[**Informazio gehiago:** async wait 1.0ren gida](https://github.com/yortus/asyncawait) +🔗[**Informazio gehiago:** async-await 1.0ren gida](https://github.com/yortus/asyncawait)

## ![✔] 3.12 Erabili gezi funtzioak (=>) -**TL;PL:** agintzak eta callbackak onartzen dituzten API zaharrekin async-wait erabiltzea eta funtzio parametroak ekiditea gomendarria bada ere, gezi funtzioek kodearen egitura trinkotu egiten dute eta erro funtzioaren testuinguru lexikoa bermatu (hau da, `this` ) +**TL;PL:** agintzak eta callbackak onartzen dituzten API zaharrekin async-await erabiltzea eta funtzio parametroak ekiditea gomendarria bada ere, gezi funtzioek kodearen egitura trinkotu egiten dute eta erro funtzioaren testuinguru lexikoa bermatu (hau da, `this`) **Bestela:** (ES5 funtzioetan) kode luzeek erroreak izateko joera handiagoa dute, eta, gainera, irakurtzeko astunak dira @@ -449,7 +447,7 @@ Aurreko azalpen guztiak faltsuak izango lirateke `===` eragilea erabili izan bal ## ![✔] 4.1 Idatzi APIaren probak (osagaia), gutxienez -**TL;PL:** proiektu gehienei ez zaie proba automatikorik egiten denbora gutxian egiten direlako edo, maiz, 'proba proiektua' kontroletik kanpo geratu eta bertan behera uzten direlako. Hori dela eta, lehentasuna eman API probei eta hasi beraiek egiten; izan ere, hori da idazteko erarik errazena eta, gainera, proba unitarioek baino estaldura handiagoa eskaintzen dute; are gehiago, API probak sor ditzakezu, [Postman](https://www.getpostman.com/) bezalako tresnak erabiliz. Ondoren, baliabide eta denbora gehiago edukiz gero, jarraitu proba aurreratuak egiten, hala nola proba unitarioak, datu baseen probak, errendimendu probak, etab. +**TL;PL:** proiektu gehienei ez zaie proba automatikorik egiten denbora gutxian egiten direlako edo, maiz, 'proba proiektua' kontroletik kanpo geratu eta bertan behera uzten delako. Hori dela eta, lehentasuna eman API probei eta hasi beraiek egiten; izan ere, hori da idazteko erarik errazena eta, gainera, proba unitarioek baino estaldura handiagoa eskaintzen dute; are gehiago, API probak sor ditzakezu, [Postman](https://www.getpostman.com/) bezalako tresnak erabiliz. Ondoren, baliabide eta denbora gehiago edukiz gero, jarraitu proba aurreratuak egiten, hala nola proba unitarioak, datu baseen probak, errendimendu probak, etab. **Bestela:** luzaroan aritu zintezke proba unitarioak idazten, azkenean soilik %20ko estaldura lortu duzula jakiteko @@ -457,11 +455,11 @@ Aurreko azalpen guztiak faltsuak izango lirateke `===` eragilea erabili izan bal ## ![✔] 4.2 Erabili 3 zati proba izen bakoitzean -**TL;PL:** proba adierazgarria izan behar da eskakizunen mailan, barne kodearekin lan egiten ohituta ez dauden QAko ingeniariek eta garatzaileek berez eta erraz uler dezaten. Probaren izenean adierazi zer ari den probatzen (probatzen ari den unitatea), zer egoeratan eta zer emaitza espero den +**TL;PL:** proba adierazgarria izan behar da eskakizunen mailan, barne kodearekin lan egiten ohituta ez dauden QAko ingeniariek eta garatzaileek berez eta erraz uler dezaten. Probaren izenean adierazi zer ari den probatzen (probapean dagoen unitatea), zer egoeratan eta zer emaitza espero den **Bestela:** inplementazio batek huts egin du, “Gehitu produktua“ izeneko proba batek huts egin du. Esaten dizu horrek zehazki zer dabilen gaizki? -🔗 [**Irakurri gehiago: erabili 3 zati proba izen bakoitzean**](/sections/testingandquality/3-parts-in-name.basque.md) +🔗 [**Informazio gehiago: erabili 3 zati proba izen bakoitzean**](./sections/testingandquality/3-parts-in-name.basque.md)

@@ -471,15 +469,15 @@ Aurreko azalpen guztiak faltsuak izango lirateke `===` eragilea erabili izan bal **Bestela:** kode nagusia ulertzen egunero orduak eta orduak pasatzeaz gainera, orain zure garuna trebatzen pasatzen duzu bestela eguneko zatirik lasaiena izan behar zuena (probak) -🔗 [**Informazio gehiago: egitura probak AAA ereduaren arabera**](/sections/testingandquality/aaa.basque.md) +🔗 [**Informazio gehiago: egitura probak AAA ereduaren arabera**](./sections/testingandquality/aaa.basque.md)

## ![✔] 4.4 Antzeman kodeko arazoak linter bat erabiliz -**TL;PL:** erabili kode linterra oinarrizko kalitatea egiaztatzeko eta antiereduak garaiz antzemateko. Exekutatu edozein proba baino lehen eta gehitu aurre-commit-a git kako moduan, edozein arazo berrikusteko eta zuzentzeko behar den denbora minimizatu ahal izateko. Era berean, egiaztatu [3. atala](#3-code-style-practices), kodearen estilo praktikei dagokienez +**TL;PL:** erabili kode linterra oinarrizko kalitatea egiaztatzeko eta antiereduak garaiz atzemateko. Exekutatu edozein proba baino lehen eta gehitu aurre-commit-a git kako moduan, edozein arazo berrikusteko eta zuzentzeko behar den denbora minimizatu ahal izateko. Era berean, egiaztatu [3. atala](#3-kode-estiloa), kodearen estilo praktikei dagokienez -**Bestela:** kode antiereduren bat zuzendu gabe utz dezakezu, zure produkzio ingurunean ahula izan litekeena +**Bestela:** kode antiereduren bat zuzendu gabe utz dezakezu, zure ekoizpen ingurunean ahula izan litekeena

@@ -489,7 +487,7 @@ Aurreko azalpen guztiak faltsuak izango lirateke `===` eragilea erabili izan bal **Bestela:** probek huts egin dutela eta, inplementazioa bertan behera utzi beharra izan duzula pentsatu. Egoera horretan, lan taldeak denbora asko pasatuko du porrotaren zergatiak aztertzen, azkenean, ondorio tamalgarri honetara iristeko: sistema ondo dabil; probek, ordea, elkarri eragiten diote eta egitura hausten dute -🔗 [**Informazio gehiago: saihestu datu globalak**](/sections/testingandquality/avoid-global-test-fixture.basque.md) +🔗 [**Informazio gehiago: saihestu datu globalak**](./sections/testingandquality/avoid-global-test-fixture.basque.md)

@@ -511,7 +509,7 @@ Aurreko azalpen guztiak faltsuak izango lirateke `===` eragilea erabili izan bal ## ![✔] 4.8 Egiaztatu zure proben estaldura, proba eredu okerrak identifikatzen laguntzen du eta -**TL;PL:** [Istanbul](https://github.com/istanbuljs/istanbuljs)/[NYC](https://github.com/istanbuljs/nyc) bezalako estaldura tresnak oso aproposak dira 3 arrazoirengatik: dohainik dira, hau da, ez da lanik egin behar txostenak lortzeko; proben estaldura gutxitu den identifikatzen laguntzen dute; eta, azkenik, baina ez garrantzi txikiagokoa, proben desdoikuntzak agerian jartzen dituzte. Koloretako kode estalduraren txostenak aztertzean, baliteke harrapaketa kapsula moduan sekula testatzen ez diren kode arloak ikustea, adibidez. Horrek esan nahi du probek bide arrakastatsuak besterik ez dituztela antzematen eta ez aplikazioak nola jokatzen duen erroreak gertatzen direnean. Konfiguratu zure probak estaldura maila batetik behera jaisten denean erroreak eragiteko +**TL;PL:** [Istanbul](https://github.com/istanbuljs/istanbuljs)/[NYC](https://github.com/istanbuljs/nyc) bezalako estaldura tresnak oso aproposak dira 3 arrazoirengatik: dohainik dira, hau da, ez da lanik egin behar txostenak lortzeko; proben estaldura gutxitu den identifikatzen laguntzen dute; eta, azkenik, baina ez garrantzi txikiagokoa, proben desdoikuntzak agerian jartzen dituzte. Koloretako kode estalduraren txostenak aztertzean, baliteke harrapaketa kapsula moduan sekula testatzen ez diren kode arloak ikustea, adibidez. Horrek esan nahi du probek bide arrakastatsuak besterik ez dituztela atzematen eta ez aplikazioak nola jokatzen duen erroreak gertatzen direnean. Konfiguratu zure probak estaldura maila batetik behera jaisten denean erroreak eragiteko **Bestela:** ez da inolako neurgailu automatizaturik egongo zure kodearen zati handi bat proben estalduratik kanpo dagoela esango dizuna @@ -519,7 +517,7 @@ Aurreko azalpen guztiak faltsuak izango lirateke `===` eragilea erabili izan bal ## ![✔] 4.9 Ikuskatu pakete zaharkituak -**TL;PL:** erabili zure tresnarik gogokoena (adibidez, 'npm outdated' edo [npm-check-updates](https://www.npmjs.com/package/npm-check-updates) zaharkituta dauden paketeak antzemateko, ezarri kontrol hau zure IEren bideetan eta, are gehiago, eragin konpilazio batek huts egitea ingurune kritikoetan. Adibidez, agertoki kritikoa izan daiteke instalatutako pakete batek 5 adabaki baieztatuak dituenean (adibidez, bertsio lokala 1.3.1 da eta biltegi bertsioa 1.3.8) edo haren egileak zaharkitu etiketa jarri dionean. Kasu horretan, ezabatu konpilazioa eta ekidin bertsio hori erabiltzea +**TL;PL:** erabili zure tresnarik gogokoena (adibidez, 'npm outdated' edo [npm-check-updates](https://www.npmjs.com/package/npm-check-updates) zaharkituta dauden paketeak atzemateko, ezarri kontrol hau zure IEren bideetan eta, are gehiago, eragin konpilazio batek huts egitea ingurune kritikoetan. Adibidez, agertoki kritikoa izan daiteke instalatutako pakete batek 5 adabaki baieztatuak dituenean (adibidez, bertsio lokala 1.3.1 da eta biltegi bertsioa 1.3.8) edo haren egileak zaharkitu etiketa jarri dionean. Kasu horretan, ezabatu konpilazioa eta ekidin bertsio hori erabiltzea **Bestela:** modu esplizituan arriskutsutzat etiketatuta dauden paketeak egikarituko ditu zure produkzioak @@ -527,7 +525,7 @@ Aurreko azalpen guztiak faltsuak izango lirateke `===` eragilea erabili izan bal ## ![✔] 4.10 Erabili production bezalako inguruneak e2e probetarako -**TL;PL:** zuzeneko datuak erabiltzen dituen hasieratik amaierarainoko proba(e2e) lehen CIren prozesuko katebegirik ahulena izaten zen, datu baseak bezalako zerbitzu astun askoren menpean dago eta. Erabili zure ekoizpen errealetik ahalik eta hurbilen dagoen ingurunea +**TL;PL:** zuzeneko datuak erabiltzen dituen hasieratik amaierarainoko proba (e2e) lehen IEren prozesuko katebegirik ahulena izaten zen, datu baseak bezalako zerbitzu astun askoren menpean dago eta. Erabili zure ekoizpen errealetik ahalik eta hurbilen dagoen ingurunea **Bestela:** docker-compose erabili ezean, taldeek ingurune bakoitzeko proben datu baseak mantendu behar izaten dituzte, garatzaileen makinak barne. Mantendu beti datu base horiek sinkronizatuta, proben emaitzak alda ez daitezen ingurune batetik bestera @@ -535,31 +533,31 @@ Aurreko azalpen guztiak faltsuak izango lirateke `===` eragilea erabili izan bal ## ![✔] 4.11 Eguneratu probak aldizka analisi estatikoko tresnak erabiliz -**TL;PL:** analisi estatikoko tresnak erabiltzeak lagundu egiten dizu kodearen kalitatea hobetzeko modu objektiboak lortzen eta zure kodea jasangarri izaten. Analisirako tresna estatikoak gehitu ahal dizkiozu zure IE konpilazioari, huts egingo duen susmoa duzuenean. Estaldurari dagokionean, bere aldeko puntu nagusiak dira kalitatea ikuskatzeko gaitasuna dutela fitxategi anitzen testuinguruan (adibidez, bikoizketak antzematea), azterketa aurreratuak egitea (adibidez, kodearen konplexutasuna hautematea), eta kode arazoen historiaren eta aurrerapenaren jarraipena egitea. Horretarako, bi tresna hauek erabil ditzakezu: [Sonarqube](https://www.sonarqube.org/) (2.600+ [izar](https://github.com/SonarSource/sonarqube)) eta [Code Climate](https://codeclimate.com/) (1.500+ [izar](https://github.com/codeclimate/codeclimate)) +**TL;PL:** analisi estatikoko tresnak erabiltzeak lagundu egiten dizu kodearen kalitatea hobetzeko modu objektiboak lortzen eta zure kodea jasangarri izaten. Analisirako tresna estatikoak gehitu ahal dizkiozu zure IE konpilazioari, huts egingo duen susmoa duzuenean. Estaldurari dagokionean, bere aldeko puntu nagusiak dira kalitatea ikuskatzeko gaitasuna dutela fitxategi anitzen testuinguruan (adibidez, bikoizketak atzematea), azterketa aurreratuak egitea (adibidez, kodearen konplexutasuna hautematea), eta kode arazoen historiaren eta aurrerapenaren jarraipena egitea. Horretarako, bi tresna hauek erabil ditzakezu: [Sonarqube](https://www.sonarqube.org/) (2.600+ [izar](https://github.com/SonarSource/sonarqube)) eta [Code Climate](https://codeclimate.com/) (1.500+ [izar](https://github.com/codeclimate/codeclimate)) **Bestela:** kodearen kalitatea txarra denean, erroreek eta errendimenduak beti emango dituzte arazoak, azken belaunaldiko ezaugarriak dituen liburutegi berri distiratsu batek ere konpontzerik izango ez dituenak -🔗 [**Informazio gehiago: Berregituratu!**](/sections/testingandquality/refactoring.basque.md) +🔗 [**Informazio gehiago: berregituratu!**](./sections/testingandquality/refactoring.basque.md)

## ![✔] 4.12 Aukeratu arretaz zure IE plataforma (Jenkins vs CircleCI vs Travis vs gainerako mundua) -**TL;PL:** zure integrazio jarraituaren plataformak (CICD) kalitateko tresna guztiak (adib. testak, lintak) ostatatu behar ditu, eta, beraz, indartsua izan beharko du pluginen ekosistema. Aspaldian [Jenkins](https://jenkins.io/) proiektu askoren balio lehenetsia izan ohi zen, komunitaterik handiena eta oso plataforma indartsua baititu, ordainetan konfigurazio konplexu samarra eta ikaste kurba pikoa baditu ere. Gaur egun, askoz errazagoa da IE irtenbide bat sortzea [CircleCI](https://circleci.com) eta haren antzeko SaaS tresnak erabiliz. Tresna horiek IE hodi malgu bat sortzea ahalbidetzen dute azpiegitura osoa kudeatzeko zama hartu beharra izan gabe. Azken batean, sendotasuna eta abiaduraren arteko oreka lortzea da kontua. Egin zure aukera arretaz +**TL;PL:** zure integrazio jarraituaren plataformak (CICD) kalitateko tresna guztiak (adib. testak, lintak) ostatatu behar ditu, eta, beraz, indartsua izan beharko du bere pluginen ekosistemak. Aspaldian [Jenkins](https://jenkins.io/) proiektu askoren balio lehenetsia izan ohi zen, komunitaterik handiena eta oso plataforma indartsua baititu, ordainetan konfigurazio konplexu samarra eta ikaste kurba pikoa baditu ere. Gaur egun, askoz errazagoa da IE irtenbide bat sortzea [CircleCI](https://circleci.com) eta haren antzeko SaaS tresnak erabiliz. Tresna horiek IE hodi malgu bat sortzea ahalbidetzen dute azpiegitura osoa kudeatzeko zama hartu beharra izan gabe. Azken batean, sendotasuna eta abiaduraren arteko oreka lortzea da kontua. Egin zure aukera arretaz **Bestela:** hornitzaile espezializatu bat aukeratzeak blokeatu zaitzake, pertsonalizazio aurreratu bat behar duzunean. Bestalde, Jenkins erabiltzeak denbora asko eska dezake azpiegitura konfiguratzean -🔗 [**Irakurri gehiago: IC plataforma aukeratzea**](/sections/testingandquality/citools.basque.md) +🔗 [**Informazio gehiago: aukeratu IE plataforma**](./sections/testingandquality/citools.basque.md)

## ![✔] 4.13 Probatu zure middlewareak eurak bakarrik -**TL;PL:** middlewareak eskaera askori erantzuten dion logika sendo bat duenean, merezi du middlewarea probatzea bera bakarrik, web esparru osoa aktibatu gabe. Hori erraz lor daiteke {req, res, next} objektuak antzemanez eta behatuz +**TL;PL:** middlewareak eskaera askori erantzuten dion logika sendo bat duenean, merezi du middlewarea probatzea bera bakarrik, web esparru osoa aktibatu gabe. Hori erraz lor daiteke {req, res, next} objektuak atzemanez eta behatuz **Bestela:** middleware Expressean === errorea izanez gero, errorea gertatuko zaizu eskaera guztietan edo gehienetan -🔗 [**Irakurri gehiago: probatu zure middlewareak eurak bakarrik**](/sections/testingandquality/test-middlewares.basque.md) +🔗 [**Informazio gehiago: probatu zure middlewareak eurak bakarrik**](./sections/testingandquality/test-middlewares.basque.md)


@@ -573,7 +571,7 @@ Aurreko azalpen guztiak faltsuak izango lirateke `===` eragilea erabili izan bal **Bestela:** hutsegitea === bezero zapuztuak -🔗 [**Irakurri gehiago: monitorizazioa!**](/sections/production/monitoring.md) +🔗 [**Informazio gehiago: monitorizazioa!**](./sections/production/monitoring.basque.md)

@@ -583,18 +581,18 @@ Aurreko azalpen guztiak faltsuak izango lirateke `===` eragilea erabili izan bal **Bestela:** kutxa beltz batekin amaituko duzu, eta zaila izango zaizu han jasotako ezarpenen zergatia aurkitzea. Azkenean, erregistro adierazpen guztiak idazten hasiko zara informazio osagarria gehitzeko -🔗 [**Gehiago irakurri: gardentasuna handitu erregistratze plataforma adimendunak erabiliz**](/sections/production/smartlogging.md) +🔗 [**Informazio gehiago: gardentasuna handitu erregistratze plataforma adimendunak erabiliz**](./sections/production/smartlogging.basque.md)

-## ![✔] 5.3. Utzi ahal den guztia alderantzizko proxy batean (adibidez, gzip, SSL) +## ![✔] 5.3. Delegatu ahal den guztia alderantzizko proxy batean (adibidez, gzip, SSL) **TL;PL:** Node izugarri txarra da PUZen zeregin intentsiboak egiten, esate baterako, gzipping, SSL termination. Haien partez benetako middleware zerbitzuak erabili behar dituzu –hala nola nginx eta Haproxy– edo hornitzaileen lainoko zerbitzuak **Bestela:** zure hari bakarra lanpetuta egongo da azpiegitura lanak egiten, zure aplikazioaren guneari kasu egin beharrean, eta, ondorioz, haren errendimenduak behera egingo du -🔗 [**Irakurri gehiago: utzi ahal den guztia alderantzizko proxy batean (adibidez, gzip, SSL)**](/sections/production/delegatetoproxy.md) +🔗 [**Informazio gehiago: delegatu ahal den guztia alderantzizko proxy batean (adibidez, gzip, SSL)**](./sections/production/delegatetoproxy.basque.md)

@@ -604,7 +602,7 @@ edo hornitzaileen lainoko zerbitzuak **Bestela:** QAk kodea xeheki probatuko du eta onartuko duen bertsioak desberdin jokatuko du produkzioan. Are okerrago, produkzio talde bereko zerbitzarien kodeak desberdinak izan litezke -🔗 [**Informazio gehiago: blokeatu menpekotasunak**](/sections/production/lockdependencies.md) +🔗 [**Informazio gehiago: blokeatu menpekotasunak**](./sections/production/lockdependencies.basque.md)

@@ -614,7 +612,7 @@ edo hornitzaileen lainoko zerbitzuak **Bestela:** estrategia argirik gabe dozenaka eskaera exekutatzeak DevOpsa nahaste-borrastera eraman dezake, hartarako aldi berean tresna gehiegi (talde kudeaketa, dockerra, PM2) erabiliz gero -🔗 [**Irakurri gehiago: babestu prozesuaren erabilgarritasuna tresna egokiak erabiliz**](/sections/production/guardprocess.md) +🔗 [**Informazio gehiago: babestu prozesuaren erabilgarritasuna tresna egokiak erabiliz**](./sections/production/guardprocess.basque.md)

@@ -624,27 +622,27 @@ edo hornitzaileen lainoko zerbitzuak **Bestela:** seguruenik, zure aplikazioak erabilgarri dituen baliabideen %25a besterik ez du erabiltzen (!), edo gutxiago, agian. Kontuan izan ohiko zerbitzariek gutxienez lau nukleo dituztela PUZen, eta Node.jsren garatzaile soilak bat bakarra erabiltzen duela (AWS beanstalk bezalako PaaS zerbitzuekin lan egiten duenean ere) -🔗 [**Informazio gehiago: erabili PUZeko nukleo guztiak**](/sections/production/utilizecpu.md) +🔗 [**Informazio gehiago: erabili PUZeko nukleo guztiak**](./sections/production/utilizecpu.basque.md)

-## ![✔] 5.7. Sortu ‘bukaerako mantentze puntua‘ +## ![✔] 5.7. Sortu ‘mantentze lanen amaiera puntua‘ **TL;PL:** API seguru batean, jarri agerian sistemarekin lotutako informazio multzo bat, hala nola, memoriaren erabilera eta REPL, etab. Nahiz eta gomendagarria den proba estandarretan eta tresna arruntetan oinarritzea, zenbait informazio eta eragiketa baliotsu errazago egiten dira kodea erabiliz **Bestela:** konturatuko zara “diagnostiko-inplementazio“ asko egiten ari zarela, eta kodea produkziora bidaltzen duzula soilik informazioa lortzeko diagnostikoa egite aldera -🔗 [**Informazio gehiago: sortu ‘bukerako mantentze puntua‘**](/sections/production/createmaintenanceendpoint.md) +🔗 [**Informazio gehiago: sortu ‘mantentze lanen amaiera puntua‘**](./sections/production/createmaintenanceendpoint.basque.md)

-## ![✔] 5.8. Aurkitu akatsak eta geldialdiak APM produktuak erabiliz +## ![✔] 5.8. Aurkitu erroreak eta geldialdiak APM produktuak erabiliz **TL;PL:** aplikazioen jarraipen eta errendimendu produktuek (APM deritzona) modu proaktiboan neurtzen dituzte kode basea eta APIa, modu automatikoan ohiko jarraipenetik haratago joateko eta erabiltzaileen esperientzia arrunta zerbitzu eta maila guztietan neurtzeko. Adibidez, APM produktu batzuek agerian jarri dezakete azken erabiltzaileen aldean motelegi kargatzen dela transakzio bat, sakoneko arrazoia iradokitzen duten bitartean **Bestela:** APIaren errendimendua eta geldialdiak neurtzeko ahalegin handia egin zenezake, eta, ziurrenik, ez zinateke jabetuko zein diren zure kodearen atalik motelenak mundu errealeko eszenatokian eta nola eragiten dioten zure erabiltzaile esperientziari -🔗 [**Irakurri gehiago: aurkitu akatsak eta geldialdiak APM produktuak erabiliz**](/sections/production/apmproducts.md) +🔗 [**Informazio gehiago: aurkitu erroreak eta geldialdiak APM produktuak erabiliz**](./sections/production/apmproducts.basque.md)

@@ -654,17 +652,17 @@ edo hornitzaileen lainoko zerbitzuak **Bestela:** IT / DevOps arloko munduko txapeldun batek ere ez du salbatuko gaizki idatzita dagoen sistema -🔗 [**Irakurri gehiago: prestatu zure kodea ekoizpenerako**](/sections/production/productioncode.md) +🔗 [**Informazio gehiago: prestatu zure kodea ekoizpenerako**](./sections/production/productioncode.basque.md)

## ![✔] 5.10. Neurtu eta babestu memoriaren erabilera -**TL;PL:** Node.jsek harreman gatazkatsuak ditu memoriarekin: v8 motorrak muga leunak dauzka memoria erabiltzean (1,4 GB) eta ezaguna da zein bidetatik galtzen duen Noderen kodeak memoria. Beraz, ezinbestekoa da Noderen prozesu memoriari erreparatzea. Aplikazio txikietan memoria aldizka neur dezakezu geruza komandoak erabiliz; baina aplikazio ertainetan eta handietan aztertu beharko zenuke ez ote zaizun komeni zure memoria erlojua kontrol sistema sendo baten erara erabiltzea +**TL;PL:** Node.jsk harreman gatazkatsuak ditu memoriarekin: v8 motorrak muga leunak dauzka memoria erabiltzean (1,4 GB) eta ezaguna da zein bidetatik galtzen duen Noderen kodeak memoria. Beraz, ezinbestekoa da Noderen prozesu memoriari erreparatzea. Aplikazio txikietan memoria aldizka neur dezakezu geruza komandoak erabiliz; baina aplikazio ertainetan eta handietan aztertu beharko zenuke ez ote zaizun komeni zure memoria erlojua kontrol sistema sendo baten erara erabiltzea **Bestela:** zure memoria prozesuak 100 bat megabyte gal dezake egunean, [Walmart](https://www.joyent.com/blog/walmart-node-js-memory-leak)-i gertatu zitzaion bezala -🔗 [**Irakurri gehiago: neurtu eta babestu memoriaren erabilera**](/sections/production/measurememory.md) +🔗 [**Informazio gehiago: neurtu eta babestu memoriaren erabilera**](./sections/production/measurememory.basque.md)

@@ -674,37 +672,37 @@ edo hornitzaileen lainoko zerbitzuak **Bestela:** Node eduki dinamikoa eskaintzeko sortu zen arren, haren hari bakarra lanpetuta egongo da html / images / angular / react erako ehunka fitxategi bidaltzen, bera egiteko sortua izan zen zereginei esleitu barik bere baliabide guztiak -🔗 [**Irakurri gehiago: atera zure frontend aktiboak Nodetik**](/sections/production/frontendout.md) +🔗 [**Informazio gehiago: atera zure frontend/interfazeko modulu aktiboak Nodetik**](./sections/production/frontendout.basque.md)

-## ![✔] 5.12. Izan stateless, hil zerbitzariak ia egunero +## ![✔] 5.12. Izan aberrigabea, hil zerbitzariak ia egunero -**TL;PL:** gorde edozein datu mota (adibidez, erabiltzaile saioak, cacheak, kargatutako fitxategiak) kanpoko datu biltegietan; eta aztertu ez ote zenituzkeen zure zerbitzari guztiak aldian behin “hil” beharko edo “zerbitzaririk gabe”ko plataformaren bat erabili (adibidez, AWS Lambda), berariaz stateless jokaera duena +**TL;PL:** gorde edozein datu mota (adibidez, erabiltzaile saioak, cacheak, kargatutako fitxategiak) kanpoko datu biltegietan; eta aztertu ez ote zenituzkeen zure zerbitzari guztiak aldian behin “hil” beharko edo “zerbitzaririk gabe”ko plataformaren bat erabili (adibidez, AWS Lambda), berariaz aberrigabe (stateless) jokaera duena **Bestela:** zerbitzari jakin batek huts eginez gero, makina akastun bat hil beharrean, aplikazioen geldialdia eragingo du. Gainera, gero eta zailagoa izango da mailaketaren elastikotasuna, zerbitzari jakin baten menpeko izanda -🔗 [**Irakurri gehiago: izan stateless, hil zerbitzariak ia egunero**](/sections/production/bestateless.md) +🔗 [**Informazio gehiago: izan aberrigabea, hil zerbitzariak ia egunero**](./sections/production/bestateless.basque.md)

-## ![✔] 5.13. Erabili ahuleziak automatikoki antzematen dituzten tresnak +## ![✔] 5.13. Erabili menpekotasunak automatikoki atzematen dituzten tresnak **TL;PL:** menpekotasun ezagunenek ere –Express, adibidez– badituzte (noizean behin) ahulezia ezagunak, sistema arriskuan jar ditzaketenak. Horrek konponbide erraza du, ordea, tresna komunitario eta komertzialak erabiliz gero, ahuleziak etengabe kontrolatu eta haien berri ematen dute eta (bertan edo GitHub-en) **Bestela:** zure kodea ahulezia eta zaurgarritasunetatik garbi mantentzeko tresna dedikaturik gabe, jarraipen estua egin beharko diezu mehatxu berriei buruz linean egiten diren argitalpenei, bide batez esanda, aspergarri samarra izaten dena -🔗 [**Irakurri gehiago: erabili ahuleziak automatikoki antzematen dituzten tresnak**](/sections/production/detectvulnerabilities.md) +🔗 [**Informazio gehiago: erabili menpekotasunak automatikoki atzematen dituzten tresnak**](./sections/production/detectvulnerabilities.basque.md)

-## ![✔] 5.14. Esleitu transakzio identifikazio bat adierazpen-erregistro bakoitzari +## ![✔] 5.14. Esleitu transakzio identifikazio bana adierazpen erregistro bakoitzari **TL;PL:** esleitu identifikatzaile bera –transakzio-: {balioren bat}– erregistro sarrera bakoitzari eskaera bakar baten barruan. Ondoren, erregistroetako erroreak ikuskatzean, erraz konturatuko zara zer gertatu zen aurretik eta ondoren. Zoritxarrez, hori ez da erraz lortzen Noden, haren izaera asinkronoa da eta. Ikusi kodearen adibideak beheko estekan **Bestela:** produkzioko erroreen erregistroa testuingururik gabe ikustean – aurretik gertatu zena, alegia –, askoz zailagoa eta motelagoa da arazoa aztertzea -🔗 [**Irakurri gehiago: esleitu ‘TransactionId’ adierazpen erregistro bakoitzari**](/sections/production/assigntransactionid.md) +🔗 [**Informazio gehiago: esleitu transakzio identifikazio bana adierazpen erregistro bakoitzari**](./sections/production/assigntransactionid.basque.md)

@@ -714,7 +712,7 @@ edo hornitzaileen lainoko zerbitzuak **Bestela:** ezaugarri soil hori gabe errendimendua asko jaits liteke. Adibidez, Express erabiltzean zerbitzarira bideratzeko `NODE_ENV` gabe, errendimendua heren bat moteltzen da -🔗 [**Informazio gehiago: Ezarri NODE_ENV = produkzioa**](/sections/production/setnodeenv.md) +🔗 [**Informazio gehiago: Ezarri NODE_ENV = produkzioa**](./sections/production/setnodeenv.basque.md)

@@ -732,7 +730,7 @@ edo hornitzaileen lainoko zerbitzuak **Bestela:** aurkitu berri diren erroreak edo ahuleziak erabil litezke produkzioan exekutatzen den aplikazio bat ustiatzeko eta baliteke zure aplikazioa ez izatea bateragarria hainbat modulurekin eta zailagoa gertatzea hura mantentzea -🔗 [**Irakurri gehiago: Erabili NTS.jsren LTS bertsioa**](/sections/production/LTSrelease.md) +🔗 [**Informazio gehiago: Erabili NTS.jsren LTS bertsioa**](./sections/production/LTSrelease.basque.md)

@@ -742,7 +740,7 @@ edo hornitzaileen lainoko zerbitzuak **Bestela:** aplikazioen kudeaketaren erregistroak bideratzea === zaila da eskalatzen, erregistroen galera dakar, eskasa izaten da kezken bereizketa -🔗 [**Irakurri gehiago: erregistroen bideraketa**](/sections/production/logrouting.md) +🔗 [**Informazio gehiago: erregistroen bideraketa**](./sections/production/logrouting.basque.md)

@@ -752,7 +750,7 @@ edo hornitzaileen lainoko zerbitzuak **Bestela:** QAk kodea sakonki probatuko du eta produkzioan modu desberdinean jokatuko duen bertsioa onartuko du. Are okerrago, produkzio talde bateko hainbat zerbitzarik kode desberdinak exekuta ditzake -🔗 [**Informazio gehiago: erabili npm ci**](/sections/production/installpackageswithnpmci.md) +🔗 [**Informazio gehiago: erabili npm ci**](./sections/production/installpackageswithnpmci.basque.md)


@@ -768,23 +766,23 @@ edo hornitzaileen lainoko zerbitzuak -**TL;PL:** erabili segurtasunarekin lotutako linter pluginak, [eslint-plugin-security](https://github.com/nodesecurity/eslint-plugin-security) bezalako segurtasun ahuleziak eta arazoak lehenbailehen antzemateko, ahal bada kodetzen ari diren bitartean. Horrek segurtasun ahuleziak atzematen lagun dezake, hala nola eval erabiltzea, bigarren mailako prozesu bat deitzea edo modulu bat inportatzea kate literal batekin (adibidez, erabiltzailearen sarrera). Egin klik 'Gehiago irakurri' atalean segurtasun liner batek antzematen dituen kode adibideak ikusteko +**TL;PL:** erabili segurtasunarekin lotutako linter pluginak, [eslint-plugin-security](https://github.com/nodesecurity/eslint-plugin-security) bezalako segurtasun ahuleziak eta arazoak lehenbailehen atzemateko, ahal bada kodetzen ari diren bitartean. Horrek segurtasun ahuleziak atzematen lagun dezake, hala nola eval erabiltzea, bigarren mailako prozesu bat deitzea edo modulu bat inportatzea kate literal batekin (adibidez, erabiltzailearen sarrera). Egin klik 'Informazio gehiago' atalean segurtasun liner batek atzematen dituen kode adibideak ikusteko **Bestela:** garapenean zehar segurtasun ahulezia zuzena izan zitekeena produkzioaren arazo nagusia bihurtzen da. Gainera, baliteke proiektuak kodeen segurtasun praktika koherenterik ez jarraitzea, ahuleziak sartzea edo urruneko biltegietan sartutako sekretu konfidentzialak sortzea -🔗 [**Gehiago irakurri: lint arauak**](/sections/security/lintrules.md) +🔗 [**Informazio gehiago: lint arauak**](./sections/security/lintrules.basque.md)

-## ![✔] 6.2. Mugatu aldi baterako eskaerak middleware bat erabiliz +## ![✔] 6.2. Mugatu aldi baterako eskaerak middlewareak erabiliz -**TL;PL:** DOS erasoak oso ezagunak dira, eta nahiko erraz eragin daitezke. Ezarri abiadura muga kanpoko zerbitzu bat erabiliz, hala nola hodeiko karga orekatzaileak, hodeiko suebakiak, nginx, [rate-limiter-flexible](https://www.npmjs.com/package/rate-limiter-flexible) edo (aplikazio txikiagoak eta ez hain kritikoetarako) abiadura mugatzeko middleware bat (adibidez, [express-rate-limit](https://www.npmjs.com/package/express-rate-limit), express abiadura mugatzailea) +**TL;PL:** DOS erasoak oso ezagunak dira, eta nahiko erraz eragin daitezke. Ezarri abiadura muga kanpoko zerbitzu bat erabiliz, hala nola hodeiko karga orekatzaileak, hodeiko suebakiak, nginx, [abiadura-mugatzaile-malgua](https://www.npmjs.com/package/rate-limiter-flexible) (rate-limiter-flexible) edo (aplikazio txikiagoak eta ez hain kritikoetarako) abiadura mugatzeko middleware bat (adibidez, [express-rate-limit](https://www.npmjs.com/package/express-rate-limit), express abiadura mugatzailea) **Bestela:** aplikazio batek erasoak jasan ahal ditu, haren erabiltzaileei ukatzen bazaie jaso beharko luketen zerbitzua, aplikazioa egoera txarrean dagoelako edo eskuragarri ez dagoelako -🔗 [**Gehiago irakurri: ezarri abiadura muga**](/sections/security/limitrequests.md) +🔗 [**Informazio gehiago: ezarri abiadura muga**](./sections/security/limitrequests.basque.md)

@@ -796,7 +794,7 @@ edo hornitzaileen lainoko zerbitzuak **Bestela:** iturburu kodearen kontrola publiko egin daiteke akats baten ondorioz, biltegi pribatuetan ere, eta orduan sekretu guztiak agerian geratzen dira. Kanpoko norbaitek iturburuko kontrolaren sarbidea ezagutzeak nahi gabe eragingo du erlazionatutako sistemetarako sarbideak ere ezagutzea (datu baseak, APIak, zerbitzuak, etab.) -🔗 [**Gehiago irakurri: kudeaketa sekretua**](/sections/security/secretmanagement.md) +🔗 [**Informazio gehiago: kudeaketa sekretua**](./sections/security/secretmanagement.basque.md)

@@ -808,15 +806,15 @@ edo hornitzaileen lainoko zerbitzuak **Bestela:** balidatu gabeko edo baimendu gabeko erabiltzaileen sarrerak operadorearen injekzioa ekar dezake NoSQLrako MongoDB-rekin lan egitean, eta saneamendu sistema edo ORM egokia ez erabiltzeak SQL injekzio erasoak ahalbidetuko ditu, ahultasun erraldoia sortuz -🔗 [**Gehiago irakurri: kontsulten injekzioaren prebentzioa ORM / ODM liburutegiak erabiliz**](/sections/security/ormodmusage.md) +🔗 [**Informazio gehiago: kontsulten injekzioaren prebentzioa ORM / ODM liburutegiak erabiliz**](./sections/security/ormodmusage.basque.md)

-## ![✔] 6.5. Segurtasuneko jardunbide egokien bilduma +## ![✔] 6.5. Segurtasuneko praktika onen bilduma -**TL;PL:** Node.jsekin zuzenean loturarik ez duen segurtasuneko aholku bilduma bat da: Noderen inplementazioa ez da hain desberdina beste edozein hizkuntzaren inplementazioaren aldean. Egin klik “irakurri gehiago” botoian sakontzeko +**TL;PL:** Node.jsrekin zuzenean loturarik ez duen segurtasuneko aholku bilduma bat da: Noderen inplementazioa ez da hain desberdina beste edozein hizkuntzaren inplementazioaren aldean. Egin klik “Informazio gehiago” botoian sakontzeko -🔗 [**Gehiago irakurri: segurtasuneko ohiko jardunbide egokienak**](/sections/security/commonsecuritybestpractices.md) +🔗 [**Informazio gehiago: ohiko segurtasun praktika onak**](./sections/security/commonsecuritybestpractices.basque.md)

@@ -828,7 +826,7 @@ edo hornitzaileen lainoko zerbitzuak **Bestela:** erasotzaileek zure aplikazioaren erabiltzaileen aurkako eraso zuzenak egin ditzakete, segurtasun ahultasun handiak sortuz -🔗 [**Gehiago irakurri: erabili izenburu seguruak zure aplikazioan**](/sections/security/secureheaders.md) +🔗 [**Informazio gehiago: erabili izenburu seguruak zure aplikazioan**](./sections/security/secureheaders.basque.md)

@@ -836,11 +834,11 @@ edo hornitzaileen lainoko zerbitzuak -**TL;PL:** npm ekosistemarekin ohikoa da proiektu batek menpekotasun ugari izatea. Menpekotasunak beti kontrolatuta egon behar dira ahultasun berriak aurkitzen diren heinean. Erabili [npm audit](https://docs.npmjs.com/cli/audit) edo [snyk](https://snyk.io/) bezalako tresnak, erasotzen errazak diren menpekotasunen jarraipena egiteko, kontrolatzeko eta adabakiak jartzeko. Tresna horiek zure IE konfigurazioarekin integratu, erasotzen errazak diren menpekotasunenak antzemateko ekoizpenera iritsi aurretik +**TL;PL:** npm ekosistemarekin ohikoa da proiektu batek menpekotasun ugari izatea. Menpekotasunak beti kontrolatuta egon behar dira ahultasun berriak aurkitzen diren heinean. Erabili [npm audit](https://docs.npmjs.com/cli/audit) edo [snyk](https://snyk.io/) bezalako tresnak, erasotzen errazak diren menpekotasunen jarraipena egiteko, kontrolatzeko eta adabakiak jartzeko. Tresna horiek zure IE konfigurazioarekin integratu, erasotzen errazak diren menpekotasunenak atzemateko ekoizpenera iritsi aurretik **Bestela:** erasotzaile batek zure web esparrua detektatu eta ageriko ahultasun guztiei eraso ahal die -🔗 [**Gehiago irakurri: menpekotasunen segurtasuna**](/sections/security/dependencysecurity.md) +🔗 [**Informazio gehiago: menpekotasunen segurtasuna**](./sections/security/dependencysecurity.basque.md)

@@ -848,11 +846,11 @@ edo hornitzaileen lainoko zerbitzuak -**TL;PL:** pasahitzak eta sekretuak (adibidez API gakoak) gorde behar dira hash + gatz funtzio seguru bat erabiliz, esaterako, `bcrypt`edo `scrypt`; eta kasurik okerrenean, `pbkdf2` +**TL;PL:** pasahitzak eta sekretuak (adibidez API giltzak) gorde behar dira hash + gatz funtzio seguru bat erabiliz, esaterako, `bcrypt`edo `scrypt`; eta kasurik okerrenean, `pbkdf2` **Bestela:** funtzio segururik erabili gabe gordetzen diren pasahitzak eta sekretuak bortxaz erasotuak izan daitezke edo hiztegi erasoak jasan ditzakete. Azkenean agerian gera daitezke, bai eta agian zabaldu ere -🔗 [**Gehiago irakurri: erabiltzaileen pasahitzak**](/sections/security/userpasswords.md) +🔗 [**Informazio gehiago: erabiltzaileen pasahitzak**](./sections/security/userpasswords.basque.md)

@@ -864,7 +862,7 @@ edo hornitzaileen lainoko zerbitzuak **Bestela:** erasotzaile batek JavaScript kodeketa kaltegarria gorde dezake zure DBn, gero bezero gizajoei dagoen moduan bidaliko zaiena -🔗 [**Gehiago irakurri: ihes irteera**](/sections/security/escape-output.md) +🔗 [**Informazio gehiago: ihes irteera**](./sections/security/escape-output.basque.md)

@@ -876,7 +874,7 @@ edo hornitzaileen lainoko zerbitzuak **Bestela:** zure eskuzabaltasunak eta ikuspegi permisiboak asko handitzen dute erasoaren tamainua, eta erasotzailea sarrera asko probatzera bultzatzen du, aplikazioa kraskatzeko konbinazio bat aurkitu arte -🔗 [**Gehiago irakurri: balidatu sarrerako JSON eskemak**](/sections/security/validation.md) +🔗 [**Informazio gehiago: balidatu sarrerako JSON eskemak**](./sections/security/validation.basque.md)

@@ -888,7 +886,7 @@ edo hornitzaileen lainoko zerbitzuak **Bestela:** edozeinek erabil litzake iraungitako edo gaizki kokatutako fitxak, maltzurki aplikazio batera sartzeko eta fitxaren jabea ordezkatzeko -🔗 [**Gehiago irakurri: JSON web fitxen zerrenda beltzak**](/sections/security/expirejwt.md) +🔗 [**Informazio gehiago: JSON web fitxen zerrenda beltzak**](./sections/security/expirejwt.basque.md)

@@ -903,11 +901,11 @@ edo hornitzaileen lainoko zerbitzuak **Bestela:** erasotzaile batek pasahitz automatizatuen saiakera mugagabeak egin ditzake aplikazio bateko kontu pribilegiatuetara sartzeko -🔗 [**Gehiago irakurri: saioa hasteko saiakera kopurua mugatzea**](/sections/security/login-rate-limit.md) +🔗 [**Informazio gehiago: mugatu saioa hasteko abiadura**](./sections/security/login-rate-limit.basque.md)

-## ![✔] 6.13. Exekutatu Node.js erro ez den erabiltzaile gisa +## ![✔] 6.13. Exekutatu Node.js erabiltzaile ez-erro gisa @@ -915,11 +913,11 @@ edo hornitzaileen lainoko zerbitzuak **Bestela:** zerbitzarian script bat exekutatzea lortzen duten erasotzaileek botere mugagabea lortzen dute makina lokalaren gainean (adibidez, iptable aldatu eta trafikoa beren zerbitzarira bideratzea) -🔗 [**Gehiago irakurri: exekutatu Node.js erro ez den erabiltzaile gisa**](/sections/security/non-root-user.md) +🔗 [**Informazio gehiago: exekutatu Node.js erabiltzaile ez-erro gisa**](./sections/security/non-root-user.basque.md)

-## ![✔] 6.14. Mugatu kargaren tamaina alderantzizko proxy edo middleware bat erabiliz +## ![✔] 6.14. Mugatu kargaren tamaina alderantzizko proxy edo middlewareak erabiliz @@ -927,7 +925,7 @@ edo hornitzaileen lainoko zerbitzuak **Bestela:** zure aplikazioak eskaera handiei aurre egin beharko die, eta ezingo du prozesatu egin behar duen beste lan garrantzitsua, ondorioz errendimendua gutxituz eta DOS erasoekiko ahulduz -🔗 [**Gehiago irakurri: mugatu kargaren tamaina**](/sections/security/requestpayloadsizelimit.md) +🔗 [**Informazio gehiago: mugatu kargaren tamaina**](./sections/security/requestpayloadsizelimit.basque.md)

@@ -939,19 +937,19 @@ edo hornitzaileen lainoko zerbitzuak **Bestela:** Javascript kode gaiztoak bidea aurkitzen du `eval` testura edo JavaScript hizkuntzak denbora errealean ebaluatzeko dituen funtzioetara sartzeko, eta sarbide osoa lortuko du JavaScripten orrialdeko baimenetara. Ahultasun hori XSS eraso gisa agertzen da askotan -🔗 [**Gehiago irakurri: saihestu JavaScript eval adierazpenak**](/sections/security/avoideval.md) +🔗 [**Informazio gehiago: saihestu JavaScript eval adierazpenak**](./sections/security/avoideval.basque.md)

-## ![✔] 6.16. Saihestu RegEx gaiztoak zure hari bakarreko exekuzioa gainkargatzea +## ![✔] 6.16. Saihestu RegEx gaiztoak zure exekuzio hari bakarra gainkargatzea -**TL;PL:** adierazpen erregularrak, oso erabilgarriak izan arren, benetako mehatxua dira JavaScript aplikazioentzat, oro har, eta Node.js plataformarentzat, bereziki. Erabiltzaile baten sarrera prozesatzeko testuarekin bat etor dadin, gerta liteke PUZeko ziklo kopuru handia behar izatea. RegExen prozesamenduaren eraginkortasuna hain txikia izan daiteke, ezen 10 hitz balioztatzen dituen eskaera bakar batek blokea baitezake gertaeren begizta osoa 6 segundoz, eta PUZa su hartzeko moduan jarri 🔥. Hori dela eta, erasotzen errazak diren ohiko adierazpen ahulen txantiloiak antzemateko erabili hirugarrenen balidazio paketeak -esaterako, [validator.js](https://github.com/chriso/validator.js)-, zuk zeure Regex ereduak idatzi edo [safe-regex](https://github.com/substack/safe-regex) erabili gabe +**TL;PL:** adierazpen erregularrak, oso erabilgarriak izan arren, benetako mehatxua dira JavaScript aplikazioentzat, oro har, eta Node.js plataformarentzat, bereziki. Erabiltzaile baten sarrera prozesatzeko testuarekin bat etor dadin, gerta liteke PUZeko ziklo kopuru handia behar izatea. RegExen prozesamenduaren eraginkortasuna hain txikia izan daiteke, ezen 10 hitz balioztatzen dituen eskaera bakar batek blokea baitezake gertaeren begizta osoa 6 segundoz, eta PUZa su hartzeko moduan jarri 🔥. Hori dela eta, erasotzen errazak diren ohiko adierazpen ahulen txantiloiak atzemateko erabili hirugarrenen balidazio paketeak -esaterako, [validator.js](https://github.com/chriso/validator.js)-, zuk zeure Regex ereduak idatzi edo [safe-regex](https://github.com/substack/safe-regex) erabili gabe **Bestela:** gaizki idatzitako ohiko adierazpenek Regular Expression DoSen erasoak jasan ditzakete, gertaeren begizta erabat blokeatuko dutenak. Adibidez, 2017ko azaroan, RegExen erabilera gaiztoak agerian jarri zuen `moment` pakete ezagunaren ahultasuna -🔗 [**Gehiago irakurri: saihestu RegEx gaiztoa erabiltzea**](/sections/security/regex.md) +🔗 [**Informazio gehiago: saihestu RegEx gaiztoa erabiltzea**](./sections/security/regex.basque.md)

@@ -959,11 +957,11 @@ edo hornitzaileen lainoko zerbitzuak -**TL;PL:** bide bat erabiltzailea sartu ondoren sortua ote den kezka baduzu eta horregatik parametro gisa ezarri baduzu, saihestu bide hori erabiltzea beste fitxategi bat deitzeko / inportatzeko. Arau hori, oro har, edozein fitxategitara sartzeko erabil daiteke (hau da, `fs.readFile()`) edo erabiltzailea sartu ondoren sortutako aldagai dinamikoak dituen beste baliabide konfidentzialetara sartzeko. [Eslint-plugin-security](https://www.npmjs.com/package/eslint-plugin-security) linterrek eredu horiek antzeman eta nahikoa goiz ohartaraz dezake +**TL;PL:** bide bat erabiltzailea sartu ondoren sortua ote den kezka baduzu eta horregatik parametro gisa ezarri baduzu, saihestu bide hori erabiltzea beste fitxategi bat deitzeko / inportatzeko. Arau hori, oro har, edozein fitxategitara sartzeko erabil daiteke (hau da, `fs.readFile()`) edo erabiltzailea sartu ondoren sortutako aldagai dinamikoak dituen beste baliabide konfidentzialetara sartzeko. [Eslint-plugin-security](https://www.npmjs.com/package/eslint-plugin-security) linterrek eredu horiek atzeman eta nahikoa goiz ohartaraz dezake **Bestela:** erabiltzaile gaiztoen sarrerak manipulatutako fitxategiak deitzeko erabiltzen den parametro batera jo dezake, adibidez, aurretik fitxategi sisteman kargatutako fitxategietara edo lehendik sisteman bazeuden fitxategietara sartzeko -🔗 [**Gehiago irakurri: moduluaren karga segurua**](/sections/security/safemoduleloading.md) +🔗 [**Informazio gehiago: moduluaren karga segurua**](./sections/security/safemoduleloading.basque.md)

@@ -975,7 +973,7 @@ edo hornitzaileen lainoko zerbitzuak **Bestela:** plugin batek bide ugari erabil ditzake erasotzeko, hala nola begizta infinituak erabiliz, memoria gainkargatuz eta prozesu ingurune eraso errazen aldagaiak eskuratuz -🔗 [**Gehiago irakurri: exekutatu kode ez segurua sandbox batean**](/sections/security/sandbox.md) +🔗 [**Informazio gehiago: exekutatu kode ez segurua sandbox batean**](./sections/security/sandbox.basque.md)

@@ -987,19 +985,19 @@ edo hornitzaileen lainoko zerbitzuak **Bestela:** bigarren mailako prozesuak ganorarik gabe erabiltzeak urruneko komandoen exekuzioa edo shell injekzioko erasoak eragin ditzake, desinfektatu gabeko sistema komando batera erabiltzaile gaiztoren bat sartu dela eta -🔗 [**Gehiago irakurri: kontuz ibili bigarren mailako prozesuekin lan egitean**](/sections/security/childprocesses.md) +🔗 [**Informazio gehiago: kontuz ibili bigarren mailako prozesuekin lan egitean**](./sections/security/childprocesses.basque.md)

-## ![✔] 6.20. Ezkutatu bezeroen erroreen xehetasunak +## ![✔] 6.20. Ezkutatu bezeroari erroreen xehetasunak -**TL;PL:** errore integratuen kudeatzaile lasterrek lehenespenez ezkutatzen dituzte erroreen xehetasunak. Haatik, aukera handia dago inplementa dezan errore pertsonalizatuak dituzten objektuak kudeatzeko berak daukan logika (batzuen ustez jardunbide egokia dena). Hala eginez gero, ziurtatu bezeroari errorearen objektu osoa ez itzultzea, horrek aplikazioen datu sentikorrak izan litzake eta +**TL;PL:** errore integratuen kudeatzaile lasterrek lehenespenez ezkutatzen dituzte erroreen xehetasunak. Haatik, aukera handia dago inplementa dezan errore pertsonalizatuak dituzten objektuak kudeatzeko berak daukan logika (batzuen ustez praktika ona dena). Hala eginez gero, ziurtatu bezeroari errorearen objektu osoa ez itzultzea, horrek aplikazioen datu sentikorrak izan litzake eta **Bestela:** aplikazioaren xehetasun sentikorrak —hala nola, zerbitzariko fitxategien bideak, erabiltzen ari diren hirugarrenen moduluak eta erasotzaile batek balia ditzakeen aplikazioaren barneko beste lan fluxuak— atera daitezke pila aztarna batean aurkitutako informazioetatik -🔗 [**Gehiago irakurri: ezkutatu bezeroaren erroreen xehetasunak**](/sections/security/hideerrors.md) +🔗 [**Informazio gehiago: ezkutatu bezeroari erroreen xehetasunak**](./sections/security/hideerrors.basque.md)

@@ -1021,15 +1019,15 @@ edo hornitzaileen lainoko zerbitzuak **Bestela:** cookieak segurtasunik gabeko konexioen bidez bidal litezke, eta erasotzaile batek saioaren identifikazioa erabil lezake web aplikazioaren barruko esparrua eta moduluen berariazko ahultasunak ere identifikatzeko -🔗 [**Gehiago irakurri: cookieak eta saioaren segurtasuna**](/sections/security/sessions.md) +🔗 [**Informazio gehiago: cookieak eta saioaren segurtasuna**](./sections/security/sessions.basque.md)

-## ![✔] 6.23. Saihestu DOS erasoak prozesu batek noiz huts egin behar duen berariaz ezarriz +## ![✔] 6.23. Saihestu DOS erasoak prozesuak noiz huts egin behar duen berariaz ezarriz -**TL;PL:** Node prozesuak huts egingo du akatsak kudeatzen ez direnean. Jardunbide egokienetako askok irtetea gomendatzen dute, akats bat atzeman eta kudeatuta badago ere. Expressek, adibidez, huts egiten du errore asinkronoren bat izanez gero –blokeatze klausula batekin ibilbideak biltzen ez badituzu behintzat. Horrek oso eraso bide aproposa irekitzen die erasotzaileei, zer informaziok eragiten duen prozesuaren blokeoa jakinda, behin eta berriz eskaera bera bidaltzen baitute prozesua blokeatzea lortu arte. Horretarako ez dago berehalako erremediorik, baina teknika batzuek mina arindu dezakete: abisatu zorroztasun kritikoarekin, kontrolatu gabeko errore baten ondorioz prozesuak huts egiten duen bakoitzean, balioztatu sarrera eta saihestu prozesua blokeatuta gelditzea erabiltzailearen sarrera baliogabea delako, bildu ibilbide guztiak cacth batekin eta kontuan hartu prozesuak ez duela huts egin behar eskaera batean errore bat sortzen denean (oro har, gertatzen denaren kontra) +**TL;PL:** Node prozesuak huts egingo du akatsak kudeatzen ez direnean. Praktika onetako askok irtetea gomendatzen dute, akats bat atzeman eta kudeatuta badago ere. Expressek, adibidez, huts egiten du errore asinkronoren bat izanez gero –blokeatze klausula batekin ibilbideak biltzen ez badituzu behintzat. Horrek oso eraso bide aproposa irekitzen die erasotzaileei, zer informaziok eragiten duen prozesuaren blokeoa jakinda, behin eta berriz eskaera bera bidaltzen baitute prozesua blokeatzea lortu arte. Horretarako ez dago berehalako erremediorik, baina teknika batzuek mina arindu dezakete: abisatu zorroztasun kritikoarekin, kontrolatu gabeko errore baten ondorioz prozesuak huts egiten duen bakoitzean, balioztatu sarrera eta saihestu prozesua blokeatuta gelditzea erabiltzailearen sarrera baliogabea delako, bildu ibilbide guztiak cacth batekin eta kontuan hartu prozesuak ez duela huts egin behar eskaera batean errore bat sortzen denean (oro har, gertatzen denaren kontra) **Bestela:** hau uste oneko suposizio soil bat besterik ez da. Node.js aplikazio asko edukiz gero, JSON gorputz huts bat POST eskaera guztietara pasatzen saiatzen bagara, zenbait aplikazio blokeatu egingo dira. Une horretan, eskaera bera berbidal dezakegu, aplikazioak erraz ezabatzeko @@ -1043,7 +1041,7 @@ edo hornitzaileen lainoko zerbitzuak **Bestela:** erasotzailea ohartzen bada erabiltzaileek emandako kanpo sarrerarik ez dela balioztatzen, ahultasun hori balia dezake foroetan, sare sozialetan eta beste toki publiko batzuetan hartarako bereziki sortutako estekak argitaratzean, erabiltzaileek bertan klik egin dezaten -🔗 [**Gehiago irakurri: saihestu birbideratze ez seguruak**](/sections/security/saferedirects.md) +🔗 [**Informazio gehiago: saihestu birbideratze ez seguruak**](./sections/security/saferedirects.basque.md)

@@ -1053,9 +1051,9 @@ edo hornitzaileen lainoko zerbitzuak **TL;PL:** neurriak hartu behar dira npm erregistro publikoetan sekretuak nahi gabe argitaratzeko arriskua ekiditeko. Erabil daiteke `.npmignore` fitxategi bat karpeta edo fitxategi espezikoak zerrenda beltz batean jartzeko eta `files` matrizea `package.json` artxiboarekin erabil daiteke zerrenda zuri moduan lan egin dezan -**Bestela:** arriskua dago norbaitek zure proiektuaren API gakoak, pasahitzak edo beste sekretu batzuk aurkitu eta erasoak egiten saiatzeko, eta horrek galera ekonomikoak, nortasun arazoak eta bestelako arriskuak sor ditzake +**Bestela:** arriskua dago norbaitek zure proiektuaren API giltzak, pasahitzak edo beste sekretu batzuk aurkitu eta erasoak egiten saiatzeko, eta horrek galera ekonomikoak, nortasun arazoak eta bestelako arriskuak sor ditzake -🔗 [**Gehiago irakurri: saihestu sekretuak argitaratzea**](/sections/security/avoid_publishing_secrets.md) +🔗 [**Informazio gehiago: saihestu sekretuak argitaratzea**](./sections/security/avoid_publishing_secrets.basque.md)


⬆ Itzuli hasierara

@@ -1066,41 +1064,41 @@ edo hornitzaileen lainoko zerbitzuak

-## ![✔] 7.1. Ez blokeatu gertaeraren begizta +## ![✔] 7.1. Ez blokeatu gertaeren begizta -**TL;PL:** saihestu PUZen zeregin intentsiboak, gertaeraren begizta blokeatuko baitute. Izan ere, gertaera horietako gehienak azpiprozesu bakarrekoak dira, eta deskargatuak izango baitira azpiprozesu dedikatu batean, prozesu batean edo teknologia desberdinetan, dauden testuinguruaren arabera +**TL;PL:** saihestu PUZen zeregin intentsiboak, gertaeren begizta blokeatuko baitute. Izan ere, gertaera horietako gehienak azpiprozesu bakarrekoak dira, eta deskargatuak izango baitira azpiprozesu dedikatu batean, prozesu batean edo teknologia desberdinetan, dauden testuinguruaren arabera -**Bestela:** gertaeraren begizta blokeatuta dagoenez, Node.jsk ezin izango du beste eskaera bat kudeatu eta, ondorioz, atzerapena eragin diezaieke erabiltzaileei. **3000 erabiltzaile erantzunaren zain daude, edukia zerbitzatzeko prest dago, baina eskaera bakar batek emaitzak berriro bidaltzea galarazten dio zerbitzariari** +**Bestela:** gertaeren begizta blokeatuta dagoenez, Node.jsk ezin izango du beste eskaera bat kudeatu eta, ondorioz, atzerapena eragin diezaieke erabiltzaileei. **3000 erabiltzaile erantzunaren zain daude, edukia zerbitzatzeko prest dago, baina eskaera bakar batek emaitzak berriro bidaltzea galarazten dio zerbitzariari** -🔗 [**Gehiago irakurri: ez blokeatu gertaeraren begizta**](/sections/performance/block-loop.md) +🔗 [**Informazio gehiago: ez blokeatu gertaeraren begizta**](./sections/performance/block-loop.basque.md)


-## ![✔] 7.2. Hobetsi jatorrizko JS metodoak Lodash bezalako erabiltzailearen baliabideak baino +## ![✔] 7.2. Hobetsi jatorrizko JS metodoak Lodash bezalako erabiltzaileen baliabideak baino **TL;PL:** askotan zorrotzagoa da `lodash` eta `underscore` bezalako baliabide liburutegiak erabiltzea jatorrizko metodoak baino, beharrezkoak ez diren menpekotasunak eragin eta abiadura moteltzen baitu. Gogoan izan, V8 motor berria ES estandar berriekin batera, bertako metodoak hobetu egin zirela, eta gaur egun baliabide liburutegiak % 50 inguru eraginkorragoak direla liburutegi publikoak baino **Bestela:** errendimendu txikiagoko proiektuak mantendu beharko zenituzke, non **dagoeneko** eskura zenuena erabili beharko baitzenuke edo, fitxategi batzu gehiagoren truke, beste zenbait lerro landu -🔗 [**Gehiago irakurri: erabiltzaileen jatorrizko baliabideak**](/sections/performance/nativeoverutil.md) +🔗 [**Informazio gehiago: erabiltzaileen jatorrizko baliabideak**](./sections/performance/nativeoverutil.basque.md)


⬆ Itzuli hasierara

-# `8. Docker` +# `8. Docker, praktika onak` 🏅 Mila esker [Bret Fisher](https://github.com/BretFisher)-i, ondorengo praktika hauetako asko ikasi baikenituen berarengandik

-## ![✔] 8.1 Erabili etapa anitzeko konpilazioak Docker irudi finagoak eta seguruagoak lortzeko +## ![✔] 8.1 Erabili etapa anitzeko konpilazioak Docker irudi sinpleagoak eta seguruagoak lortzeko **TL;PL:** erabili etapa anitzeko konpilazioak beharrezko produkzio objektuak soilik kopiatzeko. Konpilazio menpekotasun eta fitxategi asko ez dira beharrezkoak zure aplikazioa exekutatzeko. Etapa anitzeko konpilazioak erabiliz gero, baliabide horiek konpilazioan zehar erabil daitezke, denboraren exekuzio inguruneak beharrezko baliabideak besterik ez duen bitartean. Etapa anitzeko konpilazioak oso modu erraza dira gehiegizko pisua kendu eta segurtasun mehatxuak saihesteko **Bestela:** irudi handiagoek denbora gehiago beharko dute konpilatzeko eta zabaltzeko. Eraikitzeko soilik diren tresnek ahultasunak eduki ditzakete eta eraikitze faserako soilik gordetako sekretuak filtratu daitezke -### Etapa anitzeko eraikuntzetarako Dockerfile adibidea +### Etapa anitzeko eraikuntzetarako Dockerfile fitxategiaren adibidea ```dockerfile FROM node:14.4.0 AS build @@ -1108,6 +1106,7 @@ FROM node:14.4.0 AS build COPY . . RUN npm ci && npm run build + FROM node:slim-14.4.0 USER node @@ -1119,29 +1118,27 @@ RUN npm ci --production CMD [ "node", "dist/app.js" ] ``` -🔗 [**Gehiago irakurri: erabili etapa anitzeko konpilazioak**](/sections/docker/multi_stage_builds.md) +🔗 [**Informazio gehiago: erabili etapa anitzeko konpilazioak**](./sections/docker/multi_stage_builds.basque.md)


-# Edukiontzia autoabiatu node komandoa erabiliz, npm beharrean - -## ![✔] 8.2. Edukiontzia abiarazi 'node' komandoa erabiliz, saihestu npm hastea +## ![✔] 8.2. Abiarazi edukiontzia node komandoa erabiliz, saihestu npm **TL;PL:** erabili `CMD ['node','server.js']` aplikazioa abiarazteko, saihestu OS seinaleak kodera pasatzen ez dituzten npm scriptak erabiltzea. Horrek arazoak izatea ekiditen du bigarren mailako prozesuetan, seinaleak kudeatzean, itxiera seguruetan eta prozesu zonbietan **Bestela:** seinalerik pasatzen ez denean, zure kodeak ez du inoiz izango itzalaldien berri, eta, hori gabe, ez da behar bezala itxiko, unean uneko eskaerak eta / edo datuak galduz -[**Gehiago irakurri: Edukiontzia abiarazi 'node' komandoa erabiliz, sahiestu npm hastea**](/sections/docker/bootstrap-using-node.md) +[**Informazio gehiago: abiarazi edukiontzia 'node' komandoa erabiliz, saihestu npm abiatzea**](./sections/docker/bootstrap-using-node.basque.md)


-## ![✔] 8.3. Utzi Dockerren exekuzio denborak kudea ditzala erreplikazioa eta aktibitatea +## ![✔] 8.3. Utzi Dockeren egikaritze denborari erreplikatu eta jardueraren iraupena kudeatzen **TL;PL:** Dockerren exekuzio denboraren orkestratzailea erabiltzen duzunean (adibidez, Kubernetes), deitu Node.js prozesua zuzenean, prozesua errepikatzen duten bitarteko prozesuen kudeatzailerik edo koderik pertsonalizatu gabe (adibidez, PM2, Cluster modulua). Exekuzio denboraren plataformak datu kopuru eta ikusgarritasun handiena dauzka kokapenari buruzko erabakiak hartzeko: badaki zenbat prozesu behar diren, nola antolatu prozesuok eta zer egin huts eginez gero **Bestela:** edukiontziak huts egiten jarraituko du baliabide faltagatik, eta prozesuen kudeatzaileak behin eta berriro berrabiaraziko du, gelditu gabe. Kubernetes horretaz jabetuko balitz, beste toki zabal batera lekualda lezake -🔗 [**Gehiago irakurri: utzi Dockerren orkestratzaileari prozesuak berrabiaraz eta erreplika ditzala**](/sections/docker/restart-and-replicate-processes.md) +🔗 [**Informazio gehiago: utzi Dockeren exekuzio denborari erreplikatu eta jardueraren iraupena kudeatzen**](./sections/docker/restart-and-replicate-processes.basque.md)


@@ -1151,7 +1148,7 @@ CMD [ "node", "dist/app.js" ] **Bestela**: irudira sarbidea duen edonorekin partekatuko dira `.env`, `.aws` eta `.npmrc` bezalako fitxategi sekretu pertsonal arruntak (adibidez, Docker biltegia) -🔗 [**Gehiago irakurri: erabili .dockerignore**](/sections/docker/docker-ignore.md) +🔗 [**Informazio gehiago: erabili .dockerignore**](./sections/docker/docker-ignore.basque.md)


@@ -1161,7 +1158,7 @@ CMD [ "node", "dist/app.js" ] **Bestela:** npm segurtasun arau hauste ezagun asko garapen paketeen barruan aurkitu izan dira (adibidez, [eslint-scope](https://eslint.org/blog/2018/07/postmortem-for-malicious-package-publishes)) -🔗 Gehiago irakurri: [kendu garapen menpekotasunak](/sections/docker/install-for-production.md) +🔗 Informazio gehiago: [ezabatu garapen menpekotasunak](./sections/docker/install-for-production.basque.md)


@@ -1171,7 +1168,7 @@ CMD [ "node", "dist/app.js" ] **Bestela:** berehala hiltzeak etsita dauden milaka erabiltzaileri ez erantzutea ekarriko du -🔗 [**Gehiago irakurri: itzalaldi dotorea**](/sections/docker/graceful-shutdown.md) +🔗 [**Informazio gehiago: itzalaldi dotorea**](./sections/docker/graceful-shutdown.basque.md)


@@ -1181,23 +1178,21 @@ CMD [ "node", "dist/app.js" ] **Bestela:** Dockerren definizioa beharrezkoa da eskalatutako erabakiak burutzeko eta beste herritarrak gosez hiltzea ekiditeko. V8rren mugak zehaztu gabe ere, edukiontziaren baliabideak erabiliko ditu. Argibide espliziturik gabe, baliabideen %50-60a erabiltzean huts egiten du -🔗 [**Gehiago irakurri: ezarri memoria mugak Docker erabiliz soilik**](/sections/docker/memory-limit.md) +🔗 [**Informazio gehiago: ezarri memoria mugak Docker erabiliz soilik**](./sections/docker/memory-limit.basque.md)


-## ![✔] 8.8. Planifikatu cachean biltegiratzea modu eraginkorrean +## ![✔] 8.8. Baliatu cachea konpilazio denbora murrizteko **TL;PL:** Dockerren irudi osoa cache-tik berreraikitzea ia berehalakoa izan daiteke, zuzen eginez gero. Eguneratu ez diren argibideek Dockerfile fitxategiaren goialdean egon behar dute, eta etengabe aldatzen ari direnek (aplikazioaren kodea, esate baterako) beheko aldean egon behar dute **Bestela:** Docker eraikitzeak oso luze jo dezake eta baliabide asko kontsumituko ditu, nahiz eta aldaketa txikiak egin -🔗 [**Gehiago irakurri: baliatu cachea eraikitze denborak murrizteko**](/sections/docker/use-cache-for-shorter-build-time.md) +🔗 [**Informazio gehiago: baliatu cachea konpilazio denborak murrizteko**](./sections/docker/use-cache-for-shorter-build-time.basque.md)


-## ![✔] 8.9. Erabili irudiaren erreferentzia esplizitua, saihestu azken (`latest`) - -etiketa +## ![✔] 8.9. Erabili irudiaren erreferentzia esplizitua, saihestu "azken" (`latest`) etiketa **TL;PL:** zehaztu irudi laburpen esplizitu bat edo etiketa baten bertsioa, inoiz ez aipatu `latest`. Garatzaileek sarritan uste izaten dute, `latest` adieraziz gero, biltegiko azken irudia eskuratuko dutela, baina ez da horrela. Laburpena erabiltzeak zerbitzuaren instantzia guztiek kode bera exekutatuko dutela bermatzen du @@ -1205,7 +1200,7 @@ Gainera, irudi etiketa bat aipatzen bada, oinarrizko irudia aldatu egin daiteke, **Bestela:** oinarrizko irudi baten bertsio berri bat erabiliz gero, aldaketa handiak gerta litezke produkzioan, horrek aplikazioaren nahigabeko portaera sortuz -🔗 [**Gehiago irakurri: ulertu irudi etiketak eta erabili "latest" etiketa kontu handiz**](/sections/docker/image-tags.md) +🔗 [**Informazio gehiago: ulertu irudi etiketak eta erabili "azken" (`latest`) etiketa kontu handiz**](./sections/docker/image-tags.basque.md)


@@ -1215,27 +1210,27 @@ Gainera, irudi etiketa bat aipatzen bada, oinarrizko irudia aldatu egin daiteke, **Bestela:** batetik, denbora gehiago beharko da irudiak eraiki, txertatu eta ateratzeko; bestetik, erabiltzaile maltzurrek eraso bektore ezezagunak erabil ditzakete; eta, azkenik, baliabide gehiago beharko dira -🔗 [**Gehiago irakurri: hobetsi irudi txikiagoa**](/sections/docker/smaller_base_images.md) +🔗 [**Informazio gehiago: hobetsi irudi txikiagoak**](./sections/docker/smaller_base_images.basque.md)


## ![✔] 8.11. Garbitu eraikitze faseko sekretuak, saihestu sekretuak argudioetan -**TL;PL:** saihestu Dockerren konpilazio inguruneko sekretuak agerian geratzea. Docker irudi bat IE bezalako ingurune anitzetan eta ekoizpena bezain garbituta ez dauden erregistroetan partekatzen da normalean. Adibide tipikoa npm token da, normalean dockerfile batera pasatzen dena argumentu gisa. Token hori irudiaren barruan geratzen da denbora luzez beharrezkoa izateari utzi ondoren ere, eta erasotzaileari npm erregistro pribatura sartzeko aukera ematen dio. Hori ekidin daiteke sekretua `.npmrc` bezalako fitxategi batean kopiatuz, eta, ondoren, sekretu hori kenduz etapa anitzeko eraikuntza bat erabiliz (kontuz, eraikitze historia ere ezabatu beharko litzateke) edo bat ere aztarnarik uzten dituen Docker build-kit funtzio sekretua erabiliz +**TL;PL:** saihestu Dockerren konpilazio inguruneko sekretuak agerian geratzea. Docker irudi bat IE bezalako ingurune anitzetan eta ekoizpena bezain garbituta ez dauden erregistroetan partekatzen da normalean. Adibide tipikoa npm giltza (tokena) da, normalean dockerfile fitxategi batera pasatzen dena argumentu gisa. Giltza hori irudiaren barruan geratzen da denbora luzez beharrezkoa izateari utzi ondoren ere, eta erasotzaileari npm erregistro pribatura sartzeko aukera ematen dio. Hori ekidin daiteke sekretua `.npmrc` bezalako fitxategi batean kopiatuz, eta, ondoren, sekretu hori kenduz etapa anitzeko eraikuntza bat erabiliz (kontuz, eraikitze historia ere ezabatu beharko litzateke) edo bat ere aztarnarik uzten dituen Docker build-kit funtzio sekretua erabiliz **Bestela:** IE eta docker erregistroan sartzeko aukera duten guztiek erakundearen sekretu preziatuak ere eskuratzeko aukera izango dute onura gehigarri gisa -🔗 [**Gehiago irakurri: garbitu eraikitze faseko sekretuak**](/sections/docker/avoid-build-time-secrets.md) +🔗 [**Informazio gehiago: garbitu eraikitze faseko sekretuak**](./sections/docker/avoid-build-time-secrets.basque.md)


-## ![✔] 8.12. Eskaneatu irudiak ahultasun geruzen bila +## ![✔] 8.12. Eskaneatu ahultasun geruza anitzeko irudiak **TL;PL:** kode menpekotasunen ahultasunak egiaztatzeaz gain, eskaneatu ekoizpenera bidalitako azken irudia ere. Dockerren irudien eskanerrek kodeen menpekotasunak egiaztatzen dituzte, baina baita sistema eragilearen binarioak ere. E2E segurtasun eskaneatze horrek eremu handiago bat hartzen du eta egiaztatzen du inongo erabiltzaile maltzurrak ez duela maltzurkeriatik egin eraikitze aldian zerbait injektatuz. Ondorioz, hau exekutatzea gomendatzen da hedapenaren aurreko azken urrats gisa. Mordoska bat eskaner doako eta komertzial dago CI / CD pluginak ere eskaintzen dituztenak **Bestela:** baliteke zure kodeak ahultasunik ez izatea. Hala ere, baliteke oraindik ere hackeatua izatea, aplikazioek normalean erabiltzen dituzten sistema eragilearen mailako binarioen bertsioak ahultasunak dituelako (adibidez, OpenSSL, TarBall) -🔗 [**Gehiago irakurri: Dockerren praktika arruntak**](/sections/docker/scan-images.md) +🔗 [**Informazio gehiago: Docker praktika arruntak**](./sections/docker/scan-images.basque.md)


@@ -1245,25 +1240,25 @@ Gainera, irudi etiketa bat aipatzen bada, oinarrizko irudia aldatu egin daiteke, **Bestela:** ekoizpenera bidaliko den irudiak % 30 gehiago pisatuko du, inoiz erabiliko ez diren fitxategiak direla eta -🔗 [**Gehiago irakurri: garbitu NODE_MODULE cachea**](/sections/docker/clean-cache.md) +🔗 [**Informazio gehiago: garbitu NODE_MODULE cachea**](./sections/docker/clean-cache.basque.md)


-## ![✔] 8.14. Dockeren praktika arruntak +## ![✔] 8.14. Dockeren praktika generikoak -**TL;PL:** hemen duzu Node.jsekin zuzenean loturarik ez duen Docker aholkuen bilduma. Ez dago alderik Noderen eta beste edozein lengoaiaren inplementazioen artean. Egin klik “irakurri gehiago” botoian +**TL;PL:** hemen duzu Node.jsrekin zuzenean loturarik ez duen Docker aholkuen bilduma. Ez dago alderik Noderen eta beste edozein lengoaiaren inplementazioen artean. Egin klik “Informazio gehiago” botoian -🔗 [**Gehiago irakurri: Dockeren praktika arruntak**](/sections/docker/generic-tips.md) +🔗 [**Informazio gehiago: Dockeren praktika generikoak**](./sections/docker/generic-tips.basque.md)


-## ![✔] 8.15. Garbitu zure Dockerfilea +## ![✔] 8.15. Garbitu zure Dockerfile fitxategia Linterra erabiliz -**TL;PL:** Linterra erabiliz zure Dockerfilea garbitzea urrats garrantzitsua da haren barruan jardunbide egokiak errespetatzen ez dituzten arazoak identifikatzeko. Docker linter espezializatu bat erabiliz errendimendu eta segurtasun hobekuntzak erraz antzematen dira, alferrikako ordu ugari aurreztea edo produkzio kodean segurtasun arazoak murriztea lortuz +**TL;PL:** Linterra erabiliz zure Dockerfile fitxategia garbitzea urrats garrantzitsua da haren barruan praktika onak errespetatzen ez dituzten arazoak identifikatzeko. Docker garbitzaile (linter) espezializatu bat erabiliz errendimendu eta segurtasun hobekuntzak erraz atzematen dira, alferrikako ordu ugari aurreztea edo produkzio kodean segurtasun arazoak murriztea lortuz -**Bestela:** okerrez, Dockerfileren sortzaileak root bat utzi zuen produkzio erabiltzaile moduan, eta jatorri ezezaguneko biltegi irudi bat ere erabili zuen. Hori liner soil batekin ekidin liteke. +**Bestela:** okerrez, Dockerfile fitxategiaren sortzaileak nagusi (root) bat utzi zuen produkzio erabiltzaile moduan, eta jatorri ezezaguneko biltegi irudi bat ere erabili zuen. Hori liner soil batekin ekidin liteke. -🔗 [**Gehiago irakurri: garbitu zure Dockerfilea**](/sections/docker/lint-dockerfile.md) +🔗 [**Informazio gehiago: garbitu zure Dockerfile fitxategia**](./sections/docker/lint-dockerfile.basque.md)


@@ -1271,7 +1266,7 @@ Gainera, irudi etiketa bat aipatzen bada, oinarrizko irudia aldatu egin daiteke, # Mugarriak -Gida hau mantentzeko eta eguneratuta egoteko, jarraibideak eta jardunbide egokiak eguneratzen eta hobetzen ari gara etengabe komunitatearen laguntzarekin. Proiektu honetan lagundu nahi baduzu, jarraitu gure [mugarriak](https://github.com/goldbergyoni/nodebestpractices/milestones) jarrai sartu lantaldeetan +Gida hau mantentzeko eta eguneratuta egoteko, jarraibideak eta praktika onak eguneratzen eta hobetzen ari gara etengabe komunitatearen laguntzarekin. Proiektu honetan lagundu nahi baduzu, jarraitu gure [mugarriak](https://github.com/goldbergyoni/nodebestpractices/milestones) jarrai sartu lantaldeetan
@@ -1281,19 +1276,19 @@ Komunitatearen ekarpena dira hemengo itzulpen guztiak eman. Oso pozik hartuko ge ### Amaitutako itzulpenak -- ![BR](/assets/flags/BR.png) [Brasilgo portugalera](./README.brazilian-portuguese.md) - [Marcelo Melo](https://github.com/marcelosdm)-ren eskutik -- ![CN](/assets/flags/CN.png) [Txinera](./README.chinese.md) - [Matt Jin](https://github.com/mattjin)-ren eskutik -- ![RU](/assets/flags/RU.png) [Errusiera](./README.russian.md) - [Alex Ivanov](https://github.com/contributorpw)-ren eskutik -- ![PL](/assets/flags/PL.png) [Poloniera](./README.polish.md) - [Michal Biesiada](https://github.com/mbiesiad)-ren eskutik +- ![BR](./assets/flags/BR.png) [Brasilgo portugalera](./README.brazilian-portuguese.md) - [Marcelo Melo](https://github.com/marcelosdm)-ren eskutik +- ![CN](./assets/flags/CN.png) [Txinera](./README.chinese.md) - [Matt Jin](https://github.com/mattjin)-ren eskutik +- ![RU](./assets/flags/RU.png) [Errusiera](./README.russian.md) - [Alex Ivanov](https://github.com/contributorpw)-ren eskutik +- ![PL](./assets/flags/PL.png) [Poloniera](./README.polish.md) - [Michal Biesiada](https://github.com/mbiesiad)-ren eskutik +- ![EU](./assets/flags/EU.png) [Euskara](README.basque.md) - [Ane Diaz de Tuesta](https://github.com/anediaz) & Joxefe Diaz de Tuestaren eskutik ### Aribidean dauden itzulpenak -- ![FR](/assets/flags/FR.png) [Frantsesa](https://github.com/gaspaonrocks/nodebestpractices/blob/french-translation/README.french.md) ([Eztabaidan](https://github.com/goldbergyoni/nodebestpractices/issues/129)) -- ![HE](/assets/flags/HE.png) Hebrearra ([Eztabaidan](https://github.com/goldbergyoni/nodebestpractices/issues/156)) -- ![KR](/assets/flags/KR.png) [Koreera](README.korean.md) - [Sangbeom Han](https://github.com/uronly14me)-ren eskutik ([Eztabaidan](https://github.com/goldbergyoni/nodebestpractices/issues/94)) -- ![ES](/assets/flags/ES.png) [Gaztelera](https://github.com/goldbergyoni/nodebestpractices/blob/spanish-translation/README.spanish.md) ([Eztabaidan](https://github.com/goldbergyoni/nodebestpractices/issues/95)) -- ![TR](/assets/flags/TR.png) Turkiera ([Eztabaidan](https://github.com/goldbergyoni/nodebestpractices/issues/139)) -- ![EU](/assets/flags/EU.png) [Euskara](README.basque.md) - [Ane Diaz de Tuesta](https://github.com/anediaz) & Joxefe Diaz de Tuestaren eskutik ([Eztabaidan](https://github.com/goldbergyoni/nodebestpractices/issues/842)) +- ![FR](./assets/flags/FR.png) [Frantsesa](https://github.com/gaspaonrocks/nodebestpractices/blob/french-translation/README.french.md) ([Eztabaidan](https://github.com/goldbergyoni/nodebestpractices/issues/129)) +- ![HE](./assets/flags/HE.png) Hebrearra ([Eztabaidan](https://github.com/goldbergyoni/nodebestpractices/issues/156)) +- ![KR](./assets/flags/KR.png) [Koreera](README.korean.md) - [Sangbeom Han](https://github.com/uronly14me)-ren eskutik ([Eztabaidan](https://github.com/goldbergyoni/nodebestpractices/issues/94)) +- ![ES](./assets/flags/ES.png) [Gaztelera](https://github.com/goldbergyoni/nodebestpractices/blob/spanish-translation/README.spanish.md) ([Eztabaidan](https://github.com/goldbergyoni/nodebestpractices/issues/95)) +- ![TR](./assets/flags/TR.png) Turkiera ([Eztabaidan](https://github.com/goldbergyoni/nodebestpractices/issues/139))

@@ -1301,17 +1296,17 @@ Komunitatearen ekarpena dira hemengo itzulpen guztiak eman. Oso pozik hartuko ge Ezagutu Zuzendaritza Batzordeko kideak, proiektuaren orientazioa eta etorkizunerako jarraibideak emateko elkarlanean dirautenak. Gainera, batzordeko kide bakoitza gure [Github projects](https://github.com/goldbergyoni/nodebestpractices/projects)-pean dagoen proiektu baten buru da - + [Yoni Goldberg](https://github.com/goldbergyoni) -EEBB-etan, Europan eta Israelen, bezeroekin tamaina handiko Node.js aplikazioen sorkuntzan lan egiten duen Node.jsen inguruko aholkulari independentea. Gida honetako jardunbide egoki asko lehenengo aldiz [goldbergyoni.com](https://goldbergyoni.com)-en argitaratuak izan ziren. Jar zaitez Yoni-rekin kontatuan [@goldbergyoni](https://github.com/goldbergyoni)-en edo [me@goldbergyoni.com](mailto:me@goldbergyoni.com) helbidearen bidez +EEBB-etan, Europan eta Israelen, bezeroekin tamaina handiko Node.js aplikazioen sorkuntzan lan egiten duen Node.jsren inguruko aholkulari independentea. Gida honetako praktika on asko lehenengo aldiz [goldbergyoni.com](https://goldbergyoni.com)-en argitaratuak izan ziren. Jar zaitez Yoni-rekin kontatuan [@goldbergyoni](https://github.com/goldbergyoni)-en edo [me@goldbergyoni.com](mailto:me@goldbergyoni.com) helbidearen bidez
- + [Bruno Scheufler](https://github.com/BrunoScheufler) @@ -1320,7 +1315,7 @@ EEBB-etan, Europan eta Israelen, bezeroekin tamaina handiko Node.js aplikazioen
- + [Kyle Martin](https://github.com/js-kyle) @@ -1330,7 +1325,7 @@ Full Stack Garatzailea eta Zelanda Berrian lan egiten duen Site Reliability Inge
- + [Kevyn Bruyere](https://github.com/kevynb) @@ -1341,7 +1336,7 @@ Full-stack garatzaile independentea, Ops eta automatizazioan zaletua dena ### Steering Committee Emeriti - + [Sagir Khan](https://github.com/sagirk) @@ -1356,15 +1351,15 @@ Javascripten eta bere ekosisteman (React, Node.js, TypeScript, GraphQL, MongoDB, Mila esker gure laguntzaile guztiei! 🙏 -Gure kolaboratzaileak proiektuan maiz parte hartzen duten kideak dira, jardunbide egokiak proposatuz, gaien zerrenda ordenatuz, parte hartze eskaerak (pull request) aztertuz... Milaka pertsona Node.js aplikazioak hobeto sortzen laguntzen interesa baduzu, irakur ezazu gure [kolaboratzaile gida](/.operations/CONTRIBUTING.md) 🎉 +Gure kolaboratzaileak proiektuan maiz parte hartzen duten kideak dira, praktika onak proposatuz, gaien zerrenda ordenatuz, parte hartze eskaerak (pull request) aztertuz... Milaka pertsona Node.js aplikazioak hobeto sortzen laguntzen interesa baduzu, irakur ezazu gure [kolaboratzaile gida](./.operations/CONTRIBUTING.md) 🎉 -| | | +| | | | :---------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------: | | [Ido Richter (Fundatzailea)](https://github.com/idori) | [Keith Holliday](https://github.com/TheHollidayInn) | ### Emeriti Kolaboratzailea -| | +| | | :-------------------------------------------------------------------------------------------------------------------------: | | [Refael Ackermann](https://github.com/refack) | @@ -1382,175 +1377,256 @@ Eskerrik asko proiektu honetan parte hartu duten pertsona zoragarriei! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

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

📖
Kevin Rambaud
Kevin Rambaud

🖋
Michael Fine
Michael Fine

🖋
Shreya Dahal
Shreya Dahal

🖋
Matheus Cruz Rocha
Matheus Cruz Rocha

🖋
Yog Mehta
Yog Mehta

🖋
Kudakwashe Paradzayi
Kudakwashe Paradzayi

🖋
t1st3
t1st3

🖋
mulijordan1976
mulijordan1976

🖋
Matan Kushner
Matan Kushner

🖋
Fabio Hiroki
Fabio Hiroki

🖋
James Sumners
James Sumners

🖋
Dan Gamble
Dan Gamble

🖋
PJ Trainor
PJ Trainor

🖋
Remek Ambroziak
Remek Ambroziak

🖋
Yoni Jah
Yoni Jah

🖋
Misha Khokhlov
Misha Khokhlov

🖋
Evgeny Orekhov
Evgeny Orekhov

🖋
-
-

🖋
Isaac Halvorson
Isaac Halvorson

🖋
Vedran Karačić
Vedran Karačić

🖋
lallenlowe
lallenlowe

🖋
Nathan Wells
Nathan Wells

🖋
Paulo Reis
Paulo Reis

🖋
syzer
syzer

🖋
David Sancho
David Sancho

🖋
Robert Manolea
Robert Manolea

🖋
Xavier Ho
Xavier Ho

🖋
Aaron
Aaron

🖋
Jan Charles Maghirang Adona
Jan Charles Maghirang Adona

🖋
Allen
Allen

🖋
Leonardo Villela
Leonardo Villela

🖋
Michał Załęcki
Michał Załęcki

🖋
Chris Nicola
Chris Nicola

🖋
Alejandro Corredor
Alejandro Corredor

🖋
cwar
cwar

🖋
Yuwei
Yuwei

🖋
Utkarsh Bhatt
Utkarsh Bhatt

🖋
Duarte Mendes
Duarte Mendes

🖋
Jason Kim
Jason Kim

🖋
Mitja O.
Mitja O.

🖋
Sandro Miguel Marques
Sandro Miguel Marques

🖋
Gabe
Gabe

🖋
Ron Gross
Ron Gross

🖋
Valeri Karpov
Valeri Karpov

🖋
Sergio Bernal
Sergio Bernal

🖋
Nikola Telkedzhiev
Nikola Telkedzhiev

🖋
Vitor Godoy
Vitor Godoy

🖋
Manish Saraan
Manish Saraan

🖋
Sangbeom Han
Sangbeom Han

🖋
blackmatch
blackmatch

🖋
Joe Reeve
Joe Reeve

🖋
Ryan Busby
Ryan Busby

🖋
Iman Mohamadi
Iman Mohamadi

🖋
Sergii Paryzhskyi
Sergii Paryzhskyi

🖋
Kapil Patel
Kapil Patel

🖋
迷渡
迷渡

🖋
Hozefa
Hozefa

🖋
Ethan
Ethan

🖋
Sam
Sam

🖋
Arlind
Arlind

🖋
Teddy Toussaint
Teddy Toussaint

🖋
Lewis
Lewis

🖋
Gabriel Lidenor
Gabriel Lidenor

🖋
Roman
Roman

🖋
Francozeira
Francozeira

🖋
Invvard
Invvard

🖋
Rômulo Garofalo
Rômulo Garofalo

🖋
Tho Q Luong
Tho Q Luong

🖋
Burak Shen
Burak Shen

🖋
Martin Muzatko
Martin Muzatko

🖋
Jared Collier
Jared Collier

🖋
Hilton Meyer
Hilton Meyer

🖋
ChangJoo Park(박창주)
ChangJoo Park(박창주)

🖋
Masahiro Sakaguchi
Masahiro Sakaguchi

🖋
Keith Holliday
Keith Holliday

🖋
coreyc
coreyc

🖋
Maximilian Berkmann
Maximilian Berkmann

🖋
Douglas Mariano Valero
Douglas Mariano Valero

🖋
Marcelo Melo
Marcelo Melo

🖋
Mehmet Perk
Mehmet Perk

🖋
ryan ouyang
ryan ouyang

🖋
Shabeer
Shabeer

🖋
Eduard Kyvenko
Eduard Kyvenko

🖋
Deyvison Rocha
Deyvison Rocha

🖋
George Mamer
George Mamer

🖋
Konstantinos Leimonis
Konstantinos Leimonis

🖋
Oliver Lluberes
Oliver Lluberes

🌍
Tien Do
Tien Do

🖋
Ranvir Singh
Ranvir Singh

🖋
Vadim Nicolaev
Vadim Nicolaev

🖋 🌍
German Gamboa Gonzalez
German Gamboa Gonzalez

🖋
Hafez
Hafez

🖋
Chandiran
Chandiran

🖋
VinayaSathyanarayana
VinayaSathyanarayana

🖋
Kim Kern
Kim Kern

🖋
Kenneth Freitas
Kenneth Freitas

🖋
songe
songe

🖋
Kirill Shekhovtsov
Kirill Shekhovtsov

🖋
Serge
Serge

🖋
keyrwinz
keyrwinz

🖋
Dmitry Nikitenko
Dmitry Nikitenko

🖋
bushuai
bushuai

👀 🖋
Benjamin Gruenbaum
Benjamin Gruenbaum

🖋
Ezequiel
Ezequiel

🌍
Juan José Rodríguez
Juan José Rodríguez

🌍
Or Bin
Or Bin

🖋
Andreo Vieira
Andreo Vieira

🖋
Michael Solomon
Michael Solomon

🖋
Jimmy Callin
Jimmy Callin

🖋
Siddharth
Siddharth

🖋
Ryan Smith
Ryan Smith

🖋
Tom Boettger
Tom Boettger

🖋
Joaquín Ormaechea
Joaquín Ormaechea

🌍
dfrzuz
dfrzuz

🌍
Victor Homyakov
Victor Homyakov

🖋
Josh
Josh

🖋 🛡️
Alec Francis
Alec Francis

🖋
arjun6610
arjun6610

🖋
Jan Osch
Jan Osch

🖋
Thiago Rotondo Sampaio
Thiago Rotondo Sampaio

🌍
Alexsey
Alexsey

🖋
Luis A. Acurero
Luis A. Acurero

🌍
Lucas Romano
Lucas Romano

🌍
Denise Case
Denise Case

🖋
Nick Ribal
Nick Ribal

🖋 👀
0xflotus
0xflotus

🖋
Jonathan Chen
Jonathan Chen

🖋
Dilan Srilal
Dilan Srilal

🖋
vladthelittleone
vladthelittleone

🌍
Nik Osvalds
Nik Osvalds

🖋
Daniel Kiss
Daniel Kiss

📖
Forresst
Forresst

🖋
Jonathan Svenheden
Jonathan Svenheden

🖋
AustrisC
AustrisC

🖋
kyeongtae kim
kyeongtae kim

🌍
007
007

🖋
Ane Diaz de Tuesta
Ane Diaz de Tuesta

🌍 🖋
YukiOta
YukiOta

🌍
Frazer Smith
Frazer Smith

🖋
Raz Luvaton
Raz Luvaton

🖋
Yuta Azumi
Yuta Azumi

🖋
andrewjbarbour
andrewjbarbour

🖋
mr
mr

🖋
Aleksandar
Aleksandar

🖋
Owl
Owl

🖋
Yedidya Schwartz
Yedidya Schwartz

🖋 💡
ari
ari

🖋
Thomas König
Thomas König

🖋
Kalle Lämsä
Kalle Lämsä

🖋
Wyatt
Wyatt

🖋
KHADIR Tayeb
KHADIR Tayeb

🖋
Shankar Regmi
Shankar Regmi

🖋
Shubham
Shubham

🖋
Lucas Alves
Lucas Alves

🖋
Benjamin
Benjamin

🖋
Yeoh Joer
Yeoh Joer

🖋
Miigon
Miigon

🖋
Rostislav Bogorad
Rostislav Bogorad

🖋
Flouse
Flouse

🖋
Tarantini Pereira
Tarantini Pereira

🖋
Kazuki Matsuo
Kazuki Matsuo

🖋
Adam Smith
Adam Smith

🖋
Dohyeon Ko
Dohyeon Ko

🖋
Vladislav Legkov
Vladislav Legkov

🖋
Kerollos Magdy
Kerollos Magdy

🖋
Erez Lieberman
Erez Lieberman

🖋
Breno Macedo
Breno Macedo

🖋
Fernando Flores
Fernando Flores

🌍
Rafael Brito
Rafael Brito

🌍
Emiliano Peralta
Emiliano Peralta

🌍
Shin, SJ
Shin, SJ

🖋
Benjamin Forster
Benjamin Forster

🖋
Daniele Fedeli
Daniele Fedeli

🖋
djob195
djob195

🖋
antspk
antspk

🖋
정진영
정진영

🖋
kkk-cashwalk
kkk-cashwalk

🖋
apainintheneck
apainintheneck

🖋
Fajar Budhi Iswanda
Fajar Budhi Iswanda

🖋
이주호
이주호

🖋
Singh
Singh

🖋
Alex Dumitru
Alex Dumitru

🖋
Anton Lykhatskyi
Anton Lykhatskyi

🖋
sangwonlee
sangwonlee

🖋
Eugenio Berretta
Eugenio Berretta

🖋
soranakk
soranakk

🖋
고준영
고준영

🖋 💻
Guilherme Portella
Guilherme Portella

🖋
André Esser
André Esser

🖋
Scc
Scc

🌍
Mauro Accornero
Mauro Accornero

🖋
no-yan
no-yan

🖋
diff --git a/README.brazilian-portuguese.md b/README.brazilian-portuguese.md index 48fb6e233..10c88e6f2 100644 --- a/README.brazilian-portuguese.md +++ b/README.brazilian-portuguese.md @@ -3,22 +3,22 @@ # Melhores Práticas em Node.js

- Node.js Best Practices + Node.js Best Practices


- 83 items Última Atualização: June 5, 2019 Atualizado para Node 12.4.0 LTS + 83 items Última Atualização: June 5, 2019 Atualizado para Node 12.4.0 LTS

-[![nodepractices](/assets/images/twitter-s.png)](https://twitter.com/nodepractices/) **Siga-nos no Twitter!** [**@nodepractices**](https://twitter.com/nodepractices/) +[![nodepractices](./assets/images/twitter-s.png)](https://twitter.com/nodepractices/) **Siga-nos no Twitter!** [**@nodepractices**](https://twitter.com/nodepractices/)
-Leia em diferentes idiomas: [![CN](/assets/flags/CN.png)**CN**](/README.chinese.md), [![BR](/assets/flags/BR.png)**BR**](/README.brazilian-portuguese.md) [(![ES](/assets/flags/ES.png)**ES**, ![FR](/assets/flags/FR.png)**FR**, ![HE](/assets/flags/HE.png)**HE**, ![KR](/assets/flags/KR.png)**KR**, ![RU](/assets/flags/RU.png)**RU**, ![TR](/assets/flags/TR.png)**TR** e ![EU](/assets/flags/EU.png)**EU** em progresso!)](#translations)](#translations) +Leia em diferentes idiomas: [![CN](./assets/flags/CN.png)**CN**](./README.chinese.md), [![BR](./assets/flags/BR.png)**BR**](./README.brazilian-portuguese.md), [![RU](./assets/flags/RU.png)**RU**](./README.russian.md), [![PL](./assets/flags/PL.png)**PL**](./README.polish.md), [![JA](./assets/flags/JA.png)**JA**](./README.japanese.md), [![EU](./assets/flags/EU.png)**EU**](./README.basque.md) [(![ES](./assets/flags/ES.png)**ES**, ![FR](./assets/flags/FR.png)**FR**, ![HE](./assets/flags/HE.png)**HE**, ![KR](./assets/flags/KR.png)**KR** and ![TR](./assets/flags/TR.png)**TR** em progresso! )](#translations)
@@ -28,13 +28,15 @@ Leia em diferentes idiomas: [![CN](/assets/flags/CN.png)**CN**](/README.chinese. - **Nova Boa Prática:** 4.4: [Evite dados fixos e sementes para teste, adicione os dados no teste](#4-práticas-de-testes-e-qualidade-geral) -- **Nova Boa Prática:** 6.25: [Evite publicar segredos no registro do npm](/sections/security/avoid_publishing_secrets.brazilian-portuguese.md) +- **Nova Boa Prática:** 6.25: [Evite publicar segredos no registro do npm](./sections/security/avoid_publishing_secrets.brazilian-portuguese.md) -- **Nova tradução:** ![BR](/assets/flags/BR.png) [Português Brasileiro](/README.brazilian-portuguese.md) disponível agora, cortesia de [Marcelo Melo](https://github.com/marcelosdm)! ❤️ +- **Nova tradução:** ![BR](./assets/flags/BR.png) [Português Brasileiro](./README.brazilian-portuguese.md) disponível agora, cortesia de [Marcelo Melo](https://github.com/marcelosdm)! ❤️ + +- **🎊 60,000 estrelas!**: Nosso repo recebeu estrela e a confiança de 60.100 desenvolvedores. Estamos sem palavras

-# Bem-vindo! 3 Coisas Que Você Precisa Saber: +# Bem-vindo! 3 Coisas Que Você Precisa Saber **1. Quando você lê aqui, na verdade você lê alguns dos melhores artigos de Node.js -** este é um resumo e curadoria dos mais bem ranqueados conteúdos sobre as melhores práticas do Node.js. @@ -46,13 +48,13 @@ Leia em diferentes idiomas: [![CN](/assets/flags/CN.png)**CN**](/README.chinese. ## Índice -1. [Práticas de Estrutura de Projeto (5)](#1-práticas-de-estrutura-de-projeto) -2. [Práticas de Tratamento de Erros (11) ](#2-práticas-de-tratamento-de-erros) -3. [Práticas de Estilo de Código (12) ](#3-práticas-de-estilo-de-código) -4. [Práticas de Testes e Qualidade Geral (11) ](#4-práticas-de-testes-e-qualidade-geral) -5. [Práticas de Produção (18) ](#5-boas-práticas-de-produção) -6. [Práticas de Segurança (25)](#6-boas-práticas-em-segurança) -7. [Práticas de Performance (1) (Em Progresso ✍️)](#7-boas-práticas-em-performance) +1. [Práticas de Estrutura de Projeto (5)](#1-práticas-de-estrutura-de-projeto) +2. [Práticas de Tratamento de Erros (12) ](#2-práticas-de-tratamento-de-erros) +3. [Práticas de Estilo de Código (13) ](#3-práticas-de-estilo-de-código) +4. [Práticas de Testes e Qualidade Geral (13) ](#4-práticas-de-testes-e-qualidade-geral) +5. [Práticas de Produção (19) ](#5-boas-práticas-de-produção) +6. [Práticas de Segurança (25)](#6-boas-práticas-em-segurança) +7. [Práticas de Performance (1) (Em Progresso ✍️)](#7-boas-práticas-em-performance)

@@ -60,11 +62,11 @@ Leia em diferentes idiomas: [![CN](/assets/flags/CN.png)**CN**](/README.chinese. ## ![✔] 1.1 Estruture sua solução por componentes -**TL;DR:** A pior armadilha das grandes aplicações é manter uma enorme base de código com centenas de dependências - tal qual as monolíticas, que diminuem a velocidade dos desenvolvedores conforme eles tentam incorporar novos recursos. Em vez disso, particione seu código em componentes, cada um com sua própria pasta ou uma base de código dedicada, e garanta cada unidade seja mantida pequena e simples. Veja o link ‘Leia Mais’ abaixo, para ver exemplos de estrutura correta de projeto. +**TL;DR:** A pior armadilha das grandes aplicações é manter uma enorme base de código com centenas de dependências - tal qual as monolíticas, que diminuem a velocidade dos desenvolvedores conforme eles tentam incorporar novos recursos. Em vez disso, particione seu código em componentes, cada um com sua própria pasta ou uma base de código dedicada, e garanta que cada unidade seja mantida pequena e simples. Veja o link ‘Leia Mais’ abaixo, para ver exemplos de estrutura correta de projeto. **Caso contrário:** Quando desenvolvendo novos recursos, desenvolvedores têm dificuldade para perceber o impacto de suas modificações e temem estragar outros componentes dependentes - deploys se tornam mais lentos e arriscados. Também é considerado mais difícil de escalar quando nenhuma unidade de negócio está separada. -🔗 [**Leia mais: estruture por componentes**](/sections/projectstructre/breakintcomponents.brazilian-portuguese.md) +🔗 [**Leia mais: estruture por componentes**](./sections/projectstructre/breakintcomponents.brazilian-portuguese.md)

@@ -74,7 +76,7 @@ Leia em diferentes idiomas: [![CN](/assets/flags/CN.png)**CN**](/README.chinese. **Caso contrário:** Uma aplicação que misture objetos WEB com outras camadas não podem ser acessadas por códigos de teste, CRON jobs e outras chamadas não oriundas do Express. -🔗 [**Leia Mais: seu app em camadas**](/sections/projectstructre/createlayers.brazilian-portuguese.md) +🔗 [**Leia Mais: seu app em camadas**](./sections/projectstructre/createlayers.brazilian-portuguese.md)

@@ -84,7 +86,7 @@ Leia em diferentes idiomas: [![CN](/assets/flags/CN.png)**CN**](/README.chinese. **Caso contrário:** Você deverá criar seu próprio ciclo de implantação e dependência. -🔗 [**Leia Mais: estrutura por característica**](/sections/projectstructre/wraputilities.brazilian-portuguese.md) +🔗 [**Leia Mais: estrutura por característica**](./sections/projectstructre/wraputilities.brazilian-portuguese.md)

@@ -94,7 +96,7 @@ Leia em diferentes idiomas: [![CN](/assets/flags/CN.png)**CN**](/README.chinese. **Caso contrário:** Sua API será acessível apenas para testes via chamadas HTTP (mais lentos e muito mais difíceis de gerar relatórios de cobertura). Provavelmente não será um grande prazer manter centenas de linhas de código em um único arquivo. -🔗 [**Leia Mais: separe 'app' e 'server' no Express**](/sections/projectstructre/separateexpress.brazilian-portuguese.md) +🔗 [**Leia Mais: separe 'app' e 'server' no Express**](./sections/projectstructre/separateexpress.brazilian-portuguese.md)

@@ -104,7 +106,7 @@ Leia em diferentes idiomas: [![CN](/assets/flags/CN.png)**CN**](/README.chinese. **Caso contrário:** Deixar de satisfazer qualquer um dos requisitos de configuração simplesmente atrapalhará a equipe de desenvolvimento ou devops. Provavelmente ambas. -🔗 [**Leia Mais: melhores práticas de configuração**](/sections/projectstructre/configguide.brazilian-portuguese.md) +🔗 [**Leia Mais: melhores práticas de configuração**](./sections/projectstructre/configguide.brazilian-portuguese.md)


@@ -118,7 +120,7 @@ Leia em diferentes idiomas: [![CN](/assets/flags/CN.png)**CN**](/README.chinese. **Caso contrário:** O estilo de callback do Node.js, function(err, response), é um caminho promissor para um código insustentável devido à combinação de manipulação de erro com código casual, aninhamento excessivo e padrões de codificação inadequados. -🔗 [**Leia Mais: evitando callbacks**](/sections/errorhandling/asyncerrorhandling.brazilian-portuguese.md) +🔗 [**Leia Mais: evitando callbacks**](./sections/errorhandling/asyncerrorhandling.brazilian-portuguese.md)

@@ -128,7 +130,7 @@ Leia em diferentes idiomas: [![CN](/assets/flags/CN.png)**CN**](/README.chinese. **Caso contrário:** Ao invocar algum componente, sendo incerto qual tipo de erro irá retornar - isso faz com que o tratamento de erros seja muito mais difícil. Até pior, usar tipos personalizados para descrever erros pode levar à perda de informações de erros críticos, como o stack trace! -🔗 [**Leia Mais: usando o objeto interno de erro**](/sections/errorhandling/useonlythebuiltinerror.brazilian-portuguese.md) +🔗 [**Leia Mais: usando o objeto interno de erro**](./sections/errorhandling/useonlythebuiltinerror.brazilian-portuguese.md)

@@ -138,7 +140,7 @@ Leia em diferentes idiomas: [![CN](/assets/flags/CN.png)**CN**](/README.chinese. **Caso contrário:** Você pode sempre reiniciar o aplicativo quando um erro aparecer, mas por que derrubar aproximadamente 5000 usuários que estavam online por causa de um pequeno erro operacional previsto? O contrário também não é ideal - manter a aplicação rodando quando um problema desconhecido (erro de programação) ocorreu, pode levar para um comportamento não esperado. Diferenciá-los, permite agir com tato e aplicar uma abordagem equilibrada baseada no dado contexto. -🔗 [**Leia Mais: erros operacionais vs erros de programação**](/sections/errorhandling/operationalvsprogrammererror.brazilian-portuguese.md) +🔗 [**Leia Mais: erros operacionais vs erros de programação**](./sections/errorhandling/operationalvsprogrammererror.brazilian-portuguese.md)

@@ -148,7 +150,7 @@ Leia em diferentes idiomas: [![CN](/assets/flags/CN.png)**CN**](/README.chinese. **Caso contrário:** Não tratar os erros em um mesmo lugar irá levar à duplicidade de código, e provavelmente, a erros tratados incorretamente. -🔗 [**Leia Mais: tratando erros de forma centralizada**](/sections/errorhandling/centralizedhandling.brazilian-portuguese.md) +🔗 [**Leia Mais: tratando erros de forma centralizada**](./sections/errorhandling/centralizedhandling.brazilian-portuguese.md)

@@ -158,27 +160,27 @@ Leia em diferentes idiomas: [![CN](/assets/flags/CN.png)**CN**](/README.chinese. **Caso contrário:** Um cliente de uma API pode decidir travar e reiniciar, apenas pelo motivo de ter recebido de volta um erro que não conseguiu entender. Nota: o visitante de sua API pode ser você (muito comum em um ambiente de microsserviço). -🔗 [**Leia Mais: documentando erros de API no Swagger ou GraphQL**](/sections/errorhandling/documentingusingswagger.brazilian-portuguese.md) +🔗 [**Leia Mais: documentando erros de API no Swagger ou GraphQL**](./sections/errorhandling/documentingusingswagger.brazilian-portuguese.md)

## ![✔] 2.6 Finalize o processo quando um estranho chegar -**TL;DR:** Quando ocorre um erro desconhecido (um erro de programação, veja a melhor prática #3) - há incerteza sobre a integridade da aplicação. Uma prática comum sugere reiniciar cuidadosamente o processo utilizando uma ferramenta de “reinicialização” como Forever e PM2. +**TL;DR:** Quando ocorre um erro desconhecido (um erro de programação, veja a melhor prática #3) - há incerteza sobre a integridade da aplicação. Uma prática comum sugere reiniciar cuidadosamente o processo utilizando uma ferramenta de “reinicialização” como [Forever](https://www.npmjs.com/package/forever) e [PM2](http://pm2.keymetrics.io/). **Caso contrário:** Quando uma exceção desconhecida é lançada, algum objeto pode estar com defeito (por exemplo, um emissor de evento que é usado globalmente e não dispara mais eventos devido a alguma falha interna) e todas as requisições futuras podem falhar ou se comportar loucamente. -🔗 [**Leia Mais: finalizando o processo**](/sections/errorhandling/shuttingtheprocess.brazilian-portuguese.md) +🔗 [**Leia Mais: finalizando o processo**](./sections/errorhandling/shuttingtheprocess.brazilian-portuguese.md)

## ![✔] 2.7 Use um agente de log maduro para aumentar a visibilidade de erros -**TL;DR:** Um conjunto de ferramentas de registro maduras como Winston, Bunyan ou Log4j, irão acelerar a descoberta e entendimento de erros. Portanto, esqueça o console.log. +**TL;DR:** Um conjunto de ferramentas de registro maduras como [Pino](https://www.npmjs.com/package/pino), [Winston](https://www.npmjs.com/package/winston), [Bunyan](https://www.npmjs.com/package/bunyan) ou [Log4js](https://www.npmjs.com/package/log4js), irão acelerar a descoberta e entendimento de erros. Portanto, esqueça o console.log. **Caso contrário:** Ficar procurando através de console.logs ou manualmente em arquivos de texto confusos sem utilizar ferramentas de consulta ou um visualizador de log decente, pode mantê-lo ocupado até tarde. -🔗 [**Leia Mais: usando um logger maduro**](/sections/errorhandling/usematurelogger.brazilian-portuguese.md) +🔗 [**Leia Mais: usando um logger maduro**](./sections/errorhandling/usematurelogger.brazilian-portuguese.md)

@@ -188,7 +190,7 @@ Leia em diferentes idiomas: [![CN](/assets/flags/CN.png)**CN**](/README.chinese. **Caso contrário:** Sem testes, seja automático ou manual, não podemos confiar em nosso código para retornar os erros certos. Sem erros significantes, não há tratamento de erros. -🔗 [**Leia Mais: fluxos de testes de erros**](/sections/errorhandling/testingerrorflows.brazilian-portuguese.md) +🔗 [**Leia Mais: fluxos de testes de erros**](./sections/errorhandling/testingerrorflows.brazilian-portuguese.md)

@@ -198,7 +200,7 @@ Leia em diferentes idiomas: [![CN](/assets/flags/CN.png)**CN**](/README.chinese. **Caso contrário:** Você pode gastar muito esforço medindo o desempenho e os tempos de inatividade (downtime) da API. Provavelmente, você nunca saberá quais são suas partes de código mais lentas no cenário real e como elas afetam o UX. -🔗 [**Leia Mais: usando APM**](/sections/errorhandling/apmproducts.brazilian-portuguese.md) +🔗 [**Leia Mais: usando APM**](./sections/errorhandling/apmproducts.brazilian-portuguese.md)

@@ -208,7 +210,7 @@ Leia em diferentes idiomas: [![CN](/assets/flags/CN.png)**CN**](/README.chinese. **Caso contrário:** Seus erros serão engolidos e não vão deixar rastros. Nada para se preocupar. -🔗 [**Leia Mais: capturando rejeições de promises não tratadas**](/sections/errorhandling/catchunhandledpromiserejection.brazilian-portuguese.md) +🔗 [**Leia Mais: capturando rejeições de promises não tratadas**](./sections/errorhandling/catchunhandledpromiserejection.brazilian-portuguese.md)

@@ -218,7 +220,19 @@ Leia em diferentes idiomas: [![CN](/assets/flags/CN.png)**CN**](/README.chinese. **Caso contrário:** Considere isto: sua função espera receber um “Desconto” como argumento numérico que foi esquecido de passar. Mais adiante, seu código verifica se Desconto!=0 (valor do desconto permitido é maior que zero). Depois, irá permitir que o usuário desfrute de um desconto. Meu Deus, que baita bug. Entendeu? -🔗 [**Leia Mais: falhando rápido**](/sections/errorhandling/failfast.brazilian-portuguese.md) +🔗 [**Leia Mais: falhando rápido**](./sections/errorhandling/failfast.brazilian-portuguese.md) + +

+ +## ![✔] 2.12 Sempre use 'await' antes de retornar as 'promises' para evitar um rastreamento parcial da pilha de erro + +**TL;DR:** Sempre use `return await` quando retornar uma 'promise' para beneficiar o rastreamento completo da pilha de erro. Se um função retorna uma 'promise', essa função deve ser declarada como função `async` e explicitamente `await` na `promise` antes de devolvê-la + +**Caso contrário:** Uma função que retorna uma `promise` sem o `await` não aparecerá na pilha de erro. +A ausência dessas informações provavelmente complicariam a compreensão do fluxo que leva ao erro, +especialmente se a causa do comportamento anormal estiver dentro da função ausente + +🔗 [**Leia Mais: retornando promises**](./sections/errorhandling/returningpromises.md)


@@ -232,7 +246,7 @@ Leia em diferentes idiomas: [![CN](/assets/flags/CN.png)**CN**](/README.chinese. **Caso contrário:** Desenvolvedores irão focar nas preocupações tediosas de espaçamento e largura de linha e o tempo poderá ser desperdiçado pensando sobre o estilo de código do projeto. -🔗 [**Leia Mais: Usando ESLint e Prettier**](/sections/codestylepractices/eslint_prettier.brazilian-portuguese.md) +🔗 [**Leia Mais: Usando ESLint e Prettier**](./sections/codestylepractices/eslint_prettier.brazilian-portuguese.md)

@@ -257,7 +271,8 @@ function someFunction() { } // Avoid -function someFunction() { +function someFunction() +{ // code block } ``` @@ -276,7 +291,7 @@ Não importa se você usa ponto-e-vírgula ou não para separar suas declaraçõ **Caso contrário:** Como visto na seção anterior, o interpretador do JavaScript adiciona automaticamente um ponto-e-vírgula ao final de uma instrução, se não houver uma, ou considera uma instrução como não terminada onde deveria, o que pode levar a alguns resultados indesejáveis. Você pode usar atribuições e evitar o uso de expressões de função chamadas imediatas para evitar a maioria dos erros inesperados. -### Exemplo de Código +### Exemplo de código ```javascript // Faça @@ -326,7 +341,7 @@ const count = 2 // tenta executar 2(), mas 2 não é uma função **Caso contrário:** O JavaScript é a única linguagem no mundo que permite invocar um construtor (“Class”) diretamente sem instanciá-lo primeiro. Consequentemente, Classes e construtores de funções são diferenciados começando com UpperCamelCase -### Exemplo de Código +### 3.6 Exemplo de Código ```javascript // para classes nós usamos UpperCamelCase @@ -369,7 +384,7 @@ function doSomething() {} **Caso contrário:** Alterar a estrutura interna dos arquivos ou a assinatura pode quebrar a interface com clientes. -### Exemplo de Código +### 3.9 Exemplo de Código ```javascript // Do @@ -389,7 +404,7 @@ module.exports.SMSNumberResolver = require("./SMSNumberResolver/SMSNumberResolve **Caso contrário:** Variáveis diferentes podem retornar verdadeiro quando comparadas usando o operador `==`. -### Exemplo de Código +### 3.10 Exemplo de Código ```javascript "" == "0"; // false @@ -448,11 +463,21 @@ Todas as declarações acima false se feitas com `===`. **Caso contrário:** Uma implantação falhou, um teste chamado "Adicionar produto" falhou. Isso lhe diz exatamente o que está errado? -🔗 [**Leia Mais: Inclua 3 partes em cada nome de teste**](/sections/testingandquality/3-parts-in-name.brazilian-portuguese.md) +🔗 [**Leia Mais: Inclua 3 partes em cada nome de teste**](./sections/testingandquality/3-parts-in-name.brazilian-portuguese.md) + +

+ +## ![✔] 4.3 Estutura de testes padrão AAA + +**TL;DR:** Estruture seus testes com 3 seções bem separadas: Arrange, Act & Assert (AAA). A primeira parte inclui a configuração do teste, depois a execução do teste unitário, e finalmente, a fase de asserção. Seguir esta estrutura garante que o leitor não gaste nenhuma CPU cerebral para entender o plano de teste + +**Caso contrário:** Você não somente passará várias horas do dia para entender o código principal, mas agora também gastará várias horas no que deveria ter sido uma simples parte do dia (testando) esticando seu cérebro. + +🔗 [**Leia Mais: Estutura de testes padrão AAA**](./sections/testingandquality/aaa.md)

-## ![✔] 4.3 Detecte problemas de código com um linter +## ![✔] 4.4 Detecte problemas de código com um linter **TL;DR:** Use um code linter para checar a qualidade básica e detectar antipadrões antecipadamente. Rode-o antes de qualquer teste e adicione-o como um pre-commit git-hook para minimizar o tempo necessário para revisar e corrigir qualquer problema. Veja também [Seção 3](https://github.com/goldbergyoni/nodebestpractices#3-code-style-practices) no Prática de Estilo de Código. @@ -460,17 +485,17 @@ Todas as declarações acima false se feitas com `===`.

-## ![✔] 4.4 Evite dados fixos e sementes para teste, adicione os dados no teste +## ![✔] 4.5 Evite dados fixos e sementes para teste, adicione os dados no teste **TL;DR:** Para evitar o acoplamento de testes e facilitar o entendimento do fluxo do teste, cada teste deve adicionar e atuar em seu próprio conjunto de linhas de banco de dados. Sempre que um teste precisar extrair ou assumir a existência de alguns dados do banco de dados - ele deve incluir explicitamente esses dados e evitar a mutação de outros registros **Caso contrário:** Considere um cenário em que a implementação é abortada devido a falhas nos testes. Agora, a equipe gastará um tempo precioso de investigação que termina em uma triste conclusão: o sistema funciona bem, mas os testes interferem uns nos outros e quebram a compilação -🔗 [**Leia Mais: Evite dados fixos para teste**](/sections/testingandquality/avoid-global-test-fixture.brazilian-portuguese.md) +🔗 [**Leia Mais: Evite dados fixos para teste**](./sections/testingandquality/avoid-global-test-fixture.brazilian-portuguese.md)

-## ![✔] 4.5 Inspencione constantemente por dependências vulneráveis +## ![✔] 4.6 Inspencione constantemente por dependências vulneráveis **TL;DR:** Até mesmo as dependências mais confiáveis, como o Express, têm vulnerabilidades conhecidas. Isso pode ser facilmente contornado usando ferramentas comunitárias e comerciais como 🔗 [nsp](https://github.com/nodesecurity/nsp) que pode ser invocado a partir do seu CI em cada build. @@ -478,7 +503,7 @@ Todas as declarações acima false se feitas com `===`.

-## ![✔] 4.6 Marque seus testes +## ![✔] 4.7 Marque seus testes **TL;DR:** Diferentes testes devem rodar em diferentes cenários: testes de rápidos, sem IO, devem ser executados quando um desenvolvedor salva ou faz commit em um arquivo, testes completos de ponta a ponta geralmente são executados quando uma nova solicitação de request é enviada, etc. Isso pode ser conseguido através da marcação de testes com palavras-chave como #cold #api #sanity. Assim você pode invocar o subconjunto desejado. Por exemplo, é desta forma que você invocaria apenas o grupo de sanity test usando o [Mocha](https://mochajs.org/): mocha --grep 'sanity' @@ -486,7 +511,7 @@ Todas as declarações acima false se feitas com `===`.

-## ![✔] 4.7 Verifique a cobertura de seu teste, isso te ajuda a identificar padrões incorretos de teste +## ![✔] 4.8 Verifique a cobertura de seu teste, isso te ajuda a identificar padrões incorretos de teste **TL;DR:** Ferramentas de cobertura de código como [Istanbul](https://github.com/istanbuljs/istanbuljs)/[NYC](https://github.com/istanbuljs/nyc), são ótimas por 3 motivos: elas são gratuitas (nenhum esforço é necessário para beneficiar esses relatórios), elas ajuda a identificar diminuição na cobertura de testes, e por último mas não menos importante, ela destacam a incompatibilidade de testes: olhando relatórios coloridos de cobertura de código, você pode notar, por exemplo, áreas de código que nunca são testadas como cláusulas catch (o que significa que os testes só invocam os caminhos felizes e não como o aplicativo se comporta em erros). Configure-o para falhas se a cobertura estiver abaixo de um certo limite. @@ -494,7 +519,7 @@ Todas as declarações acima false se feitas com `===`.

-## ![✔] 4.8 Inspecione pacotes desatualizados +## ![✔] 4.9 Inspecione pacotes desatualizados **TL;DR:** Use sua ferramenta preferida (por exemplo, 'npm outdated' ou [npm-check-updates](https://www.npmjs.com/package/npm-check-updates) para detectar pacotes instalados que estão desatualizados, injetar essa verificação em seu pipeline de CI e até mesmo fazer uma falha grave em um cenário grave. Por exemplo, um cenário grave pode ser quando um pacote instalado esteja há 5 commits atrás (por exemplo, a versão local é 1.3.1 e a versão no repositório é 1.3.8) ou está marcada como descontinuada pelo autor - mate o build e impeça a implantação desta versão. @@ -502,7 +527,7 @@ Todas as declarações acima false se feitas com `===`.

-## ![✔] 4.9 Use docker-compose para testes e2e +## ![✔] 4.10 Use docker-compose para testes e2e **TL;DR:** Teste de ponta a ponta (end to end, ou e2e), que inclui dados ativos, costumava ser o elo mais fraco do processo de CI, já que depende de vários serviços pesados como o banco de dados. O docker-compose deixa isso mamão com açúcar, criando um ambiente de produção usando um arquivo de texto simples e comandos fáceis. Isto permite criar todos os serviços dependentes, banco de dados e rede isolada para teste e2e. Por último mas não menos importante, ele pode manter um ambiente sem estado que é invocado antes de cada suíte de testes e é encerrado logo após. @@ -510,23 +535,33 @@ Todas as declarações acima false se feitas com `===`.

-## ![✔] 4.10 Refatore regularmente usando ferramentas de análise estática +## ![✔] 4.11 Refatore regularmente usando ferramentas de análise estática **TL;DR:** O uso de ferramentas de análise estática ajuda fornecendo maneiras objetivas de melhorar a qualidade do código e manter seu código sustentável. Você pode adicionar ferramentas de análise estática para seu build de Integração Contínua (CI) falhar quando encontre code smells. Seus principais pontos de vantagem sobre o linting são a abilidade de inspecionar a qualidade no contexto de múltiplos arquivos (por exemplo, detectar duplicidades), realizar análises avançadas (por exemplo, complexidade de código), e acompanhar histórico e progresso de problemas de código. Dois dexemplos de ferramentas que podem ser utilizadas são [Sonarqube](https://www.sonarqube.org/) (mais de 2.600 [stars](https://github.com/SonarSource/sonarqube)) e [Code Climate](https://codeclimate.com/) (mais de 1.500 [stars](https://github.com/codeclimate/codeclimate)). **Caso contrário:** Com qualidade de código ruim, bugs e desempenho sempre serão um problema que nenhuma nova biblioteca maravilhosa ou recursos de última geração podem corrigir. -🔗 [**Leia Mais: Refatoração!**](/sections/testingandquality/refactoring.brazilian-portuguese.md) +🔗 [**Leia Mais: Refatoração!**](./sections/testingandquality/refactoring.brazilian-portuguese.md)

-## ![✔] 4.11 Escolha cuidadosamente sua plataforma de Integração Contínua - CI (Jenkins vs CircleCI vs Travis vs Resto do mundo) +## ![✔] 4.12 Escolha cuidadosamente sua plataforma de Integração Contínua - CI (Jenkins vs CircleCI vs Travis vs Resto do mundo) **TL;DR:** Sua plataforma de integração contínua (CICD) irá hospedar todas as ferramentas de qualidade (por exemplo, teste, lint), então ela deve vir com um ecosistema de plugins arrebatador. O [Jenkins](https://jenkins.io/) costumava ser o padrão de muitos projetos, pois tem a maior comunidade, juntamente com uma poderosa plataforma, ao preço de configuração complexa que exige uma curva de aprendizado íngreme. Atualmente, ficou bem mais fácil para configurar uma solução de CI usando ferramentas SaaS como [CircleCI](https://circleci.com) e outras. Essas ferramentas permitem a criação de um pipeline de CI flexível sem o peso de gerenciar toda a infraestrutura. Eventualmente, é um perde e ganha entre robustez e velocidade - escolha seu lado com cuidado! **Caso contrário:** Escolher algum fornecedor de nicho pode fazer com que você fique engessado quando precisar de alguma personalização avançada. Por outro lado, escolher o Jenkins pode ser uma perda de tempo precioso na configuração da infraestrutura. -🔗 [**Leia Mais: Escolhendo a plataforma de CI**](/sections/testingandquality/citools.brazilian-portuguese.md) +🔗 [**Leia Mais: Escolhendo a plataforma de CI**](./sections/testingandquality/citools.brazilian-portuguese.md) + +

+ +## ![✔] 4.13 Teste seus 'middlewares' isoladamente + +**TL;DR:** quando um 'middleware' contém alguma lógica imensa que abrange muitas solicitações, vale a pena testá-lo isoladamente, sem ativar todo o framework. Isso pode ser facilmente alcançado por 'stubbing' e espionando os objetos {req, res, next} + +**Caso contrário:** Um bug no 'middleware Express' === um bug em todas ou na maioria das solicitações + +🔗 [**Read More: Test middlewares in isolation**](./sections/testingandquality/test-middlewares.md)


@@ -534,13 +569,13 @@ Todas as declarações acima false se feitas com `===`. # `5. Boas Práticas de Produção` -## ![✔] 5.1. Monitoramento! +## ![✔] 5.1. Monitoramento **TL;DR:** O monitoramento é um jogo de descobrir problemas antes que os clientes os encontrem - obviamente deve ser atribuída muita importância para isto. O mercado está sobrecarregado de ofertas, portanto, considere começar com a definição das métricas básicas que você deve seguir (sugestões minhas dentro), depois passe por recursos extras e escolha a solução que marca todas as caixas. Acesse o ‘Gist’ abaixo para uma visão geral das soluções. **Caso contrário:** Falha === clientes desapontados. Simples -🔗 [**Leia Mais: Monitoramento!**](/sections/production/monitoring.brazilian-portuguese.md) +🔗 [**Leia Mais: Monitoramento!**](./sections/production/monitoring.brazilian-portuguese.md)

@@ -550,7 +585,7 @@ Todas as declarações acima false se feitas com `===`. **Caso contrário:** Você acaba com uma caixa preta que é difícil de raciocinar, então você começa a reescrever todas as declarações de log para adicionar informações adicionais. -🔗 [**Leia Mais: Aumente a transparência usando smart logging**](/sections/production/smartlogging.brazilian-portuguese.md) +🔗 [**Leia Mais: Aumente a transparência usando smart logging**](./sections/production/smartlogging.brazilian-portuguese.md)

@@ -560,7 +595,7 @@ Todas as declarações acima false se feitas com `===`. **Caso contrário:** Seu único e pobre thread permanecerá ocupado fazendo tarefas de infra-estrutura em vez de lidar com o núcleo da sua aplicação e o desempenho certamente será degradado. -🔗 [**Leia Mais: Delegue tudo o que for possível (por exemplo, gzip, SSL) a um proxy reverso**](/sections/production/delegatetoproxy.brazilian-portuguese.md) +🔗 [**Leia Mais: Delegue tudo o que for possível (por exemplo, gzip, SSL) a um proxy reverso**](./sections/production/delegatetoproxy.brazilian-portuguese.md)

@@ -570,7 +605,7 @@ Todas as declarações acima false se feitas com `===`. **Caso contrário:** O QA testará completamente o código e aprovará uma versão que se comportará de maneira diferente na produção. Pior ainda, servidores diferentes no mesmo cluster de produção podem executar código diferente. -🔗 [**Leia Mais: Bloqueio de dependências**](/sections/production/lockdependencies.brazilian-portuguese.md) +🔗 [**Leia Mais: Bloqueio de dependências**](./sections/production/lockdependencies.brazilian-portuguese.md)

@@ -580,7 +615,7 @@ Todas as declarações acima false se feitas com `===`. **Caso contrário:** Rodar dezenas de instâncias sem uma estratégia clara e muitas ferramentas juntas (gerenciamento de cluster, docker, PM2) pode levar o DevOps ao caos. -🔗 [**Leia Mais: Poupe tempo de atividade do processo usando a ferramenta certa**](/sections/production/guardprocess.brazilian-portuguese.md) +🔗 [**Leia Mais: Poupe tempo de atividade do processo usando a ferramenta certa**](./sections/production/guardprocess.brazilian-portuguese.md)

@@ -590,7 +625,7 @@ Todas as declarações acima false se feitas com `===`. **Caso contrário:** Sua aplicação vai utilizar apenas 25% dos recursos disponíveis(!) ou talvez até menos. Note que um servidor típico possui 4 núcleos de processamento ou mais, o deploy ingênuo do Node.js utiliza apenas 1 (mesmo usando serviços de PaaS como AWS Beanstalk!) -🔗 [**Leia Mais: Utilize todos os núcleos do processador**](/sections/production/utilizecpu.brazilian-portuguese.md) +🔗 [**Leia Mais: Utilize todos os núcleos do processador**](./sections/production/utilizecpu.brazilian-portuguese.md)

@@ -600,7 +635,7 @@ Todas as declarações acima false se feitas com `===`. **Caso contrário:** Você perceberá que está realizando muitos “deploys de diagnóstico” - enviando código para produção apenas para extrair algumas informações para fins de diagnóstico. -🔗 [**Leia Mais: Crie um ‘endpoint de manutenção’**](/sections/production/createmaintenanceendpoint.brazilian-portuguese.md) +🔗 [**Leia Mais: Crie um ‘endpoint de manutenção’**](./sections/production/createmaintenanceendpoint.brazilian-portuguese.md)

@@ -610,7 +645,7 @@ Todas as declarações acima false se feitas com `===`. **Caso contrário:** Você pode gastar muito esforço medindo o desempenho e os tempos de inatividade da API, provavelmente você nunca saberá quais são suas partes de código mais lentas no cenário do mundo real e como elas afetam o UX. -🔗 [**Leia Mais: Descubra erros e tempo de inatividade usando produtos APM**](/sections/production/apmproducts.brazilian-portuguese.md) +🔗 [**Leia Mais: Descubra erros e tempo de inatividade usando produtos APM**](./sections/production/apmproducts.brazilian-portuguese.md)

@@ -620,7 +655,7 @@ Todas as declarações acima false se feitas com `===`. **Caso contrário:** Uma pessoa fera em TI/DevOps não salvará um sistema mal escrito. -🔗 [**Leia Mais: Deixe seu código pronto para produção**](/sections/production/productioncode.brazilian-portuguese.md) +🔗 [**Leia Mais: Deixe seu código pronto para produção**](./sections/production/productioncode.brazilian-portuguese.md)

@@ -630,7 +665,7 @@ Todas as declarações acima false se feitas com `===`. **Caso contrário:** A memória de seus processos pode vazar cem megabytes por dia, assim como aconteceu no [Walmart](https://www.joyent.com/blog/walmart-node-js-memory-leak). -🔗 [**Leia Mais: Meça e proteja o uso de memória**](/sections/production/measurememory.brazilian-portuguese.md) +🔗 [**Leia Mais: Meça e proteja o uso de memória**](./sections/production/measurememory.brazilian-portuguese.md)

@@ -640,7 +675,7 @@ Todas as declarações acima false se feitas com `===`. **Caso contrário:** Seu único thread do Node ficará ocupado fazendo streaming the centenas de arquivos de html/imagens/angular/react ao invés de alocar todo seu recurso para a tarefa que ele foi designado - servir conteúdo dinâmico. -🔗 [**Leia Mais: Deixe seus recursos de frontend fora do Node**](/sections/production/frontendout.brazilian-portuguese.md) +🔗 [**Leia Mais: Deixe seus recursos de frontend fora do Node**](./sections/production/frontendout.brazilian-portuguese.md)

@@ -650,7 +685,7 @@ Todas as declarações acima false se feitas com `===`. **Caso contrário:** Falha em um determinado servidor resultará em tempo de inatividade da aplicação, em vez de apenas matar uma máquina defeituosa. Além do mais, dimensionar a elasticidade será mais desafiador devido à dependência de um servidor específico. -🔗 [**Leia Mais: Seja stateless, mate seus Servidores quase todos os dias**](/sections/production/bestateless.brazilian-portuguese.md) +🔗 [**Leia Mais: Seja stateless, mate seus Servidores quase todos os dias**](./sections/production/bestateless.brazilian-portuguese.md)

@@ -660,7 +695,7 @@ Todas as declarações acima false se feitas com `===`. **Caso contrário:** Manter seu código limpo com vulnerabilidades sem ferramentas dedicadas exigirá o acompanhamento constante de publicações online sobre novas ameaças. Bem entendiante. -🔗 [**Leia Mais: Utilize ferramentas que detectam vulnerabilidades automaticamente**](/sections/production/detectvulnerabilities.brazilian-portuguese.md) +🔗 [**Leia Mais: Utilize ferramentas que detectam vulnerabilidades automaticamente**](./sections/production/detectvulnerabilities.brazilian-portuguese.md)

@@ -670,7 +705,7 @@ Todas as declarações acima false se feitas com `===`. **Caso contrário:** Observar um log de erros de produção sem o contexto - o que aconteceu antes - torna muito mais difícil e mais lento raciocinar sobre o problema. -🔗 [**Leia Mais: Atribua ‘TransactionId’ para cada declaração de log**](/sections/production/assigntransactionid.brazilian-portuguese.md) +🔗 [**Leia Mais: Atribua ‘TransactionId’ para cada declaração de log**](./sections/production/assigntransactionid.brazilian-portuguese.md)

@@ -680,7 +715,7 @@ Todas as declarações acima false se feitas com `===`. **Caso contrário:** Omitir esta simples propriedade pode degradar muito o desempenho. Por exemplo, ao utilizar o Express para renderização do lado do servidor, omitir o NODE_ENV o torna mais lento! -🔗 [**Leia Mais: Defina NODE_ENV=production**](/sections/production/setnodeenv.brazilian-portuguese.md) +🔗 [**Leia Mais: Defina NODE_ENV=production**](./sections/production/setnodeenv.brazilian-portuguese.md)

@@ -698,7 +733,7 @@ Todas as declarações acima false se feitas com `===`. **Caso contrário:** Bugs recentemente descobertos e vulnerabilidades podem ser usados para explorar uma aplicação em produção, e sua aplicação pode se tornar incompatível com vários módulos e mais difícil de manter. -🔗 [**Leia Mais: Use uma versão LTS do Node.js**](/sections/production/LTSrelease.brazilian-portuguese.md) +🔗 [**Leia Mais: Use uma versão LTS do Node.js**](./sections/production/LTSrelease.brazilian-portuguese.md)

@@ -708,7 +743,17 @@ Todas as declarações acima false se feitas com `===`. **Caso contrário:** Aplicações manipulando o roteamento de log === difícil de dimensionar, perda de logs, separação ruim de preocupações. -🔗 [**Leia Mais: Roteamento de Logs**](/sections/production/logrouting.brazilian-portuguese.md) +🔗 [**Leia Mais: Roteamento de Logs**](./sections/production/logrouting.brazilian-portuguese.md) + +

+ +## ![✔] 5.19. Instale seus pacotes com `npm ci` + +**TL;DR:** Você precisa ter certeza de que o código de produção usa a versão exata dos pacotes que você realizou os testes. Execute `npm ci` para fazer estritamente uma instalação limpa de suas dependências correspondentes do package.json e do package-lock.json. O uso desse comando é recomendado em ambientes automatizados, como pipelines de integração contínua. + +**Caso contrário:** o QA testará completamente o código e aprovará uma versão que se comportará de maneira diferente em produção. Pior ainda, diferentes servidores no mesmo cluster de produção podem executar códigos diferentes. + +🔗 [**Read More: Use npm ci**](./sections/production/installpackageswithnpmci.md)


@@ -764,7 +809,7 @@ Todas as declarações acima false se feitas com `===`. **Caso contrário:** A entrada de usuários não validados pode levar à injeção do operador ao trabalhar com MongoDB para NoSQL e não usar um sistema próprio ou ORM irão permitir facilmente um ataque de SQL injection, criando uma grande vulnerabilidade. -🔗 [**Leia Mais: Prevenção de query injection usando bibliotecas de ORM/ODM**](/sections/security/ormodmusage.brazilian-portuguese.md) +🔗 [**Leia Mais: Prevenção de query injection usando bibliotecas de ORM/ODM**](./sections/security/ormodmusage.brazilian-portuguese.md)

@@ -772,7 +817,7 @@ Todas as declarações acima false se feitas com `===`. **TL;DR:** Esta é uma coleção de conselhos de segurança que não estão relacionadas diretamente com Node.js - a implementação do Node não é muito diferente comparado a outras linguagens. Clique em “leia mais” para dar uma olhada. -🔗 [**Leia Mais: Boas práticas comuns de segurança**](/sections/security/commonsecuritybestpractices.brazilian-portuguese.md) +🔗 [**Leia Mais: Boas práticas comuns de segurança**](./sections/security/commonsecuritybestpractices.brazilian-portuguese.md)

@@ -784,7 +829,7 @@ Todas as declarações acima false se feitas com `===`. **Caso contrário:** Invasores podem realizar ataques diretos aos usuários de sua aplicação, levando a grandes vulnerabilidades de segurança. -🔗 [**Leia Mais: Usando headers seguros em sua aplicação**](/sections/security/secureheaders.brazilian-portuguese.md) +🔗 [**Leia Mais: Usando headers seguros em sua aplicação**](./sections/security/secureheaders.brazilian-portuguese.md)

@@ -796,7 +841,7 @@ Todas as declarações acima false se feitas com `===`. **Caso contrário:** Um invasor pode detectar seu framework web e atacar todas suas vulnerabilidades. -🔗 [**Leia Mais: Segurança de dependências**](/sections/security/dependencysecurity.brazilian-portuguese.md) +🔗 [**Leia Mais: Segurança de dependências**](./sections/security/dependencysecurity.brazilian-portuguese.md)

@@ -808,7 +853,7 @@ Todas as declarações acima false se feitas com `===`. **Caso contrário:** Senhas ou segredos que são persistidos sem o uso de uma função segura, são vulneráveis a força bruta e ataques de dicionário que levarão eventualmente à sua divulgação. -🔗 [**Leia Mais: Use o Bcrypt**](/sections/security/bcryptpasswords.brazilian-portuguese.md) +🔗 [**Leia Mais: Use o Bcrypt**](./sections/security/bcryptpasswords.brazilian-portuguese.md)

@@ -820,7 +865,7 @@ Todas as declarações acima false se feitas com `===`. **Caso contrário:** Um invasor pode armazenar um código JavaScript malicioso em seu banco de dados, que será enviado para os clientes. -🔗 [**Leia Mais: Evite saídas**](/sections/security/escape-output.brazilian-portuguese.md) +🔗 [**Leia Mais: Evite saídas**](./sections/security/escape-output.brazilian-portuguese.md)

@@ -832,7 +877,7 @@ Todas as declarações acima false se feitas com `===`. **Caso contrário:** Sua generosidade e abordagem permissiva aumentam muito a superfície de ataque e incentivam o invasor a experimentar muitas entradas até encontrar alguma combinação para travar a aplicação. -🔗 [**Leia Mais: Valide os esquemas de entrada JSON**](/sections/security/validation.brazilian-portuguese.md) +🔗 [**Leia Mais: Valide os esquemas de entrada JSON**](./sections/security/validation.brazilian-portuguese.md)

@@ -844,7 +889,7 @@ Todas as declarações acima false se feitas com `===`. **Caso contrário:** Tokens expirados ou extraviados, podem ser usados maliciosamente por terceiros para acessar uma aplicação e para representar o proprietário do token. -🔗 [**Leia Mais: Blacklist de JSON Web Tokens**](/sections/security/expirejwt.brazilian-portuguese.md) +🔗 [**Leia Mais: Blacklist de JSON Web Tokens**](./sections/security/expirejwt.brazilian-portuguese.md)

@@ -859,7 +904,7 @@ Todas as declarações acima false se feitas com `===`. **Caso contrário:** Um invasor pode emitir tentativas ilimitadas de senha automatizada para obter acesso a contas com privilégios em uma aplicação. -🔗 [**Leia Mais: Limitando a taxa de login**](/sections/security/login-rate-limit.brazilian-portuguese.md) +🔗 [**Leia Mais: Limitando a taxa de login**](./sections/security/login-rate-limit.brazilian-portuguese.md)

@@ -871,7 +916,7 @@ Todas as declarações acima false se feitas com `===`. **Caso contrário:** Um invasor que consiga executar um script no servidor obtém poder ilimitado sobre a máquina local (por exemplo, alterar o iptable e redirecionar o tráfego para seu servidor). -🔗 [**Leia Mais: Rode o Node.js com um usuário não raiz**](/sections/security/non-root-user.brazilian-portuguese.md) +🔗 [**Leia Mais: Rode o Node.js com um usuário não raiz**](./sections/security/non-root-user.brazilian-portuguese.md)

@@ -883,7 +928,7 @@ Todas as declarações acima false se feitas com `===`. **Caso contrário:** Sua aplicação terá que lidar com solicitações grandes, incapazes de processar o outro trabalho importante que ele precisa realizar, o que leva a implicações de desempenho e vulnerabilidade em relação a ataques DOS. -🔗 [**Leia Mais: Limite o tamanho dos payloads**](/sections/security/requestpayloadsizelimit.brazilian-portuguese.md) +🔗 [**Leia Mais: Limite o tamanho dos payloads**](./sections/security/requestpayloadsizelimit.brazilian-portuguese.md)

@@ -895,7 +940,7 @@ Todas as declarações acima false se feitas com `===`. **Caso contrário:** o código JavaScript malicioso encontra um caminho para um texto passado para o eval ou outras funções de avaliação em tempo real da linguagem JavaScript, e terá acesso total às permissões do JavaScript na página. Essa vulnerabilidade geralmente se manifesta como um ataque XSS. -🔗 [**Leia Mais: Evite instruções eval do JavaScript**](/sections/security/avoideval.brazilian-portuguese.md) +🔗 [**Leia Mais: Evite instruções eval do JavaScript**](./sections/security/avoideval.brazilian-portuguese.md)

@@ -907,7 +952,7 @@ Todas as declarações acima false se feitas com `===`. **Caso contrário:** Expressões regulares mal escritas podem ser suscetíveis a ataques de Regular Expresssion DoS, que irão bloquear completamente o loop de eventos. Por exemplo, o popular pacote `moment` foi encontrado com vulnerabilidades de uso de RegEx maliciosos em novembro de 2017. -🔗 [**Leia Mais: Evite RegEx maliciosos**](/sections/security/regex.brazilian-portuguese.md) +🔗 [**Leia Mais: Evite RegEx maliciosos**](./sections/security/regex.brazilian-portuguese.md)

@@ -919,7 +964,7 @@ Todas as declarações acima false se feitas com `===`. **Caso contrário:** A entrada de usuário mal-intencionada pode encontrar o caminho para um parâmetro usado para require de arquivos adulterados, por exemplo, um arquivo carregado anteriormente no sistema de arquivos ou para acessar arquivos de sistema já existentes. -🔗 [**Leia Mais: Carregamento seguro de módulos**](/sections/security/safemoduleloading.brazilian-portuguese.md) +🔗 [**Leia Mais: Carregamento seguro de módulos**](./sections/security/safemoduleloading.brazilian-portuguese.md)

@@ -931,7 +976,7 @@ Todas as declarações acima false se feitas com `===`. **Caso contrário:** Um plugin pode atacar através de uma infinita variedade de opções, como loops infinitos, sobrecarga de memória e acesso a variáveis sensíveis do ambiente de processo. -🔗 [**Leia Mais: Rode códigos não seguros em uma sandbox**](/sections/security/sandbox.brazilian-portuguese.md) +🔗 [**Leia Mais: Rode códigos não seguros em uma sandbox**](./sections/security/sandbox.brazilian-portuguese.md)

@@ -943,7 +988,7 @@ Todas as declarações acima false se feitas com `===`. **Caso contrário:** O uso ingênuo de processos filhos pode resultar na execução de comandos remotos ou em ataques de shell injection, devido à entrada do usuário mal-intencionado passada para um comando do sistema não-autorizado. -🔗 [**Leia Mais: Tenha cautela ao trabalhar com processos filhos**](/sections/security/childprocesses.brazilian-portuguese.md) +🔗 [**Leia Mais: Tenha cautela ao trabalhar com processos filhos**](./sections/security/childprocesses.brazilian-portuguese.md)

@@ -955,7 +1000,7 @@ Todas as declarações acima false se feitas com `===`. **Caso contrário:** Detalhes confidenciais da aplicação como caminhos e arquivos do servidor, módulos de terceiros em uso e outros workflows internos da aplicação poderiam ser explorados e expostos por um invasor. -🔗 [**Leia Mais: Oculte detalhes de erros dos usuários**](/sections/security/hideerrors.brazilian-portuguese.md) +🔗 [**Leia Mais: Oculte detalhes de erros dos usuários**](./sections/security/hideerrors.brazilian-portuguese.md)

@@ -977,7 +1022,7 @@ Todas as declarações acima false se feitas com `===`. **Caso contrário:** Cookies podem ser enviados através de conexões não seguras, e um hacker pode usar a sessão do usuário para identificar o framework utilizado na aplicação, bem como vulnerabilidades específicas do módulo. -🔗 [**Leia Mais: Segurança de cookies e sessões**](/sections/security/sessions.brazilian-portuguese.md) +🔗 [**Leia Mais: Segurança de cookies e sessões**](./sections/security/sessions.brazilian-portuguese.md)

@@ -999,7 +1044,7 @@ Todas as declarações acima false se feitas com `===`. **Caso contrário:** Se um invasor descobrir que você não está validando informações externas fornecidas pelo usuário, ele poderá explorar essa vulnerabilidade postando links especialmente em fóruns, mídias sociais e outros locais públicos para que os usuários cliquem. -🔗 [**Leia Mais: Impeça redirecionamentos não seguros**](/sections/security/saferedirects.brazilian-portuguese.md) +🔗 [**Leia Mais: Impeça redirecionamentos não seguros**](./sections/security/saferedirects.brazilian-portuguese.md)

@@ -1011,7 +1056,7 @@ Todas as declarações acima false se feitas com `===`. **Caso contrário:** As chaves, as senhas ou outros segredos da API do seu projeto estão sujeitos a abusos por qualquer pessoa que os encontre, o que pode resultar em perda financeira, falsificação de identidade e outros riscos. -🔗 [**Leia Mais: Evite publicar segredos**](/sections/security/avoid_publishing_secrets.brazilian-portuguese.md) +🔗 [**Leia Mais: Evite publicar segredos**](./sections/security/avoid_publishing_secrets.brazilian-portuguese.md)


⬆ Voltar ao topo

@@ -1027,7 +1072,7 @@ Tenha em mente que, com a introdução do novo motor V8 juntamente com os novos **Caso contrário:** Você terá que manter projetos de menor desempenho onde você poderia simplesmente ter usado o que **já estava** disponível ou lidar com mais algumas linhas em troca de mais alguns arquivos. -🔗 [**Leia Mais: Prefira métodos nativos ao invés de utilitários do usuário como Lodash**](/sections/performance/nativeoverutil.brazilian-portuguese.md) +🔗 [**Leia Mais: Prefira métodos nativos ao invés de utilitários do usuário como Lodash**](./sections/performance/nativeoverutil.brazilian-portuguese.md)


@@ -1043,18 +1088,18 @@ Todas as traduções são contribuições da comunidade. Nós ficaremos felizes ### Traduções concluídas -- ![BR](/assets/flags/BR.png) [Português Brasileiro](/README.brazilian-portuguese.md) - Cortesia de [Marcelo Melo](https://github.com/marcelosdm) -- ![CN](/assets/flags/CN.png) [Chinês](README.chinese.md) - Cortesia de [Matt Jin](https://github.com/mattjin) +- ![BR](./assets/flags/BR.png) [Português Brasileiro](./README.brazilian-portuguese.md) - Cortesia de [Marcelo Melo](https://github.com/marcelosdm) +- ![CN](./assets/flags/CN.png) [Chinês](README.chinese.md) - Cortesia de [Matt Jin](https://github.com/mattjin) +- ![EU](./assets/flags/EU.png) [Vasco](README.basque.md) - Cortesia de [Ane Diaz de Tuesta](https://github.com/anediaz) & Joxefe Diaz de Tuesta ### Traduções em andamento -- ![FR](/assets/flags/FR.png) [Francês](https://github.com/gaspaonrocks/nodebestpractices/blob/french-translation/README.french.md) ([Discussão](https://github.com/goldbergyoni/nodebestpractices/issues/129)) -- ![HE](/assets/flags/HE.png) Hebraico ([Discussão](https://github.com/goldbergyoni/nodebestpractices/issues/156)) -- ![KR](/assets/flags/KR.png) [Coreano](https://github.com/goldbergyoni/nodebestpractices/blob/korean-translation/README.md) ([Discussão](https://github.com/goldbergyoni/nodebestpractices/issues/94)) -- ![RU](/assets/flags/RU.png) [Russo](https://github.com/goldbergyoni/nodebestpractices/blob/russian-translation/README.russian.md) ([Discussão](https://github.com/goldbergyoni/nodebestpractices/issues/454)) -- ![ES](/assets/flags/ES.png) [Espanhol](https://github.com/goldbergyoni/nodebestpractices/blob/spanish-translation/README.spanish.md) ([Discussão](https://github.com/goldbergyoni/nodebestpractices/issues/95)) -- ![TR](/assets/flags/TR.png) Turco ([Discussão](https://github.com/goldbergyoni/nodebestpractices/issues/139)) -- ![EU](/assets/flags/EU.png) [Vasco](README.basque.md) - Cortesia de [Ane Diaz de Tuesta](https://github.com/anediaz) & Joxefe Diaz de Tuesta ([Discussão](https://github.com/goldbergyoni/nodebestpractices/issues/842)) +- ![FR](./assets/flags/FR.png) [Francês](https://github.com/gaspaonrocks/nodebestpractices/blob/french-translation/README.french.md) ([Discussão](https://github.com/goldbergyoni/nodebestpractices/issues/129)) +- ![HE](./assets/flags/HE.png) Hebraico ([Discussão](https://github.com/goldbergyoni/nodebestpractices/issues/156)) +- ![KR](./assets/flags/KR.png) [Coreano](https://github.com/goldbergyoni/nodebestpractices/blob/korean-translation/README.md) ([Discussão](https://github.com/goldbergyoni/nodebestpractices/issues/94)) +- ![RU](./assets/flags/RU.png) [Russo](https://github.com/goldbergyoni/nodebestpractices/blob/russian-translation/README.russian.md) ([Discussão](https://github.com/goldbergyoni/nodebestpractices/issues/454)) +- ![ES](./assets/flags/ES.png) [Espanhol](https://github.com/goldbergyoni/nodebestpractices/blob/spanish-translation/README.spanish.md) ([Discussão](https://github.com/goldbergyoni/nodebestpractices/issues/95)) +- ![TR](./assets/flags/TR.png) Turco ([Discussão](https://github.com/goldbergyoni/nodebestpractices/issues/139))

@@ -1062,7 +1107,7 @@ Todas as traduções são contribuições da comunidade. Nós ficaremos felizes Conheça os membros do comitê diretivo - as pessoas que trabalham juntas para fornecer orientação e direção futura para o projeto. Além disso, cada membro do comitê lidera um projeto rastreado em nossos [projetos do Github](https://github.com/goldbergyoni/nodebestpractices/projects). - + [Yoni Goldberg](https://github.com/goldbergyoni) @@ -1072,7 +1117,7 @@ Consultor de Node.js independente, que trabalha com clientes nos EUA, Europa e I
- + [Bruno Scheufler](https://github.com/BrunoScheufler) @@ -1081,7 +1126,7 @@ Consultor de Node.js independente, que trabalha com clientes nos EUA, Europa e I
- + [Kyle Martin](https://github.com/js-kyle) @@ -1091,7 +1136,7 @@ Full Stack Developer e Engenheiro de Confiabilidade de Sites com sede na Nova Ze
- + [Sagir Khan](https://github.com/sagirk) @@ -1106,15 +1151,15 @@ Especialista profundo em JavaScript e seu ecossistema - React, Node.js, MongoDB, Obrigado a todos nossos colaboradores! 🙏 -Nossos colaboradores são membros que estão contribuindo com o repositório em base regular, sugerindo novas práticas recomendadas, triando problemas, analisando solicitações de pull e muito mais. Se você estiver interessado em nos ajudar a orientar milhares de pessoas a criar melhores aplicações Node.js, leia nossas [diretrizes de colaborador](/.operations/CONTRIBUTING.md) 🎉 +Nossos colaboradores são membros que estão contribuindo com o repositório em base regular, sugerindo novas práticas recomendadas, triando problemas, analisando solicitações de pull e muito mais. Se você estiver interessado em nos ajudar a orientar milhares de pessoas a criar melhores aplicações Node.js, leia nossas [diretrizes de colaborador](./.operations/CONTRIBUTING.md) 🎉 -| | | +| | | | :---------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------: | | [Ido Richter (Founder)](https://github.com/idori) | [Keith Holliday](https://github.com/TheHollidayInn) | ### Colaboradores anteriores -| | +| | | :-------------------------------------------------------------------------------------------------------------------------: | | [Refael Ackermann](https://github.com/refack) | @@ -1122,6 +1167,6 @@ Nossos colaboradores são membros que estão contribuindo com o repositório em ## Thank You Notes -We appreciate any contribution, from a single word fix to a new best practice. View our contributors and [contributing documentation here!](CONTRIBUTORS.md) +We appreciate any contribution, from a single word fix to a new best practice. View our contributors and [contributing documentation here!](./README.md#contributors-)


diff --git a/README.chinese.md b/README.chinese.md index 8d3023025..44f39e18b 100644 --- a/README.chinese.md +++ b/README.chinese.md @@ -9,15 +9,16 @@
- 82 items Last update: June 5, 2019 Updated for Node 12.4.0 LTS + 82 items Last update: June 5, 2019 Updated for Node 12.4.0 LTS

- [![nodepractices](/assets/images/twitter-s.png)](https://twitter.com/nodepractices/) **Follow us on Twitter!** [**@nodepractices**](https://twitter.com/nodepractices/) + [![nodepractices](./assets/images/twitter-s.png)](https://twitter.com/nodepractices/) **Follow us on Twitter!** [**@nodepractices**](https://twitter.com/nodepractices/)
-# 欢迎! 首先您应该知道的三件事情: +# 欢迎! 首先您应该知道的三件事情 + **1. 当您读到这里,实际上您读了很多关于Node.js的优秀文章 -** 这是对Node.js最佳实践中排名最高的内容的总结和分享 **2. 这里是最大的汇集,且每周都在增长 -** 当前,超过50个最佳实现,样式指南,架构建议已经呈现。每天都有新的issue和PR被创建,以使这本在线书籍不断更新。我们很乐于见到您能在这里做出贡献,不管是修复一些代码的错误,或是提出绝妙的新想法。请查看我们的[milestones](https://github.com/goldbergyoni/nodebestpractices/milestones?direction=asc&sort=due_date&state=open) @@ -27,6 +28,7 @@


## [目录](#table-of-contents) + 1. [项目结构实践 (5) ](#1-project-structure-practices) 2. [异常处理实践 (11) ](#2-error-handling-practices) 3. [编码规范实践 (12) ](#3-code-style-practices) @@ -35,7 +37,6 @@ 6. :star: 新: [安全实践(23)](#6-security-best-practices) 7. Performance Practices ([coming soon](https://github.com/goldbergyoni/nodebestpractices/milestones?direction=asc&sort=due_date&state=open)) -


1. 项目结构实践

@@ -45,7 +46,7 @@ **否则:** 当编写新需求的开发人员逐步意识到他所做改变的影响,并担心会破坏其他的依赖模块 - 部署会变得更慢,风险更大。当所有业务逻辑没有被分开,这也会被认为很难扩展 -🔗 [**更多: 组件结构**](/sections/projectstructre/breakintcomponents.chinese.md) +🔗 [**更多: 组件结构**](./sections/projectstructre/breakintcomponents.chinese.md)

@@ -55,7 +56,7 @@ **否则:** 对于混淆了网络层和其它层的应用,将不易于测试,执行CRON的任务,其它非-Express的调用者无法使用 -🔗 [**更多: 应用分层**](/sections/projectstructre/createlayers.chinese.md) +🔗 [**更多: 应用分层**](./sections/projectstructre/createlayers.chinese.md)

@@ -65,7 +66,7 @@ **否则:** 您将不得不重造部署和依赖的轮子 -🔗 [**更多: 通过需求构建**](/sections/projectstructre/wraputilities.chinese.md) +🔗 [**更多: 通过需求构建**](./sections/projectstructre/wraputilities.chinese.md)

@@ -75,18 +76,17 @@ **否则:** 您的API将只能通过HTTP的调用进行测试(慢,并且很难产生测试覆盖报告)。维护一个有着上百行代码的文件也不是一个令人开心的事情。 -🔗 [**更多: 分离 Express 'app' and 'server'**](/sections/projectstructre/separateexpress.chinese.md) +🔗 [**更多: 分离 Express 'app' and 'server'**](./sections/projectstructre/separateexpress.chinese.md)

## ![✔] 1.5 使用易于设置环境变量,安全和分级的配置 - **TL;DR:** 一个完美无瑕的配置安装应该确保 (a) 元素可以从文件中,也可以从环境变量中读取 (b) 密码排除在提交的代码之外 (c) 为了易于检索,配置是分级的。仅有几个包可以满足这样的条件,比如[rc](https://www.npmjs.com/package/rc), [nconf](https://www.npmjs.com/package/nconf), [config](https://www.npmjs.com/package/config) 和 [convict](https://www.npmjs.com/package/convict)。 **否则:** 不能满足任意的配置要求将会使开发,运维团队,或者两者,易于陷入泥潭。 -🔗 [**更多: 配置最佳实践**](/sections/projectstructre/configguide.chinese.md) +🔗 [**更多: 配置最佳实践**](./sections/projectstructre/configguide.chinese.md)


@@ -100,7 +100,7 @@ **否则:** Node.js回调特性, function(err, response), 是导致不可维护代码的一个必然的方式。究其原因,是由于混合了随意的错误处理代码,臃肿的内嵌,蹩脚的代码模式。 -🔗 [**更多: 避免回调**](/sections/errorhandling/asyncerrorhandling.chinese.md) +🔗 [**更多: 避免回调**](./sections/errorhandling/asyncerrorhandling.chinese.md)

@@ -108,10 +108,9 @@ **TL;DR:** 很多人抛出异常使用字符串类型或一些自定义类型 - 这会导致错误处理逻辑和模块间的调用复杂化。是否您reject一个promise,抛出异常或发出(emit)错误 - 使用内建的错误对象将会增加设计一致性,并防止信息的丢失。 - **否则:** 调用某些模块,将不确定哪种错误类型会返回 - 这将会使恰当的错误处理更加困难。更坏的情况是,使用特定的类型描述错误,会导致重要的错误信息缺失,比如stack trace! -🔗 [**更多: 使用内建错误对象**](/sections/errorhandling/useonlythebuiltinerror.chinese.md) +🔗 [**更多: 使用内建错误对象**](./sections/errorhandling/useonlythebuiltinerror.chinese.md)

@@ -121,7 +120,7 @@ **否则:** 当一个错误产生的时候,您总是得重启应用,但为什么要让 ~5000 个在线用户不能访问,仅仅是因为一个细微的,可以预测的,运行时错误?相反的方案,也不完美 – 当未知的问题(程序问题)产生的时候,使应用依旧可以访问,可能导致不可预测行为。区分两者会使处理更有技巧,并在给定的上下文下给出一个平衡的对策。 -🔗 [**更多: 运行错误和程序设计错误**](/sections/errorhandling/operationalvsprogrammererror.chinese.md) +🔗 [**更多: 运行错误和程序设计错误**](./sections/errorhandling/operationalvsprogrammererror.chinese.md)

@@ -131,7 +130,7 @@ **否则:** 错误处理的逻辑不放在一起将会导致代码重复和非常可能不恰当的错误处理。 -🔗 [**更多: 集中处理错误**](/sections/errorhandling/centralizedhandling.chinese.md) +🔗 [**更多: 集中处理错误**](./sections/errorhandling/centralizedhandling.chinese.md)

@@ -141,8 +140,7 @@ **否则:** 任何API的客户端可能决定崩溃并重启,仅仅因为它收到一个不能处理的错误。注意:API的调用者可能是你(在微服务环境中非常典型)。 - -🔗 [**更多: 使用Swagger记录错误**](/sections/errorhandling/documentingusingswagger.chinese.md) +🔗 [**更多: 使用Swagger记录错误**](./sections/errorhandling/documentingusingswagger.chinese.md)

@@ -152,32 +150,27 @@ **否则:** 当一个未知的异常被抛出,意味着某些对象包含错误的状态(例如某个全局事件发生器由于某些内在的错误,不在产生事件),未来的请求可能失败或者行为异常。 -🔗 [**更多: 停掉服务**](/sections/errorhandling/shuttingtheprocess.chinese.md) +🔗 [**更多: 停掉服务**](./sections/errorhandling/shuttingtheprocess.chinese.md)

- - ## ![✔] 2.7 使用一个成熟的日志工具提高错误的可见性 **TL;DR:** 一系列成熟的日志工具,比如Winston,Bunyan和Log4J,会加速错误的发现和理解。忘记console.log吧。 **否则:** 浏览console的log,和不通过查询工具或者一个好的日志查看器,手动浏览繁琐的文本文件,会使你忙于工作到很晚。 -🔗 [**更多: 使用好用的日志工具**](/sections/errorhandling/usematurelogger.chinese.md) - +🔗 [**更多: 使用好用的日志工具**](./sections/errorhandling/usematurelogger.chinese.md)

- ## ![✔] 2.8 使用你最喜欢的测试框架测试错误流 **TL;DR:** 无论专业的自动化测试或者简单的手动开发测试 - 确保您的代码不仅满足正常的场景,而且处理并且返回正确的错误。测试框架,比如Mocha & Chai可以非常容易的处理这些问题(在"Gist popup"中查看代码实例) 。 **否则:** 没有测试,不管自动还是手动,您不可能依赖代码去返回正确的错误。而没有可以理解的错误,那将毫无错误处理可言。 - -🔗 [**更多: 测试错误流向**](/sections/errorhandling/testingerrorflows.chinese.md) +🔗 [**更多: 测试错误流向**](./sections/errorhandling/testingerrorflows.chinese.md)

@@ -187,20 +180,17 @@ **否则:** 您花了很多的力气在测量API的性能和错误,但可能您从来没有意识到真实场景下您最慢的代码块和他们对UX的影响。 - -🔗 [**更多: 使用APM产品**](/sections/errorhandling/apmproducts.chinese.md) +🔗 [**更多: 使用APM产品**](./sections/errorhandling/apmproducts.chinese.md)

- ## ![✔] 2.10 捕获未处理的promise rejections **TL;DR:** 任何在promise中被抛出的异常将被收回和遗弃,除非开发者没有忘记去明确的处理。即使您的代码调用的是process.uncaughtException!解决这个问题可以注册到事件process.unhandledRejection。 **否则:** 您的错误将被回收,无踪迹可循。没有什么可以需要考虑。 - -🔗 [**更多: 捕获未处理的promise rejection**](/sections/errorhandling/catchunhandledpromiserejection.chinese.md) +🔗 [**更多: 捕获未处理的promise rejection**](./sections/errorhandling/catchunhandledpromiserejection.chinese.md)

@@ -210,7 +200,7 @@ **否则:** 考虑这种情况 – 您的功能期望一个数字参数 “Discount” ,然而调用者忘记传值,之后在您的代码中检查是否 Discount!=0 (允许的折扣值大于零),这样它将允许用户使用一个折扣。OMG,多么不爽的一个漏洞。你能明白吗? -🔗 [**更多: 快速查错**](/sections/errorhandling/failfast.chinese.md) +🔗 [**更多: 快速查错**](./sections/errorhandling/failfast.chinese.md)


@@ -239,6 +229,7 @@ **TL;DR:** 代码块的第一个大括号应该和声明的起始保持在同一行中。 ### 代码示例 + ```javascript // 建议 function someFunction() { @@ -280,7 +271,8 @@ **否则:** JavaScript是世界上唯一一门不需要实例化,就可以直接调用构造函数("Class")的编码语言。因此,类和函数的构造函数由采用UpperCamelCase开始区分。 -### 代码示例 ### +### 3.6 代码示例 + ```javascript // 使用UpperCamelCase命名类名 class SomeClassExample () { @@ -326,7 +318,8 @@ **否则:** 更改文件内部结构或签名可能会破坏与客户端的接口。 -### 代码示例 +### 3.9 代码示例 + ```javascript // 建议 module.exports.SMSProvider = require('./SMSProvider'); @@ -339,14 +332,14 @@

- ## ![✔] 3.10 使用 `===` 操作符 **TL;DR:** 对比弱等于 `==`,优先使用严格的全等于 `===` 。`==`将在它们转换为普通类型后比较两个变量。在 `===` 中没有类型转换,并且两个变量必须是相同的类型。 **否则:** 与 `==` 操作符比较,不相等的变量可能会返回true。 -### 代码示例 +### 3.10 代码示例 + ```javascript '' == '0' // false 0 == '' // true @@ -361,6 +354,7 @@ null == undefined // true ' \t\r\n ' == 0 // true ``` + 如果使用`===`, 上面所有语句都将返回 false。

@@ -383,12 +377,10 @@ null == undefined // true 🔗 [**更多: 这是拥抱箭头函数的时刻**](https://medium.com/javascript-scene/familiarity-bias-is-holding-you-back-its-time-to-embrace-arrow-functions-3d37e1a9bb75) -


⬆ 返回顶部

-

4. 测试和总体的质量实践

## ![✔] 4.1 至少,编写API(组件)测试 @@ -405,7 +397,6 @@ null == undefined // true **否则:** 您可能让一些反模式和易受攻击的代码传递到您的生产环境中。 -

## ![✔] 4.3 仔细挑选您的持续集成(CI)平台 @@ -414,7 +405,7 @@ null == undefined // true **否则:** 一旦您需要一些高级定制,选择一些细分市场供应商可能会让您停滞不前。另一方面,伴随着jenkins,可能会在基础设施设置上浪费宝贵的时间。 -🔗 [**更多: 挑选 CI 平台**](/sections/testingandquality/citools.chinese.md) +🔗 [**更多: 挑选 CI 平台**](./sections/testingandquality/citools.chinese.md)

@@ -440,8 +431,6 @@ null == undefined // true **否则:** 当你的大部分代码没有被测试覆盖时,就不会有任何自动化的度量指标告诉你了。 - -

## ![✔] 4.7 检查过期的依赖包 @@ -456,24 +445,21 @@ null == undefined // true **TL;DR:** 端对端(e2e)测试包含现场数据,由于它依赖于很多重型服务如数据库,习惯被认为是CI过程中最薄弱的环节。Docker-compose通过制定类似生产的环境,并使用一个简单的文本文件和简单的命令,轻松化解了这个问题。它为了e2e测试,允许制作所有相关服务,数据库和隔离网络。最后但并非最不重要的一点是,它可以保持一个无状态环境,该环境在每个测试套件之前被调用,然后立即消失。 - **否则:** 没有docker-compose,团队必须维护一个测试数据库在每一个测试环境上,包含开发机器,保持所有数据同步,这样测试结果不会因环境不同而不同。 -


⬆ 返回顶部

5. 上线实践

-## ![✔] 5.1. 监控! +## ![✔] 5.1. 监控 **TL;DR:** 监控是一种在顾客之前发现问题的游戏 – 显然这应该被赋予前所未有的重要性。考虑从定义你必须遵循的基本度量标准开始(我的建议在里面),到检查附加的花哨特性并选择解决所有问题的解决方案。市场已经淹没其中。点击下面的 ‘The Gist’ ,了解解决方案的概述。 **否则:** 错误 === 失望的客户. 非常简单. - -🔗 [**更多: 监控!**](/sections/production/monitoring.chinese.md) +🔗 [**更多: 监控!**](./sections/production/monitoring.chinese.md)

@@ -483,8 +469,7 @@ null == undefined // true **否则:** 您最终像是面对一个黑盒,不知道发生了什么事情,然后你开始重新写日志语句添加额外的信息。 - -🔗 [**更多: 使用智能日志增加透明度**](/sections/production/smartlogging.chinese.md) +🔗 [**更多: 使用智能日志增加透明度**](./sections/production/smartlogging.chinese.md)

@@ -494,8 +479,7 @@ null == undefined // true **否则:** 可怜的单线程Node将不幸地忙于处理网络任务,而不是处理应用程序核心,性能会相应降低。 - -🔗 [**更多: 委托可能的一切(例如:gzip,SSL)给反向代理**](/sections/production/delegatetoproxy.chinese.md) +🔗 [**更多: 委托可能的一切(例如:gzip,SSL)给反向代理**](./sections/production/delegatetoproxy.chinese.md)

@@ -505,8 +489,7 @@ null == undefined // true **否则:** QA测试通过的代码和批准的版本,在生产中表现不一致。更糟糕的是,同一生产集群中的不同服务器可能运行不同的代码。 - -🔗 [**更多: 锁住依赖**](/sections/production/lockdependencies.chinese.md) +🔗 [**更多: 锁住依赖**](./sections/production/lockdependencies.chinese.md)

@@ -516,9 +499,7 @@ null == undefined // true **否则:** 运行几十个实例没有明确的战略和太多的工具(集群管理,docker,PM2)可能导致一个DevOps混乱 - -🔗 [**更多: 使用正确的工具保护进程正常运行**](/sections/production/guardprocess.chinese.md) - +🔗 [**更多: 使用正确的工具保护进程正常运行**](./sections/production/guardprocess.chinese.md)

@@ -528,8 +509,7 @@ null == undefined // true **否则:** 您的应用可能只是使用了其可用资源中的25% (!),甚至更少。注意,一台典型的服务器有4个或更多的CPU,默认的Node.js部署仅仅用了一个CPU(甚至使用PaaS服务,比如AWS beanstalk,也一样)。 - -🔗 [**更多: 利用所有的CPU**](/sections/production/utilizecpu.chinese.md) +🔗 [**更多: 利用所有的CPU**](./sections/production/utilizecpu.chinese.md)

@@ -539,8 +519,7 @@ null == undefined // true **否则:** 您会发现,您正在执行许多“诊断部署” – 将代码发送到生产中,仅仅只为了诊断目的提取一些信息。 - -🔗 [**更多: 创建一个 '维护端点'**](/sections/production/createmaintenanceendpoint.chinese.md) +🔗 [**更多: 创建一个 '维护端点'**](./sections/production/createmaintenanceendpoint.chinese.md)

@@ -550,21 +529,17 @@ null == undefined // true **否则:** 你可能会花大力气测量API性能和停机时间,也许你永远不会知道,真实场景下哪个是你最慢的代码部分,这些怎么影响用户体验。 - -🔗 [**更多: 使用APM产品发现错误和宕机时间**](/sections/production/apmproducts.chinese.md) - +🔗 [**更多: 使用APM产品发现错误和宕机时间**](./sections/production/apmproducts.chinese.md)

- ## ![✔] 5.9. 使您的代码保持生产环境就绪 **TL;DR:** 在意识中抱着最终上线的想法进行编码,从第1天开始计划上线。这听起来有点模糊,所以我编写了一些与生产维护密切相关的开发技巧(点击下面的要点) **否则:** 一个世界冠军级别的IT/运维人员也不能拯救一个编码低劣的系统。 - -🔗 [**更多: 使您的代码保持生产环境就绪**](/sections/production/productioncode.chinese.md) +🔗 [**更多: 使您的代码保持生产环境就绪**](./sections/production/productioncode.chinese.md)

@@ -574,80 +549,76 @@ null == undefined // true **否则:** 您的内存可能一天泄漏一百兆,就像曾发生在沃尔玛的一样。 - -🔗 [**更多: 测量和保护内存使用**](/sections/production/measurememory.chinese.md) +🔗 [**更多: 测量和保护内存使用**](./sections/production/measurememory.chinese.md)

- ## ![✔] 5.11. Node外管理您的前端资源 **TL;DR:** 使用专门的中间件(nginx,S3,CDN)服务前端内容,这是因为在处理大量静态文件的时候,由于node的单线程模型,它的性能很受影响。 **否则:** 您的单个node线程将忙于传输成百上千的html/图片/angular/react文件,而不是分配其所有的资源为了其擅长的任务 – 服务动态内容 - -🔗 [**更多: Node外管理您的前端资源**](/sections/production/frontendout.chinese.md) +🔗 [**更多: Node外管理您的前端资源**](./sections/production/frontendout.chinese.md)

- ## ![✔] 5.12. 保持无状态,几乎每天都要停下服务器 **TL;DR:** 在外部数据存储上,存储任意类型数据(例如用户会话,缓存,上传文件)。考虑间隔地停掉您的服务器或者使用 ‘serverless’ 平台(例如 AWS Lambda),这是一个明确的强化无状态的行为。 **否则:** 某个服务器上的故障将导致应用程序宕机,而不仅仅是停用故障机器。此外,由于依赖特定服务器,伸缩弹性会变得更具挑战性。 - -🔗 [**更多: 保持无状态,几乎每天都要停下服务器**](/sections/production/bestateless.chinese.md) - +🔗 [**更多: 保持无状态,几乎每天都要停下服务器**](./sections/production/bestateless.chinese.md)

- ## ![✔] 5.13. 使用自动检测漏洞的工具 **TL;DR:** 即使是最有信誉的依赖项,比如Express,会有使系统处于危险境地的已知漏洞(随着时间推移)。通过使用社区的或者商业工具,不时的检查漏洞和警告(本地或者Github上),这类问题很容易被抑制,有些问题甚至可以立即修补。 **否则:** 否则: 在没有专用工具的情况下,使代码清除漏洞,需要不断地跟踪有关新威胁的在线出版物。相当繁琐。 - -🔗 [**更多: 使用自动检测漏洞的工具**](/sections/production/detectvulnerabilities.chinese.md) +🔗 [**更多: 使用自动检测漏洞的工具**](./sections/production/detectvulnerabilities.chinese.md)

- ## ![✔] 5.14. 在每一个log语句中指明 ‘TransactionId’ **TL;DR:** 在每一个请求的每一条log入口,指明同一个标识符,transaction-id: {某些值}。然后在检查日志中的错误时,很容易总结出前后发生的事情。不幸的是,由于Node异步的天性自然,这是不容易办到的,看下代码里面的例子 **否则:** 在没有上下文的情况下查看生产错误日志,这会使问题变得更加困难和缓慢去解决。 - -🔗 [**更多: 在每一个log语句中指明 ‘TransactionId’**](/sections/production/assigntransactionid.chinese.md) +🔗 [**更多: 在每一个log语句中指明 ‘TransactionId’**](./sections/production/assigntransactionid.chinese.md)

- ## ![✔] 5.15. 设置NODE_ENV=production **TL;DR:** 设置环境变量NODE_ENV为‘production’ 或者 ‘development’,这是一个是否激活上线优化的标志 - 很多NPM的包通过它来判断当前的环境,据此优化生产环境代码。 **否则:** 遗漏这个简单的属性可能大幅减弱性能。例如,在使用Express作为服务端渲染页面的时候,如果未设置NODE_ENV,性能将会减慢大概三分之一! - -🔗 [**更多: 设置NODE_ENV=production**](/sections/production/setnodeenv.chinese.md) - +🔗 [**更多: 设置NODE_ENV=production**](./sections/production/setnodeenv.chinese.md)

- ## ![✔] 5.16. 设计自动化、原子化和零停机时间部署 **TL;DR:** 研究表明,执行许多部署的团队降低了严重上线问题的可能性。不需要危险的手动步骤和服务停机时间的快速和自动化部署大大改善了部署过程。你应该达到使用Docker结合CI工具,使他们成为简化部署的行业标准。 **否则:** 长时间部署 -> 线上宕机 & 和人相关的错误 -> 团队部署时不自信 -> 更少的部署和需求 +

+ +## ![✔] 5.17. 使用 Node.js 的 LTS 版本 + +**TL;DR:** 确保您是使用LTS版本的Node.js来获取关键的错误修复、安全更新和性能改进。 + +**否则:** 新发现的错误或漏洞可能会被用于生产环境中运行的应用程序,您的应用程序可能会变得难以维护且不受各种模块支持. + +🔗 [**更多: 使用node.js的LTS版本**](./sections/production/LTSrelease.chinese.md) +


⬆ 返回顶部

@@ -666,7 +637,7 @@ null == undefined // true **Otherwise:** 在开发过程中, 可能一个直白的安全隐患, 成为生产环境中一个严重问题。此外, 项目可能没有遵循一致的安全规范, 而导致引入漏洞, 或敏感信息被提交到远程仓库中。 -🔗 [**更多: Lint 规范**](/sections/security/lintrules.md) +🔗 [**更多: Lint 规范**](./sections/security/lintrules.md)

@@ -678,7 +649,7 @@ null == undefined // true **否则:** 应用程序可能受到攻击, 导致拒绝服务, 在这种情况下, 真实用户会遭受服务降级或不可用。 -🔗 [**更多: 实施速率限制**](/sections/security/limitrequests.md) +🔗 [**更多: 实施速率限制**](./sections/security/limitrequests.md)

@@ -690,7 +661,7 @@ null == undefined // true **否则:** 源代码管理, 即使对于私有仓库, 也可能会被错误地公开, 此时所有的秘密信息都会被公开。外部组织的源代码管理的访问权限将无意中提供对相关系统 (数据库、api、服务等) 的访问。 -🔗 [**更多: 安全管理**](/sections/security/secretmanagement.md) +🔗 [**更多: 安全管理**](./sections/security/secretmanagement.md)

@@ -702,15 +673,15 @@ null == undefined // true **否则:** 未经验证或未脱敏处理的用户输入,可能会导致操作员在使用MongoDB进行NoSQL操作时进行注入, 而不使用适当的过滤系统或ORM很容易导致SQL注入攻击, 从而造成巨大的漏洞。 -🔗 [**更多: 使用 ORM/ODM 库防止查询注入**](/sections/security/ormodmusage.md) +🔗 [**更多: 使用 ORM/ODM 库防止查询注入**](./sections/security/ormodmusage.md)

-## ![✔] 6.5. 通用安全最佳实际集合 +## ![✔] 6.5. 通用安全最佳实践集合 **TL;DR:** 这些是与Node.js不直接相关的安全建议的集合-Node的实现与任何其他语言没有太大的不同。单击 "阅读更多" 浏览。 -🔗 [**更多: 通用安全最佳实际**](/sections/security/commonsecuritybestpractices.md) +🔗 [**更多: 通用安全最佳实践**](./sections/security/commonsecuritybestpractices.md)

@@ -722,7 +693,7 @@ null == undefined // true **否则:** 攻击者可以对应用程序的用户进行直接攻击, 导致巨大的安全漏洞 -🔗 [**更多: 在应用程序中使用安全的header**](/sections/security/secureheaders.md) +🔗 [**更多: 在应用程序中使用安全的header**](./sections/security/secureheaders.md)

@@ -734,7 +705,7 @@ null == undefined // true **否则:** 攻击者可以检测到您的web框架并攻击其所有已知的漏洞。 -🔗 [**更多: 安全依赖**](/sections/security/dependencysecurity.md) +🔗 [**更多: 安全依赖**](./sections/security/dependencysecurity.md)

@@ -746,7 +717,7 @@ null == undefined // true **否则:** 在不使用安全功能的情况下,保存的密码或秘密信息容易受到暴力破解和字典攻击, 最终会导致他们的泄露。 -🔗 [**更多: 使用Bcrypt**](/sections/security/bcryptpasswords.chinese.md) +🔗 [**更多: 使用Bcrypt**](./sections/security/bcryptpasswords.chinese.md)

@@ -758,7 +729,7 @@ null == undefined // true **否则:** 攻击者可能会将恶意的JavaScript代码存储在您的DB中, 然后将其发送给可怜的客户端。 -🔗 [**更多: 转义输出**](/sections/security/escape-output.md) +🔗 [**更多: 转义输出**](./sections/security/escape-output.md)

@@ -770,7 +741,7 @@ null == undefined // true **否则:** 您疏忽和宽松的方法大大增加了攻击面, 并鼓励攻击者尝试许多输入, 直到他们找到一些组合, 使应用程序崩溃。 -🔗 [**更多: 验证传入的JSON schemas**](/sections/security/validation.md) +🔗 [**更多: 验证传入的JSON schemas**](./sections/security/validation.md)

@@ -782,7 +753,7 @@ null == undefined // true **否则:** 过期或错误的令牌可能被第三方恶意使用,以访问应用程序,并模拟令牌的所有者。 -🔗 [**更多: 为JSON Web Token添加黑名单**](/sections/security/expirejwt.md) +🔗 [**更多: 为JSON Web Token添加黑名单**](./sections/security/expirejwt.md)

@@ -794,7 +765,7 @@ null == undefined // true **否则:** 攻击者可以发出无限制的密码匹配尝试, 以获取对应用程序中特权帐户的访问权限。 -🔗 [**更多: 限制登录频率**](/sections/security/login-rate-limit.md) +🔗 [**更多: 限制登录频率**](./sections/security/login-rate-limit.md)

@@ -806,7 +777,7 @@ null == undefined // true **否则:** 在服务器上运行脚本的攻击者在本地计算机上获得无限制的权利 (例如,改变iptable,引流到他的服务器上) -🔗 [**更多: 使用非root用户运行Node.js**](/sections/security/non-root-user.md) +🔗 [**更多: 使用非root用户运行Node.js**](./sections/security/non-root-user.md)

@@ -818,7 +789,7 @@ null == undefined // true **否则:** 您的应用程序将不得不处理大的请求, 无法处理它必须完成的其他重要工作, 从而导致对DOS攻击的性能影响和脆弱性。 -🔗 [**更多: 限制负载大小**](/sections/security/requestpayloadsizelimit.md) +🔗 [**更多: 限制负载大小**](./sections/security/requestpayloadsizelimit.md)

@@ -830,7 +801,7 @@ null == undefined // true **否则:** 恶意JavaScript代码查找传入 `eval` 或其他实时判断的JavaScript函数的文本的方法, 并将获得在该页面上javascript权限的完全访问权。此漏洞通常表现为XSS攻击。 -🔗 [**更多: 避免JavaScript的eval声明**](/sections/security/avoideval.chinese.md) +🔗 [**更多: 避免JavaScript的eval声明**](./sections/security/avoideval.chinese.md)

@@ -842,7 +813,7 @@ null == undefined // true **否则:** 写得不好的正则表达式可能容易受到正则表达式DoS攻击的影响, 这将完全阻止event loop。例如,流行的`moment`包在2017年的11月,被发现使用了错误的RegEx用法而易受攻击。 -🔗 [**更多: 防止恶意正则**](/sections/security/regex.md) +🔗 [**更多: 防止恶意正则**](./sections/security/regex.md)

@@ -854,7 +825,7 @@ null == undefined // true **否则:** 恶意用户输入可以找到用于获得篡改文件的参数, 例如, 文件系统上以前上载的文件, 或访问已有的系统文件。 -🔗 [**更多: 安全地加载模块**](/sections/security/safemoduleloading.chinese.md) +🔗 [**更多: 安全地加载模块**](./sections/security/safemoduleloading.chinese.md)

@@ -866,7 +837,7 @@ null == undefined // true **否则:** 插件可以通过无限循环、内存超载和对敏感进程环境变量的访问等多种选项进行攻击 -🔗 [**更多: 在沙箱中运行不安全代码**](/sections/security/sandbox.chinese.md) +🔗 [**更多: 在沙箱中运行不安全代码**](./sections/security/sandbox.chinese.md)

@@ -878,7 +849,7 @@ null == undefined // true **否则:** 由于将恶意用户输入传递给未脱敏处理的系统命令, 直接地使用子进程可能导致远程命令执行或shell注入攻击。 -🔗 [**更多: 处理子进程时要格外小心**](/sections/security/childprocesses.chinese.md) +🔗 [**更多: 处理子进程时要格外小心**](./sections/security/childprocesses.chinese.md)

@@ -890,7 +861,7 @@ null == undefined // true **否则:** 敏感应用程序详细信息(如服务器文件路径、使用中的第三方模块和可能被攻击者利用的应用程序的其他内部工作流)可能会从stack trace发现的信息中泄露。 -🔗 [**更多: 隐藏客户端的错误详细信息**](/sections/security/hideerrors.md) +🔗 [**更多: 隐藏客户端的错误详细信息**](./sections/security/hideerrors.md)

@@ -912,7 +883,7 @@ null == undefined // true **否则:** 可以通过不安全的连接发送cookie, 攻击者可能会使用会话标识来标识web应用程序的基础框架以及特定于模块的漏洞。 -🔗 [**更多: cookie和session安全**](/sections/security/sessions.md) +🔗 [**更多: cookie和session安全**](./sections/security/sessions.md)

@@ -934,50 +905,88 @@ null == undefined // true **否则:** 当攻击者发现你没有校验用户提供的外部输入时,他们会在论坛、社交媒体以和其他公共场合发布他们精心制作的链接来诱使用户点击,以此达到漏洞利用的目的。 -🔗 [**阅读更多: 避免不安全的重定向**](/sections/security/saferedirects.chinese.md) +🔗 [**阅读更多: 避免不安全的重定向**](./sections/security/saferedirects.chinese.md) + +


+ +## ![✔] 6.25. 避免将机密信息发布到NPM仓库 + + + +**TL;DR:** 您应该采取预防措施来避免偶然地将机密信息发布到npm仓库的风险。 一个 `.npmignore` 文件可以被用作忽略掉特定的文件或目录, 或者一个在 `package.json` 中的 `files` 数组可以起到一个白名单的作用. + +**否则:** 您项目的API密钥、密码或者其它机密信息很容易被任何碰到的人滥用,这可能会导致经济损失、身份冒充以及其它风险。 + +🔗 [**阅读更多: 避免发布机密信息**](./sections/security/avoid_publishing_secrets.md)


⬆ Return to top

-# `API Practices` +# `7. 草稿: 有关性能的最佳实践` -## Our contributors are working on this section. Would you like to join? +## 我们的贡献者们正在努力完善这个章节。 [你想要加入吗?](https://github.com/goldbergyoni/nodebestpractices/issues/256) -# `Performance Practices` +

+ +## ![✔] 7.1. 不要阻塞事件循环 + +**TL;DR:** 避免执行CPU密集型的任务,并将这些任务转移到基于上下文的专用线程中,因为它们会阻塞大多数单线程事件循环。 + +**否则:** 由于事件循环被阻塞了,Node.js 将无法处理其它请求,从而导致同时请求的用户的延迟。 **3000 位用户正在等待响应,内容本身已经准备好了提供服务, 但是一个单独的请求阻止了服务器将结果分发回去。** + +🔗 [**阅读更多: 不要阻塞事件循环**](./sections/performance/block-loop.md) + +


+ +## ![✔] 7.2. 优先使用原生的JS方法,而不是像 Lodash 这样的用户空间级别的实用工具 + +**TL;DR:** 使用像 `lodash` 和 `underscore` 这样的实用库替代原生的JS方法,通常来说这么做更不好,因为它导致了一些不必要的依赖项以及更差的性能表现。 +请记住,随着新的V8引擎以及新的ES标准的引入,原生方法得到了改进,它们现在会比这些实用工具库高出大概 50% 的性能。 + +**否则:** 你将不得不维护一些性能更低的项目,在这些项目中,你本可以很简单的使用那些已经可以用的东西,或者用几行代码来取代掉几个文件。 + +🔗 [**阅读更多: 原生方法胜过实用工具**](./sections/performance/nativeoverutil.md) + +


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

⬆ 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](https://github.com/goldbergyoni/nodebestpractices/milestones) and join the working groups if you want to contribute to this project.

# Contributors + ## `Yoni Goldberg` + Independent Node.js consultant who works with customers at USA, Europe and Israel on building large-scale scalable Node applications. Many of the best practices above were first published on his blog post at [http://www.goldbergyoni.com](http://www.goldbergyoni.com). Reach Yoni at @goldbergyoni or me@goldbergyoni.com ## `Ido Richter` + 👨‍💻 Software engineer, 🌐 web developer, 🤖 emojis enthusiast. ## `Refael Ackermann` [@refack](https://github.com/refack) <refack@gmail.com> (he/him) + Node.js Core Collaborator, been noding since 0.4, and have noded in multiple production sites. Founded `node4good` home of [`lodash-contrib`](https://github.com/node4good/lodash-contrib), [`formage`](https://github.com/node4good/formage), and [`asynctrace`](https://github.com/node4good/asynctrace). `refack` on freenode, Twitter, GitHub, GMail, and many other platforms. DMs are open, happy to help. ## `Bruno Scheufler` + 💻 full-stack web developer and Node.js enthusiast. ## `Kyle Martin` [@js-kyle](https://github.com/js-kyle) -Full Stack Developer based in New Zealand, interested in architecting and building Node.js applications to perform at global scale. Keen contributor to open source software, including Node.js Core. +Full Stack Developer based in New Zealand, interested in architecting and building Node.js applications to perform at global scale. Keen contributor to open source software, including Node.js Core.

## Thank You Notes -We appreciate any contribution, from a single word fix to a new best practice. View our contributors and [contributing documentation here!](CONTRIBUTORS.md) +We appreciate any contribution, from a single word fix to a new best practice. View our contributors and [contributing documentation here!](./README.md#contributors-)


- diff --git a/README.french.md b/README.french.md new file mode 100644 index 000000000..ad402286f --- /dev/null +++ b/README.french.md @@ -0,0 +1,1640 @@ +[✔]: assets/images/checkbox-small-blue.png + +# Bonnes pratiques Node.js + +

+ Bonnes pratiques Node.js +

+ +
+ +
+ 102 items Dernière mise à jour : 14 Juillet 2021 Mis à jour pour Node 14.0.0 +
+ +
+ +[![nodepractices](./assets/images/twitter-s.png)](https://twitter.com/nodepractices/) **Suivez nous sur Twitter !** [**@nodepractices**](https://twitter.com/nodepractices/) + +
+ +Lire dans une autre langue : [![CN](./assets/flags/CN.png)**CN**](./README.chinese.md), [![FR](./assets/flags/FR.png)**FR**](./README.french.md), [![BR](./assets/flags/BR.png)**BR**](./README.brazilian-portuguese.md), [![RU](./assets/flags/RU.png)**RU**](./README.russian.md), [![PL](./assets/flags/PL.png)**PL**](./README.polish.md), [![JA](./assets/flags/JA.png)**JA**](./README.japanese.md), [![EU](./assets/flags/EU.png)**EU**](./README.basque.md) [(![ES](./assets/flags/ES.png)**ES**, ![HE](./assets/flags/HE.png)**HE**, ![KR](./assets/flags/KR.png)**KR** et ![TR](./assets/flags/TR.png)**TR** en cours ! )](#traductions) + +
+ +###### Construit et entretenu par notre [comité de pilotage](#comité-de-pilotage) et nos [collaborateurs](#collaborateurs) + +# Dernières bonnes pratiques et nouveautés + +- **![FR](./assets/flags/FR.png) Traduction française!1! :** La dernière traduction qui rejoint notre guide international est le français. Bienvenue + +- **🇯🇵 traduction japonaise :** Notre guide est désormais également traduit en japonais ! Avec l'aimable autorisation des extraordinaires [YukiOta](https://github.com/YukiOta) et [Yuta Azumi](https://github.com/YA21). + +- **🎊 60,000 stars !** : Notre dépôt a reçu la reconnaissance et la confiance de 60 100 développeurs. Nous sommes sans voix. + +

+ +# Bienvenue ! 3 Choses à savoir avant tout + +**1. Vous êtes en train de lire un regroupement des meilleurs articles sur Node.js. -** ce référentiel est un résumé et il conserve le contenu le mieux classé sur les bonnes pratiques Node.js, ainsi que du contenu écrit ici par des collaborateurs + +**2. Il s'agit du plus grand assemblage d'articles et il s'agrandit chaque semaine -** actuellement, plus de 80 bonnes pratiques, guides de style et astuces d'architecture sont présentées. Nous serions ravis de vous voir contribuer ici, qu'il s'agisse de corriger des erreurs de code, d'aider aux traductions ou de suggérer de nouvelles idées brillantes. Consultez nos [recommandations d'écriture](./.operations/writing-guidelines.french.md) + +**3. Les bonnes pratiques contiennent des informations supplémentaires -** la plupart des points ont un lien **🔗Plus d'infos** qui développe la bonne pratique avec des exemples de code, des citations venant de pages sélectionnées et plus encore. + +

+ +## Table des matières + +1. [Structure de projet (5)](#1-structure-de-projet) +2. [Gestion des erreurs (12) ](#2-gestion-des-erreurs) +3. [Style du code (12) ](#3-style-du-code) +4. [Tests et pratiques générales de qualité (13) ](#4-tests-et-pratiques-générales-de-qualité) +5. [Pratiques de mise en production (19) ](#5-pratiques-de-mise-en-production) +6. [Sécurité (25)](#6-bonnes-pratiques-de-sécurité) +7. [Performance (2) (Travail en cours ✍️)](#7-brouillon-bonnes-pratiques-de-performance) +8. [Pratiques de Docker (15)](#8-bonnes-pratiques-de-docker) + +

+ +# `1. Structure de projet` + +## ![✔] 1.1 Organisez votre projet en composants + +**TL;PL :** Le pire obstacle des énormes applications est la maintenance d'une base de code immense contenant des centaines de dépendances - un tel monolithe ralentit les développeurs tentant d'ajouter de nouvelles fonctionnalités. Pour éviter cela, répartissez votre code en composants, chacun dans son dossier avec son code dédié, et assurez vous que chaque unité soit courte et simple. Visitez le lien « Plus d'infos » plus bas pour voir des exemples de structure de projet correcte. + +**Autrement :** Lorsque les développeurs qui codent de nouvelles fonctionnalités ont du mal à réaliser l'impact de leur changement et craignent de casser d'autres composants dépendants - les déploiements deviennent plus lents et plus risqués. Il est aussi considéré plus difficile d'élargir un modèle d'application quand les unités opérationnelles ne sont pas séparées. + +🔗 [**Plus d'infos : organisez en composants**](./sections/projectstructre/breakintcomponents.french.md) + +

+ +## ![✔] 1.2 Organisez vos composants en strates, gardez la couche web à l'intérieur de son périmètre + +**TL;PL :** Chaque composant devrait contenir des « strates » - un objet dédié pour le web, un pour la logique et un pour le code d'accès aux données. Cela permet non seulement de séparer clairement les responsabilités mais permet aussi de simuler et de tester le système de manière plus simple. Bien qu'il s'agisse d'un modèle très courant, les développeurs d'API ont tendance à mélanger les strates en passant l'objet dédié au web (Par exemple Express req, res) à la logique opérationnelle et aux strates de données - cela rend l'application dépendante et accessible seulement par les frameworks web spécifiques. + +**Autrement :** Les tests, les jobs CRON, les déclencheurs des files d'attente de messages et etc ne peuvent pas accéder à une application qui mélange les objets web avec les autres strates. + +🔗 [**Plus d'infos : organisez en strates votre app**](./sections/projectstructre/createlayers.french.md) + +

+ +## ![✔] 1.3 Externalisez les utilitaires communs en paquets NPM + +**TL;PL :** Dans une grande appli rassemblant de nombreuses lignes de codes, les utilitaires opérant sur toutes les strates comme un logger, l'encryption et autres, devraient être inclus dans le code et exposés en tant que paquets NPM privés. Cela permet leur partage au sein de plusieurs projets. + +**Autrement :** Vous devrez inventer votre propre roue de déploiement et de dépendance + +🔗 [**Plus d'infos : organisez par fonction**](./sections/projectstructre/wraputilities.french.md) + +

+ +## ![✔] 1.4 Séparez Express 'app' et 'server' + +**TL;PL :** Evitez la sale habitude de définir l'appli [Express](https://expressjs.com/) toute entière dans un seul fichier immense - séparez la définition de votre 'Express' en au moins deux fichiers : la déclaration de l'API (app.js) et les responsabilités de gestion de réseau (WWW). Pour une structure encore plus poussée, localisez la déclaration de l'API dans les composants. + +**Autrement :** Votre API sera seulement accessible aux tests par le biais d'appels HTTP (plus lent et plus difficile de générer des rapports de couverture). Cela ne sera pas un réel plaisir de maintenir des centaines de lignes de code dans un fichier unique. + +🔗 [**Plus d'infos : séparez Express 'app' et 'server'**](./sections/projectstructre/separateexpress.french.md) + +

+ +## ![✔] 1.5 Utilisez une configuration respectueuse de l'environnement, sécurisée et hiérarchique + +**TL;PL :** La mise en place d'une configuration parfaite et sans faille doit garantir que (a) les clés peuvent être lues depuis un fichier ET à partir de la variable d'environnement (b) les secrets sont conservés hors du code source (c) la configuration est hiérarchique pour une recherche plus simple. Certains paquets peuvent gérer la plupart de ces points comme [rc](https://www.npmjs.com/package/rc), [nconf](https://www.npmjs.com/package/nconf), [config](https://www.npmjs.com/package/config) et [convict](https://www.npmjs.com/package/convict). + +**Autrement :** Ne pas se soucier de ces exigences de configuration ne fera que ralentir l'équipe de développement ou l'équipe de DevOps. Probablement les deux. + +🔗 [**Plus d'infos : bonnes pratiques de configuration**](./sections/projectstructre/configguide.french.md) + +


+ +

⬆ Retourner en haut de la page

+ +# `2. Gestion des erreurs` + +## ![✔] 2.1 Utilisez Async-Await ou les promesses pour le traitement des erreurs asynchrones + +**TL;PL :** Gérer les erreurs asynchrone avec le style fonction de rappel est probablement le chemin le plus rapide vers l'enfer (ou la [pyramide condamnée](https://fr.wikipedia.org/wiki/Pyramide_condamn%C3%A9e)). Le meilleur cadeau que vous puissiez faire à votre code est d'utiliser une bibliothèque de promesses réputée ou async-await à la place, ceci permet une syntaxe de code beaucoup plus compacte et familière comme try-catch. + +**Autrement :** Le style fonction de rappel de Node.js, function(err, response), constituent une autre manière d’obtenir une solution non maintenable mêlant gestion de l’erreur avec du code ordinaire, des imbrications excessives et une conception bancale. + +🔗 [**Plus d'infos : évitez les fonctions de rappel**](./sections/errorhandling/asyncerrorhandling.french.md) + +

+ +## ![✔] 2.2 Utilisez uniquement l'objet intégré Error + +**TL;PL :** Beaucoup lèvent des erreurs sous forme de chaîne ou de type personnalisé - cela complique la logique de gestion des erreurs et l'interopérabilité entre les modules. Que vous rejetiez une promesse, leviez une exception ou émettiez une erreur - l'utilisation uniquement de l'objet intégré Error (ou un objet qui étend l'objet Error) augmentera l'uniformité et empêchera la perte d'informations. Il existe une règle ESLint `no-throw-literal` qui vérifie strictement cela (bien qu'elle ait quelques [limitations](https://eslint.org/docs/rules/no-throw-literal) qui peuvent être résolues en utilisant TypeScript et en définissant la règle `@typescript-eslint/no-throw-literal`). + +**Autrement :** Lorsque vous appelez un composant, le type d'erreurs en retour étant incertain - cela rend la gestion des erreurs beaucoup plus difficile. Pire encore, l'utilisation de types personnalisés pour décrire des erreurs peut entraîner la perte d'informations d'erreurs critiques comme la trace de la pile ! + +🔗 [**Plus d'infos : utilisez uniquement l'objet intégré Error**](./sections/errorhandling/useonlythebuiltinerror.french.md) + +

+ +## ![✔] 2.3 Distinguez les erreurs opérationnelles des erreurs de programmation + +**TL;PL :** Les erreurs opérationnelles (par exemple, l'API a reçu une entrée non valide) se rapportent à des cas connus où l'impact de l'erreur est entièrement compris et peut être géré de manière réfléchie. D'autre part, une erreur de programmation (par exemple, essayer de lire une variable non définie) fait référence à des échecs de code inconnus qui dictent de redémarrer l'application en douceur. + +**Autrement :** Vous pouvez toujours redémarrer l'application lorsqu'une erreur apparaît, mais pourquoi lâcher environ 5000 utilisateurs en ligne en raison d'une erreur opérationnelle mineure prévue ? L'inverse n'est pas non plus idéal - laisser l'application en place lorsqu'un problème inconnu (erreur de programmation) s'est produit peut conduire à un comportement imprévu. Différencier les deux permet d'agir avec tact et d'appliquer une approche équilibrée en fonction du contexte donné. + +🔗 [**Plus d'infos : erreur opérationnelle vs erreur de programmation**](./sections/errorhandling/operationalvsprogrammererror.french.md) + +

+ +## ![✔] 2.4 Gérez les erreurs de manière centralisée, pas dans un middleware + +**TL;PL :** Les logiques de gestion des erreurs telles que le mail à l'administrateur et la journalisation doivent être encapsulées dans un objet dédié et centralisé, pour que tous les points de terminaison (par exemple, middleware Express, tâches cron, tests unitaires) l'appellent lorsqu'une erreur survient. + +**Autrement :** Ne pas traiter les erreurs dans un seul endroit entraînera une duplication de code et probablement des erreurs mal gérées + +🔗 [**Plus d'infos : gestion des erreurs dans un lieu centralisé**](./sections/errorhandling/centralizedhandling.french.md) + +

+ +## ![✔] 2.5 Documentez les erreurs de l'API à l'aide de Swagger ou GraphQL + +**TL;PL :** Faites savoir à vos appelants de l'API quelles erreurs peuvent survenir en retour afin de pouvoir les traiter de manière réfléchie sans planter. Pour les API RESTful, cela se fait généralement avec des frameworks de documentation comme Swagger. Si vous utilisez GraphQL, vous pouvez également utiliser votre schéma et vos commentaires. + +**Autrement :** Un client d'une API peut décider de planter et de redémarrer uniquement parce qu'il a reçu une erreur qu'il ne comprend pas. Remarque: l'appelant de votre API peut être vous (très typique dans un environnement de microservice) + +🔗 [**Plus d'infos : documentez les erreurs de l'API à l'aide de Swagger ou GraphQL**](./sections/errorhandling/documentingusingswagger.french.md) + +

+ +## ![✔] 2.6 Quittez le processus avec élégance lorsqu'un étranger arrive en ville + +**TL;PL :** Lorsqu'une erreur inconnue se produit (une erreur de programmation, voir la bonne pratique 2.3) - il existe une incertitude sur la bonne santé de l'application. Une pratique courante suggère de redémarrer le processus avec précaution à l'aide d'un outil de gestion des processus comme [Forever](https://www.npmjs.com/package/forever) ou [PM2](http://pm2.keymetrics.io/). + +**Autrement :** Lorsqu'une exception inconnue se produit, certains objets peuvent être dans un état défectueux (par exemple, un émetteur d'événements qui est utilisé globalement et qui ne déclenche plus d'événements en raison d'une défaillance interne) et toutes les demandes futures peuvent échouer ou se comporter de manière folle. + +🔗 [**Plus d'infos : arrêtez le processus**](./sections/errorhandling/shuttingtheprocess.french.md) + +

+ +## ![✔] 2.7 Utilisez un outil de journalisation mature pour augmenter la visibilité des erreurs + +**TL;PL :** Un ensemble d'outils de journalisation matures comme [Pino](https://github.com/pinojs/pino) ou [Log4js](http://stritti.github.io/log4js/), accélérera la découverte et la compréhension des erreurs. Alors oubliez console.log. + +**Autrement :** En parcourant les console.logs ou manuellement par le biais d'un fichier texte désordonné sans outils d'interrogation ou d'une visionneuse de journaux décente, vous pourriez être occupé au travail jusqu'à tard dans la nuit. + +🔗 [**Plus d'infos : utilisation d'un outil de journalisation mature**](./sections/errorhandling/usematurelogger.french.md) + +

+ +## ![✔] 2.8 Testez les flux d'erreurs en utilisant votre framework de test préféré + +**TL;PL :** Qu'il s'agisse d'un outil automatisée d'assurance qualité professionnelle ou de tests manuels simples pour les développeurs - Assurez-vous que votre code non seulement satisfait les scénarios positifs, mais gère et renvoie également les bonnes erreurs. Les frameworks de test comme Mocha & Chai peuvent gérer cela facilement (voir les exemples de code dans « Plus d'infos ») + +**Autrement :** Sans test, que ce soit automatiquement ou manuellement, vous ne pouvez pas compter sur votre code pour renvoyer les bonnes erreurs. Sans erreurs significatives - il n'y a pas de gestion des erreurs. + +🔗 [**Plus d'infos : test des flux d'erreurs**](./sections/errorhandling/testingerrorflows.french.md) + +

+ +## ![✔] 2.9 Découvrez les erreurs et les indisponibilités à l'aide des produits de gestion de la performance applicative + +**TL;PL :** Les produits de surveillance et de performance (alias GPA, APM en anglais : application performance management) évaluent de manière proactive votre base de code ou votre API afin qu'ils puissent mettre en évidence automatiquement les erreurs, les plantages et les parties lentes qui vous ont échappé. + +**Autrement :** Vous pourriez consacrer beaucoup d'efforts à mesurer les performances et les indisponibilités de l'API, vous ne saurez probablement jamais quelles sont vos parties de code les plus lentes dans le scénario du monde réel et comment celles-ci affectent l'expérience utilisateur. + +🔗 [**Plus d'infos : utilisation des produits GPA**](./sections/errorhandling/apmproducts.french.md) + +

+ +## ![✔] 2.10 Capturez les rejets de promesses non gérés + +**TL;PL :** Toute exception levée dans une promesse sera absorbée et écartée à moins qu'un développeur n'ait pas oublié de le traiter explicitement. Même si votre code est abonné à `process.uncaughtException` ! Surmontez cela en vous inscrivant à l'événement `process.unhandledRejection`. + +**Autrement :** Vos erreurs seront absorbées et ne laisseront aucune trace. Il n'y a pas de quoi s'inquiéter. + +🔗 [**Plus d'infos : capturez les rejets de promesses non gérés**](./sections/errorhandling/catchunhandledpromiserejection.french.md) + +

+ +## ![✔] 2.11 Échouez rapidement, valider les arguments à l'aide d'une bibliothèque dédiée + +**TL;PL :** Contrôlez les arguments de l'API pour éviter les bugs désagréables qui sont beaucoup plus difficiles à suivre plus tard. Le code de validation est généralement fastidieux, sauf si vous utilisez une bibliothèque d'aide très cool comme [ajv](https://www.npmjs.com/package/ajv) et [Joi](https://www.npmjs.com/package/joi). + +**Autrement :** Considérez ceci - votre fonction attend un argument numérique « Discount » que l'appelant oublie de passer, plus loin dans le code, il vérifie si Discount!= 0 (le montant de la remise autorisée est supérieur à zéro), ensuite le code permet à l'utilisateur de profiter d'un remise. OMG, quel méchant bug. Le vois-tu ? + +🔗 [**Plus d'infos : échec rapide**](./sections/errorhandling/failfast.french.md) + +

+ +## ![✔] 2.12 Attendez toujours les promesses avant de retourner afin d'éviter des traces de pile partielles + +**TL;PL :** Faites toujours `return await` lorsque vous retournez une promesse afin de bénéficier d'une trace de pile complète. Si une +fonction retourne une promesse, cette fonction doit être déclarée comme fonction `async` et explicitement +attendre (`await`) la promesse avant de la retourner. + +**Autrement :** La fonction qui retourne une promesse sans attendre n'apparaîtra pas dans la trace de la pile. +De telles trames manquantes compliqueraient probablement la compréhension du flux qui conduit à l'erreur, +surtout si la cause du comportement anormal se situe à l'intérieur de la fonction manquante + +🔗 [**Plus d'infos : le retour des promesses**](./sections/errorhandling/returningpromises.french.md) + +


+ +

⬆ Retourner en haut de la page

+ +# `3. Style du code` + +## ![✔] 3.1 Utilisez ESLint + +**TL;PL :** [ESLint](https://eslint.org) est la norme de facto pour vérifier d'éventuelles erreurs de code et pour corriger le style du code, ce n'est pas uniquement pour identifier les problèmes d'espacement mais aussi pour détecter les antipatterns préoccupants du code comme par exemple les développeurs levant des erreurs sans classification. Bien qu'ESLint puisse corriger automatiquement les styles du code, d'autres outils comme [prettier](https://www.npmjs.com/package/prettier) et [beautify](https://www.npmjs.com/package/js-beautify) sont plus puissants dans le formatage de la correction et fonctionnent en collaboration avec ESLint. + +**Autrement :** Les développeurs se concentreront sur les problèmes fastidieux d'espacement et de largeur de ligne, ce qui pourrait faire perdre du temps à trop réfléchir sur le style de code du projet. + +🔗 [**Plus d'infos : Utilisez ESLint et Prettier**](./sections/codestylepractices/eslint_prettier.french.md) + +

+ +## ![✔] 3.2 Plugins spécifiques à Node.js + +**TL;PL :** En plus des règles standard ESLint couvrant JavaScript vanilla, ajoutez des plugins spécifiques à Node.js comme [eslint-plugin-node](https://www.npmjs.com/package/eslint-plugin-node), [eslint-plugin-mocha](https://www.npmjs.com/package/eslint-plugin-mocha) et [eslint-plugin-node-security](https://www.npmjs.com/package/eslint-plugin-security). + +**Autrement :** De nombreux modèles de code Node.js défectueux peuvent s'échapper des radars. Par exemple, les développeurs pourrait exiger des fichiers avec une variable donnée comme un chemin d'accès (`require(variableCommeChemin)`) qui permet aux attaquants d'exécuter n'importe quel script JS. Les linters de Node.js peuvent détecter de tels modèles et se plaindre en amont. + +

+ +## ![✔] 3.3 Commencez les accolades d'un bloc de code sur la même ligne + +**TL;PL :** Les accolades ouvrantes d'un bloc de code doivent être sur la même ligne que l'instruction d'ouverture. + +### Code Example + +```javascript +// À faire +function someFunction() { + // bloc de code +} + +// À éviter +function someFunction +{ + // bloc de code +} +``` + +**Autrement :** Le non-respect de cette bonne pratique peut conduire à des résultats inattendus, comme le montre la discussion de StackOverflow ci-dessous : + +🔗 [**Plus d'infos :** « Pourquoi les résultats varient-ils en fonction du placement des accolades ? » (StackOverflow)](https://stackoverflow.com/questions/3641519/why-does-a-results-vary-based-on-curly-brace-placement) + +

+ +## ![✔] 3.4 Séparez correctement vos instructions + +Peu importe si vous utilisez les points-virgules ou non pour séparer vos instructions, le fait de connaître les pièges courants des sauts de ligne incorrects ou de l'insertion automatique de points-virgules, vous aidera à éliminer les erreurs syntaxiques habituelles. + +**TL;PL :** Utilisez ESLint pour vous sensibiliser aux problèmes de séparation. [Prettier](https://prettier.io/) ou [Standardjs](https://standardjs.com/) peuvent résoudre automatiquement ces problèmes. + +**Autrement :** Comme vu dans la section précédente, l'interpréteur JavaScript ajoute automatiquement un point-virgule à la fin d'une instruction s'il n'y en a pas, ou considère une instruction comme non terminée là où elle devrait, ce qui pourrait conduire à des résultats indésirables. Vous pouvez utiliser des affectations et éviter d'utiliser des expressions de fonction invoquées immédiatement pour éviter la plupart des erreurs inattendues. + +### Exemple de code + +```javascript +// À faire +function doThing() { + // ... +} + +doThing() + +// À faire + +const items = [1, 2, 3] +items.forEach(console.log) + +// À éviter — lève une exception +const m = new Map() +const a = [1,2,3] +[...m.values()].forEach(console.log) +> [...m.values()].forEach(console.log) +> ^^^ +> SyntaxError: Unexpected token ... + +// À éviter — lève une exception +const count = 2 // il essaie d'exécuter 2(), mais 2 n'est pas une fonction +(function doSomething() { + // faire quelque chose d'incroyable +}()) +// placez un point-virgule avant la fonction immédiatement invoquée, après la définition de const, enregistrez la valeur de retour de la fonction anonyme dans une variable ou évitez tous les IIFE +``` + +🔗 [**Plus d'infos :** « Règle de ESLint : points-virgules »](https://eslint.org/docs/rules/semi) +🔗 [**Plus d'infos :** « Règle de ESLint : pas de multiligne inattendue »](https://eslint.org/docs/rules/no-unexpected-multiline) + +

+ +## ![✔] 3.5 Nommez vos fonctions + +**TL;PL :** Nommez toutes les fonctions, y compris les fermetures _(closures, NdT)_ et les fonctions de rappel. Évitez les fonctions anonymes. Cela est particulièrement utile lors du profilage d'une application de Node. Nommer toutes les fonctions vous permettra de comprendre facilement ce que vous regardez lors de la vérification d'un instantané de mémoire _(snapshot memory, NdT)_. + +**Autrement :** Le débogage des problèmes de production à l'aide d'un vidage de mémoire (instantané de mémoire) peut devenir difficile lorsque vous remarquez une consommation de mémoire importante de la part de fonctions anonymes. + +

+ +## ![✔] 3.6 Utilisez des conventions de nommage pour les variables, les constantes, les fonctions et les classes + +**TL;PL :** Utilisez **_LowerCamelCase_** lorsque vous nommez des constantes, des variables et des fonctions et **_UpperCamelCase_** (première lettre en majuscule également) lorsque vous nommez des classes. Cela vous aidera à distinguer facilement les simples variables/fonctions et les classes qui nécessitent une instanciation. Utilisez des noms évocateurs, mais efforcez-vous de les garder concis. + +**Autrement :** JavaScript est le seul langage au monde qui permet d'invoquer directement un constructeur (« Class ») sans l'instancier au préalable. Par conséquent, les classes et les fonctions-constructeurs sont différenciés en commençant par UpperCamelCase. + +### 3.6 Exemple de code + +```javascript +// pour le nom d'une classe, nous utilisons UpperCamelCase +class SomeClassExample {} + +// pour les noms de constantes, nous utilisons le mot-clé const et lowerCamelCase +const config = { + key: "value", +}; + +// pour les noms de variables et de fonctions, nous utilisons lowerCamelCase +let someVariableExample = "value"; +function doSomething() {} +``` + +

+ +## ![✔] 3.7 Préférez const à let. Laissez tomber le var + +**TL;PL :** L'utilisation de `const` signifie qu'une fois qu'une variable est affectée, elle ne peut pas être réaffectée. Préférer `const` vous aidera à ne pas être tenté d'utiliser la même variable pour différentes utilisations et rendra votre code plus clair. Si une variable doit être réaffectée, par exempledans une boucle for, utilisez `let` pour la déclarer. Un autre aspect important de `let` est qu'une variable déclarée l'utilisant n'est disponible que dans la portée du bloc dans laquelle elle a été définie. `var` est une portée de fonction, pas une portée de bloc, et [ne devrait pas être utilisé en ES6](https://hackernoon.com/why-you-shouldnt-use-var-anymore-f109a58b9b70) maintenant que vous avez `const` et `let` à votre disposition. + +**Autrement :** Le débogage devient beaucoup plus lourd lorsque vous suivez une variable qui change fréquemment. + +🔗 [**Plus d'infos : JavaScript ES6+ : var, let, ou const ?** ](https://medium.com/javascript-scene/javascript-es6-var-let-or-const-ba58b8dcde75) + +

+ +## ![✔] 3.8 Utilisez en premier require pour les modules, pas dans des fonctions internes + +**TL;PL :** Utilisez au début de chaque fichier `require` pour les modules, avant et en dehors de toute fonction. Cette bonne pratique simple vous aidera non seulement à identifier facilement et rapidement les dépendances en haut d'un fichier, mais évite également quelques problèmes potentiels. + +**Autrement :** Les `require` sont exécutées de manière synchrone par Node.js. S'ils sont appelés depuis une fonction, cela peut empêcher le traitement d'autres demandes à un moment plus critique. De plus, si un module requis ou l'une de ses dépendances lance une erreur et plante le serveur, il est préférable de le découvrir le plus tôt possible, ce qui pourrait ne pas être le cas si ce module est requis depuis une fonction. + +

+ +## ![✔] 3.9 Exiger les modules par leurs dossiers, contrairement à l'appel direct aux fichiers + +**TL;PL :** Lorsque vous développez un module/bibliothèque dans un dossier, placez un fichier index.js qui expose les composants internes du module afin que chaque utilisateur puisse y accéder. Cela sert d '« interface » à votre module et facilite les modifications futures sans rompre le contrat. + +**Autrement :** La modification de la structure interne des fichiers ou de la signature peut rompre l'interface avec les clients. + +### 3.9 Exemple de code + +```javascript +// À faire +module.exports.SMSProvider = require("./SMSProvider"); +module.exports.SMSNumberResolver = require("./SMSNumberResolver"); + +// À éviter +module.exports.SMSProvider = require("./SMSProvider/SMSProvider.js"); +module.exports.SMSNumberResolver = require("./SMSNumberResolver/SMSNumberResolver.js"); +``` + +

+ +## ![✔] 3.10 Utilisez l'opérateur `===` + +**TL;PL :** Préférez l'opérateur d'égalité stricte `===` à l'opérateur d'égalité abstraite plus faible `==`. `==` comparera deux variables après les avoir converties en un type commun. Il n'y a pas de conversion de type dans `===`, et les deux variables doivent être du même type pour être égales. + +**Autrement :** Les variables inégales peuvent renvoyer true avec l'opérateur `==`. + +### 3.10 Exemple de code + +```javascript +"" == "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 +``` + +Toutes les déclarations ci-dessus renverront false si elles sont utilisées avec `===` + +

+ +## ![✔] 3.11 Utilisez Async Await, évitez les fonctions de rappel + +**TL;PL :** Node 8 LTS prend désormais entièrement en charge Async-wait. Il s'agit d'une nouvelle façon de gérer le code asynchrone qui remplace les fonctions de rappel et les promesses. L'attente asynchrone n'est pas bloquante et rend le code asynchrone synchrone. Le meilleur cadeau que vous puissiez faire à votre code est d'utiliser async-wait qui fournit une syntaxe de code beaucoup plus compacte et familière comme try-catch. + +**Autrement :** La gestion des erreurs asynchrones dans le style des fonctions de rappel est probablement le chemin le plus rapide vers l'enfer - ce style oblige de vérifier les erreurs partout, à gérer les imbrications de code gênantes et rend difficile la compréhension du flux du code. + +🔗[**Plus d'infos :** guide pour async-await 1.0](https://github.com/yortus/asyncawait) + +

+ +## ![✔] 3.12 Utiliser les expressions de fonction fléchée (=>) + +**TL;PL :** Bien qu'il soit recommandé d'utiliser async-wait et d'éviter les paramètres de fonction lorsque vous traitez avec des API plus anciennes qui acceptent des promesses ou des rappels - les fonctions fléchées rendent la structure de code plus compacte et gardent le contexte lexical de la fonction racine (c'est-à-dire `this`). + +**Autrement :** Un code plus long (dans les fonctions ES5) est plus sujet aux bogues et lourd à lire. + +🔗 [**Plus d'infos : il est temps d'adopter les fonctions fléchées**](https://medium.com/javascript-scene/familiarity-bias-is-holding-you-back-its-time-to-embrace-arrow-functions-3d37e1a9bb75) + +


+ +

⬆ Retourner en haut de la page

+ +# `4. Tests et pratiques générales de qualité` + +## ![✔] 4.1 Au minimum, écrivez des tests API (pour chaque composant) + +**TL;PL :** La plupart des projets n'ont tout simplement pas de test automatisé en raison de délais courts ou souvent le « projet de test » est devenu incontrôlable et a été abandonné. Pour cette raison, priorisez et commencez par les tests d'API, qui est le moyen le plus simple d'écrire et qui offre plus de couverture que les tests unitaires (vous pouvez même créer des tests d'API sans code à l'aide d'outils comme [Postman](https://www.getpostman.com/)). Par la suite, si vous avez plus de ressources et de temps, continuez avec des types de tests avancés tels que les tests unitaires, les tests DB (base de données), les tests de performances, etc. + +**Autrement :** Vous pouvez passer de longues journées à écrire des tests unitaires pour découvrir que vous n'avez qu'une couverture système de 20% + +

+ +## ![✔] 4.2 Incluez 3 parties dans chaque nom de test + +**TL;PL :** Donnez un nom de test éloquent selon son niveau d'exigences pour qu'il soit compréhensible par les ingénieurs et développeurs de l'assurance qualité qui ne sont pas familiers avec les codes internes. Indiquez dans le nom du test ce qui est testé (élément du test), dans quelles circonstances et quel est le résultat attendu. + +**Autrement :** Un déploiement vient d'échouer, un test nommé « Ajoute un produit » a échoué. Cela vous indique-t-il exactement ce qui ne fonctionne pas correctement ? + +🔗[**Plus d'infos : incluez 3 parties dans chaque nom de test**](./sections/testingandquality/3-parts-in-name.french.md) + +

+ +## ![✔] 4.3 Structurez vos tests avec le format AAA + +**TL;PL :** Structurez vos tests avec 3 sections bien séparées : Arrange, Act & Assert (AAA). La première partie comprend la configuration du test, puis l'exécution de l'unité testée et enfin la phase d'assertion (vérification). Le respect de cette structure garantit que le lecteur n'utilise pas de le CPU de son cerveau pour comprendre le plan de test. + +**Autrement :** Non seulement vous passez de longues heures par jour à comprendre le code principal, mais maintenant, ce qui aurait dû être la partie la plus simple de la journée (les tests) accroche votre cerveau + +🔗[**Plus d'infos : structurez vos tests avec le format AAA**](./sections/testingandquality/aaa.french.md) + +

+ +## ![✔] 4.4 Détectez les problèmes de code avec un linter + +**TL;PL :** Utilisez un linter de code pour vérifier la qualité et détecter les antipatterns au plus tôt. Exécutez-le avant les tests et ajoutez-le en tant que git-hook de pré-commit pour diminuer le temps nécessaire pour examiner et corriger tout problème. Vérifiez également la [section 3](#3-style-du-code) sur les pratiques de style de code. + +**Autrement :** Vous pouvez laisser passer un code antipatterns et éventuellement vulnérable sur votre environnement de production. + +

+ +## ![✔] 4.5 Évitez les tests globaux, ajoutez des données pour chaque test + +**TL;PL :** Pour éviter le chevauchement de test et expliquer facilement le déroulement du test, chaque test doit ajouter et agir sur son propre ensemble d'enregistrement de la base de données. Chaque fois qu'un test a besoin de récupérer ou de présumer l'existence de certaines données de la BD - il doit explicitement ajouter ces données et éviter de modifier tout autre enregistrement. + +\***\*Autrement :** Considérez un scénario où le déploiement est interrompu à cause de l'échec des tests, l'équipe va maintenant passer un temps d'investigation précieux qui se terminera par une triste conclusion : le système fonctionne bien, les tests interfèrent cependant les uns avec les autres et interrompent la construction. + +🔗[**Plus d'infos : évitez les tests globaux, ajoutez des données pour chaque test**](./sections/testingandquality/avoid-global-test-fixture.french.md) + +

+ +## ![✔] 4.6 Inspectez en permanence les dépendances vulnérables + +**TL;PL :** Même les dépendances les plus réputées telles qu'Express ont des vulnérabilités connues. Cela peut être facilement apprivoisé à l'aide d'outils communautaires et commerciaux tels que 🔗 [npm audit](https://docs.npmjs.com/cli/audit) et 🔗 [snyk.io](https://snyk.io) qui peuvent être appelé depuis votre CI pour chaque construction. + +**Autrement :** Garder votre code propre contre les vulnérabilités sans outils dédiés nécessitera de suivre en permanence les publications en ligne sur les nouvelles menaces. C'est assez fastidieux. + +

+ +## ![✔] 4.7 Étiquetez vos tests + +**TL;PL :** Différents tests doivent s'exécuter selon différents scénarios : test d'intégrité, sans IO, les tests doivent s'exécuter lorsqu'un développeur enregistre ou commit un fichier, les tests complets de bout en bout s'exécutent généralement lorsqu'une nouvelle « pull request » est soumise, etc. Cela peut être réalisé en étiquetant les tests avec des mots clés comme #IO #api #integrite afin que vous puissiez utiliser votre harnais de test et invoquer le sous-ensemble souhaité. Par exemple, voici comment vous invoqueriez uniquement le groupe de test d'intégrité avec [Mocha](https://mochajs.org/) : mocha --grep 'sanity' + +**Autrement :** Exécutez tous les tests, y compris les tests qui effectuent des dizaines de requêtes sur la base de données, chaque fois qu'un développeur apporte un petit changement, cela peut être extrêmement lent et souvent les développeurs s'abstiennent de faire des tests. + +

+ +## ![✔] 4.8 Vérifiez votre couverture de test, cela aide à identifier les mauvaises conception de test + +**TL;PL :** Les outils de couverture de code comme [Istanbul](https://github.com/istanbuljs/istanbuljs)/[NYC](https://github.com/istanbuljs/nyc) sont parfaits pour 3 raisons : ils sont gratuits (aucun effort n'est nécessaire pour bénéficier de ces rapports), ils aident à identifier une diminution de la couverture des tests, et enfin et surtout, ils mettent en évidence les incompatibilités de test : en regardant les rapports de couverture de code en couleur, vous remarquerez peut-être, par exemple, des zones de code qui ne sont jamais testées comme les clauses catch (ce qui signifie que les tests invoquent uniquement les chemins positifs et non le comportement de l'application en cas d'erreur). Configurez-les pour faire échouer les constructions si la couverture tombe sous un certain seuil. + +**Autrement :** Il n'y aura aucune mesure automatisée vous indiquant quand une grande partie de votre code n'est pas couverte par les tests + +

+ +## ![✔] 4.9 Inspectez les paquets obsolètes + +**TL;PL :** Utilisez votre outil préféré (par exemple, `npm outdated` ou [npm-check-updates](https://www.npmjs.com/package/npm-check-updates)) pour détecter les paquets installés qui sont obsolètes, injectez cette vérification dans votre CI et même faites échouer une construction dans un scénario critique. Par exemple, un scénario critique peut se produire lorsqu'un paquet installé a 5 patchs de retard (par exemple, la version locale est 1.3.1 et la version du référentiel est 1.3.8) ou quand il est marqué comme obsolète par son auteur - stoppez la construction et empêchez le déploiement de cette version. + +**Autrement :** Votre production exécutera des paquets qui ont été explicitement étiquetés par leur auteur comme risqués. + +

+ +## ![✔] 4.10 Utilisez pour les tests e2e un environnement proche de la production + +**TL;PL :** Les tests de bout en bout (e2e) qui comprennent l'utilisation de données en direct sont les maillons les plus faibles du processus du CI car ils dépendent de plusieurs services complexes comme la base de données. Utilisez un environnement de test continue aussi proche que possible de votre production actuelle. (Un oubli pour continue ici. A en juger par la clause **Autrement**, cela devrait mentionner docker-compose) + +**Autrement :** Sans docker-compose, les équipes doivent maintenir une base de données de test pour chaque environnement de test, y compris les machines des développeurs, garder toutes ces bases de données synchronisées afin que les résultats des tests ne varient pas d'un environnement à l'autre. + +

+ +## ![✔] 4.11 Refactorisez régulièrement à l'aide d'outils d'analyse statique + +**TL;PL :** L'utilisation d'outils d'analyse statique vous aide en donnant des moyens concrets d'améliorer la qualité du code et permet de maintenir votre code. Vous pouvez ajouter des outils d'analyse statique à votre CI pour échouer lorsqu'il trouve du code incorrect. Ses principaux arguments de vente par rapport au contrôle ordinaire de code sont la capacité d'inspecter la qualité dans le contexte de plusieurs fichiers (par exemple, détecter les doublons), d'effectuer une analyse avancée (par exemple la complexité du code) et de suivre l'historique et la progression des problèmes de code. Deux exemples d'outils que vous pouvez utiliser sont [Sonarqube](https://www.sonarqube.org/) (+ de 2 600 [étoiles](https://github.com/SonarSource/sonarqube)) et [Code Climate](https://codeclimate.com/) (+ de 1 500 [étoiles](https://github.com/codeclimate/codeclimate)). + +**Autrement :** Avec une mauvaise qualité de code, les bogues et les performances seront toujours un problème qu'aucune nouvelle bibliothèque brillante ou fonctionnalité de pointe ne peut résoudre. + +🔗[**Plus d'infos: refactorisation !**](./sections/testingandquality/refactoring.french.md) + +

+ +## ![✔] 4.12 Choisissez soigneusement votre plateforme CI (Jenkins vs CircleCI vs Travis vs Rest of the world) + +**TL;PL :** Votre plateforme d'intégration continue (CICD) hébergera tous les outils de qualité (par exemple test, lint), elle devrait donc être accompagnée d'un écosystème dynamique de plugins. [Jenkins](https://jenkins.io/) était utilisé par défaut pour de nombreux projets car il a la plus grande communauté avec une plateforme très puissante au prix d'une configuration complexe qui nécessite une courbe d'apprentissage abrupte. De nos jours, il est devenu beaucoup plus facile de mettre en place une solution CI en utilisant des outils SaaS comme [CircleCI](https://circleci.com) et d'autres. Ces outils permettent de créer un pipeline de CI flexible sans avoir à gérer l'ensemble de l'infrastructure. Finalement, c'est un compromis entre robustesse et rapidité - choisissez votre camp avec soin. + +**Autrement :** Le choix d'un fournisseur de niche peut vous bloquer une fois que vous aurez besoin d'une personnalisation avancée. En revanche, faire appel à Jenkins pourrait vous faire perdre un temps précieux à la mise en place de l'infrastructure. + +🔗[**Plus d'infos : choisissez soigneusement votre plateforme CI**](./sections/testingandquality/citools.french.md) + +## ![✔] 4.13 Testez vos middlewares de manière isolée + +**TL;PL :** Lorsqu'un middleware contient une logique immense qui couvre de nombreuses requêtes, cela vaut la peine de le tester de manière isolée sans réveiller l'ensemble du framework du web. Cela peut être facilement réalisé en espionnant les objets {req, res, next}. + +**Autrement :** Un bogue dans le middleware Express === un bogue dans toutes ou la plupart des requêtes + +🔗 [**Plus d'infos : testez vos middlewares de manière isolée**](./sections/testingandquality/test-middlewares.french.md) + +


+ +

⬆ Retourner en haut de la page

+ +# `5. Pratiques de mise en production` + +## ![✔] 5.1. Surveillance + +**TL;PL :** La surveillance est un jeu qui consiste à découvrir les problèmes avant que les clients ne les trouvent - il est évident qu'il faut accorder une importance sans précédent à cette question. Le marché est submergé d'offres, pensez donc à commencer par définir les mesures de base que vous devez suivre (mes suggestions à l'intérieur), puis passez en revue les fonctionnalités supplémentaires et choisissez la solution qui coche toutes les cases. Cliquez sur « l'essentiel » ci-dessous pour un aperçu des solutions. + +**Autrement :** Échec === clients déçus. C'est simple. + +🔗 [**Plus d'infos : surveillance !**](./sections/production/monitoring.french.md) + +

+ +## ![✔] 5.2. Augmentez la clarté à l'aide de la journalisation intelligente + +**TL;PL :** Les journaux peuvent être un stupide inventaire de relevés de débogage ou le facilitateur d'un magnifique tableau de bord qui raconte l'histoire de votre application. Prévoyez votre plateforme de journalisation dès le premier jour : comment les logs sont collectés, stockés et analysés pour s'assurer que les informations souhaitées (par exemple le taux d'erreur, le suivi d'une transaction complète via des services et des serveurs, etc.) peuvent réellement être exploitées. + +**Autrement :** Vous vous retrouvez avec une boîte noire qui est difficile à analyser, puis vous commencez à réécrire toutes les instructions de journalisation pour ajouter des informations supplémentaires. + +🔗 [**Plus d'infos : augmentez la clarté à l'aide de la journalisation intelligente**](./sections/production/smartlogging.french.md) + +

+ +## ![✔] 5.3. Déléguez tout ce qui est possible (par exemple gzip, SSL) à un proxy inverse + +**TL;PL :** Node est terriblement mauvais pour faire des tâches gourmandes en CPU comme la compression avec gzip, terminaison SSL, etc. Vous devriez utiliser à la place des services de middleware « réels » comme nginx, HAproxy ou des services de fournisseurs du cloud. + +**Autrement :** Votre pauvre processus restera occupé à faire des tâches d'infrastructure au lieu de s'occuper du cœur de votre application et les performances se dégraderont en conséquence. + +🔗 [**Plus d'infos : déléguez tout ce qui est possible (par exemple gzip, SSL) à un proxy inverse**](./sections/production/delegatetoproxy.french.md) + +

+ +## ![✔] 5.4. Verrouillez les dépendances + +**TL;PL :** Votre code doit être identique dans tous les environnements, mais étonnamment npm laisse les dépendances fluctuer entre les environnements par défaut - lorsque vous installez des paquets dans différents environnements, il essaie de récupérer la dernière version du patch des paquets. Surmontez cela en utilisant les fichiers de configuration de npm, .npmrc, qui indiquent à chaque environnement de sauvegarder la version exacte (et non la dernière) de chaque paquet. Alternativement, pour un contrôle plus fin, utilisez `npm shrinkwrap`. \*Mise à jour : à partir de NPM5, les dépendances sont verrouillées par défaut. Le nouveau gestionnaire de paquets en place, Yarn, nous a aussi fourni une couverture par défaut. + +**Autrement :** Le service qualité testera le code de manière approfondie et approuvera une version qui se comportera différemment en production. Pire encore, différents serveurs dans le même cluster de production peuvent exécuter un code différent. + +🔗 [**Plus d'infos : verrouillez les dépendances**](./sections/production/lockdependencies.french.md) + +

+ +## ![✔] 5.5. Protégez la disponibilité du processus avec des bons outils + +**TL;PL :** Le processus doit continuer et être redémarré en cas d'échec. Pour des scénarios simples, des outils de gestion de processus comme PM2 peuvent suffire, mais dans le monde « dockérizé » d'aujourd'hui, les outils de gestion de cluster doivent également être pris en compte. + +**Autrement :** L'exécution simultanée de dizaines d'instances sans stratégie claire et trop d'outils (gestion de cluster, docker, PM2) pourrait conduire au chaos du DevOps. + +🔗 [**Plus d'infos : protégez la disponibilité du processus avec des bons outils**](./sections/production/guardprocess.french.md) + +

+ +## ![✔] 5.6. Utilisez tous les cœurs du CPU + +**TL;PL :** Dans sa forme de base, une application Node fonctionne sur un seul cœur de CPU alors que tous les autres sont laissés au repos. Il est de votre devoir de répliquer le processus Node et d'utiliser tous les CPU - Pour les petites et moyennes applications, vous pouvez utiliser Node Cluster ou PM2. Pour une application plus grande, pensez à répliquer le processus à l'aide d'un cluster Docker (par exemple K8S, ECS) ou des scripts de déploiement basés sur le système d'initialisation Linux (par exemple systemd). + +**Autrement :** Votre application n'utilisera probablement que 25% de ses ressources disponibles (!) ou même moins. Notez qu'un serveur typique possède 4 cœurs CPU ou plus, le déploiement naïf de Node.js n'en utilise qu'un (même en utilisant des services PaaS comme AWS beanstalk !) + +🔗 [**Plus d'infos : utilisez tous les cœurs du CPU**](./sections/production/utilizecpu.french.md) + +

+ +## ![✔] 5.7. Créez un « point de terminaison de maintenance » + +**TL;PL :** Exposez dans une API sécurisée un ensemble d'informations liées au système, comme l'utilisation de la mémoire et le REPL, etc. Bien qu'il soit fortement recommandé de s'appuyer sur des outils standard et éprouvés au combat, certaines informations et opérations précieuses sont plus faciles à utiliser à l'aide de code. + +**Autrement :** Vous constaterez que vous effectuez de nombreuses « livraisons de diagnostics » - la livraison de code vers la production uniquement pour extraire des informations à des fins de diagnostic. + +🔗 [**Plus d'infos : créez un « point de terminaison de maintenance »**](./sections/production/createmaintenanceendpoint.french.md) + +

+ +## ![✔] 5.8. Découvrez les erreurs et les indisponibilités à l'aide des produits APM + +**TL;PL :** Les produits de surveillance et de performance des applications (a.k.a APM) mesurent de manière proactive la base de code et l'API afin qu'ils puissent aller automatiquement au-delà de la surveillance traditionnelle et mesurer l'expérience utilisateur globale à travers les services et les tiers. Par exemple, certains produits APM peuvent mettre en évidence une transaction qui se charge trop lentement du côté des utilisateurs finaux tout en suggérant la cause principale. + +**Autrement :** Vous pourriez consacrer beaucoup d'efforts à mesurer les performances et l'indisponibilité de l'API, vous ne saurez probablement jamais quelles sont vos parties de code les plus lentes dans le scénario du monde réel et comment celles-ci affectent l'expérience utilisateur. + +🔗 [**Plus d'infos : découvrez les erreurs et les indisponibilités à l'aide des produits APM**](./sections/production/apmproducts.french.md) + +

+ +## ![✔] 5.9. Préparez votre code pour la production + +**TL;PL :** Codez en pensant à la solution définitive, planifiez la production dès le premier jour. Cela semble un peu vague, j'ai donc compilé quelques conseils de développement qui sont étroitement liés à la maintenance de la production (cliquez sur l'essentiel ci-dessous) + +**Autrement :** Même le champion du monde Architecte/DevOps ne sauvera pas un système mal écrit. + +🔗 [**Plus d'infos : préparez votre code pour la production**](./sections/production/productioncode.french.md) + +

+ +## ![✔] 5.10. Mesurez et protégez l'utilisation de la mémoire + +**TL;PL :** Node.js a des relations controversées avec la mémoire : le moteur v8 a de faibles limites sur l'utilisation de la mémoire (1.4GB) et il y a des moyens connus pour faire fuir la mémoire dans le code de Node - donc surveiller la mémoire du processus de Node est une chose indispensable. Dans les petites applications, vous pouvez mesurer la mémoire périodiquement en utilisant des commandes shell mais dans les applications de taille moyenne, vous pouvez envisager de faire de votre surveillance mémoire via un système de surveillance robuste. + +**Autrement :** La mémoire de votre processus peut fuir une centaine de mégaoctets par jour, comme cela s'est produit chez [Walmart](https://www.joyent.com/blog/walmart-node-js-memory-leak) + +🔗 [**Plus d'infos : mesurez et protégez l'utilisation de la mémoire**](./sections/production/measurememory.french.md) + +

+ +## ![✔] 5.11. Retirez vos ressources frontend de Node + +**TL;PL :** Servez le contenu du frontend en utilisant un middleware dédié (nginx, S3, CDN) parce que les performances de Node sont vraiment diminuées lors du traitement de nombreux fichiers statiques en raison de son modèle mono-processus. + +**Autrement :** Votre unique processus de Node sera occupé à diffuser des centaines de fichiers html/images/angular/react au lieu d'allouer toutes ses ressources à la tâche pour laquelle il est conçu - fournir du contenu dynamique + +🔗 [**Plus d'infos : retirez vos ressources frontend de Node**](./sections/production/frontendout.french.md) + +

+ +## ![✔] 5.12. Soyez sans état, tuez vos serveurs presque tous les jours + +**TL;PL :** Stockez tout type de données (par exemple, sessions utilisateur, cache, fichiers téléchargés) dans des stockages de données externes. Envisagez de « tuer » vos serveurs périodiquement ou d'utiliser une plateforme « sans serveur » (par exemple AWS Lambda) qui impose explicitement un comportement sans état. + +**Autrement :** La défaillance d'un serveur particulier entraînera l'arrêt des applications au lieu de simplement tuer une machine défectueuse. De plus, l'élasticité de l'extensibilité sera plus difficile à obtenir en raison de la dépendance à un serveur spécifique. + +🔗 [**Plus d'infos : soyez sans état, tuez vos serveurs presque tous les jours**](./sections/production/bestateless.french.md) + +

+ +## ![✔] 5.13. Utilisez des outils qui détectent automatiquement les vulnérabilités + +**TL;PL :** Même les dépendances les plus réputées comme Express ont des vulnérabilités connues (de temps en temps) qui peuvent mettre un système en danger. Cela peut être facilement maîtrisé en utilisant des outils communautaires et commerciaux qui vérifient constamment les vulnérabilités et avertissent (localement ou sur GitHub), certains peuvent même les corriger immédiatement. + +**Autrement :** Si vous ne disposez pas d'outils dédiés pour protéger votre code contre les vulnérabilités, vous devrez suivre en permanence les publications en ligne sur les nouvelles menaces. C'est assez fastidieux. + +🔗 [**Plus d'infos : Utilisez des outils qui détectent automatiquement les vulnérabilités**](./sections/production/detectvulnerabilities.french.md) + +

+ +## ![✔] 5.14. Attribuez un id de transaction à chaque relevé du journal + +Également connu sous le nom de corrélation id / transit id / tracing id / request id / request context / etc. + +**TL;PL :** Attribuez le même identifiant, transaction-id : {une valeur}, à chaque entrée du journal à l'intérieur d'une même requête. Ensuite, lors de l'inspection des erreurs dans les journaux, il est facile de conclure ce qui s'est passé avant et après. Malheureusement, cela n'est pas facile à réaliser dans Node en raison de sa nature asynchrone, consultez les exemples de code. Jusqu'à la version 14 de Node, cela n'était pas facile à réaliser en raison de la nature asynchrone de Node, mais depuis l'arrivée de AsyncLocalStorage, cela est devenu possible et plus facile que jamais. Consultez les exemples de code fournis. + +**Autrement :** L'examen d'un journal d'erreurs de production sans le contexte (ce qui s'est passé auparavant) rend le travail de réflexion beaucoup plus difficile et lent. + +🔗 [**Plus d'infos : attribuez un ‘TransactionId’ à chaque relevé du journal**](./sections/production/assigntransactionid.french.md) + +

+ +## ![✔] 5.15. Définissez `NODE_ENV=production` + +**TL;PL :** Définissez la variable d'environnement `NODE_ENV` avec « production » ou « development » pour indiquer si les optimisations de production doivent être activées - de nombreux paquets npm déterminent l'environnement en cours et optimisent leur code pour la production. + +**Autrement :** L'omission de cette simple propriété pourrait fortement dégrader les performances. Par exemple, lors de l'utilisation d'Express pour le rendu côté serveur, l'omission de `NODE_ENV` le rend trois fois plus lent ! + +🔗 [**Plus d'infos : définissez NODE_ENV=production**](./sections/production/setnodeenv.french.md) + +

+ +## ![✔] 5.16. Concevez des déploiements automatisés, atomiques et sans interruption de service + +**TL;PL :** Les études montrent que les équipes qui effectuent de nombreux déploiements réduisent la probabilité de graves problèmes en production. Les déploiements rapides et automatisés qui ne nécessitent pas d'étapes manuelles risquées ni d'interruptions de service améliorent considérablement le processus de déploiement. Vous devriez probablement y parvenir en utilisant Docker combiné à des outils de CI, car ils sont devenus la norme du secteur pour un déploiement optimisé. + +**Autrement :** Déploiements longs -> arrêt de la production et erreur humaine -> équipe peu confiante dans la réalisation du déploiement -> moins de déploiements et de fonctionnalités. + +

+ +## ![✔] 5.17. Utilisez une version LTS de Node.js + +**TL;PL :** Assurez-vous d'utiliser une version LTS de Node.js pour recevoir les corrections de bogues critiques, les mises à jour de sécurité et les améliorations de performance + +**Autrement :** Les bogues ou vulnérabilités récemment découverts pourraient être utilisés pour exploiter une application en production, et votre application pourrait devenir non supportée par divers modules et plus difficile à maintenir + +🔗 [**Plus d'infos : Utilisez une version LTS de Node.js**](./sections/production/LTSrelease.french.md) + +

+ +## ![✔] 5.18. Ne redirigez pas les journaux vers l'application + +**TL;PL :** Les destinations des journaux ne devraient pas être codées en dur par les développeurs dans le code de l'application, mais devraient plutôt être définies par l'environnement d'exécution dans lequel l'application s'exécute. Les développeurs doivent écrire des journaux dans `stdout` en utilisant un utilitaire de journalisation et laisser l'environnement d'exécution (conteneur, serveur, etc.) diriger le flux `stdout` vers la destination appropriée (c'est-à-dire Splunk, Graylog, ElasticSearch, etc.). + +**Autrement :** Acheminement des journaux de gestion des applications === difficile à dimensionner, perte de journaux, mauvaise séparation des informations. + +🔗 [**Plus d'infos : redirection du journal**](./sections/production/logrouting.french.md) + +

+ +## ![✔] 5.19. Installez vos paquets avec `npm ci` + +**TL;PL :** Vous devez vous assurer que le code de production utilise la version exacte des paquets avec lesquels vous l'avez testé. Exécutez `npm ci` pour faire une installation propre de vos dépendances correspondant aux fichiers package.json et package-lock.json. + +**Autrement :\*\*\*\*** Le service qualité testera le code de manière approfondie et approuvera une version qui se comportera différemment en production. Pire encore, différents serveurs dans le même cluster de production peuvent exécuter un code différent. + +🔗 [**Plus d'infos : utilisez npm ci**](./sections/production/installpackageswithnpmci.french.md) + +


+ +

⬆ Retourner en haut de la page

+ +# `6. Bonnes pratiques de sécurité` + +
+54 items +
+ +## ![✔] 6.1. Adoptez les règles de sécurité du linter + + + +**TL;PL :** Utilisez des plugins de sécurité de linter tels que [eslint-plugin-security](https://github.com/nodesecurity/eslint-plugin-security) pour détecter les vulnérabilités et les problèmes de sécurité le plus tôt possible, de préférence lors de leur codage. Cela peut aider à détecter des vulnérabilités de sécurité comme l'utilisation de eval, l'invocation d'un processus enfant ou l'importation d'un module avec une chaîne littérale (par exemple, une entrée utilisateur). Cliquez sur « Plus d'infos » ci-dessous pour voir des exemples de codes qui seront pris en compte par un linter de sécurité. + +**Autrement :** Ce qui aurait pu être une simple défaillance de sécurité pendant le développement devient un problème majeur en production. En outre, le projet peut ne pas suivre des pratiques de sécurité de code conformes, ce qui peut entraîner l'introduction de vulnérabilités ou la divulgation de secrets sensibles dans des dépôts distants. + +🔗 [**Plus d'infos : régles du linter**](./sections/security/lintrules.french.md) + +

+ +## ![✔] 6.2. Limitez les requêtes simultanées en utilisant un middleware + + + +**TL;PL :** Les attaques DOS sont très populaires et relativement faciles à mener. Mettre en œuvre la limitation de débit en utilisant un service externe tel que les équilibreurs de charge, les pare-feux, nginx, un paquet [rate-limiter-flexible](https://www.npmjs.com/package/rate-limiter-flexible), ou (pour les applications plus petites et moins critiques) un middleware de limitation de débit (par exemple, [express-rate-limit](https://www.npmjs.com/package/express-rate-limit)). + +**Autrement :** Une application pourrait faire l'objet d'une attaque entraînant un déni de service, de ce fait, les utilisateurs réels obtiennent un service dégradé ou indisponible. + +🔗 [**Plus d'infos : mettez en œuvre la limitation de débit**](./sections/security/limitrequests.french.md) + +

+ +## ![✔] 6.3 Retirez les secrets des fichiers de configuration ou utiliser des paquets pour les crypter + + + +**TL;PL :** Ne stockez jamais les secrets en clair dans les fichiers de configuration ou le code source. Utilisez plutôt des systèmes de gestion des secrets comme les produits Vault, Kubernetes/Docker Secrets ou des variables d'environnement. En dernier recours, les secrets stockés dans le contenu des sources doivent être cryptés et gérés (clés de roulement, expiration, audit, etc.). Utilisez des hooks de pre-commit/push pour éviter de commeittez des secrets accidentellement. + +**Autrement :** Le contenu des sources, même pour les dépôts privés, peut être rendu public par erreur, et tous les secrets sont alors dévoilés. L'accès au contenu des sources pour une partie externe donnera par inadvertance accès à des systèmes connexes (bases de données, apis, services, etc.). + +🔗 [**Plus d'infos : gestion des secrets**](./sections/security/secretmanagement.french.md) + +

+ +## ![✔] 6.4. Évitez les vulnérabilités d'injection de query avec les bibliothèques ORM/ODM + + + +**TL;PL :** Pour éviter l'injection SQL/NoSQL et d'autres attaques malveillantes, utilisez toujours un ORM/ODM ou une bibliothèque de base de données qui échappe les données ou prend en charge les queries paramétrées nommées ou indexées et se charge de valider les entrées de l'utilisateur pour les types attendus. N'utilisez jamais simplement des chaînes de template JavaScript ou une concaténation de chaînes pour injecter des valeurs dans les queries, car cela ouvre votre application à un large éventail de vulnérabilités. Toutes les bibliothèques d'accès aux données Node.js réputées (par exemple [Sequelize](https://github.com/sequelize/sequelize), [Knex](https://github.com/tgriesser/knex), [mongoose](https://github.com/Automattic/mongoose)) disposent d'une protection intégrée contre les attaques par injection. + +**Autrement :** Une entrée utilisateur non validée ou non assainie pourrait conduire à l'injection de l'opérateur lorsqu'on travaille avec MongoDB pour NoSQL, et le fait de ne pas utiliser un système d'assainissement approprié ou un ORM permettra facilement des attaques par injection SQL, créant une énorme vulnérabilité. + +🔗 [**Plus d'infos : Prévention de l'injection de queries à l'aide des bibliothèques ORM/ODM**](./sections/security/ormodmusage.french.md) + +

+ +## ![✔] 6.5. Collection des meilleures pratiques génériques en matière de sécurité + +**TL;PL :** Il s'agit d'une collection de conseils de sécurité qui n'est pas directement liée à Node.js, l'implémentation de Node n'est pas très différente de toute autre langage. Cliquez pour en savoir plus. + +🔗 [**Plus d'infos : les meilleures pratiques communes en matière de sécurité**](./sections/security/commonsecuritybestpractices.french.md) + +

+ +## ![✔] 6.6. Adaptez les entêtes de réponse HTTP pour une sécurité accrue + + + +**TL;PL :** Votre application doit utiliser des entêtes sécurisés pour empêcher les attaquants d'utiliser des attaques courantes comme le cross-site scripting (XSS), le clickjacking et d'autres attaques malveillantes. Celles-ci peuvent être facilement configurées à l'aide de modules tels que [helmet](https://www.npmjs.com/package/helmet). + +**Autrement :** Les attaquants pourraient lancer des attaques directes sur les utilisateurs de votre application, ce qui entraînerait d'énormes vulnérabilités de sécurité. + +🔗 [**Plus d'infos : utilisation d'entêtes sécurisés dans votre application**](./sections/security/secureheaders.french.md) + +

+ +## ![✔] 6.7. Inspectez constamment et automatiquement les dépendances vulnérables + + + +**TL;PL :** Avec l'écosystème npm, il est courant d'avoir de nombreuses dépendances pour un projet. Les dépendances doivent toujours être contrôlées lorsque de nouvelles vulnérabilités sont détectées. Utilisez des outils comme [npm audit](https://docs.npmjs.com/cli/audit) ou [snyk](https://snyk.io/) pour suivre, surveiller et corriger les dépendances vulnérables. Intégrez ces outils à votre configuration CI afin de détecter une dépendance vulnérable avant qu'elle ne passe en production. + +**Autrement :** Un attaquant pourrait détecter votre framework Web et attaquer toutes ses vulnérabilités connues. + +🔗 [**Plus d'infos : sécurité des dépendances**](./sections/security/dependencysecurity.french.md) + +

+ +## ![✔] 6.8. Protégez les mots de passe/secrets des utilisateurs à l'aide de bcrypt ou scrypt + + + +**TL;PL :** Les mots de passe ou les secrets (par exemple les clés API) doivent être stockés en utilisant une fonction de hachage sécurisée + un salt comme `bcrypt`,`scrypt`, ou dans le pire des cas `pbkdf2`. + +**Autrement :** Les mots de passe et les secrets qui sont stockés sans utiliser de fonction sécurisée sont vulnérables au brute-force et aux attaques de dictionnaire qui mèneront à leur divulgation. + +🔗 [**Plus d'infos : mots de passe utilisateur**](./sections/security/userpasswords.french.md) + +

+ +## ![✔] 6.9. Échappez les sorties HTML, JS et CSS + + + +**TL;PL :** Les données non approuvées qui sont envoyées au navigateur peuvent être exécutées au lieu d'être simplement affichées, ce qui est communément appelé une attaque de script intersite (XSS). Atténuez cela en utilisant des bibliothèques dédiées qui marquent explicitement les données comme du contenu pur qui ne devrait jamais être exécuté (par exemple encodage, échappement). + +**Autrement :** Un attaquant pourrait stocker du code JavaScript malveillant dans votre base de données qui sera ensuite envoyé tel quel aux pauvres clients. + +🔗 [**Plus d'infos : échappez la sortie**](./sections/security/escape-output.french.md) + +

+ +## ![✔] 6.10. Validez les schémas JSON entrants + + + +**TL;PL :** Validez la charge utile du corps des requêtes entrantes et assurez-vous qu'elle répond aux exigences, sinon échouez rapidement. Pour éviter un codage de validation fastidieux pour chaque route, vous pouvez utiliser des schémas de validation légers basés sur JSON tels que [jsonschema](https://www.npmjs.com/package/jsonschema) ou [joi](https://www.npmjs.com/package/joi). + +**Autrement :** Votre générosité et votre approche permissive augmentent considérablement la surface d'attaque et encouragent l'attaquant à essayer de nombreuses entrées jusqu'à ce qu'il trouve une combinaison pour planter l'application. + +🔗 [**Plus d'infos : validez les schémas JSON entrants**](./sections/security/validation.french.md) + +

+ +## ![✔] 6.11. Prenez en charge le blocage des JWT + + + +**TL;PL :** Lorsque vous utilisez des jetons Web JSON (par exemple, avec [Passport.js](https://github.com/jaredhanson/passport)), il n'existe par défaut aucun mécanisme permettant de révoquer l'accès aux jetons émis. Lorsque vous découvrez une activité malveillante de la part d'un utilisateur, il n'y a aucun moyen de l'empêcher d'accéder au système tant qu'il détient un jeton valide. Pour atténuer ce problème, il est possible de mettre en place une liste de blocage des jetons non fiables qui sont validés à chaque requête. + +**Autrement :** Les jetons expirés ou égarés pourraient être utilisés de manière malveillante par un tiers pour accéder à une application et se faire passer pour le propriétaire du jeton. + +🔗 [**Plus d'infos : bloquez les jetons Web JSON**](./sections/security/expirejwt.french.md) + +

+ +## ![✔] 6.12. Empêchez les attaques brute-force perpétrées contre les autorisations + + + +**TL;PL :** Une technique simple et puissante consiste à limiter les tentatives d'autorisation en utilisant deux mesures : + +1. Le premier est le nombre de tentatives infructueuses consécutives par le même ID/nom unique d'utilisateur et la même adresse IP. +2. Le deuxième est le nombre de tentatives infructueuses à partir d'une adresse IP sur une longue période de temps. Par exemple, bloquez une adresse IP si elle fait 100 tentatives infructueuses en une journée. + +**Autrement :** Un attaquant peut lancer des tentatives de mot de passe automatisées illimitées pour accéder à des comptes privilégiés sur une application. + +🔗 [**Plus d'infos : restrictions du nombre de connexions**](./sections/security/login-rate-limit.french.md) + +

+ +## ![✔] 6.13. Exécutez Node.js en tant qu'utilisateur non root + + + +**TL;PL :** Il existe un scénario répandu dans lequel Node.js s'exécute en tant qu'utilisateur root avec des autorisations illimitées. Par exemple, c'est le comportement par défaut dans les conteneurs Docker. Il est recommandé de créer un utilisateur non root et de l'intégrer dans l'image du Docker (exemples donnés ci-dessous) ou d'exécuter le processus sous le nom de cet utilisateur en invoquant le conteneur avec l'indicateur « -u nom_utilisateur ». + +**Autrement :** Un attaquant qui réussit à exécuter un script sur le serveur obtient un pouvoir illimité sur la machine locale (par exemple, modifier iptable et réacheminer le trafic vers son serveur). + +🔗 [**Plus d'infos : exécutez Node.js en tant qu'utilisateur non root**](./sections/security/non-root-user.french.md) + +

+ +## ![✔] 6.14. Limitez la capacité des données utiles en utilisant un proxy inverse ou un middleware + + + +**TL;PL :** Plus les données utiles du corps sont grandes, plus votre processus unique travaille intensément pour les traiter. C'est l'occasion pour les attaquants de mettre les serveurs à genoux sans qu'il y ait beaucoup de requêtes (attaques DOS/DDOS). Atténuez cela en limitant la taille du corps des requêtes entrantes en périphérie (par exemple, pare-feu, ELB) ou en configurant [express body parser](https://github.com/expressjs/body-parser) pour accepter uniquement les données utiles de petite taille. + +**Autrement :** Votre application devra traiter des requêtes importantes, incapable de traiter les autres travaux importants qu'elle doit accomplir, ce qui aura des conséquences sur les performances et la vulnérabilité aux attaques DOS. +Votre application devra faire face à de grosses requêtes, incapable de traiter les autres travaux importants qu'elle doit accomplir, entraînant des implications en termes de performances et une vulnérabilité face aux attaques DOS. +🔗 [**Plus d'infos : limitez la capacité des données utiles**](./sections/security/requestpayloadsizelimit.french.md) + +

+ +## ![✔] 6.15. Évitez les instruction eval de JavaScript + + + +**TL;PL :** `eval` est diabolique car il permet d'exécuter du code JavaScript personnalisé pendant l'exécution. Il ne s'agit pas seulement d'un problème de performances, mais également d'un problème de sécurité important en raison du code JavaScript malveillant qui peut provenir de la saisie de l'utilisateur. Une autre fonctionnalité du langage à éviter est le constructeur `new Function`. Il ne faut pas non plus passer de code JavaScript dynamique à `setTimeout` et `setInterval`. + +**Autrement :** Un code JavaScript malveillant trouve un moyen d'accéder au texte passé dans `eval` ou d'autres fonctions d'évaluation en temps réel du langage JavaScript, et obtiendra un accès complet aux autorisations JavaScript sur la page. Cette vulnérabilité se manifeste souvent par une attaque XSS. + +🔗 [**Plus d'infos : évitez les instruction eval de JavaScript**](./sections/security/avoideval.french.md) + +

+ +## ![✔] 6.16. Empêchez une mauvaise RegEx de surcharger l'exécution de votre unique processus + + + +**TL;PL :** Les expressions régulières, bien qu'elles soient pratiques, constituent une réelle menace pour les applications JavaScript en général et la plateforme Node.js en particulier. La saisie d'un texte par l'utilisateur peut nécessiter un nombre exceptionnel de cycles du CPU pour être traitée. Le traitement RegEx pourrait être inefficace, à tel point qu'une seule requête qui valide 10 mots peut bloquer toute la boucle d'événement pendant 6 secondes et mettre l'unité centrale en 🔥. Pour cette raison, préférez les paquets de validation tiers comme [validator.js](https://github.com/chriso/validator.js) au lieu d'écrire vos propres modèles de regex, ou utilisez [safe-regex](https://github.com/substack/safe-regex) pour détecter les modèles de regex vulnérables. + +**Autrement :** Des RegEx mal écrites pourraient être susceptibles de faire l'objet d'attaques DoS par expression régulière qui bloqueraient complètement la boucle de l'événement. Par exemple, le populaire paquet "moment" a été déclaré vulnérable par une utilisation malveillante de RegEx en novembre 2017. + +🔗 [**Plus d'infos : empêcher une RegEx malveillante**](./sections/security/regex.french.md) + +

+ +## ![✔] 6.17. Évitez le chargement de modules à l'aide d'une variable + + + +**TL;PL :** Évitez de demander/importer un autre fichier dont le chemin d'accès a été donné en paramètre, car on peut craindre qu'il provienne d'une saisie de l'utilisateur. Cette règle peut être étendue pour l'accès aux fichiers en général (c'est-à-dire `fs.readFile()`) ou à d'autres ressources sensibles avec des variables dynamiques provenant d'une entrée utilisateur. Le linter [Eslint-plugin-security](https://www.npmjs.com/package/eslint-plugin-security) peut détecter de tels modèles et avertir suffisamment tôt. + +**Autrement :** Une entrée utilisateur malveillante pourrait trouver son chemin vers un paramètre qui est utilisé pour exiger des fichiers falsifiés, par exemple, un fichier précédemment téléchargé sur le système de fichiers, ou accéder à des fichiers système déjà existants. + +🔗 [**Plus d'infos : chargement sécurisé des modules**](./sections/security/safemoduleloading.french.md) + +

+ +## ![✔] 6.18. Exécutez un code dangereux dans un bac à sable + + + +**TL;PL :** Lorsqu'il s'agit d'exécuter du code externe donné en cours d'exécution (par exemple un plugin), utilisez un environnement d'exécution de type « bac à sable » (« sandbox ») qui isole et protège le code principal contre le plugin. Ceci peut être réalisé en utilisant un processus dédié (par exemple `cluster.fork()`), un environnement sans serveur ou des paquets npm dédiés qui agissent comme un bac à sable. + +**Autrement :** Un plugin peut attaquer à travers une variété infinie d'options comme les boucles infinies, la surcharge de la mémoire et l'accès aux variables sensibles de l'environnement du processus. + +🔗 [**Plus d'infos : exécutez un code dangereux dans un bac à sable**](./sections/security/sandbox.french.md) + +

+ +## ![✔] 6.19. Soyez particulièrement vigilants lorsque vous travaillez avec des processus fils + + + +**TL;PL :** Évitez d'utiliser des processus fils lorsque c'est possible et validez et assainissez les entrées pour atténuer les attaques par injection dans l'interface sytème si vous devez encore le faire. Préférez l'utilisation de `child_process.execFile` qui, par définition, n'exécutera qu'une seule commande avec un ensemble d'attributs et ne permettra pas l'expansion des paramètres de l'interface système. + +**Autrement :** L'utilisation naïve de processus fils pourrait entraîner l'exécution de commandes à distance ou des attaques par injection dans l'interface système en raison d'une entrée utilisateur malveillante transmise à une commande système non assainie. + +🔗 [**Plus d'infos : soyez prudents lorsque vous travaillez avec des processus fils**](./sections/security/childprocesses.french.md) + +

+ +## ![✔] 6.20. Masquez les détails des erreurs aux clients + + + +**TL;PL :** Un gestionnaire d'erreur express intégré masque les détails de l'erreur par défaut. Cependant, il y a de grandes chances que vous implémentiez votre propre logique de traitement des erreurs avec des objets d'erreur personnalisés (considérés par beaucoup comme une meilleure pratique). Si vous le faites, veillez à ne pas renvoyer l'objet Error complet au client, qui pourrait contenir certains détails sensibles de l'application. + +**Autrement :** Des détails sensibles de l'application pourraient être divulgués à partir d'informations trouvées dans une trace de pile, tels que les chemins d'accès aux fichiers du serveur, les modules tiers utilisés et d'autres flux de travail internes de l'application qui pourraient être exploités par un attaquant. + +🔗 [**Plus d'infos : masquez les détails des erreurs au client**](./sections/security/hideerrors.french.md) + +

+ +## ![✔] 6.21. Configurez 2FA pour npm ou Yarn + + + +**TL;PL :** Toute étape de la chaîne de développement doit être protégée par une authentification multi-facteurs (MFA). npm/Yarn sont une belle opportunité pour les attaquants qui peuvent mettre la main sur le mot de passe d'un développeur. En utilisant les identifiants des développeurs, les attaquants peuvent injecter du code malveillant dans des bibliothèques qui sont largement installées dans les projets et les services. Peut-être même sur le web s'ils sont publiés publiquement. L'activation de l'authentification à deux facteurs dans npm ne laisse pratiquement aucune chance aux attaquants de modifier le code de votre paquet. + +**Autrement :** [Avez-vous entendu parler du développeur d'eslint dont le mot de passe a été piraté ?](https://medium.com/@oprearocks/eslint-backdoor-what-it-is-and-how-to-fix-the-issue-221f58f1a8c8) + +

+ +## ![✔] 6.22. Modifiez les paramètres du middleware de session + + + +**TL;PL :** Chaque framework et technologie web a ses faiblesses connues - dire à un attaquant quel framework web nous utilisons est d'une grande aide pour lui. L'utilisation des paramètres par défaut des middlewares de session peut exposer votre application à des attaques de détournement sur un module ou un framework spécifique, de la même manière que l'entête « X-Powered-By ». Essayez de cacher tout ce qui identifie et révèle votre pile technique (par exemple, Node.js, express). + +**Autrement :** Les cookies peuvent être envoyés via des connexions non sécurisées, et un attaquant peut utiliser l'identification de session pour identifier le framework sous-jacent de l'application web, ainsi que les vulnérabilités spécifiques aux modules. + +🔗 [**Plus d'infos : cookie et sécurité des sessions**](./sections/security/sessions.french.md) + +

+ +## ![✔] 6.23. Évitez les attaques DOS en définissant explicitement le moment où un processus doit s'interrompre + + + +**TL;PL :** Le processus de Node plante lorsque les erreurs ne sont pas gérées. De nombreuses bonnes pratiques recommandent même de quitter Node même si une erreur a été détectée et traitée. Express, par exemple, plante sur toutes les erreurs asynchrones - à moins que vous n'ayez inclus une clause catch dans les routes. Cela ouvre un point d'attaque très intéressant pour les attaquants qui reconnaissent quelle entrée fait planter le processus et envoient la même requête de manière répétée. Il n'y a pas de remède immédiat à ce problème, mais quelques techniques peuvent atténuer la menace : alertez avec une gravité critique chaque fois qu'un processus se bloque à cause d'une erreur non gérée, valider l'entrée et éviter de planter le processus à cause d'une entrée utilisateur non valide, englober toutes les routes d'une clause catch et envisager de ne pas planter lorsqu'une erreur a été commise dans une requête (par opposition à ce qui se passe globalement). + +**Autrement :** Ce n'est qu'une intuition : étant donné le grand nombre d'applications Node.js, si nous essayons de faire passer un corps JSON vide à toutes les requêtes POST - une poignée d'applications plantera. À ce stade, il suffit de répéter l'envoi de la même requête pour faire tomber les applications avec facilité. + +

+ +## ![✔] 6.24. Empêchez les redirections dangereuses + + + +**TL;PL :** Les redirections qui ne valident pas les entrées de l'utilisateur peuvent permettre aux attaquants de lancer des attaques de phishing, de voler les identifiants de l'utilisateur et d'effectuer d'autres actions malveillantes. + +**Autrement :** Si un attaquant découvre que vous ne validez pas les données externes fournies par l'utilisateur, il peut exploiter cette vulnérabilité en publiant des liens spécialement conçus sur des forums, des médias sociaux et d'autres lieux publics pour inciter les utilisateurs à cliquer. + +🔗 [**Plus d'infos : empêchez les redirections dangereuses**](./sections/security/saferedirects.french.md) + +

+ +## ![✔] 6.25. Évitez de publier des secrets dans le registre npm + + + +**TL;PL :** Des précautions doivent être prises pour éviter le risque de publier accidentellement des secrets dans les registres publics de npm. Un fichier `.npmignore` peut être utilisé pour ignorer des fichiers ou des dossiers spécifiques, ou le tableau `files` dans `package.json` peut agir comme une liste d'autorisation. + +**Autrement :** Les clés API, mots de passe ou autres secrets de votre projet sont susceptibles d'être utilisés abusivement par toute personne qui les découvre, ce qui peut entraîner des pertes financières, une usurpation d'identité et d'autres risques. + +🔗 [**Plus d'infos : évitez de publier des secrets**](./sections/security/avoid_publishing_secrets.french.md) +


+ +

⬆ Retourner en haut de la page

+ +# `7. Brouillon : Bonnes pratiques de performance` + +## Nos contributeurs travaillent sur cette section. [Voulez-vous nous rejoindre ?](https://github.com/goldbergyoni/nodebestpractices/issues/256) + +

+ +## ![✔] 7.1. Ne bloquez pas la boucle d'événement + +**TL;PL :** Évitez les tâches gourmandes en CPU car elles bloqueront la boucle d'événement principalement mono-thread, il faut les décharger vers un thread dédié, un processus ou même une technologie différente en fonction du contexte. + +**Autrement :** Comme la boucle d'événements est bloquée, Node.js sera incapable de traiter d'autres requêtes, ce qui entraînera des retards pour les utilisateurs concurrents. **3000 utilisateurs attendent une réponse, le contenu est prêt à être servi, mais une seule requêtes bloque le serveur pour qu'il ne puisse pas renvoyer les résultats**. + +🔗 [**Plus d'infos : ne bloquez pas la boucle d'événement**](./sections/performance/block-loop.french.md) + +


+ +## ![✔] 7.2. Préférez les méthodes JS natives aux utilitaires comme Lodash + +**TL;PL :** Il est souvent plus pénalisant d'utiliser des bibliothèques utilitaires telles que `lodash` et `underscore` plutôt que des méthodes natives car cela conduit à des dépendances inutiles et à des performances plus lentes. +Gardez à l'esprit qu'avec l'introduction du nouveau moteur V8 en parallèle des nouvelles normes ES, les méthodes natives ont été améliorées de telle manière qu'elles sont maintenant environ 50% plus performantes que les bibliothèques utilitaires. + +**Autrement :** Vous devez maintenir des projets moins performants où vous auriez pu simplement utiliser ce qui était **déjà** disponible ou traiter quelques lignes supplémentaires en échange de quelques fichiers supplémentaires. + +🔗 [**Plus d'infos : natif supérieur aux utilitaires**](./sections/performance/nativeoverutil.french.md) + +


+ +

⬆ Retourner en haut de la page

+ +# `8. Bonnes pratiques de Docker` + +🏅 Un grand merci à [Bret Fisher](https://github.com/BretFisher) de qui nous avons appris plusieurs des pratiques suivantes + +

+ +## ![✔] 8.1 Utilisez multi-stage builds pour des images Docker plus légères et plus sûres + +**TL;PL :** Utilisez multi-stage builds pour copier uniquement les artefacts de production nécessaires. Un grand nombre de dépendances et de fichiers au moment de la construction ne sont pas nécessaires pour exécuter votre application. Avec multi-stage builds, ces ressources peuvent être utilisées pendant la construction tandis que l'environnement d'exécution ne contient que ce qui est nécessaire. multi-stage builds est un moyen facile de se débarrasser du surpoids et des menaces de sécurité. + +**Autrement :** Les images plus grandes prendront plus de temps à construire et à livrer. Les outils uniquement de construction peuvent contenir des vulnérabilités. Et des secrets destinés uniquement à la phase de construction peuvent être divulgués. + +### Exemple de Dockerfile pour le multi-stage builds + +```dockerfile +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" ] +``` + +🔗 [**Plus d'infos : utilisez multi-stage builds**](./sections/docker/multi_stage_builds.french.md) + +


+ +## ![✔] 8.2. Démarrez à l'aide de la commande `node`, évitez `npm start` + +**TL;PL :** Utilisez `CMD ['node','server.js']` pour démarrer votre application, évitez d'utiliser des scripts npm qui ne transmettent pas les signaux du système d'exploitation au code. Cela empêche les problèmes de processus fils, de gestion du signal, d'arrêt progressif et de processus zombies. + +**Autrement :** Si aucun signal n'est transmis, votre code ne sera jamais notifié des interruptions. Sans cela, il perdra sa chance de se fermer correctement, ce qui pourrait entraîner la perte de requêtes et/ou de données en cours. + +[**Plus d'infos : Démarrez un conteneur à l'aide de la commande node, évitez npm start**](./sections/docker/bootstrap-using-node.french.md) + +


+ +## ![✔] 8.3. Laissez le système d'exécution Docker s'occuper de la réplication et de la disponibilité + +**TL;PL :** Lorsque vous utilisez un orchestrateur d'exécution Docker (par exemple, Kubernetes), appelez le processus Node.js directement sans gestionnaires de processus intermédiaires ou code personnalisé qui réplique le processus (par exemple, PM2, module Cluster). La plateforme d'exécution possède la plus grande quantité de données et la meilleure visibilité pour prendre des décisions de placement - Elle sait mieux que quiconque combien de processus sont nécessaires, comment les répartir et quoi faire en cas de plantage. + +**Autrement :** Le conteneur continue de se planter par manque de ressources et sera redémarré indéfiniment par le responsable du processus. Si Kubernetes est au courant de cela, il pourrait le déplacer vers une autre instance plus importante. + +🔗 [**Plus d'infos : laissez l'orchestrateur Docker redémarrer et répliquer les processus**](./sections/docker/restart-and-replicate-processes.french.md) + +


+ +## ![✔] 8.4. Utilisez .dockerignore pour éviter les divulgations de secrets + +**TL;PL :** Ajoutez un fichier `.dockerignore` qui filtre les fichiers secrets courants et les artefacts de développement. Ainsi, vous pouvez éviter que des secrets ne s'infiltrent dans l'image. En prime, le temps de construction sera considérablement réduit. De plus, assurez-vous de ne pas copier tous les fichiers récursivement, choisissez plutôt explicitement ce qui doit être copié dans Docker. + +**Autrement :** Les fichiers secrets personnels habituels comme `.env`, `.aws` et `.npmrc` seront partagés avec toute personne ayant accès à l'image (par exemple le dépôt Docker). + +🔗 [**Plus d'infos : utilisez .dockerignore**](./sections/docker/docker-ignore.french.md) + +


+ +## ![✔] 8.5. Nettoyez les dépendances avant la production + +**TL;PL :** Bien que des dépendances de développement soient parfois nécessaires pendant le cycle de vie de la construction et des tests, l'image qui est envoyée à la production doit être minimale et exempte de toute dépendance de développement. Cela garantit que seul le code nécessaire est livré et que la quantité d'attaques potentielles (c'est-à-dire la surface d'attaque) soit réduite au minimum. Lorsque l'on utilise un multi-stage build (voir le point consacré à ce sujet), cela peut être réalisé en installant d'abord toutes les dépendances et en exécutant enfin `npm ci --production`. + +**Autrement :** De nombreuses failles célèbres de sécurité de npm ont été trouvées dans des packages de développement (par exemple [eslint-scope](https://eslint.org/blog/2018/07/postmortem-for-malicious-package-publishes)) + +🔗 Plus d'infos : [supprimez les dépendances de développement](./sections/docker/install-for-production.french.md) + +


+ +## ![✔] 8.6. Arrêtez intelligemment et progressivement + +**TL;PL :** Gérez l'événement SIGTERM du processus et nettoyez toutes les connexions et ressources existantes. Cela doit être fait tout en répondant aux requêtes en cours. Dans des environnements d'exécution Dockerisés, l'arrêt des conteneurs n'est pas un événement rare, mais plutôt une occurrence fréquente qui se produit dans le cadre du travail routinier. Pour y parvenir, il faut un code réfléchi pour orchestrer plusieurs pièces mobiles : l'équilibreur de charge, les connexions persistantes, le serveur HTTP et d'autres ressources. + +**Autrement :** S'éteindre immédiatement signifie ne pas répondre aux milliers d'utilisateurs qui seront déçus. + +🔗 [**Plus d'infos : arrêt progressif**](./sections/docker/graceful-shutdown.french.md) + +


+ +## ![✔] 8.7. Définissez des limites de mémoire en utilisant à la fois Docker et v8 + +**TL;PL :** Configurez toujours une limite de mémoire en utilisant à la fois Docker et les indicateurs d'exécution JavaScript. La limite de Docker est nécessaire pour prendre une décision judicieuse de placement des conteneurs, l'indicateur max-old-space de --v8 est nécessaire pour lancer le GC à temps et éviter la sous-utilisation de la mémoire. Concrètement, il faut que cet indicateur de v8 soit juste un peu plus petit que la limite du conteneur. + +**Autrement :** La définition de docker est nécessaire pour prendre une décision judicieuse pour la mise à l'échelle et éviter de priver d'autres consommateurs de mémoire. Sans définir également les limites de v8, il sous-utilisera les ressources du conteneur - Sans instructions explicites, il se plantera lorsqu'il utilisera ~50-60% des ressources de ses hôtes. + +🔗 [**Plus d'infos : définissez des limites de mémoire en utilisant uniquement Docker**](./sections/docker/memory-limit.french.md) + +


+ +## ![✔] 8.8. Organisez une mise en cache efficace + +**TL;PL :** La reconstruction d'une image entière de docker à partir du cache peut être presque instantanée si elle est faite correctement. Les instructions qui changent peu devraient se trouver en haut de votre Dockerfile et celles qui changent constamment (comme le code de l'application) devraient se trouver en bas. + +**Autrement :** La construction de docker sera très longue et consommera beaucoup de ressources, même en cas de changements minimes. + +🔗 [**Plus d'infos : exploiter la mise en cache pour réduire les temps de construction**](./sections/docker/use-cache-for-shorter-build-time.french.md) + +


+ +## ![✔] 8.9. Utilisez une référence explicite de l'image, évitez le tag `latest` + +**TL;PL :** Précisez un condensé (_digest_) d'image explicite ou une étiquette versionnée, ne faites jamais référence à `latest`. Les développeurs sont souvent amenés à croire que la spécification du tag `latest` leur fournira l'image la plus récente dans le dépôt, mais ce n'est pas le cas. L'utilisation d'un digest garantit que chaque instance du service exécute exactement le même code. + +En outre, la référence à un tag d'une image signifie que l'image de base est sujette à des modifications, car on ne peut pas se fier aux tags image pour une installation déterminée. En revanche, si une installation déterminée est prévue, un digest SHA256 peut être utilisé pour faire référence à une image exacte. + +**Autrement :** Une nouvelle version d'une image de base pourrait être déployée en production avec des modifications importantes, provoquant un comportement non souhaité de l'application. + +🔗 [**Plus d'infos : Comprendre les tags d'image et utiliser le tag "latest" avec précaution**](./sections/docker/image-tags.french.md) + +


+ +## ![✔] 8.10. Privilégiez les plus petites images de base Docker + +**TL;PL :** Les images de grande taille entraînent une plus grande exposition aux vulnérabilités et une consommation accrue des ressources. L'utilisation d'images Docker plus fines, telles que les variantes Slim et Alpine de Linux, atténue ce problème. + +**Autrement :** Construire, pousser et tirer des images prendra plus de temps, des vecteurs d'attaque inconnus peuvent être utilisés par des acteurs malveillants et plus de ressources sont consommées. + +🔗 [**Plus d'infos : privilégiez les plus petites images**](./sections/docker/smaller_base_images.french.md) + +


+ +## ![✔] 8.11. Nettoyez les secrets de construction, évitez les secrets dans les arguments + +**TL;PL :** Évitez que des secrets ne s'échappent de l'environnement de construction du Docker. Une image Docker est généralement partagée dans plusieurs environnements comme les CI et un registre qui ne sont pas aussi aseptisés que la production. Un exemple typique est un jeton npm qui est généralement transmis à un fichier Docker en tant qu'argument. Ce jeton reste dans l'image longtemps après qu'on en ait eu besoin et permet à l'attaquant d'accéder indéfiniment à un registre npm privé. Cela peut être évité en copiant un fichier secret comme `.npmrc` et en le supprimant en utilisant une construction en plusieurs étapes (attention, l'historique de la construction doit également être supprimé) ou en utilisant la fonctionnalité secrète Docker build-kit qui ne laisse aucune trace. + +**Autrement :** Toute personne ayant accès au CI et au registre des dockers aura également accès, en prime, à certains secrets précieux de l'organisation + +🔗 [**Plus d'infos : nettoyez les secrets de construction**](./sections/docker/avoid-build-time-secrets.french.md) + +


+ +## ![✔] 8.12. Analysez les images pour détecter les multiples catégories de vulnérabilités + +**TL;PL :** En plus de vérifier les vulnérabilités des dépendances du code, il analyse également l'image finale qui est envoyée à la production. Les scanners d'images Docker vérifient les dépendances du code mais aussi les binaires du système d'exploitation. Ce scan de sécurité E2E couvre plus de terrain et vérifie qu'aucun mauvais gars n'a injecté de mauvaises choses pendant la construction. Par conséquent, il est recommandé de l'exécuter comme dernière étape avant le déploiement. Il existe une poignée de scanners gratuits et commerciaux qui fournissent également des plugins CI/CD. + +**Autrement :** Votre code pourrait être entièrement exempt de vulnérabilités. Cependant, il peut être piraté en raison de la vulnérabilité des versions binaires au niveau OS (par exemple, OpenSSL, TarBall) qui sont couramment utilisées par les applications. + +🔗 [**Plus d'infos : scannez l'ensemble de l'image avant la production**](./sections/docker/scan-images.french.md) + +


+ +## ![✔] 8.13 Nettoyez le cache NODE_MODULE + +**TL;PL :** Après avoir installé les dépendances dans un conteneur, il faut supprimer le cache local. Il n'est pas logique de dupliquer les dépendances pour des installations futures plus rapides puisqu'il n'y aura pas d'autres installations - Une image du Docker est immuable. Une image du Docker est immuable. En utilisant une seule ligne de code, des dizaines de Mo (généralement 10 à 50 % de la taille de l'image) sont supprimées. + +**Autrement :** L'image qui sera envoyée à la production pèsera 30 % de plus à cause de fichiers qui ne seront jamais utilisés. + +🔗 [**Plus d'infos : nettoyez le cache NODE_MODULE**](./sections/docker/clean-cache.french.md) + +


+ +## ![✔] 8.14. Les pratiques de Docker en général + +**TL;PL :** Il s'agit d'un recueil de conseils de Docker qui n'est pas directement lié à Node.js - la mise en œuvre de Node n'est pas très différente de celle de tout autre langage. Cliquez pour en savoir plus. + +🔗 [**Plus d'infos : les pratiques de Docker en général**](./sections/docker/generic-tips.french.md) + +


+ +## ![✔] 8.15. Lintez votre Dockerfile + +**TL;PL :** Linter votre Dockerfile est une étape importante pour identifier les problèmes de votre Dockerfile qui diffèrent des meilleures pratiques. En vérifiant les failles potentielles à l'aide d'un linter Docker spécialisé, les améliorations de performance et de sécurité peuvent être facilement identifiées, ce qui permet d'économiser d'innombrables heures de perte de temps ou des problèmes de sécurité dans le code de production. + +**Autrement :** Par erreur, le créateur du Dockerfile a laissé Root comme utilisateur de production, et a également utilisé une image provenant d'un dépôt de source inconnue. Cela pourrait être évité avec un simple linter. + +🔗 [**Plus d'infos : lintez your Dockerfile**](./sections/docker/lint-dockerfile.french.md) + +


+ +

⬆ Return to top

+ +# Jalons + +Pour maintenir ce guide et le tenir à jour, nous actualisons et améliorons constamment les lignes directrices et les meilleures pratiques avec l'aide de la communauté. Vous pouvez suivre nos [jalons](https://github.com/goldbergyoni/nodebestpractices/milestones) et rejoindre les groupes de travail si vous souhaitez contribuer à ce projet + +
+ +## Traductions + +Toutes les traductions sont fournies par la communauté. Nous serons heureux de recevoir toute aide concernant les traductions terminées, en cours ou nouvelles ! + +### Traductions terminées + +- ![BR](./assets/flags/BR.png) [Portugais brésilien](./README.brazilian-portuguese.md) - Avec l'aimable autorisation de [Marcelo Melo](https://github.com/marcelosdm) +- ![CN](./assets/flags/CN.png) [Chinois](./README.chinese.md) - Avec l'aimable autorisation de [Matt Jin](https://github.com/mattjin) +- ![RU](./assets/flags/RU.png) [Russe](./README.russian.md) - Avec l'aimable autorisation de [Alex Ivanov](https://github.com/contributorpw) +- ![PL](./assets/flags/PL.png) [Polonais](./README.polish.md) - Avec l'aimable autorisation de [Michal Biesiada](https://github.com/mbiesiad) +- ![JA](./assets/flags/JA.png) [Japonais](./README.japanese.md) - Avec l'aimable autorisation de [Yuki Ota](https://github.com/YukiOta), [Yuta Azumi](https://github.com/YA21) +- ![EU](./assets/flags/EU.png) [Basque](README.basque.md) - Avec l'aimable autorisation de [Ane Diaz de Tuesta](https://github.com/anediaz) & Joxefe Diaz de Tuesta + +### Traductions en cours + +- ![FR](./assets/flags/FR.png) [Français](./README.french.md) ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/129)) +- ![HE](./assets/flags/HE.png) Hébreu ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/156)) +- ![KR](./assets/flags/KR.png) [Coréen](README.korean.md) - Avec l'aimable autorisation de [Sangbeom Han](https://github.com/uronly14me) ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/94)) +- ![ES](./assets/flags/ES.png) [Espagnol](https://github.com/goldbergyoni/nodebestpractices/blob/spanish-translation/README.spanish.md) ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/95)) +- ![TR](./assets/flags/TR.png) Turque ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/139)) + +

+ +## Comité de pilotage + +Rencontrez les membres du comité de pilotage - les personnes qui travaillent ensemble pour fournir des conseils et des orientations futures au projet. En outre, chaque membre du comité dirige un projet suivi dans le cadre de nos [projets GitHub](https://github.com/goldbergyoni/nodebestpractices/projects). + + + +[Yoni Goldberg](https://github.com/goldbergyoni) + + + +Consultant indépendant Node.js qui travaille avec des clients aux États-Unis, en Europe et en Israël sur la construction d'applications Node.js à grande échelle. Nombre des meilleures pratiques ci-dessus ont été publiées pour la première fois sur [goldbergyoni.com](https://goldbergyoni.com). Contactez Yoni via [@goldbergyoni](https://github.com/goldbergyoni) ou [me@goldbergyoni.com](mailto:me@goldbergyoni.com) + +
+ + + +[Bruno Scheufler](https://github.com/BrunoScheufler) + + +💻 ingénieur web full-stack, passionné de Node.js & GraphQL + +
+ + + +[Kyle Martin](https://github.com/js-kyle) + + + +Développeur Full Stack et ingénieur de fiabilité de site basé en Nouvelle-Zélande, intéressé par la sécurité des applications web, et l'architecture et la construction d'applications Node.js pour fonctionner à l'échelle mondiale. + +
+ + + +[Kevyn Bruyere](https://github.com/kevynb) + + +Développeur indépendant full-stack ayant un penchant pour les Ops et l'automatisation. + +
+ +### Comité de pilotage émérite + + + +[Sagir Khan](https://github.com/sagirk) + + + + +Spécialiste de JavaScript et de son écosystème - React, Node.js, TypeScript, GraphQL, MongoDB, à peu près tout ce qui implique JS/JSON dans n'importe quelle couche du système - construisant des produits en utilisant la plateforme web pour les marques les plus reconnues au monde. Membre individuel de la Fondation Node.js. + +
+ +## Collaborateurs + +Merci à tous nos collaborateurs ! 🙏 + +Nos collaborateurs sont des membres qui contribuent régulièrement au dépôt, en suggérant de nouvelles bonnes pratiques, en triant les issues, en examinant les pull request et bien d'autres choses encore. Si vous souhaitez nous aider à guider des milliers de personnes à créer de meilleures applications Node.js, veuillez lire nos [directives pour les contributeurs](./.operations/CONTRIBUTING.md) 🎉 + +| | | Raz Luvaton | Josh Hemphill | +| :--: | :--: | :--: | :--: | +| [Ido Richter (Founder)](https://github.com/idori) | [Keith Holliday](https://github.com/TheHollidayInn) | [Raz Luvaton](https://github.com/rluvaton) | [Josh Hemphill](https://github.com/josh-hemphill) | + +### Collaborateur émérite + +| | +| :-------------------------------------------------------------------------------------------------------------------------: | +| [Refael Ackermann](https://github.com/refack) | + +
+ +## Contribution + +Si vous avez toujours voulu contribuer à l'open source, voici votre chance ! Consultez les [documents de contributions](.operations/CONTRIBUTING.md) pour plus d'information. + +## Contributeurs ✨ + +Merci à ces merveilleuses personnes qui ont contribué à ce dépôt ! + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Kevin Rambaud
Kevin Rambaud

🖋
Michael Fine
Michael Fine

🖋
Shreya Dahal
Shreya Dahal

🖋
Matheus Cruz Rocha
Matheus Cruz Rocha

🖋
Yog Mehta
Yog Mehta

🖋
Kudakwashe Paradzayi
Kudakwashe Paradzayi

🖋
t1st3
t1st3

🖋
mulijordan1976
mulijordan1976

🖋
Matan Kushner
Matan Kushner

🖋
Fabio Hiroki
Fabio Hiroki

🖋
James Sumners
James Sumners

🖋
Dan Gamble
Dan Gamble

🖋
PJ Trainor
PJ Trainor

🖋
Remek Ambroziak
Remek Ambroziak

🖋
Yoni Jah
Yoni Jah

🖋
Misha Khokhlov
Misha Khokhlov

🖋
Evgeny Orekhov
Evgeny Orekhov

🖋
-
-

🖋
Isaac Halvorson
Isaac Halvorson

🖋
Vedran Karačić
Vedran Karačić

🖋
lallenlowe
lallenlowe

🖋
Nathan Wells
Nathan Wells

🖋
Paulo Reis
Paulo Reis

🖋
syzer
syzer

🖋
David Sancho
David Sancho

🖋
Robert Manolea
Robert Manolea

🖋
Xavier Ho
Xavier Ho

🖋
Aaron
Aaron

🖋
Jan Charles Maghirang Adona
Jan Charles Maghirang Adona

🖋
Allen
Allen

🖋
Leonardo Villela
Leonardo Villela

🖋
Michał Załęcki
Michał Załęcki

🖋
Chris Nicola
Chris Nicola

🖋
Alejandro Corredor
Alejandro Corredor

🖋
cwar
cwar

🖋
Yuwei
Yuwei

🖋
Utkarsh Bhatt
Utkarsh Bhatt

🖋
Duarte Mendes
Duarte Mendes

🖋
Jason Kim
Jason Kim

🖋
Mitja O.
Mitja O.

🖋
Sandro Miguel Marques
Sandro Miguel Marques

🖋
Gabe
Gabe

🖋
Ron Gross
Ron Gross

🖋
Valeri Karpov
Valeri Karpov

🖋
Sergio Bernal
Sergio Bernal

🖋
Nikola Telkedzhiev
Nikola Telkedzhiev

🖋
Vitor Godoy
Vitor Godoy

🖋
Manish Saraan
Manish Saraan

🖋
Sangbeom Han
Sangbeom Han

🖋
blackmatch
blackmatch

🖋
Joe Reeve
Joe Reeve

🖋
Ryan Busby
Ryan Busby

🖋
Iman Mohamadi
Iman Mohamadi

🖋
Sergii Paryzhskyi
Sergii Paryzhskyi

🖋
Kapil Patel
Kapil Patel

🖋
迷渡
迷渡

🖋
Hozefa
Hozefa

🖋
Ethan
Ethan

🖋
Sam
Sam

🖋
Arlind
Arlind

🖋
Teddy Toussaint
Teddy Toussaint

🖋
Lewis
Lewis

🖋
Gabriel Lidenor
Gabriel Lidenor

🖋
Roman
Roman

🖋
Francozeira
Francozeira

🖋
Invvard
Invvard

🖋
Rômulo Garofalo
Rômulo Garofalo

🖋
Tho Q Luong
Tho Q Luong

🖋
Burak Shen
Burak Shen

🖋
Martin Muzatko
Martin Muzatko

🖋
Jared Collier
Jared Collier

🖋
Hilton Meyer
Hilton Meyer

🖋
ChangJoo Park(박창주)
ChangJoo Park(박창주)

🖋
Masahiro Sakaguchi
Masahiro Sakaguchi

🖋
Keith Holliday
Keith Holliday

🖋
coreyc
coreyc

🖋
Maximilian Berkmann
Maximilian Berkmann

🖋
Douglas Mariano Valero
Douglas Mariano Valero

🖋
Marcelo Melo
Marcelo Melo

🖋
Mehmet Perk
Mehmet Perk

🖋
ryan ouyang
ryan ouyang

🖋
Shabeer
Shabeer

🖋
Eduard Kyvenko
Eduard Kyvenko

🖋
Deyvison Rocha
Deyvison Rocha

🖋
George Mamer
George Mamer

🖋
Konstantinos Leimonis
Konstantinos Leimonis

🖋
Oliver Lluberes
Oliver Lluberes

🌍
Tien Do
Tien Do

🖋
Ranvir Singh
Ranvir Singh

🖋
Vadim Nicolaev
Vadim Nicolaev

🖋 🌍
German Gamboa Gonzalez
German Gamboa Gonzalez

🖋
Hafez
Hafez

🖋
Chandiran
Chandiran

🖋
VinayaSathyanarayana
VinayaSathyanarayana

🖋
Kim Kern
Kim Kern

🖋
Kenneth Freitas
Kenneth Freitas

🖋
songe
songe

🖋
Kirill Shekhovtsov
Kirill Shekhovtsov

🖋
Serge
Serge

🖋
keyrwinz
keyrwinz

🖋
Dmitry Nikitenko
Dmitry Nikitenko

🖋
bushuai
bushuai

👀 🖋
Benjamin Gruenbaum
Benjamin Gruenbaum

🖋
Ezequiel
Ezequiel

🌍
Juan José Rodríguez
Juan José Rodríguez

🌍
Or Bin
Or Bin

🖋
Andreo Vieira
Andreo Vieira

🖋
Michael Solomon
Michael Solomon

🖋
Jimmy Callin
Jimmy Callin

🖋
Siddharth
Siddharth

🖋
Ryan Smith
Ryan Smith

🖋
Tom Boettger
Tom Boettger

🖋
Joaquín Ormaechea
Joaquín Ormaechea

🌍
dfrzuz
dfrzuz

🌍
Victor Homyakov
Victor Homyakov

🖋
Josh
Josh

🖋 🛡️
Alec Francis
Alec Francis

🖋
arjun6610
arjun6610

🖋
Jan Osch
Jan Osch

🖋
Thiago Rotondo Sampaio
Thiago Rotondo Sampaio

🌍
Alexsey
Alexsey

🖋
Luis A. Acurero
Luis A. Acurero

🌍
Lucas Romano
Lucas Romano

🌍
Denise Case
Denise Case

🖋
Nick Ribal
Nick Ribal

🖋 👀
0xflotus
0xflotus

🖋
Jonathan Chen
Jonathan Chen

🖋
Dilan Srilal
Dilan Srilal

🖋
vladthelittleone
vladthelittleone

🌍
Nik Osvalds
Nik Osvalds

🖋
Daniel Kiss
Daniel Kiss

📖
Forresst
Forresst

🖋
Jonathan Svenheden
Jonathan Svenheden

🖋
AustrisC
AustrisC

🖋
kyeongtae kim
kyeongtae kim

🌍
007
007

🖋
Ane Diaz de Tuesta
Ane Diaz de Tuesta

🌍 🖋
YukiOta
YukiOta

🌍
Frazer Smith
Frazer Smith

🖋
Raz Luvaton
Raz Luvaton

🖋
Yuta Azumi
Yuta Azumi

🖋
andrewjbarbour
andrewjbarbour

🖋
mr
mr

🖋
Aleksandar
Aleksandar

🖋
Owl
Owl

🖋
Yedidya Schwartz
Yedidya Schwartz

🖋 💡
ari
ari

🖋
Thomas König
Thomas König

🖋
Kalle Lämsä
Kalle Lämsä

🖋
Wyatt
Wyatt

🖋
KHADIR Tayeb
KHADIR Tayeb

🖋
Shankar Regmi
Shankar Regmi

🖋
Shubham
Shubham

🖋
Lucas Alves
Lucas Alves

🖋
Benjamin
Benjamin

🖋
Yeoh Joer
Yeoh Joer

🖋
Miigon
Miigon

🖋
Rostislav Bogorad
Rostislav Bogorad

🖋
Flouse
Flouse

🖋
Tarantini Pereira
Tarantini Pereira

🖋
Kazuki Matsuo
Kazuki Matsuo

🖋
Adam Smith
Adam Smith

🖋
Dohyeon Ko
Dohyeon Ko

🖋
Vladislav Legkov
Vladislav Legkov

🖋
Kerollos Magdy
Kerollos Magdy

🖋
Erez Lieberman
Erez Lieberman

🖋
Breno Macedo
Breno Macedo

🖋
Fernando Flores
Fernando Flores

🌍
Rafael Brito
Rafael Brito

🌍
Emiliano Peralta
Emiliano Peralta

🌍
Shin, SJ
Shin, SJ

🖋
Benjamin Forster
Benjamin Forster

🖋
Daniele Fedeli
Daniele Fedeli

🖋
djob195
djob195

🖋
antspk
antspk

🖋
정진영
정진영

🖋
kkk-cashwalk
kkk-cashwalk

🖋
apainintheneck
apainintheneck

🖋
Fajar Budhi Iswanda
Fajar Budhi Iswanda

🖋
이주호
이주호

🖋
Singh
Singh

🖋
Alex Dumitru
Alex Dumitru

🖋
Anton Lykhatskyi
Anton Lykhatskyi

🖋
sangwonlee
sangwonlee

🖋
Eugenio Berretta
Eugenio Berretta

🖋
soranakk
soranakk

🖋
고준영
고준영

🖋 💻
Guilherme Portella
Guilherme Portella

🖋
André Esser
André Esser

🖋
Scc
Scc

🌍
Mauro Accornero
Mauro Accornero

🖋
no-yan
no-yan

🖋
+ + + + + diff --git a/README.hebrew.md b/README.hebrew.md new file mode 100644 index 000000000..22d5ce0ba --- /dev/null +++ b/README.hebrew.md @@ -0,0 +1,1927 @@ +[✔]: assets/images/checkbox-small-blue.png + +# שיטות עבודה מומלצות ב Node.js + +

+ Node.js Best Practices +

+ +
+ +
+ 102 items Last update: August 16, 2023 Updated for Node 14.0.0 +
+ +
+ +[](https://twitter.com/nodepractices/) **עיקבו אחרינו בטוויטר!** [**@nodepractices**](https://twitter.com/nodepractices/) +
+**:writing_hand: תורגם על ידי [הוד בואר](https://github.com/hodbauer)** +
+ +לקריאה בשפות נוספות: [![CN](./assets/flags/CN.png)**סינית**](./README.chinese.md), [![FR](./assets/flags/FR.png)**צרפתית**](./README.french.md), [![BR](./assets/flags/BR.png)**פורטוגזית**](./README.brazilian-portuguese.md), [![RU](./assets/flags/RU.png)**רוסית**](./README.russian.md), [![PL](./assets/flags/PL.png)**פולנית**](./README.polish.md), [![JA](./assets/flags/JA.png)**יפנית**](./README.japanese.md), [![EU](./assets/flags/EU.png)**באסקית**](./README.basque.md) [(![ES](./assets/flags/ES.png)**ספרדית**, ![HE](./assets/flags/HE.png)**עברית**, ![KR](./assets/flags/KR.png)**קוריאנית** ו ![TR](./assets/flags/TR.png)**טורקית** בתהליך! )](#translations) + +
+ +# Latest Best Practices and News + +- **🛰 2023 edition is released soon**: We're now writing the next edition, stay tuned? + +- **✨ 89,000 stars**: Blushing, surprised and proud! + +- **🔖 New menu and tags**: Our menu is collapsible now and includes `#tags`. New visitors can read `#strategic` items first. Returning visitors can focus on `#new` content. Seniors can filter for `#advanced` items. Courtesy of the one and only [Rubek Joshi](https://github.com/rubek-joshi) + +- **![FR](./assets/flags/FR.png) French translation!1! :** The latest translation that joins our international guide is French. Bienvenue + +

+ +# ברוכים הבאים! שלושה דברים שכדאי לדעת לפני שגוללים מטה + +**1. הנכם קוראים עשרות מאמרים של שיטות העבודה המומלצות ב Node.js -** המאגר הזה הוא סיכום לא יסולא בפז של שיטות העבודה המומלצות ב Node.js , כמו כן הוא נעשה על בשיתוף פעולה. + +**2. זהו האוסף הגדול ביותר, והוא ממשיך לגדול כל שבוע -** נכון לרגע זה, יש למעלה מ 100 שיטות עבודה מומלצות, המלצות ארכיטקטורה והמלצות סגנון כתיבה. נושאים חדשים ובקשות חדשות (PR's) מתווספים כל יום במטרה לשמור את התוכן מעודכן. אנחנו נשמח לראותכם תורמים לפה, בין אם לתקן שגיאות קוד, עזרה בתרגום, או להציע רעיונות מבריקים חדשים. ראו את [המדריך לכתיבת הנחיות](./.operations/writing-guidelines.md). + +**3. שיטות העבודה כוללות מידע נוסף -** רוב הנקודות כוללות קישור **🔗לקריאה נוספת** שמרחיב על ידי דוגמאות קוד, ציטוטים מבלוגים נבחרים ומידע נוסף. + +

+ +# מאת יוני גולדברג + +### לימדו איתי: כיועץ, אני נפגש עם קבוצות מכל העולם במגוון פעולות כמו סדנאות ומעבר על קוד. 🎉 לאחרונה פרסמתי את [הקורס המתקדם לכתיבת בדיקות](https://testjavascript.com/) + +

+## תוכן העניינים + +
+ + 1. מבנה הפרוייקט (6) + + +  [1.1 בנו את הפרוייקט לפי רכיבים עסקיים `#strategic` `#updated`](#-11-structure-your-solution-by-business-components)
+  [1.2 חלוקת הרכיבים ל3 שכבות, שמירה על שכבת הווב בגבולותיה `#strategic` `#updated`](#-12-layer-your-components-with-3-tiers-keep-the-web-layer-within-its-boundaries)
+  [1.3 עטפו כלים משותפים בחבילות, שקלו את הפצתם](#-13-wrap-common-utilities-as-packages-consider-publishing)
+  [1.4 השתמשו בקונפיגורציה עם משתני סביבה באופן מודע, מאובטח והיררכי `#updated`](#-14-use-environment-aware-secure-and-hierarchical-config)
+  [1.5 שקלו את כל ההשלכות בעת בחירת מסגרת `#new`](#-15-consider-all-the-consequences-when-choosing-the-main-framework)
+  [1.6 השתמשו ב-TypeScript במידתיות ובצורה מושכלת `#new`](#-16-use-typescript-sparingly-and-thoughtfully)
+ +
+ +
+ + 2. ניהול שגיאות (12) + + +  [2.1 השתמשו ב Async-Await או הבטחות לניהול שגיאות אסינכרוניות](#-21-use-async-await-or-promises-for-async-error-handling)
+  [2.2 הרחיבו את מבנה אוביקט השגיאה המובנה Error `#strategic` `#updated`](#-22-extend-the-built-in-error-object)
+  [2.3 הבחינו בין שגיאות קטסטרופליות לבין שגיאות תפעוליות `#strategic` `#updated`](#-23-distinguish-catastrophic-errors-from-operational-errors)
+  [2.4 נהלו את השגיאות במרוכז ולא באמצעות כלי ביניים `#strategic`](#-24-handle-errors-centrally-not-within-a-middleware)
+  [2.5 תעדו את שגיאות ה-API באמצעות OpenAPI או GraphQL](#-25-document-api-errors-using-openapi-or-graphql)
+  [2.6 הורידו את התהליך בצורה מסודרת כאשר זר בא לבקר `#strategic`](#-26-exit-the-process-gracefully-when-a-stranger-comes-to-town)
+  [2.7 השתמשו ב-Logger מוכר ואמין כדי להגדיל את הקְרִיאוּת של השגיאות `#updated`](#-27-use-a-mature-logger-to-increase-errors-visibility)
+  [2.8 בידקו את תגובת המערכת לשגיאות על ידי שימוש בכלי הבדיקות האהוב עליכם `#updated`](#-28-test-error-flows-using-your-favorite-test-framework)
+  [2.9 גלו שגיאות וזמני השבתה על ידי שימוש בכלי APM](#-29-discover-errors-and-downtime-using-apm-products)
+  [2.10 תפסו מקרים לא מטופלים של דחיות של הבטחות `#updated`](#-210-catch-unhandled-promise-rejections)
+  [2.11 היכשלו מהר, ודאו את משתני הקלט באמצעות ספריה יעודית](#-211-fail-fast-validate-arguments-using-a-dedicated-library)
+  [2.12 תמיד המתינו לתשובה מההבטחות לפני שאתם מעבירים את התשובה הלאה כדי להימנע ממעקב חלקי `#new`](#-212-always-await-promises-before-returning-to-avoid-a-partial-stacktrace)
+ +
+ +
+ + 3. תבניות קוד וסגנון עיצוב (13) + + +  [3.1 השתמשו ב-ESLint `#strategic`](#-31-use-eslint)
+  [3.2 השתמשו בתוספים של Node.js שמרחיבים את ESLint `#updated`](#-32-use-nodejs-eslint-extension-plugins)
+  [3.3 התחילו בלוק של קוד עם סוגריים מסולסלים באותה השורה](#-33-start-a-codeblocks-curly-braces-on-the-same-line)
+  [3.4 הפרידו בין ההצהרות השונות בצורה תקנית](#-34-separate-your-statements-properly)
+  [3.5 תנו לפונקציה שם](#-35-name-your-functions)
+  [3.6 השתמשו במוסכמות קבועות במתן שמות למשתנים, לקבועים, לפונקציות ולמחלקות](#-36-use-naming-conventions-for-variables-constants-functions-and-classes)
+  [3.7 העדיפו const על פני let. ניטשו את var](#-37-prefer-const-over-let-ditch-the-var)
+  [3.8 טענו מודולים בתחילה, ולא בקריאה לפונקציות](#-38-require-modules-first-not-inside-functions)
+  [3.9 הגדירו כניסה מסודרת לספריה שלכם `#updated`](#-39-set-an-explicit-entry-point-to-a-modulefolder)
+  [3.10 השתמשו באופרטור `===`](#-310-use-the--operator)
+  [3.11 השתמשו ב-Async Await, המנעו מ-callbacks `#strategic`](#-311-use-async-await-avoid-callbacks)
+  [3.12 השתמשו בפונקציות חץ (=>)](#-312-use-arrow-function-expressions-)
+  [3.13 הימנעו מהשפעות צדדיות מחוץ לפונקציות `#new`](#-313-avoid-effects-outside-of-functions)
+ +
+ +
+ + 4. בדיקות ובקרת איכות (13) + + +  [4.1 לפחות, כיתבו בדיקות API לרכיבים השונים `#strategic`](#-41-at-the-very-least-write-api-component-testing)
+  [4.2 סווגו 3 חלקים במתן שם לכל בדיקה `#new`](#-42-include-3-parts-in-each-test-name)
+  [4.3 חלקו את הבדיקות לפי תבנית ה-AAA `#strategic`](#-43-structure-tests-by-the-aaa-pattern)
+  [4.4 וודאו כי גרסת ה-Node אחידה `#new`](#-44-ensure-node-version-is-unified)
+  [4.5 הימנעו מאתחול מידע גרעיני משותף, הגדירו לפי צורך של בדיקה `#strategic`](#-45-avoid-global-test-fixtures-and-seeds-add-data-per-test)
+  [4.6 תייגו את הבדיקות `#advanced`](#-46-tag-your-tests)
+  [4.7 בידקו את רמת כיסוי הבדיקות שלכם, זה יעזור לזהות דפוסי בדיקות שגויים](#-47-check-your-test-coverage-it-helps-to-identify-wrong-test-patterns)
+  [4.8 Use production-like environment for e2e testing](#-48-use-production-like-environment-for-e2e-testing)
+  [4.9 שכתבו את הקוד באופן קבוע בעזרת כלי ניתוח סטטי](#-49-refactor-regularly-using-static-analysis-tools)
+  [4.10 הדמיית תשובות של שרתי HTTP חיצוניים `#new` `#advanced`](#-410-mock-responses-of-external-http-services)
+  [4.11 בדקו את פונקציות הביניים בנפרד](#-411-test-your-middlewares-in-isolation)
+  [4.12 קבעו את הפורט בייצור, הגדירו אקראי לבדיקות `#new`](#-412-specify-a-port-in-production-randomize-in-testing)
+  [4.13 בידקו את חמשת התוצאות האפשריות `#strategic` `#new`](#-413-test-the-five-possible-outcomes)
+ +
+ +
+ + 5. עלייה לאוויר (19) + + +  [5.1. ניטור `#strategic`](#-51-monitoring)
+  [5.2. הגדילו את יכולת הצפייה בעזרת לוגים איכותיים `#strategic`](#-52-increase-the-observability-using-smart-logging)
+  [5.3. האצילו כל מה שאפשר (לדוגמה gzip, SSL) לשירות נפרד `#strategic`](#-53-delegate-anything-possible-eg-gzip-ssl-to-a-reverse-proxy)
+  [5.4. קיבוע תלויות](#-54-lock-dependencies)
+  [5.5. הבטיחו את זמינות המערכת בעזרת הכלי המתאים](#-55-guard-process-uptime-using-the-right-tool)
+  [5.6. השתמשו בכל מעבדי ה-CPU](#-56-utilize-all-cpu-cores)
+  [5.7. תיצרו ‘maintenance endpoint’](#-57-create-a-maintenance-endpoint)
+  [5.8. גלו את הלא ידוע בעזרת מוצרי APM `#advanced` `#updated`](#-58-discover-the-unknowns-using-apm-products)
+  [5.9. כתבו את הקוד מותאם להתקנה](#-59-make-your-code-production-ready)
+  [5.10. מדדו ושימרו את ניצול הזיכרון `#advanced`](#-510-measure-and-guard-the-memory-usage)
+  [5.11. Get your frontend assets out of Node](#-511-get-your-frontend-assets-out-of-node)
+  [5.12. Strive to be stateless `#strategic`](#-512-strive-to-be-stateless)
+  [5.13. Use tools that automatically detect vulnerabilities](#-513-use-tools-that-automatically-detect-vulnerabilities)
+  [5.14. Assign a transaction id to each log statement `#advanced`](#-514-assign-a-transaction-id-to-each-log-statement)
+  [5.15. Set NODE_ENV=production](#-515-set-node_envproduction)
+  [5.16. Design automated, atomic and zero-downtime deployments `#advanced`](#-516-design-automated-atomic-and-zero-downtime-deployments)
+  [5.17. Use an LTS release of Node.js](#-517-use-an-lts-release-of-nodejs)
+  [5.18. Log to stdout, avoid specifying log destination within the app](#-518-log-to-stdout-avoid-specifying-log-destination-within-the-app)
+  [5.19. Install your packages with npm ci `#new`](#-519-install-your-packages-with-npm-ci)
+ +
+ +
+ + 6. אבטחה (27) + + +  [6.1. Embrace linter security rules](#-61-embrace-linter-security-rules)
+  [6.2. Limit concurrent requests using a middleware](#-62-limit-concurrent-requests-using-a-middleware)
+  [6.3 Extract secrets from config files or use packages to encrypt them `#strategic`](#-63-extract-secrets-from-config-files-or-use-packages-to-encrypt-them)
+  [6.4. Prevent query injection vulnerabilities with ORM/ODM libraries `#strategic`](#-64-prevent-query-injection-vulnerabilities-with-ormodm-libraries)
+  [6.5. Collection of generic security best practices](#-65-collection-of-generic-security-best-practices)
+  [6.6. Adjust the HTTP response headers for enhanced security](#-66-adjust-the-http-response-headers-for-enhanced-security)
+  [6.7. Constantly and automatically inspect for vulnerable dependencies `#strategic`](#-67-constantly-and-automatically-inspect-for-vulnerable-dependencies)
+  [6.8. Protect Users' Passwords/Secrets using bcrypt or scrypt `#strategic`](#-68-protect-users-passwordssecrets-using-bcrypt-or-scrypt)
+  [6.9. Escape HTML, JS and CSS output](#-69-escape-html-js-and-css-output)
+  [6.10. Validate incoming JSON schemas `#strategic`](#-610-validate-incoming-json-schemas)
+  [6.11. Support blocklisting JWTs](#-611-support-blocklisting-jwts)
+  [6.12. Prevent brute-force attacks against authorization `#advanced`](#-612-prevent-brute-force-attacks-against-authorization)
+  [6.13. Run Node.js as non-root user](#-613-run-nodejs-as-non-root-user)
+  [6.14. Limit payload size using a reverse-proxy or a middleware](#-614-limit-payload-size-using-a-reverse-proxy-or-a-middleware)
+  [6.15. Avoid JavaScript eval statements](#-615-avoid-javascript-eval-statements)
+  [6.16. Prevent evil RegEx from overloading your single thread execution](#-616-prevent-evil-regex-from-overloading-your-single-thread-execution)
+  [6.17. Avoid module loading using a variable](#-617-avoid-module-loading-using-a-variable)
+  [6.18. Run unsafe code in a sandbox](#-618-run-unsafe-code-in-a-sandbox)
+  [6.19. Take extra care when working with child processes `#advanced`](#-619-take-extra-care-when-working-with-child-processes)
+  [6.20. Hide error details from clients](#-620-hide-error-details-from-clients)
+  [6.21. Configure 2FA for npm or Yarn `#strategic`](#-621-configure-2fa-for-npm-or-yarn)
+  [6.22. Modify session middleware settings](#-622-modify-session-middleware-settings)
+  [6.23. Avoid DOS attacks by explicitly setting when a process should crash `#advanced`](#-623-avoid-dos-attacks-by-explicitly-setting-when-a-process-should-crash)
+  [6.24. Prevent unsafe redirects](#-624-prevent-unsafe-redirects)
+  [6.25. Avoid publishing secrets to the npm registry](#-625-avoid-publishing-secrets-to-the-npm-registry)
+  [6.26. 6.26 Inspect for outdated packages](#-626-inspect-for-outdated-packages)
+  [6.27. Import built-in modules using the 'node:' protocol `#new`](#-627-import-built-in-modules-using-the-node-protocol)
+ +
+ +
+ + 7. ביצועים (2) (בתהליך ✍️) + + +  [7.1. Don't block the event loop](#-71-dont-block-the-event-loop)
+  [7.2. Prefer native JS methods over user-land utils like Lodash](#-72-prefer-native-js-methods-over-user-land-utils-like-lodash)
+ +
+ +
+ + 8. דוקר (15) + + +  [8.1 Use multi-stage builds for leaner and more secure Docker images `#strategic`](#-81-use-multi-stage-builds-for-leaner-and-more-secure-docker-images)
+  [8.2. Bootstrap using node command, avoid npm start](#-82-bootstrap-using-node-command-avoid-npm-start)
+  [8.3. Let the Docker runtime handle replication and uptime `#strategic`](#-83-let-the-docker-runtime-handle-replication-and-uptime)
+  [8.4. Use .dockerignore to prevent leaking secrets](#-84-use-dockerignore-to-prevent-leaking-secrets)
+  [8.5. Clean-up dependencies before production](#-85-clean-up-dependencies-before-production)
+  [8.6. Shutdown smartly and gracefully `#advanced`](#-86-shutdown-smartly-and-gracefully)
+  [8.7. Set memory limits using both Docker and v8 `#advanced` `#strategic`](#-87-set-memory-limits-using-both-docker-and-v8)
+  [8.8. Plan for efficient caching](#-88-plan-for-efficient-caching)
+  [8.9. Use explicit image reference, avoid latest tag](#-89-use-explicit-image-reference-avoid-latest-tag)
+  [8.10. Prefer smaller Docker base images](#-810-prefer-smaller-docker-base-images)
+  [8.11. Clean-out build-time secrets, avoid secrets in args `#strategic #new`](#-811-clean-out-build-time-secrets-avoid-secrets-in-args)
+  [8.12. Scan images for multi layers of vulnerabilities `#advanced`](#-812-scan-images-for-multi-layers-of-vulnerabilities)
+  [8.13 Clean NODE_MODULE cache](#-813-clean-node_module-cache)
+  [8.14. Generic Docker practices](#-814-generic-docker-practices)
+  [8.15. Lint your Dockerfile `#new`](#-815-lint-your-dockerfile)
+ +
+ +

+ +# `1. מבנה הפרוייקט` + +## ![✔] 1.1 בנו את הפרוייקט לפי רכיבים עסקיים + +**אמ;לק:** בסיס המערכת צריך לכלול תיקיות או מאגרים שמייצג בצורה הגיונית את המידול העסקי. כל רכיב מייצג תחום מוצר (כלומר הקשר מוגבל), למשל 'משתמשים', 'הזמנות', וכולי... כל רכיב מכיל את ה API, לוגיקה ומסד הנתונים שלו. מה המטרה של זה? כאשר יש סביבה עצמאית כל שינוי משפיע אך ורק על החלק הרלוונטי - העומס הנפשי, סיבוכיות הפיתוח והחשש מפריסה חדשה של הרכיב הרבה יותר קטן. כתוצאה מכך, מתכנתים יכולים לפתח הרבה יותר מהר. זה לא דורש בהכרח הפרדה פיזית ויכול להיות מושג גם בMonorepo או multi-repo. + +```bash +my-system +├─ apps (components) +│ ├─ orders +│ ├─ users +│ ├─ payments +├─ libraries (generic cross-component functionality) +│ ├─ logger +│ ├─ authenticator +``` + +**אחרת:** כאשר מוצרים של מודולים או נושאים שונים מעורבבים יחד, ישנו סיכוי גבוה שתיווצר מערכת ספגטי בעלת צימוד גבוה. לדוגמה, בארכיטקטורה שבה 'מודול א`' קורא לשירות מ'מודול ב;', אין הפרדה ברורהבין המודולים השונים - כל שינוי בקוד עלול להשפיע על משהו אחר. עם הגישה הזאת , מתכנתים שצריכים להוסיף מוצר חדש למערכת יאבקו בה בהבנה על מה השינוי שלהם יכול להשפיע. כתוצאה מכך, הם חששו לשבור מודולים אחרים, וכל פריסה נהייתה איטית יותר ומסוכנת יותר. + +🔗 [**לקריאה נוספת: בנייה לפי רכיבים**](./sections/projectstructre/breakintcomponents.md) + +

+ +## ![✔] 1.2 חלוקת הרכיבים ל3 שכבות, שמירה על שכבת הווב בגבולותיה + +**אמ;לק:** כל רכיב צריך לכלול 'שכבות' - תיקייה יעודית עם אחריות משותפת: 'entry-point' איפה שחלקי השליטה נמצאים, 'domain' איפה שהלוגיקה נמצאת ו 'data-access'. העיקרון המנחה של הארכיטקטורות המובילות בשוק הוא להפריד את האחריות הטכנית (למשל: HTTP, DB ועוד) מהלוגיקה היעודית של המוצר כך שהמתכנתים יוכלו לקודד יותר תכולות בלי לדאוג לגבי ניהול תשתיות. השמה של כל שכבה בתיקייה יעודית, שידועה גם כ-[מודל 3 השכבות](https://he.wikipedia.org/wiki/%D7%90%D7%A8%D7%9B%D7%99%D7%98%D7%A7%D7%98%D7%95%D7%A8%D7%94_%D7%A8%D7%91-%D7%A9%D7%9B%D7%91%D7%AA%D7%99%D7%AA#%D7%90%D7%A8%D7%9B%D7%99%D7%98%D7%A7%D7%98%D7%95%D7%A8%D7%AA_%D7%A9%D7%9C%D7%95%D7%A9_%D7%A9%D7%9B%D7%91%D7%95%D7%AA) ([באנגלית](https://en.wikipedia.org/wiki/Multitier_architecture#Three-tier_architecture)) זאת הדרך _הפשוטה_ להשיג את המטרה. + +```bash +my-system +├─ apps (components) +│ ├─ component-a + │ ├─ entry-points + │ │ ├─ api # controller comes here + │ │ ├─ message-queue # message consumer comes here + │ ├─ domain # features and flows: DTO, services, logic + │ ├─ data-access # DB calls w/o ORM +``` + +**אחרת:** לעתים דחופות נתקלים בכך שהמתכנתים מעבירים אובייקטי תקשורת כדוגמת request/reqponse לפונקציות בשכבות של הלוגיקה או ניהול המידע - דבר זה פוגע בעיקרון ההפרדה וגורם לכך שבעתיד יהיה קשה יותר להנגיש את הלוגיקה לסוגי קלינטים אחרים כדוגמת: בדיקות יחידה, משימות מתוזמנות וmessage queues. + +🔗 [**לקריאה נוספת: חלק את המוצר לשכבות**](./sections/projectstructre/createlayers.md) + +

+ +## ![✔] 1.3 עטפו כלים משותפים בחבילות, שקלו את הפצתם + +**אמ;לק:** מקמו את כל הכלים שאפשר לשתף אותם בתיקייה ייעודית, למשל 'libraries' וכל כלי בתיקייה פנימית נפרדת, למשל '/libraries/logger'. הפכו את הכלי לחבילה בלתי תלויה עם קובץ ה package.json שלו וזאת כדי להגדיל את הכימוס (encapsulation), ואפשרו הפצה עתידית למאגר. כאשר הפרוייקט שלכם בנוי בתצורת monorepo, כלים אלו יכולים להיות מוגדרים על ידי שימוש ב 'npm linking' לכתובת הפיזית שלהם על ידי שימוש ב ts-paths או על ידי הפצה והתקנה על ידימנהל חבילות כדוגמת 'npm registry'. + +```bash +my-system +├─ apps (components) + │ ├─ component-a +├─ libraries (generic cross-component functionality) +│ ├─ logger +│ │ ├─ package.json +│ │ ├─ src +│ │ │ ├─ index.js + +``` + +**אחרת:** צרכנים של כלי יהיו צמודים לפונקציונליות הפנימית שלו. על ידי הגדרה של package.json בשורש הכלי מישהו יכול להגדיר קובץ package.json.main או package.json.exports כדי להצהיר במפורש אילו קבצים ופונקציולניות היא חלק מהחלקים הנגישים של הכלי. + +🔗 [**לקריאה נוספת: בנייה לפי תכונה**](./sections/projectstructre/wraputilities.md) + +

+ +## ![✔] 1.4 השתמשו בקונפיגורציה עם משתני סביבה באופן מודע, מאובטח והיררכי + +**אמ;לק:** הגדרת סביבה מושלמת צריכה להבטיח כי (א) שמות משתנים יכולים להיקרא מקבצים כמו גם ממשתני סביבה (ב) סודות נשמרים מחוץ לקוד ששייך למאגר (ג) הקונפיגורציה היא היררכית לצורך חיפוש קל יותר (ד) תמיכה בסוגים שונים של משתנים (ה) וידוא מוקדם של משתנים לא תקינים (ו) הגדרת ברירת מחדל לכל שדה. ישנן מספר ספריות שעונות על רוב הדרישות הללו כמו [convict](https://www.npmjs.com/package/convict), [env-var](env-var), [zod](https://github.com/colinhacks/zod), ועוד... + +**אחרת:** נניח וישנו משתנה סביבה הכרחי שלא הוגדר, המערכת תתחיל לרוץ בהצלחה, תענה לבקשות, חלק מהמידע יעודכן במסד הנתונים, ולפתע יהיה חסר לה שדה הכרחי להמשך התהליך ושבלעדיו היא לא יכולה לסיים את הפעולה, מה שייצור מערכת במצב "מלוכלך". + +🔗 [**לקריאה נוספת: שיטות עבודה של קונפיגורציה**](./sections/projectstructre/configguide.md) + +

+ +## ![✔] 1.5 שקלו את כל ההשלכות בעת בחירת מסגרת + +**אמ;לק:** כאשר בונים אפליקציות ו API-ים, שימוש בפריימוורק הוא חובה. קל להתעלם מהאפשרויות השונות שקיימות ומשיקולים חשובים ובסופו של דבר להשתמש באפשרות שפחות תואמת לדרישות של המוצר. נכון ל2023/2024 אנו מאמינים כי ארבעת הפריימוורקים הללו הם הכדאיים ביותר להשוואה: [Nest.js](https://nestjs.com/), [Fastify](https://www.fastify.io/), [express](https://expressjs.com/), ו [Koa](https://koajs.com/). לחצו על לקריאה נוספת בהמשך כדי לקרוא פרטים נוספים בעד ונגד כל אחת מהאפשרויות. באופן פשטני, אנו מאמינים כי Node.js זאת ההתאמה הכי טובה לצוותים שרוצים לעבוד בשיטת OOP או לבנות מוצרים שמיועדים לגדול בצורה ניכרת ואי אפשר לחלק אותם לרכיבים קטנים _ועצמאיים_. ההמלצה שלנו היא Fastify עבור מערכות בגודל סבירents (כמו Microservices) שמושתתים על עקרונות פשוטים של Node.js. + +**אחרת:** בשל הכמות העצומה של השיקולים, קל לקבל החלטה על בסיס מידע חלקי ולהשוות תפוחים לתפוזים. למשל, ישנה הנחה רווחת שFastify הוא web-server מינימלי שראוי להשוות לexpress בלבד. בפועל, זהו פריימוורק עשיר עם הרבה הרחבות רשמיות שמכסות הרבה צרכים. + +🔗 [**לקריאה נוספת: בחירת הפריימוורק הנכון**](./sections/projectstructre/choose-framework.md) + +## ![✔] 1.6 השתמשו ב-TypeScript במידתיות ובצורה מושכלת + +**אמ;לק:** קידוד ללא מקדמי בטיחות של סיווג משתנים הוא כבר לא אפשרות בת קיימא, TypeScript מהווה את האפשרות הפופולרית ביותר למשימה זו. משתמשים בה להגדרת סוגי משתנים וערכי החזרה של פונקציות. עם זאת, זוהי חרב פיפיות שיכולה בקלות ליצור מורכבות בשל בסביבות 50 מילות מפתח נוספות שיש לה ותכונות מתוחכמות שצריך לדעת להשתמש בהן. שימוש בה צריך להיעשות במידה, בעדיפות להגדרות פשוטות של משתנים, ושימוש ביכולות מתקדמות רק כאשר צורך הכרחי מופיע. + +**אחרת:** [מחקרים](https://earlbarr.com/publications/typestudy.pdf) מראים כי שימוש ב-TypeScript יכול לעזור בזיהוי כ20% מהבאגים בשלבים מוקדמים יותר. ללא TypeScript חווית הפיתוח ב IDE נהיית בלתי נסבלת. מהצד השני, 80% מהבאגים היא לא עוזרת לזהות. כתוצאה מכך, שימוש בTypeScript מוסיף ערך מוגבל. רק הוספה של בדיקות איכותיות יכולה לעזור לזהות את מגוון הבאגים הרחב, כולל כאלו שנגרמים מאפיון לא תקין של סוג המשתנה. שימוש לא טוב גם עלול להרוג את המטרה, תכונות מורכבות של קוד מעלות אתמורכבות הקוד מה שבאופן ישיר מעלה את מספר הבאגים וזמן התיקון של כל באג. + +🔗 [**לקריאה נוספת: שיקולים לשימוש ב-TypeScript**](./sections/projectstructre/typescript-considerations.md) + +


+ +

⬆ חזרה למעלה

+ +# `2. ניהול שגיאות` + +## ![✔] 2.1 השתמשו ב Async-Await או הבטחות לניהול שגיאות אסינכרוניות + +**אמ;לק:** ניהול שגיאות אסינכרוניות על ידי שימוש ב-callbacks זו הדרך המהירה לגהינום (הידועה בשם [פירמידת דום](https://en.wikipedia.org/wiki/Pyramid_of_doom_(programming))). המתנה הטובה ביותר שאפשר לתת לקוד הוא שימוש ב-promises בסגנון async-await דבר שמאפשר קוד הרבה יותר נקי ומסודר וסינטקס דומה ל try-catch. + +**אחרת:** סגנון הכתיבה `function(err, response)` הכולל שימוש ב-callbacks של Node.js, סולל דרך בטוחה לקוד שאי אפשר לתחזק בשל הערבוב בין ניהול שגיאות לניהול התהליך התקני של המערכת, עם קינון מוגזם וסגנון קוד מוזר. + +🔗 [**לקריאה נוספת: הימנעות מ-callbacks**](./sections/errorhandling/asyncerrorhandling.md) + +

+ +## ![✔] 2.2 הרחיבו את מבנה אוביקט השגיאה המובנה `Error` + +**אמ;לק:** ישנן ספריות שזורקות שגיאה כמחרוזת או כאובייקט פרי מחשבת כותבי הקוד של הספריה - דבר שיוצר מורכבות בניהול השגיאות וביצירת מכנה משותף בין מודולים שונים. במקום זאת, השקיעו ביצירת אובייקט או מחלקת (class) שגיאה שיורשת מאובייקט השגיאה המובנה של השפה והשתמשו בזה בכל פעם שצריך לדחות את המצב, לזרוק שגיאה או להפיץ שגיאה. השגיאה האפליקטיבית צריכה להוסיף שדות נוספים כדוגמת שם השגיאה ורמת החומרה שלה. על ידי כך, לכל השגיאות ישנו מבנה אחיד והן מאפשרות תמיכה טובה יותר בניהול שגיאות. ישנו כלל של `no-throw-literal` ESLint שבודק בצורה מיטבית את השימוש הזה (על אף שיש לזה קצת [מגבלות](https://eslint.org/docs/rules/no-throw-literal) שיכולות להסתדר על ידי שימוש ב-TypeScript והגדרת החוק `@typescript-eslint/no-throw-literal`) + +**אחרת:** כאשר מפעילים רכיב כלשהו, אם ישנה אי וודאות איזה סוג של שגיאה יגיע - זה גורם לכך שניהול השגיאות יהיה הרבה יותר מורכב. גרוע מכך, שימוש באובייקטים מומצאים לתיאור שגיאות עלול להוביל לאיבוד של שגיאות קריטיות בעלות מידע חשוב כמו מעקב אחר מקור השגיאה! + +🔗 [**לקריאה נוספת: שימוש באובייקט השגיאה המובנה**](./sections/errorhandling/useonlythebuiltinerror.md) + +

+ +## ![✔] 2.3 הבחינו בין שגיאות קטסטרופליות לבין שגיאות תפעוליות + +**אמ;לק:** שגיאות תפעוליות (למשל קלט לא תקין בפנייה ל-API) מתייחסות למקרים ידועים בהם ההשפעה של השגיאה מובנת לחלוטין ויכולה להיות מנוהלת בצורה מחושבת. מצד שני, שגיאות קטסטרופליות (ידועות גם כשגיאות תכנות) מתייחסות לשגיאות לא צפויות במערכת שדורשות אתחול בטוח שלה. + +**אחרת:** אתם עלולים לאתחל את המערכת בעקבות כל שגיאה. אבל למה לגרום לכ-5000 משתמשים לחוות התנתקות בגלל שגיאה תפעולית צפויה ושולית? ההיפך הוא גם לא אידיאלי - להשאיר את המערכת עובדת כאשר קטסטרופה לא צפויה קרתה בה והיא עלולה לגרור התנהגות בלתי צפויה. הבדלה בין שני המקרים מאפשרת התמודדות מושכלת ומאוזנת בהתאם להקשר. + +🔗 [**לקריאה נוספת: שגיאות תפעוליות מול שגיאות תכנות**](./sections/errorhandling/operationalvsprogrammererror.md) + +

+ +## ![✔] 2.4 נהלו את השגיאות במרוכז ולא באמצעות כלי ביניים + +**אמ;לק:** מימוש הניהול של השגיאות כמו למשל תעוד השגיאה, החלטה אם לקרוס ואילו מדדים לנטר צריך להיות מרוכז במקום אחד שכל הכניסות למערכת (למשל APIs, cron jobs, scheduled jobs) משתמשות בו כאשר חלה בהן שגיאה. + +**אחרת:** אם לא מנהלים את השגיאות במקום אחד אז במהרה יהיה שכפול קוד וכנראה ניהול לא תקין של חלק מהשגיאות. + +🔗 [**לקריאה נוספת: ניהול השגיאות במקום מרוכז**](./sections/errorhandling/centralizedhandling.md) + +

+ +## ![✔] 2.5 תעדו את שגיאות ה-API באמצעות OpenAPI או GraphQL + +**אמ;לק:** אפשרו למשתמשי ה-API שלכם לדעת אילו שגיאות עלולות להגיע כתשובה, כך שהם יוכלו להתמודד איתן בצורה מושכלת במקום לקרוס. ל-API מבוסס REST זה נעשה בדרך כלל באמצעות כלי תעוד כמו OpenAPI. אם אתם משתמשים ב-GraphQL, אתם יכולים להשתמש בסכמה ובהערות בשביל להשיג את המטרה. + +**אחרת:** מי שמשתמש ב-API שלנו עלול להחליט לגרום למערכת שלו לקרוס ולאתחל את עצמה רק בגלל שהוא קיבל שגיאה שהוא לא הצליח להבין. שימו לב: המשתמש של ה-API שלכם יכול להיות אתם (מה שקורה הרבה כשמשתמשים במיקרוסרוויסים). + +🔗 [**לקריאה נוספת: תיעוד שגיאות ה-API באמצעות OpenAPI או GraphQL**](./sections/errorhandling/documentingusingswagger.md) + +

+ +## ![✔] 2.6 הורידו את התהליך בצורה מסודרת כאשר זר בא לבקר + +**אמ;לק:** כאשר שגיאה לא ידועה חלה (שגיאה קטסטרופלית, ראו תובנה 2.3) - ישנה חוסר ודאות לגבי הבריאות והיציבות של המערכת. במקרה כזה, אין דרך לברוח מלגרום לשגיאה להיות ברת צפייה, סגירת חיבוריות לרכיבים נוספים והורדה של התהליך. כל סביבת ריצה מהימנה כדוגמת שירותי Docker או שירותי ענן שמספקים פתרונות ללא שרת (serverless) יוודאו שהתהליך יעלה מחדש עבורכם. + +**אחרת:** כאשר שגיאה לא צפויה קורית, רכיב כלשהו עלול להיות במצב לא תקין (למשל event emitter גלובאלי שמפסיק להפיץ אירועים בשל כשלון פנימי) והחל מעכשיו שאר הבקשות שמשתמשות ברכיב זה עלולות להיכשל או להתנהג באופן ממש לא צפוי. + +🔗 [**לקריאה נוספת: הורדת התהליך**](./sections/errorhandling/shuttingtheprocess.md) + +

+ +## ![✔] 2.7 השתמשו ב-Logger מוכר ואמין כדי להגדיל את הקְרִיאוּת של השגיאות + +**אמ;לק:** כלי לוגים איכותי כדוגמת [Pino](https://github.com/pinojs/pino) או [Winston](https://github.com/winstonjs/winston) מגדיל את הקריאות וההבנה של הלוגים על ידי שימוש ברמת חומרה, עימוד, עיצוב, צבעים ועוד. ל-`console.log` אין את היכולות הללו וראוי להימנע משימוש בו. העיפרון החד ביותר בתחום מאפשר הוספה של שדות שימושיים נוספים ללא תקורה גבוהה של ביצועים. מפתחים צריכים לכתוב את הלוגים ל-`stdout` ולתת לתשתית להעביר את המידע לכלי המתאים עבור כל מקרה. + +**אחרת:** רפרוף על שורות console.log או בצורה ידנית על קבצי טקסט עמוסים לעייפה ללא כלי חיפוש ותצוגה מותאמים עלולים להשאיר אתכם לעבוד עד השעות הקטנות של הלילה. + +🔗 [**לקריאה נוספת: שימוש ב-Logger אמין**](./sections/errorhandling/usematurelogger.md) + +

+ +## ![✔] 2.8 בידקו את תגובת המערכת לשגיאות על ידי שימוש בכלי הבדיקות האהוב עליכם + +**אמ;לק:** בין אם יש לכם כלי QA אוטומטי ומקצועי ובין אם אחד המפתחים מבצע את הבדיקות - ודאו כי לא רק המסלול הבטוח של הקוד מכוסה, אלא גם ניהול השגיאות ושחוזרות השגיאות שאמורות לחזור במקרה של תקלה. נוסף על כך, בידקו מקרים מורכבים יותר של שגיאות, כמו למשל שגיאות בלתי צפויות, כדי לוודא שהרכיב שמטפל בשגיאות מבצע זאת כראוי (ראו דוגמאות קוד בקישור "לקריאה נוספת") + +**אחרת:** ללא בדיקות כלל, לא ידניות ולא אוטומטיות, לא תוכלו לסמוך על הקוד שלכם שיחזיר את השגיאה הנכונה. ללא שגיאות משמעותיות לא תוכלו לטפל בשגיאות. + +🔗 [**לקריאה נוספת: בדיקת התנהגות בעת שגיאה**](./sections/errorhandling/testingerrorflows.md) + +

+ +## ![✔] 2.9 גלו שגיאות וזמני השבתה על ידי שימוש בכלי APM + +**אמ;לק:** כלי ניטור ובדיקת ביצועים (מוכרים כ-APM) מודדים באופן יזום את הקוד או ה-API כך שבאופן קסום הם מציגים שגיאות, התרסקויות וחלקים שעובדים לאט מהצפוי ואתם לא שמים לב אליהם. + +**אחרת:** אתם עלולים להתאמץ רבות במדידה של בעיות ביצועים וזמני השבתה של המערכת, כנראה שלעולם לא תהיו מודעים לאיזה חלקים במערכת הם האיטיים ביותר ואיך זה משפיע על חווית המשתמש. + +🔗 [**לקריאה נוספת: שימוש ב-APM**](./sections/errorhandling/apmproducts.md) + +

+ +## ![✔] 2.10 תפסו מקרים לא מטופלים של דחיות של הבטחות + +**אמ;לק:** כל שגיאה או דחייה שחוזרת מהבטחה תיבלע, אלא אם כן בשלב הפיתוח יטפלו בה כמו שצריך. אפילו אם יש בקוד האזנה ל `process.uncaughtException`! כדי להתגבר על זה צריך להאזין גם ל `process.unhandledRejection`. + +**אחרת:** השגיאות במערכת יבלעו ויעלמו ללא עקבות. לא משהו שצריך לדאוג ממנו... + +🔗 [**לקריאה נוספת: תפיסה של דחיות של הבטחות**](./sections/errorhandling/catchunhandledpromiserejection.md) + +

+ +## ![✔] 2.11 היכשלו מהר, ודאו את משתני הקלט באמצעות ספריה יעודית + +**אמ;לק:** הגדירו תבנית קלט קשיחה ל-API כדי להימנע מבאגים מלוכלכים שקשה הרבה יותר לעקוב אחריהם. כתיבת קוד האימות הוא תהליך מייגע, אלא אם כן תשתמשו באחת הספריות המוכרות כיום כמו [ajv](https://www.npmjs.com/package/ajv), [zod](https://github.com/colinhacks/zod), או [typebox](https://github.com/sinclairzx81/typebox). + +**אחרת:** חשבו על זה - הפונקציה שלכם מצפה לקבל כקלט משתנה `discount` מספרי שמי שקרה לפונקציה שכח להעביר. בהמשך, הקוד בודק אם `discount != 0` (כמות ההנחה שאפשר לקבל גדולה מאפס), ואם כן אז המשתמש יהנה מההנחה. וואו, זה באג מלוכלך, ראיתם??? + +🔗 [**לקריאה נוספת: כשלון מהיר**](./sections/errorhandling/failfast.md) + +

+ +## ![✔] 2.12 תמיד המתינו לתשובה מההבטחות לפני שאתם מעבירים את התשובה הלאה כדי להימנע ממעקב חלקי + +**אמ;לק:** תמיד כתבו `return await` כאשר מחזירים תוצאה של הבטחה וזאת כדי להשיג ערך מלא של מעקב אחר מקור השגיאה (stacktrace). אם פונקציה מחזירה הבטחה היא חייבת להיות מוגדרת כפונקציה אסינכרונית ובמפורש לחכות להבטחה שהיא מחזירה. + +```js +async function promisifyFunction() { + // some logic + return await new Promise(...); +} +``` + +**אחרת:** הפונקציה שמחזירה הבטחה ללא המתנה לא תופיע בנתיב המעקב אחרי השגיאה (stacktrace). חוסרים כאלו עלולים לסבך את ההבנה של זרימת המערכת שגרמה לשגיאה, במיוחד אם הגורם להתנהגות הלא צפויה קרה בפונקציה החסרה. + +🔗 [**לקריאה נוספת: החזרת הבטחות**](./sections/errorhandling/returningpromises.md) + +


+ +

⬆ חזרה למעלה

+ +# `3. תבניות קוד וסגנון עיצוב` + +## ![✔] 3.1 השתמשו ב-ESLint + +**אמ;לק:** [ESLint](https://eslint.org) הוא הסטנדרט דה-פקטו למציאת שגיאות בקוד ותיקון של סגנונות קוד, לא רק זיהוי של רווח סורר שעלול ליצור תקלה אלא גם זיהוי של קוד שלא עומד בסטנדרטים (anti-pattern) כמו זריקת שגיאות ללא סיווג. אמנם ESLint יכול לתקן באופן אוטומטי סגנונות קוד, אך כלים אחרים כדוגמת [prettier](https://www.npmjs.com/package/prettier) טובים יותר בעיצוב וסגנון הקוד ועובדים בשילוב עם ESLint. + +**אחרת:** מפתחים ישתעממו תוך כדי השקעת זמנם במציאת רווחים סוררים וידאגו לאורך השורה והזמן היקר שלהם יבוזבז על איך לשמור על סגנון הקוד של הפרוייקט. + +🔗 [**לקריאה נוספת: שימוש ב-ESLint ו-Prettier**](./sections/codestylepractices/eslint_prettier.md) + +

+ +## ![✔] 3.2 השתמשו בתוספים של Node.js שמרחיבים את ESLint + +**אמ;לק:** על גבי הסטנדרט של חוקי ESLint שמכסים את שפת JavaScript, הוסיפו את התוספים היעודיים של Node.js כמו [eslint-plugin-node](https://www.npmjs.com/package/eslint-plugin-node), [eslint-plugin-mocha](https://www.npmjs.com/package/eslint-plugin-mocha), [eslint-plugin-node-security](https://www.npmjs.com/package/eslint-plugin-security), [eslint-plugin-require](https://www.npmjs.com/package/eslint-plugin-require), [eslint-plugin-jest](https://www.npmjs.com/package/eslint-plugin-jest) ועוד תוספים שמממשים חוקים נוספים ומועילים. + +**אחרת:** הרבה תבניות קוד לא תקינות שבשימוש ב-Node.js נעלמות מתחת לרדאד. לדוגמה, מפתחים יכתבו `require(variableAsPath)` עם משתנה שמאפשר גישה לתיקיה בקוד, דבר שמאפשר לתוקפים להריץ כל קוד JS. אם תשתמשו בחוקי Node.js תוכלו לזהות את הטעות הזאת ולקבל עליה התראה מבעוד מועד. + +

+ +## ![✔] 3.3 התחילו בלוק של קוד עם סוגריים מסולסלים באותה השורה + +**אמ;לק:** מומלץ שהסוגריים המסולסלים הפותחים של בלוק של קוד יהיו באותה השורה יחד עם הקוד. + +### דוגמה + +```javascript +// Do +function someFunction() { + // code block +} + +// Avoid +function someFunction() +{ + // code block +} +``` + +**אחרת:** התעלמות משיטת עבודה זו עלולה להוביל לתוצאות לא צפויות, כמו שניתן לראות בשרשור בקישור מ StackOverflow: + +🔗 [**לקריאה נוספת:** "למה התוצאות משתנות בהתאם למיקום הסוגר המסולסל?" (StackOverflow)](https://stackoverflow.com/questions/3641519/why-does-a-results-vary-based-on-curly-brace-placement) + +

+ +## ![✔] 3.4 הפרידו בין ההצהרות השונות בצורה תקנית + +בין אם אתם משתמשים בנקודה-פסיק (;) בשביל להפריד בין ההצהרות על המשתנים ובין אם לא, עצם הידיעה על ההשלכות של ירידת שורה במקום הלא מתאים או של הוספה אוטומטית של נקודה-פסיק, יעזרו לכם לזהות שגיאות סינטקס רגילות. + +**אמ;לק:** שימוש ב-ESLint כדי להעלות את המודעות לגבי הסיכון הכרוך בזה. כלים כמו [Prettier](https://prettier.io/) או [Standardjs](https://standardjs.com/) יכולים באופן אוטומטי לפתור את הבעיות הללו. + +**אחרת:** כמו שראינו בסעיף הקודם, "המתורגמן" (interpreter) של JavaScript מוסיף אוטומטית נקודה-פסיק בסוף כל הצהרה במידה ואין, או שהוא מחליט כי ההצהרה מסתיימת במקום אחר מהמתוכנן על ידינו, דבר שעלול להוביל לתוצאות בלתי צפויות. אפשר להשתמש בהשמות ולהימנע מ [IIFE](https://developer.mozilla.org/en-US/docs/Glossary/IIFE) כדי להימנע מרוב ההתנהגויות הבלתי צפויות. + +### דוגמה + +```javascript +// 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 +``` + +🔗 [**לקריאה נוספת:** "Semi ESLint rule"](https://eslint.org/docs/rules/semi) +
+🔗 [**לקריאה נוספת:** "No unexpected multiline ESLint rule"](https://eslint.org/docs/rules/no-unexpected-multiline) + +

+ +## ![✔] 3.5 תנו לפונקציה שם + +**אמ;לק:** תנו שמות לכל הפונקציות, כולל closures ו-callbacks. הימנעו מפונקציות אנונימיות. זה מאוד שימושי כשבודקים אפליקציות Node.js. מתן שמות לכל הפונקציות יאפשר לכם להבין בקלות על מה אתם מסתכלים כשאתם צופים בתמונת מצב של הזיכרון של האפליקציה. + +**אחרת:** לדבג את גרסת היצור (production) על בסיס תמונת מצב של הזיכרון (core dump) עלול להיות מאתגר כשהבעיות של הזיכרון קורות בכל מיני פונקציות אנונימיות. + +

+ +## ![✔] 3.6 השתמשו במוסכמות קבועות במתן שמות למשתנים, לקבועים, לפונקציות ולמחלקות + +**אמ;לק:** השתמשו ב-**_lowerCamelCase_** כאשר אתם נותנים שמות לקבועים, משתנים ופונקציות, **_UpperCamelCase_** (גם האות הראשונה גדולה) כאשר אתם נותנים שמות למחלקות ו-**_UPPER_SNAKE_CASE_** כאשר אתם נותנים שמות למשתנים גלובליים או סטטיים. סדר זה יאפשר לכם להבחין בקלות בין משתנים רגילים ופונקציות לבין מחלקות שדורשות אתחול ולבין משתנים גלובליים. השתמשו בשמות שמתארים היטב את משמעות המשתנה, אך שיהיה קצר. + +**אחרת:** JavaScript היא השפה היחידה בעולם שתאפשר לכם לקרוא ל-constructor ("Class") ישירות ללא אתחול. לכן, חשוב מאוד להבדיל בין שמות מחלקות ושמות פונקציות על ידי שימוש ב-UpperCamelCase. + +### דוגמאות + +```javascript +// for global variables names we use the const/let keyword and UPPER_SNAKE_CASE +let MUTABLE_GLOBAL = "mutable value"; +const GLOBAL_CONSTANT = "immutable value"; +const CONFIG = { + key: "value", +}; + +// examples of UPPER_SNAKE_CASE convention in nodejs/javascript ecosystem +// in javascript Math.PI module +const PI = 3.141592653589793; + +// https://github.com/nodejs/node/blob/b9f36062d7b5c5039498e98d2f2c180dca2a7065/lib/internal/http2/core.js#L303 +// in nodejs http2 module +const HTTP_STATUS_OK = 200; +const HTTP_STATUS_CREATED = 201; + +// for class name we use UpperCamelCase +class SomeClassExample { + // for static class properties we use UPPER_SNAKE_CASE + static STATIC_PROPERTY = "value"; +} + +// for functions names we use lowerCamelCase +function doSomething() { + // for scoped variable names we use the const/let keyword and lowerCamelCase + const someConstExample = "immutable value"; + let someMutableExample = "mutable value"; +} +``` + +

+ +## ![✔] 3.7 העדיפו const על פני let. ניטשו את var + +**אמ;לק:** שימוש ב-`const` משמעותו היא שלאחר שהמשתנה מאותחל לראשונה הוא לא יכול להיות מאותחל שוב. העדפת שימוש ב-`const` תעזור לכם לא להתפתות ולהשתמש שוב באותו משתנה לצרכים שונים ותהפוך את הקוד שלכם לקריא יותר. אם משתנה צריך להיות מאותחל מחדש, למשל בתוך לולאת for, אז השתמשו ב-`let` לצורך כך. נקודה נוספת שחשוב לציין היא ששימוש ב-`let` אפשרית רק בתוך אותו הבלוק שהיא הוגדרה בו. `var` נצמד לscope של הפונקציה שהוא מוגדר בו ולא לבלוק ספציפי ולכן [צריך לא להשתמש בו ב-ES6](https://hackernoon.com/why-you-shouldnt-use-var-anymore-f109a58b9b70) כשאפשר להשתמש ב-`const` וב-`let`. + +**אחרת:** דיבוג הופך להיות מאוד מסורבל כאשר משתנה משתנה לעיתים דחופות. + +🔗 [**לקריאה נוספת: JavaScript ES6+: var, let, or const?** ](https://medium.com/javascript-scene/javascript-es6-var-let-or-const-ba58b8dcde75) + +

+ +## ![✔] 3.8 טענו מודולים בתחילה, ולא בקריאה לפונקציות + +**אמ;לק:** טענו את המודולים (require...) בתחילת כל קובץ, לפני כל הפונקציות. שיטת עבודה פשוטה זו לא רק שתעזור לכם בקלות ובמהירות לזהות את התלויות של קובץ מסוים, אלא גם תמנע מספר בעיות אפשריות. + +**אחרת:** טעינת מודולים היא תהליך סינכרוני ב-Node.js. אם הטעינה תתבצע מתוך פונקציה היא עלולה לחסום טיפול בבקשות אחרות בזמן קריטי. בנוסף לכך, אם מודול חיוני או מישהו שהוא תלוי בו יזרקו שגיאה ויפילו את השרת, מומלץ שזה יוודע כמה שיותר מוקדם, מה שלא בטוח יקרה במקרה שהמודול נטען מתוך פונקציה. + +

+ +## ![✔] 3.9 הגדירו כניסה מסודרת לספריה שלכם + +**אמ;לק:** בעת פיתוח מודול או ספריה, הגדירו קובץ בסיס שמייצא את הקוד המיועד לשימוש חיצוני. מנעו מהמשתמשים של הקוד שלכם את הצורך לייבא קבצים שיושבים עמוק אצלכם ואת הצורך שלהם להבין את מבנה הקבצים שלכם. כאשר עובדים בשיטת commonjs (require), זה יכול להיעשות על ידי שימוש בקובץ index.js שיושב בתיקיה הראשית או בהגדרת השדה main בקובץ package.json. כאשר עובדים בשיטת ESM (import), אם קובץ package.json קיים בתיקיה הראשית, אז השדה "exports" מאפשר את הגדרת הקובץ הראשי. אך אם אין קובץ package.json, אז שימוש בקובץ index.js בתיקיה הראשית ייצא את כל הפונקציונליות שמיועדת לשימוש חיצוני. + +**אחרת:** קיומו של קובץ ראשי רשמי משמש כממשק חיצוני שמסתיר את החלקים הפנימיים של הספריה, מקשר את המשתמש ישירות לקוד הזמין ומאפשר שינויים עתידיים ללא צורך לשבוראת החוזה. + +### דוגמה + +```javascript +// Avoid: client has deep familiarity with the internals + +// Client code +const SMSWithMedia = require("./SMSProvider/providers/media/media-provider.js"); + +// Better: explicitly export the public functions + +//index.js, module code +module.exports.SMSWithMedia = require("./SMSProvider/providers/media/media-provider.js"); + +// Client code +const { SMSWithMedia } = require("./SMSProvider"); +``` + +

+ +## ![✔] 3.10 השתמשו באופרטור `===` + +**אמ;לק:** העדיפו את ההשוואה הקפדנית באמצעות האופרטור `===` על פני ההשוואה החלשה יותר באמצעות האופרטור `==`. `==` משווה שני משתנים אחרי המרה של שניהם לסוג משתנה אחד. אין המרת סוגי משתנים באופרטור `===`, ושני המשתנים חייבים להיות מאותו סוג כדי שיוכלו להיות שווים. + +**אחרת:** משתנים בעלי ערכים שונים עלולים להחזיר `true` כאשר משווים ביניהם בעזרת האופרטור `==`. + +### דוגמאות + +```javascript +"" == "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 +``` + +כל ההשוואות לעיל יחזירו `false` בעת השוואה עם `===`. + +

+ +## ![✔] 3.11 השתמשו ב-Async Await, המנעו מ-callbacks + +**אמ;לק:** async-await זו הדרך הפשוטה ביותר לכתוב קוד אסינכרוני שירגיש כמו קוד סינכרוני. הקוד שיכתב בשיטת async-await הוא גם הרבה יותר פשוט ותומך במנגנון ה-try-catch. שיטה זו מחליפה את הצורך ב-callbacks ו-promises ברוב המקרים. שימוש בשיטה זו בקוד היא כנראה אחת המתנות הטובות יותר שאפשר לתת למי שיקרא את הקוד. + +**אחרת:** טיפול בשגיאות אסינכרוניות בשיטת callback היא כנראה הדרך המהירה לגהנום - מכיוון ששיטה זו מחייבת בדיקת שגיאות בכל שלב, יוצרת קינון מוזר בקוד ומקשה על הבנת תהליך הזרימה של הקוד. + +🔗[**לקריאה נוספת:** מדריך ל-async-await](https://github.com/yortus/asyncawait) + +

+ +## ![✔] 3.12 השתמשו בפונקציות חץ (=>) + +**אמ;לק:** אמנם מומלץ להשתמש ב async-await ולהימנע מהגדרת פרמטרים בפונקציות כאשר מתעסקים עם API ישן שתומך ב-callbacks או הבטחות - פונקציות חץ מאפשרות לארגן את הקוד קומפקטי יותר וכמובן ששומרות על הקונטקסט של פונקצית המעטפת (`this`). + +**אחרת:** קוד ארוך יותר (על בסיס פונקציות של ES5) חשוף ליותר באגים וקשה יותר לקריאה. + +🔗 [**לקריאה נוספת: הגיע הזמן לאמץ את פונקציות החץ**](https://medium.com/javascript-scene/familiarity-bias-is-holding-you-back-its-time-to-embrace-arrow-functions-3d37e1a9bb75) + +

+ +## ![✔] 3.13 הימנעו מהשפעות צדדיות מחוץ לפונקציות + +**אמ;לק:** הימנעו מכתיבת קוד עם השפעות צדדיות כמו פעולת רשת או פניה למסד נתונים מחוץ לפונקציה. אם כן תכתבו קוד כזה הוא ירוץ מיד כאשר קובץ אחר פונה לקובץ הזה. הקוד 'הצף' הזה עלול לרוץ כאשר התשתית אותה הוא מבקש עוד לא זמינה עבורו. זה גם פוגע בביצועים אפילו אם אין צורך בפונקציה שעבורה מתבצעת הפעולה בזמן הריצה. דבר אחרון, כתיבת כיסוי לפעולה זו בשביל בדיקות הרבה יותר מורכבת כשהיא לא נעשית בפונקציה. במקום זאת, שימו את הקוד הזה בפונקציה שצריכה להיקרא במפורש. אם הקוד הזה צריך להיקרא ישר בעת עליית המערכת, שיקלו שימוש ב-factory או בתבנית אחרת שמתאימה לדרישה כזאת. + +**אחרת:** תשתיות סטנדרטיות בעולם הווב מגדירות ניהול שגיאות, משתני סביבה וניטור תקלות. אם הפעולה תתבצע לפני שהתשתית מאותחלת אז לא יהיה ניטור של המקרה או שהפעולה תיכשל בשל חוסר בהגדרות שטרם נטענו. + +


+ +

⬆ חזרה למעלה

+ +# `4. בדיקות ובקרת איכות` + +> יש לנו מדריכים יעודיים לכתיבת בדיקות. רשימת שיטות העבודה המומלצות פה היא סיכום כללי של המדריכים הללו. +> +> א. [שיטות עבודה מומלצות בכתיבת בדיקות ל-JavaScript](https://github.com/goldbergyoni/javascript-testing-best-practices)
+> ב. [בדיקות ב-Node.js - מעבר ליסודות](https://github.com/testjavascript/nodejs-integration-tests-best-practices) + + +## ![✔] 4.1 לפחות, כיתבו בדיקות API לרכיבים השונים + +**אמ;לק:** ברוב הפרויקטים אין בדיקות אוטומטיות כלל בשל לוח זמנים קצר, או שהתחילו לנסות להוסיף בדיקות בפרויקט נוסף אך זה יצא משליטה וננטש עם הזמן. לכן, לתעדף ולהתחיל בדיקות API שזאת הדרך הקלה לכתוב בדיקות ולספק כיסוי (בדיקות) של הקוד מאשר בבדיקות יחידה של פונקציות בודדות (אפשר להשתמש בשביל זה גם בכלים חיצוניים ללא כתיבת קוד, למשל שימוש ב-[Postman](https://www.getpostman.com/)). לאחר מכן, אם יש לכם יותר משאבים וזמן תמשיכו עם בדיקות מתקדמות יותר כגון בדיקות יחידה, בדיקות מול מסדי הנתונים בדיקות ביצועים ועוד. + +**אחרת:** אתם עלולים לבזבז ימים שלמים על כתיבת בדיקות יחידה בלבד ולגלות בסופו של דבר שכיסיתם רק 20% מהמערכת. + +

+ +## ![✔] 4.2 סווגו 3 חלקים במתן שם לכל בדיקה + +**אמ;לק:** גירמו לבדיקה לתאר את שלב הדרישות כך שהיא תסביר את עצמה גם לQA או לאחרים (כולל אתכם בעתיד הלא רחוק) שלא בקיאים בחלקים הפנימיים של הקוד. ציינו בבדיקה (1) איזה חלק נבדק, (2) באילו תנאים (3) ומה התוצאה שמצפים שתחול. + +**אחרת:** ההתקנה בדיוק נכשלה, בדיקה בשם “Add product” נכשלה. האם זה מתאר מה בדיוק לא תיפקד? + +🔗 [**לקריאה נוספת: סווגו 3 חלקים במתן שם לכל בדיקה**](./sections/testingandquality/3-parts-in-name.md) + +

+ +## ![✔] 4.3 חלקו את הבדיקות לפי תבנית ה-AAA + +**אמ;לק:** חלקו את הבדיקות לשלושה חלקים נפרדים: Arrange (ארגן), Act (פעל) & Assert (ודא) (AAA). החלק הראשון כולל את ההכנה של הסביבה לבדיקה, החלק השני את ההרצה במצב בדיקות, ולבסוף החלק שמוודא שהתקבלה התוצאה הרצויה. שימוש במבנה זה בעקביות מבטיח שהקורא לא יבזבז זמן מחשבה של הבנת הבדיקה. + +**אחרת:** לא מספיק שיתבזבז זמן נרחב מהיום על הבנת הקוד, עכשיו גם החלק הקל ביום (הבנת הבדיקות) ישרוף את המוח. + +🔗 [**לקריאה נוספת: חלקו את הבדיקות לפי תבנית ה-AAA**](./sections/testingandquality/aaa.md) + +

+ +## ![✔] 4.4 וודאו כי גרסת ה-Node אחידה + +**אמ;לק:** השתמשו בכלים המעודדים או אוכפים שימוש באותה גרסת Node.js בסביבות השונות ועל ידי שאר המפתחים. כלים כמו [nvm](https://github.com/nvm-sh/nvm), ו-[Volta](https://volta.sh/) מאפשרים להגדיר במפורש את הגרסה הנדרשת בפרויקט בקובץ כך שכל חברי הצוות יכולים על ידי הרצת פקודה אחת ליישר קו עם גרסת הפרויקט. ישנה אפשרות שגרסה זו גם תשתקף לתהליך ה-CI וסביבת היצור/לקוחות (לדוגמה על ידי העתקת מספר הגרסה המבוקש ל-`.Dockerfile` ולקבצי ההגדרות של תהליך ה-CI). + +**אחרת:** מפתחת עלולה להיתקל או לפספס שגיאה מכיוון שהיא משתמשת בגרסת Node.js שונה משאר הצוות. או גרוע מכך, סביבת היצור רצה באמצעות גרסה שונה מזו שהורצו עליה הבדיקות. + +

+ +## ![✔] 4.5 הימנעו מאתחול מידע גרעיני משותף, הגדירו לפי צורך של בדיקה + +**אמ;לק:** כדי להימנע מצמידות ותלות בין בדיקות שונות וכדי שיהיה ברור יותר איך להסביר מה קורה בשלבים השונים של הבדיקה, ראוי שכל בדיקה תוסיף ותנהל את המידע העוטף שלה (למשל שורות בטבלה). במקרה ובדיקה צריכה לצרוך מידע מטבלה או להניח שהוא קיים שם - היא צריכה קודם לכן להוסיף את המידע במפורש ולהימנע משינוי מידע של בדיקה אחרת. + +**אחרת:** תארו לכם מקרה בו הפצת גרסה נכשלה בשל שגיאה בבדיקות, הצוות משנס מותניים לחקור את הסיבה ומגיע אם התובנה העצובה שהמערכת עובדת תקין אבל הבדיקות דורסות מידע אחת לשניה ולכן נכשלו ועצרו את תהליך ההפצה. + +🔗 [**לקריאה נוספת: הימנעו מאתחול מידע גרעיני משותף**](./sections/testingandquality/avoid-global-test-fixture.md) + +

+ +## ![✔] 4.6 תייגו את הבדיקות + +**אמ;לק:** בדיקות שונות צריכות לרוץ בתרחישים שונים: בדיקות שפיות (quick smoke/sanity), IO-less, בדיקות בעת שמירת קובץ או commit, בדיקות מלאות מקצה לקצה (e2e) כאשר נפתח PR וכולי... התרחישים השונים יכולים להיות מוגדרים בעזרת תיוג בדיקות שונות עם מילות מפתח כמו #cold #api #sanity דבר המאפשר להגדיר קבוצת בדיקות בהתאם לצורך ולהריץ רק אותה. למשל, זאת השיטה להריץ רק את קבוצת בדיקות השפיות באמצעות [Mocha](https://mochajs.org/): `mocha --grep 'sanity'`. + +**אחרת:** הרצה של כל הבדיקות כולל כאלו שמבצעות עשרות פניות למסד נתונים בכל פעם שמפתח עושה שינוי קטן יאט את קצב הפיתוח בצורה ניכרת ותמנע מצוות הפיתוח להריץ בדיקות. + +

+ +## ![✔] 4.7 בידקו את רמת כיסוי הבדיקות שלכם, זה יעזור לזהות דפוסי בדיקות שגויים + +**אמ;לק:** כלים לבדיקת כיסוי הקוד על ידי בדיקות כמו [Istanbul](https://github.com/istanbuljs/istanbuljs)/[NYC](https://github.com/istanbuljs/nyc) מצוינים בשל שלוש סיבות: הם בחינם (אין עלות לדו"חות שהם מספקים), הם עוזרים לזהות ירידה באחוזי הכיסוי, ואחרון חביב הם מדגישים מקרים של אי התאמה בבדיקות: על ידי צפייה בצבעים שהדוחות הללו מספקים אפשר לזהות למשל שיש קטעי קוד שלא נבדקים לעולם כמו הסתעפויות של `catch` (מה שאומר שיש בדיקות רק למסלול המצליח ולא למקרים של השגיאות). רצוי להגדיר את זה כך שזה יפיל את תהליכי יצירת הגרסאות במידה והכיסוי לא עובר סף מסוים. + +**אחרת:** לא יהיה שום אמצעי מדידה שידווח שקטעים נרחבים מהקוד לא נבדקים כלל. + +

+ +## ![✔] 4.8 Use production-like environment for e2e testing + +**אמ;לק:** 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) + +**אחרת:** 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.9 שכתבו את הקוד באופן קבוע בעזרת כלי ניתוח סטטי + +**אמ;לק:** שימוש בכלי ניתוח סטטי (static analysis tools) עוזר בכך שהוא נותן דרכים מתאימות לשפר את איכות הקוד ולשמור על הקוד מתוחזק. אפשר להוסיף כלים כאלו לשלבי הבנייה ב-CI כך שיפילו את התהליך במידה והם מזהים ניחוחות בקוד. אחד היתרונות העיקריים שלהם על פני כלים פשוטים יותר הוא היכולת לזהות פגמים באיכות הקוד על פני מספר קבצים (כמו כפל קוד), מורכבות גבוהה של קוד ומעקב אחרי ההיסטוריה וההתקדמות של הקוד. שני כלים מומלצים לשימוש הם [Sonarqube](https://www.sonarqube.org/) (7,900+ [stars](https://github.com/SonarSource/sonarqube)) ו [Code Climate](https://codeclimate.com/) (2,400+ [stars](https://github.com/codeclimate/codeclimate)). + +**אחרת:** אם הקוד באיכות נמוכה, תקלות ובעיות ביצועים תמיד יהוו אתגר שאף ספריה חדשה ונוצצת או פתרון טכנולוגי חדיש יוכלו לפתור. + +🔗 [**לקריאה נוספת: שכתוב!**](./sections/testingandquality/refactoring.md) + +

+ +## ![✔] 4.10 הדמיית תשובות של שרתי HTTP חיצוניים + +**אמ;לק:** השתמשו בכלי הדמיה של המידע שמגיע מהרשת עבור תשובות שמגיעות משירותים חיצוניים (כמו בקשות REST ו GraphQL). זה הכרחי לא רק כדי לבודד את הרכיב שנבדק אלא בעיקר כדי לבדוק מצבים לא צפויים. כלים כמו [nock](https://github.com/nock/nock) או [Mock-Server](https://www.mock-server.com/) מאפשרים להגדיר תשובה מסוימת לבקשה לשירות חיצוני בשורת קוד בודדה. חשוב לא לשכוח לדמות גם שגיאות, עיכובים, timeouts, וכל אירוע אחר שכנראה יקרה בסביבת הייצור. + +**אחרת:** לאפשר לרכיב לגשת למידע אמיתי משירותים חיצוניים בדרך כלל יסתיים בבדיקות פשוטות שמכסות בעיקר את המקרים שהכל טוב. בנוסף לכך הבדיקות לפעמים יכשלו ויהיו איטיות יותר. + +🔗 [**לקריאה נוספת: הדמיית שירותים חיצוניים**](./sections/testingandquality/mock-external-services.md) + +

+ +## ![✔] 4.11 בידקו את פונקציות הביניים בנפרד + +**אמ;לק:** כאשר פונקציית ביניים (middleware) אוחזת נתח משמעותי של לוגיקה שמשתרעת על פני מספר עצום של בקשות, כדאי לבדוק אותה בצורה מבודדת ללא צורך לטעון את כל תשתית הפריימוורק. אפשר להשיג את הפעולה הזאת בקלות על ידי עטיפה או הדמיה של `{req, res, next}`. + +**אחרת:** באג בפונקציות ביניים ב-`express` === באג ברוב הקריטי של הבקשות. + +🔗 [**לקריאה נוספת: לבדוק פונקציות ביניים בנפרד**](./sections/testingandquality/test-middlewares.md) + +

+ +## ![✔] 4.12 קבעו את הפורט בייצור, הגדירו אקראי לבדיקות + +**אמ;לק:** כאשר מבצעים בדיקות מול API, זה רצוי ואף נהוג לאתחל את השרת בתוך הבדיקות. תנו לשרת לבחור פורט באופן אקראי כאשר מריצים בדיקות כדי למנוע התנגשויות. אם אתם משתמשים בשרת HTTP של Node.js (בשימוש על ידי רוב ספריות התשתית), כדי להשיג את היכולת הזאת אין צורך לעשות כלום מלבד להעביר port=0 - זה כבר יגרום להקצאה דינאמית של פורט. + +**אחרת:** הגדרה של פורט ספציפי ימנע את האפשרות להריץ שני טסטים במקביל. רוב הכלים שמריצים כיום טסטים - מריצים במקביל כברירת מחדל. + +🔗 [**לקריאה נוספת: הגדירו פורט אקראי לבדיקות**](./sections/testingandquality/randomize-port.md) + +

+ +## ![✔] 4.13 בידקו את חמשת התוצאות האפשריות + +**אמ;לק:** בעת בדיקת מקרה, ודאו שאתם מכסים את חמשת הקטגוריות האפשריות. בכל פעם שפעולה חלה (למשל קריאת API), מתחילה תגובה, **תוצאה** משמעותית נוצרת ומתבצעת קריאה לבדיקה. ישנן חמש סוגי תוצאות לכל מקרה: תגובה, שינוי נראה לעין (כמו עדכון במסד הנתונים), שליחת קריאה ל- +API, הודעה חדשה נרשמת לתור, וקריאה לכלי צפיה במידע (כמו לוגר ואנליטיקות). [רשימת בדיקות בסיסיות](https://testjavascript.com/wp-content/uploads/2021/10/the-backend-checklist.pdf). כל סוג של תוצאה מגיע אם אתגרים יחודיים ושיטות להמתיק את האתגרים הללו - כתבנו מדריך יעודי על נושא זה [בדיקות ב-Node.js - מעבר ליסודות](https://github.com/testjavascript/nodejs-integration-tests-best-practices) + +**אחרת:** תארו לעצמכם מקרה של בדיקת הוספה של מוצר חדש למערכת. נפוץ לראות בדיקות שמכסות אך ורק את המקרים של תשובה תקינה. מה יקרה אם המוצר לא יתווסף על אף התשובה החיובית? מה צריך להיעשות במידה ובעת הוספת מוצר יש גם קריאה לשירות חיצוני או הוספת הודעה לתור - האם הבדיקה לא צריכה להתייחס גם לזה? קל להתעלם ממגוון מקרים, ובנקודה זאת [רשימת הבדיקות](https://testjavascript.com/wp-content/uploads/2021/10/the-backend-checklist.pdf) עוזרת. + +🔗 [**לקריאה נוספת: בדיקת חמשת התוצאות**](./sections/testingandquality/test-five-outcomes.md) + +


+ +

⬆ חזרה למעלה

+ +# `5. עלייה לאוויר` + +## ![✔] 5.1. ניטור + +**אמ;לק:** ניטור הוא משחק של מציאת בעיות לפני שהמשתמשים מוצאים אותן - מובן מאליו שזה צריך להיות בראש סדר העדיפויות. השוק מוצף בהצעות להגדרות מה הם המדדים הבסיסיים שחייבים לעקוב אחריהם (ההמלצות שלנו בהמשך), לאחר מכן לעבור על כל היכולות המעניינות שכל מוצר מציע ולבחור את הפתרון המיטבי עבור הדרישות שלכם. בכל מקרה, ארבעת השכבות הניתנות לצפייה חייבות להימדד: (1) Uptime - מציינת האם המערכת זמינה, (2) Metrics - מציינת מהי ההתנהגות המצטברת של המערכת (האם 99% מהבקשות נענות), (3) Logging - בודקת אם בקשה מסויימת מסתיימת בהצלחה, (4) Distributed tracing - בודקת האם המערכת יציבה בין הרכיבים המבוזרים שלה. + +**אחרת:** כשלון === לקוחות מאוכזבים. פשוט מאוד. + +🔗 [**לקריאה נוספת: ניטור!**](./sections/production/monitoring.md) + +

+ +## ![✔] 5.2. הגדילו את יכולת הצפייה בעזרת לוגים איכותיים + +**אמ;לק:** לוגים יכולים להיות פח הזבל של שלל מצבים שהמפתחים רצו לדבג או לחלופין מסך מהמם שמתאר את המצב של המוצר. תכננו את הלוגים שלכם מהיום הראשון: איך הם נאספים, איפה הם נשמרים ואיך הם מנותחים כדי להבטיח שהמידע ההכרחי (אחוז שגיאות, מעקב אחר פעולה בין מספר שירותים וכו') באמת נגיש ובר שימוש. + +**אחרת:** יש לכם קופסה שחורה שקשה להבין למה היא מגיעה למצב הנוכחי, ורק עכשיו אתם מתחילים לשכתב את כל הלוגים שלכם כדי שיהיה מידע רלוונטי. + +🔗 [**לקריאה נוספת: הגדלת השקיפות על ידי לוגים איכותיים**](./sections/production/smartlogging.md) + +

+ +## ![✔] 5.3. האצילו כל מה שאפשר (לדוגמה gzip, SSL) לשירות נפרד + +**אמ;לק:** Node.js גרוע בלבצע פעולות שדורשות עוצמת חישוב גבוהה מה-CPU, כמו למשל דחיסה, סיום תהליך SSL, וכו'... כדאי שתשתמשו בתשתיות כמו nginx, HAproxy או שירותי ענן אחרים לשם כך. + +**אחרת:** הת'רד הבודד והמסכן שלכם יישאר עסוק במשימות תשתיתיות במקום להתעסק בלב המערכת שלכם והביצועים יישחקו בהתאם. + +🔗 [**לקריאה נוספת: האצלת כל מה שאפשר (לדוגמה gzip, SSL) לשירות נפרד**](./sections/production/delegatetoproxy.md) + +

+ +## ![✔] 5.4. קיבוע תלויות + +**אמ;לק:** הקוד שלכם צריך להיות זהה בכל הסביבות, אך ללא קובץ יעודי npm יאפשר שימוש בתלויות שונות בכל סביבה. ודאו כי יש לכם `package-lock.json` כך שכל הסביבות יהיו זהות. + +**אחרת:** אנשי הבדיקות יאשרו גרסה שתתנהג אחרת בסביבת ייצור. גרוע מכך, שרתים שונים באותה סביבה יריצו קוד שונה. + +🔗 [**לקריאה נוספת: קיבוע תלויות**](./sections/production/lockdependencies.md) + +

+ +## ![✔] 5.5. הבטיחו את זמינות המערכת בעזרת הכלי המתאים + +**אמ;לק:** המערכת צריכה להמשיך לעבוד ולהתאתחל במידה וקרתה שגיאה קריטית. סביבות ריצה חדשות כמו למשל כאלו המבוססות דוקר (כמו קוברנטיס), או Serverless מטפלות בזה בצורה אוטומטית. כאשר המוצר מותקן על שרת אמיתי פיזי, יש צורך לנהל את משאבי המערכת בעזרת כלי כמו [systemd](https://systemd.io/). אך יש להימנע מלעשות זאת כאשר משתמשים בתשתיות שכבר מבצעות את הניטור מכיוון שזה יגרום לבליעת שגיאות. כאשר לתשתית אין מודעות לשגיאות, אין לה יכולת של ביצוע שלבי פיחות משאבים כמו העברת האינסטנס של המערכת למקום אחר ברשת. + +**אחרת:** הרצה של עשרות אינסטנסים ללא סיבה ברורה ויותר מידי כלי תשתית יחד (cluster management, docker, PM2) עלול לגרום לכאוס עבור ה-DevOps. + +🔗 [**לקריאה נוספת: הבטיחו את זמינות המערכת בעזרת הכלי המתאים**](./sections/production/guardprocess.md) + +

+ +## ![✔] 5.6. השתמשו בכל מעבדי ה-CPU + +**אמ;לק:** בתצורה הבסיסית שלה, מערכת מבוססת Node.js תרוץ על מעבד CPU אחד ושאר המעבדים ינוחו. מחובתכם לשכפל את התהליך ולנהל את המערכת ככה שתרוץ על כל המעבדים. רוב תשתיות הריצה החדשות (כמו קוברנטיס) מאפשרות לשכפל את התהליכים למספר מעבדים, אך הן לא מבטיחות להשתמש בכל המעבדים - זאת האחריות שלכם! אם המוצר מותקן על שרת פיזי, אז כחלק מאחריותכם אתם צריכים גם להשתמש בפתרונות שיבצעו את השכפול של התהליך (כמו systemd). + +**אחרת:** המוצר שלכם ינצל לכל היותר 25% מהמשאבים הזמינים(!). זכרו שלשרת רגיל יש 4 מעבדי CPU או יותר, והתקנה סטנדרטית של תהליך Node.js משתמשת רק במעבד אחד (גם שירותים בשיטת PaaS כמו AWS beanstalk!). + +🔗 [**לקריאה נוספת: השתמשו בכל מעבדי ה-CPU**](./sections/production/utilizecpu.md) + +

+ +## ![✔] 5.7. תיצרו ‘maintenance endpoint’ + +**אמ;לק:** חישפו מידע רלוונטי על המערכת, למשל מצב הזיכרון ו -[REPL](https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop), באמצעות API מאובטח. על אף שמומלץ להישען על כלים יעודיים לשם כך, את חלק מהמידע והפעולות יותר פשוט לבדוק באמצעות כתיבת קוד. + +**אחרת:** תגלו שאתם מבצעים הרבה “diagnostic deploys” – העלאת קוד לסביבת הייצור רק כדי להשיג עוד קצת מידע אבחנתי על המערכת. + +🔗 [**לקריאה נוספת: יצירת ‘maintenance endpoint’**](./sections/production/createmaintenanceendpoint.md) + +

+ +## ![✔] 5.8. גלו את הלא ידוע בעזרת מוצרי APM + +**אמ;לק:** שיקלו הוספת שכבה נוספת של בטיחות למוצר שלכם - [APM](https://en.wikipedia.org/wiki/Application_performance_management) (Application monitoring and performance products). אמנם רוב הסממנים והגורמים יכולים להימצא על ידי טכניקות ניטור סטנדרטיות, אך במערכות מבוזרות יש עוד רבדים סמויים מן העין. ניטור מערכות ובדיקת ביצועים (או בקיצור APM) יכולים באופן קסום להוסיף שכבה נוספת של חוויית פיתוח מעבר למה שמספקים הכלים הסטנדרטיים. לדוגמה, ישנם כלי APM שיכולים להדגיש טרנזקציה שטוענת לאט מידי את **צד הלקוח** ולהציע מה הסיבה לכך. כלים אלו גם מספקים יותר הקשר לצוות הפיתוח שמנסים לחקור שגיאה וזאת על ידי הצגה של העומסים שהיו בשרת בזמן שחלה השגיאה. + +**אחרת:** אתם משקיעים זמן ניכר במדידת ביצועי API ואי זמינות של המערכת, כנראה שלעולם לא תהיו מודעים לאילו חלקים בקוד הם האיטיים ביותר בזמן אמת ואיך זה משפיע על חווית המשתמש. + +🔗 [**לקריאה נוספת: גילוי שגיאות וזמני השבתה בעזרת מוצרי APM**](./sections/production/apmproducts.md) + +

+ +## ![✔] 5.9. כתבו את הקוד מותאם להתקנה + +**אמ;לק:** קודדו כאשר התוצאה הסופית במחשבותיכם, התכוננו להתקנה בסביבת יצור כבר מהיום הראשון. זה אמנם נשמע קצת מעורפל ולכן בקישור ישנן מספר המלצות הקשורות לתמיכה במוצר שכבר הותקן. + +**אחרת:** אלופי העולם של IT/DevOps לא ינסו להציל מערכת שכתובה גרוע. + +🔗 [**לקריאה נוספת: כתבו את הקוד מותאם להתקנה**](./sections/production/productioncode.md) + +

+ +## ![✔] 5.10. מדדו ושימרו את ניצול הזיכרון + +**אמ;לק:** ל-Node.js ישנה מערכת יחסים מורכבת עם ניהול הזיכרון: למנוע ה-v8 ישנם גבולות עדינים של צריכת זיכרון (1.4GB) וישנן דרכים ידועות איך לגרום לזליגת זיכרון בקוד של Node.js - ולכן מעקב אחר צריכת הזיכרון של תהליך Node.js הוא חובה. במוצרים קטנים, אפשר לאמוד את צריכת הזיכרון כל כמה זמן בעזרת פקודות shell, אבל במוצרים בינוניים-גדולים צריך לתעדף שימוש בכלים חזקים לניטור מצב הזיכרון. + +**אחרת:** זולגים לכם מאות MB כל יום מהתהליך כמו שקרה ב[וולמארט](https://www.joyent.com/blog/walmart-node-js-memory-leak) + +🔗 [**לקריאה נוספת: מדידה ושמירה על ניצול הזיכרון**](./sections/production/measurememory.md) + +

+ +## ![✔] 5.11. Get your frontend assets out of Node + +**אמ;לק:** Serve frontend content using a specialized infrastructure (nginx, S3, CDN) because Node performance gets hurt when dealing with many static files due to its single-threaded model. One exception to this guideline is when doing server-side rendering + +**אחרת:** 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**](./sections/production/frontendout.md) + +

+ +## ![✔] 5.12. Strive to be stateless + +**אמ;לק:** Store any type of _data_ (e.g. user sessions, cache, uploaded files) within external data stores. When the app holds data in-process this adds additional layer of maintenance complexity like routing users to the same instance and higher cost of restarting a process. To enforce and encourage a stateless approach, most modern runtime platforms allows 'reapp-ing' instances periodically + +**אחרת:** 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**](./sections/production/bestateless.md) + +

+ +## ![✔] 5.13. Use tools that automatically detect vulnerabilities + +**אמ;לק:** 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 be tamed using community and commercial tools that constantly check for vulnerabilities and warn (locally or at GitHub), some can even patch them immediately + +**אחרת:** 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**](./sections/production/detectvulnerabilities.md) + +

+ +## ![✔] 5.14. Assign a transaction id to each log statement + +**אמ;לק:** Assign the same identifier, transaction-id: uuid(), to each log entry within a single request (also known as correlation-id/tracing-id/request-context). Then when inspecting errors in logs, easily conclude what happened before and after. Node has a built-in mechanism, [AsyncLocalStorage](https://nodejs.org/api/async_context.html), for keeping the same context across asynchronous calls. see code examples inside + +**אחרת:** 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**](./sections/production/assigntransactionid.md) + +

+ +## ![✔] 5.15. Set `NODE_ENV=production` + +**אמ;לק:** Set the environment variable `NODE_ENV` to ‘production’ or ‘development’ to flag whether production optimizations should get activated – some npm packages determine the current environment and optimize their code for production + +**אחרת:** Omitting this simple property might greatly degrade performance when dealing with some specific libraries like Express server-side rendering + +🔗 [**Read More: Set NODE_ENV=production**](./sections/production/setnodeenv.md) + +

+ +## ![✔] 5.16. Design automated, atomic and zero-downtime deployments + +**אמ;לק:** 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 + +**אחרת:** 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 + +**אמ;לק:** Ensure you are using an LTS version of Node.js to receive critical bug fixes, security updates and performance improvements + +**אחרת:** 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**](./sections/production/LTSrelease.md) + +

+ +## ![✔] 5.18. Log to stdout, avoid specifying log destination within the app + +**אמ;לק:** 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.). + +**אחרת:** If developers set the log routing, less flexibility is left for the ops professional who wishes to customize it. Beyond this, if the app tries to log directly to a remote location (e.g., Elastic Search), in case of panic or crash - further logs that might explain the problem won't arrive + +🔗 [**Read More: Log Routing**](./sections/production/logrouting.md) + +

+ +## ![✔] 5.19. Install your packages with `npm ci` + +**אמ;לק:** Run `npm ci` to strictly do a clean install of your dependencies matching package.json and package-lock.json. Obviously production code must use the exact version of the packages that were used for testing. While package-lock.json file sets strict version for dependencies, in case of mismatch with the file package.json, the command 'npm install' will treat package.json as the source of truth. On the other hands, the command 'npm ci' will exit with error in case of mismatch between these files + +**אחרת:** 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**](./sections/production/installpackageswithnpmci.md) + +


+ +

⬆ חזרה למעלה

+ +# `6. אבטחה` + +
+54 items +
+ +## ![✔] 6.1. Embrace linter security rules + + + +**אמ;לק:** Make use of security-related linter plugins such as [eslint-plugin-security](https://github.com/nodesecurity/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 + +**אחרת:** 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**](./sections/security/lintrules.md) + +

+ +## ![✔] 6.2. Limit concurrent requests using a middleware + + + +**אמ;לק:** 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](https://www.npmjs.com/package/rate-limiter-flexible) package, or (for smaller and less critical apps) a rate-limiting middleware (e.g. [express-rate-limit](https://www.npmjs.com/package/express-rate-limit)) + +**אחרת:** 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**](./sections/security/limitrequests.md) + +

+ +## ![✔] 6.3 Extract secrets from config files or use packages to encrypt them + + + +**אמ;לק:** 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 + +**אחרת:** 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**](./sections/security/secretmanagement.md) + +

+ +## ![✔] 6.4. Prevent query injection vulnerabilities with ORM/ODM libraries + + + +**אמ;לק:** 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](https://github.com/sequelize/sequelize), [Knex](https://github.com/tgriesser/knex), [mongoose](https://github.com/Automattic/mongoose)) have built-in protection against injection attacks. + +**אחרת:** 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**](./sections/security/ormodmusage.md) + +

+ +## ![✔] 6.5. Collection of generic security best practices + +**אמ;לק:** 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**](./sections/security/commonsecuritybestpractices.md) + +

+ +## ![✔] 6.6. Adjust the HTTP response headers for enhanced security + + + +**אמ;לק:** 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](https://www.npmjs.com/package/helmet). + +**אחרת:** Attackers could perform direct attacks on your application's users, leading to huge security vulnerabilities + +🔗 [**Read More: Using secure headers in your application**](./sections/security/secureheaders.md) + +

+ +## ![✔] 6.7. Constantly and automatically inspect for vulnerable dependencies + + + +**אמ;לק:** 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](https://docs.npmjs.com/cli/audit) or [snyk](https://snyk.io/) 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. + +**אחרת:** An attacker could detect your web framework and attack all its known vulnerabilities. + +🔗 [**Read More: Dependency security**](./sections/security/dependencysecurity.md) + +

+ +## ![✔] 6.8. Protect Users' Passwords/Secrets using bcrypt or scrypt + + + +**אמ;לק:** Passwords or secrets (e.g. API keys) should be stored using a secure hash + salt function like `bcrypt`,`scrypt`, or worst case `pbkdf2`. + +**אחרת:** 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**](./sections/security/userpasswords.md) + +

+ +## ![✔] 6.9. Escape HTML, JS and CSS output + + + +**אמ;לק:** 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) + +**אחרת:** 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**](./sections/security/escape-output.md) + +

+ +## ![✔] 6.10. Validate incoming JSON schemas + + + +**אמ;לק:** 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](https://www.npmjs.com/package/jsonschema) or [joi](https://www.npmjs.com/package/joi) + +**אחרת:** 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**](./sections/security/validation.md) + +

+ +## ![✔] 6.11. Support blocklisting JWTs + + + +**אמ;לק:** When using JSON Web Tokens (for example, with [Passport.js](https://github.com/jaredhanson/passport)), 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. + +**אחרת:** 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**](./sections/security/expirejwt.md) + +

+ +## ![✔] 6.12. Prevent brute-force attacks against authorization + + + +**אמ;לק:** 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. + +**אחרת:** An attacker can issue unlimited automated password attempts to gain access to privileged accounts on an application + +🔗 [**Read More: Login rate limiting**](./sections/security/login-rate-limit.md) + +

+ +## ![✔] 6.13. Run Node.js as non-root user + + + +**אמ;לק:** 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" + +**אחרת:** 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 their server) + +🔗 [**Read More: Run Node.js as non-root user**](./sections/security/non-root-user.md) + +

+ +## ![✔] 6.14. Limit payload size using a reverse-proxy or a middleware + + + +**אמ;לק:** 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](https://github.com/expressjs/body-parser) to accept only small-size payloads + +**אחרת:** 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**](./sections/security/requestpayloadsizelimit.md) + +

+ +## ![✔] 6.15. Avoid JavaScript eval statements + + + +**אמ;לק:** `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. + +**אחרת:** 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**](./sections/security/avoideval.md) + +

+ +## ![✔] 6.16. Prevent evil RegEx from overloading your single thread execution + + + +**אמ;לק:** 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](https://github.com/chriso/validator.js) instead of writing your own Regex patterns, or make use of [safe-regex](https://github.com/substack/safe-regex) to detect vulnerable regex patterns + +**אחרת:** 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**](./sections/security/regex.md) + +

+ +## ![✔] 6.17. Avoid module loading using a variable + + + +**אמ;לק:** 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](https://www.npmjs.com/package/eslint-plugin-security) linter can catch such patterns and warn early enough + +**אחרת:** 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**](./sections/security/safemoduleloading.md) + +

+ +## ![✔] 6.18. Run unsafe code in a sandbox + + + +**אמ;לק:** 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 + +**אחרת:** 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**](./sections/security/sandbox.md) + +

+ +## ![✔] 6.19. Take extra care when working with child processes + + + +**אמ;לק:** 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. + +**אחרת:** 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**](./sections/security/childprocesses.md) + +

+ +## ![✔] 6.20. Hide error details from clients + + + +**אמ;לק:** 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 + +**אחרת:** 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**](./sections/security/hideerrors.md) + +

+ +## ![✔] 6.21. Configure 2FA for npm or Yarn + + + +**אמ;לק:** 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. + +**אחרת:** [Have you heard about the eslint developer whose password was hijacked?](https://medium.com/@oprearocks/eslint-backdoor-what-it-is-and-how-to-fix-the-issue-221f58f1a8c8) + +

+ +## ![✔] 6.22. Modify session middleware settings + + + +**אמ;לק:** 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) + +**אחרת:** 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**](./sections/security/sessions.md) + +

+ +## ![✔] 6.23. Avoid DOS attacks by explicitly setting when a process should crash + + + +**אמ;לק:** 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) + +**אחרת:** 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 + + + +**אמ;לק:** Redirects that do not validate user input can enable attackers to launch phishing scams, steal user credentials, and perform other malicious actions. + +**אחרת:** 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**](./sections/security/saferedirects.md) + +

+ +## ![✔] 6.25. Avoid publishing secrets to the npm registry + + + +**אמ;לק:** 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. + +**אחרת:** 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**](./sections/security/avoid_publishing_secrets.md) + +

+ +## ![✔] 6.26 Inspect for outdated packages + +**אמ;לק:** Use your preferred tool (e.g. `npm outdated` or [npm-check-updates](https://www.npmjs.com/package/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 + +**אחרת:** Your production will run packages that have been explicitly tagged by their author as risky + +

+ +## ![✔] 6.27. Import built-in modules using the 'node:' protocol + + + +**אמ;לק:** Import or require built-in Node.js modules using the 'node protocol' syntax: + +```javascript +import { functionName } from "node:module"; // note that 'node:' prefix +``` + +For example: + +```javascript +import { createServer } from "node:http"; +``` + +This style ensures that there is no ambiguity with global npm packages and makes it clear for the reader that the code refers to a well-trusted official module. This style can be enforced with the eslint rule ['prefer-node-protocol'](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-node-protocol.md) + +**אחרת:** Using the import syntax without 'node:' prefix opens the door for [typosquatting attacks](https://en.wikipedia.org/wiki/Typosquatting) where one could mistakenly mistype a module name (e.g., 'event' instead of 'events) and get a malicious package that was built only to trick users into installing them + +


+ +

⬆ חזרה למעלה

+ +# `7. טיוטה: ביצועים` + +## Our contributors are working on this section. [Would you like to join?](https://github.com/goldbergyoni/nodebestpractices/issues/256) + +

+ +## ![✔] 7.1. Don't block the event loop + +**אמ;לק:** 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. + +**אחרת:** 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**](./sections/performance/block-loop.md) + +


+ +## ![✔] 7.2. Prefer native JS methods over user-land utils like Lodash + +**אמ;לק:** 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. + +**אחרת:** 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**](./sections/performance/nativeoverutil.md) + +


+ +

⬆ חזרה למעלה

+ +# `8. דוקר` + +🏅 Many thanks to [Bret Fisher](https://github.com/BretFisher) from whom we learned many of the following practices + +

+ +## ![✔] 8.1 Use multi-stage builds for leaner and more secure Docker images + +**אמ;לק:** 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. + +**אחרת:** 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 + +```dockerfile +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**](./sections/docker/multi_stage_builds.md) + +


+ +## ![✔] 8.2. Bootstrap using `node` command, avoid `npm start` + +**אמ;לק:** 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 + +Update: [Starting from npm 7, npm claim](https://docs.npmjs.com/cli/v7/using-npm/changelog#706-2020-10-27) to pass signals. We follow and will update accordingly + +**אחרת:** 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**](./sections/docker/bootstrap-using-node.md) + +


+ +## ![✔] 8.3. Let the Docker runtime handle replication and uptime + +**אמ;לק:** 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 + +**אחרת:** 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**](./sections/docker/restart-and-replicate-processes.md) + +


+ +## ![✔] 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**](./sections/docker/docker-ignore.md) + +


+ +## ![✔] 8.5. Clean-up dependencies before production + +**אמ;לק:** 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` + +**אחרת:** Many of the infamous npm security breaches were found within development packages (e.g. [eslint-scope](https://eslint.org/blog/2018/07/postmortem-for-malicious-package-publishes)) + +🔗 Read More: [Remove development dependencies](./sections/docker/install-for-production.md) + +


+ +## ![✔] 8.6. Shutdown smartly and gracefully + +**אמ;לק:** 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 + +**אחרת:** Dying immediately means not responding to thousands of disappointed users + +🔗 [**Read More: Graceful shutdown**](./sections/docker/graceful-shutdown.md) + +


+ +## ![✔] 8.7. Set memory limits using both Docker and v8 + +**אמ;לק:** 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 + +**אחרת:** 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**](./sections/docker/memory-limit.md) + +


+ +## ![✔] 8.8. Plan for efficient caching + +**אמ;לק:** 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. + +**אחרת:** Docker build will be very long and consume lot of resources even when making tiny changes + +🔗 [**Read More: Leverage caching to reduce build times**](./sections/docker/use-cache-for-shorter-build-time.md) + +


+ +## ![✔] 8.9. Use explicit image reference, avoid `latest` tag + +**אמ;לק:** 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. + +**אחרת:** 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**](./sections/docker/image-tags.md) + +


+ +## ![✔] 8.10. Prefer smaller Docker base images + +**אמ;לק:** 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. + +**אחרת:** 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**](./sections/docker/smaller_base_images.md) + +


+ +## ![✔] 8.11. Clean-out build-time secrets, avoid secrets in args + +**אמ;לק:** 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 + +**אחרת:** 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**](./sections/docker/avoid-build-time-secrets.md) + +


+ +## ![✔] 8.12. Scan images for multi layers of vulnerabilities + +**אמ;לק:** 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 + +**אחרת:** 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**](./sections/docker/scan-images.md) + +


+ +## ![✔] 8.13 Clean NODE_MODULE cache + +**אמ;לק:** 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 + +**אחרת:** 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**](./sections/docker/clean-cache.md) + +


+ +## ![✔] 8.14. Generic Docker practices + +**אמ;לק:** 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**](./sections/docker/generic-tips.md) + +


+ +## ![✔] 8.15. Lint your Dockerfile + +**אמ;לק:** 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. + +**אחרת:** 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**](./sections/docker/lint-dockerfile.md) + +


+ +

⬆ חזרה למעלה

+ +# 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](https://github.com/goldbergyoni/nodebestpractices/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 + +- ![BR](./assets/flags/BR.png) [Brazilian Portuguese](./README.brazilian-portuguese.md) - Courtesy of [Marcelo Melo](https://github.com/marcelosdm) +- ![CN](./assets/flags/CN.png) [Chinese](./README.chinese.md) - Courtesy of [Matt Jin](https://github.com/mattjin) +- ![RU](./assets/flags/RU.png) [Russian](./README.russian.md) - Courtesy of [Alex Ivanov](https://github.com/contributorpw) +- ![PL](./assets/flags/PL.png) [Polish](./README.polish.md) - Courtesy of [Michal Biesiada](https://github.com/mbiesiad) +- ![JA](./assets/flags/JA.png) [Japanese](./README.japanese.md) - Courtesy of [Yuki Ota](https://github.com/YukiOta), [Yuta Azumi](https://github.com/YA21) +- ![EU](./assets/flags/EU.png) [Basque](README.basque.md) - Courtesy of [Ane Diaz de Tuesta](https://github.com/anediaz) & Joxefe Diaz de Tuesta + +### Translations in progress + +- ![FR](./assets/flags/FR.png) [French](./README.french.md) ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/129)) +- ![HE](./assets/flags/HE.png) Hebrew ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/156)) +- ![KR](./assets/flags/KR.png) [Korean](README.korean.md) - Courtesy of [Sangbeom Han](https://github.com/uronly14me) ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/94)) +- ![ES](./assets/flags/ES.png) [Spanish](https://github.com/goldbergyoni/nodebestpractices/blob/spanish-translation/README.spanish.md) ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/95)) +- ![TR](./assets/flags/TR.png) Turkish ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/139)) + +

+ +## 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](https://github.com/goldbergyoni/nodebestpractices/projects). + + + +[Yoni Goldberg](https://github.com/goldbergyoni) + + + +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](https://goldbergyoni.com). Reach Yoni at [@goldbergyoni](https://github.com/goldbergyoni) or [me@goldbergyoni.com](mailto:me@goldbergyoni.com) + +
+ +Josh Hemphill + +[Josh Hemphill](https://github.com/josh-hemphill) + + + + +Full Stack Software Engineer / Developer specializing in Security, DevOps/DevSecOps, and ERP Integrations. + +
+ +Raz Luvaton + +[Raz Luvaton](https://github.com/rluvaton) + + + +Full Stack Developer who knows how to exit from Vim and loves Architecture, Virtualization and Security. + +
+ +## Contributing + +If you've ever wanted to contribute to open source, now is your chance! See the [contributing docs](.operations/CONTRIBUTING.md) for more information. + +## Contributors ✨ + +Thanks goes to these wonderful people who have contributed to this repository! + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Kevin Rambaud
Kevin Rambaud

🖋
Michael Fine
Michael Fine

🖋
Shreya Dahal
Shreya Dahal

🖋
Matheus Cruz Rocha
Matheus Cruz Rocha

🖋
Yog Mehta
Yog Mehta

🖋
Kudakwashe Paradzayi
Kudakwashe Paradzayi

🖋
t1st3
t1st3

🖋
mulijordan1976
mulijordan1976

🖋
Matan Kushner
Matan Kushner

🖋
Fabio Hiroki
Fabio Hiroki

🖋
James Sumners
James Sumners

🖋
Dan Gamble
Dan Gamble

🖋
PJ Trainor
PJ Trainor

🖋
Remek Ambroziak
Remek Ambroziak

🖋
Yoni Jah
Yoni Jah

🖋
Misha Khokhlov
Misha Khokhlov

🖋
Evgeny Orekhov
Evgeny Orekhov

🖋
-
-

🖋
Isaac Halvorson
Isaac Halvorson

🖋
Vedran Karačić
Vedran Karačić

🖋
lallenlowe
lallenlowe

🖋
Nathan Wells
Nathan Wells

🖋
Paulo Reis
Paulo Reis

🖋
syzer
syzer

🖋
David Sancho
David Sancho

🖋
Robert Manolea
Robert Manolea

🖋
Xavier Ho
Xavier Ho

🖋
Aaron
Aaron

🖋
Jan Charles Maghirang Adona
Jan Charles Maghirang Adona

🖋
Allen
Allen

🖋
Leonardo Villela
Leonardo Villela

🖋
Michał Załęcki
Michał Załęcki

🖋
Chris Nicola
Chris Nicola

🖋
Alejandro Corredor
Alejandro Corredor

🖋
cwar
cwar

🖋
Yuwei
Yuwei

🖋
Utkarsh Bhatt
Utkarsh Bhatt

🖋
Duarte Mendes
Duarte Mendes

🖋
Jason Kim
Jason Kim

🖋
Mitja O.
Mitja O.

🖋
Sandro Miguel Marques
Sandro Miguel Marques

🖋
Gabe
Gabe

🖋
Ron Gross
Ron Gross

🖋
Valeri Karpov
Valeri Karpov

🖋
Sergio Bernal
Sergio Bernal

🖋
Nikola Telkedzhiev
Nikola Telkedzhiev

🖋
Vitor Godoy
Vitor Godoy

🖋
Manish Saraan
Manish Saraan

🖋
Sangbeom Han
Sangbeom Han

🖋
blackmatch
blackmatch

🖋
Joe Reeve
Joe Reeve

🖋
Ryan Busby
Ryan Busby

🖋
Iman Mohamadi
Iman Mohamadi

🖋
Sergii Paryzhskyi
Sergii Paryzhskyi

🖋
Kapil Patel
Kapil Patel

🖋
迷渡
迷渡

🖋
Hozefa
Hozefa

🖋
Ethan
Ethan

🖋
Sam
Sam

🖋
Arlind
Arlind

🖋
Teddy Toussaint
Teddy Toussaint

🖋
Lewis
Lewis

🖋
Gabriel Lidenor
Gabriel Lidenor

🖋
Roman
Roman

🖋
Francozeira
Francozeira

🖋
Invvard
Invvard

🖋
Rômulo Garofalo
Rômulo Garofalo

🖋
Tho Q Luong
Tho Q Luong

🖋
Burak Shen
Burak Shen

🖋
Martin Muzatko
Martin Muzatko

🖋
Jared Collier
Jared Collier

🖋
Hilton Meyer
Hilton Meyer

🖋
ChangJoo Park(박창주)
ChangJoo Park(박창주)

🖋
Masahiro Sakaguchi
Masahiro Sakaguchi

🖋
Keith Holliday
Keith Holliday

🖋
coreyc
coreyc

🖋
Maximilian Berkmann
Maximilian Berkmann

🖋
Douglas Mariano Valero
Douglas Mariano Valero

🖋
Marcelo Melo
Marcelo Melo

🖋
Mehmet Perk
Mehmet Perk

🖋
ryan ouyang
ryan ouyang

🖋
Shabeer
Shabeer

🖋
Eduard Kyvenko
Eduard Kyvenko

🖋
Deyvison Rocha
Deyvison Rocha

🖋
George Mamer
George Mamer

🖋
Konstantinos Leimonis
Konstantinos Leimonis

🖋
Oliver Lluberes
Oliver Lluberes

🌍
Tien Do
Tien Do

🖋
Ranvir Singh
Ranvir Singh

🖋
Vadim Nicolaev
Vadim Nicolaev

🖋 🌍
German Gamboa Gonzalez
German Gamboa Gonzalez

🖋
Hafez
Hafez

🖋
Chandiran
Chandiran

🖋
VinayaSathyanarayana
VinayaSathyanarayana

🖋
Kim Kern
Kim Kern

🖋
Kenneth Freitas
Kenneth Freitas

🖋
songe
songe

🖋
Kirill Shekhovtsov
Kirill Shekhovtsov

🖋
Serge
Serge

🖋
keyrwinz
keyrwinz

🖋
Dmitry Nikitenko
Dmitry Nikitenko

🖋
bushuai
bushuai

👀 🖋
Benjamin Gruenbaum
Benjamin Gruenbaum

🖋
Ezequiel
Ezequiel

🌍
Juan José Rodríguez
Juan José Rodríguez

🌍
Or Bin
Or Bin

🖋
Andreo Vieira
Andreo Vieira

🖋
Michael Solomon
Michael Solomon

🖋
Jimmy Callin
Jimmy Callin

🖋
Siddharth
Siddharth

🖋
Ryan Smith
Ryan Smith

🖋
Tom Boettger
Tom Boettger

🖋
Joaquín Ormaechea
Joaquín Ormaechea

🌍
dfrzuz
dfrzuz

🌍
Victor Homyakov
Victor Homyakov

🖋
Josh
Josh

🖋 🛡️
Alec Francis
Alec Francis

🖋
arjun6610
arjun6610

🖋
Jan Osch
Jan Osch

🖋
Thiago Rotondo Sampaio
Thiago Rotondo Sampaio

🌍
Alexsey
Alexsey

🖋
Luis A. Acurero
Luis A. Acurero

🌍
Lucas Romano
Lucas Romano

🌍
Denise Case
Denise Case

🖋
Nick Ribal
Nick Ribal

🖋 👀
0xflotus
0xflotus

🖋
Jonathan Chen
Jonathan Chen

🖋
Dilan Srilal
Dilan Srilal

🖋
vladthelittleone
vladthelittleone

🌍
Nik Osvalds
Nik Osvalds

🖋
Daniel Kiss
Daniel Kiss

📖
Forresst
Forresst

🖋
Jonathan Svenheden
Jonathan Svenheden

🖋
AustrisC
AustrisC

🖋
kyeongtae kim
kyeongtae kim

🌍
007
007

🖋
Ane Diaz de Tuesta
Ane Diaz de Tuesta

🌍 🖋
YukiOta
YukiOta

🌍
Frazer Smith
Frazer Smith

🖋
Raz Luvaton
Raz Luvaton

🖋
Yuta Azumi
Yuta Azumi

🖋
andrewjbarbour
andrewjbarbour

🖋
mr
mr

🖋
Aleksandar
Aleksandar

🖋
Owl
Owl

🖋
Yedidya Schwartz
Yedidya Schwartz

🖋 💡
ari
ari

🖋
Thomas König
Thomas König

🖋
Kalle Lämsä
Kalle Lämsä

🖋
Wyatt
Wyatt

🖋
KHADIR Tayeb
KHADIR Tayeb

🖋
Shankar Regmi
Shankar Regmi

🖋
Shubham
Shubham

🖋
Lucas Alves
Lucas Alves

🖋
Benjamin
Benjamin

🖋
Yeoh Joer
Yeoh Joer

🖋
Miigon
Miigon

🖋
Rostislav Bogorad
Rostislav Bogorad

🖋
Flouse
Flouse

🖋
Tarantini Pereira
Tarantini Pereira

🖋
Kazuki Matsuo
Kazuki Matsuo

🖋
Adam Smith
Adam Smith

🖋
Dohyeon Ko
Dohyeon Ko

🖋
Vladislav Legkov
Vladislav Legkov

🖋
Kerollos Magdy
Kerollos Magdy

🖋
Erez Lieberman
Erez Lieberman

🖋
Breno Macedo
Breno Macedo

🖋
Fernando Flores
Fernando Flores

🌍
Rafael Brito
Rafael Brito

🌍
Emiliano Peralta
Emiliano Peralta

🌍
Shin, SJ
Shin, SJ

🖋
Benjamin Forster
Benjamin Forster

🖋
Daniele Fedeli
Daniele Fedeli

🖋
djob195
djob195

🖋
antspk
antspk

🖋
정진영
정진영

🖋
kkk-cashwalk
kkk-cashwalk

🖋
apainintheneck
apainintheneck

🖋
Fajar Budhi Iswanda
Fajar Budhi Iswanda

🖋
이주호
이주호

🖋
Singh
Singh

🖋
Alex Dumitru
Alex Dumitru

🖋
Anton Lykhatskyi
Anton Lykhatskyi

🖋
sangwonlee
sangwonlee

🖋
Eugenio Berretta
Eugenio Berretta

🖋
soranakk
soranakk

🖋
고준영
고준영

🖋 💻
Guilherme Portella
Guilherme Portella

🖋
André Esser
André Esser

🖋
Scc
Scc

🌍
Mauro Accornero
Mauro Accornero

🖋
no-yan
no-yan

🖋
+ + + + + + +### Steering Committee Emeriti + +[Bruno Scheufler](https://github.com/BrunoScheufler) + + +💻 full-stack web engineer, Node.js & GraphQL enthusiast + +
+ + + +[Kyle Martin](https://github.com/js-kyle) + + + +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](https://github.com/kevynb) + + +Independent full-stack developer with a taste for Ops and automation. + +
+ + + +[Sagir Khan](https://github.com/sagirk) + + + + +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. diff --git a/README.indonesian.md b/README.indonesian.md index 9cafd1ea1..f4d2d2f71 100644 --- a/README.indonesian.md +++ b/README.indonesian.md @@ -3,22 +3,22 @@ # Praktik Terbaik Node.js

- Praktik Terbaik Node.js + Praktik Terbaik Node.js


- 102 item Pembaruan terakhir: November, 2020 Diperbarui untuk Node 14.0.0 + 102 item Pembaruan terakhir: November, 2020 Diperbarui untuk Node 14.0.0

-[![nodepractices](/assets/images/twitter-s.png)](https://twitter.com/nodepractices/) **Ikuti kami di Twitter!** [**@nodepractices**](https://twitter.com/nodepractices/) +[![nodepractices](./assets/images/twitter-s.png)](https://twitter.com/nodepractices/) **Ikuti kami di Twitter!** [**@nodepractices**](https://twitter.com/nodepractices/)
-Baca dalam bahasa yang berbeda: [![CN](/assets/flags/CN.png)**CN**](/README.chinese.md), [![BR](/assets/flags/BR.png)**BR**](/README.brazilian-portuguese.md), [![RU](/assets/flags/RU.png)**RU**](/README.russian.md), [![PL](/assets/flags/PL.png)**PL**](/README.polish.md) [(![ES](/assets/flags/ES.png)**ES**, ![FR](/assets/flags/FR.png)**FR**, ![HE](/assets/flags/HE.png)**HE**, ![KR](/assets/flags/KR.png)**KR** dan ![TR](/assets/flags/TR.png)**TR** dalam proses!)](#translations) +Baca dalam bahasa yang berbeda: [![CN](./assets/flags/CN.png)**CN**](./README.chinese.md), [![BR](./assets/flags/BR.png)**BR**](./README.brazilian-portuguese.md), [![RU](./assets/flags/RU.png)**RU**](./README.russian.md), [![PL](./assets/flags/PL.png)**PL**](./README.polish.md), [![EU](./assets/flags/EU.png)**EU**](./README.basque.md) [(![ES](./assets/flags/ES.png)**ES**, ![FR](./assets/flags/FR.png)**FR**, ![HE](./assets/flags/HE.png)**HE**, ![KR](./assets/flags/KR.png)**KR** dan ![TR](./assets/flags/TR.png)**TR** dalam proses!)](#translations)
@@ -38,7 +38,7 @@ Baca dalam bahasa yang berbeda: [![CN](/assets/flags/CN.png)**CN**](/README.chin **1. Anda sedang membaca berbagai artikel Node.js terbaik -** repositori ini adalah ringkasan dan kurasi dari konten peringkat teratas dalam praktik terbaik Node.js, serta konten yang ditulis oleh kolaborator -**2. Ini adalah kompilasi terbesar, dan berkembang tiap minggu -** saat ini, lebih dari 80 praktik terbaik, panduan gaya, dan tips arsitektural tersajikan. Issue baru dan pull request dibuat setiap hari agar kontennya tetap diperbarui. Kami senang melihat Anda berkontribusi di sini, maupun itu memperbaiki kesalahan kode, membantu dalam terjemahan, atau menyarankan ide cemerlang yang baru. Lihat [pedoman menulis](/.operations/writing-guidelines.md) kami +**2. Ini adalah kompilasi terbesar, dan berkembang tiap minggu -** saat ini, lebih dari 80 praktik terbaik, panduan gaya, dan tips arsitektural tersajikan. Issue baru dan pull request dibuat setiap hari agar kontennya tetap diperbarui. Kami senang melihat Anda berkontribusi di sini, maupun itu memperbaiki kesalahan kode, membantu dalam terjemahan, atau menyarankan ide cemerlang yang baru. Lihat [pedoman menulis](./.operations/writing-guidelines.md) kami **3. Praktik terbaik mempunyai informasi tambahan -** kebanyakan poin mempunyai tautan **🔗Baca selengkapnya** yang memperluas praktiknya dengan contoh kode, kutipan dari blog terpilih, dan informasi lebih lanjut @@ -49,7 +49,7 @@ Baca dalam bahasa yang berbeda: [![CN](/assets/flags/CN.png)**CN**](/README.chin 1. [Praktik Struktur Proyek (5)](#1-praktik-struktur-proyek) 2. [Praktik Penanganan Kesalahan (11) ](#2-praktik-penanganan-kesalahan) 3. [Praktik Gaya Kode (12) ](#3-praktik-gaya-kode) -4. [Praktik Pengujian dan Kualitas Secara Keseluruhan (13) ](#4-praktik-pengujian-dan-kualitas-secara-keseluruhan ) +4. [Praktik Pengujian dan Kualitas Secara Keseluruhan (13) ](#4-praktik-pengujian-dan-kualitas-secara-keseluruhan) 5. [Praktik Dalam Produksi(19) ](#5-praktik-dalam-produksi) 6. [Praktik Keamanan (25)](#6-praktik-terbaik-keamanan) 7. [Praktik Performa (2) (Pekerjaan Dalam Proses ✍️)](#7-draf-praktik-terbaik-performa) @@ -65,7 +65,7 @@ Baca dalam bahasa yang berbeda: [![CN](/assets/flags/CN.png)**CN**](/README.chin **Jika tidak:** Saat pengembang yang menambahkan fitur baru kesusahan untuk melihat dampak dari perubahan mereka dan takut akan merusak komponen lain yang bergantung - _deployment_ menjadi lebih lambat dan berisiko. Kode juga dianggap lebih sulit untuk dikembangkan ketika semua unit bisnis tidak dipisahkan -🔗 [**Baca selengkapnya: structure by components**](/sections/projectstructre/breakintcomponents.md) +🔗 [**Baca selengkapnya: structure by components**](./sections/projectstructre/breakintcomponents.md)

@@ -75,7 +75,7 @@ Baca dalam bahasa yang berbeda: [![CN](/assets/flags/CN.png)**CN**](/README.chin **Jika tidak:** Aplikasi yang menggabungkan objek web dengan lapisan lain tidak dapat diakses oleh kode pengujian, pekerjaan CRON, triggers dari message queues, dll. -🔗 [**Baca selengkapnya: layer your app**](/sections/projectstructre/createlayers.md) +🔗 [**Baca selengkapnya: layer your app**](./sections/projectstructre/createlayers.md)

@@ -85,7 +85,7 @@ Baca dalam bahasa yang berbeda: [![CN](/assets/flags/CN.png)**CN**](/README.chin **Jika tidak:** Anda harus membuat cara _deployment_ dan _dependency_ Anda sendiri -🔗 [**Baca selengkapnya: Structure by feature**](/sections/projectstructre/wraputilities.md) +🔗 [**Baca selengkapnya: Structure by feature**](./sections/projectstructre/wraputilities.md)

@@ -95,7 +95,7 @@ Baca dalam bahasa yang berbeda: [![CN](/assets/flags/CN.png)**CN**](/README.chin **Jika tidak:** API Anda hanya dapat diakses untuk pengujian melalui panggilan HTTP (lebih lambat and lebih susah untuk membuat laporan cakupan pengujian). Mengurus ratusan baris kode dalam satu file mungkin bukanlah hal yang menyenangkan -🔗 [**Baca selengkapnya: separate Express 'app' and 'server'**](/sections/projectstructre/separateexpress.md) +🔗 [**Baca selengkapnya: separate Express 'app' and 'server'**](./sections/projectstructre/separateexpress.md)

@@ -105,7 +105,7 @@ Baca dalam bahasa yang berbeda: [![CN](/assets/flags/CN.png)**CN**](/README.chin **Jika tidak:** Gagal untuk memenuhi salah satu persyaratan konfigurasi hanya akan menghambat tim pengembang atau DevOps. Mungkin keduanya -🔗 [**Baca selengkapnya: configuration best practices**](/sections/projectstructre/configguide.md) +🔗 [**Baca selengkapnya: configuration best practices**](./sections/projectstructre/configguide.md)


@@ -119,7 +119,7 @@ Baca dalam bahasa yang berbeda: [![CN](/assets/flags/CN.png)**CN**](/README.chin **Jika tidak:** Gaya panggilan balik Node.js, function(err, response), adalah cara yang menjanjikan untuk kode yang tidak dapat dipelihara karena campuran dari penanganan kesalahan dengan kode kasual, bersarang yang berlebihan, dan pola pengkodean yang canggung -🔗 [**Baca selengkapnya: avoiding callbacks**](/sections/errorhandling/asyncerrorhandling.md) +🔗 [**Baca selengkapnya: avoiding callbacks**](./sections/errorhandling/asyncerrorhandling.md)

@@ -129,7 +129,7 @@ Baca dalam bahasa yang berbeda: [![CN](/assets/flags/CN.png)**CN**](/README.chin **Jika tidak:** Saat menjalankan beberapa komponen, karena tidak yakin jenis kesalahan yang akan di lempar – ini membuat penanganan kesalahan yang benar jauh lebih sulit. Lebih buruk lagi, menggunakan tipe khusus untuk mendeskripsikan kesalahan dapat menyebabkan hilangnya informasi kesalahan kritis seperti _stack trace_! -🔗 [**Baca selengkapnya: using the built-in error object**](/sections/errorhandling/useonlythebuiltinerror.md) +🔗 [**Baca selengkapnya: using the built-in error object**](./sections/errorhandling/useonlythebuiltinerror.md)

@@ -139,7 +139,7 @@ Baca dalam bahasa yang berbeda: [![CN](/assets/flags/CN.png)**CN**](/README.chin **Jika tidak:** Anda selalu dapat memulai ulang aplikasi Anda ketika kesalahan muncul, namun kenapa mengecewakan ~5000 pengguna hanya karena kesalahan operasional yang kecil dan dapat diprediksi? hal sebaliknya juga tidak ideal – membiarkan aplikasi tetap berjalan ketika terdapat kesalahan yang tidak diketahui (kesalahan oleh pengembang) dapat menyebabkan perilaku yang tidak terduga. Membedakan kedua kesalahan tersebut memungkinkan untuk melakukan tindakan yang benar dan menerapkan cara penyelesaian masalah yang sesuai dengan konteks yang diberikan -🔗 [**Baca selengkapnya: operational vs programmer error**](/sections/errorhandling/operationalvsprogrammererror.md) +🔗 [**Baca selengkapnya: operational vs programmer error**](./sections/errorhandling/operationalvsprogrammererror.md)

@@ -149,7 +149,7 @@ Baca dalam bahasa yang berbeda: [![CN](/assets/flags/CN.png)**CN**](/README.chin **Jika tidak:** Tidak menangani kesalahan dalam satu tempat akan menyebabkan duplikasi kode dan mungkin kesalahan yang tidak ditangani dengan tepat -🔗 [**Baca selengkapnya: handling errors in a centralized place**](/sections/errorhandling/centralizedhandling.md) +🔗 [**Baca selengkapnya: handling errors in a centralized place**](./sections/errorhandling/centralizedhandling.md)

@@ -159,7 +159,7 @@ Baca dalam bahasa yang berbeda: [![CN](/assets/flags/CN.png)**CN**](/README.chin **Jika tidak:** Klien API mungkin memutuskan untuk memberhentikan aplikasi dan memulai ulang hanya karena menerima kesalahan yang tidak dapat dipahami. Catatan: pemanggil API mungkin adalah Anda (sangat umum dalam lingkungan _microservice_) -🔗 [**Baca selengkapnya: documenting API errors in Swagger or GraphQL**](/sections/errorhandling/documentingusingswagger.md) +🔗 [**Baca selengkapnya: documenting API errors in Swagger or GraphQL**](./sections/errorhandling/documentingusingswagger.md)

@@ -169,7 +169,7 @@ Baca dalam bahasa yang berbeda: [![CN](/assets/flags/CN.png)**CN**](/README.chin **Jika tidak:** Ketika pengecualian yang tidak dikenal terjadi, beberapa objek mungkin dalam keadaan rusak (contohnya event emitter yang digunakan secara global dan tidak dapat mengaktifkan event lagi karena kesalahan internal) dan semua panggilan yang akan datang mungkin akan gagal atau tidak berperilaku dengan normal -🔗 [**Baca selengkapnya: shutting the process**](/sections/errorhandling/shuttingtheprocess.md) +🔗 [**Baca selengkapnya: shutting the process**](./sections/errorhandling/shuttingtheprocess.md)

@@ -179,7 +179,7 @@ Baca dalam bahasa yang berbeda: [![CN](/assets/flags/CN.png)**CN**](/README.chin **Jika tidak:** Melihat beberapa console.log atau secara manual melalui file teks yang berantakan tanpa alat kueri atau penampil catatan yang baik dapat membuat Anda sibuk di tempat kerja hingga larut -🔗 [**Baca selengkapnya: using a mature logger**](/sections/errorhandling/usematurelogger.md) +🔗 [**Baca selengkapnya: using a mature logger**](./sections/errorhandling/usematurelogger.md)

@@ -189,7 +189,7 @@ Baca dalam bahasa yang berbeda: [![CN](/assets/flags/CN.png)**CN**](/README.chin **Jika tidak:** Tanpa testing, maupun secara otomatis ataupun manual, Anda tidak dapat mengandalkan kode Anda untuk mengembalikan jenis kesalahan yang tepat. Tanpa jenis kesalahan yang berarti – tidak ada penanganan kesalahan -🔗 [**Baca selengkapnya: testing error flows**](/sections/errorhandling/testingerrorflows.md) +🔗 [**Baca selengkapnya: testing error flows**](./sections/errorhandling/testingerrorflows.md)

@@ -199,7 +199,7 @@ Baca dalam bahasa yang berbeda: [![CN](/assets/flags/CN.png)**CN**](/README.chin **Jika tidak:** Anda mungkin menghabiskan banyak usaha untuk mengukur kinerja dan waktu henti API, mungkin Anda tidak akan menyadari bagian kode mana yang paling lambat dalam skenario dunia nyata dan bagaimana hal ini dapat memengaruhi pengalaman pengguna -🔗 [**Baca selengkapnya: using APM products**](/sections/errorhandling/apmproducts.md) +🔗 [**Baca selengkapnya: using APM products**](./sections/errorhandling/apmproducts.md)

@@ -209,7 +209,7 @@ Baca dalam bahasa yang berbeda: [![CN](/assets/flags/CN.png)**CN**](/README.chin **Jika tidak:** Kesalahan dari kode Anda akan ditelan dan hilang tanpa jejak. Tidak ada yang perlu dikhawatirkan -🔗 [**Baca selengkapnya: catching unhandled promise rejection**](/sections/errorhandling/catchunhandledpromiserejection.md) +🔗 [**Baca selengkapnya: catching unhandled promise rejection**](./sections/errorhandling/catchunhandledpromiserejection.md)

@@ -219,7 +219,7 @@ Baca dalam bahasa yang berbeda: [![CN](/assets/flags/CN.png)**CN**](/README.chin **Jika tidak:** Anggap seperti ini – jika fungsi Anda mengharapkan argumen numerik “Diskon” yang lupa diletak oleh pemanggil, kemudian, kode Anda memeriksa jika Diskon!=0 (jumlah diskon yang diizinkan lebih besar dari nol), maka itu akan memungkinkan pengguna untuk menikmati diskon. OMG, bug yang sangat buruk. Bisakah Anda melihatnya? -🔗 [**Baca selengkapnya: failing fast**](/sections/errorhandling/failfast.md) +🔗 [**Baca selengkapnya: failing fast**](./sections/errorhandling/failfast.md)

@@ -231,7 +231,7 @@ Baca dalam bahasa yang berbeda: [![CN](/assets/flags/CN.png)**CN**](/README.chin Kerangka yang hilang seperti itu mungkin akan mempersulit pemahaman tentang aliran yang mengarah ke kesalahan, terutama jika penyebab perilaku yang tidak normal ada di dalam fungsi yang hilang itu -🔗 [**Baca selengkapnya: returning promises**](/sections/errorhandling/returningpromises.md) +🔗 [**Baca selengkapnya: returning promises**](./sections/errorhandling/returningpromises.md)


@@ -245,7 +245,7 @@ terutama jika penyebab perilaku yang tidak normal ada di dalam fungsi yang hilan **Jika tidak:** Pengembang akan fokus pada masalah spasi dan lebar garis dan waktu mungkin akan terbuang hanya untuk memikirkan gaya kode pada proyek -🔗 [**Baca selengkapnya: Using ESLint and Prettier**](/sections/codestylepractices/eslint_prettier.md) +🔗 [**Baca selengkapnya: Using ESLint and Prettier**](./sections/codestylepractices/eslint_prettier.md)

@@ -270,8 +270,7 @@ function someFunction() { } // Hindari -function someFunction() -{ +function someFunction() { // blok kode } ``` @@ -328,7 +327,7 @@ const count = 2 // mencoba menjalankan 2(), tapi 2 bukanlah sebuah fungsi ## ![✔] 3.5 Namakan fungsi Anda -**TL;DR:** Namakan semua fungsi, termasuk closure dan panggilan balik. Hindari fungsi anonim. Ini sangat berguna saat mengukur sebuah aplikasi node. Menamakan semua fungsi memungkinkan Anda untuk memahami dengan mudah apa yang Anda lihat saat memeriksa snapshot memori +**TL;DR:** Namakan semua fungsi, termasuk closure dan panggilan balik. Hindari fungsi anonim. Ini sangat berguna saat mengukur sebuah aplikasi node. Menamakan semua fungsi memungkinkan Anda untuk memahami dengan mudah apa yang Anda lihat saat memeriksa snapshot memori **Jika tidak:** Men-debug masalah produksi menggunakan core dump (snapshot memori) dapat menjadi tantangan karena Anda melihat konsumsi memori yang signifikan dari fungsi anonim @@ -398,7 +397,7 @@ module.exports.SMSNumberResolver = require("./SMSNumberResolver/SMSNumberResolve ## ![✔] 3.10 Gunakan operator `===` -**TL;DR:** Utamakan operator persamaan ketat `===` daripada operator persamaan abstrak `==` yang lebih lemah. `==` akan membandingkan dua variabel setelah mengubahnya ke tipe umum. Tidak ada konversi tipe di `===`, dan kedua variabel harus sejenis agar sama +**TL;DR:** Utamakan operator persamaan ketat `===` daripada operator persamaan abstrak `==` yang lebih lemah. `==` akan membandingkan dua variabel setelah mengubahnya ke tipe umum. Tidak ada konversi tipe di `===`, dan kedua variabel harus sejenis agar sama **Jika tidak:** Variabel yang tidak sama dapat mengembalikan _true_ ketika dibandingkan dengan operator `==` @@ -445,7 +444,7 @@ Semua pernyataan di atas akan mengembalikan nilai _false_ jika menggunakan `===`

⬆ Kembali ke atas

-# `4. Praktik Pengujian dan Kualitas Secara Keseluruhan ` +# `4. Praktik Pengujian dan Kualitas Secara Keseluruhan` ## ![✔] 4.1 Paling tidak, buat pengujian API (komponen) @@ -461,7 +460,7 @@ Semua pernyataan di atas akan mengembalikan nilai _false_ jika menggunakan `===` **Jika tidak:** Deployment baru saja gagal, sebuah pengujian bernama “Tambah produk” gagal. Apakah ini memberi tahu Anda dengan tepat apa yang tidak berfungsi? -🔗 [**Baca selengkapnya: Include 3 parts in each test name**](/sections/testingandquality/3-parts-in-name.md) +🔗 [**Baca selengkapnya: Include 3 parts in each test name**](./sections/testingandquality/3-parts-in-name.md)

@@ -471,7 +470,7 @@ Semua pernyataan di atas akan mengembalikan nilai _false_ jika menggunakan `===` **Jika tidak:** Tidak hanya Anda menghabiskan waktu yang lama untuk memahami kode utama, tetapi sekarang hal paling mudah dari hari Anda (melakukan pengujian) dapat meregangkan otak Anda -🔗 [**Baca selengkapnya: Structure tests by the AAA pattern**](/sections/testingandquality/aaa.md) +🔗 [**Baca selengkapnya: Structure tests by the AAA pattern**](./sections/testingandquality/aaa.md)

@@ -489,7 +488,7 @@ Semua pernyataan di atas akan mengembalikan nilai _false_ jika menggunakan `===` **Jika tidak:** Anggap sebuah skenario di mana _deployment_ gagal karena pengujian yang gagal, tim sekarang akan menghabiskan waktu yang berharga untuk melakukan investigasi yang berakhir dengan kesimpulan yang menyedihkan: sistem berfungsi dengan baik, namun pengujian saling mengganggu dan merusak _build_-nya -🔗 [**Baca selengkapnya: Avoid global test fixtures**](/sections/testingandquality/avoid-global-test-fixture.md) +🔗 [**Baca selengkapnya: Avoid global test fixtures**](./sections/testingandquality/avoid-global-test-fixture.md)

@@ -539,7 +538,7 @@ Semua pernyataan di atas akan mengembalikan nilai _false_ jika menggunakan `===` **Jika tidak:** Dengan kualitas kode yang buruk, _bug_ dan performa selalu akan selalu menjadi masalah yang tidak dapat diperbaiki oleh pustaka baru atau fitur-fitur canggih -🔗 [**Baca selengkapnya: Refactoring!**](/sections/testingandquality/refactoring.md) +🔗 [**Baca selengkapnya: Refactoring!**](./sections/testingandquality/refactoring.md)

@@ -549,7 +548,7 @@ Semua pernyataan di atas akan mengembalikan nilai _false_ jika menggunakan `===` **Jika tidak:** Memilih vendor khusus mungkin akan membatasi Anda ketika Anda membutuhkan penyesuaian tingkat lanjut. Di sisi lain, menggunakan Jenkins dapat menghabiskan waktu berharga dalam penyiapan infrastruktur -🔗 [**Baca selengkapnya: Choosing CI platform**](/sections/testingandquality/citools.md) +🔗 [**Baca selengkapnya: Choosing CI platform**](./sections/testingandquality/citools.md) ## ![✔] 4.13 Uji middleware Anda secara terpisah @@ -557,7 +556,7 @@ Semua pernyataan di atas akan mengembalikan nilai _false_ jika menggunakan `===` **Otherwise:** Sebuah _bug_ di middleware Express === sebuah bug di semua atau banyak _request_ -🔗 [**Baca selengkapnya: Test middlewares in isolation**](/sections/testingandquality/test-middlewares.md) +🔗 [**Baca selengkapnya: Test middlewares in isolation**](./sections/testingandquality/test-middlewares.md)


@@ -571,7 +570,7 @@ Semua pernyataan di atas akan mengembalikan nilai _false_ jika menggunakan `===` **Jika tidak:** Kegagalan === pelanggan kecewa. Sederhana -🔗 [**Baca selengkapnya: Monitoring!**](/sections/production/monitoring.md) +🔗 [**Baca selengkapnya: Monitoring!**](./sections/production/monitoring.md)

@@ -581,7 +580,7 @@ Semua pernyataan di atas akan mengembalikan nilai _false_ jika menggunakan `===` **Jika tidak:** Anda berakhir dengan kotak hitam yang sulit dimengerti, kemudian Anda mulai menulis ulang semua statement log untuk menambahkan informasi tambahan -🔗 [**Baca selengkapnya: Increase transparency using smart logging**](/sections/production/smartlogging.md) +🔗 [**Baca selengkapnya: Increase transparency using smart logging**](./sections/production/smartlogging.md)

@@ -591,7 +590,7 @@ Semua pernyataan di atas akan mengembalikan nilai _false_ jika menggunakan `===` **Jika tidak:** Thread utama Anda akan tetap sibuk melakukan tugas infrastruktur alih-alih menangani inti aplikasi Anda dan performa akan menurun karenanya -🔗 [**Baca selengkapnya: Delegate anything possible (e.g. gzip, SSL) to a reverse proxy**](/sections/production/delegatetoproxy.md) +🔗 [**Baca selengkapnya: Delegate anything possible (e.g. gzip, SSL) to a reverse proxy**](./sections/production/delegatetoproxy.md)

@@ -601,7 +600,7 @@ Semua pernyataan di atas akan mengembalikan nilai _false_ jika menggunakan `===` **Jika tidak:** QA akan menguji kode secara menyeluruh dan menyetujui versi yang kemudian akan berperilaku berbeda dalam produksi. Lebih buruk lagi, server yang berbeda dalam kelompok produksi mungkin menjalankan kode yang berbeda -🔗 [**Baca selengkapnya: Lock dependencies**](/sections/production/lockdependencies.md) +🔗 [**Baca selengkapnya: Lock dependencies**](./sections/production/lockdependencies.md)

@@ -611,7 +610,7 @@ Semua pernyataan di atas akan mengembalikan nilai _false_ jika menggunakan `===` **Jika tidak:** Menjalankan banyak instansi tanpa strategi yang jelas dan terlalu banyak alat (manajemen cluster, docker, PM2) dapat menyebabkan kekacauan DevOps -🔗 [**Baca selengkapnya: Guard process uptime using the right tool**](/sections/production/guardprocess.md) +🔗 [**Baca selengkapnya: Guard process uptime using the right tool**](./sections/production/guardprocess.md)

@@ -621,7 +620,7 @@ Semua pernyataan di atas akan mengembalikan nilai _false_ jika menggunakan `===` **Jika tidak:** Aplikasi Anda kemungkinan hanya menggunakan 25% dari sumber daya yang tersedia(!) atau bahkan kurang. Ingat bahwa server tipikal memiliki 4 core CPU atau lebih, _deployment_ Node.js yang naif hanya menggunakan 1 (bahkan jika menggunakan layanan PaaS seperti AWS beanstalk!) -🔗 [**Baca selengkapnya: Utilize all CPU cores**](/sections/production/utilizecpu.md) +🔗 [**Baca selengkapnya: Utilize all CPU cores**](./sections/production/utilizecpu.md)

@@ -631,7 +630,7 @@ Semua pernyataan di atas akan mengembalikan nilai _false_ jika menggunakan `===` **Jika tidak:** Anda akan melakukan banyak “deploy diagnostik” – mendeploy kode ke produksi hanya untuk mengekstrak beberapa informasi untuk keperluan diagnostik -🔗 [**Baca selengkapnya: Create a ‘maintenance endpoint’**](/sections/production/createmaintenanceendpoint.md) +🔗 [**Baca selengkapnya: Create a ‘maintenance endpoint’**](./sections/production/createmaintenanceendpoint.md)

@@ -641,7 +640,7 @@ Semua pernyataan di atas akan mengembalikan nilai _false_ jika menggunakan `===` **Jika tidak:** Anda mungkin menghabiskan banyak tenaga untuk mengukur kinerja dan downtime API, mungkin Anda tidak akan pernah tau bagian kode mana yang paling lambat dalam skenario dunia nyata dan bagaimana hal ini dapat memengaruhi pengalaman pengguna -🔗 [**Baca selengkapnya: Discover errors and downtime using APM products**](/sections/production/apmproducts.md) +🔗 [**Baca selengkapnya: Discover errors and downtime using APM products**](./sections/production/apmproducts.md)

@@ -651,7 +650,7 @@ Semua pernyataan di atas akan mengembalikan nilai _false_ jika menggunakan `===` **Jika tidak:** Seorang juara dunia IT/DevOps tidak akan memperbaiki sistem yang ditulis dengan buruk -🔗 [**Baca selengkapnya: Make your code production-ready**](/sections/production/productioncode.md) +🔗 [**Baca selengkapnya: Make your code production-ready**](./sections/production/productioncode.md)

@@ -661,7 +660,7 @@ Semua pernyataan di atas akan mengembalikan nilai _false_ jika menggunakan `===` **Jika tidak:** Memori proses Anda mungkin bocor ratusan megabyte sehari seperti yang terjadi pada [Walmart](https://www.joyent.com/blog/walmart-node-js-memory-leak) -🔗 [**Baca selengkapnya: Measure and guard the memory usage**](/sections/production/measurememory.md) +🔗 [**Baca selengkapnya: Measure and guard the memory usage**](./sections/production/measurememory.md)

@@ -671,7 +670,7 @@ Semua pernyataan di atas akan mengembalikan nilai _false_ jika menggunakan `===` **Jika tidak:** Thread tunggal Node Anda akan sibuk mengirimkan ratusan file html/gambar/angular/react alih-alih mengalokasikan semua sumber dayanya untuk tugas yang seharusnya – menyajikan konten dinamis -🔗 [**Baca selengkapnya: Get your frontend assets out of Node**](/sections/production/frontendout.md) +🔗 [**Baca selengkapnya: Get your frontend assets out of Node**](./sections/production/frontendout.md)

@@ -681,7 +680,7 @@ Semua pernyataan di atas akan mengembalikan nilai _false_ jika menggunakan `===` **Jika tidak:** Kegagalan di server tertentu akan mengakibatkan downtime aplikasi, bukannya hanya mematikan mesin yang rusak. Selain itu, elastisitas penskalaan akan menjadi lebih sulit karena ketergantungan pada server tertentu -🔗 [**Baca selengkapnya: Be stateless, kill your Servers almost every day**](/sections/production/bestateless.md) +🔗 [**Baca selengkapnya: Be stateless, kill your Servers almost every day**](./sections/production/bestateless.md)

@@ -691,7 +690,7 @@ Semua pernyataan di atas akan mengembalikan nilai _false_ jika menggunakan `===` **Jika tidak:** Menjaga kode Anda bersih dari kerentanan tanpa alat khusus mengharuskan Anda untuk mengikuti publikasi online tentang ancaman baru. Cukup membosankan -🔗 [**Baca selengkapnya: Use tools that automatically detect vulnerabilities**](/sections/production/detectvulnerabilities.md) +🔗 [**Baca selengkapnya: Use tools that automatically detect vulnerabilities**](./sections/production/detectvulnerabilities.md)

@@ -701,7 +700,7 @@ Semua pernyataan di atas akan mengembalikan nilai _false_ jika menggunakan `===` **Jika tidak:** Melihat catatan kesalahan produksi tanpa konteks – apa yang terjadi sebelumnya – membuat Anda lebih sulit untuk memahami penyebab kesalahannya -🔗 [**Baca selengkapnya: Assign ‘TransactionId’ to each log statement**](/sections/production/assigntransactionid.md) +🔗 [**Baca selengkapnya: Assign ‘TransactionId’ to each log statement**](./sections/production/assigntransactionid.md)

@@ -711,7 +710,7 @@ Semua pernyataan di atas akan mengembalikan nilai _false_ jika menggunakan `===` **Jika tidak:** Mengabaikan properti sederhana ini dapat menurunkan performa. Contohnya, pada saat menggunakan Express untuk rendering sisi server menghilangkan `NODE_ENV` membuat proses render lebih lambat hingga 3 kali lipat! -🔗 [**Baca selengkapnya: Set NODE_ENV=production**](/sections/production/setnodeenv.md) +🔗 [**Baca selengkapnya: Set NODE_ENV=production**](./sections/production/setnodeenv.md)

@@ -729,7 +728,7 @@ Semua pernyataan di atas akan mengembalikan nilai _false_ jika menggunakan `===` **Otherwise:** Bug atau kerentanan yang baru ditemukan dapat digunakan untuk mengeksploitasi aplikasi yang sedang berjalan dalam produksi, dan aplikasi Anda mungkin menjadi tidak didukung oleh berbagai modul dan lebih sulit untuk di dipelihara -🔗 [**Baca selengkapnya: Use an LTS release of Node.js**](/sections/production/LTSrelease.md) +🔗 [**Baca selengkapnya: Use an LTS release of Node.js**](./sections/production/LTSrelease.md)

@@ -739,7 +738,7 @@ Semua pernyataan di atas akan mengembalikan nilai _false_ jika menggunakan `===` **Jika tidak:** Aplikasi menangani rute catatan === sulit untuk dikembangkan, kehilangan catatan, dan _separation of concerns_ yang buruk -🔗 [**Baca selengkapnya: Log Routing**](/sections/production/logrouting.md) +🔗 [**Baca selengkapnya: Log Routing**](./sections/production/logrouting.md)

@@ -749,7 +748,7 @@ Semua pernyataan di atas akan mengembalikan nilai _false_ jika menggunakan `===` **Jika tidak:** QA akan menguji kode secara menyeluruh dan menyetujui versi yang kemudian akan berperilaku berbeda dalam produksi. Lebih buruk lagi, server yang berbeda dalam kelompok produksi mungkin menjalankan kode yang berbeda. -🔗 [**Baca selengkapnya: Use npm ci**](/sections/production/installpackageswithnpmci.md) +🔗 [**Baca selengkapnya: Use npm ci**](./sections/production/installpackageswithnpmci.md)


@@ -769,7 +768,7 @@ Semua pernyataan di atas akan mengembalikan nilai _false_ jika menggunakan `===` **Jika tidak:** Kelemahan keamanan yang jelas selama masa pengembangan malah menjadi masalah besar dalam produksi. Selain itu, proyek mungkin tidak mengikuti praktik kode keamanan yang konsisten, yang mengarah ke kerentanan baru, atau rahasia sensitif yang ter-_commit_ ke dalam repositori remote -🔗 [**Baca selengkapnya: Lint rules**](/sections/security/lintrules.md) +🔗 [**Baca selengkapnya: Lint rules**](./sections/security/lintrules.md)

@@ -781,7 +780,7 @@ Semua pernyataan di atas akan mengembalikan nilai _false_ jika menggunakan `===` **Jika tidak:** Aplikasi dapat terkena serangan _denial of service_ sementara pengguna asli menggunakan layanan yang terdegradasi atau tidak tersedia. -🔗 [**Baca selengkapnya: Implement rate limiting**](/sections/security/limitrequests.md) +🔗 [**Baca selengkapnya: Implement rate limiting**](./sections/security/limitrequests.md)

@@ -789,15 +788,15 @@ Semua pernyataan di atas akan mengembalikan nilai _false_ jika menggunakan `===` -**TL;DR:** Jangan pernah menyimpan rahasia dalam bentuk teks biasa dalam file konfigurasi atau kode sumber. Sebagai gantinya, gunakan sistem manajemen rahasia seperti produk _Vault_, _Kubernetes/Docker Secrets_, atau gunakan variabel lingkungan. Sebagai cara terakhir, rahasia yang disimpan di kontrol kode harus terenkripsi dan teratur (kunci bergulir, kedaluwarsa, audit, dll.). Manfaatkan hook pra-_commit_/_push_ untuk mencegah agar rahasia tidak ter-_commit_ secara tidak sengaja +**TL;DR:** Jangan pernah menyimpan rahasia dalam bentuk teks biasa dalam file konfigurasi atau kode sumber. Sebagai gantinya, gunakan sistem manajemen rahasia seperti produk _Vault_, _Kubernetes/Docker Secrets_, atau gunakan variabel lingkungan. Sebagai cara terakhir, rahasia yang disimpan di kontrol kode harus terenkripsi dan teratur (kunci bergulir, kedaluwarsa, audit, dll.). Manfaatkan hook pra-_commit_/_push_ untuk mencegah agar rahasia tidak ter-_commit_ secara tidak sengaja **Jika tidak:** Kontrol sumber, bahkan untuk repositori pribadi, dapat di buat publik secara tidak sengaja, di mana semua rahasia dapat terungkap. Akses kontrol sumber dari pihak eksternal dapat memberikan akses ke sistem terkait (database, api, layanan, dll.) secara tidak sengaja. -🔗 [**Baca selengkapnya: Secret management**](/sections/security/secretmanagement.md) +🔗 [**Baca selengkapnya: Secret management**](./sections/security/secretmanagement.md)

-## ![✔] 6.4. Cegah injeksi kueri dengan menggunakan pustaka ORM/ODM +## ![✔] 6.4. Cegah injeksi kueri dengan menggunakan pustaka ORM/ODM @@ -805,7 +804,7 @@ Semua pernyataan di atas akan mengembalikan nilai _false_ jika menggunakan `===` **Jika tidak:** Masukan pengguna yang tidak divalidasi atau tidak disanitasi dapat menyebabkan injeksi operator saat menggunakan MongoDB untuk NoSQL, dan dengan tidak menggunakan sistem sanitasi atau ORM dapat memungkinkan serangan injeksi SQL, membuat suatu kerentanan yang besar. -🔗 [**Baca selengkapnya: Query injection prevention using ORM/ODM libraries**](/sections/security/ormodmusage.md) +🔗 [**Baca selengkapnya: Query injection prevention using ORM/ODM libraries**](./sections/security/ormodmusage.md)

@@ -813,7 +812,7 @@ Semua pernyataan di atas akan mengembalikan nilai _false_ jika menggunakan `===` **TL;DR:** Ini adalah kumpulan saran keamanan yang tidak berhubungan langsung dengan Node.js - implementasi pada Node tidak jauh berbeda dengan implementasi pada bahasa lain. Klik 'Baca selengkapnya' untuk membaca sekilas. -🔗 [**Baca selengkapnya: Common security best practices**](/sections/security/commonsecuritybestpractices.md) +🔗 [**Baca selengkapnya: Common security best practices**](./sections/security/commonsecuritybestpractices.md)

@@ -825,7 +824,7 @@ Semua pernyataan di atas akan mengembalikan nilai _false_ jika menggunakan `===` **Jika tidak:** Penyerang dapat melakukan serangan langsung pada pengguna aplikasi, yang menyebabkan kerentanan keamanan yang sangat besar -🔗 [**Baca selengkapnya: Using secure headers in your application**](/sections/security/secureheaders.md) +🔗 [**Baca selengkapnya: Using secure headers in your application**](./sections/security/secureheaders.md)

@@ -837,7 +836,7 @@ Semua pernyataan di atas akan mengembalikan nilai _false_ jika menggunakan `===` **Jika tidak:** Penyerang dapat mendeteksi framework web Anda dan menyerang semua kerentanan yang diketahui. -🔗 [**Baca selengkapnya: Dependency security**](/sections/security/dependencysecurity.md) +🔗 [**Baca selengkapnya: Dependency security**](./sections/security/dependencysecurity.md)

@@ -849,7 +848,7 @@ Semua pernyataan di atas akan mengembalikan nilai _false_ jika menggunakan `===` **Jika tidak:** Kata sandi dan rahasia yang disimpan tanpa fungsi yang aman akan rentan terhadap _brute force_ dan penyerangan kamus yang pada akhirnya akan mengarah pada data rahasia yang terekspos. -🔗 [**Baca selengkapnya: User Passwords**](/sections/security/userpasswords.md) +🔗 [**Baca selengkapnya: User Passwords**](./sections/security/userpasswords.md)

@@ -861,7 +860,7 @@ Semua pernyataan di atas akan mengembalikan nilai _false_ jika menggunakan `===` **Jika tidak:** Penyerang mungkin menyimpan kode JavaScript yang berbahaya di DB Anda yang kemudian akan dikirim apa adanya ke pengguna -🔗 [**Baca selengkapnya: Escape output**](/sections/security/escape-output.md) +🔗 [**Baca selengkapnya: Escape output**](./sections/security/escape-output.md)

@@ -873,7 +872,7 @@ Semua pernyataan di atas akan mengembalikan nilai _false_ jika menggunakan `===` **Jika tidak:** Kemurahan hati dan cara permisif Anda dapat meningkatkan kemungkinan penyerangan dan mendorong penyerang untuk mencoba banyak masukan sampai mereka menemukan beberapa kombinasi untuk merusak aplikasi -🔗 [**Baca selengkapnya: Validate incoming JSON schemas**](/sections/security/validation.md) +🔗 [**Baca selengkapnya: Validate incoming JSON schemas**](./sections/security/validation.md)

@@ -885,7 +884,7 @@ Semua pernyataan di atas akan mengembalikan nilai _false_ jika menggunakan `===` **Jika tidak:** Token yang kedaluwarsa atau salah ditempatkan dapat digunakan secara jahat oleh pihak ketiga untuk mengakses aplikasi dan menyamar sebagai pemilik token. -🔗 [**Baca selengkapnya: Blacklist JSON Web Tokens**](/sections/security/expirejwt.md) +🔗 [**Baca selengkapnya: Blacklist JSON Web Tokens**](./sections/security/expirejwt.md)

@@ -900,7 +899,7 @@ Semua pernyataan di atas akan mengembalikan nilai _false_ jika menggunakan `===` **Jika tidak:** Penyerang dapat melakukan percobaan kata sandi otomatis tanpa batas untuk mendapatkan akses ke akun yang memiliki hak istimewa pada suatu aplikasi -🔗 [**Baca selengkapnya: Login rate limiting**](/sections/security/login-rate-limit.md) +🔗 [**Baca selengkapnya: Login rate limiting**](./sections/security/login-rate-limit.md)

@@ -912,7 +911,7 @@ Semua pernyataan di atas akan mengembalikan nilai _false_ jika menggunakan `===` **Jika tidak:** Penyerang yang berhasil menjalankan skrip di server mendapatkan kekuatan tak terbatas atas mesin lokal (misalnya mengganti iptable dan merutekan ulang traffic ke servernya) -🔗 [**Baca selengkapnya: Run Node.js as non-root user**](/sections/security/non-root-user.md) +🔗 [**Baca selengkapnya: Run Node.js as non-root user**](./sections/security/non-root-user.md)

@@ -924,7 +923,7 @@ Semua pernyataan di atas akan mengembalikan nilai _false_ jika menggunakan `===` **Jika tidak:** Aplikasi Anda harus menangani request yang besar, tidak dapat memproses pekerjaan penting lainnya yang harus diselesaikan, yang mengarah ke implikasi performa dan kerentanan terhadap serangan DOS -🔗 [**Baca selengkapnya: Limit payload size**](/sections/security/requestpayloadsizelimit.md) +🔗 [**Baca selengkapnya: Limit payload size**](./sections/security/requestpayloadsizelimit.md)

@@ -936,7 +935,7 @@ Semua pernyataan di atas akan mengembalikan nilai _false_ jika menggunakan `===` **Jika tidak:** Kode JavaScript yang berbahaya menemukan jalan ke dalam teks yang diteruskan ke `eval` atau fungsi evaluasi _real-time_ bahasa Javascript lainnya, dan akan mendapatkan akses penuh ke izin JavaScript di halaman tersebut. Kerentanan ini sering kali diwujudkan sebagai serangan XSS. -🔗 [**Baca selengkapnya: Avoid JavaScript eval statements**](/sections/security/avoideval.md) +🔗 [**Baca selengkapnya: Avoid JavaScript eval statements**](./sections/security/avoideval.md)

@@ -948,7 +947,7 @@ Semua pernyataan di atas akan mengembalikan nilai _false_ jika menggunakan `===` **Jika tidak:** Regex yang ditulis dengan buruk dapat rentan terhadap serangan DoS Regular Expression yang akan memblokir event loop sepenuhnya. MIsalnya, paket `moment` yang populer ditemukan rentan terhadap penggunaan Regex pada November 2017 -🔗 [**Baca selengkapnya: Prevent malicious RegEx**](/sections/security/regex.md) +🔗 [**Baca selengkapnya: Prevent malicious RegEx**](./sections/security/regex.md)

@@ -960,7 +959,7 @@ Semua pernyataan di atas akan mengembalikan nilai _false_ jika menggunakan `===` **Jika tidak:** Masukan pengguna yang berbahaya dapat menemukan jalannya ke parameter yang digunakan untuk memuat file, misalnya, file yang sebelumnya diunggah ke sistem file, atau pengaksesan file sistem yang sudah ada. -🔗 [**Baca selengkapnya: Safe module loading**](/sections/security/safemoduleloading.md) +🔗 [**Baca selengkapnya: Safe module loading**](./sections/security/safemoduleloading.md)

@@ -972,7 +971,7 @@ Semua pernyataan di atas akan mengembalikan nilai _false_ jika menggunakan `===` **JIka tidak:** Sebuah plugin dapat menyerang dengan berbagai pilihan seperti perulangan tak terbatas, memberi muatan lebih pada memori, dan mengakses variabel lingkungan sensitif pada proses -🔗 [**Baca selengkapnya: Run unsafe code in a sandbox**](/sections/security/sandbox.md) +🔗 [**Baca selengkapnya: Run unsafe code in a sandbox**](./sections/security/sandbox.md)

@@ -984,7 +983,7 @@ Semua pernyataan di atas akan mengembalikan nilai _false_ jika menggunakan `===` **Jika tidak:** Penggunaan child process yang naif dapat mengakibatkan eksekusi perintah secara remote atau serangan injeksi shell karena masukan pengguna yang berbahaya diteruskan ke perintah sistem yang tidak disanitasi. -🔗 [**Baca selengkapnya: Be cautious when working with child processes**](/sections/security/childprocesses.md) +🔗 [**Baca selengkapnya: Be cautious when working with child processes**](./sections/security/childprocesses.md)

@@ -996,7 +995,7 @@ Semua pernyataan di atas akan mengembalikan nilai _false_ jika menggunakan `===` **Jika tidak:** Informasi sensitif aplikasi seperti path file server, modul pihak ketiga yang digunakan, dan alur kerja internal aplikasi lainnya yang dapat dieksploitasi oleh penyerang, dapat dibocorkan dari informasi yang ditemukan di dalam stack trace -🔗 [**Baca selengkapnya: Hide error details from client**](/sections/security/hideerrors.md) +🔗 [**Baca selengkapnya: Hide error details from client**](./sections/security/hideerrors.md)

@@ -1018,7 +1017,7 @@ Semua pernyataan di atas akan mengembalikan nilai _false_ jika menggunakan `===` **Jika tidak:** Cookie dapat dikirim melalui koneksi yang tidak aman, dan penyerang dapat menggunakan identifikasi sesi untuk mengidentifikasi framework dari aplikasi web, serta kerentanan masing-masing modul -🔗 [**Baca selengkapnya: Cookie and session security**](/sections/security/sessions.md) +🔗 [**Baca selengkapnya: Cookie and session security**](./sections/security/sessions.md)

@@ -1040,7 +1039,7 @@ Semua pernyataan di atas akan mengembalikan nilai _false_ jika menggunakan `===` **Jika tidak:** Jika penyerang menemukan bahwa Anda tidak memvalidasi masukan eksternal yang diberikan oleh pengguna, mereka dapat mengeksploitasi kerentanan ini dengan memposting tautan yang dibuat khusus di forum, media sosial, dan tempat publik lainnya agar pengguna mengkliknya. -🔗 [**Baca selengkapnya: Prevent unsafe redirects**](/sections/security/saferedirects.md) +🔗 [**Baca selengkapnya: Prevent unsafe redirects**](./sections/security/saferedirects.md)

@@ -1052,7 +1051,7 @@ Semua pernyataan di atas akan mengembalikan nilai _false_ jika menggunakan `===` **Jika tidak:** Kunci API, kata sandi atau rahasia lain proyek Anda dapat disalahgunakan oleh siapapun yang menemukannya, yang dapat mengakibatkan kerugian finansial, peniruan identitas, dan risiko lainnya. -🔗 [**Baca selengkapnya: Avoid publishing secrets**](/sections/security/avoid_publishing_secrets.md) +🔗 [**Baca selengkapnya: Avoid publishing secrets**](./sections/security/avoid_publishing_secrets.md)


⬆ Kembali ke atas

@@ -1065,11 +1064,11 @@ Semua pernyataan di atas akan mengembalikan nilai _false_ jika menggunakan `===` ## ![✔] 7.1. Jangan memblokir _event loop_ -**TL;DR:** Hindari pekerjaan yang intensif CPU karena mereka akan memblokir _Event Loop_ dalam satu _thread_ dan pindahkan pekerjaan ini ke _thread_ khusus, proses atau bahkan teknologi yang berbeda berdasarkan konteksnya. +**TL;DR:** Hindari pekerjaan yang intensif CPU karena mereka akan memblokir _Event Loop_ dalam satu _thread_ dan pindahkan pekerjaan ini ke _thread_ khusus, proses atau bahkan teknologi yang berbeda berdasarkan konteksnya. **Jika tidak:** Ketika _Event Loop_ diblokir, Node.js tidak akan dapat menangani permintaan lain sehingga menyebabkan penundaan bagi pengguna lain. **3000 pengguna sedang menunggu tanggapan, konten siap diberikan, tapi satu permintaan mencegah server-nya untuk mengirimkan hasilnya** -🔗 [**Baca selengkapnya: Do not block the event loop**](/sections/performance/block-loop.md) +🔗 [**Baca selengkapnya: Do not block the event loop**](./sections/performance/block-loop.md)


@@ -1080,7 +1079,7 @@ Ingatlah bahwa dengan diperkenalkannya mesin V8 baru bersama dengan standar ES b **Jika tidak:** Anda harus mengurus proyek dengan kinerja yang lebih rendah di mana Anda dapat menggunakan apa yang **sudah** ada atau berurusan dengan lebih sedikit baris namun lebih banyak file sebagai gantinya. -🔗 [**Baca selengkapnya: Native over user land utils**](/sections/performance/nativeoverutil.md) +🔗 [**Baca selengkapnya: Native over user land utils**](./sections/performance/nativeoverutil.md)


@@ -1106,6 +1105,7 @@ FROM node:14.4.0 AS build COPY . . RUN npm ci && npm run build + FROM node:slim-14.4.0 USER node @@ -1117,7 +1117,7 @@ RUN npm ci --production CMD [ "node", "dist/app.js" ] ``` -🔗 [**Baca selengkapnya: Use multi-stage builds**](/sections/docker/multi_stage_builds.md) +🔗 [**Baca selengkapnya: Use multi-stage builds**](./sections/docker/multi_stage_builds.md)


@@ -1127,7 +1127,7 @@ CMD [ "node", "dist/app.js" ] **Jika tidak:** Ketika tidak ada sinyal yang dilewatkan, kode Anda tidak akan pernah diberi tahu tentang penghentian. Tanpa itu, kode Anda akan kehilangan kesempatan untuk berhenti dengan benar dan kehilangan permintaan dan/atau data dapat terjadi. -[**Baca selengkapnya: Bootstrap container using node command, avoid npm start**](/sections/docker/bootstrap-using-node.md) +[**Baca selengkapnya: Bootstrap container using node command, avoid npm start**](./sections/docker/bootstrap-using-node.md)


@@ -1135,9 +1135,9 @@ CMD [ "node", "dist/app.js" ] **TL;DR:** Ketika menggunakan orkestrator run time Docker (misalnya Kubernetes), aktifkan proses Node.js seecara langsung tanpa manajer proses perantara atau kode khusus yang mereplikasi proses (misalnya PM2, modul Cluster). Platform runtime mempunyai jumlah data dan visibilitas tertinggi untuk membuat keputusan penempatan - Platform ini mengetahui dengan baik berapa banyak proses yang diperlukan, cara menyebarkannya dan apa yang harus dilakukan jika terjadi kerusakan -**Jika tidak:** Kontainer tetap rusak karena kekurangan sumber daya akan dimulai ulang tanpa batas oleh manajer proses. Jika Kubernetes menyadari hal ini, Kubernetes dapat memindahkannya ke banyak instance yang berbeda +**Jika tidak:** Kontainer tetap rusak karena kekurangan sumber daya akan dimulai ulang tanpa batas oleh manajer proses. Jika Kubernetes menyadari hal ini, Kubernetes dapat memindahkannya ke banyak instance yang berbeda -🔗 [**Baca selengkapnya: Let the Docker orchestrator restart and replicate processes**](/sections/docker/restart-and-replicate-processes.md) +🔗 [**Baca selengkapnya: Let the Docker orchestrator restart and replicate processes**](./sections/docker/restart-and-replicate-processes.md)


@@ -1147,7 +1147,7 @@ CMD [ "node", "dist/app.js" ] **Jika tidak**: File rahasia pribadi umum seperti `.env`, `.aws` dan `.npmrc` akan dibagikan dengan siapapun yang memiliki akses ke image (misalnya repositori Docker) -🔗 [**Baca selengkapnya: Use .dockerignore**](/sections/docker/docker-ignore.md) +🔗 [**Baca selengkapnya: Use .dockerignore**](./sections/docker/docker-ignore.md)


@@ -1157,7 +1157,7 @@ CMD [ "node", "dist/app.js" ] **Jika tidak:** Banyak penerobosan keamanan npm yang buruk ditemukan dalam paket pengembangan (misalnya [eslint-scope](https://eslint.org/blog/2018/07/postmortem-for-malicious-package-publishes)) -🔗 [**Baca selengkapnya: Remove development dependencies](/sections/docker/install-for-production.md) +🔗 [\*\*Baca selengkapnya: Remove development dependencies](./sections/docker/install-for-production.md)


@@ -1167,7 +1167,7 @@ CMD [ "node", "dist/app.js" ] **Jika tidak:** Mematikan aplikasi secara langsung berarti tidak menanggapi ribuan pengguna yang kecewa -🔗 [**Baca selengkapnya: Graceful shutdown**](/sections/docker/graceful-shutdown.md) +🔗 [**Baca selengkapnya: Graceful shutdown**](./sections/docker/graceful-shutdown.md)


@@ -1177,7 +1177,7 @@ CMD [ "node", "dist/app.js" ] **Jika tidak:** Definisi Docker diperlukan untuk melakukan keputusan penskalaan yang baik dan mencegah kelaparan warga lain. Tanpa menentukan batas pada v8 juga, sumber daya kontainer juga akan kurang digunakan oleh Node - Tanpa instruksi eksplisit Node akan berhenti saat menggunakan ~50-60% dari sumber daya hostnya -🔗 [**Baca selengkapnya: Set memory limits using Docker only**](/sections/docker/memory-limit.md) +🔗 [**Baca selengkapnya: Set memory limits using Docker only**](./sections/docker/memory-limit.md)


@@ -1187,7 +1187,7 @@ CMD [ "node", "dist/app.js" ] **Jika tidak:** Build Docker akan sangat lama dan memakan banyak sumber daya bahkan saat melakukan perubahan kecil -🔗 [**Baca selengkapnya: Leverage caching to reduce build times**](/sections/docker/use-cache-for-shorter-build-time.md) +🔗 [**Baca selengkapnya: Leverage caching to reduce build times**](./sections/docker/use-cache-for-shorter-build-time.md)


@@ -1199,7 +1199,7 @@ Selain itu, merujuk ke sebuah tag gambar berarti gambar dasar dapat berubah, kar **Jika tidak:** Versi baru gambar dasar dapat dideploy ke produksi dengan perubahan yang dapat merusak, menyebabkan perilaku aplikasi yang tidak diinginkan. -🔗 [**Baca selengkapnya: Understand image tags and use the "latest" tag with caution**](/sections/docker/image-tags.md) +🔗 [**Baca selengkapnya: Understand image tags and use the "latest" tag with caution**](./sections/docker/image-tags.md)


@@ -1209,7 +1209,7 @@ Selain itu, merujuk ke sebuah tag gambar berarti gambar dasar dapat berubah, kar **Jika tidak:** Membangun, mendorong, dan menarik gambar akan membutuhkan waktu yang lebih lama, vektor serangan yang tidak diketahui dapat digunakan oleh aktor jahat dan lebih banyak sumber daya yang dikonsumsi. -🔗 [**Baca selengkapnya: Prefer smaller images**](/sections/docker/smaller_base_images.md) +🔗 [**Baca selengkapnya: Prefer smaller images**](./sections/docker/smaller_base_images.md)


@@ -1219,7 +1219,7 @@ Selain itu, merujuk ke sebuah tag gambar berarti gambar dasar dapat berubah, kar **Jika tidak:** Setiap orang yang mempunyai akses ke CI dan registri Docker juga akan mendapatkan akses ke rahasia organisasi yang berharga sebagai bonus -🔗 [**Baca selengkapnya: Clean-out build-time secrets**](/sections/docker/avoid-build-time-secrets.md) +🔗 [**Baca selengkapnya: Clean-out build-time secrets**](./sections/docker/avoid-build-time-secrets.md)


@@ -1229,7 +1229,7 @@ Selain itu, merujuk ke sebuah tag gambar berarti gambar dasar dapat berubah, kar **Jika tidak:** Kode Anda mungkin sepenuhnya bebas dari kerentanan. Namun itu mungkin masih dapat diretas karena versi binari OS-level yang rentan (misalnya OpenSSL, TarBall) yang biasanya digunakan oleh aplikasi -🔗 [**Baca selengkapnya: Generic Docker practices**](/sections/docker/scan-images.md) +🔗 [**Baca selengkapnya: Generic Docker practices**](./sections/docker/scan-images.md)


@@ -1239,7 +1239,7 @@ Selain itu, merujuk ke sebuah tag gambar berarti gambar dasar dapat berubah, kar **Jika tidak:** Gambar yang akan dikirim ke produksi akan menjadi 30% lebih besar karena file yang tidak akan pernah digunakan -🔗 [**Baca selengkapnya: Clean NODE_MODULE cache**](/sections/docker/clean-cache.md) +🔗 [**Baca selengkapnya: Clean NODE_MODULE cache**](./sections/docker/clean-cache.md)


@@ -1247,7 +1247,7 @@ Selain itu, merujuk ke sebuah tag gambar berarti gambar dasar dapat berubah, kar **TL;DR:** Ini adalah kumpulan saran Docker yang tidak terkait langsung dengan Node.js - implementasi pada Node tidak jauh berbeda dengan bahasa lain. Klik baca selengkapnya untuk membaca sekilas. -🔗 [**Baca selengkapnya: Generic Docker practices**](/sections/docker/generic-tips.md) +🔗 [**Baca selengkapnya: Generic Docker practices**](./sections/docker/generic-tips.md)


@@ -1257,7 +1257,7 @@ Selain itu, merujuk ke sebuah tag gambar berarti gambar dasar dapat berubah, kar **Jika tidak:** Secara tidak sengaja pembuat Dockerfile meninggalkan Root sebagai pengguna produksi, dan juga menggunakan gambar dari repositori yang tidak dikenal. Hal ini dapat dihindari hanya dengan linter sederhana. -🔗 [**Baca selengkapnya: Lint your Dockerfile**](/sections/docker/lint-dockerfile.md) +🔗 [**Baca selengkapnya: Lint your Dockerfile**](./sections/docker/lint-dockerfile.md)


@@ -1275,18 +1275,19 @@ Semua terjemahan merupakan kontribusi dari komunitas. Kami akan dengan senang ha ### Terjemahan selesai -- ![BR](/assets/flags/BR.png) [Portugis Brazil](./README.brazilian-portuguese.md) - Terima kasih kepada [Marcelo Melo](https://github.com/marcelosdm) -- ![CN](/assets/flags/CN.png) [Cina](./README.chinese.md) - Terima kasih kepada [Matt Jin](https://github.com/mattjin) -- ![RU](/assets/flags/RU.png) [Rusia](./README.russian.md) - Terima kasih kepada [Alex Ivanov](https://github.com/contributorpw) -- ![PL](/assets/flags/PL.png) [Polandia](./README.polish.md) - Terima kasih kepada [Michal Biesiada](https://github.com/mbiesiad) +- ![BR](./assets/flags/BR.png) [Portugis Brazil](./README.brazilian-portuguese.md) - Terima kasih kepada [Marcelo Melo](https://github.com/marcelosdm) +- ![CN](./assets/flags/CN.png) [Cina](./README.chinese.md) - Terima kasih kepada [Matt Jin](https://github.com/mattjin) +- ![RU](./assets/flags/RU.png) [Rusia](./README.russian.md) - Terima kasih kepada [Alex Ivanov](https://github.com/contributorpw) +- ![PL](./assets/flags/PL.png) [Polandia](./README.polish.md) - Terima kasih kepada [Michal Biesiada](https://github.com/mbiesiad) +- ![EU](./assets/flags/EU.png) [Basque](README.basque.md) - Terima kasih kepada [Ane Diaz de Tuesta](https://github.com/anediaz) & Joxefe Diaz de Tuesta ### Terjemahan dalam proses -- ![FR](/assets/flags/FR.png) [Prancis](https://github.com/gaspaonrocks/nodebestpractices/blob/french-translation/README.french.md) ([Diskusi](https://github.com/goldbergyoni/nodebestpractices/issues/129)) -- ![HE](/assets/flags/HE.png) Ibrani ([Diskusi](https://github.com/goldbergyoni/nodebestpractices/issues/156)) -- ![KR](/assets/flags/KR.png) [Korea](README.korean.md) - Terima kasih kepada [Sangbeom Han](https://github.com/uronly14me) ([Diskusi](https://github.com/goldbergyoni/nodebestpractices/issues/94)) -- ![ES](/assets/flags/ES.png) [Spanyol](https://github.com/goldbergyoni/nodebestpractices/blob/spanish-translation/README.spanish.md) ([Diskusi](https://github.com/goldbergyoni/nodebestpractices/issues/95)) -- ![TR](/assets/flags/TR.png) Turki ([Diskusi](https://github.com/goldbergyoni/nodebestpractices/issues/139)) +- ![FR](./assets/flags/FR.png) [Prancis](https://github.com/gaspaonrocks/nodebestpractices/blob/french-translation/README.french.md) ([Diskusi](https://github.com/goldbergyoni/nodebestpractices/issues/129)) +- ![HE](./assets/flags/HE.png) Ibrani ([Diskusi](https://github.com/goldbergyoni/nodebestpractices/issues/156)) +- ![KR](./assets/flags/KR.png) [Korea](README.korean.md) - Terima kasih kepada [Sangbeom Han](https://github.com/uronly14me) ([Diskusi](https://github.com/goldbergyoni/nodebestpractices/issues/94)) +- ![ES](./assets/flags/ES.png) [Spanyol](https://github.com/goldbergyoni/nodebestpractices/blob/spanish-translation/README.spanish.md) ([Diskusi](https://github.com/goldbergyoni/nodebestpractices/issues/95)) +- ![TR](./assets/flags/TR.png) Turki ([Diskusi](https://github.com/goldbergyoni/nodebestpractices/issues/139))

@@ -1294,7 +1295,7 @@ Semua terjemahan merupakan kontribusi dari komunitas. Kami akan dengan senang ha Memperkenalkan anggota komite pengarah - orang-orang yang bekerja sama untuk memberikan panduan dan arahan masa depan proyek. Selain itu, setiap anggota komite memimpin proyek yang dilacak dalam [Github projects](https://github.com/goldbergyoni/nodebestpractices/projects) kami. - + [Yoni Goldberg](https://github.com/goldbergyoni) @@ -1304,7 +1305,7 @@ Konsultan Node.js independen yang bekerja dengan pelanggan di AS, Eropa, dan Isr
- + [Bruno Scheufler](https://github.com/BrunoScheufler) @@ -1313,7 +1314,7 @@ Konsultan Node.js independen yang bekerja dengan pelanggan di AS, Eropa, dan Isr
- + [Kyle Martin](https://github.com/js-kyle) @@ -1323,7 +1324,7 @@ Pengembang Full Stack & Site Reliability Engineer yang berbasis di Selandia Baru
- + [Kevyn Bruyere](https://github.com/kevynb) @@ -1334,7 +1335,7 @@ Pengembang full-stack independen dengan selera untuk Ops dan otomatisasi. ### Mantan Komite Pengarah - + [Sagir Khan](https://github.com/sagirk) @@ -1349,15 +1350,15 @@ Spesialis mendalam dalam JavaScript dan ekosistemnya — React, Node.js, TypeScr Terima kasih untuk semua kolaborator kami! 🙏 -Kolaborator kami adalah anggota yang sering berkontribusi ke repositori ini, melalui menyarankan praktik terbaik baru, menyortir masalah, meninjau pull request dan banyak lagi. Jika Anda tertarik untuk membantu kami memandu ribuan orang untuk membuat aplikasi Node.js yang lebih baik, silakan baca [contributor guidelines](/.operations/CONTRIBUTING.md) 🎉 +Kolaborator kami adalah anggota yang sering berkontribusi ke repositori ini, melalui menyarankan praktik terbaik baru, menyortir masalah, meninjau pull request dan banyak lagi. Jika Anda tertarik untuk membantu kami memandu ribuan orang untuk membuat aplikasi Node.js yang lebih baik, silakan baca [contributor guidelines](./.operations/CONTRIBUTING.md) 🎉 -| | | +| | | | :---------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------: | | [Ido Richter (Founder)](https://github.com/idori) | [Keith Holliday](https://github.com/TheHollidayInn) | ### Mantan Kolaborator -| | +| | | :-------------------------------------------------------------------------------------------------------------------------: | | [Refael Ackermann](https://github.com/refack) | @@ -1375,181 +1376,256 @@ Terima kasih kepada orang-orang hebat ini yang telah berkontribusi pada reposito - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

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

🌍
Kevin Rambaud
Kevin Rambaud

🖋
Michael Fine
Michael Fine

🖋
Shreya Dahal
Shreya Dahal

🖋
Matheus Cruz Rocha
Matheus Cruz Rocha

🖋
Yog Mehta
Yog Mehta

🖋
Kudakwashe Paradzayi
Kudakwashe Paradzayi

🖋
t1st3
t1st3

🖋
mulijordan1976
mulijordan1976

🖋
Matan Kushner
Matan Kushner

🖋
Fabio Hiroki
Fabio Hiroki

🖋
James Sumners
James Sumners

🖋
Dan Gamble
Dan Gamble

🖋
PJ Trainor
PJ Trainor

🖋
Remek Ambroziak
Remek Ambroziak

🖋
Yoni Jah
Yoni Jah

🖋
Misha Khokhlov
Misha Khokhlov

🖋
Evgeny Orekhov
Evgeny Orekhov

🖋
-
-

🖋
Isaac Halvorson
Isaac Halvorson

🖋
Vedran Karačić
Vedran Karačić

🖋
lallenlowe
lallenlowe

🖋
Nathan Wells
Nathan Wells

🖋
Paulo Reis
Paulo Reis

🖋
syzer
syzer

🖋
David Sancho
David Sancho

🖋
Robert Manolea
Robert Manolea

🖋
Xavier Ho
Xavier Ho

🖋
Aaron
Aaron

🖋
Jan Charles Maghirang Adona
Jan Charles Maghirang Adona

🖋
Allen
Allen

🖋
Leonardo Villela
Leonardo Villela

🖋
Michał Załęcki
Michał Załęcki

🖋
Chris Nicola
Chris Nicola

🖋
Alejandro Corredor
Alejandro Corredor

🖋
cwar
cwar

🖋
Yuwei
Yuwei

🖋
Utkarsh Bhatt
Utkarsh Bhatt

🖋
Duarte Mendes
Duarte Mendes

🖋
Jason Kim
Jason Kim

🖋
Mitja O.
Mitja O.

🖋
Sandro Miguel Marques
Sandro Miguel Marques

🖋
Gabe
Gabe

🖋
Ron Gross
Ron Gross

🖋
Valeri Karpov
Valeri Karpov

🖋
Sergio Bernal
Sergio Bernal

🖋
Nikola Telkedzhiev
Nikola Telkedzhiev

🖋
Vitor Godoy
Vitor Godoy

🖋
Manish Saraan
Manish Saraan

🖋
Sangbeom Han
Sangbeom Han

🖋
blackmatch
blackmatch

🖋
Joe Reeve
Joe Reeve

🖋
Ryan Busby
Ryan Busby

🖋
Iman Mohamadi
Iman Mohamadi

🖋
Sergii Paryzhskyi
Sergii Paryzhskyi

🖋
Kapil Patel
Kapil Patel

🖋
迷渡
迷渡

🖋
Hozefa
Hozefa

🖋
Ethan
Ethan

🖋
Sam
Sam

🖋
Arlind
Arlind

🖋
Teddy Toussaint
Teddy Toussaint

🖋
Lewis
Lewis

🖋
Gabriel Lidenor
Gabriel Lidenor

🖋
Roman
Roman

🖋
Francozeira
Francozeira

🖋
Invvard
Invvard

🖋
Rômulo Garofalo
Rômulo Garofalo

🖋
Tho Q Luong
Tho Q Luong

🖋
Burak Shen
Burak Shen

🖋
Martin Muzatko
Martin Muzatko

🖋
Jared Collier
Jared Collier

🖋
Hilton Meyer
Hilton Meyer

🖋
ChangJoo Park(박창주)
ChangJoo Park(박창주)

🖋
Masahiro Sakaguchi
Masahiro Sakaguchi

🖋
Keith Holliday
Keith Holliday

🖋
coreyc
coreyc

🖋
Maximilian Berkmann
Maximilian Berkmann

🖋
Douglas Mariano Valero
Douglas Mariano Valero

🖋
Marcelo Melo
Marcelo Melo

🖋
Mehmet Perk
Mehmet Perk

🖋
ryan ouyang
ryan ouyang

🖋
Shabeer
Shabeer

🖋
Eduard Kyvenko
Eduard Kyvenko

🖋
Deyvison Rocha
Deyvison Rocha

🖋
George Mamer
George Mamer

🖋
Konstantinos Leimonis
Konstantinos Leimonis

🖋
Oliver Lluberes
Oliver Lluberes

🌍
Tien Do
Tien Do

🖋
Ranvir Singh
Ranvir Singh

🖋
Vadim Nicolaev
Vadim Nicolaev

🖋 🌍
German Gamboa Gonzalez
German Gamboa Gonzalez

🖋
Hafez
Hafez

🖋
Chandiran
Chandiran

🖋
VinayaSathyanarayana
VinayaSathyanarayana

🖋
Kim Kern
Kim Kern

🖋
Kenneth Freitas
Kenneth Freitas

🖋
songe
songe

🖋
Kirill Shekhovtsov
Kirill Shekhovtsov

🖋
Serge
Serge

🖋
keyrwinz
keyrwinz

🖋
Dmitry Nikitenko
Dmitry Nikitenko

🖋
bushuai
bushuai

👀 🖋
Benjamin Gruenbaum
Benjamin Gruenbaum

🖋
Ezequiel
Ezequiel

🌍
Juan José Rodríguez
Juan José Rodríguez

🌍
Or Bin
Or Bin

🖋
Andreo Vieira
Andreo Vieira

🖋
Michael Solomon
Michael Solomon

🖋
Jimmy Callin
Jimmy Callin

🖋
Siddharth
Siddharth

🖋
Ryan Smith
Ryan Smith

🖋
Tom Boettger
Tom Boettger

🖋
Joaquín Ormaechea
Joaquín Ormaechea

🌍
dfrzuz
dfrzuz

🌍
Victor Homyakov
Victor Homyakov

🖋
Josh
Josh

🖋 🛡️
Alec Francis
Alec Francis

🖋
arjun6610
arjun6610

🖋
Jan Osch
Jan Osch

🖋
Thiago Rotondo Sampaio
Thiago Rotondo Sampaio

🌍
Alexsey
Alexsey

🖋
Luis A. Acurero
Luis A. Acurero

🌍
Lucas Romano
Lucas Romano

🌍
Denise Case
Denise Case

🖋
Nick Ribal
Nick Ribal

🖋 👀
0xflotus
0xflotus

🖋
Jonathan Chen
Jonathan Chen

🖋
Dilan Srilal
Dilan Srilal

🖋
vladthelittleone
vladthelittleone

🌍
Nik Osvalds
Nik Osvalds

🖋
Daniel Kiss
Daniel Kiss

📖
Forresst
Forresst

🖋
Jonathan Svenheden
Jonathan Svenheden

🖋
AustrisC
AustrisC

🖋
kyeongtae kim
kyeongtae kim

🌍
007
007

🖋
Ane Diaz de Tuesta
Ane Diaz de Tuesta

🌍 🖋
YukiOta
YukiOta

🌍
Frazer Smith
Frazer Smith

🖋
Raz Luvaton
Raz Luvaton

🖋
Yuta Azumi
Yuta Azumi

🖋
andrewjbarbour
andrewjbarbour

🖋
mr
mr

🖋
Aleksandar
Aleksandar

🖋
Owl
Owl

🖋
Yedidya Schwartz
Yedidya Schwartz

🖋 💡
ari
ari

🖋
Thomas König
Thomas König

🖋
Kalle Lämsä
Kalle Lämsä

🖋
Wyatt
Wyatt

🖋
KHADIR Tayeb
KHADIR Tayeb

🖋
Shankar Regmi
Shankar Regmi

🖋
Shubham
Shubham

🖋
Lucas Alves
Lucas Alves

🖋
Benjamin
Benjamin

🖋
Yeoh Joer
Yeoh Joer

🖋
Miigon
Miigon

🖋
Rostislav Bogorad
Rostislav Bogorad

🖋
Flouse
Flouse

🖋
Tarantini Pereira
Tarantini Pereira

🖋
Kazuki Matsuo
Kazuki Matsuo

🖋
Adam Smith
Adam Smith

🖋
Dohyeon Ko
Dohyeon Ko

🖋
Vladislav Legkov
Vladislav Legkov

🖋
Kerollos Magdy
Kerollos Magdy

🖋
Erez Lieberman
Erez Lieberman

🖋
Breno Macedo
Breno Macedo

🖋
Fernando Flores
Fernando Flores

🌍
Rafael Brito
Rafael Brito

🌍
Emiliano Peralta
Emiliano Peralta

🌍
Shin, SJ
Shin, SJ

🖋
Benjamin Forster
Benjamin Forster

🖋
Daniele Fedeli
Daniele Fedeli

🖋
djob195
djob195

🖋
antspk
antspk

🖋
정진영
정진영

🖋
kkk-cashwalk
kkk-cashwalk

🖋
apainintheneck
apainintheneck

🖋
Fajar Budhi Iswanda
Fajar Budhi Iswanda

🖋
이주호
이주호

🖋
Singh
Singh

🖋
Alex Dumitru
Alex Dumitru

🖋
Anton Lykhatskyi
Anton Lykhatskyi

🖋
sangwonlee
sangwonlee

🖋
Eugenio Berretta
Eugenio Berretta

🖋
soranakk
soranakk

🖋
고준영
고준영

🖋 💻
Guilherme Portella
Guilherme Portella

🖋
André Esser
André Esser

🖋
Scc
Scc

🌍
Mauro Accornero
Mauro Accornero

🖋
no-yan
no-yan

🖋
diff --git a/README.japanese.md b/README.japanese.md index 64b978cf4..7ec6e9559 100644 --- a/README.japanese.md +++ b/README.japanese.md @@ -3,23 +3,22 @@ # Node.js ベストプラクティス

- Node.js Best Practices + Node.js Best Practices


- 101 items Last update: March, 2020 Updated for Node 13.1.0 + 101 items Last update: March, 2020 Updated for Node 13.1.0

-[![nodepractices](/assets/images/twitter-s.png)](https://twitter.com/nodepractices/) **私たちの Twitter をフォローしましょう!** [**@nodepractices**](https://twitter.com/nodepractices/) - +[![nodepractices](./assets/images/twitter-s.png)](https://twitter.com/nodepractices/) **私たちの Twitter をフォローしましょう!** [**@nodepractices**](https://twitter.com/nodepractices/)
-他の言語で読む: [![CN](/assets/flags/CN.png)**CN**](/README.chinese.md), [![BR](/assets/flags/BR.png)**BR**](/README.brazilian-portuguese.md), [![RU](/assets/flags/RU.png)**RU**](/README.russian.md), [![PL](/assets/flags/PL.png)**PL**](/README.polish.md), [![JA](/assets/flags/JA.png)**JA**](/README.japanese.md) [(![ES](/assets/flags/ES.png)**ES**, ![FR](/assets/flags/FR.png)**FR**, ![HE](/assets/flags/HE.png)**HE**, ![KR](/assets/flags/KR.png)**KR** and ![TR](/assets/flags/TR.png)**TR** in progress!)](#translations) +他の言語で読む: [![CN](./assets/flags/CN.png)**CN**](./README.chinese.md), [![BR](./assets/flags/BR.png)**BR**](./README.brazilian-portuguese.md), [![RU](./assets/flags/RU.png)**RU**](./README.russian.md), [![PL](./assets/flags/PL.png)**PL**](./README.polish.md), [![JA](./assets/flags/JA.png)**JA**](./README.japanese.md), [![EU](./assets/flags/EU.png)**EU**](./README.basque.md) [(![ES](./assets/flags/ES.png)**ES**, ![FR](./assets/flags/FR.png)**FR**, ![HE](./assets/flags/HE.png)**HE**, ![KR](./assets/flags/KR.png)**KR** and ![TR](./assets/flags/TR.png)**TR** in progress!)](#translations)
@@ -41,7 +40,7 @@ **1. 実際、あなたは何十もの Node.js の最高の記事を読んでいます -** このリポジトリは、Node.js のベストプラクティスに関するトップランクのコンテンツや、コラボレーターによって書かれたコンテンツをまとめたものです。 -**2. 最大の集大成であり、毎週のように増え続けています -** 現在、80 以上のベストプラクティスやスタイルガイド、アーキテクチャのヒントが記載されています。この「生きた本」がアップデートされた状態を保つために、新しいイシューやプルリクエストは毎日のように作成されています。私たちは、コードの修正や翻訳作業、素晴らしい新たなアイデアの提案に至るまで、あなたの貢献を心待ちにしています。詳しくは[ライティングガイドライン](/.operations/writing-guidelines.japanese.md)をご覧ください。 +**2. 最大の集大成であり、毎週のように増え続けています -** 現在、80 以上のベストプラクティスやスタイルガイド、アーキテクチャのヒントが記載されています。この「生きた本」がアップデートされた状態を保つために、新しいイシューやプルリクエストは毎日のように作成されています。私たちは、コードの修正や翻訳作業、素晴らしい新たなアイデアの提案に至るまで、あなたの貢献を心待ちにしています。詳しくは[ライティングガイドライン](./.operations/writing-guidelines.japanese.md)をご覧ください。 **3. ほとんどのベストプラクティスには追加情報があります -** ほとんどの項目に **🔗 さらに読む** というリンクがあります。このリンクは、コード例や厳選されたブログからの引用、その他多くの情報など、プラクティスを発展させる内容を含んでいます。 @@ -68,7 +67,7 @@ **さもないと:** 新しい機能をコーディングする開発者が、自分の変更の影響を理解するのに苦労したり、他の依存するコンポーネントを壊すことを恐れたりすると、デプロイが遅くなり、リスクが高くなります。また、すべてのビジネスユニットが分離されていない場合、スケールアウトするのは難しいと考えられています。 -🔗 [**さらに読む: コンポーネントで構成する**](/sections/projectstructre/breakintcomponents.japanese.md) +🔗 [**さらに読む: コンポーネントで構成する**](./sections/projectstructre/breakintcomponents.japanese.md)

@@ -78,7 +77,7 @@ **さもないと:** Web オブジェクトと他のレイヤーが混在するアプリには、テストコードや CRON ジョブ、メッセージキューからのトリガーなどからアクセスすることはできません。 -🔗 [**さらに読む: アプリケーションを階層化する**](/sections/projectstructre/createlayers.japanese.md) +🔗 [**さらに読む: アプリケーションを階層化する**](./sections/projectstructre/createlayers.japanese.md)

@@ -88,17 +87,17 @@ **さもないと:** デプロイと依存関係の車輪の作成をしなければいけなくなります -🔗 [**さらに読む: 機能で構成する**](/sections/projectstructre/wraputilities.japanese.md) +🔗 [**さらに読む: 機能で構成する**](./sections/projectstructre/wraputilities.japanese.md)

## ![✔] 1.4 Express の「アプリ」と「サーバー」を分離する -**TL;DR:** [Express](https://expressjs.com/) のアプリ全体を単一の巨大なファイルで定義するという厄介な習慣を回避します。- 「Express」の定義を、API 宣言( app.js )とネットワーク関連( WWW )の少なくとも2つのファイルに分離してください。より良い構造にするためには、API 宣言をコンポーネント内に配置してください。 +**TL;DR:** [Express](https://expressjs.com/) のアプリ全体を単一の巨大なファイルで定義するという厄介な習慣を回避します。- 「Express」の定義を、API 宣言( app.js )とネットワーク関連( WWW )の少なくとも 2 つのファイルに分離してください。より良い構造にするためには、API 宣言をコンポーネント内に配置してください。 **さもないと:** API は HTTP 呼び出しのみでテストにアクセスできるようになります(カバレッジレポートを生成するのがより遅く、はるかに困難になります)。何百行ものコードを一つのファイルで管理するのは、おそらく大きな喜びではないでしょう。 -🔗 [**さらに読む: Express の「アプリ」と「サーバー」を分離する**](/sections/projectstructre/separateexpress.japanese.md) +🔗 [**さらに読む: Express の「アプリ」と「サーバー」を分離する**](./sections/projectstructre/separateexpress.japanese.md)

@@ -108,7 +107,7 @@ **さもないと:** 設定要件のどれかを満たさないと、開発チームや DevOps チーム、おそらく両方ともの頭を悩ませてしまいます。 -🔗 [**さらに読む: 構成のベストプラクティス**](/sections/projectstructre/configguide.japanese.md) +🔗 [**さらに読む: 構成のベストプラクティス**](./sections/projectstructre/configguide.japanese.md)


@@ -122,7 +121,7 @@ **さもなければ:** Node.js のコールバックスタイル、つまり function(err, response) を利用することは、正常な処理を行うコードとエラーハンドリングの混同、過剰なネスト構造、そして厄介なコーディングパターンが原因となって、メンテナンス性の低いコードにつながります。 -🔗 [**さらに読む: コールバック関数の利用を避ける**](/sections/errorhandling/asyncerrorhandling.japanese.md) +🔗 [**さらに読む: コールバック関数の利用を避ける**](./sections/errorhandling/asyncerrorhandling.japanese.md)

@@ -132,7 +131,7 @@ **さもないと:** ある要素を呼び出したとき、どの型のエラーが返ってくるか不確かである - といった状況は、適切なエラー処理をより難しいものにします。さらに悪いことに、エラーを表現するためにカスタム型を使うことは、スタックトレースのような重大なエラー情報を失うことに繋がるかもしれません。 -🔗 [**さらに読む: 組み込みのエラーオブジェクトのみを使用する**](/sections/errorhandling/useonlythebuiltinerror.japanese.md) +🔗 [**さらに読む: 組み込みのエラーオブジェクトのみを使用する**](./sections/errorhandling/useonlythebuiltinerror.japanese.md)

@@ -142,7 +141,7 @@ **さもないと:** エラーが発生したときに毎回アプリケーションを再起動しているかもしれませんが、さほど重要でない、予測可能な、操作上のエラーを原因としてなぜ ~5000 人規模のオンラインユーザーをダウンさせるのでしょうか? その逆もまた理想的ではありません ー 未知のエラー(プログラマーのエラー)が発生したときにアプリケーションをそのまま起動し続けることは、予想外の振る舞いに繋がるかもしれません。この2つを区別することで、機転の利いた振る舞いをさせ、与えられたコンテキストに基づいた適切なアプローチを適用させることができます。 -🔗 [**さらに読む: 操作上のエラーとプログラマーのエラーを区別する**](/sections/errorhandling/operationalvsprogrammererror.japanese.md) +🔗 [**さらに読む: 操作上のエラーとプログラマーのエラーを区別する**](./sections/errorhandling/operationalvsprogrammererror.japanese.md)

@@ -152,7 +151,7 @@ **さもないと:** エラーを一箇所で処理しないと、コードの重複や、不適切に処理されたエラーの発生に繋がる可能性があります。 -🔗 [**さらに読む: エラー処理を一元化し、ミドウェア内で処理をしない**](/sections/errorhandling/centralizedhandling.japanese.md) +🔗 [**さらに読む: エラー処理を一元化し、ミドウェア内で処理をしない**](./sections/errorhandling/centralizedhandling.japanese.md)

@@ -162,7 +161,7 @@ **さもないと:** API クライアントがクラッシュして再起動するのは、不明なエラーを受け取ったからかもしれません。注意: API の呼び出し元はあなた自身かもしれません(マイクロサービス構成では非常によくあることです) -🔗 [**さらに読む: Swagger または GraphQL を利用して API のエラーをドキュメント化する**](/sections/errorhandling/documentingusingswagger.japanese.md) +🔗 [**さらに読む: Swagger または GraphQL を利用して API のエラーをドキュメント化する**](./sections/errorhandling/documentingusingswagger.japanese.md)

@@ -172,7 +171,7 @@ **さもないと:** 不明な例外が発生した場合、一部のオブジェクトが不完全な状態(例えば、グローバルに使用されているイベントエミッタが内部的なエラーによりイベントを発火しなくなっている、など)になっている可能性があり、後に来るリクエストが失敗したり、予期せぬ挙動をしたりするかもしれません。 -🔗 [**さらに読む: 見ず知らずの事象が起きたら潔くプロセスを終了する**](/sections/errorhandling/shuttingtheprocess.japanese.md) +🔗 [**さらに読む: 見ず知らずの事象が起きたら潔くプロセスを終了する**](./sections/errorhandling/shuttingtheprocess.japanese.md)

@@ -182,7 +181,7 @@ **さもないと:** console.log によるログに目を通したり、クエリツールやまともなログビューア無しで扱いにくいテキストファイルを手動で確認したりすると、遅くまで仕事をする羽目になるかもしれません。 -🔗 [**さらに読む: エラーの可視性を高めるために成熟したロガーを使用する**](/sections/errorhandling/usematurelogger.japanese.md) +🔗 [**さらに読む: エラーの可視性を高めるために成熟したロガーを使用する**](./sections/errorhandling/usematurelogger.japanese.md)

@@ -192,7 +191,7 @@ **さもないと:** 自動であっても手動であっても、テストがなければ、コードが正しいエラーを返すと信用することはできません。意味のあるエラーがなければ、エラー処理はできません。 -🔗 [**さらに読む: お気に入りのテストフレームワークを使用してエラーフローをテストする**](/sections/errorhandling/testingerrorflows.japanese.md) +🔗 [**さらに読む: お気に入りのテストフレームワークを使用してエラーフローをテストする**](./sections/errorhandling/testingerrorflows.japanese.md)

@@ -202,7 +201,7 @@ **さもないと:** API のパフォーマンスとダウンタイムの計測に多大な労力を費やしているかもしれませんが、現実のシナリオにおいてどの部分のコードが最も遅いのか、そしてそれらがどのように UX に影響を及ぼしているのか、あなたが気づくことは恐らくないでしょう。 -🔗 [**さらに読む: APM 製品を利用してエラーとダウンタイムを発見する**](/sections/errorhandling/apmproducts.japanese.md) +🔗 [**さらに読む: APM 製品を利用してエラーとダウンタイムを発見する**](./sections/errorhandling/apmproducts.japanese.md)

@@ -212,7 +211,7 @@ **さもないと:** あなたのエラーは飲み込まれて、何のトレースも残しません。心配することは、何も残りません。 -🔗 [**さらに読む: 未処理の reject された promise を捕捉する**](/sections/errorhandling/catchunhandledpromiserejection.japanese.md) +🔗 [**さらに読む: 未処理の reject された promise を捕捉する**](./sections/errorhandling/catchunhandledpromiserejection.japanese.md)

@@ -222,7 +221,7 @@ **さもないと:** 考えてみて下さい ー 関数は数値の引数「Discount」を受け取ることを期待していますが、呼び出し元が値を渡すのを忘れてしまいました。その後、コードが Discount!=0 (許容されたディスカウントの量が 0 よりも大きいことを想定) であるということをチェックし、そのチェックをクリアした場合にユーザーがディスカウントを受けられるようにしました。オーマイガー、なんて厄介なバグなんでしょう。わかりますか?(訳注:「さらに読む」に具体的なコード例が載っています) -🔗 [**さらに読む: 専用のライブラリを利用して引数の検証を高速に行う**](/sections/errorhandling/failfast.japanese.md) +🔗 [**さらに読む: 専用のライブラリを利用して引数の検証を高速に行う**](./sections/errorhandling/failfast.japanese.md)


@@ -236,7 +235,7 @@ **さもないと:** 開発者は退屈な間隔や線幅の問題に集中し、プロジェクトのコードスタイルを考えすぎて時間を無駄にしてしまうかもしれません。 -🔗 [**さらに読む: ESLint と Prettier を使う**](/sections/codestylepractices/eslint_prettier.japanese.md) +🔗 [**さらに読む: ESLint と Prettier を使う**](./sections/codestylepractices/eslint_prettier.japanese.md)

@@ -280,7 +279,7 @@ function someFunction() **さもないと:** 前のセクションで見たように、JavaScript のインタプリタは、セミコロンがない場合は自動的に文の最後にセミコロンを追加したり、ステートメントが本来あるべき場所で終わっていないとみなしたりすることで、望まない結果になってしまう可能性があります。代入を使用し、即時に呼び出された関数式の使用を避けることで、予期せぬエラーのほとんどを防ぐことができます。 -### コード例 +### 3.4 コード例 ```javascript // する @@ -326,7 +325,7 @@ const count = 2 // 2() を実行しようとしますが、2 は関数ではあ ## ![✔] 3.6 変数、定数、関数、クラスの命名規則を使用する -**TL;DR:** 定数、変数、関数の命名をするときは **_lowerCamelCase_** を使用し、クラスの命名をするときは**_UpperCamelCase_** (頭文字も大文字) を使用してください。これは、プレーンな変数/関数とインスタンス化を必要とするクラスを簡単に区別するのに役立ちます。記述的な名前を使用しますが、短くしてください。 +**TL;DR:** 定数、変数、関数の命名をするときは **_lowerCamelCase_** を使用し、クラスの命名をするときは**_UpperCamelCase_** (頭文字も大文字) を使用してください。これは、プレーンな変数/関数とインスタンス化を必要とするクラスを簡単に区別するのに役立ちます。記述的な名前を使用しますが、短くしてください。 **さもないと:** JavaScript は、最初にインスタンスを作成せずにコンストラクタ(「クラス」)を直接呼び出すことができる世界で唯一の言語です。その結果、クラスと関数構造体は UpperCamelCase から始まることで区別されます。 @@ -338,7 +337,7 @@ class SomeClassExample {} // const 名には const キーワードと lowerCamelCase を使用します const config = { - key: "value" + key: "value", }; // 変数や関数名には lowerCamelCase を使用します @@ -348,9 +347,9 @@ function doSomething() {}

-## ![✔] 3.7 let よりも const を優先してください。var はいりません。 +## ![✔] 3.7 let よりも const を優先してください。var はいりません -**TL;DR:** `const` を使うということは、一度代入された変数は再代入できないということを意味します。`const` を優先することで、同じ変数を異なる用途に使いたくなることを防ぎ、コードをより明確にすることができます。変数を再割り当てする必要がある場合、例えば for ループの中などでは、`let` を使って宣言します。もう一つの重要な点は、`let` を使って宣言された変数は、それが定義されたブロックスコープ内でのみ利用可能であるということです。`var` はブロックスコープではなく関数スコープであり、[ES6では使うべきではない](https://hackernoon.com/why-you-shouldnt-use-var-anymore-f109a58b9b70) ので、`const` と `let` がある以上必要ありません。 +**TL;DR:** `const` を使うということは、一度代入された変数は再代入できないということを意味します。`const` を優先することで、同じ変数を異なる用途に使いたくなることを防ぎ、コードをより明確にすることができます。変数を再割り当てする必要がある場合、例えば for ループの中などでは、`let` を使って宣言します。もう一つの重要な点は、`let` を使って宣言された変数は、それが定義されたブロックスコープ内でのみ利用可能であるということです。`var` はブロックスコープではなく関数スコープであり、[ES6 では使うべきではない](https://hackernoon.com/why-you-shouldnt-use-var-anymore-f109a58b9b70) ので、`const` と `let` がある以上必要ありません。 **さもないと:** 頻繁に変化する変数に従うと、デバッグが非常に面倒になります。 @@ -388,9 +387,9 @@ module.exports.SMSNumberResolver = require("./SMSNumberResolver/SMSNumberResolve ## ![✔] 3.10 `===` 演算子を使用する -**TL;DR:** 弱い抽象的な等号演算子 `==` よりも厳密な等号演算子 `===` を優先してください。`==` は2つの変数を共通の型に変換した後に比較します。`===` には型変換はなく、両方の変数が同じ型で等しくなければいけません。 +**TL;DR:** 弱い抽象的な等号演算子 `==` よりも厳密な等号演算子 `===` を優先してください。`==` は 2 つの変数を共通の型に変換した後に比較します。`===` には型変換はなく、両方の変数が同じ型で等しくなければいけません。 -**さもないと:** `==` 演算子で比較すると、同じでない値でも真を返すかもしれません。 +**さもないと:** `==` 演算子で比較すると、同じでない値でも真を返すかもしれません。 ### 3.10 Code example @@ -451,7 +450,7 @@ null == undefined; // true **さもないと:** "Add product" という名付けられたテストが通らず、デプロイが失敗しました。これは、実際に何がうまく動作しなかったのかを示しているでしょうか? -🔗 [**さらに読む: 各テスト名に 3 つの要素を含む**](/sections/testingandquality/3-parts-in-name.japanese.md) +🔗 [**さらに読む: 各テスト名に 3 つの要素を含む**](./sections/testingandquality/3-parts-in-name.japanese.md)

@@ -461,7 +460,7 @@ null == undefined; // true **さもないと:** メインコードを理解するのに長時間費やすだけでなく、今までシンプルな部分であったはずのもの(テスト)が、脳のリソースを奪います。 -🔗 [**さらに読む: AAA パターンを用いてテストを構成する**](/sections/testingandquality/aaa.japanese.md) +🔗 [**さらに読む: AAA パターンを用いてテストを構成する**](./sections/testingandquality/aaa.japanese.md)

@@ -479,7 +478,7 @@ null == undefined; // true **さもないと:** テストが失敗したことによってデプロイが中止されるというシナリオを考えてみましょう。チームは貴重な時間を調査に費やし、結果として悲しい結論にたどり着きます: システムは機能していますが、テスト同士が干渉しあって、ビルドを壊しているのです。 -🔗 [**さらに読む: グローバルなテストフィクスチャとシードを避け、テストごとにデータを追加する**](/sections/testingandquality/avoid-global-test-fixture.japanese.md) +🔗 [**さらに読む: グローバルなテストフィクスチャとシードを避け、テストごとにデータを追加する**](./sections/testingandquality/avoid-global-test-fixture.japanese.md)

@@ -529,7 +528,7 @@ null == undefined; // true **さもないと:** コードの品質が低いと、ピカピカの新しいライブラリや最新の機能では修正できない類のバグやパフォーマンスが常に問題となります。 -🔗 [**さらに読む: リファクタリング!**](/sections/testingandquality/refactoring.japanese.md) +🔗 [**さらに読む: リファクタリング!**](./sections/testingandquality/refactoring.japanese.md)

@@ -539,7 +538,7 @@ null == undefined; // true **さもないと:** ニッチなベンダーを選択すると、高度なカスタマイズが必要になった際に困るかもしれません。一方で、Jenkins を選択するとインフラのセットアップに貴重な時間を費やすことになる可能性があります。 -🔗 [**さらに読む: CI プラットフォームを選択する**](/sections/testingandquality/citools.japanese.md) +🔗 [**さらに読む: CI プラットフォームを選択する**](./sections/testingandquality/citools.japanese.md) ## ![✔] 4.13 ミドルウェアを分離してテストする @@ -547,7 +546,7 @@ null == undefined; // true **さもないと:** Express ミドルウェアにおけるバグ === ほぼ全てのリクエストにおけるバグ -🔗 [**さらに読む: ミドルウェアを分離してテストする**](/sections/testingandquality/test-middlewares.japanese.md) +🔗 [**さらに読む: ミドルウェアを分離してテストする**](./sections/testingandquality/test-middlewares.japanese.md)


@@ -561,17 +560,17 @@ null == undefined; // true **さもないと:** 失敗 === 失望したお客さん。シンプルです。 -🔗 [**さらに読む: モニタリング!**](/sections/production/monitoring.japanese.md) +🔗 [**さらに読む: モニタリング!**](./sections/production/monitoring.japanese.md)

## ![✔] 5.2. スマートロギングで透明性を高める -**TL;DR:** ログは、デバッグ ステートメント用のゴミ倉庫にも、アプリのストーリーを伝える美しいダッシュボードのイネーブラーにもなり得ます。1日目からロギングプラットフォームを計画しましょう:ログをどのように収集、保存、分析するかで、必要な情報(エラー率、サービスやサーバーを介したトランザクション全体の追跡など)を実際に抽出できるようにします。 +**TL;DR:** ログは、デバッグ ステートメント用のゴミ倉庫にも、アプリのストーリーを伝える美しいダッシュボードのイネーブラーにもなり得ます。1 日目からロギングプラットフォームを計画しましょう:ログをどのように収集、保存、分析するかで、必要な情報(エラー率、サービスやサーバーを介したトランザクション全体の追跡など)を実際に抽出できるようにします。 **さもないと:** 推論するのが難しいブラックボックスになってしまい、追加情報を追加するためにすべてのロギングステートメントを書き直します。 -🔗 [**さらに読む: スマートロギングで透明性を高める**](/sections/production/smartlogging.japanese.md) +🔗 [**さらに読む: スマートロギングで透明性を高める**](./sections/production/smartlogging.japanese.md)

@@ -581,7 +580,7 @@ null == undefined; // true **さもないと:** 貧弱なシングルスレッドは、アプリケーションコアを処理する代わりにインフラタスクを行うことに忙しくなり、パフォーマンスはそれに応じて低下します。 -🔗 [**さらに読む: 可能な限りのこと全て( gzip、SSL など)をリバースプロキシに委譲する**](/sections/production/delegatetoproxy.japanese.md) +🔗 [**さらに読む: 可能な限りのこと全て( gzip、SSL など)をリバースプロキシに委譲する**](./sections/production/delegatetoproxy.japanese.md)

@@ -591,7 +590,7 @@ null == undefined; // true **さもないと:** QA はコードを徹底的にテストし、本番環境では異なる挙動をするバージョンを承認します。さらに悪いことに、同じクラスタ内の異なるサーバが異なるコードを実行する可能性があります。 -🔗 [**さらに読む: 依存関係をロックする**](/sections/production/lockdependencies.japanese.md) +🔗 [**さらに読む: 依存関係をロックする**](./sections/production/lockdependencies.japanese.md)

@@ -601,17 +600,17 @@ null == undefined; // true **さもないと:** 明確な戦略を持たずに何十ものインスタンスを実行し、あまりにも多くのツール(クラスタ管理、docker、PM2)を一緒に使いすぎると、DevOps のカオスにつながる可能性があります。 -🔗 [**さらに読む: 適切なツールを使用してプロセスの稼働時間を守る**](/sections/production/guardprocess.japanese.md) +🔗 [**さらに読む: 適切なツールを使用してプロセスの稼働時間を守る**](./sections/production/guardprocess.japanese.md)

## ![✔] 5.6. すべての CPU コアを利用する -**TL;DR:** 基本的な形として、Node アプリは他のすべてがアイドル状態のままで、単一のCPUコア上で動作します。 Node プロセスを複製し、すべての CPU を利用するのはあなたの義務です。 – 中小規模のアプリでは、Node クラスタや PM2 を使用することができます。大規模なアプリケーションでは、Docker クラスタ( K8S や ECS など)や Linux の init システム( systemd など)をベースにしたデプロイスクリプトを使用してプロセスを複製することを検討してください。 +**TL;DR:** 基本的な形として、Node アプリは他のすべてがアイドル状態のままで、単一の CPU コア上で動作します。 Node プロセスを複製し、すべての CPU を利用するのはあなたの義務です。 – 中小規模のアプリでは、Node クラスタや PM2 を使用することができます。大規模なアプリケーションでは、Docker クラスタ( K8S や ECS など)や Linux の init システム( systemd など)をベースにしたデプロイスクリプトを使用してプロセスを複製することを検討してください。 -**さもないと:** あなたのアプリは、利用可能なリソースの25%、もしくはそれ以下しか使用していない可能性が高いです(!)。一般的なサーバは4つ以上の CPU コアを持っていますが、 Node.js のナイーブなデプロイでは1つしか利用していないことに注意してください( AWS beanstalk のような PaaS サービスを利用している場合でも!)。 +**さもないと:** あなたのアプリは、利用可能なリソースの 25%、もしくはそれ以下しか使用していない可能性が高いです(!)。一般的なサーバは 4 つ以上の CPU コアを持っていますが、 Node.js のナイーブなデプロイでは 1 つしか利用していないことに注意してください( AWS beanstalk のような PaaS サービスを利用している場合でも!)。 -🔗 [**さらに読む: すべての CPU コアを利用する**](/sections/production/utilizecpu.japanese.md) +🔗 [**さらに読む: すべての CPU コアを利用する**](./sections/production/utilizecpu.japanese.md)

@@ -621,7 +620,7 @@ null == undefined; // true **さもないと:** 多くの「診断デプロイ」を実行していることがわかります。– 診断目的のための情報を抽出するためだけにコードを本番環境に出荷するなど -🔗 [**さらに読む: 「メンテナンスエンドポイント」を作成する**](/sections/production/createmaintenanceendpoint.japanese.md) +🔗 [**さらに読む: 「メンテナンスエンドポイント」を作成する**](./sections/production/createmaintenanceendpoint.japanese.md)

@@ -631,17 +630,17 @@ null == undefined; // true **さもないと:** API のパフォーマンスやダウンタイムの測定に多大な労力を費やすことになるかもしれません。実世界のシナリオで最も遅いコード部分はどれか、それが UX にどのように影響するのか、おそらくあなたは意識することはないでしょう。 -🔗 [**さらに読む: APM 製品を使用してエラーやダウンタイムを発見する**](/sections/production/apmproducts.japanese.md) +🔗 [**さらに読む: APM 製品を使用してエラーやダウンタイムを発見する**](./sections/production/apmproducts.japanese.md)

## ![✔] 5.9. コードを本番に即したものにする -**TL;DR:** ゴールを意識してコードを作成し、1日目から制作計画を立てます。ちょっと漠然としているように聞こえるので、生産保守と密接に関係する開発のヒントをいくつかまとめてみました(下の Gist をクリックしてください)。 +**TL;DR:** ゴールを意識してコードを作成し、1 日目から制作計画を立てます。ちょっと漠然としているように聞こえるので、生産保守と密接に関係する開発のヒントをいくつかまとめてみました(下の Gist をクリックしてください)。 **さもないと:** 世界チャンピオンの IT/DevOps の男でも、下手に書かれたシステムを救うことはできません。 -🔗 [**さらに読む: コードを本番に即したものにする**](/sections/production/productioncode.japanese.md) +🔗 [**さらに読む: コードを本番に即したものにする**](./sections/production/productioncode.japanese.md)

@@ -649,9 +648,9 @@ null == undefined; // true **TL;DR:** Node.js はメモリとの関係で物議を醸しています: v8 エンジンはメモリ使用量にソフトな制限(1.4 GB )があり、Node のコードにはメモリリークの経路が知られています。– そのため、Node のプロセスメモリを監視することは必須です。小さなアプリでは、シェルコマンドを使って定期的にメモリを測定することができますが、中規模以上のアプリでは、メモリ監視を堅牢な監視システムに組み込むことを検討してください。 -**さもないと:** あなたのプロセスメモリは、[Walmart](https://www.joyent.com/blog/walmart-node-js-memory-leak) で起こったように、1日に10MBもリークするかもしれません。 +**さもないと:** あなたのプロセスメモリは、[Walmart](https://www.joyent.com/blog/walmart-node-js-memory-leak) で起こったように、1 日に 10MB もリークするかもしれません。 -🔗 [**さらに読む: メモリ使用量を測定してガードする**](/sections/production/measurememory.japanese.md) +🔗 [**さらに読む: メモリ使用量を測定してガードする**](./sections/production/measurememory.japanese.md)

@@ -661,7 +660,7 @@ null == undefined; // true **さもないと:** あなたの Node のシングルスレッドは、何百もの html/images/angular/react ファイルのストリーミングに忙殺され、本来の目的のために生まれたタスクにすべてのリソースを確保することができません。– 動的コンテンツの提供 -🔗 [**さらに読む: フロントエンドの資産を Node から取り出す**](/sections/production/frontendout.japanese.md) +🔗 [**さらに読む: フロントエンドの資産を Node から取り出す**](./sections/production/frontendout.japanese.md)

@@ -671,17 +670,17 @@ null == undefined; // true **Otherwise:** 特定のサーバーで障害が発生すると、障害のあるマシンを停止する代わりに、アプリケーションのダウンタイムが発生します。さらに、特定のサーバーに依存しているため、スケーリングアウトの弾力性はより困難になります。 -🔗 [**さらに読む: ステートレスのままで、ほぼ毎日サーバーを停止させる**](/sections/production/bestateless.japanese.md) +🔗 [**さらに読む: ステートレスのままで、ほぼ毎日サーバーを停止させる**](./sections/production/bestateless.japanese.md)

## ![✔] 5.13. 脆弱性を自動的に検出するツールを使用する -**TL;DR:** Express のような最も評判の良い依存関係にも、(時折)システムを危険にさらす既知の脆弱性があります。脆弱性を常にチェックして警告するコミュニティや商用ツール(ローカルまたはGitHub)を使えば簡単に手なずけることができ、いくつかはすぐにパッチを当てることもできます。 +**TL;DR:** Express のような最も評判の良い依存関係にも、(時折)システムを危険にさらす既知の脆弱性があります。脆弱性を常にチェックして警告するコミュニティや商用ツール(ローカルまたは GitHub)を使えば簡単に手なずけることができ、いくつかはすぐにパッチを当てることもできます。 **さもないと:** 専用のツールを使用せずに脆弱性からコードをクリーンに保つには、新しい脅威についてのオンライン出版物を常にフォローする必要があります。とても面倒です。 -🔗 [**さらに読む: 脆弱性を自動的に検出するツールを使用する**](/sections/production/detectvulnerabilities.japanese.md) +🔗 [**さらに読む: 脆弱性を自動的に検出するツールを使用する**](./sections/production/detectvulnerabilities.japanese.md)

@@ -691,7 +690,7 @@ null == undefined; // true **さもないと:** – 前に何が起こったのか – というコンテキストなしでプロダクションのエラーログを見ると、問題の原因を究明するのが非常に難しくなり、時間がかかります。 -🔗 [**さらに読む: 各ログ文に 'TransactionId' を割り当てる**](/sections/production/assigntransactionid.japanese.md) +🔗 [**さらに読む: 各ログ文に 'TransactionId' を割り当てる**](./sections/production/assigntransactionid.japanese.md)

@@ -699,9 +698,9 @@ null == undefined; // true **TL;DR:** 環境変数 NODE_ENV を「production」または「development」に設定して、本番環境での最適化を有効にするかどうかのフラグを立てます。– 多くの npm パッケージが現在の環境を判断し、本番用にコードを最適化します。 -**さもないと:** この単純なプロパティを省略すると、パフォーマンスが大きく低下する可能性があります。例えば、サーバサイドのレンダリングに Express を使用する場合、`NODE_ENV` を省略すると3倍も遅くなります。 +**さもないと:** この単純なプロパティを省略すると、パフォーマンスが大きく低下する可能性があります。例えば、サーバサイドのレンダリングに Express を使用する場合、`NODE_ENV` を省略すると 3 倍も遅くなります。 -🔗 [**さらに読む: NODE_ENV=production を設定する**](/sections/production/setnodeenv.japanese.md) +🔗 [**さらに読む: NODE_ENV=production を設定する**](./sections/production/setnodeenv.japanese.md)

@@ -719,7 +718,7 @@ null == undefined; // true **さもないと:** 新たに発見されたバグや脆弱性は、本番環境で運用中のアプリケーションを悪用するために使用される可能性があり、アプリケーションは様々なモジュールでサポートされておらず、保守が困難になる可能性があります。 -🔗 [**さらに読む: Node.js の LTS リリースを使用する**](/sections/production/LTSrelease.japanese.md) +🔗 [**さらに読む: Node.js の LTS リリースを使用する**](./sections/production/LTSrelease.japanese.md)

@@ -729,7 +728,7 @@ null == undefined; // true **さもないと:** アプリケーションがログのルーティングをハンドリングする === スケールアップが難しい、ログの損失、懸念事項の分離が悪い -🔗 [**さらに読む: ログルーティング**](/sections/production/logrouting.japanese.md) +🔗 [**さらに読む: ログルーティング**](./sections/production/logrouting.japanese.md)

@@ -739,7 +738,7 @@ null == undefined; // true **さもないと:** QA はコードを徹底的にテストし、本番環境では異なる動作をするバージョンを承認します。さらに悪いことに、同じプロダクションクラスタ内の異なるサーバが異なるコードを実行する可能性があります。 -🔗 [**さらに読む: npm ci を使う**](/sections/production/installpackageswithnpmci.japanese.md) +🔗 [**さらに読む: npm ci を使う**](./sections/production/installpackageswithnpmci.japanese.md)


@@ -759,7 +758,7 @@ null == undefined; // true **さもなければ:** 開発時には単純なセキュリティ上の弱点だったかもしれないものが、本番環境では大きな問題となります。同様に、プロジェクトが一貫したコードセキュリティプラクティスに従わない場合もあり、脆弱性が入り込んだり、リモートリポジトリに機密情報がコミットされたりする可能性があります。 -🔗 [**さらに読む: Lint ルール**](/sections/security/lintrules.japanese.md) +🔗 [**さらに読む: Lint ルール**](./sections/security/lintrules.japanese.md)

@@ -771,7 +770,7 @@ null == undefined; // true **さもないと:** アプリケーションは攻撃を受ける可能性があり、結果としてユーザーに不十分なサービスを提供したり、サービス停止をしなければならない状況に陥ります。 -🔗 [**さらに読む: レートリミットの実装**](/sections/security/limitrequests.japanese.md) +🔗 [**さらに読む: レートリミットの実装**](./sections/security/limitrequests.japanese.md)

@@ -783,19 +782,19 @@ null == undefined; // true **さもないと:** ソースコントロールは、たとえプライベートリポジトリであっても誤ってパブリックになる可能性があり、その時点で全てのシークレットが公開されてしまいます。外部サービスに与えられたソースコントロールへのアクセス権限は、関連するシステム(データベース、API、その他サービスなど)へのアクセス権限をうっかり与えてしまうことがあります。 -🔗 [**さらに読む: シークレット管理**](/sections/security/secretmanagement.japanese.md) +🔗 [**さらに読む: シークレット管理**](./sections/security/secretmanagement.japanese.md)

-## ![✔] 6.4. O/Rマッパ/ODM ライブラリを使用してクエリインジェクション脆弱性を防ぐ +## ![✔] 6.4. O/R マッパ/ODM ライブラリを使用してクエリインジェクション脆弱性を防ぐ -**TL;DR:** SQL/NoSQL インジェクションやその他の悪意ある攻撃を防ぐために、データをエスケープしたり、名前付きやインデックス付きのパラメータ化されたクエリをサポートしていたり、ユーザー入力が期待する型となっているか検証してくれる O/Rマッパ/ODM やデータベースライブラリを活用してください。JavaScript のテンプレート文字列や文字列の結合を使用して値をクエリに挿入してはいけません。これはアプリケーションに広範囲の脆弱性を与えます。全ての評判の良い Node.js データアクセスライブラリ([Sequelize](https://github.com/sequelize/sequelize), [Knex](https://github.com/tgriesser/knex), [mongoose](https://github.com/Automattic/mongoose) など)はインジェクション攻撃に対してあらかじめ対策されています。 +**TL;DR:** SQL/NoSQL インジェクションやその他の悪意ある攻撃を防ぐために、データをエスケープしたり、名前付きやインデックス付きのパラメータ化されたクエリをサポートしていたり、ユーザー入力が期待する型となっているか検証してくれる O/R マッパ/ODM やデータベースライブラリを活用してください。JavaScript のテンプレート文字列や文字列の結合を使用して値をクエリに挿入してはいけません。これはアプリケーションに広範囲の脆弱性を与えます。全ての評判の良い Node.js データアクセスライブラリ([Sequelize](https://github.com/sequelize/sequelize), [Knex](https://github.com/tgriesser/knex), [mongoose](https://github.com/Automattic/mongoose) など)はインジェクション攻撃に対してあらかじめ対策されています。 -**さもないと:** 未検証またはサニタイズされていないユーザー入力は、MongoDB のような NoSQL データベースで作業している際にオペレーターインジェクションを招きますし、適切なサニタイズシステムまたは O/Rマッパ を利用しないことは容易に SQL インジェクション攻撃を招き、多大な脆弱性を生みます。 +**さもないと:** 未検証またはサニタイズされていないユーザー入力は、MongoDB のような NoSQL データベースで作業している際にオペレーターインジェクションを招きますし、適切なサニタイズシステムまたは O/R マッパ を利用しないことは容易に SQL インジェクション攻撃を招き、多大な脆弱性を生みます。 -🔗 [**さらに読む: ORM/ODM ライブラリを使用してクエリインジェクション脆弱性を防ぐ**](/sections/security/ormodmusage.japanese.md) +🔗 [**さらに読む: ORM/ODM ライブラリを使用してクエリインジェクション脆弱性を防ぐ**](./sections/security/ormodmusage.japanese.md)

@@ -803,7 +802,7 @@ null == undefined; // true **TL;DR:** Node.js とは直接関係のないセキュリティに関するアドバイス集です ー Node における実装は他の言語とあまり違いはありません。さらに読むをクリックして、読み進めてください。 -🔗 [**さらに読む: 一般的なセキュリティベストプラクティス**](/sections/security/commonsecuritybestpractices.japanese.md) +🔗 [**さらに読む: 一般的なセキュリティベストプラクティス**](./sections/security/commonsecuritybestpractices.japanese.md)

@@ -815,7 +814,7 @@ null == undefined; // true **さもないと:** 攻撃者がアプリケーションユーザーに対して直接攻撃を行い、甚大なセキュリティ脆弱性につながる可能性があります。 -🔗 [**さらに読む: アプリケーションでセキュアなヘッダーを利用する**](/sections/security/secureheaders.japanese.md) +🔗 [**さらに読む: アプリケーションでセキュアなヘッダーを利用する**](./sections/security/secureheaders.japanese.md)

@@ -827,7 +826,7 @@ null == undefined; // true **さもないと:** 攻撃者がウェブフレームワークを特定して、全ての既知の脆弱性を突いてくる可能性があります。 -🔗 [**さらに読む: 依存性のセキュリティ**](/sections/security/dependencysecurity.japanese.md) +🔗 [**さらに読む: 依存性のセキュリティ**](./sections/security/dependencysecurity.japanese.md)

@@ -839,7 +838,7 @@ null == undefined; // true **さもないと:** セキュアな関数を使わずに永続化されたパスワードやシークレット情報は、ブルートフォース攻撃や辞書攻撃に弱く、結果として情報漏えいに繋がります。 -🔗 [**さらに読む: Bcrypt を使用する**](/sections/security/bcryptpasswords.japanese.md) +🔗 [**さらに読む: Bcrypt を使用する**](./sections/security/bcryptpasswords.japanese.md)

@@ -851,7 +850,7 @@ null == undefined; // true **さもないと:** 攻撃者は悪意のある JavaScript のコードを DB に保存し、それをそのまま脆弱なクライアントに送信する可能性があります。 -🔗 [**さらに読む: 出力をエスケープする**](/sections/security/escape-output.japanese.md) +🔗 [**さらに読む: 出力をエスケープする**](./sections/security/escape-output.japanese.md)

@@ -863,7 +862,7 @@ null == undefined; // true **さもないと:** あなたの寛大で寛容なアプローチは攻撃対象を大幅に拡大させ、攻撃者がアプリケーションをクラッシュさせるための組み合わせを見つけるまで、多くの入力を試してみるように促すことに繋がります。 -🔗 [**さらに読む: 受信した JSON スキーマを検証する**](/sections/security/validation.japanese.md) +🔗 [**さらに読む: 受信した JSON スキーマを検証する**](./sections/security/validation.japanese.md)

@@ -875,7 +874,7 @@ null == undefined; // true **さもないと:** 期限切れや、誤って配置されたトークンは、アプリケーションにアクセスしたり、トークンの所有者になりすますために、サードパーティによって悪意を持って利用される可能性があります。 -🔗 [**さらに読む: JSON Web Token のブラックリスト**](/sections/security/expirejwt.japanese.md) +🔗 [**さらに読む: JSON Web Token のブラックリスト**](./sections/security/expirejwt.japanese.md)

@@ -890,7 +889,7 @@ null == undefined; // true **さもないと:** 攻撃者が、アプリケーションの特権アカウントへのアクセス権を得るために、無制限の自動化されたパスワード試行を行うことができます。 -🔗 [**さらに読む: ログインレートリミット**](/sections/security/login-rate-limit.japanese.md) +🔗 [**さらに読む: ログインレートリミット**](./sections/security/login-rate-limit.japanese.md)

@@ -902,7 +901,7 @@ null == undefined; // true **さもないと:** サーバ上でスクリプトを実行することに成功した攻撃者が、ローカルマシンにおける無制限の権限を獲得してしまいます(例:iptable を変更して、攻撃者のサーバに再ルーティングする)。 -🔗 [**さらに読む: 非 root ユーザとして Node.js を実行する**](/sections/security/non-root-user.japanese.md) +🔗 [**さらに読む: 非 root ユーザとして Node.js を実行する**](./sections/security/non-root-user.japanese.md)

@@ -914,7 +913,7 @@ null == undefined; // true **さもないと:** アプリケーションは大きなリクエストを処理しなければなくなり、他の重要な仕事を完遂させることができず、パフォーマンスへの影響や DDoS 攻撃に対する脆弱性につながります。 -🔗 [**さらに読む: ペイロードサイズを制限する**](/sections/security/requestpayloadsizelimit.japanese.md) +🔗 [**さらに読む: ペイロードサイズを制限する**](./sections/security/requestpayloadsizelimit.japanese.md)

@@ -926,7 +925,7 @@ null == undefined; // true **さもないと:** 悪意のある JavaScript コードが `eval` やその他のリアルタイムに評価する JavaScript の関数に渡されるテキストへたどり着き、そのページにおける JavaScript の完全な権限を獲得してしまいます。この脆弱性はしばしば XSS 攻撃として顕在化します。 -🔗 [**さらに読む: JavaScript の eval 構文を避ける**](/sections/security/avoideval.japanese.md) +🔗 [**さらに読む: JavaScript の eval 構文を避ける**](./sections/security/avoideval.japanese.md)

@@ -934,11 +933,11 @@ null == undefined; // true -**TL;DR:** 正規表現(RegEx)は便利ですが、JavaScript アプリケーション全体、特に Node.js プラットフォームに対して真の脅威となります。テキストのユーザー入力をマッチさせることは、処理に大量の CPU サイクルを必要とするかもしれません。RegEx の処理は、10 Wordを検証する単一のリクエストが 6 秒間イベントループ全体をブロックし、CPU に 🔥 を点けるほどには非効率であるかもしれません。そのため、独自の RegExp パターンを記述する代わりに [validator.js](https://github.com/chriso/validator.js) のようなサードパーティ検証パッケージを利用するか、脆弱な正規表現パターンを検出するために [safe-regex](https://github.com/substack/safe-regex) を利用するようにしましょう。 +**TL;DR:** 正規表現(RegEx)は便利ですが、JavaScript アプリケーション全体、特に Node.js プラットフォームに対して真の脅威となります。テキストのユーザー入力をマッチさせることは、処理に大量の CPU サイクルを必要とするかもしれません。RegEx の処理は、10 Word を検証する単一のリクエストが 6 秒間イベントループ全体をブロックし、CPU に 🔥 を点けるほどには非効率であるかもしれません。そのため、独自の RegExp パターンを記述する代わりに [validator.js](https://github.com/chriso/validator.js) のようなサードパーティ検証パッケージを利用するか、脆弱な正規表現パターンを検出するために [safe-regex](https://github.com/substack/safe-regex) を利用するようにしましょう。 **さもないと:** 下手な正規表現の記述は、イベントループを完全にブロックしてしまう正規表現 DoS 攻撃の影響を受ける可能性があります。例えば、人気のある `moment` パッケージでは、2017 年 11 月に悪意のある RegEx の使用による脆弱性が発見されています。 -🔗 [**さらに読む: 悪質な RegEx を防止する**](/sections/security/regex.japanese.md) +🔗 [**さらに読む: 悪質な RegEx を防止する**](./sections/security/regex.japanese.md)

@@ -950,7 +949,7 @@ null == undefined; // true **さもないと:** 悪意のあるユーザー入力は、既存のシステムファイルに、前にファイルシステムにアップロードされたファイルのような改変されたファイルを要求したり、既存のシステムファイルにアクセスするために利用されるパラメータを操作する可能性があります。 -🔗 [**さらに読む: 安全なモジュール読み込み**](/sections/security/safemoduleloading.japanese.md) +🔗 [**さらに読む: 安全なモジュール読み込み**](./sections/security/safemoduleloading.japanese.md)

@@ -962,7 +961,7 @@ null == undefined; // true **さもないと:** プラグインは、無限ループやメモリーオーバーロード、センシティブなプロセスの環境変数へのアクセスなど、あらゆる手段を通じて攻撃可能となります。 -🔗 [**さらに読む: サンドボックス内で安全でないコードを実行する**](/sections/security/sandbox.japanese.md) +🔗 [**さらに読む: サンドボックス内で安全でないコードを実行する**](./sections/security/sandbox.japanese.md)

@@ -974,7 +973,7 @@ null == undefined; // true **さもないと:** 子プロセスを愚直に利用することは、サニタイズされていないシステムコマンドに渡される悪意のあるユーザー入力が原因となって、結果としてリモートからのコマンド実行、またはシェルインジェクション攻撃を受けることにつながります。 -🔗 [**さらに読む: 子プロセスで処理を行う場合は注意する**](/sections/security/childprocesses.japanese.md) +🔗 [**さらに読む: 子プロセスで処理を行う場合は注意する**](./sections/security/childprocesses.japanese.md)

@@ -986,15 +985,15 @@ null == undefined; // true **さもないと:** 攻撃者によって悪用される可能性のある、サーバファイルのパス、使用中のサードパーティモジュール、アプリケーションのその他内部ワークフローなど、機密性の高いアプリケーションの詳細情報が、スタックトレース内に残された情報から漏洩する可能性があります。 -🔗 [**さらに読む: エラーの詳細をクライアントから隠す**](/sections/security/hideerrors.japanese.md) +🔗 [**さらに読む: エラーの詳細をクライアントから隠す**](./sections/security/hideerrors.japanese.md)

-## ![✔] 6.21. npm や Yarn に2要素認証(2FA)を設定する +## ![✔] 6.21. npm や Yarn に 2 要素認証(2FA)を設定する -**TL;DR:** 開発におけるどのステップも、MFA(多要素認証)で保護されるべきです。npm/Yarn は開発者のパスワードに触れることができる攻撃者にとって絶好の機会となります。開発者の認証情報を利用して、プロジェクトやサービスにおいて広くインストールされている攻撃者は悪意のあるコードを注入することができます。もしパブリックに公開されている場合は、ウェブ全体にまで及ぶかもしれません。npm において2要素認証を設定することで、攻撃者がパッケージコードを改ざんする可能性はほぼゼロになります。 +**TL;DR:** 開発におけるどのステップも、MFA(多要素認証)で保護されるべきです。npm/Yarn は開発者のパスワードに触れることができる攻撃者にとって絶好の機会となります。開発者の認証情報を利用して、プロジェクトやサービスにおいて広くインストールされている攻撃者は悪意のあるコードを注入することができます。もしパブリックに公開されている場合は、ウェブ全体にまで及ぶかもしれません。npm において 2 要素認証を設定することで、攻撃者がパッケージコードを改ざんする可能性はほぼゼロになります。 **さもないと:** [Have you heard about the eslint developer whose password was hijacked?(パスワードがハイジャックされた eslint 開発者の話を聞いたことがありますか?)](https://medium.com/@oprearocks/eslint-backdoor-what-it-is-and-how-to-fix-the-issue-221f58f1a8c8) @@ -1006,9 +1005,9 @@ null == undefined; // true **TL;DR:** それぞれの Web フレームワークや技術には、既知の弱点があります - 攻撃者に対してどの Web フレームワークを利用しているかを伝えることは、攻撃者にとって大きな助けになることです。セッションミドルウェアのデフォルトの設定を利用することは、`X-Powered-By` ヘッダー同様に、アプリケーションをモジュールやフレームワーク固有のハイジャック攻撃にさらす可能性があります。技術スタック(例:Node.js、express など)を識別したり、明らかにするものは極力隠すようにしてください。 -**さもないと:** Cookieは安全でないコネクションを通じて送信される恐れがあり、攻撃者はセッション識別子を利用して背後にある Web アプリケーションフレームワークや、モジュール固有の脆弱性を特定する可能性があります。 +**さもないと:** Cookie は安全でないコネクションを通じて送信される恐れがあり、攻撃者はセッション識別子を利用して背後にある Web アプリケーションフレームワークや、モジュール固有の脆弱性を特定する可能性があります。 -🔗 [**さらに読む: クッキー(Cookie)とセッションの安全性**](/sections/security/sessions.japanese.md) +🔗 [**さらに読む: クッキー(Cookie)とセッションの安全性**](./sections/security/sessions.japanese.md)

@@ -1030,7 +1029,7 @@ null == undefined; // true **さもないと:** もし攻撃者が、外部のユーザーから与えられた入力を検証していないことを発見した場合、特別に作成されたリンクをフォーラムやソーシャルメディア、その他のパブリックな場所に投稿してユーザーにクリックさせることで、この脆弱性を悪用する恐れがあります。 -🔗 [**さらに読む: 安全でないリダイレクトを防ぐ**](/sections/security/saferedirects.japanese.md) +🔗 [**さらに読む: 安全でないリダイレクトを防ぐ**](./sections/security/saferedirects.japanese.md)

@@ -1042,7 +1041,7 @@ null == undefined; // true **さもないと:** プロジェクトの API キーやパスワード、その他のシークレットが公開され、その情報を目にしたすべての人に悪用されることで、結果として金銭的な損失、なりすまし、その他リスクに繋がってしまいます。 -🔗 [**さらに読む: シークレットの公開を避ける**](/sections/security/avoid_publishing_secrets.japanese.md) +🔗 [**さらに読む: シークレットの公開を避ける**](./sections/security/avoid_publishing_secrets.japanese.md)


⬆ トップに戻る

@@ -1055,11 +1054,11 @@ null == undefined; // true ## ![✔] 7.1. イベントループをブロックしない -**TL;DR:** CPU集約的なタスクは、主にシングルスレッドのイベントループをブロックし、専用のスレッド、プロセス、またはコンテキストに基づいて別の技術にそれらをオフロードするため、避けてください。 +**TL;DR:** CPU 集約的なタスクは、主にシングルスレッドのイベントループをブロックし、専用のスレッド、プロセス、またはコンテキストに基づいて別の技術にそれらをオフロードするため、避けてください。 -**さもないと:** イベントループがブロックされると、Node.js は他のリクエストを処理することができなくなり、同時接続ユーザーの遅延を引き起こします。**3000人のユーザーがレスポンスを待っていて、コンテンツを提供する準備ができていたとしても、1つのリクエストがサーバからの結果のディスパッチをブロックしていしまいます*** +**さもないと:** イベントループがブロックされると、Node.js は他のリクエストを処理することができなくなり、同時接続ユーザーの遅延を引き起こします。**3000 人のユーザーがレスポンスを待っていて、コンテンツを提供する準備ができていたとしても、1 つのリクエストがサーバからの結果のディスパッチをブロックしていしまいます** -🔗 [**さらに読む: イベントループをブロックしない**](/sections/performance/block-loop.japanese.md) +🔗 [**さらに読む: イベントループをブロックしない**](./sections/performance/block-loop.japanese.md)


@@ -1070,7 +1069,7 @@ null == undefined; // true **さもないと:** **すでに**利用可能なものを単純に使用できたり、いくつかのファイルと引き換えに、数行で処理することができるような、パフォーマンスの低いプロジェクトを維持しなければならないでしょう。 -🔗 [**さらに読む: ユーザーランドなユーティリティよりもネイティブを使用する**](/sections/performance/nativeoverutil.japanese.md) +🔗 [**さらに読む: ユーザーランドなユーティリティよりもネイティブを使用する**](./sections/performance/nativeoverutil.japanese.md)


@@ -1096,6 +1095,7 @@ FROM node:14.4.0 AS build COPY . . RUN npm ci && npm run build + FROM node:slim-14.4.0 USER node @@ -1107,17 +1107,17 @@ RUN npm ci --production CMD [ "node", "dist/app.js" ] ``` -🔗 [**さらに読む: マルチステージビルドを使用する**](/sections/docker/multi_stage_builds.japanese.md) +🔗 [**さらに読む: マルチステージビルドを使用する**](./sections/docker/multi_stage_builds.japanese.md)


-## ![✔] 8.2. 'node' コマンドを使用して、npm start 避けた Bootstrap +## ![✔] 8.2. 'node' コマンドを使用して、npm start 避けた Bootstrap **TL;DR:** アプリの起動には `CMD ['node','server.js']` を使用し、OS のシグナルをコードに渡さない npm スクリプトの使用は避けてください。これにより、子プロセス、シグナル処理、グレースフルシャットダウン、ゾンビプロセスの問題を防ぐことができます。 **さもないと:** シグナルが渡されない場合、あなたのコードはシャットダウンについて通知されることはありません。これがなければ、適切に閉じる機会を失い、現在のリクエストやデータを失う可能性があります。 -[**さらに読む: node コマンドを使用して 、npm の起動を避けた Bootstrap コンテナ**](/sections/docker/bootstrap-using-node.japanese.md) +[**さらに読む: node コマンドを使用して 、npm の起動を避けた Bootstrap コンテナ**](./sections/docker/bootstrap-using-node.japanese.md)


@@ -1127,7 +1127,7 @@ CMD [ "node", "dist/app.js" ] **さもないと:** リソース不足でクラッシュし続けるコンテナは、プロセスマネージャによって無期限に再起動されてしまいます。Kubernetes がそれを認識していれば、別の余裕のあるインスタンスに移すことができます。 -🔗 [**さらに読む: プロセスを再起動と複製をDocker オーケストレーターに任せる**](/sections/docker/restart-and-replicate-processes.japanese.md) +🔗 [**さらに読む: プロセスを再起動と複製を Docker オーケストレーターに任せる**](./sections/docker/restart-and-replicate-processes.japanese.md)


@@ -1137,7 +1137,7 @@ CMD [ "node", "dist/app.js" ] **さもないと**: `.env`, `.aws`, `.npmrc` のような共通の個人秘密ファイルは、イメージにアクセスできる人全員に共有されます (例: Docker リポジトリ)。 -🔗 [**さらに読む: .dockerignore を使用する**](/sections/docker/docker-ignore.japanese.md) +🔗 [**さらに読む: .dockerignore を使用する**](./sections/docker/docker-ignore.japanese.md)


@@ -1147,7 +1147,7 @@ CMD [ "node", "dist/app.js" ] **さもないと:** 悪名高い npm のセキュリティ侵害の多くは開発パッケージ内で発見されました (例: [eslint-scope](https://eslint.org/blog/2018/07/postmortem-for-malicious-package-publishes) -🔗 さらに読む: [開発依存性の除去](/sections/docker/install-for-production.japanese.md) +🔗 さらに読む: [開発依存性の除去](./sections/docker/install-for-production.japanese.md)


@@ -1157,7 +1157,7 @@ CMD [ "node", "dist/app.js" ] **さもないと:** 即座に kill してしまうことは、何千人もの失望したユーザーに対応しないことを意味します。 -🔗 [**さらに読む: グレースフルシャットダウン**](/sections/docker/graceful-shutdown.japanese.md) +🔗 [**さらに読む: グレースフルシャットダウン**](./sections/docker/graceful-shutdown.japanese.md)


@@ -1167,7 +1167,7 @@ CMD [ "node", "dist/app.js" ] **さもないと:** docker の定義は、思慮深いスケーリングの決定を行い、他の市民を飢えさせないようにするために必要です。v8 の制限を定義しないと、コンテナリソースを十分に利用できません。 - 明示的な指示がないと、ホストリソースの ~50-60% を利用するときにクラッシュします。 -🔗 [**さらに読む: Docker のみを使用してメモリ制限を設定する**](/sections/docker/memory-limit.japanese.md) +🔗 [**さらに読む: Docker のみを使用してメモリ制限を設定する**](./sections/docker/memory-limit.japanese.md)


@@ -1177,7 +1177,7 @@ CMD [ "node", "dist/app.js" ] **さもないと:** Docker のビルドが非常に長くなり、小さな変更をした場合でも多くのリソースを消費することになります。 -🔗 [**さらに読む: キャッシュを活用してビルド時間を短縮する**](/sections/docker/use-cache-for-shorter-build-time.japanese.md) +🔗 [**さらに読む: キャッシュを活用してビルド時間を短縮する**](./sections/docker/use-cache-for-shorter-build-time.japanese.md)


@@ -1189,7 +1189,7 @@ CMD [ "node", "dist/app.js" ] **さもないと:** 破壊的変更を含むベースイメージの新しいバージョンが本番環境にデプロイされ、意図しないアプリケーションの挙動を引き起こす可能性があります。 -🔗 [**さらに読む: イメージタグを理解して「latest」タグを注意して使う**](/sections/docker/image-tags.japanese.md) +🔗 [**さらに読む: イメージタグを理解して「latest」タグを注意して使う**](./sections/docker/image-tags.japanese.md)


@@ -1199,7 +1199,7 @@ CMD [ "node", "dist/app.js" ] **さもないと:** イメージのビルド、プッシュ、プルに時間を要し、未知の攻撃の因子が悪意のあるアクターによって使用され、より多くのリソースが消費されます。 -🔗 [**さらに読む: 小さなイメージを優先する**](/sections/docker/smaller_base_images.japanese.md) +🔗 [**さらに読む: 小さなイメージを優先する**](./sections/docker/smaller_base_images.japanese.md)


@@ -1209,7 +1209,7 @@ CMD [ "node", "dist/app.js" ] **さもないと:** CI と docker レジストリへのアクセス権限を持っている人は誰でも、おまけとして貴重な組織の情報にアクセスできてしまいます。 -🔗 [**さらに読む: ビルド時のシークレットをクリーンアウトする**](/sections/docker/avoid-build-time-secrets.japanese.md) +🔗 [**さらに読む: ビルド時のシークレットをクリーンアウトする**](./sections/docker/avoid-build-time-secrets.japanese.md)


@@ -1219,7 +1219,7 @@ CMD [ "node", "dist/app.js" ] **さもないと:** コードは脆弱性から完全に脆弱性から解放されているかもしれませんが、アプリケーションで一般的に使用されている OS レベルのバイナリ(例:OpenSSL、TarBall)の脆弱性が原因となって、ハッキングされる可能性が依然としてあります。 -🔗 [**さらに読む: プロダクションの前にイメージ全体をスキャンする**](/sections/docker/scan-images.japanese.md) +🔗 [**さらに読む: プロダクションの前にイメージ全体をスキャンする**](./sections/docker/scan-images.japanese.md)


@@ -1229,7 +1229,7 @@ CMD [ "node", "dist/app.js" ] **さもないと:** 使用されないファイルが原因で、サイズが 3 割増のイメージがプロダクションにデプロイされることになります。 -🔗 [**さらに読む: NODE_MODULE キャッシュをクリーンアップする**](/sections/docker/clean-cache.japanese.md) +🔗 [**さらに読む: NODE_MODULE キャッシュをクリーンアップする**](./sections/docker/clean-cache.japanese.md)


@@ -1237,18 +1237,17 @@ CMD [ "node", "dist/app.js" ] **TL;DR:** Node.js とは直接関係の無い、Docker に関するアドバイス集です - Node における実装は他の言語とあまり変わりません。「さらに読む」から読み進めてください。 -🔗 [**さらに読む: 一般的な Docker のプラクティス**](/sections/docker/generic-tips.japanese.md) +🔗 [**さらに読む: 一般的な Docker のプラクティス**](./sections/docker/generic-tips.japanese.md)


- ## ![✔] 8.15. Dockerfile を lint する **TL;DR:** Dockerfile を linting することは、ベストプラクティスとは異なってしまっている Dockerfile の問題点を特定するための重要なステップです。Docker 専用の linter を使って潜在的な欠落をチェックすることで、パフォーマンスとセキュリティの改善可能箇所を容易に特定することができ、無駄な時間を削り、またプロダクションコードにおけるセキュリティの問題から解放してくれます。 **さもないと:** Dockerfile の作者が誤って root を本番ユーザーにしてしまい、不明なソースリポジトリからの Docker イメージを使用してしまう、といったことが起こり得ます。これは、シンプルな litner を利用することで回避することができます。 -🔗 [**さらに読む: Dockerfile を lint する**](/sections/docker/lint-dockerfile.japanese.md) +🔗 [**さらに読む: Dockerfile を lint する**](./sections/docker/lint-dockerfile.japanese.md)


@@ -1266,19 +1265,20 @@ CMD [ "node", "dist/app.js" ] ### 翻訳(完了済み) -- ![BR](/assets/flags/BR.png) [Brazilian Portuguese](./README.brazilian-portuguese.md) - Courtesy of [Marcelo Melo](https://github.com/marcelosdm) -- ![CN](/assets/flags/CN.png) [Chinese](./README.chinese.md) - Courtesy of [Matt Jin](https://github.com/mattjin) -- ![RU](/assets/flags/RU.png) [Russian](./README.russian.md) - Courtesy of [Alex Ivanov](https://github.com/contributorpw) -- ![PL](/assets/flags/PL.png) [Polish](./README.polish.md) - Courtesy of [Michal Biesiada](https://github.com/mbiesiad) -- ![JA](/assets/flags/JA.png) [Japanese](./README.japanese.md) - Courtesy of [Yuki Ota](https://github.com/YukiOta), [Yuta Azumi](https://github.com/YA21) +- ![BR](./assets/flags/BR.png) [Brazilian Portuguese](./README.brazilian-portuguese.md) - Courtesy of [Marcelo Melo](https://github.com/marcelosdm) +- ![CN](./assets/flags/CN.png) [Chinese](./README.chinese.md) - Courtesy of [Matt Jin](https://github.com/mattjin) +- ![RU](./assets/flags/RU.png) [Russian](./README.russian.md) - Courtesy of [Alex Ivanov](https://github.com/contributorpw) +- ![PL](./assets/flags/PL.png) [Polish](./README.polish.md) - Courtesy of [Michal Biesiada](https://github.com/mbiesiad) +- ![JA](./assets/flags/JA.png) [Japanese](./README.japanese.md) - Courtesy of [Yuki Ota](https://github.com/YukiOta), [Yuta Azumi](https://github.com/YA21) +- ![EU](./assets/flags/EU.png) [Basque](README.basque.md) - Courtesy of [Ane Diaz de Tuesta](https://github.com/anediaz) & Joxefe Diaz de Tuesta ### 翻訳(進行中) -- ![FR](/assets/flags/FR.png) [French](https://github.com/gaspaonrocks/nodebestpractices/blob/french-translation/README.french.md) ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/129)) -- ![HE](/assets/flags/HE.png) Hebrew ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/156)) -- ![KR](/assets/flags/KR.png) [Korean](README.korean.md) - Courtesy of [Sangbeom Han](https://github.com/uronly14me) ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/94)) -- ![ES](/assets/flags/ES.png) [Spanish](https://github.com/goldbergyoni/nodebestpractices/blob/spanish-translation/README.spanish.md) ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/95)) -- ![TR](/assets/flags/TR.png) Turkish ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/139)) +- ![FR](./assets/flags/FR.png) [French](https://github.com/gaspaonrocks/nodebestpractices/blob/french-translation/README.french.md) ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/129)) +- ![HE](./assets/flags/HE.png) Hebrew ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/156)) +- ![KR](./assets/flags/KR.png) [Korean](README.korean.md) - Courtesy of [Sangbeom Han](https://github.com/uronly14me) ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/94)) +- ![ES](./assets/flags/ES.png) [Spanish](https://github.com/goldbergyoni/nodebestpractices/blob/spanish-translation/README.spanish.md) ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/95)) +- ![TR](./assets/flags/TR.png) Turkish ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/139))

@@ -1286,7 +1286,7 @@ CMD [ "node", "dist/app.js" ] ステアリングコミッティーのメンバーをご紹介します。このプロジェクトのガイダンスと将来の方向性を提供するために協力してくださっている方々です。さらに、コミッティーの各メンバーは、[GitHub プロジェクト](https://github.com/goldbergyoni/nodebestpractices/projects)で管理されているプロジェクトをリードしています。 - + [Yoni Goldberg](https://github.com/goldbergyoni) @@ -1296,7 +1296,7 @@ CMD [ "node", "dist/app.js" ]
- + [Bruno Scheufler](https://github.com/BrunoScheufler) @@ -1305,7 +1305,7 @@ CMD [ "node", "dist/app.js" ]
- + [Kyle Martin](https://github.com/js-kyle) @@ -1315,7 +1315,7 @@ CMD [ "node", "dist/app.js" ]
- + [Kevyn Bruyere](https://github.com/kevynb) @@ -1326,14 +1326,14 @@ Ops や自動化に関心のあるフルスタックデベロッパー。 ### ステアリングコミッティー・エメリティ - + [Sagir Khan](https://github.com/sagirk) -JavaScript とそのエコシステム(React、Node.js、TypeScript、GraphQL、MongoDBなど、システムのあらゆるレイヤーで JS/JSON が関係するものであるなら何でも)の専門家。世界で最も認知されているブランドのために Web プラットフォームを利用してプロダクトを構築しています。Node.js ファウンデーションの個人メンバー。 +JavaScript とそのエコシステム(React、Node.js、TypeScript、GraphQL、MongoDB など、システムのあらゆるレイヤーで JS/JSON が関係するものであるなら何でも)の専門家。世界で最も認知されているブランドのために Web プラットフォームを利用してプロダクトを構築しています。Node.js ファウンデーションの個人メンバー。
@@ -1341,21 +1341,22 @@ JavaScript とそのエコシステム(React、Node.js、TypeScript、GraphQL すべてのコラボレーターの方々に感謝いたします! 🙏 -私たちのコラボレーターは、新たなベストプラクティスの提案やイシューの優先順位付け、プルリクエストのレビューなどその他多くのことを通じて、定期的にこのリポジトリに貢献してくださっているメンバーの方々です。多くの人々がより良い Node.js アプリケーションを構築できるように導く私たちをサポートすることにもし興味があるのであれば、[貢献ガイドライン](/.operations/CONTRIBUTING.md)をお読み下さい🎉 +私たちのコラボレーターは、新たなベストプラクティスの提案やイシューの優先順位付け、プルリクエストのレビューなどその他多くのことを通じて、定期的にこのリポジトリに貢献してくださっているメンバーの方々です。多くの人々がより良い Node.js アプリケーションを構築できるように導く私たちをサポートすることにもし興味があるのであれば、[貢献ガイドライン](./.operations/CONTRIBUTING.md)をお読み下さい 🎉 -| | | +| | | | :---------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------: | | [Ido Richter (Founder)](https://github.com/idori) | [Keith Holliday](https://github.com/TheHollidayInn) | ### コラボレーター・エメリティ -| | +| | | :-------------------------------------------------------------------------------------------------------------------------: | | [Refael Ackermann](https://github.com/refack) |
## 貢献 + もしオープンソースに貢献したいと思ったことがあるのなら、いまがチャンスです! 詳細は[貢献ドキュメント](.operations/CONTRIBUTING.md)を参照してください。 ## 貢献メンバー ✨ @@ -1366,156 +1367,259 @@ JavaScript とそのエコシステム(React、Node.js、TypeScript、GraphQL - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

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

🌍
Kevin Rambaud
Kevin Rambaud

🖋
Michael Fine
Michael Fine

🖋
Shreya Dahal
Shreya Dahal

🖋
Matheus Cruz Rocha
Matheus Cruz Rocha

🖋
Yog Mehta
Yog Mehta

🖋
Kudakwashe Paradzayi
Kudakwashe Paradzayi

🖋
t1st3
t1st3

🖋
mulijordan1976
mulijordan1976

🖋
Matan Kushner
Matan Kushner

🖋
Fabio Hiroki
Fabio Hiroki

🖋
James Sumners
James Sumners

🖋
Dan Gamble
Dan Gamble

🖋
PJ Trainor
PJ Trainor

🖋
Remek Ambroziak
Remek Ambroziak

🖋
Yoni Jah
Yoni Jah

🖋
Misha Khokhlov
Misha Khokhlov

🖋
Evgeny Orekhov
Evgeny Orekhov

🖋
-
-

🖋
Isaac Halvorson
Isaac Halvorson

🖋
Vedran Karačić
Vedran Karačić

🖋
lallenlowe
lallenlowe

🖋
Nathan Wells
Nathan Wells

🖋
Paulo Reis
Paulo Reis

🖋
syzer
syzer

🖋
David Sancho
David Sancho

🖋
Robert Manolea
Robert Manolea

🖋
Xavier Ho
Xavier Ho

🖋
Aaron
Aaron

🖋
Jan Charles Maghirang Adona
Jan Charles Maghirang Adona

🖋
Allen
Allen

🖋
Leonardo Villela
Leonardo Villela

🖋
Michał Załęcki
Michał Załęcki

🖋
Chris Nicola
Chris Nicola

🖋
Alejandro Corredor
Alejandro Corredor

🖋
cwar
cwar

🖋
Yuwei
Yuwei

🖋
Utkarsh Bhatt
Utkarsh Bhatt

🖋
Duarte Mendes
Duarte Mendes

🖋
Jason Kim
Jason Kim

🖋
Mitja O.
Mitja O.

🖋
Sandro Miguel Marques
Sandro Miguel Marques

🖋
Gabe
Gabe

🖋
Ron Gross
Ron Gross

🖋
Valeri Karpov
Valeri Karpov

🖋
Sergio Bernal
Sergio Bernal

🖋
Nikola Telkedzhiev
Nikola Telkedzhiev

🖋
Vitor Godoy
Vitor Godoy

🖋
Manish Saraan
Manish Saraan

🖋
Sangbeom Han
Sangbeom Han

🖋
blackmatch
blackmatch

🖋
Joe Reeve
Joe Reeve

🖋
Ryan Busby
Ryan Busby

🖋
Iman Mohamadi
Iman Mohamadi

🖋
Sergii Paryzhskyi
Sergii Paryzhskyi

🖋
Kapil Patel
Kapil Patel

🖋
迷渡
迷渡

🖋
Hozefa
Hozefa

🖋
Ethan
Ethan

🖋
Sam
Sam

🖋
Arlind
Arlind

🖋
Teddy Toussaint
Teddy Toussaint

🖋
Lewis
Lewis

🖋
Gabriel Lidenor
Gabriel Lidenor

🖋
Roman
Roman

🖋
Francozeira
Francozeira

🖋
Invvard
Invvard

🖋
Rômulo Garofalo
Rômulo Garofalo

🖋
Tho Q Luong
Tho Q Luong

🖋
Burak Shen
Burak Shen

🖋
Martin Muzatko
Martin Muzatko

🖋
Jared Collier
Jared Collier

🖋
Hilton Meyer
Hilton Meyer

🖋
ChangJoo Park(박창주)
ChangJoo Park(박창주)

🖋
Masahiro Sakaguchi
Masahiro Sakaguchi

🖋
Keith Holliday
Keith Holliday

🖋
coreyc
coreyc

🖋
Maximilian Berkmann
Maximilian Berkmann

🖋
Douglas Mariano Valero
Douglas Mariano Valero

🖋
Marcelo Melo
Marcelo Melo

🖋
Mehmet Perk
Mehmet Perk

🖋
ryan ouyang
ryan ouyang

🖋
Shabeer
Shabeer

🖋
Eduard Kyvenko
Eduard Kyvenko

🖋
Deyvison Rocha
Deyvison Rocha

🖋
George Mamer
George Mamer

🖋
Konstantinos Leimonis
Konstantinos Leimonis

🖋
Oliver Lluberes
Oliver Lluberes

🌍
Tien Do
Tien Do

🖋
Ranvir Singh
Ranvir Singh

🖋
Vadim Nicolaev
Vadim Nicolaev

🖋 🌍
German Gamboa Gonzalez
German Gamboa Gonzalez

🖋
Hafez
Hafez

🖋
Chandiran
Chandiran

🖋
VinayaSathyanarayana
VinayaSathyanarayana

🖋
Kim Kern
Kim Kern

🖋
Kenneth Freitas
Kenneth Freitas

🖋
songe
songe

🖋
Kirill Shekhovtsov
Kirill Shekhovtsov

🖋
Serge
Serge

🖋
keyrwinz
keyrwinz

🖋
Dmitry Nikitenko
Dmitry Nikitenko

🖋
bushuai
bushuai

👀 🖋
Benjamin Gruenbaum
Benjamin Gruenbaum

🖋
Ezequiel
Ezequiel

🌍
Juan José Rodríguez
Juan José Rodríguez

🌍
Or Bin
Or Bin

🖋
Andreo Vieira
Andreo Vieira

🖋
Michael Solomon
Michael Solomon

🖋
Jimmy Callin
Jimmy Callin

🖋
Siddharth
Siddharth

🖋
Ryan Smith
Ryan Smith

🖋
Tom Boettger
Tom Boettger

🖋
Joaquín Ormaechea
Joaquín Ormaechea

🌍
dfrzuz
dfrzuz

🌍
Victor Homyakov
Victor Homyakov

🖋
Josh
Josh

🖋 🛡️
Alec Francis
Alec Francis

🖋
arjun6610
arjun6610

🖋
Jan Osch
Jan Osch

🖋
Thiago Rotondo Sampaio
Thiago Rotondo Sampaio

🌍
Alexsey
Alexsey

🖋
Luis A. Acurero
Luis A. Acurero

🌍
Lucas Romano
Lucas Romano

🌍
Denise Case
Denise Case

🖋
Nick Ribal
Nick Ribal

🖋 👀
0xflotus
0xflotus

🖋
Jonathan Chen
Jonathan Chen

🖋
Dilan Srilal
Dilan Srilal

🖋
vladthelittleone
vladthelittleone

🌍
Nik Osvalds
Nik Osvalds

🖋
Daniel Kiss
Daniel Kiss

📖
Forresst
Forresst

🖋
Jonathan Svenheden
Jonathan Svenheden

🖋
AustrisC
AustrisC

🖋
kyeongtae kim
kyeongtae kim

🌍
007
007

🖋
Ane Diaz de Tuesta
Ane Diaz de Tuesta

🌍 🖋
YukiOta
YukiOta

🌍
Frazer Smith
Frazer Smith

🖋
Raz Luvaton
Raz Luvaton

🖋
Yuta Azumi
Yuta Azumi

🖋
andrewjbarbour
andrewjbarbour

🖋
mr
mr

🖋
Aleksandar
Aleksandar

🖋
Owl
Owl

🖋
Yedidya Schwartz
Yedidya Schwartz

🖋 💡
ari
ari

🖋
Thomas König
Thomas König

🖋
Kalle Lämsä
Kalle Lämsä

🖋
Wyatt
Wyatt

🖋
KHADIR Tayeb
KHADIR Tayeb

🖋
Shankar Regmi
Shankar Regmi

🖋
Shubham
Shubham

🖋
Lucas Alves
Lucas Alves

🖋
Benjamin
Benjamin

🖋
Yeoh Joer
Yeoh Joer

🖋
Miigon
Miigon

🖋
Rostislav Bogorad
Rostislav Bogorad

🖋
Flouse
Flouse

🖋
Tarantini Pereira
Tarantini Pereira

🖋
Kazuki Matsuo
Kazuki Matsuo

🖋
Adam Smith
Adam Smith

🖋
Dohyeon Ko
Dohyeon Ko

🖋
Vladislav Legkov
Vladislav Legkov

🖋
Kerollos Magdy
Kerollos Magdy

🖋
Erez Lieberman
Erez Lieberman

🖋
Breno Macedo
Breno Macedo

🖋
Fernando Flores
Fernando Flores

🌍
Rafael Brito
Rafael Brito

🌍
Emiliano Peralta
Emiliano Peralta

🌍
Shin, SJ
Shin, SJ

🖋
Benjamin Forster
Benjamin Forster

🖋
Daniele Fedeli
Daniele Fedeli

🖋
djob195
djob195

🖋
antspk
antspk

🖋
정진영
정진영

🖋
kkk-cashwalk
kkk-cashwalk

🖋
apainintheneck
apainintheneck

🖋
Fajar Budhi Iswanda
Fajar Budhi Iswanda

🖋
이주호
이주호

🖋
Singh
Singh

🖋
Alex Dumitru
Alex Dumitru

🖋
Anton Lykhatskyi
Anton Lykhatskyi

🖋
sangwonlee
sangwonlee

🖋
Eugenio Berretta
Eugenio Berretta

🖋
soranakk
soranakk

🖋
고준영
고준영

🖋 💻
Guilherme Portella
Guilherme Portella

🖋
André Esser
André Esser

🖋
Scc
Scc

🌍
Mauro Accornero
Mauro Accornero

🖋
no-yan
no-yan

🖋
- + + diff --git a/README.korean.md b/README.korean.md index 726206ad7..a29f23351 100644 --- a/README.korean.md +++ b/README.korean.md @@ -3,18 +3,18 @@ # Node.js 모범 사례

- Node.js Best Practices + Node.js Best Practices


- 86 items Last update: March, 2020 Updated for Node 13.1.0 + 86 items Last update: March, 2020 Updated for Node 13.1.0

-[![nodepractices](/assets/images/twitter-s.png)](https://twitter.com/nodepractices/) **트위터에서 팔로우 하세요!** [**@nodepractices**](https://twitter.com/nodepractices/) +[![nodepractices](./assets/images/twitter-s.png)](https://twitter.com/nodepractices/) **트위터에서 팔로우 하세요!** [**@nodepractices**](https://twitter.com/nodepractices/)
@@ -22,7 +22,7 @@
-다른 언어로 읽기: [![CN](/assets/flags/CN.png)**CN**](/README.chinese.md), [![BR](/assets/flags/BR.png)**BR**](/README.brazilian-portuguese.md), [![RU](/assets/flags/RU.png)**RU**](/README.russian.md) [(![ES](/assets/flags/ES.png)**ES**, ![FR](/assets/flags/FR.png)**FR**, ![HE](/assets/flags/HE.png)**HE**, ![KR](/assets/flags/KR.png)**KR** and ![TR](/assets/flags/TR.png)**TR** 은 작업중입니다!)](#translations) +다른 언어로 읽기: [![CN](./assets/flags/CN.png)**CN**](./README.chinese.md), [![BR](./assets/flags/BR.png)**BR**](./README.brazilian-portuguese.md), [![RU](./assets/flags/RU.png)**RU**](./README.russian.md), [![EU](./assets/flags/EU.png)**EU**](./README.basque.md) [(![ES](./assets/flags/ES.png)**ES**, ![FR](./assets/flags/FR.png)**FR**, ![HE](./assets/flags/HE.png)**HE**, ![KR](./assets/flags/KR.png)**KR** and ![TR](./assets/flags/TR.png)**TR** 은 작업중입니다!)](#translations)
@@ -30,19 +30,19 @@ # 최근 모범사례와 뉴스 -- **:tada: Node.js 모범사례가 4만 별에 도달했습니다**: 이 프로젝트가 지금 여기까지 올 수 있도록 도와주신 모든 협력자분들께 감사드립니다. 앞으로도 계속 늘어나는 Node.js 모범사례들을 추가하여 더욱더 확장시킬 계획입니다. +- **![FR](./assets/flags/FR.png) 프랑스어 번역!1! :** 우리의 국제 가이드에 합류한 최신 번역은 프랑스어입니다. Bienvenue(어서오세요.) -- **:rocket: 새로운 모범사례 둘 추가**: 그동안 열심히 만든 dependency state를 production 환경에서 미리 볼 수 있는 [npm ci 사용](https://github.com/goldbergyoni/nodebestpractices#-519-install-your-packages-with-npm-ci) 관련 부분과, [미들웨어 격리 테스트](https://github.com/goldbergyoni/nodebestpractices#-413-test-your-middlewares-in-isolation)에 관한 새로운 모범사례들을 두 개 추가했습니다. +- **🇯🇵 Japanese translation:** 우리 가이드는 이제 일본어로도 번역됩니다! 뛰어난 [YukiOta](https://github.com/YukiOta)와 [Yuta Azumi](https://github.com/YA21)의 제공입니다. -- **:whale: Node.js + Docker 모범사례**: dockerized 된 Node.js 애플리케이션 관련 모범사례 [아이디어 수집](https://github.com/goldbergyoni/nodebestpractices/issues/620)을 개시합니다. 그 외에 다른 모범사례가 있다면 주저말고 대화에 참여해주세요! +- **🎊 60,000 stars!**: 우리 리포지토리는 60,100명의 개발자에게 별을 받고 신뢰를 얻었습니다. 말문이 막힐 정도입니다.

-# 어서오세요! 먼저 이 3가지를 알아두세요: +# 어서오세요! 먼저 이 3가지를 알아두세요 **1. 이 문서를 읽는 것은 베스트 Node.js 문서 수십개를 읽는 것과 같습니다. -** 이 문서는 Node.js 의 가장 일반적인 Best Practice 모범사례들을 모은 요약집 및 큐레이션입니다. -**2. 가장 큰 모음집이며, 매주 성장하고 있습니다. -** 현재 80개 이상의 모범사례들과 스타일 가이드 및 아키텍처 관련 팁들을 제공하고 있습니다. 이 문서를 계속 갱신하는 새로운 이슈들과 PR들이 매일 나오고 있습니다. 이 문서의 잘못된 코드를 고치거나 새로운 아이디어들을 제안하는 것은 매우 환영합니다. [글쓰기 지침은 여기](/.operations/writing-guidelines.md)서 확인하세요 +**2. 가장 큰 모음집이며, 매주 성장하고 있습니다. -** 현재 80개 이상의 모범사례들과 스타일 가이드 및 아키텍처 관련 팁들을 제공하고 있습니다. 이 문서를 계속 갱신하는 새로운 이슈들과 PR들이 매일 나오고 있습니다. 이 문서의 잘못된 코드를 고치거나 새로운 아이디어들을 제안하는 것은 매우 환영합니다. [글쓰기 지침은 여기](./.operations/writing-guidelines.md)서 확인하세요 **3. 항목 대부분은 추가적인 정보가 있습니다 -** 항목 옆쪽에 존재하는 **🔗자세히 보기** 링크에서 코드 예제, 참조 블로그 또는 기타 정보들을 확인 할 수 있습니다. @@ -68,7 +68,7 @@ **그렇게 하지 않을 경우:** 새로운 기능을 작성하는 개발자가 변경사항이 어떤 영향을 미치는지 알기가 힘들면 의존하고 있는 다른 컴포넌트를 망칠까 두려워 하게 되고, 이는 배포를 더 느리고 더 불안전하게 만든다. 비지니스 단위가 나눠져 있지 않으면 확장(scale-out)하기도 쉽지 않게 된다. -🔗 [**자세히 보기: 컴포넌트로 구조화하기**](/sections/projectstructre/breakintcomponents.korean.md) +🔗 [**자세히 보기: 컴포넌트로 구조화하기**](./sections/projectstructre/breakintcomponents.korean.md)

@@ -78,7 +78,7 @@ **그렇게 하지 않을 경우:** 웹 객체와 다른 계층을 뒤섞은 앱은 테스트 코드, CRON 작업이나 Express가 아닌 다른 곳에서의 접근을 불가능하게 한다. -🔗 [**자세히 보기: 앱을 계층화하기**](/sections/projectstructre/createlayers.korean.md) +🔗 [**자세히 보기: 앱을 계층화하기**](./sections/projectstructre/createlayers.korean.md)

@@ -88,7 +88,7 @@ **그렇게 하지 않을 경우:** 당신 자신만의 배포 및 종속 바퀴(dependency wheel)를 새로이 발명해야 할 것이다. -🔗 [**자세히 보기: 기능으로 구조화 하기**](/sections/projectstructre/wraputilities.korean.md) +🔗 [**자세히 보기: 기능으로 구조화 하기**](./sections/projectstructre/wraputilities.korean.md)

@@ -98,7 +98,7 @@ **그렇게 하지 않을 경우:** HTTP 요청으로만 API 테스트가 가능하게 된다 (커버리지 보고서를 생성하기가 더 느려지고 훨씬 힘들어진다). 수백줄의 코드를 하나의 파일에서 관리하는 것이 크게 즐겁지는 않을 것이다. -🔗 [**자세히 보기: Express를 'app'과 'server'로 분리하기**](/sections/projectstructre/separateexpress.korean.md) +🔗 [**자세히 보기: Express를 'app'과 'server'로 분리하기**](./sections/projectstructre/separateexpress.korean.md)

@@ -108,7 +108,7 @@ **그렇게 하지 않을 경우:** 위의 구성 요구사항 중 하나라도 만족시키지 못한다면 개발팀이나 데브옵스팀을 늪으로 몰아갈 수 있다. 십중팔구 둘 다. -🔗 [**자세히 보기: 구성 모범 사례**](/sections/projectstructre/configguide.korean.md) +🔗 [**자세히 보기: 구성 모범 사례**](./sections/projectstructre/configguide.korean.md)


@@ -122,7 +122,7 @@ **그렇게 하지 않을 경우:** Node.js의 function(err, response) 콜백 스타일은 에러 처리와 일반 코드의 혼합, 코드의 과도한 중첩, 어색한 코딩 패턴 때문에 유지보수가 불가능한 코드로 가는 확실한 길이다. -🔗 [**자세히 보기: 콜백 피하기**](/sections/errorhandling/asyncerrorhandling.korean.md) +🔗 [**자세히 보기: 콜백 피하기**](./sections/errorhandling/asyncerrorhandling.korean.md)

@@ -132,7 +132,7 @@ **그렇게 하지 않을 경우:** 일부 컴포넌트를 호출할때 어떤 에러의 타입이 반환될지 불확실해져서 적절한 에러처리가 매우 어려워진다. 게다가 임의적인 타입으로 에러를 나타내는 것은 스택 정보(stack trace)와 같은 중요한 에러 관련 정보 손실을 일으킬 수 있다! -🔗 [**자세히 보기: 내장된 Error 객체 사용하기**](/sections/errorhandling/useonlythebuiltinerror.korean.md) +🔗 [**자세히 보기: 내장된 Error 객체 사용하기**](./sections/errorhandling/useonlythebuiltinerror.korean.md)

@@ -142,7 +142,7 @@ **그렇게 하지 않을 경우:** 에러가 날 때마다 어플리케이션을 다시 시작할수도 있지만, 왜 사소하고 예측가능한 동작상의 오류때문에 5000명의 온라인 사용자를 다운시키는 것인가? 그 반대도 이상적이지 않다. 알수없는 이슈 (프로그래머 에러)가 났는데 어플리케이션을 그대로 두는 것은 예측이 불가능한 반응을 일으킬 수 있다. 두 가지를 구별하면 요령있는 처신과 주어진 상황에 따른 균형잡힌 접근이 가능하다. -🔗 [**자세히 보기: 동작상의 에러와 프로그래머 에러**](/sections/errorhandling/operationalvsprogrammererror.korean.md) +🔗 [**자세히 보기: 동작상의 에러와 프로그래머 에러**](./sections/errorhandling/operationalvsprogrammererror.korean.md)

@@ -152,7 +152,7 @@ **그렇게 하지 않을 경우:** 한 곳에서 에러를 처리하지 않는 것은 코드 중복과 부적절한 에러처리로 이어진다. -🔗 [**자세히 보기: 중앙집중적으로 에러 처리하기**](/sections/errorhandling/centralizedhandling.korean.md) +🔗 [**자세히 보기: 중앙집중적으로 에러 처리하기**](./sections/errorhandling/centralizedhandling.korean.md)

@@ -162,7 +162,7 @@ **그렇게 하지 않을 경우:** API 클라이언트는 알수 없는 에러로 인한 충돌 후에 재시작을 결정할수도 있을 것이다. 참고로 당신의 API를 호출한 사람이 당신 자신 일수도 있다 (마이크로서비스 환경에서는 아주 일반적이다). -🔗 [**자세히 보기: Swagger에서 에러 문서화하기**](/sections/errorhandling/documentingusingswagger.korean.md) +🔗 [**자세히 보기: Swagger에서 에러 문서화하기**](./sections/errorhandling/documentingusingswagger.korean.md)

@@ -172,7 +172,7 @@ **그렇게 하지 않을 경우:** 익숙치 않은 예외가 발생하면 일부 객체가 오류 상태 (예를 들어 전역적으로 사용되지만 내부 오류로 인해 이벤트를 더이상 내보내지 않는 event emitter)라서 향후의 모든 요청을 실패시키거나 미친것처럼 작동할 수 있다. -🔗 [**자세히 보기: 프로세스 중단하기**](/sections/errorhandling/shuttingtheprocess.korean.md) +🔗 [**자세히 보기: 프로세스 중단하기**](./sections/errorhandling/shuttingtheprocess.korean.md)

@@ -182,7 +182,7 @@ **그렇게 하지 않을 경우:** 로그 검색 도구나 제대로 된 로그 뷰어 없이 console.log을 훑어보거나 복잡하게 꼬인 텍스트 파일을 일일이 읽어 보는 것은 야근을 부를 수 있다. -🔗 [**자세히 보기: 발전된 로거를 사용하기**](/sections/errorhandling/usematurelogger.korean.md) +🔗 [**자세히 보기: 발전된 로거를 사용하기**](./sections/errorhandling/usematurelogger.korean.md)

@@ -192,7 +192,7 @@ **그렇게 하지 않을 경우:** 자동이든 수동이든 테스트가 없다면 당신은 당신의 코드가 올바른 에러를 반환하는지 믿지 못할 것이다. 의미 있는 에러가 없다면 에러 처리도 없는 것이다. -🔗 [**자세히 보기: 에러 흐름 테스트하기**](/sections/errorhandling/testingerrorflows.korean.md) +🔗 [**자세히 보기: 에러 흐름 테스트하기**](./sections/errorhandling/testingerrorflows.korean.md)

@@ -202,7 +202,7 @@ **그렇게 하지 않을 경우:** API의 성능과 다운타임을 측정하기위해 많은 노력을 들여야 할지도 모른다. 아마 당신은 실제 상황에서 어떤 코드 부분이 가장 느린지, 그것이 UX에 어떻게 영향을 미칠지 절대 알수없을 것이다. -🔗 [**자세히 보기: APM 제품 사용하기**](/sections/errorhandling/apmproducts.korean.md) +🔗 [**자세히 보기: APM 제품 사용하기**](./sections/errorhandling/apmproducts.korean.md)

@@ -212,7 +212,7 @@ **그렇게 하지 않을 경우:** 당신의 에러는 삼켜지고 어떤 흔적도 남기지 않을 것이다. 걱정할 것이 없긴 하다. -🔗 [**자세히 보기: 처리되지 않은 promise 거부 잡기**](/sections/errorhandling/catchunhandledpromiserejection.korean.md) +🔗 [**자세히 보기: 처리되지 않은 promise 거부 잡기**](./sections/errorhandling/catchunhandledpromiserejection.korean.md)

@@ -222,7 +222,7 @@ **그렇게 하지 않을 경우:** 이런 상황을 생각해보자. 당신의 함수가 "Discount"라는 숫자를 받아야하는데 요청하는 사람이 넘겨주는 것을 깜빡했다. 그 후에 당신의 코드는 Discount!=0인지 아닌지 체크한다(사실 허용된 Discount의 값은 0보다 커야 한다). 그러면 사용자가 할인을 받게될 것이다. 보이는가? 엄청나게 지저분한 버그이다. -🔗 [**자세히 보기: 빠르게 실패하기**](/sections/errorhandling/failfast.korean.md) +🔗 [**자세히 보기: 빠르게 실패하기**](./sections/errorhandling/failfast.korean.md)


@@ -279,7 +279,7 @@ function someFunction() **그렇게 하지 않을 경우:** 이전 섹션에서 본것처럼 자바스크립트의 인터프리터는 세미콜론이 없으면 자동으로 문장의 끝에 세미콜론을 붙이거나, 문장이 끝났어야 함에도 끝났다고 인지하지 못하여 의도되지 않은 결과를 야기할 수 있다. 대부분의 의도하지 않은 에러들은 assignment를 사용하고 imediate invoked function expression을 사용하는 것을 피함으로써 예방할 수 있다. -### 코드 예제 +### 3.4 코드 예제 ```javascript // 좋은 예 @@ -325,7 +325,7 @@ const count = 2 // 2()를 호출하려 하지만, 2는 함수가 아니다 ## ![✔] 3.6 변수, 상수, 함수, 클래스의 명명 규칙(naming convention) -**핵심요약:** 상수와 변수 함수를 명명할때는 **_lowerCamelCase_** 를 사용하고 클래스를 명명 할때는 **_UpperCamelCase_**(첫 글자 대문자)를 사용하라. 이것은 일반 변수/함수와 인스턴스로 만들어야 하는 클래스를 구분하는데 도움을 것이다. 설명이 포함된 이름을 사용하되 이름을 짧게 유지하도록 해라. +**핵심요약:** 상수와 변수 함수를 명명할때는 **_lowerCamelCase_** 를 사용하고 클래스를 명명 할때는 **_UpperCamelCase_**(첫 글자 대문자)를 사용하라. 이것은 일반 변수/함수와 인스턴스로 만들어야 하는 클래스를 구분하는데 도움을 것이다. 설명이 포함된 이름을 사용하되 이름을 짧게 유지하도록 해라. **그렇게 하지 않을 경우:** 자바스크립트는 먼저 인스턴스로 만들지 않고 직접 생성자("Class")를 호출할 수 있는 세계 유일의 언어이다. 그러므로 클래스와 함수생성자는 UpperCamelCase를 통해 구분된다. @@ -337,11 +337,11 @@ class SomeClassExample {} // 상수명은 const 키워드와 lowerCamelCase 사용 const config = { - key: 'value' + key: "value", }; // 변수와 함수 이름은 lowerCamelCase 사용 -let someVariableExample = 'value'; +let someVariableExample = "value"; function doSomething() {} ``` @@ -371,16 +371,16 @@ function doSomething() {} **그렇게 하지 않을 경우:** 파일 내부의 구조 혹은 서명을 변경하면 클라이언트와의 인터페이스가 손상될 수 있다. -### 코드 예제 +### 3.9 코드 예제 ```javascript // 좋은 예 -module.exports.SMSProvider = require('./SMSProvider'); -module.exports.SMSNumberResolver = require('./SMSNumberResolver'); +module.exports.SMSProvider = require("./SMSProvider"); +module.exports.SMSNumberResolver = require("./SMSNumberResolver"); // 나쁜 예 -module.exports.SMSProvider = require('./SMSProvider/SMSProvider.js'); -module.exports.SMSNumberResolver = require('./SMSNumberResolver/SMSNumberResolver.js'); +module.exports.SMSProvider = require("./SMSProvider/SMSProvider.js"); +module.exports.SMSNumberResolver = require("./SMSNumberResolver/SMSNumberResolver.js"); ```

@@ -391,21 +391,21 @@ module.exports.SMSNumberResolver = require('./SMSNumberResolver/SMSNumberResolve **그렇게 하지 않을 경우:** `==`으로 비교하는 경우 같지 않은 변수가 true로 반환 될 수있다. -### 코드 예제 +### 3.10 코드 예제 ```javascript -'' == '0' // false -0 == '' // true -0 == '0' // true +"" == "0"; // false +0 == ""; // true +0 == "0"; // true -false == 'false' // false -false == '0' // true +false == "false"; // false +false == "0"; // true -false == undefined // false -false == null // false -null == undefined // true +false == undefined; // false +false == null; // false +null == undefined; // true -' \t\r\n ' == 0 // true +" \t\r\n " == 0; // true ``` 위의 모든 문장은 `===`를 사용했다면 false를 반환 했을것이다. @@ -448,10 +448,9 @@ null == undefined // true **핵심요약:** 코드 내부에 익숙하지 않은 QA 엔지니어들과 개발자들에게 따로 설명이 필요 없도록 requirement 계층에서 이미 자명하도록 해라. 무엇을 (unit under test), 어떤 환경에서, 어떤 결과를 예상하고 테스트 하는 것인지 테스트 이름에 명시해라. - **그렇게 하지 않을 경우:** 배포에 실패하였습니다, “프로덕트 추가” 라는 테스트가 실패했습니다. 이런 메시지를 보고 정확히 뭐가 잘못되었는지 알 수 있는가? -🔗 [**자세히 보기: Include 3 parts in each test name**](/sections/testingandquality/3-parts-in-name.md) +🔗 [**자세히 보기: Include 3 parts in each test name**](./sections/testingandquality/3-parts-in-name.md)

@@ -461,8 +460,7 @@ null == undefined // true **그렇게 하지 않을 경우:** 매일 하루종일 주요 코드를 읽는데 시간을 오래 쓰는 것도 모자라 간단해야하는 테스트 부분에도 열심히 머리를 써야 할 것이다. - -🔗 [**Read More: Structure tests by the AAA pattern**](/sections/testingandquality/aaa.md) +🔗 [**Read More: Structure tests by the AAA pattern**](./sections/testingandquality/aaa.md)

@@ -480,7 +478,7 @@ null == undefined // true **그렇게 하지 않을 경우:** 실패하는 테스트때문에 전개(deployment)가 중단되었다고 가정해 보자. 이제 팀원들은 소중한 시간을 조사하는데 소모한 뒤 슬픈 결론을 내릴 것이다: 시스템은 잘 작동하지만, 테스트간의 상호 간섭으로 빌드 실패. -🔗 [**자세히 보기: Avoid global test fixtures**](/sections/testingandquality/avoid-global-test-fixture.md) +🔗 [**자세히 보기: Avoid global test fixtures**](./sections/testingandquality/avoid-global-test-fixture.md)

@@ -530,7 +528,7 @@ null == undefined // true **그렇게 하지 않을 경우:** 아무리 반짝이는 새로나온 라이브러리나 최첨단 기능을 써봤자 코드 품질이 불량하면 버그와 성능은 못고친다 -🔗 [**자세히 보기: Refactoring!**](/sections/testingandquality/refactoring.md) +🔗 [**자세히 보기: Refactoring!**](./sections/testingandquality/refactoring.md)

@@ -540,15 +538,15 @@ null == undefined // true **그렇게 하지 않을 경우:** 잘 알려지지 않은 중소 솔루션 업체를 쓰다간 흔치 않은 고급 설정을 커스터마이징 해야할 때 막혀버릴 수도 있다. 하지만 반대로, Jenkins를 택하면 인프라를 수축하는데 소중한 시간을 다 빼앗길 수도 있다. -🔗 [**자세히 보기: Choosing CI platform**](/sections/testingandquality/citools.korean.md) +🔗 [**자세히 보기: Choosing CI platform**](./sections/testingandquality/citools.korean.md) ## ![✔] 4.13 미들웨어들은 격리시켜 테스트해라 **핵심요약:** 여러 요청에 걸친 막대한 로직을 미들웨어가 수용하는 경우, 웹 프레임워크 전체를 깨우지 않고 격리 상태로 테스트 할만한 가치가 있다. {req, res, next} 객체들을 스텁(stub)하여 염탐(spy)하면 쉽게 달성할 수 있다. -**그렇게 하지 않을 경우:** Express 미들웨어의 버그 === 거의 모든 요청의 버그 +**그렇게 하지 않을 경우:** Express 미들웨어의 버그 === 거의 모든 요청의 버그 -🔗 [**자세히 보기: Test middlewares in isolation**](/sections/testingandquality/test-middlewares.md) +🔗 [**자세히 보기: Test middlewares in isolation**](./sections/testingandquality/test-middlewares.md)


@@ -562,7 +560,7 @@ null == undefined // true **그렇게 하지 않을 경우:** 오류 === 고객의 실망. 간단하다 -🔗 [**자세히 보기: 모니터링!**](/sections/production/monitoring.md) +🔗 [**자세히 보기: 모니터링!**](./sections/production/monitoring.md)

@@ -572,7 +570,7 @@ null == undefined // true **그렇게 하지 않을 경우:** 이해하기 힘든 블랙박스가 되어버려서 필요한 정보를 추가하기 위해 모든 로그를 다시 작성하게 될것이다 -🔗 [**자세히 보기: Increase transparency using smart logging**](/sections/production/smartlogging.md) +🔗 [**자세히 보기: Increase transparency using smart logging**](./sections/production/smartlogging.md)

@@ -582,17 +580,17 @@ null == undefined // true **그렇게 하지 않을 경우:** 불쌍한 싱글 스레드가 어플리케이션의 코어를 처리하는 대신 인프라 작업을 수행하느라 바빠져서 성능이 저하될 것이다 -🔗 [**자세히 보기: 가능한 모든 것들(예: gzip, SSL)을 reverse proxy에 위임하라**](/sections/production/delegatetoproxy.md) +🔗 [**자세히 보기: 가능한 모든 것들(예: gzip, SSL)을 reverse proxy에 위임하라**](./sections/production/delegatetoproxy.md)

## ![✔] 5.4. 의존성을 잠궈라(Lock dependencies) -**핵심요약:** 코드는 모든 환경에서 동일해야하지만 놀랍게도 npm을 사용하면 기본적으로 환경간에 종속성이 달라질 수 있는데, 다양한 환경에서 패키지를 설치하면 패키지의 최신 패치 버전을 가져오기 때문이다. npm config 파일인 .npmrc를 사용하여이 문제를 극복해라. 각 환경에 각 패키지의 최신 버전이 아닌 정확한 버전을 저장하도록 알려준다. 또는 세밀하게 제어하려면 `npm shrinkwrap`을 사용하라. \* 업데이트 : NPM5부터는 종속성이 기본적으로 잠겨 있다. 새로운 패키지 관리자인 Yarn도 기본적으로 잠겨 있다. +**핵심요약:** 코드는 모든 환경에서 동일해야하지만 놀랍게도 npm을 사용하면 기본적으로 환경간에 종속성이 달라질 수 있는데, 다양한 환경에서 패키지를 설치하면 패키지의 최신 패치 버전을 가져오기 때문이다. npm config 파일인 .npmrc를 사용하여이 문제를 극복해라. 각 환경에 각 패키지의 최신 버전이 아닌 정확한 버전을 저장하도록 알려준다. 또는 세밀하게 제어하려면 `npm shrinkwrap`을 사용하라. \* 업데이트 : NPM5부터는 종속성이 기본적으로 잠겨 있다. 새로운 패키지 관리자인 Yarn도 기본적으로 잠겨 있다. **그렇게 하지 않을 경우:** QA팀은 코드를 철저히 테스트 했음에도 테스트 환경과는 다르게 작동하는 버전을 승인할 것이다. 심지어 같은 프로덕션 클러스터의 여러 서버가 서로 다른 코드를 실행할 수도 있다. -🔗 [**자세히 보기: Lock dependencies**](/sections/production/lockdependencies.md) +🔗 [**자세히 보기: Lock dependencies**](./sections/production/lockdependencies.md)

@@ -602,7 +600,7 @@ null == undefined // true **그렇게 하지 않을 경우:** 명확한 전략없이 수십 개의 인스턴스와 너무 많은 도구 (클러스터 관리, 도커, PM2)를 실행하면 데브옵스가 혼란을 겪을 수 있다 -🔗 [**자세히 보기: Guard process uptime using the right tool**](/sections/production/guardprocess.md) +🔗 [**자세히 보기: Guard process uptime using the right tool**](./sections/production/guardprocess.md)

@@ -612,7 +610,7 @@ null == undefined // true **그렇게 하지 않을 경우:** 앱이 사용 가능한 리소스 중 25%(!)에도 못 미치게 활용할 것이다. 일반적인 서버는 CPU 코어가 4개 이상임에도 Node를 기본형으로 배포하면 그 중 단 1 개만 사용하게 될것이다 (AWS beanstalk과 같은 PaaS 서비스 사용해도 마찬가지) -🔗 [**자세히 보기: 모든 CPU를 활용하라**](/sections/production/utilizecpu.md) +🔗 [**자세히 보기: 모든 CPU를 활용하라**](./sections/production/utilizecpu.md)

@@ -622,7 +620,7 @@ null == undefined // true **그렇게 하지 않을 경우:** 단지 서버 진단을 목적으로 일부 정보를 추출하기 위하여 상용서버에 코드를 배포하는 "진단용 배포"를 자주 수행하고 있게 될 것이다 -🔗 [**자세히 보기: Create a ‘maintenance endpoint’**](/sections/production/createmaintenanceendpoint.md) +🔗 [**자세히 보기: Create a ‘maintenance endpoint’**](./sections/production/createmaintenanceendpoint.md)

@@ -632,7 +630,7 @@ null == undefined // true **그렇게 하지 않을 경우:** API 성능 및 가동 중지 시간을 측정하는 데 많은 노력을 기울임에도 실전에서 가장 느린 코드 부분이 어느것인지, 그리고 이것이 UX에 미치는 영향을 알지 못할 것이다 -🔗 [**자세히 보기: Discover errors and downtime using APM products**](/sections/production/apmproducts.md) +🔗 [**자세히 보기: Discover errors and downtime using APM products**](./sections/production/apmproducts.md)

@@ -642,7 +640,7 @@ null == undefined // true **그렇게 하지 않을 경우:** 세계 최고의 IT/DevOps 전문가도 형편없이 쓰여진 코드로 이루어진 시스템은 구하지 못한다 -🔗 [**자세히 보기: Make your code production-ready**](/sections/production/productioncode.md) +🔗 [**자세히 보기: Make your code production-ready**](./sections/production/productioncode.md)

@@ -652,7 +650,7 @@ null == undefined // true **그렇게 하지 않을 경우:** [월마트](https://www.joyent.com/blog/walmart-node-js-memory-leak)에서 일어났던 것처럼 메모리가 하루에 수백 메가바이트씩 누수 될 수 있다 -🔗 [**자세히 보기: 메모리 사용량 측정 및 보호**](/sections/production/measurememory.md) +🔗 [**자세히 보기: 메모리 사용량 측정 및 보호**](./sections/production/measurememory.md)

@@ -662,7 +660,7 @@ null == undefined // true **그렇게 하지 않을 경우:** 단일 노드 스레드는 수백 개의 html/이미지/angular/react 파일을 스트리밍 하느라 바빠서 정작 천직인 동적 컨텐츠를 전달하는 작업에는 신경쓸 겨를이 없을것이다. -🔗 [**자세히 보기: Get your frontend assets out of Node**](/sections/production/frontendout.md) +🔗 [**자세히 보기: Get your frontend assets out of Node**](./sections/production/frontendout.md)

@@ -672,7 +670,7 @@ null == undefined // true **그렇게 하지 않을 경우:** 해당서버에 오류가 발생하면 해당 서버만 제거하면 되는 것이 아니라 어플리케이션의 다운타임이 발생하게된다. 게다가 특정 서버에 의존하기 때문에 수평적 확장이 힘들어질 것이다 -🔗 [**자세히 보기: Be stateless, kill your Servers almost every day**](/sections/production/bestateless.md) +🔗 [**자세히 보기: Be stateless, kill your Servers almost every day**](./sections/production/bestateless.md)

@@ -682,7 +680,7 @@ null == undefined // true **그렇게 하지 않을 경우:** 전용 도구없이 취약점으로부터 코드를 깨끗하게 유지하려면 새로운 취약점에 대한 데이터를 지속적으로 확인해야 할것이다 -🔗 [**자세히 보기: Use tools that automatically detect vulnerabilities**](/sections/production/detectvulnerabilities.md) +🔗 [**자세히 보기: Use tools that automatically detect vulnerabilities**](./sections/production/detectvulnerabilities.md)

@@ -692,7 +690,7 @@ null == undefined // true **그렇게 하지 않을 경우:** 이전에 어떤일이 일어났는지에 대한 컨텍스트 없이 에러 로그를 확인하는 것은 문제를 해결하는 것을 더 어렵고 느리게 만든다 -🔗 [**자세히 보기: Assign ‘TransactionId’ to each log statement**](/sections/production/assigntransactionid.md) +🔗 [**자세히 보기: Assign ‘TransactionId’ to each log statement**](./sections/production/assigntransactionid.md)

@@ -702,7 +700,7 @@ null == undefined // true **그렇게 하지 않을 경우:** 이 단순한 속성을 빠뜨리면 성능이 크게 저하된다. 예를 들어 Express에서 서버 사이드 렌더링(Server Side Rendering, SSP)을 사용할때 `NODE_ENV`를 빠뜨리면 3배 느려진다 -🔗 [**자세히 보기: Set NODE_ENV=production**](/sections/production/setnodeenv.md) +🔗 [**자세히 보기: Set NODE_ENV=production**](./sections/production/setnodeenv.md)

@@ -720,7 +718,7 @@ null == undefined // true **그렇게 하지 않을 경우:** 새로 발견된 버그나 취약점이 상용에서 운영중인 어플리케이션을 악용하는데 사용될 수 있으며, 다양한 모듈들에서 지원을 하지 않게 되고 유지보수하는 것이 힘들어 지게될것이다 -🔗 [**자세히 보기: Use an LTS release of Node.js**](/sections/production/LTSrelease.md) +🔗 [**자세히 보기: Use an LTS release of Node.js**](./sections/production/LTSrelease.md)

@@ -730,7 +728,7 @@ null == undefined // true **그렇게 하지 않을 경우:** 어플리케이션 로그 라우팅 처리 === 확장성 저하, 로그 유실, 관심사의 분리 실패(Separation of Concerns, SoC) -🔗 [**자세히 보기: Log Routing**](/sections/production/logrouting.md) +🔗 [**자세히 보기: Log Routing**](./sections/production/logrouting.md)

@@ -740,7 +738,7 @@ null == undefined // true **그렇게 하지 않을 경우:** QA팀이 코드를 승인하기 전에 철저히 테스트해도 상용환경에서는 다르게 작동할것이다. 게다가 같은 프로덕션 클러스터의 다른 서버들이 서로 다른 코드를 실행할 수도 있다. -🔗 [**자세히 보기: npm ci 쓰기**](/sections/production/installpackageswithnpmci.md) +🔗 [**자세히 보기: npm ci 쓰기**](./sections/production/installpackageswithnpmci.md)


@@ -760,7 +758,7 @@ null == undefined // true **그렇게 하지 않을 경우:** 개발과정에서는 이해하기 쉬운 보안 약점이었음에도 상용환경에서는 주요쟁점이 된다. 또, 프로젝트가 일관된 보안 프렉티스를 따르지 않아, 취약점이 노출되거나 민감한 정보가 원격 저장소에 유출될 수 있다. -🔗 [**자세히 보기: Lint rules**](/sections/security/lintrules.md) +🔗 [**자세히 보기: Lint rules**](./sections/security/lintrules.md)

@@ -772,7 +770,7 @@ null == undefined // true **그렇게 하지 않을 경우:** 애플리케이션이 서비스 거부 공격을 받으면 실제 이용자들이 받는 서비스가 저하되거나 먹통이 된다. -🔗 [**자세히 보기: Implement rate limiting**](/sections/security/limitrequests.md) +🔗 [**자세히 보기: Implement rate limiting**](./sections/security/limitrequests.md)

@@ -784,7 +782,7 @@ null == undefined // true **그렇게 하지 않을 경우:** 비공개 저장소라 하여도 소스 제어가 실수로 공개되면 모든 기밀사항이 그대로 드러난다. 외부관계자가 소스제어에 접근이 가능해지면 의도치 않아도 관련 시스템(데이터베이스, API, 서비스 등)에도 접근을 허락하는것과 마찬가지다. -🔗 [**자세히 보기: Secret management**](/sections/security/secretmanagement.md) +🔗 [**자세히 보기: Secret management**](./sections/security/secretmanagement.md)

@@ -796,7 +794,7 @@ null == undefined // true **그렇게 하지 않을 경우:** 확인되지 않거나 (unvalidated) 살균되지 않은 (unsanitized) 사용자 입력은 MangoDB for NoSQL를 쓸 때 operator injection를 초래할 수 있고, 제대로 된 위생처리 시스템이나 ORM을 쓰지 않는것은 SQL 주입 공격을 쉽게 만들어 엄청난 취약점을 만들어낼 수 있다. -🔗 [**자세히 보기: Query injection prevention using ORM/ODM libraries**](/sections/security/ormodmusage.md) +🔗 [**자세히 보기: Query injection prevention using ORM/ODM libraries**](./sections/security/ormodmusage.md)

@@ -804,7 +802,7 @@ null == undefined // true **핵심요약:** 이것은 Node.js와는 직접적으로 관련되지 않은 보안과 관련된 조언 모음집이지만, Node의 시행도 다른 언어들과 그닥 다르지 않다. 자세히 보기를 클릭해서 읽어봐라. -🔗 [**자세히 보기: Common security best practices**](/sections/security/commonsecuritybestpractices.md) +🔗 [**자세히 보기: Common security best practices**](./sections/security/commonsecuritybestpractices.md)

@@ -816,7 +814,7 @@ null == undefined // true **그렇게 하지 않을 경우:** 공격자들이 애플리케이션 사용자들을 직접적으로 공격할 수 있게되면 엄청난 보안 취약점을 초래할 수 있다 -🔗 [**자세히 보기: Using secure headers in your application**](/sections/security/secureheaders.md) +🔗 [**자세히 보기: Using secure headers in your application**](./sections/security/secureheaders.md)

@@ -828,7 +826,7 @@ null == undefined // true **그렇게 하지 않을 경우:** 공격자가 당신의 웹 프레임워크를 감지하면 알려진 모든 취약점을 공격할 수 있다. -🔗 [**자세히 보기: Dependency security**](/sections/security/dependencysecurity.md) +🔗 [**자세히 보기: Dependency security**](./sections/security/dependencysecurity.md)

@@ -840,7 +838,7 @@ null == undefined // true **그렇게 하지 않을 경우:** 보안함수(secure function)를 쓰지 않고 저장된 암호나 기밀사항들은 억지기법이나 사전공격에 취약해져 결국엔 다 뚫리게 된다. -🔗 [**자세히 보기: Use Bcrypt**](/sections/security/bcryptpasswords.md) +🔗 [**자세히 보기: Use Bcrypt**](./sections/security/userpasswords.md)

@@ -852,7 +850,7 @@ null == undefined // true **그렇게 하지 않을 경우:** 공격자가 악의적인 자바스크립트 코드를 당신 DB에 저장하면 불쌍한 클라이언트에게 그대로 보내질 수 있다 -🔗 [**자세히 보기: Escape output**](/sections/security/escape-output.md) +🔗 [**자세히 보기: Escape output**](./sections/security/escape-output.md)

@@ -864,7 +862,7 @@ null == undefined // true **그렇게 하지 않을 경우:** 입력에 대해 너그럽고 관대하면 공격 받을 수 있는 면적이 넓어지고, 공격자에게 애플리케이션을 끌어내리는 조합을 찾을때까지 다양한 입력값을 시도해보도록 장려하는 꼴이 된다. -🔗 [**자세히 보기: Validate incoming JSON schemas**](/sections/security/validation.md) +🔗 [**자세히 보기: Validate incoming JSON schemas**](./sections/security/validation.md)

@@ -876,7 +874,7 @@ null == undefined // true **그렇게 하지 않을 경우:** 제삼자가 만료되었거나 부적절한 토큰을 악의적으로 사용하여 애플리케이션에 접근하거나 토큰 소유자인 척 가장할 수 있다. -🔗 [**자세히 보기: Blacklist JSON Web Tokens**](/sections/security/expirejwt.md) +🔗 [**자세히 보기: Blacklist JSON Web Tokens**](./sections/security/expirejwt.md)

@@ -891,7 +889,7 @@ null == undefined // true **그렇게 하지 않을 경우:** 공격자가 무제한으로 암호를 시도해서 특권있는 계좌에 접근할 수 있다 -🔗 [**자세히 보기: Login rate limiting**](/sections/security/login-rate-limit.md) +🔗 [**자세히 보기: Login rate limiting**](./sections/security/login-rate-limit.md)

@@ -899,11 +897,11 @@ null == undefined // true -**핵심요약:** Node.js가 승인에 제한이 없는 루트 사용자로써 실행하는 일이 비일비재하다. 예를 들면, 도커 컨테이너 안에서는 이것이 기본적인 설정이다. 루트가 아닌 사용자를 만들어 도커 이미지에 구워넣거나 (아래예시) 프로세스를 "-u username" 플래그를 써서 이 사용자를 대신해서 실행하는것을 추천한다. +**핵심요약:** Node.js가 승인에 제한이 없는 루트 사용자로써 실행하는 일이 비일비재하다. 예를 들면, 도커 컨테이너 안에서는 이것이 기본적인 설정이다. 루트가 아닌 사용자를 만들어 도커 이미지에 구워넣거나 (아래예시) 프로세스를 "-u username" 플래그를 써서 이 사용자를 대신해서 실행하는것을 추천한다. **그렇게 하지 않을 경우:** 공격자가 서버에 스크립트를 실행하는데 성공하면 로컬 머신을 마음대로 할 권리를 무제한으로 갖게 된다 (예: iptable을 바꾼다던가 트래픽 경로를 자기 서버로 변경 한다던가) -🔗 [**자세히 보기: Run Node.js as non-root user**](/sections/security/non-root-user.md) +🔗 [**자세히 보기: Run Node.js as non-root user**](./sections/security/non-root-user.md)

@@ -915,7 +913,7 @@ null == undefined // true **그렇게 하지 않을 경우:** 애플리케이션이 커다란 요청을 처리해야하면 다른 중요한 일을 완수할 수 없게 되어 성능이 영향을 받고 DOS 공격에 취약하게 된다 -🔗 [**자세히 보기: Limit payload size**](/sections/security/requestpayloadsizelimit.md) +🔗 [**자세히 보기: Limit payload size**](./sections/security/requestpayloadsizelimit.md)

@@ -927,7 +925,7 @@ null == undefined // true **그렇게 하지 않을 경우:** 악의적인 자바스크립트 코드가 `eval`같이 실시간으로 평가하는 자바스크립트 언어 함수에 넘어가면 페이지 안의 자바스크립트 승인을 완전히 장악하게 된다. 이 취약점은 XSS 공격 형태로 자주 나타난다. -🔗 [**자세히 보기: Avoid JavaScript eval statements**](/sections/security/avoideval.md) +🔗 [**자세히 보기: Avoid JavaScript eval statements**](./sections/security/avoideval.md)

@@ -939,7 +937,7 @@ null == undefined // true **그렇게 하지 않을 경우:** 저조하게 쓰여진 정규표현들은 이벤트 루프를 완전히 정체시킬 수 있는 정규표현 DOS 공격에 취약해진다. 예를들면, 자주 쓰이는 `moment` 패키지 또한 2017년 11월에 악성 정규표현 사용에 취약하다는 것이 발견되었다 -🔗 [**자세히 보기: Prevent malicious RegEx**](/sections/security/regex.md) +🔗 [**자세히 보기: Prevent malicious RegEx**](./sections/security/regex.md)

@@ -951,7 +949,7 @@ null == undefined // true **그렇게 하지 않을 경우:** 악의적인 사용자 입력이 이전에 파일시스템에 업로드되었거나 이미 시스템에 존재하는 흑화된 파일을 require 하는데 쓰이는 매개변수로 들어가게 될 수 있다. -🔗 [**자세히 보기: Safe module loading**](/sections/security/safemoduleloading.md) +🔗 [**자세히 보기: Safe module loading**](./sections/security/safemoduleloading.md)

@@ -963,7 +961,7 @@ null == undefined // true **그렇게 하지 않을 경우:** 플러그인이 무한 루프나, 메모리 과부화나, 민감한 프로세스 환경 변수로의 접근과 같이 무한히 가지각색으로 공격할 수 있다 -🔗 [**자세히 보기: Run unsafe code in a sandbox**](/sections/security/sandbox.md) +🔗 [**자세히 보기: Run unsafe code in a sandbox**](./sections/security/sandbox.md)

@@ -975,7 +973,7 @@ null == undefined // true **그렇게 하지 않을 경우:** 순진무구하게 자식 프로세스를 썼다가는 악의적인 사용자 입력이 무결처리 되지 않은 시스템 명령어로 인한 원격 커맨드 실행이나 쉘 주입 공격을 초래할 수 있다. -🔗 [**자세히 보기: Be cautious when working with child processes**](/sections/security/childprocesses.md) +🔗 [**자세히 보기: Be cautious when working with child processes**](./sections/security/childprocesses.md)

@@ -987,7 +985,7 @@ null == undefined // true **그렇게 하지 않을 경우:** 서버 파일 경로나, 사용중인 제삼자 모듈, 그리고 그 외 애플리케이션 내부 작업 순서 같이 공격자가 악용할 수 있는 민감한 애플리케이션 세부사항이 스택트레이스에 보여지는 정보로 새어나갈 수 있다 -🔗 [**자세히 보기: Hide error details from client**](/sections/security/hideerrors.md) +🔗 [**자세히 보기: Hide error details from client**](./sections/security/hideerrors.md)

@@ -995,7 +993,7 @@ null == undefined // true -**핵심요약:** 개발 과정의 모든 단계는 다중인증(MFA: multi-factor authentication)을 사용해서 보호해야한다. npm이나 Yarn은 공격자들이 개발자 암호를 수집할 수 있는 절호의 기회다. 공격자들은 개발자의 크리덴셜을 사용하면 악의적인 코드를 다양한 프로젝트와 서비스에 널리 설치된 라이브러리에 주입할 수 있다. 공개 출판 되었다면 웹상에서도 가능하다. npm 이중인증을 활성화 해 두면 공격자들이 패키지 코드를 변경할 확률이 0에 가까워진다. +**핵심요약:** 개발 과정의 모든 단계는 다중인증(MFA: multi-factor authentication)을 사용해서 보호해야한다. npm이나 Yarn은 공격자들이 개발자 암호를 수집할 수 있는 절호의 기회다. 공격자들은 개발자의 크리덴셜을 사용하면 악의적인 코드를 다양한 프로젝트와 서비스에 널리 설치된 라이브러리에 주입할 수 있다. 공개 출판 되었다면 웹상에서도 가능하다. npm 이중인증을 활성화 해 두면 공격자들이 패키지 코드를 변경할 확률이 0에 가까워진다. **그렇게 하지 않을 경우:** [암호를 하이재킹 당한 eslint 개발자에 대해 들어봤는가?](https://medium.com/@oprearocks/eslint-backdoor-what-it-is-and-how-to-fix-the-issue-221f58f1a8c8) @@ -1009,7 +1007,7 @@ null == undefined // true **그렇게 하지 않을 경우:** 쿠키가 insecure 연결로 송신되면 공격자가 세션 ID를 보고 웹 어플리케이션 프레임워크를 식별하고, 모듈관련 취약점도 찾아낼 수 있다 -🔗 [**자세히 보기: Cookie and session security**](/sections/security/sessions.md) +🔗 [**자세히 보기: Cookie and session security**](./sections/security/sessions.md)

@@ -1031,7 +1029,7 @@ null == undefined // true **그렇게 하지 않을 경우:** 공격자가 당신이 외부 유저로부터 조달된 입력을 검사하지 않는다는 것을 발견 할 경우, 특수 조작된 포럼 링크를 포럼이나 소셜 미디어, 그 외 공공 장소에 게재해서 유저들이 클릭하도록 해서 이 취약점을 악용할 수 있다. -🔗 [**자세히 보기: Prevent unsafe redirects**](/sections/security/saferedirects.md) +🔗 [**자세히 보기: Prevent unsafe redirects**](./sections/security/saferedirects.md)

@@ -1043,7 +1041,7 @@ null == undefined // true **그렇게 하지 않을 경우:** 프로젝트의 API key나, 암호나, 그 외 기밀사항들이 이것들을 우연히 발견한 이들 누구나에 의해 남용되면 재정적 손실이나 사칭과 같은 위험을 초래할 수 있다. -🔗 [**자세히 보기: Avoid publishing secrets**](/sections/security/avoid_publishing_secrets.md) +🔗 [**자세히 보기: Avoid publishing secrets**](./sections/security/avoid_publishing_secrets.md)


⬆ Return to top

@@ -1060,7 +1058,7 @@ null == undefined // true **그렇게 하지 않을 경우:** 이벤트 루프가 블로킹되면 Node.js는 다른 요청을 처리할 수 없게 되어 동시성 (concurrent) 사용자들을 지체하게 한다. **사용자 3000명이 응답을 기다리고 있고, 콘텐츠도 제공될 준비가 되어있는데, 단 하나의 요청이 서버가 결과물을 발송하지 못하도록 블로킹 할 수 있다** -🔗 [**자세히 보기: Do not block the event loop**](/sections/performance/block-loop.md) +🔗 [**자세히 보기: Do not block the event loop**](./sections/performance/block-loop.md)


@@ -1071,7 +1069,7 @@ null == undefined // true **그렇게 하지 않을 경우:** 기본적으로 **이미** 내장된 코드를 쓰거나 코드를 몇줄 더 써서 파일을 몇개 더 써야 하는 것을 막을 수 있었음에도 불구하고 더 비능률적인 프로젝트를 유지해야 할 것이다. -🔗 [**자세히 보기: Native over user land utils**](/sections/performance/nativeoverutil.md) +🔗 [**자세히 보기: Native over user land utils**](./sections/performance/nativeoverutil.md)


@@ -1087,17 +1085,17 @@ null == undefined // true ### 번역 작업 완료 -- ![BR](/assets/flags/BR.png) [브라질식 포르투갈어](./README.brazilian-portuguese.md) - [마르셀로 멜로](https://github.com/marcelosdm) 제공 -- ![CN](/assets/flags/CN.png) [중국어](./README.chinese.md) - [맷 진](https://github.com/mattjin) 제공 -- ![RU](/assets/flags/RU.png) [러시아어](./README.russian.md) - [알렉스 이바노브](https://github.com/contributorpw) 제공 +- ![BR](./assets/flags/BR.png) [브라질식 포르투갈어](./README.brazilian-portuguese.md) - [마르셀로 멜로](https://github.com/marcelosdm) 제공 +- ![CN](./assets/flags/CN.png) [중국어](./README.chinese.md) - [맷 진](https://github.com/mattjin) 제공 +- ![RU](./assets/flags/RU.png) [러시아어](./README.russian.md) - [알렉스 이바노브](https://github.com/contributorpw) 제공 ### 번역 작업중 -- ![FR](/assets/flags/FR.png) [프랑스어](https://github.com/gaspaonrocks/nodebestpractices/blob/french-translation/README.french.md) ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/129)) -- ![HE](/assets/flags/HE.png) 히브리어 ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/156)) -- ![KR](/assets/flags/KR.png) [한국어](README.korean.md) - [한상범](https://github.com/uronly14me) ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/94)) 제공 -- ![ES](/assets/flags/ES.png) [스페인어](https://github.com/goldbergyoni/nodebestpractices/blob/spanish-translation/README.spanish.md) ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/95)) -- ![TR](/assets/flags/TR.png) 터키어 ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/139)) +- ![FR](./assets/flags/FR.png) [프랑스어](https://github.com/gaspaonrocks/nodebestpractices/blob/french-translation/README.french.md) ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/129)) +- ![HE](./assets/flags/HE.png) 히브리어 ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/156)) +- ![KR](./assets/flags/KR.png) [한국어](README.korean.md) - [한상범](https://github.com/uronly14me) ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/94)) 제공 +- ![ES](./assets/flags/ES.png) [스페인어](https://github.com/goldbergyoni/nodebestpractices/blob/spanish-translation/README.spanish.md) ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/95)) +- ![TR](./assets/flags/TR.png) 터키어 ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/139))

@@ -1105,7 +1103,7 @@ null == undefined // true 프로젝트를 지도하고 앞으로 나아갈 방향을 제시하는데 함께 일하는 운영 위원회 일원들을 소개합니다. 추가로, 위원회원들은 각자 [Github 프로젝트](https://github.com/goldbergyoni/nodebestpractices/projects) 아래에 인행되는 프로젝트들을 인솔합니다. - + [요니 골드버그](https://github.com/goldbergyoni) @@ -1115,7 +1113,7 @@ null == undefined // true
- + [브루노 슈플러](https://github.com/BrunoScheufler) @@ -1124,7 +1122,7 @@ null == undefined // true
- + [카일 마틴](https://github.com/js-kyle) @@ -1134,7 +1132,7 @@ null == undefined // true
- + [사기르 칸](https://github.com/sagirk) @@ -1149,21 +1147,22 @@ null == undefined // true 모든 공동 저자 분들께 감사드립니다! 🙏 -공동 저자들은 새로운 모범사례를 제안하거나, 사안을 분류하거나, 풀리퀘스트를 검토하는 등 리포지토리에 정기적으로 기여하는 일원들입니다. 수천명의 사람들이 더 나은 Node.js 애플리케이션을 만들 수 있도록 안내하며 돕는데 관심이 있으시다면 [기여자 지침서](/.operations/CONTRIBUTING.md)를 읽어주세요 🎉 +공동 저자들은 새로운 모범사례를 제안하거나, 사안을 분류하거나, 풀리퀘스트를 검토하는 등 리포지토리에 정기적으로 기여하는 일원들입니다. 수천명의 사람들이 더 나은 Node.js 애플리케이션을 만들 수 있도록 안내하며 돕는데 관심이 있으시다면 [기여자 지침서](./.operations/CONTRIBUTING.md)를 읽어주세요 🎉 -| | | | -| :----------------------------------------------------------: | :----------------------------------------------------------: | :----------------------------------------------------------: | -| [이도 릭터 (창립주)](https://github.com/idori) | [키스 홀리데이](https://github.com/TheHollidayInn) | [케빈 브뤼예르](https://github.com/kevynb) | +| | | | +| :---------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------------: | +| [이도 릭터 (창립주)](https://github.com/idori) | [키스 홀리데이](https://github.com/TheHollidayInn) | [케빈 브뤼예르](https://github.com/kevynb) | ### 전 공동 저자 -| | +| | | :-------------------------------------------------------------------------------------------------------------------------: | | [Refael Ackermann](https://github.com/refack) |
## 기여하기 + 오픈소스에 참여하고 싶으시다면 지금이 바로 기회! [기여자 지침서](.operations/CONTRIBUTING.md)에서 더 자세한 내용을 확인하세요. ## 기여자 ✨ @@ -1174,133 +1173,259 @@ null == undefined // true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

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

🖋
Kevin Rambaud
Kevin Rambaud

🖋
Michael Fine
Michael Fine

🖋
Shreya Dahal
Shreya Dahal

🖋
Matheus Cruz Rocha
Matheus Cruz Rocha

🖋
Yog Mehta
Yog Mehta

🖋
Kudakwashe Paradzayi
Kudakwashe Paradzayi

🖋
t1st3
t1st3

🖋
mulijordan1976
mulijordan1976

🖋
Matan Kushner
Matan Kushner

🖋
Fabio Hiroki
Fabio Hiroki

🖋
James Sumners
James Sumners

🖋
Dan Gamble
Dan Gamble

🖋
PJ Trainor
PJ Trainor

🖋
Remek Ambroziak
Remek Ambroziak

🖋
Yoni Jah
Yoni Jah

🖋
Misha Khokhlov
Misha Khokhlov

🖋
Evgeny Orekhov
Evgeny Orekhov

🖋
-
-

🖋
Isaac Halvorson
Isaac Halvorson

🖋
Vedran Karačić
Vedran Karačić

🖋
lallenlowe
lallenlowe

🖋
Nathan Wells
Nathan Wells

🖋
Paulo Reis
Paulo Reis

🖋
syzer
syzer

🖋
David Sancho
David Sancho

🖋
Robert Manolea
Robert Manolea

🖋
Xavier Ho
Xavier Ho

🖋
Aaron
Aaron

🖋
Jan Charles Maghirang Adona
Jan Charles Maghirang Adona

🖋
Allen
Allen

🖋
Leonardo Villela
Leonardo Villela

🖋
Michał Załęcki
Michał Załęcki

🖋
Chris Nicola
Chris Nicola

🖋
Alejandro Corredor
Alejandro Corredor

🖋
cwar
cwar

🖋
Yuwei
Yuwei

🖋
Utkarsh Bhatt
Utkarsh Bhatt

🖋
Duarte Mendes
Duarte Mendes

🖋
Jason Kim
Jason Kim

🖋
Mitja O.
Mitja O.

🖋
Sandro Miguel Marques
Sandro Miguel Marques

🖋
Gabe
Gabe

🖋
Ron Gross
Ron Gross

🖋
Valeri Karpov
Valeri Karpov

🖋
Sergio Bernal
Sergio Bernal

🖋
Nikola Telkedzhiev
Nikola Telkedzhiev

🖋
Vitor Godoy
Vitor Godoy

🖋
Manish Saraan
Manish Saraan

🖋
Sangbeom Han
Sangbeom Han

🖋
blackmatch
blackmatch

🖋
Joe Reeve
Joe Reeve

🖋
Ryan Busby
Ryan Busby

🖋
Iman Mohamadi
Iman Mohamadi

🖋
Sergii Paryzhskyi
Sergii Paryzhskyi

🖋
Kapil Patel
Kapil Patel

🖋
迷渡
迷渡

🖋
Hozefa
Hozefa

🖋
Ethan
Ethan

🖋
Sam
Sam

🖋
Arlind
Arlind

🖋
Teddy Toussaint
Teddy Toussaint

🖋
Lewis
Lewis

🖋
Gabriel Lidenor
Gabriel Lidenor

🖋
Roman
Roman

🖋
Francozeira
Francozeira

🖋
Invvard
Invvard

🖋
Rômulo Garofalo
Rômulo Garofalo

🖋
Tho Q Luong
Tho Q Luong

🖋
Burak Shen
Burak Shen

🖋
Martin Muzatko
Martin Muzatko

🖋
Jared Collier
Jared Collier

🖋
Hilton Meyer
Hilton Meyer

🖋
ChangJoo Park(박창주)
ChangJoo Park(박창주)

🖋
Masahiro Sakaguchi
Masahiro Sakaguchi

🖋
Keith Holliday
Keith Holliday

🖋
coreyc
coreyc

🖋
Maximilian Berkmann
Maximilian Berkmann

🖋
Douglas Mariano Valero
Douglas Mariano Valero

🖋
Marcelo Melo
Marcelo Melo

🖋
Mehmet Perk
Mehmet Perk

🖋
ryan ouyang
ryan ouyang

🖋
Shabeer
Shabeer

🖋
Eduard Kyvenko
Eduard Kyvenko

🖋
Deyvison Rocha
Deyvison Rocha

🖋
George Mamer
George Mamer

🖋
Konstantinos Leimonis
Konstantinos Leimonis

🖋
Oliver Lluberes
Oliver Lluberes

🌍
Tien Do
Tien Do

🖋
Ranvir Singh
Ranvir Singh

🖋
Vadim Nicolaev
Vadim Nicolaev

🖋 🌍
German Gamboa Gonzalez
German Gamboa Gonzalez

🖋
Hafez
Hafez

🖋
Chandiran
Chandiran

🖋
VinayaSathyanarayana
VinayaSathyanarayana

🖋
Kim Kern
Kim Kern

🖋
Kenneth Freitas
Kenneth Freitas

🖋
songe
songe

🖋
Kirill Shekhovtsov
Kirill Shekhovtsov

🖋
Serge
Serge

🖋
keyrwinz
keyrwinz

🖋
Dmitry Nikitenko
Dmitry Nikitenko

🖋
bushuai
bushuai

👀 🖋
Benjamin Gruenbaum
Benjamin Gruenbaum

🖋
Ezequiel
Ezequiel

🌍
Juan José Rodríguez
Juan José Rodríguez

🌍
Or Bin
Or Bin

🖋
Andreo Vieira
Andreo Vieira

🖋
Michael Solomon
Michael Solomon

🖋
Jimmy Callin
Jimmy Callin

🖋
Siddharth
Siddharth

🖋
Ryan Smith
Ryan Smith

🖋
Tom Boettger
Tom Boettger

🖋
Joaquín Ormaechea
Joaquín Ormaechea

🌍
dfrzuz
dfrzuz

🌍
Victor Homyakov
Victor Homyakov

🖋
Josh
Josh

🖋 🛡️
Alec Francis
Alec Francis

🖋
arjun6610
arjun6610

🖋
Jan Osch
Jan Osch

🖋
Thiago Rotondo Sampaio
Thiago Rotondo Sampaio

🌍
Alexsey
Alexsey

🖋
Luis A. Acurero
Luis A. Acurero

🌍
Lucas Romano
Lucas Romano

🌍
Denise Case
Denise Case

🖋
Nick Ribal
Nick Ribal

🖋 👀
0xflotus
0xflotus

🖋
Jonathan Chen
Jonathan Chen

🖋
Dilan Srilal
Dilan Srilal

🖋
vladthelittleone
vladthelittleone

🌍
Nik Osvalds
Nik Osvalds

🖋
Daniel Kiss
Daniel Kiss

📖
Forresst
Forresst

🖋
Jonathan Svenheden
Jonathan Svenheden

🖋
AustrisC
AustrisC

🖋
kyeongtae kim
kyeongtae kim

🌍
007
007

🖋
Ane Diaz de Tuesta
Ane Diaz de Tuesta

🌍 🖋
YukiOta
YukiOta

🌍
Frazer Smith
Frazer Smith

🖋
Raz Luvaton
Raz Luvaton

🖋
Yuta Azumi
Yuta Azumi

🖋
andrewjbarbour
andrewjbarbour

🖋
mr
mr

🖋
Aleksandar
Aleksandar

🖋
Owl
Owl

🖋
Yedidya Schwartz
Yedidya Schwartz

🖋 💡
ari
ari

🖋
Thomas König
Thomas König

🖋
Kalle Lämsä
Kalle Lämsä

🖋
Wyatt
Wyatt

🖋
KHADIR Tayeb
KHADIR Tayeb

🖋
Shankar Regmi
Shankar Regmi

🖋
Shubham
Shubham

🖋
Lucas Alves
Lucas Alves

🖋
Benjamin
Benjamin

🖋
Yeoh Joer
Yeoh Joer

🖋
Miigon
Miigon

🖋
Rostislav Bogorad
Rostislav Bogorad

🖋
Flouse
Flouse

🖋
Tarantini Pereira
Tarantini Pereira

🖋
Kazuki Matsuo
Kazuki Matsuo

🖋
Adam Smith
Adam Smith

🖋
Dohyeon Ko
Dohyeon Ko

🖋
Vladislav Legkov
Vladislav Legkov

🖋
Kerollos Magdy
Kerollos Magdy

🖋
Erez Lieberman
Erez Lieberman

🖋
Breno Macedo
Breno Macedo

🖋
Fernando Flores
Fernando Flores

🌍
Rafael Brito
Rafael Brito

🌍
Emiliano Peralta
Emiliano Peralta

🌍
Shin, SJ
Shin, SJ

🖋
Benjamin Forster
Benjamin Forster

🖋
Daniele Fedeli
Daniele Fedeli

🖋
djob195
djob195

🖋
antspk
antspk

🖋
정진영
정진영

🖋
kkk-cashwalk
kkk-cashwalk

🖋
apainintheneck
apainintheneck

🖋
Fajar Budhi Iswanda
Fajar Budhi Iswanda

🖋
이주호
이주호

🖋
Singh
Singh

🖋
Alex Dumitru
Alex Dumitru

🖋
Anton Lykhatskyi
Anton Lykhatskyi

🖋
sangwonlee
sangwonlee

🖋
Eugenio Berretta
Eugenio Berretta

🖋
soranakk
soranakk

🖋
고준영
고준영

🖋 💻
Guilherme Portella
Guilherme Portella

🖋
André Esser
André Esser

🖋
Scc
Scc

🌍
Mauro Accornero
Mauro Accornero

🖋
no-yan
no-yan

🖋
- + + diff --git a/README.md b/README.md index 9992e605e..e3139767d 100644 --- a/README.md +++ b/README.md @@ -3,34 +3,32 @@ # Node.js Best Practices

- Node.js Best Practices + Node.js Best Practices


- 102 items Last update: November, 2020 Updated for Node 14.0.0 + 102 items Last update: July 19, 2023 Updated for Node 19.0.0

-[![nodepractices](/assets/images/twitter-s.png)](https://twitter.com/nodepractices/) **Follow us on Twitter!** [**@nodepractices**](https://twitter.com/nodepractices/) +[](https://twitter.com/nodepractices/) **Follow us on Twitter!** [**@nodepractices**](https://twitter.com/nodepractices/)
-Read in a different language: [![CN](/assets/flags/CN.png)**CN**](/README.chinese.md), [![BR](/assets/flags/BR.png)**BR**](/README.brazilian-portuguese.md), [![RU](/assets/flags/RU.png)**RU**](/README.russian.md), [![PL](/assets/flags/PL.png)**PL**](/README.polish.md), [![JA](/assets/flags/JA.png)**JA**](/README.japanese.md), [(![ES](/assets/flags/ES.png)**ES**, ![FR](/assets/flags/FR.png)**FR**, ![HE](/assets/flags/HE.png)**HE**, ![KR](/assets/flags/KR.png)**KR**, ![TR](/assets/flags/TR.png)**TR** and ![EU](/assets/flags/EU.png)**EU** in progress! )](#translations) +Read in a different language: [![CN](./assets/flags/CN.png)**CN**](./README.chinese.md), [![FR](./assets/flags/FR.png)**FR**](./README.french.md), [![BR](./assets/flags/BR.png)**BR**](./README.brazilian-portuguese.md), [![RU](./assets/flags/RU.png)**RU**](./README.russian.md), [![PL](./assets/flags/PL.png)**PL**](./README.polish.md), [![JA](./assets/flags/JA.png)**JA**](./README.japanese.md), [![EU](./assets/flags/EU.png)**EU**](./README.basque.md) [(![ES](./assets/flags/ES.png)**ES**, ![HE](./assets/flags/HE.png)**HE**, ![KR](./assets/flags/KR.png)**KR** and ![TR](./assets/flags/TR.png)**TR** ![AR](./assets/flags/AR.png)**AR** in progress! )](#translations)
-###### Built and maintained by our [Steering Committee](#steering-committee) and [Collaborators](#collaborators) +# 🎊 2023 edition is here! -# Latest Best Practices and News +- **🛰 Modernized to 2023**: Tons of text edits, new recommended libraries, and some new best practices -- **🇯🇵 Japanese translation:** Our guide is now also translated to Japanese! Courtesy of the amazing [YukiOta](https://github.com/YukiOta) and [Yuta Azumi](https://github.com/YA21) +- **✨ Easily focus on new content**: Already visited before? Search for `#new` or `#updated` tags for new content only -- **✅ New best practice:** Bullet 6.8 by Josh Hemphill recommends "Protect Users' Passwords/Secrets using BCrypt or Script". It contains an in-depth explanation about when and why each option suits a specific project. Don't miss this short guide with a brief overview of the various hashing options - -- **🎊 60,000 stars!**: Our repo was starred and trusted by 60,100 developers. We're speechless +- **🔖 Curious to see examples? We have a starter**: Visit [Practica.js](https://github.com/practicajs/practica), our application example and boilerplate (beta) to see some practices in action

@@ -38,74 +36,295 @@ Read in a different language: [![CN](/assets/flags/CN.png)**CN**](/README.chines **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](/.operations/writing-guidelines.md) +**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](./.operations/writing-guidelines.md) **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

+# By Yoni Goldberg + +### Learn with me: As a consultant, I engage with worldwide teams on various activities like workshops and code reviews. 🎉AND... Hold on, I've just launched my [beyond-the-basics testing course, which is on a 🎁 limited-time sale](https://testjavascript.com/) until August 7th + +

+ ## Table of Contents -1. [Project Structure Practices (5)](#1-project-structure-practices) -2. [Error Handling Practices (12) ](#2-error-handling-practices) -3. [Code Style Practices (12) ](#3-code-style-practices) -4. [Testing And Overall Quality Practices (13) ](#4-testing-and-overall-quality-practices) -5. [Going To Production Practices (19) ](#5-going-to-production-practices) -6. [Security Practices (25)](#6-security-best-practices) -7. [Performance Practices (2) (Work In Progress️ ✍️)](#7-draft-performance-best-practices) -8. [Docker Practices (15)](#8-docker-best-practices) +
+ + 1. Project Architecture Practices (6) + + +  [1.1 Structure your solution by components `#strategic` `#updated`](#-11-structure-your-solution-by-business-components)
+  [1.2 Layer your components, keep the web layer within its boundaries `#strategic` `#updated`](#-12-layer-your-components-with-3-tiers-keep-the-web-layer-within-its-boundaries)
+  [1.3 Wrap common utilities as packages, consider publishing](#-13-wrap-common-utilities-as-packages-consider-publishing)
+  [1.4 Use environment aware, secure and hierarchical config `#updated`](#-14-use-environment-aware-secure-and-hierarchical-config)
+  [1.5 Consider all the consequences when choosing the main framework `#new`](#-15-consider-all-the-consequences-when-choosing-the-main-framework)
+  [1.6 Use TypeScript sparingly and thoughtfully `#new`](#-16-use-typescript-sparingly-and-thoughtfully)
+ +
+ +
+ + 2. Error Handling Practices (12) + + +  [2.1 Use Async-Await or promises for async error handling](#-21-use-async-await-or-promises-for-async-error-handling)
+  [2.2 Extend the built-in Error object `#strategic` `#updated`](#-22-extend-the-built-in-error-object)
+  [2.3 Distinguish operational vs programmer errors `#strategic` `#updated`](#-23-distinguish-catastrophic-errors-from-operational-errors)
+  [2.4 Handle errors centrally, not within a middleware `#strategic`](#-24-handle-errors-centrally-not-within-a-middleware)
+  [2.5 Document API errors using OpenAPI or GraphQL](#-25-document-api-errors-using-openapi-or-graphql)
+  [2.6 Exit the process gracefully when a stranger comes to town `#strategic`](#-26-exit-the-process-gracefully-when-a-stranger-comes-to-town)
+  [2.7 Use a mature logger to increase errors visibility `#updated`](#-27-use-a-mature-logger-to-increase-errors-visibility)
+  [2.8 Test error flows using your favorite test framework `#updated`](#-28-test-error-flows-using-your-favorite-test-framework)
+  [2.9 Discover errors and downtime using APM products](#-29-discover-errors-and-downtime-using-apm-products)
+  [2.10 Catch unhandled promise rejections `#updated`](#-210-catch-unhandled-promise-rejections)
+  [2.11 Fail fast, validate arguments using a dedicated library](#-211-fail-fast-validate-arguments-using-a-dedicated-library)
+  [2.12 Always await promises before returning to avoid a partial stacktrace `#new`](#-212-always-await-promises-before-returning-to-avoid-a-partial-stacktrace)
+  [2.13 Subscribe to event emitters 'error' event `#new`](#-213-subscribe-to-event-emitters-and-streams-error-event)
+ +
+ +
+ + 3. Code Style Practices (12) + + +  [3.1 Use ESLint `#strategic`](#-31-use-eslint)
+  [3.2 Use Node.js eslint extension plugins `#updated`](#-32-use-nodejs-eslint-extension-plugins)
+  [3.3 Start a Codeblock's Curly Braces on the Same Line](#-33-start-a-codeblocks-curly-braces-on-the-same-line)
+  [3.4 Separate your statements properly](#-34-separate-your-statements-properly)
+  [3.5 Name your functions](#-35-name-your-functions)
+  [3.6 Use naming conventions for variables, constants, functions and classes](#-36-use-naming-conventions-for-variables-constants-functions-and-classes)
+  [3.7 Prefer const over let. Ditch the var](#-37-prefer-const-over-let-ditch-the-var)
+  [3.8 Require modules first, not inside functions](#-38-require-modules-first-not-inside-functions)
+  [3.9 Set an explicit entry point to a module/folder `#updated`](#-39-set-an-explicit-entry-point-to-a-modulefolder)
+  [3.10 Use the === operator](#-310-use-the--operator)
+  [3.11 Use Async Await, avoid callbacks `#strategic`](#-311-use-async-await-avoid-callbacks)
+  [3.12 Use arrow function expressions (=>)](#-312-use-arrow-function-expressions-)
+  [3.13 Avoid effects outside of functions `#new`](#-313-avoid-effects-outside-of-functions)
+ +
+ +
+ + 4. Testing And Overall Quality Practices (13) + + +  [4.1 At the very least, write API (component) testing `#strategic`](#-41-at-the-very-least-write-api-component-testing)
+  [4.2 Include 3 parts in each test name `#new`](#-42-include-3-parts-in-each-test-name)
+  [4.3 Structure tests by the AAA pattern `#strategic`](#-43-structure-tests-by-the-aaa-pattern)
+  [4.4 Ensure Node version is unified `#new`](#-44-ensure-node-version-is-unified)
+  [4.5 Avoid global test fixtures and seeds, add data per-test `#strategic`](#-45-avoid-global-test-fixtures-and-seeds-add-data-per-test)
+  [4.6 Tag your tests `#advanced`](#-46-tag-your-tests)
+  [4.7 Check your test coverage, it helps to identify wrong test patterns](#-47-check-your-test-coverage-it-helps-to-identify-wrong-test-patterns)
+  [4.8 Use production-like environment for e2e testing](#-48-use-production-like-environment-for-e2e-testing)
+  [4.9 Refactor regularly using static analysis tools](#-49-refactor-regularly-using-static-analysis-tools)
+  [4.10 Mock responses of external HTTP services #advanced `#new` `#advanced`](#-410-mock-responses-of-external-http-services)
+  [4.11 Test your middlewares in isolation](#-411-test-your-middlewares-in-isolation)
+  [4.12 Specify a port in production, randomize in testing `#new`](#-412-specify-a-port-in-production-randomize-in-testing)
+  [4.13 Test the five possible outcomes #strategic `#new`](#-413-test-the-five-possible-outcomes)
+ +
+ +
+ + 5. Going To Production Practices (19) + + +  [5.1. Monitoring `#strategic`](#-51-monitoring)
+  [5.2. Increase the observability using smart logging `#strategic`](#-52-increase-the-observability-using-smart-logging)
+  [5.3. Delegate anything possible (e.g. gzip, SSL) to a reverse proxy `#strategic`](#-53-delegate-anything-possible-eg-gzip-ssl-to-a-reverse-proxy)
+  [5.4. Lock dependencies](#-54-lock-dependencies)
+  [5.5. Guard process uptime using the right tool](#-55-guard-process-uptime-using-the-right-tool)
+  [5.6. Utilize all CPU cores](#-56-utilize-all-cpu-cores)
+  [5.7. Create a ‘maintenance endpoint’](#-57-create-a-maintenance-endpoint)
+  [5.8. Discover the unknowns using APM products `#advanced` `#updated`](#-58-discover-the-unknowns-using-apm-products)
+  [5.9. Make your code production-ready](#-59-make-your-code-production-ready)
+  [5.10. Measure and guard the memory usage `#advanced`](#-510-measure-and-guard-the-memory-usage)
+  [5.11. Get your frontend assets out of Node](#-511-get-your-frontend-assets-out-of-node)
+  [5.12. Strive to be stateless `#strategic`](#-512-strive-to-be-stateless)
+  [5.13. Use tools that automatically detect vulnerabilities](#-513-use-tools-that-automatically-detect-vulnerabilities)
+  [5.14. Assign a transaction id to each log statement `#advanced`](#-514-assign-a-transaction-id-to-each-log-statement)
+  [5.15. Set NODE_ENV=production](#-515-set-node_envproduction)
+  [5.16. Design automated, atomic and zero-downtime deployments `#advanced`](#-516-design-automated-atomic-and-zero-downtime-deployments)
+  [5.17. Use an LTS release of Node.js](#-517-use-an-lts-release-of-nodejs)
+  [5.18. Log to stdout, avoid specifying log destination within the app `#updated`](#-518-log-to-stdout-avoid-specifying-log-destination-within-the-app)
+  [5.19. Install your packages with npm ci `#new`](#-519-install-your-packages-with-npm-ci)
+ +
+ +
+ + 6. Security Practices (25) + + +  [6.1. Embrace linter security rules](#-61-embrace-linter-security-rules)
+  [6.2. Limit concurrent requests using a middleware](#-62-limit-concurrent-requests-using-a-middleware)
+  [6.3 Extract secrets from config files or use packages to encrypt them `#strategic`](#-63-extract-secrets-from-config-files-or-use-packages-to-encrypt-them)
+  [6.4. Prevent query injection vulnerabilities with ORM/ODM libraries `#strategic`](#-64-prevent-query-injection-vulnerabilities-with-ormodm-libraries)
+  [6.5. Collection of generic security best practices](#-65-collection-of-generic-security-best-practices)
+  [6.6. Adjust the HTTP response headers for enhanced security](#-66-adjust-the-http-response-headers-for-enhanced-security)
+  [6.7. Constantly and automatically inspect for vulnerable dependencies `#strategic`](#-67-constantly-and-automatically-inspect-for-vulnerable-dependencies)
+  [6.8. Protect Users' Passwords/Secrets using bcrypt or scrypt `#strategic`](#-68-protect-users-passwordssecrets-using-bcrypt-or-scrypt)
+  [6.9. Escape HTML, JS and CSS output](#-69-escape-html-js-and-css-output)
+  [6.10. Validate incoming JSON schemas `#strategic`](#-610-validate-incoming-json-schemas)
+  [6.11. Support blocklisting JWTs](#-611-support-blocklisting-jwts)
+  [6.12. Prevent brute-force attacks against authorization `#advanced`](#-612-prevent-brute-force-attacks-against-authorization)
+  [6.13. Run Node.js as non-root user](#-613-run-nodejs-as-non-root-user)
+  [6.14. Limit payload size using a reverse-proxy or a middleware](#-614-limit-payload-size-using-a-reverse-proxy-or-a-middleware)
+  [6.15. Avoid JavaScript eval statements](#-615-avoid-javascript-eval-statements)
+  [6.16. Prevent evil RegEx from overloading your single thread execution](#-616-prevent-evil-regex-from-overloading-your-single-thread-execution)
+  [6.17. Avoid module loading using a variable](#-617-avoid-module-loading-using-a-variable)
+  [6.18. Run unsafe code in a sandbox](#-618-run-unsafe-code-in-a-sandbox)
+  [6.19. Take extra care when working with child processes `#advanced`](#-619-take-extra-care-when-working-with-child-processes)
+  [6.20. Hide error details from clients](#-620-hide-error-details-from-clients)
+  [6.21. Configure 2FA for npm or Yarn `#strategic`](#-621-configure-2fa-for-npm-or-yarn)
+  [6.22. Modify session middleware settings](#-622-modify-session-middleware-settings)
+  [6.23. Avoid DOS attacks by explicitly setting when a process should crash `#advanced`](#-623-avoid-dos-attacks-by-explicitly-setting-when-a-process-should-crash)
+  [6.24. Prevent unsafe redirects](#-624-prevent-unsafe-redirects)
+  [6.25. Avoid publishing secrets to the npm registry](#-625-avoid-publishing-secrets-to-the-npm-registry)
+  [6.26. 6.26 Inspect for outdated packages](#-626-inspect-for-outdated-packages)
+  [6.27. Import built-in modules using the 'node:' protocol `#new`](#-627-import-built-in-modules-using-the-node-protocol)
+ +
+ +
+ + 7. Performance Practices (2) (Work In Progress️ ✍️) + + +  [7.1. Don't block the event loop](#-71-dont-block-the-event-loop)
+  [7.2. Prefer native JS methods over user-land utils like Lodash](#-72-prefer-native-js-methods-over-user-land-utils-like-lodash)
+ +
+ +
+ + 8. Docker Practices (15) + + +  [8.1 Use multi-stage builds for leaner and more secure Docker images `#strategic`](#-81-use-multi-stage-builds-for-leaner-and-more-secure-docker-images)
+  [8.2. Bootstrap using node command, avoid npm start](#-82-bootstrap-using-node-command-avoid-npm-start)
+  [8.3. Let the Docker runtime handle replication and uptime `#strategic`](#-83-let-the-docker-runtime-handle-replication-and-uptime)
+  [8.4. Use .dockerignore to prevent leaking secrets](#-84-use-dockerignore-to-prevent-leaking-secrets)
+  [8.5. Clean-up dependencies before production](#-85-clean-up-dependencies-before-production)
+  [8.6. Shutdown smartly and gracefully `#advanced`](#-86-shutdown-smartly-and-gracefully)
+  [8.7. Set memory limits using both Docker and v8 `#advanced` `#strategic`](#-87-set-memory-limits-using-both-docker-and-v8)
+  [8.8. Plan for efficient caching](#-88-plan-for-efficient-caching)
+  [8.9. Use explicit image reference, avoid latest tag](#-89-use-explicit-image-reference-avoid-latest-tag)
+  [8.10. Prefer smaller Docker base images](#-810-prefer-smaller-docker-base-images)
+  [8.11. Clean-out build-time secrets, avoid secrets in args `#strategic #new`](#-811-clean-out-build-time-secrets-avoid-secrets-in-args)
+  [8.12. Scan images for multi layers of vulnerabilities `#advanced`](#-812-scan-images-for-multi-layers-of-vulnerabilities)
+  [8.13 Clean NODE_MODULE cache](#-813-clean-node_module-cache)
+  [8.14. Generic Docker practices](#-814-generic-docker-practices)
+  [8.15. Lint your Dockerfile `#new`](#-815-lint-your-dockerfile)
+ +
+ +

+ +# `1. Project Architecture Practices` + +## ![✔] 1.1 Structure your solution by business components + +### `📝 #updated` + +**TL;DR:** The root of a system should contain folders or repositories that represent reasonably sized business modules. Each component represents a product domain (i.e., bounded context), like 'user-component', 'order-component', etc. Each component has its own API, logic, and logical database. What is the significant merit? With an autonomous component, every change is performed over a granular and smaller scope - the mental overload, development friction, and deployment fear are much smaller and better. As a result, developers can move much faster. This does not necessarily demand physical separation and can be achieved using a Monorepo or with a multi-repo + +```bash +my-system +├─ apps (components) +│ ├─ orders +│ ├─ users +│ ├─ payments +├─ libraries (generic cross-component functionality) +│ ├─ logger +│ ├─ authenticator +``` + +**Otherwise:** when artifacts from various modules/topics are mixed together, there are great chances of a tightly-coupled 'spaghetti' system. For example, in an architecture where 'module-a controller' might call 'module-b service', there are no clear modularity borders - every code change might affect anything else. With this approach, developers who code new features struggle to realize the scope and impact of their change. Consequently, they fear breaking other modules, and each deployment becomes slower and riskier + +🔗 [**Read More: structure by components**](./sections/projectstructre/breakintcomponents.md)

-# `1. Project Structure Practices` +## ![✔] 1.2 Layer your components with 3-tiers, keep the web layer within its boundaries -## ![✔] 1.1 Structure your solution by components +### `📝 #updated` -**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 +**TL;DR:** Each component should contain 'layers' - a dedicated folder for common concerns: 'entry-point' where controller lives, 'domain' where the logic lives, and 'data-access'. The primary principle of the most popular architectures is to separate the technical concerns (e.g., HTTP, DB, etc) from the pure logic of the app so a developer can code more features without worrying about infrastructural concerns. Putting each concern in a dedicated folder, also known as the [3-Tier pattern](https://en.wikipedia.org/wiki/Multitier_architecture), is the _simplest_ way to meet this goal + +```bash +my-system +├─ apps (components) +│ ├─ component-a + │ ├─ entry-points + │ │ ├─ api # controller comes here + │ │ ├─ message-queue # message consumer comes here + │ ├─ domain # features and flows: DTO, services, logic + │ ├─ data-access # DB calls w/o ORM +``` -**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 +**Otherwise:** It's often seen that developer pass web objects like request/response to functions in the domain/logic layer - this violates the separation principle and makes it harder to access later the logic code by other clients like testing code, scheduled jobs, message queues, etc -🔗 [**Read More: structure by components**](/sections/projectstructre/breakintcomponents.md) +🔗 [**Read More: layer your app**](./sections/projectstructre/createlayers.md)

-## ![✔] 1.2 Layer your components, keep the web layer within its boundaries +## ![✔] 1.3 Wrap common utilities as packages, consider publishing -**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 +**TL;DR:** Place all reusable modules in a dedicated folder, e.g., "libraries", and underneath each module in its own folder, e.g., "/libraries/logger". Make the module an independent package with its own package.json file to increase the module encapsulation, and allows future publishing to a repository. In a Monorepo setup, modules can be consumed by 'npm linking' to their physical paths, using ts-paths or by publishing and installing from a package manager repository like the npm registry -**Otherwise:** App that mixes web objects with other layers cannot be accessed by testing code, CRON jobs, triggers from message queues, etc +```bash +my-system +├─ apps (components) + │ ├─ component-a +├─ libraries (generic cross-component functionality) +│ ├─ logger +│ │ ├─ package.json +│ │ ├─ src +│ │ │ ├─ index.js -🔗 [**Read More: layer your app**](/sections/projectstructre/createlayers.md) +``` + +**Otherwise:** Clients of a module might import and get coupled to internal functionality of a module. With a package.json at the root, one can set a package.json.main or package.json.exports to explicitly tell which files and functions are part of the public interface + +🔗 [**Read More: Structure by feature**](./sections/projectstructre/wraputilities.md)

-## ![✔] 1.3 Wrap common utilities as npm packages +## ![✔] 1.4 Use environment aware, secure and hierarchical config -**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 +### `📝 #updated` -**Otherwise:** You'll have to invent your deployment and the dependency wheel +**TL;DR:** A 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 (d) typing support (e) validation for failing fast (f) Specify default for each key. There are a few packages that can help tick most of those boxes like [convict](https://www.npmjs.com/package/convict), [env-var](https://github.com/evanshortiss/env-var), [zod](https://github.com/colinhacks/zod), and others -🔗 [**Read More: Structure by feature**](/sections/projectstructre/wraputilities.md) +**Otherwise:** Consider a mandatory environment variable that wasn't provided. The app starts successfully and serve requests, some information is already persisted to DB. Then, it's realized that without this mandatory key the request can't complete, leaving the app in a dirty state + +🔗 [**Read More: configuration best practices**](./sections/projectstructre/configguide.md)

-## ![✔] 1.4 Separate Express 'app' and 'server' +## ![✔] 1.5 Consider all the consequences when choosing the main framework -**TL;DR:** Avoid the nasty habit of defining the entire [Express](https://expressjs.com/) 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 +### `🌟 #new` -**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 +**TL;DR:** When building apps and APIs, using a framework is mandatory. It's easy to overlook alternative frameworks or important considerations and then finally land on a sub optimal option. As of 2023/2024, we believe that these four frameworks are worth considering: [Nest.js](https://nestjs.com/), [Fastify](https://www.fastify.io/), [express](https://expressjs.com/), and [Koa](https://koajs.com/). Click read more below for a detailed pros/cons of each framework. Simplistically, we believe that Nest.js is the best match for teams who wish to go OOP and/or build large-scale apps that can't get partitioned into smaller _autonomous_ components. Fastify is our recommendation for apps with reasonably-sized components (e.g., Microservices) that are built around simple Node.js mechanics. Read our [full considerations guide here](./sections/projectstructre/choose-framework.md) -🔗 [**Read More: separate Express 'app' and 'server'**](/sections/projectstructre/separateexpress.md) +**Otherwise:** Due to the overwhelming amount of considerations, it's easy to make decisions based on partial information and compare apples with oranges. For example, it's believed that Fastify is a minimal web-server that should get compared with express only. In reality, it's a rich framework with many official plugins that cover many concerns -

+🔗 [**Read More: Choosing the right framework**](./sections/projectstructre/choose-framework.md) -## ![✔] 1.5 Use environment aware, secure and hierarchical config +## ![✔] 1.6 Use TypeScript sparingly and thoughtfully -**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](https://www.npmjs.com/package/rc), [nconf](https://www.npmjs.com/package/nconf), [config](https://www.npmjs.com/package/config), and [convict](https://www.npmjs.com/package/convict). +### `🌟 #new` -**Otherwise:** Failing to satisfy any of the config requirements will simply bog down the development or DevOps team. Probably both +**TL;DR:** Coding without type safety is no longer an option, TypeScript is the most popular option for this mission. Use it to define variables and functions return types. With that, it is also a double edge sword that can greatly _encourage_ complexity with its additional ~ 50 keywords and sophisticated features. Consider using it sparingly, mostly with simple types, and utilize advanced features only when a real need arises -🔗 [**Read More: configuration best practices**](/sections/projectstructre/configguide.md) +**Otherwise:** [Researches](https://earlbarr.com/publications/typestudy.pdf) show that using TypeScript can help in detecting ~20% bugs earlier. Without it, also the developer experience in the IDE is intolerable. On the flip side, 80% of other bugs were not discovered using types. Consequently, typed syntax is valuable but limited. Only efficient tests can discover the whole spectrum of bugs, including type-related bugs. It might also defeat its purpose: sophisticated code features are likely to increase the code complexity, which by itself increases both the amount of bugs and the average bug fix time + +🔗 [**Read More: TypeScript considerations**](./sections/projectstructre/typescript-considerations.md)


@@ -115,81 +334,89 @@ Read in a different language: [![CN](/assets/flags/CN.png)**CN**](/README.chines ## ![✔] 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 +**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 Promises with async-await 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**](/sections/errorhandling/asyncerrorhandling.md) +🔗 [**Read More: avoiding callbacks**](./sections/errorhandling/asyncerrorhandling.md)

-## ![✔] 2.2 Use only the built-in Error object +## ![✔] 2.2 Extend the built-in Error object + +### `📝 #updated` -**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](https://eslint.org/docs/rules/no-throw-literal) which can be solved when using TypeScript and setting the `@typescript-eslint/no-throw-literal` rule) +**TL;DR:** Some libraries throw errors as a string or as some custom type – this complicates the error handling logic and the interoperability between modules. Instead, create app error object/class that extends the built-in Error object and use it whenever rejecting, throwing or emitting an error. The app error should add useful imperative properties like the error name/code and isCatastrophic. By doing so, all errors have a unified structure and support better error handling. There is `no-throw-literal` ESLint rule that strictly checks that (although it has some [limitations](https://eslint.org/docs/rules/no-throw-literal) 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**](/sections/errorhandling/useonlythebuiltinerror.md) +🔗 [**Read More: using the built-in error object**](./sections/errorhandling/useonlythebuiltinerror.md)

-## ![✔] 2.3 Distinguish operational vs programmer errors +## ![✔] 2.3 Distinguish catastrophic errors from operational errors + +### `📝 #updated` -**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 +**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, catastrophic error (also known as programmer errors) refers to unusual 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 +**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 catastrophic 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**](/sections/errorhandling/operationalvsprogrammererror.md) +🔗 [**Read More: operational vs programmer error**](./sections/errorhandling/operationalvsprogrammererror.md)

## ![✔] 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 +**TL;DR:** Error handling logic such as logging, deciding whether to crash and monitoring metrics should be encapsulated in a dedicated and centralized object that all entry-points (e.g. APIs, cron jobs, scheduled jobs) 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**](/sections/errorhandling/centralizedhandling.md) +🔗 [**Read More: handling errors in a centralized place**](./sections/errorhandling/centralizedhandling.md)

-## ![✔] 2.5 Document API errors using Swagger or GraphQL +## ![✔] 2.5 Document API errors using OpenAPI 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. +**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 OpenAPI. 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**](/sections/errorhandling/documentingusingswagger.md) +🔗 [**Read More: documenting API errors in Swagger or GraphQL**](./sections/errorhandling/documentingusingswagger.md)

## ![✔] 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](https://www.npmjs.com/package/forever) or [PM2](http://pm2.keymetrics.io/) +**TL;DR:** When an unknown error occurs (catastrophic error, see best practice 2.3) - there is uncertainty about the application healthiness. In this case, there is no escape from making the error observable, shutting off connections and exiting the process. Any reputable runtime framework like Dockerized services or cloud serverless solutions will take care to restart **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**](/sections/errorhandling/shuttingtheprocess.md) +🔗 [**Read More: shutting the process**](./sections/errorhandling/shuttingtheprocess.md)

-## ![✔] 2.7 Use a mature logger to increase error visibility +## ![✔] 2.7 Use a mature logger to increase errors visibility -**TL;DR:** A set of mature logging tools like [Pino](https://github.com/pinojs/pino) or [Log4js](https://www.npmjs.com/package/log4js), will speed-up error discovery and understanding. So forget about console.log +### `📝 #updated` + +**TL;DR:** A robust logging tools like [Pino](https://github.com/pinojs/pino) or [Winston](https://github.com/winstonjs/winston) increases the errors visibility using features like log-levels, pretty print coloring and more. Console.log lacks these imperative features and should be avoided. The best in class logger allows attaching custom useful properties to log entries with minimized serialization performance penalty. Developers should write logs to `stdout` and let the infrastructure pipe the stream to the appropriate log aggregator **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**](/sections/errorhandling/usematurelogger.md) +🔗 [**Read More: using a mature logger**](./sections/errorhandling/usematurelogger.md)

## ![✔] 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") +### `📝 #updated` + +**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. On top of this, simulate deeper error flows like uncaught exceptions and ensure that the error handler treat these properly (see code examples within the "read more" section) **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**](/sections/errorhandling/testingerrorflows.md) +🔗 [**Read More: testing error flows**](./sections/errorhandling/testingerrorflows.md)

@@ -199,32 +426,36 @@ Read in a different language: [![CN](/assets/flags/CN.png)**CN**](/README.chines **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**](/sections/errorhandling/apmproducts.md) +🔗 [**Read More: using APM products**](./sections/errorhandling/apmproducts.md)

## ![✔] 2.10 Catch unhandled promise rejections +### `📝 #updated` + **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**](/sections/errorhandling/catchunhandledpromiserejection.md) +🔗 [**Read More: catching unhandled promise rejection**](./sections/errorhandling/catchunhandledpromiserejection.md)

## ![✔] 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](https://www.npmjs.com/package/ajv) and [Joi](https://www.npmjs.com/package/joi) +**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 modern validation library like [ajv](https://www.npmjs.com/package/ajv), [zod](https://github.com/colinhacks/zod), or [typebox](https://github.com/sinclairzx81/typebox) **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**](/sections/errorhandling/failfast.md) +🔗 [**Read More: failing fast**](./sections/errorhandling/failfast.md)

## ![✔] 2.12 Always await promises before returning to avoid a partial stacktrace +### `🌟 #new` + **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 @@ -233,27 +464,39 @@ function returns a promise, that function must be declared as `async` function a 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**](/sections/errorhandling/returningpromises.md) +🔗 [**Read More: returning promises**](./sections/errorhandling/returningpromises.md) + +

+ +## ![✔] 2.13 Subscribe to event emitters and streams 'error' event + +### `🌟 #new` + +**TL;DR:** Unlike typical functions, a try-catch clause won't get errors that originate from Event Emitters and anything inherited from it (e.g., streams). Instead of try-catch, subscribe to an event emitter's 'error' event so your code can handle the error in context. When dealing with [EventTargets](https://nodejs.org/api/events.html#eventtarget-and-event-api) (the web standard version of Event Emitters) there are no 'error' event and all errors end in the process.on('error) global event - in this case, at least ensure that the process crash or not based on the desired context. Also, mind that error originating from _asynchronous_ event handlers are not get caught unless the event emitter is initialized with {captureRejections: true} + +**Otherwise:** Event emitters are commonly used for global and key application functionality such as DB or message queue connection. When this kind of crucial objects throw an error, at best the process will crash due to unhandled exception. Even worst, it will stay alive as a zombie while a key functionality is turned off


⬆ Return to top

-# `3. Code Style Practices` +# `3. Code Patterns And Style Practices` ## ![✔] 3.1 Use ESLint -**TL;DR:** [ESLint](https://eslint.org) 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](https://www.npmjs.com/package/prettier) and [beautify](https://www.npmjs.com/package/js-beautify) are more powerful in formatting the fix and work in conjunction with ESLint +**TL;DR:** [ESLint](https://eslint.org) 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](https://www.npmjs.com/package/prettier) 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**](/sections/codestylepractices/eslint_prettier.md) +🔗 [**Read More: Using ESLint and Prettier**](./sections/codestylepractices/eslint_prettier.md)

-## ![✔] 3.2 Node.js specific plugins +## ![✔] 3.2 Use Node.js eslint extension plugins -**TL;DR:** On top of ESLint standard rules that cover vanilla JavaScript, add Node.js specific plugins like [eslint-plugin-node](https://www.npmjs.com/package/eslint-plugin-node), [eslint-plugin-mocha](https://www.npmjs.com/package/eslint-plugin-mocha) and [eslint-plugin-node-security](https://www.npmjs.com/package/eslint-plugin-security) +### `📝 #updated` + +**TL;DR:** On top of ESLint standard rules that cover vanilla JavaScript, add Node.js specific plugins like [eslint-plugin-node](https://www.npmjs.com/package/eslint-plugin-node), [eslint-plugin-mocha](https://www.npmjs.com/package/eslint-plugin-mocha) and [eslint-plugin-node-security](https://www.npmjs.com/package/eslint-plugin-security), [eslint-plugin-require](https://www.npmjs.com/package/eslint-plugin-require), [/eslint-plugin-jest](https://www.npmjs.com/package/eslint-plugin-jest) and other useful rules **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 @@ -338,24 +581,41 @@ const count = 2 // it tries to run 2(), but 2 is not a function ## ![✔] 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 +**TL;DR:** Use **_lowerCamelCase_** when naming constants, variables and functions, **_UpperCamelCase_** (capital first letter as well) when naming classes and **_UPPER_SNAKE_CASE_** when naming global or static variables. This will help you to easily distinguish between plain variables, functions, classes that require instantiation and variables declared at global module scope. 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 ```javascript -// for class name we use UpperCamelCase -class SomeClassExample {} - -// for const names we use the const keyword and lowerCamelCase -const config = { +// for global variables names we use the const/let keyword and UPPER_SNAKE_CASE +let MUTABLE_GLOBAL = "mutable value"; +const GLOBAL_CONSTANT = "immutable value"; +const CONFIG = { key: "value", }; -// for variables and functions names we use lowerCamelCase -let someVariableExample = "value"; -function doSomething() {} +// examples of UPPER_SNAKE_CASE convention in nodejs/javascript ecosystem +// in javascript Math.PI module +const PI = 3.141592653589793; + +// https://github.com/nodejs/node/blob/b9f36062d7b5c5039498e98d2f2c180dca2a7065/lib/internal/http2/core.js#L303 +// in nodejs http2 module +const HTTP_STATUS_OK = 200; +const HTTP_STATUS_CREATED = 201; + +// for class name we use UpperCamelCase +class SomeClassExample { + // for static class properties we use UPPER_SNAKE_CASE + static STATIC_PROPERTY = "value"; +} + +// for functions names we use lowerCamelCase +function doSomething() { + // for scoped variable names we use the const/let keyword and lowerCamelCase + const someConstExample = "immutable value"; + let someMutableExample = "mutable value"; +} ```

@@ -378,22 +638,29 @@ function doSomething() {}

-## ![✔] 3.9 Require modules by folders, as opposed to the files directly +## ![✔] 3.9 Set an explicit entry point to a module/folder -**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 +### `📝 #updated` -**Otherwise:** Changing the internal structure of files or the signature may break the interface with clients +**TL;DR:** When developing a module/library, set an explicit root file that exports the public and interesting code. Discourage the client code from importing deep files and becoming familiar with the internal structure. With commonjs (require), this can be done with an index.js file at the folder's root or the package.json.main field. With ESM (import), if a package.json exists on the root, the field "exports" allow specifying the module's root file. If no package.json exists, you may put an index.js file on the root which re-exports all the public functionality -### 3.9 Code example +**Otherwise:** Having an explicit root file acts like a public 'interface' that encapsulates the internal, directs the caller to the public code and facilitates future changes without breaking the contract + +### 3.9 Code example - avoid coupling the client to the module structure ```javascript -// Do -module.exports.SMSProvider = require("./SMSProvider"); -module.exports.SMSNumberResolver = require("./SMSNumberResolver"); +// Avoid: client has deep familiarity with the internals -// Avoid -module.exports.SMSProvider = require("./SMSProvider/SMSProvider.js"); -module.exports.SMSNumberResolver = require("./SMSNumberResolver/SMSNumberResolver.js"); +// Client code +const SMSWithMedia = require("./SMSProvider/providers/media/media-provider.js"); + +// Better: explicitly export the public functions + +//index.js, module code +module.exports.SMSWithMedia = require("./SMSProvider/providers/media/media-provider.js"); + +// Client code +const { SMSWithMedia } = require("./SMSProvider"); ```

@@ -427,7 +694,7 @@ 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 +**TL;DR:** Async-await is the simplest way to express an asynchronous flow as it makes asynchronous code look synchronous. Async-await will also result in much more compact code and support for try-catch. This technique now supersedes callbacks and promises in _most_ cases. Using it in your code is probably the best gift one can give to the code reader **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 @@ -443,15 +710,31 @@ All statements above will return false if used with `===` 🔗 [**Read more: It’s Time to Embrace Arrow Functions**](https://medium.com/javascript-scene/familiarity-bias-is-holding-you-back-its-time-to-embrace-arrow-functions-3d37e1a9bb75) +

+ +## ![✔] 3.13 Avoid effects outside of functions + +### `🌟 #new` + +**TL;DR:** Avoid putting code with effects like network or DB calls outside of functions. Such a code will be executed immediately when another file requires the file. This 'floating' code might get executed when the underlying system is not ready yet. It also comes with a performance penalty even when this module's functions will finally not be used in runtime. Last, mocking these DB/network calls for testing is harder outside of functions. Instead, put this code inside functions that should get called explicitly. If some DB/network code must get executed right when the module loads, consider using the factory or revealing module patterns + +**Otherwise:** A typical web framework sets error handler, environment variables and monitoring. When DB/network calls are made before the web framework is initialized, they won't be monitored or fail due to a lack of configuration data +


⬆ Return to top

# `4. Testing And Overall Quality Practices` +\_We have dedicated guides for testing, see below. The best practices list here is a brief summary of these guides + +a. [JavaScript testing best practices](https://github.com/goldbergyoni/javascript-testing-best-practices) +b. [Node.js testing - beyond the basics](https://github.com/testjavascript/nodejs-integration-tests-best-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](https://www.getpostman.com/)). Afterward, should you have more resources and time, continue with advanced test types like unit testing, DB testing, performance testing, etc +**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](https://www.getpostman.com/)). Afterwards, 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 @@ -459,29 +742,35 @@ All statements above will return false if used with `===` ## ![✔] 4.2 Include 3 parts in each test name +### `🌟 #new` + **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**](/sections/testingandquality/3-parts-in-name.md) +🔗 [**Read More: Include 3 parts in each test name**](./sections/testingandquality/3-parts-in-name.md)

## ![✔] 4.3 Structure tests by the AAA pattern +### `🌟 #new` + **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**](/sections/testingandquality/aaa.md) +🔗 [**Read More: Structure tests by the AAA pattern**](./sections/testingandquality/aaa.md)

-## ![✔] 4.4 Detect code issues with a linter +## ![✔] 4.4 Ensure Node version is unified + +### `🌟 #new` -**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](#3-code-style-practices) on Code Style Practices +**TL;DR:** Use tools that encourage or enforce the same Node.js version across different environments and developers. Tools like [nvm](https://github.com/nvm-sh/nvm), and [Volta](https://volta.sh/) allow specifying the project's version in a file so each team member can run a single command to conform with the project's version. Optionally, this definition can be replicated to CI and the production runtime (e.g., copy the specified value to .Dockerfile build and to the CI declaration file) -**Otherwise:** You may let pass some anti-pattern and possible vulnerable code to your production environment. +**Otherwise:** A developer might face or miss an error because she uses a different Node.js version than her teammates. Even worse - the production runtime might be different than the environment where tests were executed

@@ -491,19 +780,11 @@ All statements above will return false if used with `===` **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**](/sections/testingandquality/avoid-global-test-fixture.md) - -

- -## ![✔] 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](https://docs.npmjs.com/cli/audit) and 🔗 [snyk.io](https://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 +🔗 [**Read More: Avoid global test fixtures**](./sections/testingandquality/avoid-global-test-fixture.md)

-## ![✔] 4.7 Tag your tests +## ![✔] 4.6 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](https://mochajs.org/): mocha --grep 'sanity' @@ -511,7 +792,7 @@ All statements above will return false if used with `===`

-## ![✔] 4.8 Check your test coverage, it helps to identify wrong test patterns +## ![✔] 4.7 Check your test coverage, it helps to identify wrong test patterns **TL;DR:** Code coverage tools like [Istanbul](https://github.com/istanbuljs/istanbuljs)/[NYC](https://github.com/istanbuljs/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 @@ -519,15 +800,7 @@ All statements above will return false if used with `===`

-## ![✔] 4.9 Inspect for outdated packages - -**TL;DR:** Use your preferred tool (e.g. `npm outdated` or [npm-check-updates](https://www.npmjs.com/package/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 +## ![✔] 4.8 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) @@ -535,31 +808,53 @@ All statements above will return false if used with `===`

-## ![✔] 4.11 Refactor regularly using static analysis tools +## ![✔] 4.9 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](https://www.sonarqube.org/) (2,600+ [stars](https://github.com/SonarSource/sonarqube)) and [Code Climate](https://codeclimate.com/) (1,500+ [stars](https://github.com/codeclimate/codeclimate)). **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!**](/sections/testingandquality/refactoring.md) +🔗 [**Read More: Refactoring!**](./sections/testingandquality/refactoring.md)

-## ![✔] 4.12 Carefully choose your CI platform (Jenkins vs CircleCI vs Travis vs Rest of the world) +## ![✔] 4.10 Mock responses of external HTTP services -**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](https://jenkins.io/) 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](https://circleci.com) 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 +### `🌟 #new` -**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 +**TL;DR:** Use network mocking tools to simulate responses of external collaborators' services that are approached over the network (e.g., REST, Graph). This is imperative not only to isolate the component under test but mostly to simulate non-happy path flows. Tools like [nock](https://github.com/nock/nock) (in-process) or [Mock-Server](https://www.mock-server.com/) allow defining a specific response of external service in a single line of code. Remember to simulate also errors, delays, timeouts, and any other event that is likely to happen in production -🔗 [**Read More: Choosing CI platform**](/sections/testingandquality/citools.md) +**Otherwise:** Allowing your component to reach real external services instances will likely result in naive tests that mostly cover happy paths. The tests might also be flaky and slow -## ![✔] 4.13 Test your middlewares in isolation +🔗 [**Read More: Mock external services**](./sections/testingandquality/mock-external-services.md) + +## ![✔] 4.11 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**](/sections/testingandquality/test-middlewares.md) +🔗 [**Read More: Test middlewares in isolation**](./sections/testingandquality/test-middlewares.md) + +## ![✔] 4.12 Specify a port in production, randomize in testing + +### `🌟 #new` + +**TL;DR:** When testing against the API, it's common and desirable to initialize the web server inside the tests. Let the server randomize the web server port in testing to prevent collisions. If you're using Node.js http server (used by most frameworks), doing so demands nothing but passing a port number zero - this will randomize an available port + +**Otherwise:** Specifying a fixed port will prevent two testing processes from running at the same time. Most of the modern test runners run with multiple processes by default + +🔗 [**Read More: Randomize a port for testing**](./sections/testingandquality/randomize-port.md) + +## ![✔] 4.13 Test the five possible outcomes + +### `🌟 #new` + +**TL;DR:** When testing a flow, ensure to cover five potential categories. Any time some action is triggered (e.g., API call), a reaction occurs, a meaningful **outcome** is produced and calls for testing. There are five possible outcome types for every flow: a response, a visible state change (e.g., DB), an outgoing API call, a new message in a queue, and an observability call (e.g., logging, metric). See a [checklist here](https://testjavascript.com/wp-content/uploads/2021/10/the-backend-checklist.pdf). Each type of outcome comes with unique challenges and techniques to mitigate those challenges - we have a dedicated guide about this topic: [Node.js testing - beyond the basics](https://github.com/testjavascript/nodejs-integration-tests-best-practices) + +**Otherwise:** Consider a case when testing the addition of a new product to the system. It's common to see tests that assert on a valid response only. What if the product was failed to persist regardless of the positive response? what if when adding a new product demands calling some external service, or putting a message in the queue - shouldn't the test assert these outcomes as well? It's easy to overlook various paths, this is where a [checklist comes handy](https://testjavascript.com/wp-content/uploads/2021/10/the-backend-checklist.pdf) + +🔗 [**Read More: Test five outcomes**](./sections/testingandquality/test-five-outcomes.md)


@@ -569,91 +864,93 @@ All statements above will return false if used with `===` ## ![✔] 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 +**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. In any case, the 4 layers of observability must be covered: uptime, metrics with focus on user-facing symptoms and Node.js technical metrics like event loop lag, distributed flows measurement with Open Telemetry and logging. Click ‘Read More’ below for an overview of the solutions **Otherwise:** Failure === disappointed customers. Simple -🔗 [**Read More: Monitoring!**](/sections/production/monitoring.md) +🔗 [**Read More: Monitoring!**](./sections/production/monitoring.md)

-## ![✔] 5.2. Increase transparency using smart logging +## ![✔] 5.2. Increase the observability 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**](/sections/production/smartlogging.md) +🔗 [**Read More: Increase transparency using smart logging**](./sections/production/smartlogging.md)

## ![✔] 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 +**TL;DR:** Node is quite bad at doing CPU intensive tasks like gzipping, SSL termination, etc. You should use specialized infrastructure 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**](/sections/production/delegatetoproxy.md) +🔗 [**Read More: Delegate anything possible (e.g. gzip, SSL) to a reverse proxy**](./sections/production/delegatetoproxy.md)

## ![✔] 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 +**TL;DR:** Your code must be identical across all environments, but without a special lockfile npm lets dependencies drift across environments. Ensure to commit your package-lock.json so all the environments will be identical **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**](/sections/production/lockdependencies.md) +🔗 [**Read More: Lock dependencies**](./sections/production/lockdependencies.md)

## ![✔] 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 +**TL;DR:** The process must go on and get restarted upon failures. Modern runtime platforms like Docker-ized platforms (e.g. Kubernetes), and Serverless take care for this automatically. When the app is hosted on a bare metal server, one must take care for a process management tools like [systemd](https://systemd.io/). Avoid including a custom process management tool in a modern platform that monitors an app instance (e.g., Kubernetes) - doing so will hide failures from the infrastructure. When the underlying infrastructure is not aware of errors, it can't perform useful mitigation steps like re-placing the instance in a different location **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**](/sections/production/guardprocess.md) +🔗 [**Read More: Guard process uptime using the right tool**](./sections/production/guardprocess.md)

## ![✔] 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) +**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. Most of the modern run-times platform (e.g., Kubernetes) allow replicating instances of the app but they won't verify that all cores are utilized - this is your duty. If the app is hosted on a bare server, it's also your duty to use some process replication solution (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**](/sections/production/utilizecpu.md) +🔗 [**Read More: Utilize all CPU cores**](./sections/production/utilizecpu.md)

## ![✔] 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 +**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-tested 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’**](/sections/production/createmaintenanceendpoint.md) +🔗 [**Read More: Create a ‘maintenance endpoint’**](./sections/production/createmaintenanceendpoint.md)

-## ![✔] 5.8. Discover errors and downtime using APM products +## ![✔] 5.8. Discover the unknowns 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 +### `📝 #updated` + +**TL;DR:** Consider adding another safety layer to the production stack - APM. While the majority of symptoms and causes can be detected using traditional monitoring techniques, in a distributed system there is more than meets the eye. Application monitoring and performance products (a.k.a. APM) can auto-magically go beyond traditional monitoring and provide additional layer of discovery and developer-experience. For example, some APM products can highlight a transaction that loads too slow on the **end-user's side** while suggesting the root cause. APMs also provide more context for developers who try to troubleshoot a log error by showing what was the server busy with when the error occurred. To name a few example **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**](/sections/production/apmproducts.md) +🔗 [**Read More: Discover errors and downtime using APM products**](./sections/production/apmproducts.md)

## ![✔] 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) +**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 'Read More') **Otherwise:** A world champion IT/DevOps guy won’t save a system that is badly written -🔗 [**Read More: Make your code production-ready**](/sections/production/productioncode.md) +🔗 [**Read More: Make your code production-ready**](./sections/production/productioncode.md)

@@ -663,27 +960,27 @@ All statements above will return false if used with `===` **Otherwise:** Your process memory might leak a hundred megabytes a day like how it happened at [Walmart](https://www.joyent.com/blog/walmart-node-js-memory-leak) -🔗 [**Read More: Measure and guard the memory usage**](/sections/production/measurememory.md) +🔗 [**Read More: Measure and guard the memory usage**](./sections/production/measurememory.md)

## ![✔] 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 +**TL;DR:** Serve frontend content using a specialized infrastructure (nginx, S3, CDN) because Node performance gets hurt when dealing with many static files due to its single-threaded model. One exception to this guideline is when doing server-side rendering **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**](/sections/production/frontendout.md) +🔗 [**Read More: Get your frontend assets out of Node**](./sections/production/frontendout.md)

-## ![✔] 5.12. Be stateless, kill your servers almost every day +## ![✔] 5.12. Strive to be stateless -**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 +**TL;DR:** Store any type of _data_ (e.g. user sessions, cache, uploaded files) within external data stores. When the app holds data in-process this adds additional layer of maintenance complexity like routing users to the same instance and higher cost of restarting a process. To enforce and encourage a stateless approach, most modern runtime platforms allows 'reapp-ing' instances periodically **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**](/sections/production/bestateless.md) +🔗 [**Read More: Be stateless, kill your Servers almost every day**](./sections/production/bestateless.md)

@@ -693,29 +990,27 @@ All statements above will return false if used with `===` **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**](/sections/production/detectvulnerabilities.md) +🔗 [**Read More: Use tools that automatically detect vulnerabilities**](./sections/production/detectvulnerabilities.md)

## ![✔] 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 +**TL;DR:** Assign the same identifier, transaction-id: uuid(), to each log entry within a single request (also known as correlation-id/tracing-id/request-context). Then when inspecting errors in logs, easily conclude what happened before and after. Node has a built-in mechanism, [AsyncLocalStorage](https://nodejs.org/api/async_context.html), for keeping the same context across asynchronous calls. 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**](/sections/production/assigntransactionid.md) +🔗 [**Read More: Assign ‘TransactionId’ to each log statement**](./sections/production/assigntransactionid.md)

## ![✔] 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 +**TL;DR:** Set the environment variable `NODE_ENV` to ‘production’ or ‘development’ to flag whether production optimizations should get activated – some 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! +**Otherwise:** Omitting this simple property might greatly degrade performance when dealing with some specific libraries like Express server-side rendering -🔗 [**Read More: Set NODE_ENV=production**](/sections/production/setnodeenv.md) +🔗 [**Read More: Set NODE_ENV=production**](./sections/production/setnodeenv.md)

@@ -733,27 +1028,29 @@ Also known as correlation id / transit id / tracing id / request id / request co **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**](/sections/production/LTSrelease.md) +🔗 [**Read More: Use an LTS release of Node.js**](./sections/production/LTSrelease.md)

-## ![✔] 5.18. Don't route logs within the app +## ![✔] 5.18. Log to stdout, avoid specifying log destination within the app + +### `📝 #updated` **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 +**Otherwise:** If developers set the log routing, less flexibility is left for the ops professional who wishes to customize it. Beyond this, if the app tries to log directly to a remote location (e.g., Elastic Search), in case of panic or crash - further logs that might explain the problem won't arrive -🔗 [**Read More: Log Routing**](/sections/production/logrouting.md) +🔗 [**Read More: Log Routing**](./sections/production/logrouting.md)

## ![✔] 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. +**TL;DR:** Run `npm ci` to strictly do a clean install of your dependencies matching package.json and package-lock.json. Obviously production code must use the exact version of the packages that were used for testing. While package-lock.json file sets strict version for dependencies, in case of mismatch with the file package.json, the command 'npm install' will treat package.json as the source of truth. On the other hand, the command 'npm ci' will exit with error in case of mismatch between these files **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**](/sections/production/installpackageswithnpmci.md) +🔗 [**Read More: Use npm ci**](./sections/production/installpackageswithnpmci.md)


@@ -773,7 +1070,7 @@ Also known as correlation id / transit id / tracing id / request id / request co **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**](/sections/security/lintrules.md) +🔗 [**Read More: Lint rules**](./sections/security/lintrules.md)

@@ -785,7 +1082,7 @@ Also known as correlation id / transit id / tracing id / request id / request co **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**](/sections/security/limitrequests.md) +🔗 [**Read More: Implement rate limiting**](./sections/security/limitrequests.md)

@@ -797,7 +1094,7 @@ Also known as correlation id / transit id / tracing id / request id / request co **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**](/sections/security/secretmanagement.md) +🔗 [**Read More: Secret management**](./sections/security/secretmanagement.md)

@@ -809,7 +1106,7 @@ Also known as correlation id / transit id / tracing id / request id / request co **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**](/sections/security/ormodmusage.md) +🔗 [**Read More: Query injection prevention using ORM/ODM libraries**](./sections/security/ormodmusage.md)

@@ -817,7 +1114,7 @@ Also known as correlation id / transit id / tracing id / request id / request co **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**](/sections/security/commonsecuritybestpractices.md) +🔗 [**Read More: Common security best practices**](./sections/security/commonsecuritybestpractices.md)

@@ -829,7 +1126,7 @@ Also known as correlation id / transit id / tracing id / request id / request co **Otherwise:** Attackers could perform direct attacks on your application's users, leading to huge security vulnerabilities -🔗 [**Read More: Using secure headers in your application**](/sections/security/secureheaders.md) +🔗 [**Read More: Using secure headers in your application**](./sections/security/secureheaders.md)

@@ -841,7 +1138,7 @@ Also known as correlation id / transit id / tracing id / request id / request co **Otherwise:** An attacker could detect your web framework and attack all its known vulnerabilities. -🔗 [**Read More: Dependency security**](/sections/security/dependencysecurity.md) +🔗 [**Read More: Dependency security**](./sections/security/dependencysecurity.md)

@@ -853,7 +1150,7 @@ Also known as correlation id / transit id / tracing id / request id / request co **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**](/sections/security/userpasswords.md) +🔗 [**Read More: User Passwords**](./sections/security/userpasswords.md)

@@ -865,7 +1162,7 @@ Also known as correlation id / transit id / tracing id / request id / request co **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**](/sections/security/escape-output.md) +🔗 [**Read More: Escape output**](./sections/security/escape-output.md)

@@ -877,7 +1174,7 @@ Also known as correlation id / transit id / tracing id / request id / request co **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**](/sections/security/validation.md) +🔗 [**Read More: Validate incoming JSON schemas**](./sections/security/validation.md)

@@ -889,7 +1186,7 @@ Also known as correlation id / transit id / tracing id / request id / request co **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**](/sections/security/expirejwt.md) +🔗 [**Read More: Blocklist JSON Web Tokens**](./sections/security/expirejwt.md)

@@ -904,7 +1201,7 @@ Also known as correlation id / transit id / tracing id / request id / request co **Otherwise:** An attacker can issue unlimited automated password attempts to gain access to privileged accounts on an application -🔗 [**Read More: Login rate limiting**](/sections/security/login-rate-limit.md) +🔗 [**Read More: Login rate limiting**](./sections/security/login-rate-limit.md)

@@ -914,9 +1211,9 @@ Also known as correlation id / transit id / tracing id / request id / request co **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) +**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 their server) -🔗 [**Read More: Run Node.js as non-root user**](/sections/security/non-root-user.md) +🔗 [**Read More: Run Node.js as non-root user**](./sections/security/non-root-user.md)

@@ -928,7 +1225,7 @@ Also known as correlation id / transit id / tracing id / request id / request co **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**](/sections/security/requestpayloadsizelimit.md) +🔗 [**Read More: Limit payload size**](./sections/security/requestpayloadsizelimit.md)

@@ -940,7 +1237,7 @@ Also known as correlation id / transit id / tracing id / request id / request co **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**](/sections/security/avoideval.md) +🔗 [**Read More: Avoid JavaScript eval statements**](./sections/security/avoideval.md)

@@ -952,7 +1249,7 @@ Also known as correlation id / transit id / tracing id / request id / request co **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**](/sections/security/regex.md) +🔗 [**Read More: Prevent malicious RegEx**](./sections/security/regex.md)

@@ -964,7 +1261,7 @@ Also known as correlation id / transit id / tracing id / request id / request co **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**](/sections/security/safemoduleloading.md) +🔗 [**Read More: Safe module loading**](./sections/security/safemoduleloading.md)

@@ -976,7 +1273,7 @@ Also known as correlation id / transit id / tracing id / request id / request co **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**](/sections/security/sandbox.md) +🔗 [**Read More: Run unsafe code in a sandbox**](./sections/security/sandbox.md)

@@ -988,7 +1285,7 @@ Also known as correlation id / transit id / tracing id / request id / request co **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**](/sections/security/childprocesses.md) +🔗 [**Read More: Be cautious when working with child processes**](./sections/security/childprocesses.md)

@@ -1000,7 +1297,7 @@ Also known as correlation id / transit id / tracing id / request id / request co **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**](/sections/security/hideerrors.md) +🔗 [**Read More: Hide error details from client**](./sections/security/hideerrors.md)

@@ -1022,7 +1319,7 @@ Also known as correlation id / transit id / tracing id / request id / request co **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**](/sections/security/sessions.md) +🔗 [**Read More: Cookie and session security**](./sections/security/sessions.md)

@@ -1044,7 +1341,7 @@ Also known as correlation id / transit id / tracing id / request id / request co **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**](/sections/security/saferedirects.md) +🔗 [**Read More: Prevent unsafe redirects**](./sections/security/saferedirects.md)

@@ -1056,7 +1353,40 @@ Also known as correlation id / transit id / tracing id / request id / request co **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**](/sections/security/avoid_publishing_secrets.md) +🔗 [**Read More: Avoid publishing secrets**](./sections/security/avoid_publishing_secrets.md) + +

+ +## ![✔] 6.26 Inspect for outdated packages + +**TL;DR:** Use your preferred tool (e.g. `npm outdated` or [npm-check-updates](https://www.npmjs.com/package/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 + +

+ +## ![✔] 6.27. Import built-in modules using the 'node:' protocol + +### `🌟 #new` + + + +**TL;DR:** Import or require built-in Node.js modules using the 'node protocol' syntax: + +```javascript +import { functionName } from "node:module"; // note that 'node:' prefix +``` + +For example: + +```javascript +import { createServer } from "node:http"; +``` + +This style ensures that there is no ambiguity with global npm packages and makes it clear for the reader that the code refers to a well-trusted official module. This style can be enforced with the eslint rule ['prefer-node-protocol'](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-node-protocol.md) + +**Otherwise:** Using the import syntax without 'node:' prefix opens the door for [typosquatting attacks](https://en.wikipedia.org/wiki/Typosquatting) where one could mistakenly mistype a module name (e.g., 'event' instead of 'events) and get a malicious package that was built only to trick users into installing them +


⬆ Return to top

@@ -1073,7 +1403,7 @@ Also known as correlation id / transit id / tracing id / request id / request co **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**](/sections/performance/block-loop.md) +🔗 [**Read More: Do not block the event loop**](./sections/performance/block-loop.md)


@@ -1084,7 +1414,7 @@ Bear in mind that with the introduction of the new V8 engine alongside the new E **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**](/sections/performance/nativeoverutil.md) +🔗 [**Read More: Native over user land utils**](./sections/performance/nativeoverutil.md)


@@ -1110,6 +1440,7 @@ FROM node:14.4.0 AS build COPY . . RUN npm ci && npm run build + FROM node:slim-14.4.0 USER node @@ -1121,17 +1452,19 @@ RUN npm ci --production CMD [ "node", "dist/app.js" ] ``` -🔗 [**Read More: Use multi-stage builds**](/sections/docker/multi_stage_builds.md) +🔗 [**Read More: Use multi-stage builds**](./sections/docker/multi_stage_builds.md)


## ![✔] 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. +**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 + +Update: [Starting from npm 7, npm claim](https://docs.npmjs.com/cli/v7/using-npm/changelog#706-2020-10-27) to pass signals. We follow and will update accordingly -**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. +**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**](/sections/docker/bootstrap-using-node.md) +[**Read More: Bootstrap container using node command, avoid npm start**](./sections/docker/bootstrap-using-node.md)


@@ -1141,7 +1474,7 @@ CMD [ "node", "dist/app.js" ] **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**](/sections/docker/restart-and-replicate-processes.md) +🔗 [**Read More: Let the Docker orchestrator restart and replicate processes**](./sections/docker/restart-and-replicate-processes.md)


@@ -1151,7 +1484,7 @@ CMD [ "node", "dist/app.js" ] **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**](/sections/docker/docker-ignore.md) +🔗 [**Read More: Use .dockerignore**](./sections/docker/docker-ignore.md)


@@ -1161,17 +1494,17 @@ CMD [ "node", "dist/app.js" ] **Otherwise:** Many of the infamous npm security breaches were found within development packages (e.g. [eslint-scope](https://eslint.org/blog/2018/07/postmortem-for-malicious-package-publishes)) -🔗 Read More: [Remove development dependencies](/sections/docker/install-for-production.md) +🔗 Read More: [Remove development dependencies](./sections/docker/install-for-production.md)


## ![✔] 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 +**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**](/sections/docker/graceful-shutdown.md) +🔗 [**Read More: Graceful shutdown**](./sections/docker/graceful-shutdown.md)


@@ -1181,7 +1514,7 @@ CMD [ "node", "dist/app.js" ] **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**](/sections/docker/memory-limit.md) +🔗 [**Read More: Set memory limits using Docker only**](./sections/docker/memory-limit.md)


@@ -1191,7 +1524,7 @@ CMD [ "node", "dist/app.js" ] **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**](/sections/docker/use-cache-for-shorter-build-time.md) +🔗 [**Read More: Leverage caching to reduce build times**](./sections/docker/use-cache-for-shorter-build-time.md)


@@ -1203,7 +1536,7 @@ In addition, referring to an image tag means that the base image is subject to c **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**](/sections/docker/image-tags.md) +🔗 [**Read More: Understand image tags and use the "latest" tag with caution**](./sections/docker/image-tags.md)


@@ -1213,17 +1546,19 @@ In addition, referring to an image tag means that the base image is subject to c **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**](/sections/docker/smaller_base_images.md) +🔗 [**Read More: Prefer smaller images**](./sections/docker/smaller_base_images.md)


## ![✔] 8.11. Clean-out build-time secrets, avoid secrets in args +### `🌟 #new` + **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**](/sections/docker/avoid-build-time-secrets.md) +🔗 [**Read More: Clean-out build-time secrets**](./sections/docker/avoid-build-time-secrets.md)


@@ -1233,7 +1568,7 @@ In addition, referring to an image tag means that the base image is subject to c **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: Generic Docker practices**](/sections/docker/scan-images.md) +🔗 [**Read More: Scan the entire image before production**](./sections/docker/scan-images.md)


@@ -1243,7 +1578,7 @@ In addition, referring to an image tag means that the base image is subject to c **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**](/sections/docker/clean-cache.md) +🔗 [**Read More: Clean NODE_MODULE cache**](./sections/docker/clean-cache.md)


@@ -1251,17 +1586,19 @@ In addition, referring to an image tag means that the base image is subject to c **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**](/sections/docker/generic-tips.md) +🔗 [**Read More: Generic Docker practices**](./sections/docker/generic-tips.md)


## ![✔] 8.15. Lint your Dockerfile +### `🌟 #new` + **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**](/sections/docker/lint-dockerfile.md) +🔗 [**Read More: Lint your Dockerfile**](./sections/docker/lint-dockerfile.md)


@@ -1279,20 +1616,21 @@ All translations are contributed by the community. We will be happy to get any h ### Completed translations -- ![BR](/assets/flags/BR.png) [Brazilian Portuguese](./README.brazilian-portuguese.md) - Courtesy of [Marcelo Melo](https://github.com/marcelosdm) -- ![CN](/assets/flags/CN.png) [Chinese](./README.chinese.md) - Courtesy of [Matt Jin](https://github.com/mattjin) -- ![RU](/assets/flags/RU.png) [Russian](./README.russian.md) - Courtesy of [Alex Ivanov](https://github.com/contributorpw) -- ![PL](/assets/flags/PL.png) [Polish](./README.polish.md) - Courtesy of [Michal Biesiada](https://github.com/mbiesiad) -- ![JA](/assets/flags/JA.png) [Japanese](./README.japanese.md) - Courtesy of [Yuki Ota](https://github.com/YukiOta), [Yuta Azumi](https://github.com/YA21) +- ![BR](./assets/flags/BR.png) [Brazilian Portuguese](./README.brazilian-portuguese.md) - Courtesy of [Marcelo Melo](https://github.com/marcelosdm) +- ![CN](./assets/flags/CN.png) [Chinese](./README.chinese.md) - Courtesy of [Matt Jin](https://github.com/mattjin) +- ![RU](./assets/flags/RU.png) [Russian](./README.russian.md) - Courtesy of [Alex Ivanov](https://github.com/contributorpw) +- ![PL](./assets/flags/PL.png) [Polish](./README.polish.md) - Courtesy of [Michal Biesiada](https://github.com/mbiesiad) +- ![JA](./assets/flags/JA.png) [Japanese](./README.japanese.md) - Courtesy of [Yuki Ota](https://github.com/YukiOta), [Yuta Azumi](https://github.com/YA21) +- ![EU](./assets/flags/EU.png) [Basque](README.basque.md) - Courtesy of [Ane Diaz de Tuesta](https://github.com/anediaz) & Joxefe Diaz de Tuesta ### Translations in progress -- ![FR](/assets/flags/FR.png) [French](https://github.com/gaspaonrocks/nodebestpractices/blob/french-translation/README.french.md) ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/129)) -- ![HE](/assets/flags/HE.png) Hebrew ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/156)) -- ![KR](/assets/flags/KR.png) [Korean](README.korean.md) - Courtesy of [Sangbeom Han](https://github.com/uronly14me) ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/94)) -- ![ES](/assets/flags/ES.png) [Spanish](https://github.com/goldbergyoni/nodebestpractices/blob/spanish-translation/README.spanish.md) ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/95)) -- ![TR](/assets/flags/TR.png) Turkish ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/139)) -- ![EU](/assets/flags/EU.png) [Basque](README.basque.md) - Courtesy of [Ane Diaz de Tuesta](https://github.com/anediaz) & Joxefe Diaz de Tuesta ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/842)) +- ![FR](./assets/flags/FR.png) [French](./README.french.md) ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/129)) +- ![HE](./assets/flags/HE.png) [Hebrew](./README.hebrew.md) ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/156)) +- ![KR](./assets/flags/KR.png) [Korean](README.korean.md) - Courtesy of [Sangbeom Han](https://github.com/uronly14me) ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/94)) +- ![ES](./assets/flags/ES.png) [Spanish](https://github.com/goldbergyoni/nodebestpractices/blob/spanish-translation/README.spanish.md) ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/95)) +- ![TR](./assets/flags/TR.png) Turkish ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/139)) +- ![AR](./assets/flags/AR.png) [Arabic](https://github.com/goldbergyoni/nodebestpractices/blob/spanish-translation/README.arabic.md)

@@ -1300,278 +1638,340 @@ All translations are contributed by the community. We will be happy to get any h 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](https://github.com/goldbergyoni/nodebestpractices/projects). - + [Yoni Goldberg](https://github.com/goldbergyoni) - - + + 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](https://goldbergyoni.com). Reach Yoni at [@goldbergyoni](https://github.com/goldbergyoni) or [me@goldbergyoni.com](mailto:me@goldbergyoni.com)
- +Josh Hemphill -[Bruno Scheufler](https://github.com/BrunoScheufler) - +[Josh Hemphill](https://github.com/josh-hemphill) + + + -💻 full-stack web engineer, Node.js & GraphQL enthusiast +Full Stack Software Engineer / Developer specializing in Security, DevOps/DevSecOps, and ERP Integrations.
- +Raz Luvaton -[Kyle Martin](https://github.com/js-kyle) - - +[Raz Luvaton](https://github.com/rluvaton) + + -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. +Full Stack Developer who knows how to exit from Vim and loves Architecture, Virtualization and Security.
- - -[Kevyn Bruyere](https://github.com/kevynb) - +## Contributing -Independent full-stack developer with a taste for Ops and automation. +If you've ever wanted to contribute to open source, now is your chance! See the [contributing docs](.operations/CONTRIBUTING.md) for more information. -
+## Contributors ✨ -### Steering Committee Emeriti +Thanks goes to these wonderful people who have contributed to this repository! - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Kevin Rambaud
Kevin Rambaud

🖋
Michael Fine
Michael Fine

🖋
Shreya Dahal
Shreya Dahal

🖋
Matheus Cruz Rocha
Matheus Cruz Rocha

🖋
Yog Mehta
Yog Mehta

🖋
Kudakwashe Paradzayi
Kudakwashe Paradzayi

🖋
t1st3
t1st3

🖋
mulijordan1976
mulijordan1976

🖋
Matan Kushner
Matan Kushner

🖋
Fabio Hiroki
Fabio Hiroki

🖋
James Sumners
James Sumners

🖋
Dan Gamble
Dan Gamble

🖋
PJ Trainor
PJ Trainor

🖋
Remek Ambroziak
Remek Ambroziak

🖋
Yoni Jah
Yoni Jah

🖋
Misha Khokhlov
Misha Khokhlov

🖋
Evgeny Orekhov
Evgeny Orekhov

🖋
-
-

🖋
Isaac Halvorson
Isaac Halvorson

🖋
Vedran Karačić
Vedran Karačić

🖋
lallenlowe
lallenlowe

🖋
Nathan Wells
Nathan Wells

🖋
Paulo Reis
Paulo Reis

🖋
syzer
syzer

🖋
David Sancho
David Sancho

🖋
Robert Manolea
Robert Manolea

🖋
Xavier Ho
Xavier Ho

🖋
Aaron
Aaron

🖋
Jan Charles Maghirang Adona
Jan Charles Maghirang Adona

🖋
Allen
Allen

🖋
Leonardo Villela
Leonardo Villela

🖋
Michał Załęcki
Michał Załęcki

🖋
Chris Nicola
Chris Nicola

🖋
Alejandro Corredor
Alejandro Corredor

🖋
cwar
cwar

🖋
Yuwei
Yuwei

🖋
Utkarsh Bhatt
Utkarsh Bhatt

🖋
Duarte Mendes
Duarte Mendes

🖋
Jason Kim
Jason Kim

🖋
Mitja O.
Mitja O.

🖋
Sandro Miguel Marques
Sandro Miguel Marques

🖋
Gabe
Gabe

🖋
Ron Gross
Ron Gross

🖋
Valeri Karpov
Valeri Karpov

🖋
Sergio Bernal
Sergio Bernal

🖋
Nikola Telkedzhiev
Nikola Telkedzhiev

🖋
Vitor Godoy
Vitor Godoy

🖋
Manish Saraan
Manish Saraan

🖋
Sangbeom Han
Sangbeom Han

🖋
blackmatch
blackmatch

🖋
Joe Reeve
Joe Reeve

🖋
Ryan Busby
Ryan Busby

🖋
Iman Mohamadi
Iman Mohamadi

🖋
Sergii Paryzhskyi
Sergii Paryzhskyi

🖋
Kapil Patel
Kapil Patel

🖋
迷渡
迷渡

🖋
Hozefa
Hozefa

🖋
Ethan
Ethan

🖋
Sam
Sam

🖋
Arlind
Arlind

🖋
Teddy Toussaint
Teddy Toussaint

🖋
Lewis
Lewis

🖋
Gabriel Lidenor
Gabriel Lidenor

🖋
Roman
Roman

🖋
Francozeira
Francozeira

🖋
Invvard
Invvard

🖋
Rômulo Garofalo
Rômulo Garofalo

🖋
Tho Q Luong
Tho Q Luong

🖋
Burak Shen
Burak Shen

🖋
Martin Muzatko
Martin Muzatko

🖋
Jared Collier
Jared Collier

🖋
Hilton Meyer
Hilton Meyer

🖋
ChangJoo Park(박창주)
ChangJoo Park(박창주)

🖋
Masahiro Sakaguchi
Masahiro Sakaguchi

🖋
Keith Holliday
Keith Holliday

🖋
coreyc
coreyc

🖋
Maximilian Berkmann
Maximilian Berkmann

🖋
Douglas Mariano Valero
Douglas Mariano Valero

🖋
Marcelo Melo
Marcelo Melo

🖋
Mehmet Perk
Mehmet Perk

🖋
ryan ouyang
ryan ouyang

🖋
Shabeer
Shabeer

🖋
Eduard Kyvenko
Eduard Kyvenko

🖋
Deyvison Rocha
Deyvison Rocha

🖋
George Mamer
George Mamer

🖋
Konstantinos Leimonis
Konstantinos Leimonis

🖋
Oliver Lluberes
Oliver Lluberes

🌍
Tien Do
Tien Do

🖋
Ranvir Singh
Ranvir Singh

🖋
Vadim Nicolaev
Vadim Nicolaev

🖋 🌍
German Gamboa Gonzalez
German Gamboa Gonzalez

🖋
Hafez
Hafez

🖋
Chandiran
Chandiran

🖋
VinayaSathyanarayana
VinayaSathyanarayana

🖋
Kim Kern
Kim Kern

🖋
Kenneth Freitas
Kenneth Freitas

🖋
songe
songe

🖋
Kirill Shekhovtsov
Kirill Shekhovtsov

🖋
Serge
Serge

🖋
keyrwinz
keyrwinz

🖋
Dmitry Nikitenko
Dmitry Nikitenko

🖋
bushuai
bushuai

👀 🖋
Benjamin Gruenbaum
Benjamin Gruenbaum

🖋
Ezequiel
Ezequiel

🌍
Juan José Rodríguez
Juan José Rodríguez

🌍
Or Bin
Or Bin

🖋
Andreo Vieira
Andreo Vieira

🖋
Michael Solomon
Michael Solomon

🖋
Jimmy Callin
Jimmy Callin

🖋
Siddharth
Siddharth

🖋
Ryan Smith
Ryan Smith

🖋
Tom Boettger
Tom Boettger

🖋
Joaquín Ormaechea
Joaquín Ormaechea

🌍
dfrzuz
dfrzuz

🌍
Victor Homyakov
Victor Homyakov

🖋
Josh
Josh

🖋 🛡️
Alec Francis
Alec Francis

🖋
arjun6610
arjun6610

🖋
Jan Osch
Jan Osch

🖋
Thiago Rotondo Sampaio
Thiago Rotondo Sampaio

🌍
Alexsey
Alexsey

🖋
Luis A. Acurero
Luis A. Acurero

🌍
Lucas Romano
Lucas Romano

🌍
Denise Case
Denise Case

🖋
Nick Ribal
Nick Ribal

🖋 👀
0xflotus
0xflotus

🖋
Jonathan Chen
Jonathan Chen

🖋
Dilan Srilal
Dilan Srilal

🖋
vladthelittleone
vladthelittleone

🌍
Nik Osvalds
Nik Osvalds

🖋
Daniel Kiss
Daniel Kiss

📖
Forresst
Forresst

🖋
Jonathan Svenheden
Jonathan Svenheden

🖋
AustrisC
AustrisC

🖋
kyeongtae kim
kyeongtae kim

🌍
007
007

🖋
Ane Diaz de Tuesta
Ane Diaz de Tuesta

🌍 🖋
YukiOta
YukiOta

🌍
Frazer Smith
Frazer Smith

🖋
Raz Luvaton
Raz Luvaton

🖋
Yuta Azumi
Yuta Azumi

🖋
andrewjbarbour
andrewjbarbour

🖋
mr
mr

🖋
Aleksandar
Aleksandar

🖋
Owl
Owl

🖋
Yedidya Schwartz
Yedidya Schwartz

🖋 💡
ari
ari

🖋
Thomas König
Thomas König

🖋
Kalle Lämsä
Kalle Lämsä

🖋
Wyatt
Wyatt

🖋
KHADIR Tayeb
KHADIR Tayeb

🖋
Shankar Regmi
Shankar Regmi

🖋
Shubham
Shubham

🖋
Lucas Alves
Lucas Alves

🖋
Benjamin
Benjamin

🖋
Yeoh Joer
Yeoh Joer

🖋
Miigon
Miigon

🖋
Rostislav Bogorad
Rostislav Bogorad

🖋
Flouse
Flouse

🖋
Tarantini Pereira
Tarantini Pereira

🖋
Kazuki Matsuo
Kazuki Matsuo

🖋
Adam Smith
Adam Smith

🖋
Dohyeon Ko
Dohyeon Ko

🖋
Vladislav Legkov
Vladislav Legkov

🖋
Kerollos Magdy
Kerollos Magdy

🖋
Erez Lieberman
Erez Lieberman

🖋
Breno Macedo
Breno Macedo

🖋
Fernando Flores
Fernando Flores

🌍
Rafael Brito
Rafael Brito

🌍
Emiliano Peralta
Emiliano Peralta

🌍
Shin, SJ
Shin, SJ

🖋
Benjamin Forster
Benjamin Forster

🖋
Daniele Fedeli
Daniele Fedeli

🖋
djob195
djob195

🖋
antspk
antspk

🖋
정진영
정진영

🖋
kkk-cashwalk
kkk-cashwalk

🖋
apainintheneck
apainintheneck

🖋
Fajar Budhi Iswanda
Fajar Budhi Iswanda

🖋
이주호
이주호

🖋
Singh
Singh

🖋
Alex Dumitru
Alex Dumitru

🖋
Anton Lykhatskyi
Anton Lykhatskyi

🖋
sangwonlee
sangwonlee

🖋
Eugenio Berretta
Eugenio Berretta

🖋
soranakk
soranakk

🖋
고준영
고준영

🖋 💻
Guilherme Portella
Guilherme Portella

🖋
André Esser
André Esser

🖋
Scc
Scc

🌍
Mauro Accornero
Mauro Accornero

🖋
no-yan
no-yan

🖋
hodbauer
hodbauer

🌍
-[Sagir Khan](https://github.com/sagirk) - - - + + -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. + -
+### Steering Committee Emeriti -## Collaborators +[Bruno Scheufler](https://github.com/BrunoScheufler) + -Thank you to all our collaborators! 🙏 +💻 full-stack web engineer, Node.js & GraphQL enthusiast -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](/.operations/CONTRIBUTING.md) 🎉 +
-| | | -| :---------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------: | -| [Ido Richter (Founder)](https://github.com/idori) | [Keith Holliday](https://github.com/TheHollidayInn) | + -### Collaborator Emeriti +[Kyle Martin](https://github.com/js-kyle) + + -| | -| :-------------------------------------------------------------------------------------------------------------------------: | -| [Refael Ackermann](https://github.com/refack) | +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.
-## Contributing + -If you've ever wanted to contribute to open source, now is your chance! See the [contributing docs](.operations/CONTRIBUTING.md) for more information. +[Kevyn Bruyere](https://github.com/kevynb) + -## Contributors ✨ +Independent full-stack developer with a taste for Ops and automation. -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

🖋 💡
+ - - +[Sagir Khan](https://github.com/sagirk) + + + - +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. diff --git a/README.polish.md b/README.polish.md index 2f9e7d44e..3fdae83d2 100644 --- a/README.polish.md +++ b/README.polish.md @@ -3,22 +3,22 @@ # Node.js - Najlepsze praktyki

- Node.js Best Practices + Node.js Best Practices


- 85 items Last update: Oct 12, 2019 Updated for Node 12.12.0 + 85 items Last update: Oct 12, 2019 Updated for Node 12.12.0

-[![nodepractices](/assets/images/twitter-s.png)](https://twitter.com/nodepractices/) **Follow us on Twitter!** [**@nodepractices**](https://twitter.com/nodepractices/) +[![nodepractices](./assets/images/twitter-s.png)](https://twitter.com/nodepractices/) **Follow us on Twitter!** [**@nodepractices**](https://twitter.com/nodepractices/)
-Przeczytaj także w innych językach: [![CN](/assets/flags/CN.png)**CN**](/README.chinese.md), [![BR](/assets/flags/BR.png)**BR**](/README.brazilian-portuguese.md), [![RU](/assets/flags/RU.png)**RU**](/README.russian.md) [(![ES](/assets/flags/ES.png)**ES**, ![FR](/assets/flags/FR.png)**FR**, ![HE](/assets/flags/HE.png)**HE**, ![KR](/assets/flags/KR.png)**KR**, ![TR](/assets/flags/TR.png)**TR**, ![EU](/assets/flags/EU.png)**EU** w trakcie! )](#tłumaczenia) +Przeczytaj także w innych językach: [![CN](./assets/flags/CN.png)**CN**](./README.chinese.md), [![BR](./assets/flags/BR.png)**BR**](./README.brazilian-portuguese.md), [![RU](./assets/flags/RU.png)**RU**](./README.russian.md), [![EU](./assets/flags/EU.png)**EU**](./README.basque.md) [(![ES](./assets/flags/ES.png)**ES**, ![FR](./assets/flags/FR.png)**FR**, ![HE](./assets/flags/HE.png)**HE**, ![KR](./assets/flags/KR.png)**KR**, ![TR](./assets/flags/TR.png)**TR** w trakcie! )](#tłumaczenia)
@@ -28,7 +28,7 @@ Przeczytaj także w innych językach: [![CN](/assets/flags/CN.png)**CN**](/READM - **✅ Nowa najlepsza praktyka:** 7.1: [Nie blokuj pętli zdarzeń](#7-wersja-robocza-najlepsze-praktyki-dotyczące-wydajności) od Keith Holliday -- **🇷🇺 Rosyjskie tłumaczenie:** Niesamowity Alex Ivanov właśnie opublikował [rosyjskie tłumaczenie](/README.russian.md) +- **🇷🇺 Rosyjskie tłumaczenie:** Niesamowity Alex Ivanov właśnie opublikował [rosyjskie tłumaczenie](./README.russian.md) - **Szukamy autorów TypeScript:** chcesz pomóc w tworzeniu przykładów TypeScript? Weź udział, otwierając issue @@ -63,7 +63,7 @@ Przeczytaj także w innych językach: [![CN](/assets/flags/CN.png)**CN**](/READM **W przeciwnym razie:** Gdy programiści, którzy kodują nowe funkcje, walczą o uświadomienie sobie wpływu ich zmian i boją się zniszczyć inne zależne komponenty - wdrożenia stają się wolniejsze i bardziej ryzykowne. Trudniej jest także skalować, gdy wszystkie jednostki biznesowe nie są rozdzielone -🔗 [**Czytaj więcej: struktura według komponentów**](/sections/projectstructre/breakintcomponents.polish.md) +🔗 [**Czytaj więcej: struktura według komponentów**](./sections/projectstructre/breakintcomponents.polish.md)

@@ -73,7 +73,7 @@ Przeczytaj także w innych językach: [![CN](/assets/flags/CN.png)**CN**](/READM **W przeciwnym razie:** Nie można uzyskać dostępu do aplikacji, która miesza obiekty internetowe z innymi warstwami, testując kod, zadania CRON i inne obiekty wywołujące inne niż Express -🔗 [**Czytaj więcej: warstwa twojej aplikacji**](/sections/projectstructre/createlayers.polish.md) +🔗 [**Czytaj więcej: warstwa twojej aplikacji**](./sections/projectstructre/createlayers.polish.md)

@@ -83,7 +83,7 @@ Przeczytaj także w innych językach: [![CN](/assets/flags/CN.png)**CN**](/READM **W przeciwnym razie:** Będziesz musiał wymyślić własne koło wdrażania i zależności -🔗 [**Czytaj więcej: Struktura według funkcji**](/sections/projectstructre/wraputilities.polish.md) +🔗 [**Czytaj więcej: Struktura według funkcji**](./sections/projectstructre/wraputilities.polish.md)

@@ -93,7 +93,7 @@ Przeczytaj także w innych językach: [![CN](/assets/flags/CN.png)**CN**](/READM **W przeciwnym razie:** Twój interfejs API będzie dostępny do testowania tylko za pośrednictwem połączeń HTTP (wolniejsze i znacznie trudniejsze do generowania raportów zasięgu). Utrzymanie setek linii kodu w jednym pliku prawdopodobnie nie będzie wielką przyjemnością -🔗 [**Czytaj więcej: oddzielna aplikacja „Express” i „serwer”**](/sections/projectstructre/separateexpress.polish.md) +🔗 [**Czytaj więcej: oddzielna aplikacja „Express” i „serwer”**](./sections/projectstructre/separateexpress.polish.md)

@@ -103,7 +103,7 @@ Przeczytaj także w innych językach: [![CN](/assets/flags/CN.png)**CN**](/READM **W przeciwnym razie:** Niespełnienie któregokolwiek z wymagań konfiguracji po prostu ugrzęźnie w zespole programistów lub DevOps. Prawdopodobnie jedno i drugie -🔗 [**Czytaj więcej: najlepsze praktyki dotyczące konfiguracji**](/sections/projectstructre/configguide.polish.md) +🔗 [**Czytaj więcej: najlepsze praktyki dotyczące konfiguracji**](./sections/projectstructre/configguide.polish.md)


@@ -117,7 +117,7 @@ Przeczytaj także w innych językach: [![CN](/assets/flags/CN.png)**CN**](/READM **W przeciwnym razie:** styl wywołania zwrotnego Node.js, funkcja (błąd, odpowiedź) jest obiecującym sposobem na niemożliwy do utrzymania kod ze względu na połączenie obsługi błędów z przypadkowym kodem, nadmiernym zagnieżdżaniem i niewygodnymi wzorcami kodowania -🔗 [**Czytaj więcej: avoiding callbacks**](/sections/errorhandling/asyncerrorhandling.polish.md) +🔗 [**Czytaj więcej: avoiding callbacks**](./sections/errorhandling/asyncerrorhandling.polish.md)

@@ -127,7 +127,7 @@ Przeczytaj także w innych językach: [![CN](/assets/flags/CN.png)**CN**](/READM **W przeciwnym razie:** Podczas wywoływania jakiegoś komponentu brak pewności, jaki rodzaj błędów w zamian wraca - znacznie utrudnia prawidłowe zarządzanie błędami. Co gorsza, używanie niestandardowych typów do opisywania błędów może prowadzić do utraty krytycznych informacji o błędach, takich jak stack trace! -🔗 [**Czytaj więcej: using the built-in error object**](/sections/errorhandling/useonlythebuiltinerror.polish.md) +🔗 [**Czytaj więcej: using the built-in error object**](./sections/errorhandling/useonlythebuiltinerror.polish.md)

@@ -137,7 +137,7 @@ Przeczytaj także w innych językach: [![CN](/assets/flags/CN.png)**CN**](/READM **W przeciwnym razie:** Zawsze możesz ponownie uruchomić aplikację, gdy pojawi się błąd, ale dlaczego zawieść ~5000 użytkowników online z powodu drobnego, przewidywanego błędu operacyjnego? Drugie rozwiązanie nie jest też idealne - utrzymanie aplikacji w stanie, gdy wystąpi nieznany problem (błąd programisty), może prowadzić do nieprzewidzianego zachowania. Rozróżnienie tych dwóch pozwala działać taktownie i stosować zrównoważone podejście oparte na danym kontekście -🔗 [**Czytaj więcej: operational vs programmer error**](/sections/errorhandling/operationalvsprogrammererror.polish.md) +🔗 [**Czytaj więcej: operational vs programmer error**](./sections/errorhandling/operationalvsprogrammererror.polish.md)

@@ -147,7 +147,7 @@ Przeczytaj także w innych językach: [![CN](/assets/flags/CN.png)**CN**](/READM **W przeciwnym razie:** Brak obsługi błędów w jednym miejscu prowadzi do duplikacji kodu i prawdopodobnie do nieprawidłowej obsługi błędów -🔗 [**Czytaj więcej: handling errors in a centralized place**](/sections/errorhandling/centralizedhandling.polish.md) +🔗 [**Czytaj więcej: handling errors in a centralized place**](./sections/errorhandling/centralizedhandling.polish.md)

@@ -157,7 +157,7 @@ Przeczytaj także w innych językach: [![CN](/assets/flags/CN.png)**CN**](/READM **W przeciwnym razie:** Klient API może zdecydować o awarii i ponownym uruchomieniu tylko dlatego, że otrzymał błąd, którego nie mógł zrozumieć. Uwaga: osobą wywołującą interfejs API możesz być Ty (bardzo typowe w środowisku mikrousług) -🔗 [**Czytaj więcej: documenting API errors in Swagger or GraphQL**](/sections/errorhandling/documentingusingswagger.polish.md) +🔗 [**Czytaj więcej: documenting API errors in Swagger or GraphQL**](./sections/errorhandling/documentingusingswagger.polish.md)

@@ -167,7 +167,7 @@ Przeczytaj także w innych językach: [![CN](/assets/flags/CN.png)**CN**](/READM **W przeciwnym razie:** Gdy wystąpi nieznany wyjątek, niektóre obiekty mogą znajdować się w stanie wadliwym (np. Emiter zdarzeń, który jest używany globalnie i nie uruchamia już zdarzeń z powodu pewnych wewnętrznych awarii), a wszystkie przyszłe żądania mogą zawieść lub zachowywać się szaleńczo -🔗 [**Czytaj więcej: shutting the process**](/sections/errorhandling/shuttingtheprocess.polish.md) +🔗 [**Czytaj więcej: shutting the process**](./sections/errorhandling/shuttingtheprocess.polish.md)

@@ -177,7 +177,7 @@ Przeczytaj także w innych językach: [![CN](/assets/flags/CN.png)**CN**](/READM **W przeciwnym razie:** Przeglądanie w pliku console.logs lub ręcznie przez niechlujny plik tekstowy bez korzystania z narzędzi zapytań lub porządnej przeglądarki dziennika może być zajęciem w pracy do późna -🔗 [**Czytaj więcej: using a mature logger**](/sections/errorhandling/usematurelogger.polish.md) +🔗 [**Czytaj więcej: using a mature logger**](./sections/errorhandling/usematurelogger.polish.md)

@@ -187,7 +187,7 @@ Przeczytaj także w innych językach: [![CN](/assets/flags/CN.png)**CN**](/READM **W przeciwnym razie:** Bez testowania, automatycznie lub ręcznie, nie można polegać na kodzie, który zwraca prawidłowe błędy. Bez znaczących błędów - nie ma obsługi błędów -🔗 [**Czytaj więcej: testing error flows**](/sections/errorhandling/testingerrorflows.polish.md) +🔗 [**Czytaj więcej: testing error flows**](./sections/errorhandling/testingerrorflows.polish.md)

@@ -197,7 +197,7 @@ Przeczytaj także w innych językach: [![CN](/assets/flags/CN.png)**CN**](/READM **W przeciwnym razie:** Możesz poświęcić wiele wysiłku na pomiar wydajności interfejsu API i przestojów, prawdopodobnie nigdy nie będziesz wiedział, jakie są twoje najwolniejsze części kodu w rzeczywistym scenariuszu i jak wpływają one na UX -🔗 [**Czytaj więcej: using APM products**](/sections/errorhandling/apmproducts.polish.md) +🔗 [**Czytaj więcej: using APM products**](./sections/errorhandling/apmproducts.polish.md)

@@ -207,7 +207,7 @@ Przeczytaj także w innych językach: [![CN](/assets/flags/CN.png)**CN**](/READM **W przeciwnym razie:** Twoje błędy zostaną połknięte i nie pozostawiają śladu. Nie ma się o co martwić -🔗 [**Czytaj więcej: catching unhandled promise rejection**](/sections/errorhandling/catchunhandledpromiserejection.polish.md) +🔗 [**Czytaj więcej: catching unhandled promise rejection**](./sections/errorhandling/catchunhandledpromiserejection.polish.md)

@@ -217,7 +217,7 @@ Przeczytaj także w innych językach: [![CN](/assets/flags/CN.png)**CN**](/READM **W przeciwnym razie:** Rozważ to - twoja funkcja oczekuje argumentu liczbowego „Discount”, który wywołujący zapomina przekazać, a następnie kod sprawdza, czy Discount!=0 (kwota dozwolonego discounta jest większa od zera), a następnie pozwoli użytkownikowi cieszyć się discountem. OMG, co za paskudny błąd. Widzisz to? -🔗 [**Czytaj więcej: failing fast**](/sections/errorhandling/failfast.polish.md) +🔗 [**Czytaj więcej: failing fast**](./sections/errorhandling/failfast.polish.md)


@@ -231,7 +231,7 @@ Przeczytaj także w innych językach: [![CN](/assets/flags/CN.png)**CN**](/READM **W przeciwnym razie:** Programiści skoncentrują się na żmudnych odstępach i problemach z szerokością linii, a czas może zostać zmarnowany na przemyślenie stylu kodu projektu -🔗 [**Czytaj więcej: Using ESLint and Prettier**](/sections/codestylepractices/eslint_prettier.polish.md) +🔗 [**Czytaj więcej: Using ESLint and Prettier**](./sections/codestylepractices/eslint_prettier.polish.md)

@@ -256,7 +256,8 @@ function someFunction() { } // Avoid -function someFunction() { +function someFunction() +{ // code block } ``` @@ -275,7 +276,7 @@ Bez względu na to, czy używasz średników, czy też nie rozdzielasz swoich in **W przeciwnym razie:** Jak widać w poprzedniej sekcji, interpreter JavaScript automatycznie dodaje średnik na końcu instrukcji, jeśli nie istnieje, lub uważa instrukcję za niezakończoną tam, gdzie powinna, co może prowadzić do niepożądanych wyników. Możesz używać przypisań i unikać używania natychmiastowych wywoływanych wyrażeń funkcyjnych, aby zapobiec większości nieoczekiwanych błędów. -### Przykład kodu +### Przykład Kodu ```javascript // Do @@ -446,7 +447,7 @@ Wszystkie powyższe instrukcje zwrócą wartość false, jeśli zostaną użyte **W przeciwnym razie:** Wdrożenie właśnie nie powiodło się, test o nazwie „Dodaj produkt” nie powiódł się. Czy to mówi ci, co dokładnie działa nieprawidłowo? -🔗 [**Czytaj więcej: Include 3 parts in each test name**](/sections/testingandquality/3-parts-in-name.polish.md) +🔗 [**Czytaj więcej: Include 3 parts in each test name**](./sections/testingandquality/3-parts-in-name.polish.md)

@@ -456,7 +457,7 @@ Wszystkie powyższe instrukcje zwrócą wartość false, jeśli zostaną użyte **W przeciwnym razie:** Nie tylko spędzasz długie codzienne godziny na zrozumieniu głównego kodu, ale także to, co powinno być prostą częścią dnia (testowanie) rozciąga Twój mózg -🔗 [**Czytaj więcej: Structure tests by the AAA pattern**](/sections/testingandquality/aaa.polish.md) +🔗 [**Czytaj więcej: Structure tests by the AAA pattern**](./sections/testingandquality/aaa.polish.md)

@@ -474,7 +475,7 @@ Wszystkie powyższe instrukcje zwrócą wartość false, jeśli zostaną użyte **W przeciwnym razie:** Rozważmy scenariusz, w którym wdrożenie zostało przerwane z powodu nieudanych testów, zespół zamierza teraz poświęcić cenny czas na dochodzenie, które kończy się smutnym wnioskiem: system działa dobrze, testy jednak przeszkadzają sobie nawzajem i przerywają kompilację -🔗 [**Czytaj więcej: Avoid global test fixtures**](/sections/testingandquality/avoid-global-test-fixture.polish.md) +🔗 [**Czytaj więcej: Avoid global test fixtures**](./sections/testingandquality/avoid-global-test-fixture.polish.md)

@@ -524,7 +525,7 @@ Wszystkie powyższe instrukcje zwrócą wartość false, jeśli zostaną użyte **W przeciwnym razie:** Przy złej jakości kodu błędy i wydajność zawsze będą stanowić problem, którego nie będzie w stanie naprawić żadna nowa błyszcząca biblioteka ani najnowocześniejsze funkcje -🔗 [**Czytaj więcej: Refactoring!**](/sections/testingandquality/refactoring.polish.md) +🔗 [**Czytaj więcej: Refactoring!**](./sections/testingandquality/refactoring.polish.md)

@@ -534,7 +535,7 @@ Wszystkie powyższe instrukcje zwrócą wartość false, jeśli zostaną użyte **W przeciwnym razie:** Wybranie jakiegoś niszowego dostawcy może spowodować zablokowanie użytkownika, gdy będzie potrzebne zaawansowane dostosowanie. Z drugiej strony pójście z Jenkinsem może skrócić cenny czas na konfigurację infrastruktury -🔗 [**Czytaj więcej: Choosing CI platform**](/sections/testingandquality/citools.polish.md) +🔗 [**Czytaj więcej: Choosing CI platform**](./sections/testingandquality/citools.polish.md)


@@ -548,7 +549,7 @@ Wszystkie powyższe instrukcje zwrócą wartość false, jeśli zostaną użyte **W przeciwnym razie:** Awaria === rozczarowani klienci. Proste -🔗 [**Czytaj więcej: Monitoring!**](/sections/production/monitoring.polish.md) +🔗 [**Czytaj więcej: Monitoring!**](./sections/production/monitoring.polish.md)

@@ -558,7 +559,7 @@ Wszystkie powyższe instrukcje zwrócą wartość false, jeśli zostaną użyte **W przeciwnym razie:** W rezultacie pojawia się czarna skrzynka, o której trudno uzasadnić, a następnie zaczynasz ponownie pisać wszystkie instrukcje rejestrowania, aby dodać dodatkowe informacje -🔗 [**Czytaj więcej: Increase transparency using smart logging**](/sections/production/smartlogging.polish.md) +🔗 [**Czytaj więcej: Increase transparency using smart logging**](./sections/production/smartlogging.polish.md)

@@ -568,7 +569,7 @@ Wszystkie powyższe instrukcje zwrócą wartość false, jeśli zostaną użyte **W przeciwnym razie:** Twój słaby pojedynczy wątek pozostanie zajęty wykonywaniem zadań infrastrukturalnych zamiast zajmowania się rdzeniem aplikacji, a wydajność odpowiednio się obniży -🔗 [**Czytaj więcej: Delegate anything possible (e.g. gzip, SSL) to a reverse proxy**](/sections/production/delegatetoproxy.polish.md) +🔗 [**Czytaj więcej: Delegate anything possible (e.g. gzip, SSL) to a reverse proxy**](./sections/production/delegatetoproxy.polish.md)

@@ -578,7 +579,7 @@ Wszystkie powyższe instrukcje zwrócą wartość false, jeśli zostaną użyte **W przeciwnym razie:** Dział kontroli jakości dokładnie przetestuje kod i zatwierdzi wersję, która będzie zachowywać się inaczej w środowisku produkcyjnym. Co gorsza, różne serwery w tym samym klastrze produkcyjnym mogą uruchamiać inny kod -🔗 [**Czytaj więcej: Lock dependencies**](/sections/production/lockdependencies.polish.md) +🔗 [**Czytaj więcej: Lock dependencies**](./sections/production/lockdependencies.polish.md)

@@ -588,7 +589,7 @@ Wszystkie powyższe instrukcje zwrócą wartość false, jeśli zostaną użyte **W przeciwnym razie:** Uruchomienie dziesiątek instancji bez jasnej strategii i zbyt wielu narzędzi razem (zarządzanie klastrami, okno dokowane, PM2) może doprowadzić do chaosu DevOps -🔗 [**Czytaj więcej: Guard process uptime using the right tool**](/sections/production/guardprocess.polish.md) +🔗 [**Czytaj więcej: Guard process uptime using the right tool**](./sections/production/guardprocess.polish.md)

@@ -598,7 +599,7 @@ Wszystkie powyższe instrukcje zwrócą wartość false, jeśli zostaną użyte **W przeciwnym razie:** Twoja aplikacja prawdopodobnie wykorzysta tylko 25% dostępnych zasobów (!) lub nawet mniej. Zauważ, że typowy serwer ma 4 rdzenie procesora lub więcej, naiwne wdrożenie Node.js wykorzystuje tylko 1 (nawet przy użyciu usług PaaS, takich jak AWS beanstalk!) -🔗 [**Czytaj więcej: Utilize all CPU cores**](/sections/production/utilizecpu.polish.md) +🔗 [**Czytaj więcej: Utilize all CPU cores**](./sections/production/utilizecpu.polish.md)

@@ -608,7 +609,7 @@ Wszystkie powyższe instrukcje zwrócą wartość false, jeśli zostaną użyte **W przeciwnym razie:** Przekonasz się, że wykonujesz wiele „wdrożeń diagnostycznych” - wysyłasz kod do produkcji tylko po to, aby wyodrębnić niektóre informacje do celów diagnostycznych -🔗 [**Czytaj więcej: Create a ‘maintenance endpoint’**](/sections/production/createmaintenanceendpoint.polish.md) +🔗 [**Czytaj więcej: Create a ‘maintenance endpoint’**](./sections/production/createmaintenanceendpoint.polish.md)

@@ -618,7 +619,7 @@ Wszystkie powyższe instrukcje zwrócą wartość false, jeśli zostaną użyte **W przeciwnym razie:** Możesz poświęcić wiele wysiłku na pomiar wydajności interfejsu API i przestojów, prawdopodobnie nigdy nie będziesz wiedział, jakie są twoje najwolniejsze części kodu w rzeczywistym scenariuszu i jak wpływają one na UX -🔗 [**Czytaj więcej: Discover errors and downtime using APM products**](/sections/production/apmproducts.polish.md) +🔗 [**Czytaj więcej: Discover errors and downtime using APM products**](./sections/production/apmproducts.polish.md)

@@ -628,7 +629,7 @@ Wszystkie powyższe instrukcje zwrócą wartość false, jeśli zostaną użyte **W przeciwnym razie:** Mistrz świata IT / DevOps nie uratuje źle napisanego systemu -🔗 [**Czytaj więcej: Make your code production-ready**](/sections/production/productioncode.polish.md) +🔗 [**Czytaj więcej: Make your code production-ready**](./sections/production/productioncode.polish.md)

@@ -638,7 +639,7 @@ Wszystkie powyższe instrukcje zwrócą wartość false, jeśli zostaną użyte **W przeciwnym razie:** Pamięć procesowa może przeciekać sto megabajtów dziennie, jak to się stało w [Walmart](https://www.joyent.com/blog/walmart-node-js-memory-leak) -🔗 [**Czytaj więcej: Measure and guard the memory usage**](/sections/production/measurememory.polish.md) +🔗 [**Czytaj więcej: Measure and guard the memory usage**](./sections/production/measurememory.polish.md)

@@ -648,7 +649,7 @@ Wszystkie powyższe instrukcje zwrócą wartość false, jeśli zostaną użyte **W przeciwnym razie:** Twój pojedynczy wątek Node'a będzie zajęty przesyłaniem strumieniowym setek plików HTML / images / Angular / React zamiast przydzielania wszystkich swoich zasobów do zadania, dla którego się urodził - udostępniania treści dynamicznych -🔗 [**Czytaj więcej: Get your frontend assets out of Node**](/sections/production/frontendout.polish.md) +🔗 [**Czytaj więcej: Get your frontend assets out of Node**](./sections/production/frontendout.polish.md)

@@ -658,7 +659,7 @@ Wszystkie powyższe instrukcje zwrócą wartość false, jeśli zostaną użyte **W przeciwnym razie:** Awaria na danym serwerze spowoduje przestoje aplikacji, a nie tylko zabicie wadliwego komputera. Co więcej, elastyczność skalowania stanie się trudniejsza ze względu na zależność od konkretnego serwera -🔗 [**Czytaj więcej: Be stateless, kill your Servers almost every day**](/sections/production/bestateless.polish.md) +🔗 [**Czytaj więcej: Be stateless, kill your Servers almost every day**](./sections/production/bestateless.polish.md)

@@ -668,7 +669,7 @@ Wszystkie powyższe instrukcje zwrócą wartość false, jeśli zostaną użyte **W przeciwnym razie:** Utrzymanie kodu w czystości przed lukami bez dedykowanych narzędzi będzie wymagało ciągłego śledzenia publikacji online na temat nowych zagrożeń. Dość nudne -🔗 [**Czytaj więcej: Use tools that automatically detect vulnerabilities**](/sections/production/detectvulnerabilities.polish.md) +🔗 [**Czytaj więcej: Use tools that automatically detect vulnerabilities**](./sections/production/detectvulnerabilities.polish.md)

@@ -678,7 +679,7 @@ Wszystkie powyższe instrukcje zwrócą wartość false, jeśli zostaną użyte **W przeciwnym razie:** Patrzenie na dziennik błędów produkcyjnych bez kontekstu - co zdarzyło się wcześniej - sprawia, że znacznie trudniej i wolniej jest myśleć o problemie -🔗 [**Czytaj więcej: Assign ‘TransactionId’ to each log statement**](/sections/production/assigntransactionid.polish.md) +🔗 [**Czytaj więcej: Assign ‘TransactionId’ to each log statement**](./sections/production/assigntransactionid.polish.md)

@@ -688,7 +689,7 @@ Wszystkie powyższe instrukcje zwrócą wartość false, jeśli zostaną użyte **W przeciwnym razie:** Pominięcie tej prostej właściwości może znacznie obniżyć wydajność. Na przykład, używając Express do renderowania po stronie serwera, pominięcie `NODE_ENV` powoduje spowolnienie trzykrotnie! -🔗 [**Czytaj więcej: Set NODE_ENV=production**](/sections/production/setnodeenv.polish.md) +🔗 [**Czytaj więcej: Set NODE_ENV=production**](./sections/production/setnodeenv.polish.md)

@@ -706,7 +707,7 @@ Wszystkie powyższe instrukcje zwrócą wartość false, jeśli zostaną użyte **W przeciwnym razie:** Nowo odkryte błędy lub luki można wykorzystać do wykorzystania aplikacji działającej w środowisku produkcyjnym, a aplikacja może nie być obsługiwana przez różne moduły i trudniejsza do utrzymania -🔗 [**Czytaj więcej: Use an LTS release of Node.js**](/sections/production/LTSrelease.polish.md) +🔗 [**Czytaj więcej: Use an LTS release of Node.js**](./sections/production/LTSrelease.polish.md)

@@ -716,7 +717,7 @@ Wszystkie powyższe instrukcje zwrócą wartość false, jeśli zostaną użyte **W przeciwnym razie:** Trasowanie dzienników obsługi aplikacji === trudne do skalowania, utrata dzienników, słaba separacja problemów -🔗 [**Czytaj więcej: Log Routing**](/sections/production/logrouting.polish.md) +🔗 [**Czytaj więcej: Log Routing**](./sections/production/logrouting.polish.md)


@@ -736,7 +737,7 @@ Wszystkie powyższe instrukcje zwrócą wartość false, jeśli zostaną użyte **W przeciwnym razie:** To, co mogło być bezpośrednią słabością bezpieczeństwa podczas programowania, staje się poważnym problemem w produkcji. Ponadto projekt może nie być zgodny ze spójnymi praktykami bezpieczeństwa kodu, co prowadzi do wprowadzenia luk w zabezpieczeniach lub poufnych danych wrażliwych wrzuconych w zdalnych repozytoriach -🔗 [**Czytaj więcej: Lint rules**](/sections/security/lintrules.polish.md) +🔗 [**Czytaj więcej: Lint rules**](./sections/security/lintrules.polish.md)

@@ -748,7 +749,7 @@ Wszystkie powyższe instrukcje zwrócą wartość false, jeśli zostaną użyte **W przeciwnym razie:** Aplikacja może zostać zaatakowana, co spowoduje odmowę usługi, w wyniku której prawdziwi użytkownicy otrzymają usługę o obniżonej jakości lub niedostępną. -🔗 [**Czytaj więcej: Implement rate limiting**](/sections/security/limitrequests.polish.md) +🔗 [**Czytaj więcej: Implement rate limiting**](./sections/security/limitrequests.polish.md)

@@ -760,7 +761,7 @@ Wszystkie powyższe instrukcje zwrócą wartość false, jeśli zostaną użyte **W przeciwnym razie:** Kontrola źródła, nawet w przypadku prywatnych repozytoriów, może zostać omyłkowo upubliczniona, w którym to momencie ujawniane są wszystkie dane wrażliwe. Dostęp do kontroli źródła dla strony zewnętrznej nieumyślnie zapewni dostęp do powiązanych systemów (baz danych, API, usług itp.). -🔗 [**Czytaj więcej: Secret management**](/sections/security/secretmanagement.polish.md) +🔗 [**Czytaj więcej: Secret management**](./sections/security/secretmanagement.polish.md)

@@ -772,7 +773,7 @@ Wszystkie powyższe instrukcje zwrócą wartość false, jeśli zostaną użyte **W przeciwnym razie:** Nieprawidłowe lub niezaangażowane dane wejściowe użytkownika mogą prowadzić do wstrzyknięcia przez operatora podczas pracy z MongoDB dla NoSQL, a niestosowanie odpowiedniego systemu odkażania lub ORM z łatwością pozwoli na ataki z zastrzykiem SQL, tworząc ogromną lukę. -🔗 [**Czytaj więcej: Query injection prevention using ORM/ODM libraries**](/sections/security/ormodmusage.polish.md) +🔗 [**Czytaj więcej: Query injection prevention using ORM/ODM libraries**](./sections/security/ormodmusage.polish.md)

@@ -780,7 +781,7 @@ Wszystkie powyższe instrukcje zwrócą wartość false, jeśli zostaną użyte **TL;DR:** Jest to zbiór porad bezpieczeństwa, które nie są bezpośrednio związane z Node.js - implementacja Node nie różni się niczym od żadnego innego języka. Kliknij Czytaj więcej, aby przejrzeć. -🔗 [**Czytaj więcej: Common security best practices**](/sections/security/commonsecuritybestpractices.polish.md) +🔗 [**Czytaj więcej: Common security best practices**](./sections/security/commonsecuritybestpractices.polish.md)

@@ -792,7 +793,7 @@ Wszystkie powyższe instrukcje zwrócą wartość false, jeśli zostaną użyte **W przeciwnym razie:** Atakujący mogą wykonywać bezpośrednie ataki na użytkowników aplikacji, co prowadzi do ogromnych luk w zabezpieczeniach -🔗 [**Czytaj więcej: Using secure headers in your application**](/sections/security/secureheaders.polish.md) +🔗 [**Czytaj więcej: Using secure headers in your application**](./sections/security/secureheaders.polish.md)

@@ -804,7 +805,7 @@ Wszystkie powyższe instrukcje zwrócą wartość false, jeśli zostaną użyte **W przeciwnym razie:** Osoba atakująca może wykryć strukturę sieci i zaatakować wszystkie znane luki w zabezpieczeniach. -🔗 [**Czytaj więcej: Dependency security**](/sections/security/dependencysecurity.polish.md) +🔗 [**Czytaj więcej: Dependency security**](./sections/security/dependencysecurity.polish.md)

@@ -816,7 +817,7 @@ Wszystkie powyższe instrukcje zwrócą wartość false, jeśli zostaną użyte **W przeciwnym razie:** Hasła lub dane wrażliwe, które są utrwalane bez korzystania z bezpiecznej funkcji, są podatne na brute force i ataki słownikowe, które ostatecznie doprowadzą do ich ujawnienia. -🔗 [**Czytaj więcej: Use Bcrypt**](/sections/security/bcryptpasswords.polish.md) +🔗 [**Czytaj więcej: Use Bcrypt**](./sections/security/bcryptpasswords.polish.md)

@@ -828,7 +829,7 @@ Wszystkie powyższe instrukcje zwrócą wartość false, jeśli zostaną użyte **W przeciwnym razie:** Osoba atakująca może przechowywać złośliwy kod JavaScript w bazie danych, który zostanie następnie wysłany „tak jak jest” do biednych klientów -🔗 [**Czytaj więcej: Escape output**](/sections/security/escape-output.polish.md) +🔗 [**Czytaj więcej: Escape output**](./sections/security/escape-output.polish.md)

@@ -840,7 +841,7 @@ Wszystkie powyższe instrukcje zwrócą wartość false, jeśli zostaną użyte **W przeciwnym razie:** Twoja hojność i liberalne podejście znacznie zwiększa powierzchnię ataku i zachęca atakującego do wypróbowania wielu danych wejściowych, dopóki nie znajdzie kombinacji umożliwiającej zawieszenie aplikacji -🔗 [**Czytaj więcej: Validate incoming JSON schemas**](/sections/security/validation.polish.md) +🔗 [**Czytaj więcej: Validate incoming JSON schemas**](./sections/security/validation.polish.md)

@@ -852,7 +853,7 @@ Wszystkie powyższe instrukcje zwrócą wartość false, jeśli zostaną użyte **W przeciwnym razie:** Wygasłe lub niewłaściwie umieszczone tokeny mogą być złośliwie wykorzystywane przez osoby trzecie do uzyskiwania dostępu do aplikacji i podszywania się pod właściciela tokena. -🔗 [**Czytaj więcej: Blacklist JSON Web Tokens**](/sections/security/expirejwt.polish.md) +🔗 [**Czytaj więcej: Blacklist JSON Web Tokens**](./sections/security/expirejwt.polish.md)

@@ -867,7 +868,7 @@ Wszystkie powyższe instrukcje zwrócą wartość false, jeśli zostaną użyte **W przeciwnym razie:** Osoba atakująca może podejmować nieograniczoną liczbę zautomatyzowanych prób uzyskania hasła w celu uzyskania dostępu do uprzywilejowanych kont w aplikacji -🔗 [**Czytaj więcej: Login rate limiting**](/sections/security/login-rate-limit.polish.md) +🔗 [**Czytaj więcej: Login rate limiting**](./sections/security/login-rate-limit.polish.md)

@@ -879,7 +880,7 @@ Wszystkie powyższe instrukcje zwrócą wartość false, jeśli zostaną użyte **W przeciwnym razie:** Atakujący, któremu uda się uruchomić skrypt na serwerze, uzyskuje nieograniczoną władzę nad maszyną lokalną (np. zmienia iptable i przekierowuje ruch do swojego serwera) -🔗 [**Czytaj więcej: Run Node.js as non-root user**](/sections/security/non-root-user.polish.md) +🔗 [**Czytaj więcej: Run Node.js as non-root user**](./sections/security/non-root-user.polish.md)

@@ -891,7 +892,7 @@ Wszystkie powyższe instrukcje zwrócą wartość false, jeśli zostaną użyte **W przeciwnym razie:** Twoja aplikacja będzie musiała poradzić sobie z dużymi żądaniami, niezdolna do przetworzenia innej ważnej pracy, którą musi wykonać, co będzie miało wpływ na wydajność i podatność na ataki DOS -🔗 [**Czytaj więcej: Limit payload size**](/sections/security/requestpayloadsizelimit.polish.md) +🔗 [**Czytaj więcej: Limit payload size**](./sections/security/requestpayloadsizelimit.polish.md)

@@ -899,11 +900,11 @@ Wszystkie powyższe instrukcje zwrócą wartość false, jeśli zostaną użyte -**TL;DR:** `eval` jest złe, ponieważ pozwala na wykonanie niestandardowego kodu JavaScript w czasie wykonywania. Jest to nie tylko kwestia wydajności, ale także ważna kwestia bezpieczeństwa ze względu na złośliwy kod JavaScript, który może pochodzić z danych wejściowych użytkownika. Inną cechą językową, której należy unikać, jest konstruktor `new Function`. `setTimeout` i` setInterval` nigdy nie powinny być przekazywane dynamicznemu kodowi JavaScript. +**TL;DR:** `eval` jest złe, ponieważ pozwala na wykonanie niestandardowego kodu JavaScript w czasie wykonywania. Jest to nie tylko kwestia wydajności, ale także ważna kwestia bezpieczeństwa ze względu na złośliwy kod JavaScript, który może pochodzić z danych wejściowych użytkownika. Inną cechą językową, której należy unikać, jest konstruktor `new Function`. `setTimeout` i`setInterval` nigdy nie powinny być przekazywane dynamicznemu kodowi JavaScript. **W przeciwnym razie:** Złośliwy kod JavaScript znajduje drogę do tekstu przekazywanego do `eval` lub innych funkcji języka JavaScript oceniających w czasie rzeczywistym, i uzyskuje pełny dostęp do uprawnień JavaScript na stronie. Luka ta często objawia się jako atak XSS. -🔗 [**Czytaj więcej: Avoid JavaScript eval statements**](/sections/security/avoideval.polish.md) +🔗 [**Czytaj więcej: Avoid JavaScript eval statements**](./sections/security/avoideval.polish.md)

@@ -915,7 +916,7 @@ Wszystkie powyższe instrukcje zwrócą wartość false, jeśli zostaną użyte **W przeciwnym razie:** Źle napisane wyrażenia regularne mogą być podatne na ataki DoS wyrażeń regularnych, które całkowicie zablokują pętlę zdarzeń. Na przykład popularny pakiet `moment` został uznany za podatny na złośliwe użycie Regex w listopadzie 2017r. -🔗 [**Czytaj więcej: Prevent malicious RegEx**](/sections/security/regex.polish.md) +🔗 [**Czytaj więcej: Prevent malicious RegEx**](./sections/security/regex.polish.md)

@@ -927,7 +928,7 @@ Wszystkie powyższe instrukcje zwrócą wartość false, jeśli zostaną użyte **W przeciwnym razie:** Złośliwe dane wejściowe użytkownika mogą znaleźć drogę do parametru wymaganego do zmodyfikowania plików, na przykład wcześniej przesłanego pliku do systemu plików lub uzyskania dostępu do już istniejących plików systemowych. -🔗 [**Czytaj więcej: Safe module loading**](/sections/security/safemoduleloading.polish.md) +🔗 [**Czytaj więcej: Safe module loading**](./sections/security/safemoduleloading.polish.md)

@@ -939,7 +940,7 @@ Wszystkie powyższe instrukcje zwrócą wartość false, jeśli zostaną użyte **W przeciwnym razie:** Wtyczka może atakować poprzez nieskończoną różnorodność opcji, takich jak nieskończone pętle, przeciążenie pamięci i dostęp do wrażliwych zmiennych środowiskowych procesu -🔗 [**Czytaj więcej: Run unsafe code in a sandbox**](/sections/security/sandbox.polish.md) +🔗 [**Czytaj więcej: Run unsafe code in a sandbox**](./sections/security/sandbox.polish.md)

@@ -951,7 +952,7 @@ Wszystkie powyższe instrukcje zwrócą wartość false, jeśli zostaną użyte **W przeciwnym razie:** Naiwne użycie procesów potomnych może spowodować zdalne wykonanie poleceń lub ataki polegające na wstrzyknięciu powłoki z powodu wprowadzenia złośliwego użytkownika do niezarządzanego polecenia systemowego. -🔗 [**Czytaj więcej: Be cautious when working with child processes**](/sections/security/childprocesses.polish.md) +🔗 [**Czytaj więcej: Be cautious when working with child processes**](./sections/security/childprocesses.polish.md)

@@ -963,7 +964,7 @@ Wszystkie powyższe instrukcje zwrócą wartość false, jeśli zostaną użyte **W przeciwnym razie:** Wrażliwe szczegóły aplikacji, takie jak ścieżki plików serwera, używane moduły stron trzecich i inne wewnętrzne przepływy pracy aplikacji, które mogą zostać wykorzystane przez atakującego, mogą zostać wyciekły z informacji znalezionych w stack trace -🔗 [**Czytaj więcej: Hide error details from client**](/sections/security/hideerrors.polish.md) +🔗 [**Czytaj więcej: Hide error details from client**](./sections/security/hideerrors.polish.md)

@@ -985,7 +986,7 @@ Wszystkie powyższe instrukcje zwrócą wartość false, jeśli zostaną użyte **W przeciwnym razie:** Pliki cookie mogą być przesyłane za pośrednictwem niezabezpieczonych połączeń, a osoba atakująca może użyć identyfikacji sesji w celu zidentyfikowania podstawowej struktury aplikacji internetowej, a także podatności na uszkodzenia specyficzne dla modułu -🔗 [**Czytaj więcej: Cookie and session security**](/sections/security/sessions.polish.md) +🔗 [**Czytaj więcej: Cookie and session security**](./sections/security/sessions.polish.md)

@@ -1007,7 +1008,7 @@ Wszystkie powyższe instrukcje zwrócą wartość false, jeśli zostaną użyte **W przeciwnym razie:** Jeśli osoba atakująca odkryje, że nie weryfikujesz danych zewnętrznych dostarczonych przez użytkownika, może wykorzystać tę lukę, publikując specjalnie spreparowane łącza na forach, w mediach społecznościowych i innych miejscach publicznych, aby użytkownicy mogli ją kliknąć. -🔗 [**Czytaj więcej: Prevent unsafe redirects**](/sections/security/saferedirects.polish.md) +🔗 [**Czytaj więcej: Prevent unsafe redirects**](./sections/security/saferedirects.polish.md)

@@ -1015,11 +1016,11 @@ Wszystkie powyższe instrukcje zwrócą wartość false, jeśli zostaną użyte -**TL;DR:** Należy podjąć środki ostrożności, aby uniknąć ryzyka przypadkowego opublikowania danych wrażliwych w publicznych rejestrach npm. Plik `.npmignore` może być użyty do umieszczenia na czarnej liście określonych plików lub folderów, lub tablica` files` w `package.json` może działać jako biała lista. +**TL;DR:** Należy podjąć środki ostrożności, aby uniknąć ryzyka przypadkowego opublikowania danych wrażliwych w publicznych rejestrach npm. Plik `.npmignore` może być użyty do umieszczenia na czarnej liście określonych plików lub folderów, lub tablica`files` w `package.json` może działać jako biała lista. **W przeciwnym razie:** Klucze API, hasła i inne dane wrażliwe twojego projektu są otwarte na wykorzystywanie przez każdego, kto je napotka, co może spowodować straty finansowe, podszywanie się pod inne osoby i inne ryzyko. -🔗 [**Czytaj więcej: Avoid publishing secrets**](/sections/security/avoid_publishing_secrets.polish.md) +🔗 [**Czytaj więcej: Avoid publishing secrets**](./sections/security/avoid_publishing_secrets.polish.md)


⬆ Powrót na górę

@@ -1036,7 +1037,7 @@ Wszystkie powyższe instrukcje zwrócą wartość false, jeśli zostaną użyte **W przeciwnym razie:** Ponieważ pętla zdarzeń jest zablokowana, Node.js nie będzie w stanie obsłużyć innych żądań, co spowoduje opóźnienia dla równoczesnych użytkowników. **3000 użytkowników czeka na odpowiedź, treść jest gotowa do wyświetlenia, ale jedno pojedyncze żądanie blokuje serwerowi odesłanie wyników z powrotem** -🔗 [**Czytaj więcej: Do not block the event loop**](/sections/performance/block-loop.polish.md) +🔗 [**Czytaj więcej: Do not block the event loop**](./sections/performance/block-loop.polish.md)


@@ -1047,7 +1048,7 @@ Należy pamiętać, że wraz z wprowadzeniem nowego silnika V8 wraz z nowymi sta **W przeciwnym razie:** Będziesz musiał utrzymywać mniej wydajne projekty, w których mógłbyś po prostu użyć tego, co było **już** dostępne lub zająć się kilkoma kolejnymi liniami w zamian za kilka dodatkowych plików. -🔗 [**Czytaj więcej: Native over user land utils**](/sections/performance/nativeoverutil.polish.md) +🔗 [**Czytaj więcej: Native over user land utils**](./sections/performance/nativeoverutil.polish.md)


@@ -1063,19 +1064,19 @@ Wszystkie tłumaczenia pochodzą od społeczności. Z przyjemnością uzyskamy w ### Ukończone tłumaczenia -- ![BR](/assets/flags/BR.png) [Brazilian Portuguese](./README.brazilian-portuguese.md) - Dzięki uprzejmości [Marcelo Melo](https://github.com/marcelosdm) -- ![CN](/assets/flags/CN.png) [Chinese](./README.chinese.md) - Dzięki uprzejmości [Matt Jin](https://github.com/mattjin) -- ![RU](/assets/flags/RU.png) [Russian](./README.russian.md) - Dzięki uprzejmości [Alex Ivanov](https://github.com/contributorpw) -- ![PL](/assets/flags/PL.png) [Polish](./README.polish.md) - Dzięki uprzejmości [Michal Biesiada](https://github.com/mbiesiad) +- ![BR](./assets/flags/BR.png) [Brazilian Portuguese](./README.brazilian-portuguese.md) - Dzięki uprzejmości [Marcelo Melo](https://github.com/marcelosdm) +- ![CN](./assets/flags/CN.png) [Chinese](./README.chinese.md) - Dzięki uprzejmości [Matt Jin](https://github.com/mattjin) +- ![RU](./assets/flags/RU.png) [Russian](./README.russian.md) - Dzięki uprzejmości [Alex Ivanov](https://github.com/contributorpw) +- ![PL](./assets/flags/PL.png) [Polish](./README.polish.md) - Dzięki uprzejmości [Michal Biesiada](https://github.com/mbiesiad) +- ![EU](./assets/flags/EU.png) [Basque](README.basque.md) - Dzięki uprzejmości [Ane Diaz de Tuesta](https://github.com/anediaz) & Joxefe Diaz de Tuesta ### Tłumaczenia w trakcie -- ![FR](/assets/flags/FR.png) [French](https://github.com/gaspaonrocks/nodebestpractices/blob/french-translation/README.french.md) ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/129)) -- ![HE](/assets/flags/HE.png) Hebrew ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/156)) -- ![KR](/assets/flags/KR.png) [Korean](README.korean.md) - Courtesy of [Sangbeom Han](https://github.com/uronly14me) ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/94)) -- ![ES](/assets/flags/ES.png) [Spanish](https://github.com/goldbergyoni/nodebestpractices/blob/spanish-translation/README.spanish.md) ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/95)) -- ![TR](/assets/flags/TR.png) Turkish ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/139)) -- ![EU](/assets/flags/EU.png) [Basque](README.basque.md) - Courtesy of [Ane Diaz de Tuesta](https://github.com/anediaz) & Joxefe Diaz de Tuesta ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/842)) +- ![FR](./assets/flags/FR.png) [French](https://github.com/gaspaonrocks/nodebestpractices/blob/french-translation/README.french.md) ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/129)) +- ![HE](./assets/flags/HE.png) Hebrew ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/156)) +- ![KR](./assets/flags/KR.png) [Korean](README.korean.md) - Courtesy of [Sangbeom Han](https://github.com/uronly14me) ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/94)) +- ![ES](./assets/flags/ES.png) [Spanish](https://github.com/goldbergyoni/nodebestpractices/blob/spanish-translation/README.spanish.md) ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/95)) +- ![TR](./assets/flags/TR.png) Turkish ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/139))

@@ -1083,7 +1084,7 @@ Wszystkie tłumaczenia pochodzą od społeczności. Z przyjemnością uzyskamy w Spotkaj się z członkami komitetu sterującego - ludźmi, którzy pracują razem, aby zapewnić wytyczne i przyszłe kierunki projektu. Ponadto każdy członek komitetu prowadzi projekt śledzony w ramach naszych [projektów GitHub](https://github.com/goldbergyoni/nodebestpractices/projects). - + [Yoni Goldberg](https://github.com/goldbergyoni) @@ -1093,7 +1094,7 @@ Niezależny konsultant Node.js, który współpracuje z klientami w USA, Europie
- + [Bruno Scheufler](https://github.com/BrunoScheufler) @@ -1102,7 +1103,7 @@ Niezależny konsultant Node.js, który współpracuje z klientami w USA, Europie
- + [Kyle Martin](https://github.com/js-kyle) @@ -1112,7 +1113,7 @@ Full Stack Developer & Site Reliability Engineer z siedzibą w Nowej Zelandii, z
- + [Sagir Khan](https://github.com/sagirk) @@ -1127,15 +1128,15 @@ Doświadczony specjalista w JavaScript i jego ekosystemie - React, Node.js, Mong Dziękujemy wszystkim wpółpracownikom! 🙏 -Nasi współpracownicy są członkami, którzy regularnie współuczestniczą w repozytorium, sugerując nowe najlepsze praktyki, analizując problemy, sprawdzając pull requesty i wiele więcej. Jeśli chcesz pomóc nam poprowadzić tysiące ludzi do tworzenia lepszych aplikacji Node.js, przeczytaj nasze [wytyczne dla współpracowników](/.operations/CONTRIBUTING.md) 🎉 +Nasi współpracownicy są członkami, którzy regularnie współuczestniczą w repozytorium, sugerując nowe najlepsze praktyki, analizując problemy, sprawdzając pull requesty i wiele więcej. Jeśli chcesz pomóc nam poprowadzić tysiące ludzi do tworzenia lepszych aplikacji Node.js, przeczytaj nasze [wytyczne dla współpracowników](./.operations/CONTRIBUTING.md) 🎉 -| | | +| | | | :---------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------: | | [Ido Richter (Founder)](https://github.com/idori) | [Keith Holliday](https://github.com/TheHollidayInn) | ### Wcześniejsza współpraca -| | +| | | :-------------------------------------------------------------------------------------------------------------------------: | | [Refael Ackermann](https://github.com/refack) | @@ -1143,5 +1144,5 @@ Nasi współpracownicy są członkami, którzy regularnie współuczestniczą w ## Dziękujemy za uwagi -Doceniamy każdy wkład, od poprawki pojedynczego słowa, po nową najlepszą praktykę. Zobacz naszych autorów i [dokumentację CONTRIBUTORS tutaj!](CONTRIBUTORS.md) +Doceniamy każdy wkład, od poprawki pojedynczego słowa, po nową najlepszą praktykę. Zobacz naszych autorów i [dokumentację CONTRIBUTORS tutaj!](./README.md#contributors-)


diff --git a/README.russian.md b/README.russian.md index 1639a7f47..7030112dd 100644 --- a/README.russian.md +++ b/README.russian.md @@ -3,22 +3,22 @@ # Node.js Лучшие практики

- Node.js Лучшие практики + Node.js Лучшие практики


- 85 items Last update: Oct 12, 2019 Updated for Node 12.12.0 + 85 items Last update: Oct 12, 2019 Updated for Node 12.12.0

-[![nodepractices](/assets/images/twitter-s.png)](https://twitter.com/nodepractices/) **Следите за нами в Twitter!** [**@nodepractices**](https://twitter.com/nodepractices/) +[![nodepractices](./assets/images/twitter-s.png)](https://twitter.com/nodepractices/) **Следите за нами в Twitter!** [**@nodepractices**](https://twitter.com/nodepractices/)
-Читайте на других языках: [![CN](/assets/flags/CN.png)**CN**](/README.chinese.md), [![BR](/assets/flags/BR.png)**BR**](/README.brazilian-portuguese.md), [![RU](/assets/flags/RU.png)**RU**](/README.russian.md) [(![ES](/assets/flags/ES.png)**ES**, ![FR](/assets/flags/FR.png)**FR**, ![HE](/assets/flags/HE.png)**HE**, ![KR](/assets/flags/KR.png)**KR**, ![TR](/assets/flags/TR.png)**TR** and ![EU](/assets/flags/EU.png)**EU** in progress! )](#translations) +Читайте на других языках: [![CN](./assets/flags/CN.png)**CN**](./README.chinese.md), [![BR](./assets/flags/BR.png)**BR**](./README.brazilian-portuguese.md), [![RU](./assets/flags/RU.png)**RU**](./README.russian.md), [![EU](./assets/flags/EU.png)**EU**](./README.basque.md) [(![ES](./assets/flags/ES.png)**ES**, ![FR](./assets/flags/FR.png)**FR**, ![HE](./assets/flags/HE.png)**HE**, ![KR](./assets/flags/KR.png)**KR** and ![TR](./assets/flags/TR.png)**TR** in progress! )](#translations)
@@ -28,17 +28,17 @@ - **✅ Новая лучшая практика:** 7.1: [Не блокируйте цикл событий](#-71-не-блокируйте-цикл-событий) by Keith Holliday -- **🇷🇺 Перевод на русский:** Alex Ivanov недавно опубликовал [Russian translation](/README.russian.md) +- **🇷🇺 Перевод на русский:** Alex Ivanov недавно опубликовал [Russian translation](./README.russian.md) - **Мы ищем авторов текстов:** хотите помочь с примерами TypeScript? Пожалуйста, обратитесь, открыв вопрос.

-# Добро пожаловать! 3 вещи, которые вы должны знать в первую очередь: +# Добро пожаловать! 3 вещи, которые вы должны знать в первую очередь **1. На самом деле вы читаете десятки лучших статей Node.js -** этот репозиторий представляет собой краткий обзор и список наиболее популярных материалов по рекомендациям Node.js, а также материалов, написанных здесь соавторами. -**2. Это самая большая подборка, и она растет каждую неделю -** в настоящее время представлено более 80 передовых практик, руководств по стилю и архитектурных советов. Новые выпуски и запросы на добавление, чтобы обновлять эту живую книгу, создаются каждый день. Мы бы хотели, чтобы вы внесли свой вклад здесь, будь то исправление ошибок в коде, помощь с переводами или предложение блестящих новых идей. Смотрите наши [правила написания здесь](/.operations/writing-guidelines.md). +**2. Это самая большая подборка, и она растет каждую неделю -** в настоящее время представлено более 80 передовых практик, руководств по стилю и архитектурных советов. Новые выпуски и запросы на добавление, чтобы обновлять эту живую книгу, создаются каждый день. Мы бы хотели, чтобы вы внесли свой вклад здесь, будь то исправление ошибок в коде, помощь с переводами или предложение блестящих новых идей. Смотрите наши [правила написания здесь](./.operations/writing-guidelines.md). **3. У большинства лучших практик есть дополнительная информация -** большинство маркеров включают в себя ссылку **🔗 Подробнее**, которая расширяет практику с примерами кода, цитатами из выбранных блогов и дополнительной информацией. @@ -46,13 +46,13 @@ ## Оглавление -1. [Практики структуры проекта (5)](#1-Практики-структуры-проекта) -2. [Практики обработки ошибок (11)](#2-Практики-обработки-ошибок) -3. [Практики стиля кода (12)](#3-Практики-стиля-кода) -4. [Тестирование и общие методы контроля качества (12)](#4-Тестирование-и-общие-методы-контроля-качества) -5. [Переход к производственным практикам (18)](#5-Переход-к-производственным-практикам) -6. [Практики безопасности (25)](#6-Практики-безопасности) -7. [Практики эффективности (2) (Работа в процессе️ ✍️)](#7-черновик-практики-эффективности) +1. [Практики структуры проекта (5)](#1-Практики-структуры-проекта) +2. [Практики обработки ошибок (11)](#2-Практики-обработки-ошибок) +3. [Практики стиля кода (12)](#3-Практики-стиля-кода) +4. [Тестирование и общие методы контроля качества (12)](#4-Тестирование-и-общие-методы-контроля-качества) +5. [Переход к производственным практикам (18)](#5-Переход-к-производственным-практикам) +6. [Практики безопасности (25)](#6-Практики-безопасности) +7. [Практики эффективности (2) (Работа в процессе️ ✍️)](#7-черновик-практики-эффективности)

@@ -64,7 +64,7 @@ **Иначе:** Когда разработчики, которые пишут новые функции, изо всех сил пытаются понять влияние своих изменений и боятся сломать другие зависимые компоненты, развертывания становятся медленнее и рискованнее. Также считается сложнее масштабировать, когда все бизнес-единицы не разделены. -🔗 [**Подробнее: Структурируйте свое решение по компонентам**](/sections/projectstructre/breakintcomponents.russian.md) +🔗 [**Подробнее: Структурируйте свое решение по компонентам**](./sections/projectstructre/breakintcomponents.russian.md)

@@ -74,7 +74,7 @@ **Иначе:** Приложение, которое смешивает веб-объекты с другими слоями, не может быть доступно для тестирования кода, заданий CRON и других вызовов в обход Express. -🔗 [**Подробнее: Выделяйте ваши компоненты в отдельный слой, держите Express в его границах**](/sections/projectstructre/createlayers.russian.md) +🔗 [**Подробнее: Выделяйте ваши компоненты в отдельный слой, держите Express в его границах**](./sections/projectstructre/createlayers.russian.md)

@@ -84,7 +84,7 @@ **Иначе:** Вам придется изобрести собственный велосипед для развертывания и поддержания зависимостей. -🔗 [**Подробнее: Оборачивайте общие утилиты в пакеты npm**](/sections/projectstructre/wraputilities.russian.md) +🔗 [**Подробнее: Оборачивайте общие утилиты в пакеты npm**](./sections/projectstructre/wraputilities.russian.md)

@@ -94,7 +94,7 @@ **Иначе:** Ваш API будет доступен для тестирования только через HTTP-вызовы (медленнее и намного сложнее создавать отчеты о покрытии). Скорее всего, вы не будете испытывать огромное удовольствие, если будете хранить сотни строк кода в одном файле. -🔗 [**Подробнее: Разделяйте Express "приложение" и "сервер"**](/sections/projectstructre/separateexpress.russian.md) +🔗 [**Подробнее: Разделяйте Express "приложение" и "сервер"**](./sections/projectstructre/separateexpress.russian.md)

@@ -104,7 +104,7 @@ **Иначе:** Невыполнение каких-либо требований к конфигурации приведет к срывам в работе разработчиков или devops-команды. А вероятно, и тех и других. -🔗 [**Подробнее: Используйте конфигурацию с учетом среды, безопасную и иерархическую конфигурацию**](/sections/projectstructre/configguide.russian.md) +🔗 [**Подробнее: Используйте конфигурацию с учетом среды, безопасную и иерархическую конфигурацию**](./sections/projectstructre/configguide.russian.md)


@@ -118,7 +118,7 @@ **Иначе:** Callback-стиль Node.js, function(err, response), является многообещающим способом создания непригодного для использования кода из-за сочетания таких проблем, как обработка ошибок со случайным кодом, чрезмерные вложения и неудобные шаблоны проектирования. -🔗 [**Подробнее: Используйте Async-Await или обещания для асинхронной обработки ошибок**](/sections/errorhandling/asyncerrorhandling.russian.md) +🔗 [**Подробнее: Используйте Async-Await или обещания для асинхронной обработки ошибок**](./sections/errorhandling/asyncerrorhandling.russian.md)

@@ -128,7 +128,7 @@ **Иначе:** При вызове какого-либо компонента нельзя быть уверенным, какой тип ошибок приходит в ответ -- это значительно затрудняет правильную обработку ошибок. Хуже того, использование пользовательских типов для описания ошибок может привести к потере информации о критических ошибках, таких как трассировка стека! -🔗 [**Подробнее: Используйте только встроенный объект Error**](/sections/errorhandling/useonlythebuiltinerror.russian.md) +🔗 [**Подробнее: Используйте только встроенный объект Error**](./sections/errorhandling/useonlythebuiltinerror.russian.md)

@@ -138,7 +138,7 @@ **Иначе:** Вы всегда можете перезапустить приложение, когда появляется ошибка, но зачем подводить ~5000 онлайн-пользователей из-за незначительной и прогнозируемой операционной ошибки? Обратное также не является идеальным -- отсутствие перезапуска приложения в случае, если возникла неизвестная проблема (ошибка программиста), может привести к непредсказуемому поведению. Понимание типа ошибки позволит действовать тактично и применять сбалансированный подход, основанный на предоставленном контексте. -🔗 [**Подробнее: Различайте операционные ошибки и ошибки программиста**](/sections/errorhandling/operationalvsprogrammererror.russian.md) +🔗 [**Подробнее: Различайте операционные ошибки и ошибки программиста**](./sections/errorhandling/operationalvsprogrammererror.russian.md)

@@ -148,7 +148,7 @@ **Иначе:** Отсутствие обработки ошибок в едином месте приведет к дублированию кода и, возможно, к неверной обработке ошибок. -🔗 [**Подробнее: Обрабатывайте ошибки централизованно. Не в промежуточных слоях**](/sections/errorhandling/centralizedhandling.russian.md) +🔗 [**Подробнее: Обрабатывайте ошибки централизованно. Не в промежуточных слоях**](./sections/errorhandling/centralizedhandling.russian.md)

@@ -158,7 +158,7 @@ **Иначе:** Клиент API может принять решение о сбое и перезапуске только потому, что он получил ошибку, которую он не может понять. Примечание: вызывающим абонентом вашего API можете быть и вы сами (очень типично для микросервисной среды) -🔗 [**Подробнее: Документироваие ошибок API при использовании Swagger или GraphQL**](/sections/errorhandling/documentingusingswagger.russian.md) +🔗 [**Подробнее: Документироваие ошибок API при использовании Swagger или GraphQL**](./sections/errorhandling/documentingusingswagger.russian.md)

@@ -168,7 +168,7 @@ **Иначе:** Когда происходит незнакомое исключение, некоторый объект может быть в неисправном состоянии (например, источник событий, который используется глобально и больше не генерирует события из-за некоторого внутреннего сбоя), и все будущие запросы могут давать сбой или вести себя безумно. -🔗 [**Подробнее: Изящно выходите из процесса, когда неизвестное случается**](/sections/errorhandling/shuttingtheprocess.russian.md) +🔗 [**Подробнее: Изящно выходите из процесса, когда неизвестное случается**](./sections/errorhandling/shuttingtheprocess.russian.md)

@@ -178,7 +178,7 @@ **Иначе:** Сканирование через console.logs или вручную через грязный текстовый файл без запросов инструментов или приличного просмотра журнала может занять вас на работе до поздна. -🔗 [**Подробнее: Используйте проверенный логгер, чтобы увеличить видимость ошибок**](/sections/errorhandling/usematurelogger.russian.md) +🔗 [**Подробнее: Используйте проверенный логгер, чтобы увеличить видимость ошибок**](./sections/errorhandling/usematurelogger.russian.md)

@@ -188,7 +188,7 @@ **Иначе:** Без тестирования, будь то автоматически или вручную, вы не сможете полагаться на свой код для возврата правильных ошибок. Без значения ошибок -- нет обработки ошибок. -🔗 [**Подробнее: Тестируйте потоки ошибок с использованием вашей любимой тестовой среды**](/sections/errorhandling/testingerrorflows.russian.md) +🔗 [**Подробнее: Тестируйте потоки ошибок с использованием вашей любимой тестовой среды**](./sections/errorhandling/testingerrorflows.russian.md)

@@ -198,7 +198,7 @@ **Иначе:** Вы можете потратить огромные усилия на измерение производительности и времени простоя API, возможно, вы никогда самостоятельно не узнаете, какие части кода в реально сценарии самые медленные, и как они влияют на UX. -🔗 [**Подробнее: Обнаружение ошибок и простоев с использованием продуктов APM**](/sections/errorhandling/apmproducts.russian.md) +🔗 [**Подробнее: Обнаружение ошибок и простоев с использованием продуктов APM**](./sections/errorhandling/apmproducts.russian.md)

@@ -208,7 +208,7 @@ **Иначе:** Ваши ошибки будут проглочены и не оставят следов. Не о чем беспокоиться! -🔗 [**Подробнее: Перехватывайте необработанные отказы от обещаний**](/sections/errorhandling/catchunhandledpromiserejection.russian.md) +🔗 [**Подробнее: Перехватывайте необработанные отказы от обещаний**](./sections/errorhandling/catchunhandledpromiserejection.russian.md)

@@ -218,7 +218,7 @@ **Иначе:** Учтите это -- ваша функция ожидает числовой аргумент "Скидка", который вызывающая сторона забывает передать, позже ваш код проверяет, если Скидка !=0 (сумма разрешенной скидки больше нуля), тогда она позволит пользователю пользоваться скидкой. О, Боже, какая неприятная ошибка! Видишь? -🔗 [**Подробнее: Быстро проваливайтесь, проверяя аргументы, используя выделенную библиотеку**](/sections/errorhandling/failfast.russian.md) +🔗 [**Подробнее: Быстро проваливайтесь, проверяя аргументы, используя выделенную библиотеку**](./sections/errorhandling/failfast.russian.md)


@@ -235,7 +235,7 @@ пропуски, вероятнее всего, усложнят процесс понимания пути возникновения ошибки, особенно если причина ненормального поведения как раз в отсутствующей функции и находится -🔗 [**Подробнее: возвращение промисов**](/sections/errorhandling/returningpromises.russian.md) +🔗 [**Подробнее: возвращение промисов**](./sections/errorhandling/returningpromises.russian.md)

⬆ К началу

@@ -247,7 +247,7 @@ **Иначе:** Разработчики сосредоточатся на утомительных проблемах с интервалами и шириной линии, и время может быть потрачено впустую на продумывание стиля кода проекта. -🔗 [**Подробнее: Использование ESLint и Prettier**](/sections/codestylepractices/eslint_prettier.russian.md) +🔗 [**Подробнее: Использование ESLint и Prettier**](./sections/codestylepractices/eslint_prettier.russian.md)

@@ -259,7 +259,7 @@

-##! [✔] 3.3 Начинайте кодовый блок фигурными скобками на той же линии. +## ! [✔] 3.3 Начинайте кодовый блок фигурными скобками на той же линии **TL;DR:** Открывающие фигурные скобки блока кода должны находиться на той же строке, что и оператор открытия. @@ -272,7 +272,8 @@ function someFunction() { } // Избегайте -function someFunction() { +function someFunction() +{ // code block } ``` @@ -283,7 +284,7 @@ function someFunction() {

-##! [✔] 3.4 Разделяйте свои выражения правильно +## ! [✔] 3.4 Разделяйте свои выражения правильно Независимо от того, используете ли вы точки с запятой или нет для разделения своих операторов, знание общих ошибок неправильных разрывов строк или автоматической вставки точек с запятой поможет вам устранить обычные синтаксические ошибки. @@ -291,7 +292,7 @@ function someFunction() { **Иначе:** Как видно из предыдущего раздела, интерпретатор JavaScript автоматически добавляет точку с запятой в конце оператора, если его нет, или считает, что оператор не завершен, где он должен, что может привести к нежелательным результатам. , Вы можете использовать присваивания и избегать немедленного вызова выражений функций для предотвращения большинства непредвиденных ошибок. -### Пример кода +### 3.4 Пример кода ```javascript // Делайте так @@ -341,7 +342,7 @@ const count = 2 // it tries to run 2(), but 2 is not a function **Иначе:** Javascript -- это единственный язык в мире, который позволяет напрямую вызывать конструктор ("Class") без его инициализации. Следовательно, классы и конструкторы функций должщны различаться, начинаясь с UpperCamelCase. -### Пример кода +### 3.6 Пример кода ```javascript // для класса мы используем UpperCamelCase @@ -383,7 +384,7 @@ function doSomething() {} **Иначе:** Изменение внутренней структуры файлов или подписи может нарушить интерфейс с клиентами. -### Пример кода +### 3.9 Пример кода ```javascript // Делайте так @@ -403,7 +404,7 @@ module.exports.SMSNumberResolver = require("./SMSNumberResolver/SMSNumberResolve **Иначе:** Неравные переменные могут возвращать true при сравнении с оператором `==`. -### Пример кода +### 3.10 Пример кода ```javascript "" == "0"; // false @@ -462,7 +463,7 @@ null == undefined; // true **Иначе:** Развертывание только что прошло, тест под названием "Добавить продукт" не прошел. Это говорит вам, что именно работает со сбоями? -🔗 [**Подробнее: Включите 3 части в каждое название теста**](/sections/testingandquality/3-parts-in-name.russian.md) +🔗 [**Подробнее: Включите 3 части в каждое название теста**](./sections/testingandquality/3-parts-in-name.russian.md)

@@ -472,7 +473,7 @@ null == undefined; // true **Иначе:** Не только вы тратите долгие ежедневные часы на понимание основного кода, теперь и то, что должно было быть простой частью дня (тестирование), напрягает ваш мозг. -🔗 [**Read More: Structure tests by the AAA pattern**](/sections/testingandquality/aaa.russian.md) +🔗 [**Read More: Structure tests by the AAA pattern**](./sections/testingandquality/aaa.russian.md)

@@ -490,7 +491,7 @@ null == undefined; // true **Иначе:** Рассмотрим сценарий, в котором развертывание прерывается из-за неудачных тестов, теперь команда собирается потратить драгоценное время на исследование, которое заканчивается печальным выводом: система работает хорошо, однако тесты мешают друг другу и нарушают сборку. -🔗 [**Подробнее: Избегайте глобальных тестовых приспособлений и параметров, добавляйте данные для каждого теста**](/sections/testingandquality/avoid-global-test-fixture.russian.md) +🔗 [**Подробнее: Избегайте глобальных тестовых приспособлений и параметров, добавляйте данные для каждого теста**](./sections/testingandquality/avoid-global-test-fixture.russian.md)

@@ -540,7 +541,7 @@ null == undefined; // true **Иначе:** При плохом качестве кода ошибки и производительность всегда будут проблемой, которую не может исправить ни одна блестящая новая библиотека или современные функции. -🔗 [**Подробнее: Рефакторинг**](/sections/testingandquality/refactoring.russian.md) +🔗 [**Подробнее: Рефакторинг**](./sections/testingandquality/refactoring.russian.md)

@@ -550,7 +551,7 @@ null == undefined; // true **Иначе:** Выбор какого-либо нишевого поставщика может заблокировать вас, когда вам понадобится дополнительная настройка. С другой стороны, работа с Jenkins может потратить драгоценное время на настройку инфраструктуры. -🔗 [**Подробнее: Тщательно выбирайте платформу CI**](/sections/testingandquality/citools.russian.md) +🔗 [**Подробнее: Тщательно выбирайте платформу CI**](./sections/testingandquality/citools.russian.md)


@@ -558,13 +559,13 @@ null == undefined; // true # `5. Переход к производственным практикам` -## ![✔] 5.1. Мониторинг! +## ![✔] 5.1. Мониторинг **TL;DR:** Мониторинг -- это игра для выявления проблем до того, как их решат клиенты, очевидно, этому следует придать беспрецедентную важность. Рынок перегружен предложениями, поэтому подумайте о том, чтобы начать с определения основных метрик, которым вы должны следовать (мои предложения в подробностях), затем перейти к дополнительным необычным функциям и выбрать решение, которое помечает все поля. Нажмите "Подробнее" ниже для обзора решений. **Иначе:** Отказ === разочарованные клиенты. Просто. -🔗 [**Подробнее: Мониторинг!**](/sections/production/monitoring.russian.md) +🔗 [**Подробнее: Мониторинг!**](./sections/production/monitoring.russian.md)

@@ -574,7 +575,7 @@ null == undefined; // true **Иначе:** Вы в конечном итоге получаете черный ящик, о котором трудно подумать, затем вы начинаете переписывать все операторы регистрации, чтобы добавить дополнительную информацию. -🔗 [**Подробнее: Сделайте ваше приложение прозрачным, используя умные логи**](/sections/production/smartlogging.russian.md) +🔗 [**Подробнее: Сделайте ваше приложение прозрачным, используя умные логи**](./sections/production/smartlogging.russian.md)

@@ -584,7 +585,7 @@ null == undefined; // true **Иначе:** Ваш бедный одиночный поток будет занят выполнением инфраструктурных задач вместо того, чтобы работать с ядром приложения, и производительность будет соответственно снижаться. -🔗 [**Подробнее: Делегируйте все возможное (например, gzip, SSL) обратному прокси**](/sections/production/delegatetoproxy.russian.md) +🔗 [**Подробнее: Делегируйте все возможное (например, gzip, SSL) обратному прокси**](./sections/production/delegatetoproxy.russian.md)

@@ -594,7 +595,7 @@ null == undefined; // true **Иначе:** QA тщательно протестирует код и утвердит версию, которая будет вести себя по-другому в производстве. Хуже того, на разных серверах в одном и том же производственном кластере может выполняться другой код. -🔗 [**Подробнее: Блокируйте зависимости**](/sections/production/lockdependencies.russian.md) +🔗 [**Подробнее: Блокируйте зависимости**](./sections/production/lockdependencies.russian.md)

@@ -604,7 +605,7 @@ null == undefined; // true **Иначе:** Запуск десятков экземпляров без четкой стратегии и слишком большого количества инструментов (управление кластером, docker, PM2) может привести к хаосу DevOps. -🔗 [**Подробнее: Защищайте и перезапускайте свой процесс в случае неудачи (используя правильный инструмент)**](/sections/production/guardprocess.russian.md) +🔗 [**Подробнее: Защищайте и перезапускайте свой процесс в случае неудачи (используя правильный инструмент)**](./sections/production/guardprocess.russian.md)

@@ -614,7 +615,7 @@ null == undefined; // true **Иначе:** Ваше приложение, скорее всего, будет использовать только 25% доступных ресурсов (!) Или даже меньше. Обратите внимание, что типичный сервер имеет 4 или более ядер ЦП, для простого развертывания Node.js используется только 1 (даже при использовании сервисов PaaS, таких как AWS beanstalk!) -🔗 [**Подробнее: Используйте все ядра процессора**](/sections/production/utilizecpu.russian.md) +🔗 [**Подробнее: Используйте все ядра процессора**](./sections/production/utilizecpu.russian.md)

@@ -624,7 +625,7 @@ null == undefined; // true **Иначе:** Вы обнаружите, что выполняете много "диагностических развертываний" -- отправка кода в производство только для извлечения некоторой информации в диагностических целях. -🔗 [**Подробнее: Создавайте конечную точку обслуживания**](/sections/production/createmaintenanceendpoint.russian.md) +🔗 [**Подробнее: Создавайте конечную точку обслуживания**](./sections/production/createmaintenanceendpoint.russian.md)

@@ -634,7 +635,7 @@ null == undefined; // true **Иначе:** Вы можете потратить огромные усилия на измерение производительности и времени простоя API, возможно, вы никогда не узнаете, какие ваши самые медленные части кода в реальном сценарии и как они влияют на UX. -🔗 [**Подробнее: Уверенный пользовательский опыт с продуктами APM**](/sections/production/apmproducts.russian.md) +🔗 [**Подробнее: Уверенный пользовательский опыт с продуктами APM**](./sections/production/apmproducts.russian.md)

@@ -644,7 +645,7 @@ null == undefined; // true **Иначе:** Чемпион мира по IT/DevOps не спасет плохо написанную систему. -🔗 [**Подробнее: Делайте ваш код готовым к работе**](/sections/production/productioncode.russian.md) +🔗 [**Подробнее: Делайте ваш код готовым к работе**](./sections/production/productioncode.russian.md)

@@ -654,7 +655,7 @@ null == undefined; // true **Иначе:** Ваша память процесса может пропускать сотни мегабайт в день, как это было в [Walmart](https://www.joyent.com/blog/walmart-node-js-memory-leak). -🔗 [**Подробнее: Измеряйте и защищайте использование памяти**](/sections/production/measurememory.russian.md) +🔗 [**Подробнее: Измеряйте и защищайте использование памяти**](./sections/production/measurememory.russian.md)

@@ -664,7 +665,7 @@ null == undefined; // true **Иначе:** Ваш единственный поток Node будет занят потоковой передачей сотен файлов html/images/angular/react вместо того, чтобы выделять все свои ресурсы на задачи, для которой он был создан -- обслуживание динамического контента. -🔗 [**Подробнее: Получайте ваши внешние ресурсы вне Node**](/sections/production/frontendout.russian.md) +🔗 [**Подробнее: Получайте ваши внешние ресурсы вне Node**](./sections/production/frontendout.russian.md)

@@ -674,7 +675,7 @@ null == undefined; // true **Иначе:** Сбой на данном сервере приведет к простою приложения, а не просто к гибели неисправного компьютера. Более того, гибкость масштабирования станет более сложной из-за зависимости от конкретного сервера. -🔗 [**Подробнее: Не прописывайтесь на постоянку, убивайте свои серверы почти каждый день**](/sections/production/bestateless.md) +🔗 [**Подробнее: Не прописывайтесь на постоянку, убивайте свои серверы почти каждый день**](./sections/production/bestateless.md)

@@ -684,7 +685,7 @@ null == undefined; // true **Иначе:** Для обеспечения чистоты кода от уязвимостей без использования специальных инструментов вам потребуется постоянно следить за публикациями в Интернете о новых угрозах. Довольно утомительно. -🔗 [**Подробнее: Используйте инструменты, которые автоматически обнаруживают уязвимые зависимости**](/sections/production/detectvulnerabilities.russian.md) +🔗 [**Подробнее: Используйте инструменты, которые автоматически обнаруживают уязвимые зависимости**](./sections/production/detectvulnerabilities.russian.md)

@@ -694,7 +695,7 @@ null == undefined; // true **Иначе:** Глядя на журнал ошибок производства без контекста -- что произошло раньше -- становится намного сложнее и медленнее рассуждать о проблеме. -🔗 [**Read More: Назначьте "TransactionId" для каждого вхождения журнала логирования**](/sections/production/assigntransactionid.russian.md) +🔗 [**Read More: Назначьте "TransactionId" для каждого вхождения журнала логирования**](./sections/production/assigntransactionid.russian.md)

@@ -704,7 +705,7 @@ null == undefined; // true **Иначе:** Пропуск этого простого свойства может значительно снизить производительность. Например, при использовании Express для рендеринга на стороне сервера пропуск `NODE_ENV` замедляет его в три раза! -🔗 [**Подробнее: Устанавливайте NODE_ENV=production**](/sections/production/setnodeenv.russian.md) +🔗 [**Подробнее: Устанавливайте NODE_ENV=production**](./sections/production/setnodeenv.russian.md)

@@ -722,7 +723,7 @@ null == undefined; // true **Иначе:** Недавно обнаруженные ошибки или уязвимости могут быть использованы для эксплуатации приложения, работающего в производственной среде, и ваше приложение может стать неподдерживаемым различными модулями и усложнить поддержку. -🔗 [**Подробнее: Используйте LTS-релиз Node.js в производстве**](/sections/production/LTSrelease.russian.md) +🔗 [**Подробнее: Используйте LTS-релиз Node.js в производстве**](./sections/production/LTSrelease.russian.md)

@@ -732,7 +733,7 @@ null == undefined; // true **Иначе:** Маршрутизация журналов обработки приложения === трудности масштабирования, потеря журналов, плохое разделение задач -🔗 [**Подробнее: Код вашего приложения не должен обрабатывать журналы маршрутизации**](/sections/production/logrouting.russian.md) +🔗 [**Подробнее: Код вашего приложения не должен обрабатывать журналы маршрутизации**](./sections/production/logrouting.russian.md)


@@ -752,7 +753,7 @@ null == undefined; // true **Иначе:** То, что могло быть простым недостатком безопасности во время разработки, становится основной проблемой в производстве. Кроме того, проект может не следовать согласованным методам обеспечения безопасности кода, что приводит к появлению уязвимостей или секретных секретов, передаваемых в удаленные репозитории. -🔗 [**Подробнее: Пользуйтесь правилами безопасности линтера**](/sections/security/lintrules.russian.md) +🔗 [**Подробнее: Пользуйтесь правилами безопасности линтера**](./sections/security/lintrules.russian.md)

@@ -764,7 +765,7 @@ null == undefined; // true **Иначе:** Приложение может подвергнуться атаке, приводящей к отказу в обслуживании, когда реальные пользователи получают ухудшенный или недоступный сервис. -🔗 [**Подробнее: Ограничивайте одновременные запросы с использованием балансировщика или промежуточного программного обеспечения**](/sections/security/limitrequests.russian.md) +🔗 [**Подробнее: Ограничивайте одновременные запросы с использованием балансировщика или промежуточного программного обеспечения**](./sections/security/limitrequests.russian.md)

@@ -776,7 +777,7 @@ null == undefined; // true **Иначе:** Контроль источников, даже для частных репозиториев, может быть ошибочно обнародован, после чего все секреты будут раскрыты. Доступ к управлению исходным кодом для внешней стороны непреднамеренно предоставит доступ к связанным системам (базам данных, API, службам и т.д.). -🔗 [**Подробнее: Извлекайте секреты из конфигурационных файлов или используйте пакет npm, который их шифрует**](/sections/security/secretmanagement.russian.md) +🔗 [**Подробнее: Извлекайте секреты из конфигурационных файлов или используйте пакет npm, который их шифрует**](./sections/security/secretmanagement.russian.md)

@@ -788,15 +789,15 @@ null == undefined; // true **Иначе:** Непроверенный или недеанонимизированный пользовательский ввод может привести к внедрению оператора при работе с MongoDB для NoSQL, а отсутствие надлежащей системы очистки или ORM легко разрешит атаки с использованием SQL-инъекции, создав гигантскую уязвимость. -🔗 [**Подробнее: Предотвращайте уязвимости при внедрении базы данных с помощью библиотек ORM/ODM или других пакетов DAL**](/sections/security/ormodmusage.russian.md) +🔗 [**Подробнее: Предотвращайте уязвимости при внедрении базы данных с помощью библиотек ORM/ODM или других пакетов DAL**](./sections/security/ormodmusage.russian.md)

-##! [✔] 6.5. Сборник общих рекомендаций по безопасности +## ! [✔] 6.5. Сборник общих рекомендаций по безопасности **TL;DR:** Это набор рекомендаций по безопасности, которые не связаны напрямую с Node.js -- реализация Node мало чем отличается от любого другого языка. Нажмите "Подробнее", чтобы просмотреть. -🔗 [**Подробнее: Общие рекомендации по безопасности Node.js**](/sections/security/commonsecuritybestpractices.russian.md) +🔗 [**Подробнее: Общие рекомендации по безопасности Node.js**](./sections/security/commonsecuritybestpractices.russian.md)

@@ -808,7 +809,7 @@ null == undefined; // true **Иначе:** Злоумышленники могут выполнять прямые атаки на пользователей вашего приложения, что приводит к огромным уязвимостям безопасности. -🔗 [**Подробнее: Используйте связанные с безопасностью заголовки для защиты вашего приложения от распространенных атак**](/sections/security/secureheaders.russian.md) +🔗 [**Подробнее: Используйте связанные с безопасностью заголовки для защиты вашего приложения от распространенных атак**](./sections/security/secureheaders.russian.md)

@@ -820,7 +821,7 @@ null == undefined; // true **Иначе:** Злоумышленник может обнаружить ваш веб-фреймворк и атаковать все его известные уязвимости. -🔗 [**Подробнее: Постоянно и автоматически проверяйте наличие уязвимых зависимостей**](/sections/security/dependencysecurity.russian.md) +🔗 [**Подробнее: Постоянно и автоматически проверяйте наличие уязвимых зависимостей**](./sections/security/dependencysecurity.russian.md)

@@ -832,11 +833,11 @@ null == undefined; // true **Иначе:** Пароли или секреты, которые сохраняются без использования защищенной функции, уязвимы для взлома и атак по словарю, которые в конечном итоге приведут к их раскрытию. -🔗 [**Подробнее: Не используйте криптографическую библиотеку Node.js для паролей, используйте Bcrypt**](/sections/security/bcryptpasswords.russian.md) +🔗 [**Подробнее: Не используйте криптографическую библиотеку Node.js для паролей, используйте Bcrypt**](./sections/security/bcryptpasswords.russian.md)

-##! [✔] 6.9. Экранируйте вывод HTML, JS и CSS +## ! [✔] 6.9. Экранируйте вывод HTML, JS и CSS @@ -844,7 +845,7 @@ null == undefined; // true **Иначе:** Злоумышленник может сохранить вредоносный код JavaScript в вашей БД, который затем будет отправлен бедным клиентам как есть. -🔗 [**Подробнее: Экранируйте вывод**](/sections/security/escape-output.russian.md) +🔗 [**Подробнее: Экранируйте вывод**](./sections/security/escape-output.russian.md)

@@ -856,7 +857,7 @@ null == undefined; // true **Иначе:** Ваша щедрость и разрешительный подход значительно увеличивают поверхность атаки и побуждают злоумышленника опробовать множество входных данных, пока они не найдут какую-то комбинацию для сбоя приложения. -🔗 [**Подробнее: Проверяйте входящие JSON схемы**](/sections/security/validation.russian.md) +🔗 [**Подробнее: Проверяйте входящие JSON схемы**](./sections/security/validation.russian.md)

@@ -868,7 +869,7 @@ null == undefined; // true **Иначе:** Устаревшие или неуместные токены могут быть использованы злонамеренно для доступа к приложению третьей стороной, которая может выдавать себя за владельца токена. -🔗 [**Подробнее: Реализовывайте поддержку внесения JWT в черный список**](/sections/security/expirejwt.russian.md) +🔗 [**Подробнее: Реализовывайте поддержку внесения JWT в черный список**](./sections/security/expirejwt.russian.md)

@@ -883,7 +884,7 @@ null == undefined; // true **Иначе:** Злоумышленник может выполнить неограниченное количество автоматических попыток ввода пароля для получения доступа к привилегированным учетным записям в приложении. -🔗 [**Подробнее: Предотвращайте атаки методом грубой силы против авторизации**](/section/security/login-rate-limit.russian.md) +🔗 [**Подробнее: Предотвращайте атаки методом грубой силы против авторизации**](./sections/security/login-rate-limit.russian.md)

@@ -895,7 +896,7 @@ null == undefined; // true **Иначе:** Злоумышленник, которому удается запустить скрипт на сервере, получает неограниченную власть над локальной машиной (например, он может изменить iptable и перенаправить трафик на свой сервер). -🔗 [**Подробнее: Запускайте Node.js как пользователь без полномочий root**](/sections/security/non-root-user.russian.md) +🔗 [**Подробнее: Запускайте Node.js как пользователь без полномочий root**](./sections/security/non-root-user.russian.md)

@@ -907,7 +908,7 @@ null == undefined; // true **Иначе:** Вашему приложению придется иметь дело с большими запросами, неспособными обработать другую важную работу, которую он должен выполнить, что приводит к снижению производительности и уязвимости к атакам DOS. -🔗 [**Подробнее: Ограничивайте размер полезной нагрузки с помощью обратного прокси или промежуточного ПО**](/sections/security/requestpayloadsizelimit.russian.md) +🔗 [**Подробнее: Ограничивайте размер полезной нагрузки с помощью обратного прокси или промежуточного ПО**](./sections/security/requestpayloadsizelimit.russian.md)

@@ -915,11 +916,11 @@ null == undefined; // true -**TL;DR:** `eval` -- это зло, поскольку оно позволяет выполнять пользовательский код JavaScript во время выполнения. Это не только проблема производительности, но и важная проблема безопасности из-за вредоносного кода JavaScript, который может быть получен из пользовательского ввода. Другой языковой особенностью, которую следует избегать, является конструктор `new Function`. `setTimeout` и` setInterval` также никогда не должны передавать динамический код JavaScript. +**TL;DR:** `eval` -- это зло, поскольку оно позволяет выполнять пользовательский код JavaScript во время выполнения. Это не только проблема производительности, но и важная проблема безопасности из-за вредоносного кода JavaScript, который может быть получен из пользовательского ввода. Другой языковой особенностью, которую следует избегать, является конструктор `new Function`. `setTimeout` и`setInterval` также никогда не должны передавать динамический код JavaScript. **Иначе:** Вредоносный код JavaScript находит путь в текст, передаваемый в `eval` или другие функции оценки языка JavaScript в режиме реального времени, и получает полный доступ к разрешениям JavaScript на странице. Эта уязвимость часто проявляется как атака XSS. -🔗 [**Подробнее: Избегайте JavaScript eval утверждений**](/sections/security/avoideval.russian.md) +🔗 [**Подробнее: Избегайте JavaScript eval утверждений**](./sections/security/avoideval.russian.md)

@@ -931,7 +932,7 @@ null == undefined; // true **Иначе:** Плохо написанные регулярные выражения могут быть подвержены DoS-атакам регулярного выражения, которые полностью блокируют цикл обработки событий. Например, популярный пакет `момент` был посчитан уязвимым для вредоносного использования RegEx в ноябре 2017 года. -🔗 [**Подробнее: Предотвращайте ваше однопоточное выполнение от перегрузки злонамеренным RegEx**](/sections/security/regex.russian.md) +🔗 [**Подробнее: Предотвращайте ваше однопоточное выполнение от перегрузки злонамеренным RegEx**](./sections/security/regex.russian.md)

@@ -943,7 +944,7 @@ null == undefined; // true **Иначе:** Вредоносный пользовательский ввод может найти путь к параметру, который используется для запроса измененных файлов, например, ранее загруженного файла в файловой системе, или для доступа к уже существующим системным файлам. -🔗 [**Подробнее: Избегайте загрузки модулей с использованием переменных**](/sections/security/safemoduleloading.russian.md) +🔗 [**Подробнее: Избегайте загрузки модулей с использованием переменных**](./sections/security/safemoduleloading.russian.md)

@@ -955,7 +956,7 @@ null == undefined; // true **Иначе:** Плагин может атаковать с помощью бесконечного множества вариантов, таких как бесконечные циклы, перегрузка памяти и доступ к чувствительным переменным среды процесса. -🔗 [**Подробнее: Запускайте небезопасный код в песочнице**](/sections/security/sandbox.russian.md) +🔗 [**Подробнее: Запускайте небезопасный код в песочнице**](./sections/security/sandbox.russian.md)

@@ -967,7 +968,7 @@ null == undefined; // true **Иначе:** Наивное использование дочерних процессов может привести к удаленному выполнению команды или атакам внедрения оболочки из-за того, что злонамеренный пользовательский ввод передан неантизированной системной команде. -🔗 [**Подробнее: Будьте осторожны при работе с дочерними процессами**](/sections/security/childprocesses.russian.md) +🔗 [**Подробнее: Будьте осторожны при работе с дочерними процессами**](./sections/security/childprocesses.russian.md)

@@ -979,7 +980,7 @@ null == undefined; // true **Иначе:** Чувствительная информация о приложении, такая как пути к файлам сервера, используемые сторонние модули и другие внутренние рабочие процессы приложения, которые могут быть использованы злоумышленником, может быть утечка из информации, найденной в трассировке стека. -🔗 [**Подробнее: Скрывайте детали ошибок от клиентов**](/sections/security/hideerrors.russian.md) +🔗 [**Подробнее: Скрывайте детали ошибок от клиентов**](./sections/security/hideerrors.russian.md)

@@ -1001,7 +1002,7 @@ null == undefined; // true **Иначе:** Файлы cookie могут быть отправлены по незащищенным соединениям, и злоумышленник может использовать идентификатор сеанса для определения базовой структуры веб-приложения, а также уязвимостей, специфичных для модуля. -🔗 [**Подробнее: Изменяйте настройки промежуточного программного обеспечения сеанса по умолчанию**](/sections/security/sessions.russian.md) +🔗 [**Подробнее: Изменяйте настройки промежуточного программного обеспечения сеанса по умолчанию**](./sections/security/sessions.russian.md)

@@ -1023,7 +1024,7 @@ null == undefined; // true **Иначе:** Если злоумышленник обнаружит, что вы не проверяете внешний вводимый пользователем ввод, он может воспользоваться этой уязвимостью, разместив специально созданные ссылки на форумах, в социальных сетях и других общедоступных местах, чтобы пользователи могли щелкнуть по нему. -🔗 [**Подробнее: Предотвращайте небезопасные перенаправления**](/sections/security/saferedirects.russian.md) +🔗 [**Подробнее: Предотвращайте небезопасные перенаправления**](./sections/security/saferedirects.russian.md)

@@ -1031,11 +1032,11 @@ null == undefined; // true -**TL;DR:** Следует принять меры предосторожности, чтобы избежать риска случайной публикации секретов в открытых реестрах npm. Файл `.npmignore` может использоваться для внесения в черный список определенных файлов или папок, или массив` files` в `package.json` может выступать в качестве белого списка. +**TL;DR:** Следует принять меры предосторожности, чтобы избежать риска случайной публикации секретов в открытых реестрах npm. Файл `.npmignore` может использоваться для внесения в черный список определенных файлов или папок, или массив`files` в `package.json` может выступать в качестве белого списка. **Иначе:** Ключи API вашего проекта, пароли или другие секреты открыты для злоупотребления любым, кто сталкивается с ними, что может привести к финансовым потерям, подлогу и другим рискам. -🔗 [**Подробнее: Избегайте публикации секретов в реестре npm**](/sections/security/avoid_publishing_secrets.russian.md) +🔗 [**Подробнее: Избегайте публикации секретов в реестре npm**](./sections/security/avoid_publishing_secrets.russian.md)


⬆ К началу

@@ -1052,7 +1053,7 @@ null == undefined; // true **Иначе:** Поскольку цикл обработки событий заблокирован, Node.js не сможет обработать другой запрос, что приведет к задержкам для одновременных пользователей. **3000 пользователей ждут ответа, контент готов к отправке, но один-единственный запрос не позволяет серверу отправить результаты обратно** -🔗 [**Read More: Не блокируйте цикл событий**](/sections/performance/block-loop.russian.md) +🔗 [**Read More: Не блокируйте цикл событий**](./sections/performance/block-loop.russian.md)


@@ -1063,7 +1064,7 @@ null == undefined; // true **Иначе:** Вам придется поддерживать менее эффективные проекты, где вы могли бы просто использовать то, что **уже** доступно или иметь дело с еще несколькими строками в обмен на еще несколько файлов. -🔗 [**Подробнее: Предпочитайте нативные методы JS над пользовательскими утилитами, такими как Lodash**](/sections/performance/nativeoverutil.russian.md) +🔗 [**Подробнее: Предпочитайте нативные методы JS над пользовательскими утилитами, такими как Lodash**](./sections/performance/nativeoverutil.russian.md)


@@ -1079,18 +1080,18 @@ null == undefined; // true ### Завершенные переводы -- ![BR](/assets/flags/BR.png) [Brazilian Portuguese](./README.brazilian-portuguese.md) - Любезно предоставлено [Marcelo Melo](https://github.com/marcelosdm) -- ![CN](/assets/flags/CN.png) [Chinese](./README.chinese.md) - Любезно предоставлено [Matt Jin](https://github.com/mattjin) -- ![RU](/assets/flags/RU.png) [Russian](./README.russian.md) - Любезно предоставлено [Alex Ivanov](https://github.com/contributorpw) +- ![BR](./assets/flags/BR.png) [Brazilian Portuguese](./README.brazilian-portuguese.md) - Любезно предоставлено [Marcelo Melo](https://github.com/marcelosdm) +- ![CN](./assets/flags/CN.png) [Chinese](./README.chinese.md) - Любезно предоставлено [Matt Jin](https://github.com/mattjin) +- ![RU](./assets/flags/RU.png) [Russian](./README.russian.md) - Любезно предоставлено [Alex Ivanov](https://github.com/contributorpw) +- ![EU](./assets/flags/EU.png) [Basque](README.basque.md) - Любезно предоставлено [Ane Diaz de Tuesta](https://github.com/anediaz) & Joxefe Diaz de Tuesta ### Переводы в процессе -- ![FR](/assets/flags/FR.png) [French](https://github.com/gaspaonrocks/nodebestpractices/blob/french-translation/README.french.md) ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/129)) -- ![HE](/assets/flags/HE.png) Hebrew ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/156)) -- ![KR](/assets/flags/KR.png) [Korean](README.korean.md) - Любезно предоставлено [Sangbeom Han](https://github.com/uronly14me) ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/94)) -- ![ES](/assets/flags/ES.png) [Spanish](https://github.com/goldbergyoni/nodebestpractices/blob/spanish-translation/README.spanish.md) ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/95)) -- ![TR](/assets/flags/TR.png) Turkish ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/139)) -- ![EU](/assets/flags/EU.png) [Basque](README.basque.md) - Любезно предоставлено [Ane Diaz de Tuesta](https://github.com/anediaz) & Joxefe Diaz de Tuesta ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/842)) +- ![FR](./assets/flags/FR.png) [French](https://github.com/gaspaonrocks/nodebestpractices/blob/french-translation/README.french.md) ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/129)) +- ![HE](./assets/flags/HE.png) Hebrew ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/156)) +- ![KR](./assets/flags/KR.png) [Korean](README.korean.md) - Любезно предоставлено [Sangbeom Han](https://github.com/uronly14me) ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/94)) +- ![ES](./assets/flags/ES.png) [Spanish](https://github.com/goldbergyoni/nodebestpractices/blob/spanish-translation/README.spanish.md) ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/95)) +- ![TR](./assets/flags/TR.png) Turkish ([Discussion](https://github.com/goldbergyoni/nodebestpractices/issues/139))

@@ -1098,17 +1099,17 @@ null == undefined; // true Познакомьтесь с членами руководящего комитета -- людьми, которые работают вместе, чтобы обеспечить управление и дальнейшее руководство проектом. Кроме того, каждый член комитета руководит проектом, отслеживаемым в рамках наших [проектов Github](https://github.com/goldbergyoni/nodebestpractices/projects). - + [Yoni Goldberg](https://github.com/goldbergyoni) -Независимый консультант Node.js, который работает с клиентами в США, Европе и Израиле над созданием масштабируемых масштабируемых приложений Node. Многие из приведенных выше лучших практик были впервые опубликованы на [goldbergyoni.com](https://goldbergyoni.com). Свяжитесь с Yoni как @goldbergyoni или me@goldbergyoni.com +Независимый консультант Node.js, который работает с клиентами в США, Европе и Израиле над созданием масштабируемых приложений Node. Многие из приведенных выше лучших практик были впервые опубликованы на [goldbergyoni.com](https://goldbergyoni.com). Свяжитесь с Yoni как @goldbergyoni или me@goldbergyoni.com
- + [Bruno Scheufler](https://github.com/BrunoScheufler) @@ -1117,7 +1118,7 @@ null == undefined; // true
- + [Kyle Martin](https://github.com/js-kyle) @@ -1127,7 +1128,7 @@ null == undefined; // true
- + [Sagir Khan](https://github.com/sagirk) @@ -1142,15 +1143,15 @@ null == undefined; // true Спасибо всем нашим соавторам! 🙏 -Наши соавторы являются участниками, которые регулярно вносят свой вклад в хранилище, предлагая новые лучшие практики, разбирая проблемы, просматривая запросы на изменение и многое другое. Если вы заинтересованы в том, чтобы помочь нам научить тысячи людей создавать более качественные приложения Node.js, ознакомьтесь с нашими [руководством для соавторов](/.operations/CONTRIBUTING.md) 🎉 +Наши соавторы являются участниками, которые регулярно вносят свой вклад в хранилище, предлагая новые лучшие практики, разбирая проблемы, просматривая запросы на изменение и многое другое. Если вы заинтересованы в том, чтобы помочь нам научить тысячи людей создавать более качественные приложения Node.js, ознакомьтесь с нашими [руководством для соавторов](./.operations/CONTRIBUTING.md) 🎉 -| | | +| | | | :---------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------: | | [Ido Richter (Founder)](https://github.com/idori) | [Keith Holliday](https://github.com/TheHollidayInn) | ### Прошлые соавторы -| | +| | | :-------------------------------------------------------------------------------------------------------------------------: | | [Refael Ackermann](https://github.com/refack) | @@ -1158,6 +1159,6 @@ null == undefined; // true ## Благодарности -Мы ценим любой вклад, от одного исправленного слова до новой лучшей практики. Список участников и [документация по поддержке тут!](CONTRIBUTORS.md) +Мы ценим любой вклад, от одного исправленного слова до новой лучшей практики. Список участников и [документация по поддержке тут!](./README.md#contributors-)


diff --git a/assets/flags/AR.png b/assets/flags/AR.png new file mode 100644 index 000000000..a5bb1c4e2 Binary files /dev/null and b/assets/flags/AR.png differ diff --git a/assets/flags/BR.jpg b/assets/flags/BR.jpg index 1f295edff..387b7e983 100644 Binary files a/assets/flags/BR.jpg and b/assets/flags/BR.jpg differ diff --git a/assets/flags/EN.png b/assets/flags/EN.png new file mode 100644 index 000000000..0291e2982 Binary files /dev/null and b/assets/flags/EN.png differ diff --git a/assets/flags/JA.png b/assets/flags/JA.png index cbd5f3c5e..964d5b059 100644 Binary files a/assets/flags/JA.png and b/assets/flags/JA.png differ diff --git a/assets/flags/ar.png b/assets/flags/ar.png new file mode 100644 index 000000000..a5bb1c4e2 Binary files /dev/null and b/assets/flags/ar.png differ diff --git a/assets/images/6-parts-in-test.jpg b/assets/images/6-parts-in-test.jpg index 46ce51992..4a7065c53 100644 Binary files a/assets/images/6-parts-in-test.jpg and b/assets/images/6-parts-in-test.jpg differ diff --git a/assets/images/Privatenpm.png b/assets/images/Privatenpm.png index ce3fe3e68..d14466f78 100644 Binary files a/assets/images/Privatenpm.png and b/assets/images/Privatenpm.png differ diff --git a/assets/images/Sketch (8).png b/assets/images/Sketch (8).png index 47c1662b8..4b8860bb6 100644 Binary files a/assets/images/Sketch (8).png and b/assets/images/Sketch (8).png differ diff --git a/assets/images/The backend testing checklist.png b/assets/images/The backend testing checklist.png new file mode 100644 index 000000000..0b867d9cf Binary files /dev/null and b/assets/images/The backend testing checklist.png differ diff --git a/assets/images/anchore-report.png b/assets/images/anchore-report.png index d733c438e..5dccb932d 100644 Binary files a/assets/images/anchore-report.png and b/assets/images/anchore-report.png differ diff --git a/assets/images/apm1.png b/assets/images/apm1.png index 30dfea2db..1ec43cae4 100644 Binary files a/assets/images/apm1.png and b/assets/images/apm1.png differ diff --git a/assets/images/apm3.png b/assets/images/apm3.png index a6894ea31..835ebc0db 100644 Binary files a/assets/images/apm3.png and b/assets/images/apm3.png differ diff --git a/assets/images/app-dynamics-dashboard.png b/assets/images/app-dynamics-dashboard.png index e9f600c27..622a24e62 100644 Binary files a/assets/images/app-dynamics-dashboard.png and b/assets/images/app-dynamics-dashboard.png differ diff --git a/assets/images/banner-1.png b/assets/images/banner-1.png index e288c0720..8c531375f 100644 Binary files a/assets/images/banner-1.png and b/assets/images/banner-1.png differ diff --git a/assets/images/banner-2.jpg b/assets/images/banner-2.jpg index 41df36ded..5d18c73b3 100644 Binary files a/assets/images/banner-2.jpg and b/assets/images/banner-2.jpg differ diff --git a/assets/images/banner-3.jpg b/assets/images/banner-3.jpg index 18c69f9be..ded0ded3c 100644 Binary files a/assets/images/banner-3.jpg and b/assets/images/banner-3.jpg differ diff --git a/assets/images/banner-4.jpg b/assets/images/banner-4.jpg index 86b93d8a2..2379a7e08 100644 Binary files a/assets/images/banner-4.jpg and b/assets/images/banner-4.jpg differ diff --git a/assets/images/circleci.png b/assets/images/circleci.png index 949414556..3667d5b5b 100644 Binary files a/assets/images/circleci.png and b/assets/images/circleci.png differ diff --git a/assets/images/concat-benchmark.png b/assets/images/concat-benchmark.png index 62412363b..425318bcc 100644 Binary files a/assets/images/concat-benchmark.png and b/assets/images/concat-benchmark.png differ diff --git a/assets/images/createmaintenanceendpoint1.png b/assets/images/createmaintenanceendpoint1.png index a155bf246..b79509a25 100644 Binary files a/assets/images/createmaintenanceendpoint1.png and b/assets/images/createmaintenanceendpoint1.png differ diff --git a/assets/images/error-handling-flow.png b/assets/images/error-handling-flow.png index a1b3ca6b8..33ee988e7 100644 Binary files a/assets/images/error-handling-flow.png and b/assets/images/error-handling-flow.png differ diff --git a/assets/images/eslint-plugin-security.png b/assets/images/eslint-plugin-security.png index e43270f53..dd57f2ca7 100644 Binary files a/assets/images/eslint-plugin-security.png and b/assets/images/eslint-plugin-security.png differ diff --git a/assets/images/event-loop.png b/assets/images/event-loop.png index f806b6f86..3b0dd75c6 100644 Binary files a/assets/images/event-loop.png and b/assets/images/event-loop.png differ diff --git a/assets/images/jenkins_dashboard.png b/assets/images/jenkins_dashboard.png index 79409f75f..bbf0f9158 100644 Binary files a/assets/images/jenkins_dashboard.png and b/assets/images/jenkins_dashboard.png differ diff --git a/assets/images/keepexpressinweb.gif b/assets/images/keepexpressinweb.gif index 2e55d1761..d4d863ba0 100644 Binary files a/assets/images/keepexpressinweb.gif and b/assets/images/keepexpressinweb.gif differ diff --git a/assets/images/kibana-graph-1024x550.jpg b/assets/images/kibana-graph-1024x550.jpg index ebfb22366..d93da6505 100644 Binary files a/assets/images/kibana-graph-1024x550.jpg and b/assets/images/kibana-graph-1024x550.jpg differ diff --git a/assets/images/kibana-raw-1024x637.png b/assets/images/kibana-raw-1024x637.png index 36ea84802..a127cc8db 100644 Binary files a/assets/images/kibana-raw-1024x637.png and b/assets/images/kibana-raw-1024x637.png differ diff --git a/assets/images/linkedin.svg b/assets/images/linkedin.svg new file mode 100644 index 000000000..949c44529 --- /dev/null +++ b/assets/images/linkedin.svg @@ -0,0 +1 @@ +> \ No newline at end of file diff --git a/assets/images/logging-overview.png b/assets/images/logging-overview.png index 96ffe500b..8897c825e 100644 Binary files a/assets/images/logging-overview.png and b/assets/images/logging-overview.png differ diff --git a/assets/images/logs-with-transaction-id.jpg b/assets/images/logs-with-transaction-id.jpg index 8e9ec3d10..83a1e12b3 100644 Binary files a/assets/images/logs-with-transaction-id.jpg and b/assets/images/logs-with-transaction-id.jpg differ diff --git a/assets/images/logs-withtout-transaction-id.jpg b/assets/images/logs-withtout-transaction-id.jpg index 94bec6c77..09bf71ab9 100644 Binary files a/assets/images/logs-withtout-transaction-id.jpg and b/assets/images/logs-withtout-transaction-id.jpg differ diff --git a/assets/images/members/bruno.png b/assets/images/members/bruno.png index 045a905e8..cc0519f3e 100644 Binary files a/assets/images/members/bruno.png and b/assets/images/members/bruno.png differ diff --git a/assets/images/members/create-member-icon.md b/assets/images/members/create-member-icon.md new file mode 100644 index 000000000..b20cf1198 --- /dev/null +++ b/assets/images/members/create-member-icon.md @@ -0,0 +1,44 @@ +## How to create a new color coded icon image + +To create a new image for yourself in either the collaborators or committee +sections follow the directions and template below. + +1. Replace `[USERNAME]` in the template with your username. +2. Replace `[BORDER_COLOR]` according to this: + - Committee: `#33cd32` + - Collaborators: `#0efeff` +3. Paste the text into a text file with `.svg` extension. +4. Open in an image editor of your choice that supports SVG and then export as + PNG (Enable transparency if it's optional) + +
+ +```svg + + + + + + + + +``` + +#### Tested Image Editors + +- [Inkscape](https://inkscape.org/) +- [GIMP](https://www.gimp.org/) diff --git a/assets/images/members/ido.png b/assets/images/members/ido.png index 5cb6c4687..627a514ef 100644 Binary files a/assets/images/members/ido.png and b/assets/images/members/ido.png differ diff --git a/assets/images/members/josh-hemphill.png b/assets/images/members/josh-hemphill.png new file mode 100644 index 000000000..021048234 Binary files /dev/null and b/assets/images/members/josh-hemphill.png differ diff --git a/assets/images/members/keith.png b/assets/images/members/keith.png index fcf4c32bc..839670b08 100644 Binary files a/assets/images/members/keith.png and b/assets/images/members/keith.png differ diff --git a/assets/images/members/kevyn.png b/assets/images/members/kevyn.png index a99f56e15..8f49da4e6 100644 Binary files a/assets/images/members/kevyn.png and b/assets/images/members/kevyn.png differ diff --git a/assets/images/members/kyle.png b/assets/images/members/kyle.png index 805956f23..055894550 100644 Binary files a/assets/images/members/kyle.png and b/assets/images/members/kyle.png differ diff --git a/assets/images/members/raz-luvaton.jpg b/assets/images/members/raz-luvaton.jpg new file mode 100644 index 000000000..33a5070b5 Binary files /dev/null and b/assets/images/members/raz-luvaton.jpg differ diff --git a/assets/images/members/refael.png b/assets/images/members/refael.png index fe57d04a2..937c1f6b1 100644 Binary files a/assets/images/members/refael.png and b/assets/images/members/refael.png differ diff --git a/assets/images/members/sagir.png b/assets/images/members/sagir.png index 7fe4732aa..608cb0995 100644 Binary files a/assets/images/members/sagir.png and b/assets/images/members/sagir.png differ diff --git a/assets/images/members/yoni.png b/assets/images/members/yoni.png index 34c4680ad..e1b53d143 100644 Binary files a/assets/images/members/yoni.png and b/assets/images/members/yoni.png differ diff --git a/assets/images/monitoring1.png b/assets/images/monitoring1.png index ddf126270..61d0c7331 100644 Binary files a/assets/images/monitoring1.png and b/assets/images/monitoring1.png differ diff --git a/assets/images/monitoring2.jpg b/assets/images/monitoring2.jpg index ed53a8a06..85e96c7e5 100644 Binary files a/assets/images/monitoring2.jpg and b/assets/images/monitoring2.jpg differ diff --git a/assets/images/monitoring3.png b/assets/images/monitoring3.png index 27253a0ae..7f86541aa 100644 Binary files a/assets/images/monitoring3.png and b/assets/images/monitoring3.png differ diff --git a/assets/images/npm-audit.png b/assets/images/npm-audit.png index 37a5ec072..75f729d2f 100644 Binary files a/assets/images/npm-audit.png and b/assets/images/npm-audit.png differ diff --git a/assets/images/sampleMeanDiag.png b/assets/images/sampleMeanDiag.png index ecf4a9fa4..2d10444c3 100644 Binary files a/assets/images/sampleMeanDiag.png and b/assets/images/sampleMeanDiag.png differ diff --git a/assets/images/setnodeenv1.png b/assets/images/setnodeenv1.png index 185800627..53701125d 100644 Binary files a/assets/images/setnodeenv1.png and b/assets/images/setnodeenv1.png differ diff --git a/assets/images/smartlogging1.png b/assets/images/smartlogging1.png index 36ea84802..c49a7db73 100644 Binary files a/assets/images/smartlogging1.png and b/assets/images/smartlogging1.png differ diff --git a/assets/images/smartlogging2.jpg b/assets/images/smartlogging2.jpg index ebfb22366..d93da6505 100644 Binary files a/assets/images/smartlogging2.jpg and b/assets/images/smartlogging2.jpg differ diff --git a/assets/images/swaggerDoc.png b/assets/images/swaggerDoc.png index 17eae6b44..9d05a9ce0 100644 Binary files a/assets/images/swaggerDoc.png and b/assets/images/swaggerDoc.png differ diff --git a/assets/images/swaggerMarkup.png b/assets/images/swaggerMarkup.png index ddc935017..26944fdba 100644 Binary files a/assets/images/swaggerMarkup.png and b/assets/images/swaggerMarkup.png differ diff --git a/assets/images/test-report-like-requirements.jpeg b/assets/images/test-report-like-requirements.jpeg index 58eb26d3d..d8691bf92 100644 Binary files a/assets/images/test-report-like-requirements.jpeg and b/assets/images/test-report-like-requirements.jpeg differ diff --git a/assets/images/testingpyramid.png b/assets/images/testingpyramid.png index 9243b7d4d..259da5682 100644 Binary files a/assets/images/testingpyramid.png and b/assets/images/testingpyramid.png differ diff --git a/assets/images/twitter.svg b/assets/images/twitter.svg new file mode 100644 index 000000000..8cac4f029 --- /dev/null +++ b/assets/images/twitter.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/uptimerobot.jpg b/assets/images/uptimerobot.jpg index bfde3fa68..ee45d3d4d 100644 Binary files a/assets/images/uptimerobot.jpg and b/assets/images/uptimerobot.jpg differ diff --git a/assets/images/web.svg b/assets/images/web.svg new file mode 100644 index 000000000..7c3b5254f --- /dev/null +++ b/assets/images/web.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/www.png b/assets/images/www.png index 2934df0d7..ef0b291c3 100644 Binary files a/assets/images/www.png and b/assets/images/www.png differ diff --git a/assets/images/ydnlu.png b/assets/images/ydnlu.png index 871a391be..0882c32ba 100644 Binary files a/assets/images/ydnlu.png and b/assets/images/ydnlu.png differ diff --git a/.operations/package.json b/package.json similarity index 54% rename from .operations/package.json rename to package.json index f4629e887..66bf9d9a0 100644 --- a/.operations/package.json +++ b/package.json @@ -4,9 +4,7 @@ "description": "[✔]: assets/images/checkbox-small-blue.png", "main": "gen-html.js", "scripts": { - "build": "cd .. && node .operations/gen-html.js", - "test": "echo \"Error: no test specified\" && exit 1", - "lint": "./node_modules/.bin/markdownlint ../README.md" + "lint": "markdownlint ./README*.md" }, "repository": { "type": "git", @@ -19,13 +17,6 @@ }, "homepage": "https://github.com/goldbergyoni/nodebestpractices#readme", "dependencies": { - "cheerio": "^1.0.0-rc.2", - "github-api": "^3.0.0", - "graceful-fs": "^4.1.15", - "imagemin": "^6.0.0", - "imagemin-jpegtran": "^6.0.0", - "imagemin-pngquant": "^6.0.0", - "markdownlint-cli": "^0.18.0", - "showdown": "^1.9.0" + "markdownlint-cli": "^0.18.0" } } diff --git a/sections/codestylepractices/eslint_prettier.basque.md b/sections/codestylepractices/eslint_prettier.basque.md index 384ecf1d1..94b810259 100644 --- a/sections/codestylepractices/eslint_prettier.basque.md +++ b/sections/codestylepractices/eslint_prettier.basque.md @@ -2,7 +2,7 @@ ### ESLint eta Prettier alderatzen -Kode hau formateatzen baduzu ESLint erabiliz, abisu bat besterik ez dizu emango luzeegia dela esanez (zure `max-len` ezarpenaren arabera). Prettierrek zure order automatikoki formateatuko du. +Kode hau formateatzen baduzu ESLint erabiliz, abisu bat besterik ez dizu emango luzeegia dela esanez (zure `max-len` ezarpenaren arabera). Prettierrek zure order automatikoki formateatuko du ```javascript @@ -29,4 +29,4 @@ Iturria: [https://github.com/prettier/prettier-eslint/issues/101](https://github ### ESLint eta Prettier integratzen -ESLint eta Prettier kodearen formateatze funtzionalitateetan gainjar daitezke, baina erraz konbina daitezke [prettier-eslint](https://github.com/prettier/prettier-eslint), [eslint-plugin-prettier](https://github.com/prettier/eslint-plugin-prettier), eta [eslint-config-prettier](https://github.com/prettier/eslint-config-prettier) bezalako liburutegiekin. Haien arteko ezberdintasunei buruzko informazio gehiago nahi izanez gero, [hemen](https://stackoverflow.com/questions/44690308/whats-the-difference-between-prettier-eslint-eslint-plugin-prettier-and-eslint) begira dezakezu esteka +ESLint eta Prettier kodea formateatzeko funtzionalitateetan gainjar daitezke, baina erraz konbina daitezke [prettier-eslint](https://github.com/prettier/prettier-eslint), [eslint-plugin-prettier](https://github.com/prettier/eslint-plugin-prettier), eta [eslint-config-prettier](https://github.com/prettier/eslint-config-prettier) bezalako liburutegiekin. Haien arteko ezberdintasunei buruzko informazio gehiago nahi izanez gero, [hemen](https://stackoverflow.com/questions/44690308/whats-the-difference-between-prettier-eslint-eslint-plugin-prettier-and-eslint) begira dezakezu esteka. diff --git a/sections/codestylepractices/eslint_prettier.french.md b/sections/codestylepractices/eslint_prettier.french.md new file mode 100644 index 000000000..f629cc879 --- /dev/null +++ b/sections/codestylepractices/eslint_prettier.french.md @@ -0,0 +1,26 @@ +# Utilisez ESLint et Prettier + + +### Comparaison d'ESLint et de Prettier + +Si vous formatez ce code à l'aide d'ESLint, il vous avertira simplement qu'il est trop large (dépend de votre paramètre `max-len`). Prettier le formatera automatiquement pour vous. + +```javascript +foo(reallyLongArg(), omgSoManyParameters(), IShouldRefactorThis(), isThereSeriouslyAnotherOne(), noWayYouGottaBeKiddingMe()); +``` + +```javascript +foo( + reallyLongArg(), + omgSoManyParameters(), + IShouldRefactorThis(), + isThereSeriouslyAnotherOne(), + noWayYouGottaBeKiddingMe() +); +``` + +Source : [https://github.com/prettier/prettier-eslint/issues/101](https://github.com/prettier/prettier-eslint/issues/101) + +### Intégration d'ESLint et de Prettier + +ESLint et Prettier se recoupent dans la fonction de formatage du code mais ils peuvent être facilement combinés en utilisant d'autres packages comme [prettier-eslint](https://github.com/prettier/prettier-eslint), [eslint-plugin-prettier](https://github.com/prettier/eslint-plugin-prettier) et [eslint-config-prettier](https://github.com/prettier/eslint-config-prettier). Pour plus d'informations sur leurs différences, vous pouvez consulter le lien [ici](https://stackoverflow.com/questions/44690308/whats-the-difference-between-prettier-eslint-eslint-plugin-prettier-and-eslint). diff --git a/sections/docker/avoid-build-time-secrets.basque.md b/sections/docker/avoid-build-time-secrets.basque.md new file mode 100644 index 000000000..6b9e2fb35 --- /dev/null +++ b/sections/docker/avoid-build-time-secrets.basque.md @@ -0,0 +1,98 @@ +# Garbitu eraikitze faseko sekretuak, saihestu sekretuak argudioetan + +

+ +### Azalpena + +Docker irudi bat ez da soilik fitxategi pilo bat, eraikitze garaian gertatutakoa kontatzen duten geruza anitz baizik. Oso ohikoa izaten da garatzaileek npm giltza (tokena) behar izatea eraikitze garaian (gehienetan erregistro pribatuetarako), eta horretarako sasibide bat erabiltzen dute giltza eraikitze garaiko argudio bezala pasatuz. Sinplea eta segurua eman dezake, baina giltza hori garatzailearen ordenagailuko Docker historiatik, Docker erregistrotik eta IEtik eskura daiteke. Giltza eskuratzea lortzen duen erasotzailea gai izango da erakunde horren npm erregistro pribatuan idazteko. Bi aukera daude, hori baino seguruagoak direnak: bikainena, Docker --secret funtzioalitatea erabiltzea (2020ko uztailetik aurrera esperimentala), fitxategi bat antolatzea ahalbidetzen duena eraikitze garaian. Bigarrenak, lehenengo, etapa anitzeko konpilazioa argudioekin erabiltzen du; gero, konpilazioa egiten du; eta, azkenik, bakarrik beharrezkoak diren fitxategiak kopiatzen ditu ekoizpenean. Azken teknika horrek ez du sekreturik igortzen irudiekin, baina sekretuak Dockeren historian agertuko dira. Normalean, erakunde gehienenek nahikoa segurutzat jotzen dute. + +

+ +### Kode adibidea: erabili Docker sekretu instalatuentzat (esperimentala, baina egonkorra) + +
+ +Dockerfile + +```dockerfile +# syntax = docker/dockerfile:1.0-experimental + +FROM node:12-slim + +WORKDIR /usr/src/app +COPY package.json package-lock.json ./ +RUN --mount=type=secret,id=npm,target=/root/.npmrc npm ci + +# Gainerakoa hemen dator +``` + +
+ +

+ +### Kode adibidea: modu seguruan eraiki etapa anitzeko konpilazioa erabiliz + +
+ +Dockerfile + +```dockerfile +FROM node:12-slim AS build + +ARG NPM_TOKEN + +WORKDIR /usr/src/app +COPY . /dist +RUN echo "//registry.npmjs.org/:\_authToken=\$NPM_TOKEN" > .npmrc && \ + npm ci --production && \ + rm -f .npmrc + + +FROM build as prod + +COPY --from=build /dist /dist + +CMD ["node", "index.js"] + +# ARG eta .npmrc ez dira agertuko azken irudian baina Docker daemonen etiketatu gabeko irudien zerrendan ager daitezke, ziurtatu hauek ezabatu dituzula +``` + +
+ +

+ +### Anti ereduaren kode adibidea: erabili eraikitze garaiko argudioak + +
+ +Dockerfile + +```dockerfile +FROM node:12-slim + +ARG NPM_TOKEN + +WORKDIR /usr/src/app +COPY . /dist +RUN echo "//registry.npmjs.org/:\_authToken=\$NPM_TOKEN" > .npmrc && \ + npm ci --production && \ + rm -f .npmrc + +# .npmrc copy komando berean ezabatzeari esker ez du geruzan gordeko, hala ere, irudi historian aurki ahalko dugu + +CMD ["node", "index.js"] +``` + +
+ +

+ +### Blogeko aipua: "Sekretu hauek ez dira azken Dockerean gordetzen" + +[Alexandra Ulsh](https://www.alexandraulsh.com/2019/02/24/docker-build-secrets-and-npmrc/?fbclid=IwAR0EAr1nr4_QiGzlNQcQKkd9rem19an9atJRO_8-n7oOZXwprToFQ53Y0KQ)en bloga + +> 2018ko azaroan, Docker 18.09k sekretu bandera berria gehitu zuen docker eraikuntzarentzat. Horrek aukera ematen digu gure fitxategi baten sekretuak Docker eraikuntzara pasatzeko. Sekretu horiek ez dira ez Dokeren azken irudian gordetzen, ez tarteko irudietan, ez irudiaren balioztatze historian. Eraikitze sekretuei esker, npm pakete pribatudun Docker irudiak eraiki ditzakezu, eraikitze argudiorik gabe eta etapa anitzekin. + +``` + +``` diff --git a/sections/docker/avoid-build-time-secrets.chinese.md b/sections/docker/avoid-build-time-secrets.chinese.md index 9f97e138a..8b578a7b2 100644 --- a/sections/docker/avoid-build-time-secrets.chinese.md +++ b/sections/docker/avoid-build-time-secrets.chinese.md @@ -14,10 +14,11 @@ Docker映像不仅仅是一堆文件,而是展示构建期间所发生的层 Dockerfile -``` +```dockerfile # syntax = docker/dockerfile:1.0-experimental FROM node:12-slim + WORKDIR /usr/src/app COPY package.json package-lock.json ./ RUN --mount=type=secret,id=npm,target=/root/.npmrc npm ci @@ -35,19 +36,22 @@ RUN --mount=type=secret,id=npm,target=/root/.npmrc npm ci Dockerfile -``` - +```dockerfile FROM node:12-slim AS build + ARG NPM_TOKEN + WORKDIR /usr/src/app COPY . /dist RUN echo "//registry.npmjs.org/:\_authToken=\$NPM_TOKEN" > .npmrc && \ npm ci --production && \ rm -f .npmrc + FROM build as prod + COPY --from=build /dist /dist -CMD ["node","index.js"] +CMD ["node", "index.js"] # ARG和.npmrc在最终的镜像中不会出现,但会在Docker daemon的未打标签(un-tagged)镜像列表中找到它们 - 确保删除他们 ``` @@ -62,10 +66,11 @@ CMD ["node","index.js"] Dockerfile -``` - +```dockerfile FROM node:12-slim + ARG NPM_TOKEN + WORKDIR /usr/src/app COPY . /dist RUN echo "//registry.npmjs.org/:\_authToken=\$NPM_TOKEN" > .npmrc && \ @@ -74,7 +79,7 @@ RUN echo "//registry.npmjs.org/:\_authToken=\$NPM_TOKEN" > .npmrc && \ # 在拷贝命令的同时删除.npmrc文件不会在layer里面保存它, 但在镜像历史里面还是会找到它 -CMD ["node","index.js"] +CMD ["node", "index.js"] ``` diff --git a/sections/docker/avoid-build-time-secrets.french.md b/sections/docker/avoid-build-time-secrets.french.md new file mode 100644 index 000000000..ad5a95508 --- /dev/null +++ b/sections/docker/avoid-build-time-secrets.french.md @@ -0,0 +1,100 @@ +# Clean build-time secrets, avoid secrets as args + +

+ +### One Paragraph Explainer + + +A Docker image isn't just a bunch of files but rather multiple layers revealing what happened during build-time. In a very common scenario, developers need the npm token during build time (mostly for private registries) - this is falsely achieved by passing the token as a build time args. It might seem innocent and safe, however this token can now be fetched from the developer's machine Docker history, from the Docker registry and the CI. An attacker who gets access to that token is now capable of writing into the organization private npm registry. There are two more secured alternatives: The flawless one is using Docker --secret feature (experimental as of July 2020) which allows mounting a file during build time only. The second approach is using multi-stage build with args, building and then copying only the necessary files to production. The last technique will not ship the secrets with the images but will appear in the local Docker history - This is typically considered as secured enough for most organizations. + +

+ +### Code Example – Using Docker mounted secrets (experimental but stable) + +
+ +Dockerfile + +```dockerfile +# syntax = docker/dockerfile:1.0-experimental + +FROM node:12-slim + +WORKDIR /usr/src/app +COPY package.json package-lock.json ./ +RUN --mount=type=secret,id=npm,target=/root/.npmrc npm ci + +# The rest comes here +``` + +
+ +

+ +### Code Example – Building securely using multi-stage build + +
+ +Dockerfile + +```dockerfile +FROM node:12-slim AS build + +ARG NPM_TOKEN + +WORKDIR /usr/src/app +COPY . /dist + +RUN echo "//registry.npmjs.org/:\_authToken=\$NPM_TOKEN" > .npmrc && \ + npm ci --production && \ + rm -f .npmrc + + +FROM build as prod + +COPY --from=build /dist /dist +CMD ["node", "index.js"] + +# The ARG and .npmrc won't appear in the final image but can be found in the Docker daemon un-tagged images list - make sure to delete those +``` + +
+ +

+ +### Code Example Anti Pattern – Using build time args + +
+ +Dockerfile + +```dockerfile +FROM node:12-slim + +ARG NPM_TOKEN + +WORKDIR /usr/src/app +COPY . /dist + +RUN echo "//registry.npmjs.org/:\_authToken=\$NPM_TOKEN" > .npmrc && \ + npm ci --production && \ + rm -f .npmrc + +# Deleting the .npmrc within the same copy command will not save it inside the layer, however it can be found in image history + +CMD ["node", "index.js"] +``` + +
+ +

+ +### Blog Quote: "These secrets aren’t saved in the final Docker" + +From the blog, [Alexandra Ulsh](https://www.alexandraulsh.com/2019/02/24/docker-build-secrets-and-npmrc/?fbclid=IwAR0EAr1nr4_QiGzlNQcQKkd9rem19an9atJRO_8-n7oOZXwprToFQ53Y0KQ) + +> In November 2018 Docker 18.09 introduced a new --secret flag for docker build. This allows us to pass secrets from a file to our Docker builds. These secrets aren’t saved in the final Docker image, any intermediate images, or the image commit history. With build secrets, you can now securely build Docker images with private npm packages without build arguments and multi-stage builds. + +``` + +``` \ No newline at end of file diff --git a/sections/docker/avoid-build-time-secrets.japanese.md b/sections/docker/avoid-build-time-secrets.japanese.md index d0b873d22..339e6b36e 100644 --- a/sections/docker/avoid-build-time-secrets.japanese.md +++ b/sections/docker/avoid-build-time-secrets.japanese.md @@ -15,10 +15,11 @@ Docker イメージは単なるファイルの束ではなく、ビルド時に Dockerfile -``` +```dockerfile # syntax = docker/dockerfile:1.0-experimental FROM node:12-slim + WORKDIR /usr/src/app COPY package.json package-lock.json ./ RUN --mount=type=secret,id=npm,target=/root/.npmrc npm ci @@ -36,19 +37,23 @@ RUN --mount=type=secret,id=npm,target=/root/.npmrc npm ci Dockerfile -``` - +```dockerfile FROM node:12-slim AS build + ARG NPM_TOKEN + WORKDIR /usr/src/app COPY . /dist + RUN echo "//registry.npmjs.org/:\_authToken=\$NPM_TOKEN" > .npmrc && \ npm ci --production && \ rm -f .npmrc + FROM build as prod + COPY --from=build /dist /dist -CMD ["node","index.js"] +CMD ["node", "index.js"] # ARG と .npmrc は最終的なイメージには現れませんが、Docker デーモンの un-tagged イメージリストから見つけることができます - これらを忘れずに削除してください ``` @@ -63,10 +68,11 @@ CMD ["node","index.js"] Dockerfile -``` - +```dockerfile FROM node:12-slim + ARG NPM_TOKEN + WORKDIR /usr/src/app COPY . /dist RUN echo "//registry.npmjs.org/:\_authToken=\$NPM_TOKEN" > .npmrc && \ @@ -75,7 +81,7 @@ RUN echo "//registry.npmjs.org/:\_authToken=\$NPM_TOKEN" > .npmrc && \ # .npmrc を同じ copy コマンド内で削除するとレイヤー内には保存されませんが、イメージ履歴から見つけることができます -CMD ["node","index.js"] +CMD ["node", "index.js"] ``` diff --git a/sections/docker/avoid-build-time-secrets.md b/sections/docker/avoid-build-time-secrets.md index 2d33ee088..e729f7919 100644 --- a/sections/docker/avoid-build-time-secrets.md +++ b/sections/docker/avoid-build-time-secrets.md @@ -15,10 +15,11 @@ A Docker image isn't just a bunch of files but rather multiple layers revealing Dockerfile -``` +```dockerfile # syntax = docker/dockerfile:1.0-experimental FROM node:12-slim + WORKDIR /usr/src/app COPY package.json package-lock.json ./ RUN --mount=type=secret,id=npm,target=/root/.npmrc npm ci @@ -36,19 +37,23 @@ RUN --mount=type=secret,id=npm,target=/root/.npmrc npm ci Dockerfile -``` - +```dockerfile FROM node:12-slim AS build + ARG NPM_TOKEN + WORKDIR /usr/src/app COPY . /dist + RUN echo "//registry.npmjs.org/:\_authToken=\$NPM_TOKEN" > .npmrc && \ npm ci --production && \ rm -f .npmrc + FROM build as prod + COPY --from=build /dist /dist -CMD ["node","index.js"] +CMD ["node", "index.js"] # The ARG and .npmrc won't appear in the final image but can be found in the Docker daemon un-tagged images list - make sure to delete those ``` @@ -63,19 +68,21 @@ CMD ["node","index.js"] Dockerfile -``` - +```dockerfile FROM node:12-slim + ARG NPM_TOKEN + WORKDIR /usr/src/app COPY . /dist + RUN echo "//registry.npmjs.org/:\_authToken=\$NPM_TOKEN" > .npmrc && \ npm ci --production && \ rm -f .npmrc # Deleting the .npmrc within the same copy command will not save it inside the layer, however it can be found in image history -CMD ["node","index.js"] +CMD ["node", "index.js"] ``` diff --git a/sections/docker/bootstrap-using-node.basque.md b/sections/docker/bootstrap-using-node.basque.md new file mode 100644 index 000000000..0a001735e --- /dev/null +++ b/sections/docker/bootstrap-using-node.basque.md @@ -0,0 +1,81 @@ +# Abiarazi edukiontzia node komandoa erabiliz npm erabili ordez + +## Azalpena + +Ohikoa da jendeak `CMD 'npm start'` erabiltzea bere aplikazioa abiarazteko kodea egitea. Praktika txarra da hori, ordea. `npm` bitarrak ez du seinalerik birbidaliko zure aplikaziora, aplikazioa behar bezala ixtea eragozten duena (ikus [/sections/docker/graceful-shutdown.basque.md]). Bigarren mailako prozesuak erabiltzen badituzu, ez dira behar bezala garbituko ustekabeko itzaltzeren bat gertatzen bada, prozesu zonbiak utziko dituena. `npm start`ek ere onuragarria ez den prozesu bat gehiago egiten du. Erabili `CMD ['node','server.js']` zure aplikazioa abiarazteko. Zure aplikazioak bigarren mailako prozesuak baditu, erabili gainera `TINI`sarbide gisa. + +### Kode adibidea: abiarazi aplikazioa Node erabiliz + +```dockerfile +FROM node:12-slim AS build + +WORKDIR /usr/src/app +COPY package.json package-lock.json ./ +RUN npm ci --production && npm clean cache --force + +CMD ["node", "server.js"] +``` + +### Kode adibidea: erabili Tiny sarbide gisa + +```dockerfile +FROM node:12-slim AS build + +# Gehitu Tini bigarren mailako prozesuak erabiltzen badituzu +ENV TINI_VERSION v0.19.0 +ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /tini +RUN chmod +x /tini + +WORKDIR /usr/src/app +COPY package.json package-lock.json ./ +RUN npm ci --production && npm clean cache --force + +ENTRYPOINT ["/tini", "--"] + +CMD ["node", "server.js"] +``` + +### Anti ereduak + +npm start erabiliz + +```dockerfile +FROM node:12-slim AS build + +WORKDIR /usr/src/app +COPY package.json package-lock.json ./ +RUN npm ci --production && npm clean cache --force + +# ez egin hau! +CMD "npm start" +``` +Node string bakarrean erabiltzeak zure komandoa egikaritzeko bash/ash shell prozesu bat abiaraziko du. Hori ia `npm` erabiltzea modukoa da + +```dockerfile +FROM node:12-slim AS build + +WORKDIR /usr/src/app +COPY package.json package-lock.json ./ +RUN npm ci --production && npm clean cache --force + +# ez egin hau, bash abiatuko du eta +CMD "node server.js" +``` + +npmrekin abiatuz, hau da prozesuaren zuhaitza: + +```console +$ ps falx + UID PID PPID COMMAND + 0 1 0 npm + 0 16 1 sh -c node server.js + 0 17 16 \_ node server.js +``` + +Bi prozesu estra hauek edukitzeak ez du inongo abantailarik ekartzen + +Iturriak: + +https://maximorlov.com/process-signals-inside-docker-containers/ + +https://github.com/nodejs/docker-node/blob/master/docs/BestPractices.md#handling-kernel-signals diff --git a/sections/docker/bootstrap-using-node.chinese.md b/sections/docker/bootstrap-using-node.chinese.md index 48df2340f..29f3d184a 100644 --- a/sections/docker/bootstrap-using-node.chinese.md +++ b/sections/docker/bootstrap-using-node.chinese.md @@ -7,10 +7,8 @@ ### 代码示例 - 启动Node ```dockerfile - FROM node:12-slim AS build - WORKDIR /usr/src/app COPY package.json package-lock.json ./ RUN npm ci --production && npm clean cache --force @@ -22,7 +20,6 @@ CMD ["node", "server.js"] ### 代码示例 - 使用Tiny作为入口(ENTRYPOINT) ```dockerfile - FROM node:12-slim AS build # 使用子进程(child-processes)的情况下,添加Tini @@ -43,8 +40,8 @@ CMD ["node", "server.js"] 使用npm start ```dockerfile - FROM node:12-slim AS build + WORKDIR /usr/src/app COPY package.json package-lock.json ./ RUN npm ci --production && npm clean cache --force @@ -56,8 +53,8 @@ CMD "npm start" 在同一字符串命令里面使用node,将启动一个bash/ash脚本进程去执行您的命令。它和使用`npm`的效果类似。 ```dockerfile - FROM node:12-slim AS build + WORKDIR /usr/src/app COPY package.json package-lock.json ./ RUN npm ci --production && npm clean cache --force @@ -67,7 +64,7 @@ CMD "node server.js" ``` 使用npm启动,这里是进程树: -``` +```console $ ps falx UID PID PPID COMMAND 0 1 0 npm diff --git a/sections/docker/bootstrap-using-node.french.md b/sections/docker/bootstrap-using-node.french.md new file mode 100644 index 000000000..e3f5388c8 --- /dev/null +++ b/sections/docker/bootstrap-using-node.french.md @@ -0,0 +1,82 @@ +# Bootstrap container using node command instead of npm + +## One paragraph explainer + +We are used to see code examples where folks start their app using `CMD 'npm start'`. This is a bad practice. The `npm` binary will not forward signals to your app which prevents graceful shutdown (see [/sections/docker/graceful-shutdown.md]). If you are using child-processes they won’t be cleaned up correctly in case of unexpected shutdown, leaving zombie processes on your host. `npm start` also results in having an extra process for no benefit. To start you app use `CMD ['node','server.js']`. If your app spawns child-processes also use `TINI` as an entrypoint. + +### Code example - Bootsraping using Node + +```dockerfile +FROM node:12-slim AS build + +WORKDIR /usr/src/app +COPY package.json package-lock.json ./ +RUN npm ci --production && npm clean cache --force + +CMD ["node", "server.js"] +``` + + +### Code example - Using Tiny as entrypoint + +```dockerfile +FROM node:12-slim AS build + +# Add Tini if using child-processes +ENV TINI_VERSION v0.19.0 +ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /tini +RUN chmod +x /tini + +WORKDIR /usr/src/app +COPY package.json package-lock.json ./ +RUN npm ci --production && npm clean cache --force + +ENTRYPOINT ["/tini", "--"] + +CMD ["node", "server.js"] +``` + +### Antipatterns + +Using npm start +```dockerfile +FROM node:12-slim AS build + +WORKDIR /usr/src/app +COPY package.json package-lock.json ./ +RUN npm ci --production && npm cache clean --force + +# don’t do that! +CMD "npm start" +``` + +Using node in a single string will start a bash/ash shell process to execute your command. That is almost the same as using `npm` + +```dockerfile +FROM node:12-slim AS build + +WORKDIR /usr/src/app +COPY package.json package-lock.json ./ +RUN npm ci --production && npm clean cache --force + +# don’t do that, it will start bash +CMD "node server.js" +``` + +Starting with npm, here’s the process tree: +```console +$ ps falx + UID PID PPID COMMAND + 0 1 0 npm + 0 16 1 sh -c node server.js + 0 17 16 \_ node server.js +``` +There is no advantage to those two extra processes. + +Sources: + + +https://maximorlov.com/process-signals-inside-docker-containers/ + + +https://github.com/nodejs/docker-node/blob/master/docs/BestPractices.md#handling-kernel-signals \ No newline at end of file diff --git a/sections/docker/bootstrap-using-node.japanese.md b/sections/docker/bootstrap-using-node.japanese.md index 606b5ca5f..e24d9d1f8 100644 --- a/sections/docker/bootstrap-using-node.japanese.md +++ b/sections/docker/bootstrap-using-node.japanese.md @@ -7,10 +7,8 @@ ### コード例 - node を使用した Bootsraping ```dockerfile - FROM node:12-slim AS build - WORKDIR /usr/src/app COPY package.json package-lock.json ./ RUN npm ci --production && npm clean cache --force @@ -22,7 +20,6 @@ CMD ["node", "server.js"] ### コード例 - エントリーポイントとしての Tiny の使用 ```dockerfile - FROM node:12-slim AS build # 子プロセスを使用している場合は、Tini を追加します。 @@ -43,8 +40,8 @@ CMD ["node", "server.js"] Using npm start ```dockerfile - FROM node:12-slim AS build + WORKDIR /usr/src/app COPY package.json package-lock.json ./ RUN npm ci --production && npm clean cache --force @@ -56,8 +53,8 @@ CMD "npm start" Using node in a single string will start a bash/ash shell process to execute your command. That is almost the same as using `npm` ```dockerfile - FROM node:12-slim AS build + WORKDIR /usr/src/app COPY package.json package-lock.json ./ RUN npm ci --production && npm clean cache --force @@ -67,7 +64,7 @@ CMD "node server.js" ``` npm でスタートすると、プロセスツリーは以下のようになります。: -``` +```console $ ps falx UID PID PPID COMMAND 0 1 0 npm diff --git a/sections/docker/bootstrap-using-node.md b/sections/docker/bootstrap-using-node.md index e61ff8e7f..7be2aa900 100644 --- a/sections/docker/bootstrap-using-node.md +++ b/sections/docker/bootstrap-using-node.md @@ -2,15 +2,13 @@ ## One paragraph explainer -We are used to see code examples where folks start their app using `CMD 'npm start'`. This is a bad practice. The `npm` binary will not forward signals to your app which prevents graceful shutdown (see [/sections/docker/graceful-shutdown.md]). If you are using child-processes they won’t be cleaned up correctly in case of unexpected shutdown, leaving zombie processes on your host. `npm start` also results in having an extra process for no benefit. To start you app use `CMD ['node','server.js']`. If your app spawns child-processes also use `TINI` as an entrypoint. +We are used to see code examples where folks start their app using `CMD 'npm start'`. This is a bad practice. The `npm` binary will not forward signals to your app which prevents graceful shutdown [see](/sections/docker/graceful-shutdown.md). If you are using child-processes they won’t be cleaned up correctly in case of unexpected shutdown, leaving zombie processes on your host. `npm start` also results in having an extra process for no benefit. To start you app use `CMD ['node','server.js']`. If your app spawns child-processes also use `TINI` as an entrypoint. -### Code example - Bootsraping using Node +### Code example - Bootstrapping using Node ```dockerfile - FROM node:12-slim AS build - WORKDIR /usr/src/app COPY package.json package-lock.json ./ RUN npm ci --production && npm clean cache --force @@ -22,7 +20,6 @@ CMD ["node", "server.js"] ### Code example - Using Tiny as entrypoint ```dockerfile - FROM node:12-slim AS build # Add Tini if using child-processes @@ -43,8 +40,8 @@ CMD ["node", "server.js"] Using npm start ```dockerfile - FROM node:12-slim AS build + WORKDIR /usr/src/app COPY package.json package-lock.json ./ RUN npm ci --production && npm cache clean --force @@ -56,8 +53,8 @@ CMD "npm start" Using node in a single string will start a bash/ash shell process to execute your command. That is almost the same as using `npm` ```dockerfile - FROM node:12-slim AS build + WORKDIR /usr/src/app COPY package.json package-lock.json ./ RUN npm ci --production && npm clean cache --force @@ -67,7 +64,7 @@ CMD "node server.js" ``` Starting with npm, here’s the process tree: -``` +```console $ ps falx UID PID PPID COMMAND 0 1 0 npm diff --git a/sections/docker/clean-cache.basque.md b/sections/docker/clean-cache.basque.md new file mode 100644 index 000000000..7b206e2a9 --- /dev/null +++ b/sections/docker/clean-cache.basque.md @@ -0,0 +1,28 @@ +# Garbitu NODE_MODULE cachea + +

+ +### Azalpena + +npm eta Yarn Node paketeen kudeatzaileek cachean gordetzen dituzte lokalean instalatutako paketeak, liburutegi horien beharra dituzten etorkizuneko proiektuek urruneko biltegi batetik eskuratu beharrik izan ez dezaten. Horrek paketeak bikoiztu eta biltegiratze gehiago kontsumitzen duen arren, normalean pakete berdinak instalatzen jarraitzen duen tokiko garapen ingurunean merezi egiten du hori egitea. Docker edukiontzian biltegiratzea handitzeak ez du ezertarako balio, menpekotasuna behin bakarrik instalatzen baitu. Cachea kenduta, MB asko ezabatzen dira iruditik kode lerro bakarra erabiliz. Hori egiten ari zaren bitartean, ziurtatu zero ez den kode batekin irteten ez dela eta IE eraikitzean huts egiten duela cachearen arazoengatik. Hori ekidin daiteke --force adierazlea erantsiz. + +_Mesedez, kontutan hartu hau ez dela garrantzitsua etapa anitzeko konpilazioa erabiltzen duzun kasuan, ez duzu-eta pakete berririk instalatzen azken etapan_ + +

+ +### Kode adibidea: cachea garbitu + +
+Dockerfile + +```dockerfile +FROM node:12-slim AS build + +WORKDIR /usr/src/app +COPY package.json package-lock.json ./ +RUN npm ci --production && npm cache clean --force + +# Gainontzeko guztia hemen dator +``` + +
diff --git a/sections/docker/clean-cache.chinese.md b/sections/docker/clean-cache.chinese.md new file mode 100644 index 000000000..5e2c09918 --- /dev/null +++ b/sections/docker/clean-cache.chinese.md @@ -0,0 +1,27 @@ +# 清除NODE_MODULE缓存 + +

+ +### 一段解释 + +node包管理器,npm和Yarn,会本地缓存安装过的包,以便在未来的项目中,如果需要同样的包,就不需要从远程仓库重新获取。尽管这会导致包的重复,消耗更多的存储 - 作为回报,它维持了一个安装相同包的本地开发环境。而在Docker容器中,这种存储是没什么价值的,因为它仅仅安装依赖一次。通过移除这类缓存,只需要使用一行代码,上十MB的存储会从image中移除。当这样做的时候,确保它不会通过非零(non-zero)码退出,因而由于缓存问题导致CI构建失败 - 这可以通过添加一个force标志位来避免。 + +*请注意如果您使用multi-stage构建,只要您在最后阶段不安装新的包,清除缓存是没意义的* + +

+ +### 代码示例 - 清除缓存 + +
+Dockerfile + +```dockerfile +FROM node:12-slim AS build +WORKDIR /usr/src/app +COPY package.json package-lock.json ./ +RUN npm ci --production && npm cache clean --force + +# 剩余部分 +``` + +
\ No newline at end of file diff --git a/sections/docker/clean-cache.french.md b/sections/docker/clean-cache.french.md new file mode 100644 index 000000000..1c4bad560 --- /dev/null +++ b/sections/docker/clean-cache.french.md @@ -0,0 +1,28 @@ +# Clean NODE_MODULE cache + +

+ +### One Paragraph Explainer + +Node package managers, npm & Yarn, cache the installed packages locally so that future projects which need the same libraries won't need to fetch from a remote repository. Although this duplicates the packages and consumes more storage - it pays off in a local development environment that typically keeps installing the same packages. In a Docker container this storage increase is worthless since it installs the dependency only once. By removing this cache, using a single line of code, tens of MB are shaved from the image. While doing so, ensure that it doesn't exit with non-zero code and fail the CI build because of caching issues - This can be avoided by including the --force flag. + +*Please note that this is not relevant if you are using a multi-stage build as long as you don't install new packages in the last stage* + +

+ +### Code Example – Clean cache + +
+Dockerfile + +```dockerfile +FROM node:12-slim AS build + +WORKDIR /usr/src/app +COPY package.json package-lock.json ./ +RUN npm ci --production && npm cache clean --force + +# The rest comes here +``` + +
\ No newline at end of file diff --git a/sections/docker/clean-cache.japanese.md b/sections/docker/clean-cache.japanese.md index b3f8b19fe..5a8891dd9 100644 --- a/sections/docker/clean-cache.japanese.md +++ b/sections/docker/clean-cache.japanese.md @@ -15,8 +15,9 @@ Node パッケージマネージャである npm や Yarn は、同じライブ
Dockerfile -``` +```dockerfile FROM node:12-slim AS build + WORKDIR /usr/src/app COPY package.json package-lock.json ./ RUN npm ci --production && npm cache clean --force diff --git a/sections/docker/clean-cache.md b/sections/docker/clean-cache.md index 485d074d6..c5ab40ec6 100644 --- a/sections/docker/clean-cache.md +++ b/sections/docker/clean-cache.md @@ -6,7 +6,7 @@ Node package managers, npm & Yarn, cache the installed packages locally so that future projects which need the same libraries won't need to fetch from a remote repository. Although this duplicates the packages and consumes more storage - it pays off in a local development environment that typically keeps installing the same packages. In a Docker container this storage increase is worthless since it installs the dependency only once. By removing this cache, using a single line of code, tens of MB are shaved from the image. While doing so, ensure that it doesn't exit with non-zero code and fail the CI build because of caching issues - This can be avoided by including the --force flag. -*Please not that this is not relevant if you are using a multi-stage build as long as you don't install new packages in the last stage* +*Please note that this is not relevant if you are using a multi-stage build as long as you don't install new packages in the last stage*

@@ -15,8 +15,9 @@ Node package managers, npm & Yarn, cache the installed packages locally so that
Dockerfile -``` +```dockerfile FROM node:12-slim AS build + WORKDIR /usr/src/app COPY package.json package-lock.json ./ RUN npm ci --production && npm cache clean --force diff --git a/sections/docker/docker-ignore.basque.md b/sections/docker/docker-ignore.basque.md new file mode 100644 index 000000000..6e76a860b --- /dev/null +++ b/sections/docker/docker-ignore.basque.md @@ -0,0 +1,50 @@ +# Erabili .dockerignore sekretuak filtratzea ekiditeko + +

+ +### Azalpena + +Docker konpilazio komandoak tokian tokiko fitxategiak konpilazioaren testuinguruko ingurunean kopiatzen ditu sare birtual baten bidez. Kontuz ibili, garapen eta IE karpetek .npmrc, .aws, .env fitxategiak eta beste fitxategi garrantzitsu batzuk eduki ditzakete eta. Ondorioz, gertatu daiteke Dockereko irudiek sekretuak gordetzea eta lurralde arriskutsuetan agerian uztea (esaterako Docker bilgailua, kideen zerbitzariak). Mundu hobe batean Dockerfile fitxategiak zehaztu beharko luke zer ari den kopiatzen. Horretaz gainera, azken segurtasun sare gisa, gehitu .dockerignore fitxategia, beharrezkoak ez diren karpetak eta balizko sekretuak iragazten dituena. Hori egiteak abiadura azkartzen du gainera, ekoizpenean erabilerarik ez duten garapen karpeta arruntak alde batera utziz (adibidez .git, proben emaitzak, garatze programen konfigurazioak), eraikitzaileak cachea hobeto erabil dezake eta errendimendu hobea eskuratu + +

+ +### Kode adibidea: .dockerignore fitxategi lehenetsi ona Node.jsrentzat + +
+.dockerignore + +``` +**/node_modules/ +**/.git +**/README.md +**/LICENSE +**/.vscode +**/npm-debug.log +**/coverage +**/.env +**/.editorconfig +**/.aws +**/dist +``` + +
+ +

+ +### Anti ereduaren kode adibidea: kopia errekurtsiboa fitxategi guztientzat + +
+Dockerfile + +```dockerfile +FROM node:12-slim AS build + +WORKDIR /usr/src/app +# The next line copies everything +COPY . . + +# Hemen duzu beste guztia + +``` + +
diff --git a/sections/docker/docker-ignore.chinese.md b/sections/docker/docker-ignore.chinese.md new file mode 100644 index 000000000..4743e5c8f --- /dev/null +++ b/sections/docker/docker-ignore.chinese.md @@ -0,0 +1,50 @@ +# 使用.dockerignore防止泄漏机密 + +

+ +### 一段解释 + +Docker的build命令会通过一个虚拟网络(virtual network)拷贝本地文件到构建的上下文环境。注意 - 开发和CI文件夹会包含机密文件,比如.npmrc,.aws,.env,以及其他一些敏感文件。最终,Docker镜像可能会包含机密信息,并在不安全的区域暴露它们(例如,Docker repository,partners servers)。一个更好的方式是,Dockerfile应该明确地描述哪些文件需要被复制。除此之外,包含一个.dockerginore文件,还充当最后一个安全网,过滤掉不必要的文件夹和潜在的机密文件。这样做还可以加快构建速度 - 通过排除在生产环境并不会用到的通用开发文件夹(例如.git,测试结果,IDE配置),整个构建过程可以更好的使用缓存,并取得一个更佳的性能。 + +

+ +### 代码示例 – 对于Node.js,一个好的默认.dockerignore示例 + +
+.dockerignore + +``` +**/node_modules/ +**/.git +**/README.md +**/LICENSE +**/.vscode +**/npm-debug.log +**/coverage +**/.env +**/.editorconfig +**/.aws +**/dist +``` + +
+ +

+ +### 代码示例 反模式 - 遍历拷贝所有文件 + +
+Dockerfile + +```dockerfile +FROM node:12-slim AS build + +WORKDIR /usr/src/app +# 下一行拷贝所有文件 +COPY . . + +# 剩余部分 + +``` + +
diff --git a/sections/docker/docker-ignore.french.md b/sections/docker/docker-ignore.french.md new file mode 100644 index 000000000..b7d8abb95 --- /dev/null +++ b/sections/docker/docker-ignore.french.md @@ -0,0 +1,50 @@ +# Use .dockerignore to prevent leaking secrets + +

+ +### One Paragraph Explainer + +The Docker build command copies the local files into the build context environment over a virtual network. Be careful - development and CI folders contain secrets like .npmrc, .aws, .env files and other sensitive files. Consequently, Docker images might hold secrets and expose them in unsafe territories (e.g. Docker repository, partners servers). In a better world the Dockerfile should be explicit about what is being copied. On top of this include a .dockerignore file that acts as the last safety net that filters out unnecessary folders and potential secrets. Doing so also boosts the build speed - By leaving out common development folders that have no use in production (e.g. .git, test results, IDE configuration), the builder can better utilize the cache and achieve better performance + +

+ +### Code Example – A good default .dockerignore for Node.js + +
+.dockerignore + +``` +**/node_modules/ +**/.git +**/README.md +**/LICENSE +**/.vscode +**/npm-debug.log +**/coverage +**/.env +**/.editorconfig +**/.aws +**/dist +``` + +
+ +

+ +### Code Example Anti-Pattern – Recursive copy of all files + +
+Dockerfile + +```dockerfile +FROM node:12-slim AS build + +WORKDIR /usr/src/app +# The next line copies everything +COPY . . + +# The rest comes here + +``` + +
\ No newline at end of file diff --git a/sections/docker/docker-ignore.japanese.md b/sections/docker/docker-ignore.japanese.md index 6a2510e0f..e83bd3a4a 100644 --- a/sections/docker/docker-ignore.japanese.md +++ b/sections/docker/docker-ignore.japanese.md @@ -36,8 +36,9 @@ Docker ビルドコマンドは、仮想ネットワークを介してローカ
Dockerfile -``` +```dockerfile FROM node:12-slim AS build + WORKDIR /usr/src/app # 次の行はすべてをコピーします COPY . . diff --git a/sections/docker/docker-ignore.md b/sections/docker/docker-ignore.md index 37ab9bd0a..e82e15e3d 100644 --- a/sections/docker/docker-ignore.md +++ b/sections/docker/docker-ignore.md @@ -36,8 +36,9 @@ The Docker build command copies the local files into the build context environme
Dockerfile -``` +```dockerfile FROM node:12-slim AS build + WORKDIR /usr/src/app # The next line copies everything COPY . . diff --git a/sections/docker/generic-tips.basque.md b/sections/docker/generic-tips.basque.md new file mode 100644 index 000000000..476a5d067 --- /dev/null +++ b/sections/docker/generic-tips.basque.md @@ -0,0 +1,29 @@ +[✔]: ../../assets/images/checkbox-small-blue.png + +# Common Node.js Dockeren praktika onak + +Dockeren praktika arrunten atal honek programazio lengoaia guztietan araupetuta dauden praktika onak biltzen ditu, ez dira Node.jsrentzat bakarrik + +## ![✔] Nahiago COPY, ADD komandoa baino + +**TL;PL:** COPY seguruagoa da, bakarrik lekuko fitxategiak kopiatzen ditu eta; ADDek, aldiz, bestelako funtzionalitateak onartzen ditu, adibidez, urruneko webguneetatik binarioak deskargatzea + +## ![✔] Ekidin oinarrizko sistema eragilea eguneratzea + +**TL;PL:** eraikitze prozesuaren lekuko binarioak eguneratzeak (adibidez apt-get update) sendotasunik gabeko irudiak sortzen ditu exekutatzen duen bakoitzean eta pribilegio handiak eskatzen ditu. Horren ordez, erabili sarri eguneratzen diren oinarrizko irudiak + +## ![✔] Sailkatu irudiak etiketen bidez + +**TL;PL:** irudi bakoitzaren metadatuak emateak Ops-eko profesionalei modu egokian tratatzen lagundu diezaieke. Adibidez, gehitu mantentze arduradunaren izena, eraikitze data eta bestelako informazioa, irudi bat erabili behar duenari lagungarria izango zaiona + +## ![✔] Erabili pribilegiorik gabeko edukiontziak + +**TL;PL:** pribilegiodun edukiontziek erabiltzaile nagusiak (root) dituen baimen eta gaitasun berdinak ditu makina ostalariaren gainean. Hori ia inoiz ez da beharrezkoa, eta, normalean, Node irudi ofizialetan sortzen den 'node' erabiltzailea erabili behar da + +## ![✔] Arakatu eta egiaztatu bukaerako emaitza + +**TL;PL:** batzuetan erraza da eraikitze prozesuko albo efektuak ahaztea, hala nola sekretu filtratuak edota beharrezkoak ez diren fitxategiak. [Dive](https://github.com/wagoodman/dive) bezalako tresnak erabiltzeak sortutako irudia arakatzeko horrelako arazoak identifikatzen lagun dezake + +## ![✔] Burutu osotasunaren egiaztapena + +**TL;PL:** oinarrizko edo bukaerako irudiak argitaratzen ari zaren bitartean, sarea engainatu eta birbideratu egin daiteke irudi maltzurrak deskargatzeko. Dockeren protokolo estandarrak ez du ezer eragozten edukia sinatu eta egiaztatu ezean. [Docker Notary](https://docs.docker.com/notary/getting_started/) da hori lortzea ahalbidetzen duten tresnetako bat da diff --git a/sections/docker/generic-tips.chinese.md b/sections/docker/generic-tips.chinese.md new file mode 100644 index 000000000..ad6f322fd --- /dev/null +++ b/sections/docker/generic-tips.chinese.md @@ -0,0 +1,29 @@ +[✔]: ../../assets/images/checkbox-small-blue.png + +# 通用的Node.js Docker最佳实践 + +此通用Docker指南部分包含所有编程语言中标准化的最佳实践,并没有针对Node.js的特殊解释 + +## ![✔] 使用命令COPY优于ADD + +**TL;DR:** COPY更安全,因为它只复制本地文件,而ADD支持更高级的获取,比如从远程站点下载二进制文件 + +## ![✔] 避免更新基础OS + +**TL;DR:** 在构建期间更新本地二进制文件(例如apt get update)会在每次运行时创建不一致的映像,并且还需要提升权限。取而代之,使用经常更新的基础镜像 + +## ![✔] 使用标签对镜像分类 + +**TL;DR:** 为每个镜像提供元数据(metadata)可能有助于Ops专业人员充分处理它。例如,包括维护人员姓名、构建日期和其他信息,当有人需要对映像进行推理时,这些信息可能会被证明是有用的 + +## ![✔] 使用非特权容器 + +**TL;DR:** 特权容器具有与主机上的根用户相同的权限和功能。这是很少需要的,作为一个经验法则,应该使用在官方Node镜像中创建的'node'用户 + +## ![✔] 检查并验证最终结果 + +**TL;DR:** 有时很容易忽略构建过程中的副作用,如泄露的秘密或不必要的文件。使用[Dive](https://github.com/wagoodman/dive)等工具检查生成的镜像可以很容易地帮助识别此类问题 + +## ![✔] 执行完整性检查 + +**TL;DR:** 在拉取基本镜像或最终镜像时,网络可能会被误导并重定向到下载恶意镜像。除非对内容进行签名和验证,否则标准Docker协议中没有任何内容可以防止这种情况。[Docker Notary](https://docs.docker.com/notary/getting_started/)是一个可以执行此类检查的工具 diff --git a/sections/docker/generic-tips.french.md b/sections/docker/generic-tips.french.md new file mode 100644 index 000000000..5e4fba34c --- /dev/null +++ b/sections/docker/generic-tips.french.md @@ -0,0 +1,29 @@ +[✔]: ../../assets/images/checkbox-small-blue.png + +# Common Node.js Docker best practices + +This common Docker guidelines section contains best practices that are standardized among all programming languages and have no special Node.js interpretation + +## ![✔] Prefer COPY over ADD command + +**TL;DR:** COPY is safer as it copies local files only while ADD supports fancier fetches like downloading binaries from remote sites + +## ![✔] Avoid updating the base OS + +**TL;DR:** Updating the local binaries during build (e.g. apt-get update) creates inconsistent images every time it runs and also demands elevated privileges. Instead use base images that are updated frequently + +## ![✔] Classify images using labels + +**TL;DR:** Providing metadata for each image might help Ops professionals treat it adequately. For example, include the maintainer name, build date and other information that might prove useful when someone needs to reason about an image + +## ![✔] Use unprivileged containers + +**TL;DR:** Privileged container have the same permissions and capabilities as the root user over the host machine. This is rarely needed and as a rule of thumb one should use the 'node' user that is created within official Node images + +## ![✔] Inspect and verify the final result + +**TL;DR:** Sometimes it's easy to overlook side effects in the build process like leaked secrets or unnecessary files. Inspecting the produced image using tools like [Dive](https://github.com/wagoodman/dive) can easily help to identify such issues + +## ![✔] Perform integrity check + +**TL;DR:** While pulling base or final images, the network might be mislead and redirected to download malicious images. Nothing in the standard Docker protocol prevents this unless signing and verifying the content. [Docker Notary](https://docs.docker.com/notary/getting_started/) is one of the tools to achieve this \ No newline at end of file diff --git a/sections/docker/graceful-shutdown.basque.md b/sections/docker/graceful-shutdown.basque.md new file mode 100644 index 000000000..174f88a7f --- /dev/null +++ b/sections/docker/graceful-shutdown.basque.md @@ -0,0 +1,80 @@ +# Itzalaldi dotorea + +

+ +### Azalpena + +Kubernetes bezalako exekuzio ingurune Dockerizatu batean, edukiontziak sarri jaio eta hiltzen dira. Erroreak jaurtitzen direnean gertatzen da hori, baina baita bestelako arrazoi onak direla eta, hala nola edukiontziak berrerabiltzeagatik edo kontainerrak bertsio berriago batekin ordezkatzeagatik. Eta hori lortzen da prozesuari 30 segunduko itxarote iraupena duen abisu bat (SIGTERM seinalea) bidaliz. Horrek erronka bat gehitzen dio garatzaileari bermatu behar baitu aplikazioa modu egokian ari dela kudeatzen une horretan bertan egikaritzen ari diren eskaerak eta garbiketako baliabideak. Bestela, milaka erabiltzaile goibelduko lirateke erantzunik jasoko ez luketelako. Inplementazioari dagokionez, itzaltze kodeak itxoin beharko du uneko eskaera guztiak bukatuta egon eta ondoren baliabideak garbituta egon arte. Errazagoa da esatea egitea baino, ordea, praktikan hainbat zati kudeatzea eskatzen du eta: esan LoadBalancerari aplikazioak ezin duela eskaera gehiago onartu (health-checkaren bidez), itxaron uneko eskariak amaituta egon arte, ekidin eskaera berriak kudeatzea, garbitu baliabideak eta, azkenik, erregistratu informazio baliagarria hil aurretik. Bizirik matentzeko konexioak (Keep-Alive) erabiliz gero, konexio berriak sortu behar direla jakinarazi behar zaie erabiltzaileei. [Stoppable](https://github.com/hunterloftis/stoppable) bezalako liburutegia laguntza handia izan daiteke hori lortzeko. + +

+ +### Kode adibidea: Node.js prozesu errotzat definitzeak kodeari seinaleak pasatzea ahalbidetzen du ([ikusi abiarazi node erabiliz](./bootstrap-using-node.basque.md)) + +
+ +Dockerfile + +```dockerfile +FROM node:12-slim + +# Eraikitze logika hemen dago + +CMD ["node", "index.js"] +#Hemengo ilarak Node.js prozesu erroa (PID1) bilakatuko du + +``` + +
+ +

+ +### Kode adibidea: erabili Tily prozesu kudeatzailea seinaleak Noderi berbidaltzeko + +
+ +Dockerfile + +```dockerfile +FROM node:12-slim + +# Eraikitze logika hemen dago + +ENV TINI_VERSION v0.19.0 +ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /tini +RUN chmod +x /tini +ENTRYPOINT ["/tini", "--"] + +CMD ["node", "index.js"] +#Hemendik aurrera Nodek PID1 bezala jokatuko duten TINIren azpi prozesuak abiatuko ditu + +``` + +
+ +

+ +### Anti ereduaren kode adibidea: erabili npm scriptak prozesua hasieratzeko + +
+ +Dockerfile + +```dockerfile +FROM node:12-slim + +# Eraikitze logika hemen dator + +CMD ["npm", "start"] +#Hemendik aurrera Nodek bigarren mailako prozesuak abiatuko ditu eta npmek ez ditu seinaleak jasoko + +``` + +
+ +

+ +### Adibidea - Itzaltze faseak + +[Rising Stack](https://blog.risingstack.com/graceful-shutdown-node-js-kubernetes/) blogetik + +![alt text](../../assets/images/Kubernetes-graceful-shutdown-flowchart.png "Itzaltze faseak") diff --git a/sections/docker/graceful-shutdown.french.md b/sections/docker/graceful-shutdown.french.md new file mode 100644 index 000000000..6be36dd64 --- /dev/null +++ b/sections/docker/graceful-shutdown.french.md @@ -0,0 +1,81 @@ +# Shutdown gracefully + +

+ +### One Paragraph Explainer + +In a Dockerized runtime like Kubernetes, containers are born and die frequently. This happens not only when errors are thrown but also for good reasons like relocating containers, replacing them with a newer version and more. It's achieved by sending a notice (SIGTERM signal) to the process with a 30 second grace period. This puts a challenge on the developer to ensure the app is handling the ongoing requests and clean-up resources in a timely fashion. Otherwise thousands of sad users will not get a response. Implementation-wise, the shutdown code should wait until all ongoing requests are flushed out and then clean-up resources. Easier said than done, practically it demands orchestrating several parts: Tell the LoadBalancer that the app is not ready to serve more requests (via health-check), wait for existing requests to be done, avoid handling new requests, clean-up resources and finally log some useful information before dying. If Keep-Alive connections are being used, the clients must also be notified that a new connection should be established - A library like [Stoppable](https://github.com/hunterloftis/stoppable) can greatly help achieving this. + +

+ + +### Code Example – Placing Node.js as the root process allows passing signals to the code (see [bootstrap using node](./bootstrap-using-node.md)) + +
+ +Dockerfile + +```dockerfile +FROM node:12-slim + +# Build logic comes here + +CMD ["node", "index.js"] +#This line above will make Node.js the root process (PID1) + +``` + +
+ +

+ +### Code Example – Using Tiny process manager to forward signals to Node + +
+ +Dockerfile + +```dockerfile +FROM node:12-slim + +# Build logic comes here + +ENV TINI_VERSION v0.19.0 +ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /tini +RUN chmod +x /tini +ENTRYPOINT ["/tini", "--"] + +CMD ["node", "index.js"] +#Now Node will run a sub-process of TINI which acts as PID1 + +``` + +
+ +

+ +### Code Example Anti Pattern – Using npm scripts to initialize the process + +
+ +Dockerfile + +```dockerfile +FROM node:12-slim + +# Build logic comes here + +CMD ["npm", "start"] +#Now Node will run a sub-process of npm and won't receive signals + +``` + +
+ +

+ +### Example - The shutdown phases + +From the blog, [Rising Stack](https://blog.risingstack.com/graceful-shutdown-node-js-kubernetes/) + +![alt text](../../assets/images/Kubernetes-graceful-shutdown-flowchart.png "The shutdown phases") \ No newline at end of file diff --git a/sections/docker/graceful-shutdown.japanese.md b/sections/docker/graceful-shutdown.japanese.md index fa96f1dab..697f45e44 100644 --- a/sections/docker/graceful-shutdown.japanese.md +++ b/sections/docker/graceful-shutdown.japanese.md @@ -9,14 +9,13 @@ Kubernetes のような Docker 化されたランタイムでは、コンテナ

-### コード例 – Node.js をルートプロセスとして配置することで、コードにシグナルを渡すことができます([bootstrap using node](/sections/docker/bootstrap-using-node.japanese.md) を参照してください)。 +### コード例 – Node.js をルートプロセスとして配置することで、コードにシグナルを渡すことができます([bootstrap using node](./bootstrap-using-node.japanese.md) を参照してください)。
Dockerfile -``` - +```dockerfile FROM node:12-slim # ビルドロジックはここ @@ -36,8 +35,7 @@ CMD ["node", "index.js"] Dockerfile -``` - +```dockerfile FROM node:12-slim # ビルドロジックはここ @@ -62,8 +60,7 @@ CMD ["node", "index.js"] Dockerfile -``` - +```dockerfile FROM node:12-slim # ビルドロジックはここ @@ -81,4 +78,4 @@ CMD ["npm", "start"] ブログ [Rising Stack](https://blog.risingstack.com/graceful-shutdown-node-js-kubernetes/) より -![alt text](/assets/images/Kubernetes-graceful-shutdown-flowchart.png "The shutdown phases") +![alt text](../../assets/images/Kubernetes-graceful-shutdown-flowchart.png "The shutdown phases") diff --git a/sections/docker/graceful-shutdown.md b/sections/docker/graceful-shutdown.md index 471989bba..a6adcb0b6 100644 --- a/sections/docker/graceful-shutdown.md +++ b/sections/docker/graceful-shutdown.md @@ -9,14 +9,13 @@ In a Dockerized runtime like Kubernetes, containers are born and die frequently.

-### Code Example – Placing Node.js as the root process allows passing signals to the code (see [bootstrap using node](/sections/docker/bootstrap-using-node.md)) +### Code Example – Placing Node.js as the root process allows passing signals to the code (see [bootstrap using node](./bootstrap-using-node.md))
Dockerfile -``` - +```dockerfile FROM node:12-slim # Build logic comes here @@ -36,8 +35,7 @@ CMD ["node", "index.js"] Dockerfile -``` - +```dockerfile FROM node:12-slim # Build logic comes here @@ -62,8 +60,7 @@ CMD ["node", "index.js"] Dockerfile -``` - +```dockerfile FROM node:12-slim # Build logic comes here @@ -81,4 +78,4 @@ CMD ["npm", "start"] From the blog, [Rising Stack](https://blog.risingstack.com/graceful-shutdown-node-js-kubernetes/) -![alt text](/assets/images/Kubernetes-graceful-shutdown-flowchart.png "The shutdown phases") +![alt text](../../assets/images/Kubernetes-graceful-shutdown-flowchart.png "The shutdown phases") diff --git a/sections/docker/image-tags.basque.md b/sections/docker/image-tags.basque.md new file mode 100644 index 000000000..c276d2746 --- /dev/null +++ b/sections/docker/image-tags.basque.md @@ -0,0 +1,30 @@ +# Ulertu irudi etiketak eta laburpenak eta erabili "azken" (latest) etiketak kontu handiz + +### Azalpena + +Ekoizpen aldian segurtasuna eta egonkortasuna garrantzitsuak dira, eta "erosotasuna" ez da erabakitze faktore egokiena. Gainera, `:latest` Dockeren lehenetsitako etiketa da. Horrek esan nahi du etiketa esplizitua gehitzea ahaztu duen garatzaileak nahi gabe irudi baten bertsio berria argitaratuko duela, espero gabeko emaitzak sor ditzakeena `latest` etiketa ekoizpeneko azken irudia izatea erabakiz gero. + +### Kode adibidea: + +```bash +$ docker build -t company/image_name:0.1 . +# :azken irudia ez da eguneratua +$ docker build -t company/image_name +# :azken irudia eguneratua da +$ docker build -t company/image_name:0.2 . +# :azken irudia ez da eguneratua +$ docker build -t company/image_name:latest . +# :azken irudia eguneratua da +``` + +### Beste bloglariek diotena + +[Vladislav Supalov](https://vsupalov.com/docker-latest-tag/)en bloga: + +> Batzuek espero dute :latestek beti irudi baten bertsio berrienari erreferentzia egingo diola. Hori ez da egia. + +[Docker success center](https://success.docker.com/article/images-tagging-vs-digests) bloga + +> + +
diff --git a/sections/docker/image-tags.french.md b/sections/docker/image-tags.french.md new file mode 100644 index 000000000..f770243da --- /dev/null +++ b/sections/docker/image-tags.french.md @@ -0,0 +1,27 @@ +# Understand image tags vs digests and use the `:latest` tag with caution + +### One Paragraph Explainer + +If this is a production situation and security and stability are important then just "convenience" is likely not the best deciding factor. In addition the `:latest` tag is Docker's default tag. This means that a developer who forgets to add an explicit tag will accidentally push a new version of an image as `latest`, which might end in very unintended results if the `latest` tag is being relied upon as the latest production image. + +### Code example: + +```bash +$ docker build -t company/image_name:0.1 . +# :latest image is not updated +$ docker build -t company/image_name +# :latest image is updated +$ docker build -t company/image_name:0.2 . +# :latest image is not updated +$ docker build -t company/image_name:latest . +# :latest image is updated +``` + +### What Other Bloggers Say +From the blog by [Vladislav Supalov](https://vsupalov.com/docker-latest-tag/): +> Some people expect that :latest always points to the most-recently-pushed version of an image. That’s not true. + +From the [Docker success center](https://success.docker.com/article/images-tagging-vs-digests) +> + +
\ No newline at end of file diff --git a/sections/docker/install-for-production.basque.md b/sections/docker/install-for-production.basque.md new file mode 100644 index 000000000..8ca1564e9 --- /dev/null +++ b/sections/docker/install-for-production.basque.md @@ -0,0 +1,89 @@ +# Ezabatu garapen menpekotasunak + +

+ +### Azalpena + +Garapen menpekotasunek asko handitzen dute edukiontziaren eraso azalera (esaterako, segurtasun ahulezia potentzialak) eta edukiontziaren tamaina. Adibide gisa, npm segurtasun zulo handienak [eslint-scope](https://eslint.org/blog/2018/07/postmortem-for-malicious-package-publishes) bezakako garapen menpekotasunek sortuak izan ziren, edo [nodemonek erabilitako ebentu katea](https://snyk.io/blog/a-post-mortem-of-the-malicious-event-stream-backdoor/) bezalako garapenerako paketeek. Arrazoi horiek direla eta, ekoizpenerako bidaliko den irudiak segurua eta txikia izan behar du. Hasiera bikaina da npm install komandoa `--production`ekin abiatzea. Hala ere, `npm ci` erabiltzea oraindik seguruagoa da, hutsetik sortutako instalazioa eta sarrail filtxategiaren sorrera ziurtatzen ditu eta. Tokiko cachea ezabatzeak hamarkada MB gehiago berreskuratzen lagun dezake. Sarritan edukiontzi batean probatu edo araztu behar izaten da devDependencies erabiliz. Kasu horretan, [etapa anitzeko konpilazioek](./multi_stage_builds.basque.md) menpekotasun multzo zenbaita izaten lagun dezakete eta, azkenik, ekoizpenerako behar direnak soilik. + +

+ +### Kode adibidea: ekoizpenerako instalazioa + +
+ +Dockerfile + +```dockerfile +FROM node:12-slim AS build + +WORKDIR /usr/src/app +COPY package.json package-lock.json ./ +RUN npm ci --production && npm clean cache --force + +# Gainontzeko guztia hemen dator +``` + +
+ +

+ +### Kode adibidea: ekoizpenerako instalazioa etapa anitzeko eraikuntzarekin + +
+ +Dockerfile + +```dockerfile +FROM node:14.8.0-alpine AS build + +COPY --chown=node:node package.json package-lock.json ./ +# ✅ Instalazio segurua +RUN npm ci +COPY --chown=node:node src ./src +RUN npm run build + + +# Run-time stage +FROM node:14.8.0-alpine + +COPY --chown=node:node --from=build package.json package-lock.json ./ +COPY --chown=node:node --from=build node_modules ./node_modules +COPY --chown=node:node --from=build dist ./dist + +# ✅ Garapen paketeak garbitu +RUN npm prune --production + +CMD [ "node", "dist/app.js" ] +``` + +
+ +

+ +### Anti ereduaren kode adibidea: instalatu menpekotasun guztiak Dockerfile fitxategiko etapa bakarrean + +
+ +Dockerfile + +```dockerfile +FROM node:12-slim AS build + +WORKDIR /usr/src/app +COPY package.json package-lock.json ./ +# Bi akatz hemen: Garapen menpekotasunak instalatu eta cachea ez ezabatu npm install egin ondoren +RUN npm install + +# Gainontzeko guztia hemen dator +``` + +
+ +

+ +### Blogeko aipua: "gainera, instalazio arrunta baino zorrotzagoa da npm ci" + +[npmen dokumentazioa](https://docs.npmjs.com/cli/ci.html) + +> Komando hau npm-installen antzekoa da, salbu eta ingurune automatizatuetan erabiltzeko sortua dela, hala nola, proben plataformak, integrazio eta inplementazio jarraituak, edo zure menpekotasunen instalazio garbi bat egiten ari zarela ziur zauden egoeretan. npm install askoz azkarragoa izan liteke komando arrunta baino, erabiltzaileentzako funtzionalitate batzuk alde batera uzten dituelako. Instalazio arrunt bat baino zorrotzagoa ere bada, npm erabiltzaile gehienek gutxinaka-gutxinaka instalatutako tokiko inguruneek sortzen dituzten erroreak edo kontraesanak identifikatzen lagungarri izan daitekeena. diff --git a/sections/docker/install-for-production.french.md b/sections/docker/install-for-production.french.md new file mode 100644 index 000000000..6f19612b1 --- /dev/null +++ b/sections/docker/install-for-production.french.md @@ -0,0 +1,90 @@ +# Remove development dependencies + +

+ +### One Paragraph Explainer + +Dev dependencies greatly increase the container attack surface (i.e. potential security weakness) and the container size. As an example, some of the most impactful npm security breaches were originated from devDependencies like [eslint-scope](https://eslint.org/blog/2018/07/postmortem-for-malicious-package-publishes) or affected dev packages like [event-stream that was used by nodemon](https://snyk.io/blog/a-post-mortem-of-the-malicious-event-stream-backdoor/). For those reasons the image that is finally shipped to production should be safe and minimal. Running npm install with a `--production` is a great start, however it gets even safer to run `npm ci` that ensures a fresh install and the existence of a lock file. Removing the local cache can shave additional tens of MB. Often there is a need to test or debug within a container using devDependencies - In that case, [multi stage builds](./multi_stage_builds.md) can help in having different sets of dependencies and finally only those for production. + +

+ +### Code Example – Installing for production + +
+ +Dockerfile + +```dockerfile +FROM node:12-slim AS build + +WORKDIR /usr/src/app +COPY package.json package-lock.json ./ +RUN npm ci --production && npm cache clean --force + +# The rest comes here +``` + +
+ +

+ +### Code Example – Installing for production with multi-stage build + +
+ +Dockerfile + +```dockerfile +FROM node:14.8.0-alpine AS build + +COPY --chown=node:node package.json package-lock.json ./ +# ✅ Safe install +RUN npm ci +COPY --chown=node:node src ./src +RUN npm run build + + +# Run-time stage +FROM node:14.8.0-alpine + +COPY --chown=node:node --from=build package.json package-lock.json ./ +COPY --chown=node:node --from=build node_modules ./node_modules +COPY --chown=node:node --from=build dist ./dist + +# ✅ Clean dev packages +RUN npm prune --production + +CMD [ "node", "dist/app.js" ] +``` + +
+ + +

+ +### Code Example Anti-Pattern – Installing all dependencies in a single stage dockerfile + +
+ +Dockerfile + +```dockerfile +FROM node:12-slim AS build + +WORKDIR /usr/src/app +COPY package.json package-lock.json ./ +# Two mistakes below: Installing dev dependencies, not deleting the cache after npm install +RUN npm install + +# The rest comes here +``` + +
+ +

+ +### Blog Quote: "npm ci is also more strict than a regular install" + +From [npm documentation](https://docs.npmjs.com/cli/ci.html) + +> This command is similar to npm-install, except it’s meant to be used in automated environments such as test platforms, continuous integration, and deployment – or any situation where you want to make sure you’re doing a clean install of your dependencies. It can be significantly faster than a regular npm install by skipping certain user-oriented features. It is also more strict than a regular install, which can help catch errors or inconsistencies caused by the incrementally-installed local environments of most npm users. \ No newline at end of file diff --git a/sections/docker/install-for-production.japanese.md b/sections/docker/install-for-production.japanese.md index d405c7e88..03994e9ed 100644 --- a/sections/docker/install-for-production.japanese.md +++ b/sections/docker/install-for-production.japanese.md @@ -4,7 +4,7 @@ ### 一段落説明 -Dev-Dependencies は、コンテナへの攻撃面 (つまり潜在的なセキュリティ上の弱点) とコンテナサイズを大幅に増加させます。例として、最も影響力のある npm のセキュリティ侵害のいくつかは、[eslint-scope](https://eslint.org/blog/2018/07/postmortem-for-malicious-package-publishes) のような devDependencies や、[nodeemon が使用していた event-stream](https://snyk.io/blog/a-post-mortem-of-the-malicious-event-stream-backdoor/) のような Dev-Dependencies に由来しています。これらの理由から、最終的に本番環境に出荷されるイメージは安全で最小限のものでなければなりません。npm install を `--production` で実行するのは素晴らしいスタートですが、新鮮なインストールとロックファイルの存在を保証する `npm ci` を実行するとさらに安全になります。ローカルキャッシュを削除することで、さらに数十 MB 削ることができます。devDependencies を使ってコンテナ内でテストやデバッグをする必要がある場合がよくあります - その場合、[multi stage builds](/sections/docker/multi_stage_builds.japanese.md) は、異なる依存関係のセットを持ち、最終的には本番用の依存関係だけを持つのに役立ちます。 +Dev-Dependencies は、コンテナへの攻撃面 (つまり潜在的なセキュリティ上の弱点) とコンテナサイズを大幅に増加させます。例として、最も影響力のある npm のセキュリティ侵害のいくつかは、[eslint-scope](https://eslint.org/blog/2018/07/postmortem-for-malicious-package-publishes) のような devDependencies や、[nodeemon が使用していた event-stream](https://snyk.io/blog/a-post-mortem-of-the-malicious-event-stream-backdoor/) のような Dev-Dependencies に由来しています。これらの理由から、最終的に本番環境に出荷されるイメージは安全で最小限のものでなければなりません。npm install を `--production` で実行するのは素晴らしいスタートですが、新鮮なインストールとロックファイルの存在を保証する `npm ci` を実行するとさらに安全になります。ローカルキャッシュを削除することで、さらに数十 MB 削ることができます。devDependencies を使ってコンテナ内でテストやデバッグをする必要がある場合がよくあります - その場合、[multi stage builds](./multi_stage_builds.japanese.md) は、異なる依存関係のセットを持ち、最終的には本番用の依存関係だけを持つのに役立ちます。

@@ -14,8 +14,9 @@ Dev-Dependencies は、コンテナへの攻撃面 (つまり潜在的なセキ Dockerfile -``` +```dockerfile FROM node:12-slim AS build + WORKDIR /usr/src/app COPY package.json package-lock.json ./ RUN npm ci --production && npm clean cache --force @@ -33,16 +34,19 @@ RUN npm ci --production && npm clean cache --force Dockerfile -``` +```dockerfile FROM node:14.8.0-alpine AS build + COPY --chown=node:node package.json package-lock.json ./ # ✅ セーフインストール RUN npm ci COPY --chown=node:node src ./src RUN npm run build + # ランタイムステージ FROM node:14.8.0-alpine + COPY --chown=node:node --from=build package.json package-lock.json ./ COPY --chown=node:node --from=build node_modules ./node_modules COPY --chown=node:node --from=build dist ./dist @@ -64,9 +68,9 @@ CMD [ "node", "dist/app.js" ] Dockerfile -``` - +```dockerfile FROM node:12-slim AS build + WORKDIR /usr/src/app COPY package.json package-lock.json ./ # 以下2つのミスがあります: dev の依存関係のインストールをし、npm インストール後にキャッシュを削除していません diff --git a/sections/docker/install-for-production.md b/sections/docker/install-for-production.md index 88b01c921..d95afed98 100644 --- a/sections/docker/install-for-production.md +++ b/sections/docker/install-for-production.md @@ -4,7 +4,7 @@ ### One Paragraph Explainer -Dev dependencies greatly increase the container attack surface (i.e. potential security weakness) and the container size. As an example, some of the most impactful npm security breaches were originated from devDependencies like [eslint-scope](https://eslint.org/blog/2018/07/postmortem-for-malicious-package-publishes) or affected dev packages like [event-stream that was used by nodemon](https://snyk.io/blog/a-post-mortem-of-the-malicious-event-stream-backdoor/). For those reasons the image that is finally shipped to production should be safe and minimal. Running npm install with a `--production` is a great start, however it gets even safer to run `npm ci` that ensures a fresh install and the existence of a lock file. Removing the local cache can shave additional tens of MB. Often there is a need to test or debug within a container using devDependencies - In that case, [multi stage builds](/sections/docker/multi_stage_builds.md) can help in having different sets of dependencies and finally only those for production. +Dev dependencies greatly increase the container attack surface (i.e. potential security weakness) and the container size. As an example, some of the most impactful npm security breaches were originated from devDependencies like [eslint-scope](https://eslint.org/blog/2018/07/postmortem-for-malicious-package-publishes) or affected dev packages like [event-stream that was used by nodemon](https://snyk.io/blog/a-post-mortem-of-the-malicious-event-stream-backdoor/). For those reasons the image that is finally shipped to production should be safe and minimal. Running npm install with a `--production` is a great start, however it gets even safer to run `npm ci` that ensures a fresh install and the existence of a lock file. Removing the local cache can shave additional tens of MB. Often there is a need to test or debug within a container using devDependencies - In that case, [multi stage builds](./multi_stage_builds.md) can help in having different sets of dependencies and finally only those for production.

@@ -14,8 +14,9 @@ Dev dependencies greatly increase the container attack surface (i.e. potential s Dockerfile -``` +```dockerfile FROM node:12-slim AS build + WORKDIR /usr/src/app COPY package.json package-lock.json ./ RUN npm ci --production && npm cache clean --force @@ -33,16 +34,19 @@ RUN npm ci --production && npm cache clean --force Dockerfile -``` +```dockerfile FROM node:14.8.0-alpine AS build + COPY --chown=node:node package.json package-lock.json ./ # ✅ Safe install RUN npm ci COPY --chown=node:node src ./src RUN npm run build + # Run-time stage FROM node:14.8.0-alpine + COPY --chown=node:node --from=build package.json package-lock.json ./ COPY --chown=node:node --from=build node_modules ./node_modules COPY --chown=node:node --from=build dist ./dist @@ -64,9 +68,9 @@ CMD [ "node", "dist/app.js" ] Dockerfile -``` - +```dockerfile FROM node:12-slim AS build + WORKDIR /usr/src/app COPY package.json package-lock.json ./ # Two mistakes below: Installing dev dependencies, not deleting the cache after npm install diff --git a/sections/docker/lint-dockerfile.basque.md b/sections/docker/lint-dockerfile.basque.md new file mode 100644 index 000000000..02ad85f67 --- /dev/null +++ b/sections/docker/lint-dockerfile.basque.md @@ -0,0 +1,26 @@ +# Garbitu zure Dockerfile fitxategia + +### Azalpena + +Gure oinarrizko aplikazioaren kodea praktika onen arabera lan egiteko eta arazo bihurtu aurretik arazoak eta akatsak ezabatzeko eratuta dago, eta gure Dockerfile fitxategiek ere hala beharko lukete. Dockerfile fitxategiak garbitzeak ekoizpen arazoak garaiz atzemateko aukerak handitzea dakar oso ahalegin txikiarekin. Adibidez, zure Dockefileetan zehaztutako logikarekin eta aginduekin inolako egiturazko arazorik ez dagoela ziurtatu dezake; esaterako, existitzen ez den etapa bat kopiatzea, onlineko biltegi ezezagun batetik kopiak egitea, aplikazioa super erabiltzailearekin (SUDO) exekutatzea eta beste hainbat. Dockerfile fitxategiren [Hadolint](https://github.com/hadolint/hadolint) linter irekia (Open Source) eskuz edota IE prozesuaren zati gisa erabil daiteke zure Dockerfile fitxategia(k) garbitzeko. Hadolint Dockerfile fitxategi garbitzaile aurreratua da, [Dockerren praktika onak](https://docs.docker.com/develop/develop-images/dockerfile_best-practices/) bultzatzen dituena. + +
+ +### Kode adibidea: arakatu Dockerfile fitxategia hadolint erabiliz + +```bash +hadolint production.Dockerfile +hadolint --ignore DL3003 --ignore DL3006 # arau zehatzak burutu +hadolint --trusted-registry my-company.com:500 # Erabiltzailea jakinarazi irudi fidaezinak erabiltzeagatik +``` + +### Beste bloglariek diotena + +[Josh Reichardt](https://thepracticalsysadmin.com/lint-your-dockerfiles-with-hadolint/)en bloga: + +> Oraindik ez badaukazu zure Dockerfile fitxategiak garbitzeko ohiturarik, ohitu zaitez egiten. Kode garbiketa software garapeneko praktika arrunta da, arazo eta akatsak aurkitu, identifikatu eta ezabatzen laguntzen duena benetako arazo bihurtu aurretik. Zure kodea garbitzearen abantaila handienetako bat da akats txiki korapilasuak atzematen eta ezabatzen laguntzen duela, arazo bihurtu aurretik. + +[Jamie Phillips](https://www.phillipsj.net/posts/hadolint-linting-your-dockerfile/)en bloga: + +> Garbitzaileak edota linterrak sarri erabiltzen dira garapenean, lan taldeei programazio eta estilo erroreak atzematen laguntzeko. Hadolint Haskell erabiliz Dockerfile fitxategientzat sortutako garbitzailea (linterra) da. Tresna horrek zure Dockerfile fitxategiaren sintaxia aztertzen du eta Dockerek zehaztutako praktika onak kontutan hartu. Plataforma nagusi gehienetarako balio du, eta tutorial honek edukiontzia erabiliko du Dockerfile fitxategi batean garbiketa egiteko. +>
diff --git a/sections/docker/lint-dockerfile.french.md b/sections/docker/lint-dockerfile.french.md new file mode 100644 index 000000000..64ff2df01 --- /dev/null +++ b/sections/docker/lint-dockerfile.french.md @@ -0,0 +1,25 @@ +# Lint your Dockerfile + +### One Paragraph Explainer + +As our core application code is linted to conform to best practices and eliminate issues and bugs before it could become a problem, so too should our Dockerfiles. Linting the Dockerfile means increasing the chances of catching production issues on time with very light effort. For example, it can ensure that there aren’t any structural problems with the logic and instructions specified in your Dockerfiles like trying to copy from non-existing stage, copying from unknown online repository, running the app with power user (SUDO) and many more. The Open Source Dockerfile linter [Hadolint](https://github.com/hadolint/hadolint) can be used manually or as part of a CI process to lint your Dockerfile/s. Hadolint is a specialized Dockerfile linter that aims to embrace the [Docker best practices.](https://docs.docker.com/develop/develop-images/dockerfile_best-practices/) + + +
+ +### Code example: Inspecting a Dockerfile using hadolint + +```bash +hadolint production.Dockerfile +hadolint --ignore DL3003 --ignore DL3006 # exclude specific rules +hadolint --trusted-registry my-company.com:500 # Warn when using untrusted FROM images +``` + +### What Other Bloggers Say + +From the blog by [Josh Reichardt](https://thepracticalsysadmin.com/lint-your-dockerfiles-with-hadolint/): +> If you haven’t already gotten in to the habit of linting your Dockerfiles you should. Code linting is a common practice in software development which helps find, identify and eliminate issues and bugs before they are ever able to become a problem. One of the main benefits of linting your code is that it helps identify and eliminate nasty little bugs before they ever have a chance to become a problem. + +From the blog by [Jamie Phillips](https://www.phillipsj.net/posts/hadolint-linting-your-dockerfile/) +> Linters are commonly used in development to help teams detect programmatic and stylistic errors. Hadolint is a linter created for Dockerfiles using Haskell. This tool validates against the best practices outlined by Docker and takes a neat approach to parse the Dockerfile that you should checkout. It supports all major platforms, and this tutorial will be leveraging the container to perform the linting on an example Dockerfile. +
\ No newline at end of file diff --git a/sections/docker/lint-dockerfile.japanese.md b/sections/docker/lint-dockerfile.japanese.md index 31b5b1c4a..6b0a41e99 100644 --- a/sections/docker/lint-dockerfile.japanese.md +++ b/sections/docker/lint-dockerfile.japanese.md @@ -2,7 +2,7 @@ ### 一段落説明 -コアアプリケーションのコードをベストプラクティスに従わせ、問題になる前にイシューやバグを取り除くために lint を利用するように、Dockerfile も同様に linting されるべきです。Dockerfile を linting することは、非常に軽い労力でプロダクションの問題をオンタイムで捕らえることができる可能性を高めることを意味します。例えば、存在しないステージからコピーを試みたり、不明なオンラインリポジトリからコピーしてきたり、パワーユーザー(SUDO)でアプリケーションを実行したりなど、DOckerfile に記述されたロジックや命令に構造的な問題が無いことを確認することができます。オープンソースの Dockerfile linter である [Hadolint](https://github.com/hadolint/hadolint) は、手動または CI プロセスの一部として利用することができます。Hadolint は、[Docker ベストプラクティス](https://docs.docker.com/develop/develop-images/dockerfile_best-practices/) に従うことを目的とした Dockerfile 専用の linter です。 +コアアプリケーションのコードをベストプラクティスに従わせ、問題になる前にイシューやバグを取り除くために lint を利用するように、Dockerfile も同様に linting されるべきです。Dockerfile を linting することは、非常に軽い労力でプロダクションの問題をオンタイムで捕らえることができる可能性を高めることを意味します。例えば、存在しないステージからコピーを試みたり、不明なオンラインリポジトリからコピーしてきたり、パワーユーザー(SUDO)でアプリケーションを実行したりなど、Dockerfile に記述されたロジックや命令に構造的な問題が無いことを確認することができます。オープンソースの Dockerfile linter である [Hadolint](https://github.com/hadolint/hadolint) は、手動または CI プロセスの一部として利用することができます。Hadolint は、[Docker ベストプラクティス](https://docs.docker.com/develop/develop-images/dockerfile_best-practices/) に従うことを目的とした Dockerfile 専用の linter です。
diff --git a/sections/docker/memory-limit.basque.md b/sections/docker/memory-limit.basque.md new file mode 100644 index 000000000..fce834f5d --- /dev/null +++ b/sections/docker/memory-limit.basque.md @@ -0,0 +1,70 @@ +# Ezarri memoria mugak Docker eta v8 erabiliz + +

+ +### Azalpena + +Memoria mugatzeak prozesuari/edukiontziari adierazten dio zer tamainako memoria erabiltzeko baimena duen gehienez ere. Tamaina horretatik gorako eskaerak edo erabilerak prozesua hil egingo du (OOMKill). Hori egitea jarraibide bikaina da ziurtatzeko herritar batek zuku guztia berak bakarrik edaten ez duela, beste guztiak egarriz akabatzen utzita. Memoria mugek, gainera, exekuzio garaian edukiontzia instantzia egokian ipintzea ahalbidetzen du; izan ere, 500MB erabiltzen dituen edukiontzi bat 300MB dituen instantzia baten ipintzeak arazoak ekar litzake. Bi aukerek muga konfiguratzen laguntzen dute: V8 banderak (--max-old-space-size) eta Docker abiatze denbora, biak guztiz beharrezkoak dira. Ziurtatu beti Dockeren iraupen mugak konfiguratu dituzula, osasun erabaki egokiak hartzeko ikuspegi askoz zabalagoa baitu: muga hori izanda, exekuzioak badaki baliabide gehiago eskalatzen eta sortzen. Noiz huts egin behar duen erabaki dezake: kontainerrean, memoria eskaeran, eztanda labur bat gertatzen bada eta ostatatutako instantzia horri eusteko gai bada, Dockerek bizirik egoten utziko dio edukiontziari. Azkenik, Dockeri esker, Ops adituak hainbat memoria konfigurazio ezar ditzake, ekoizpenean kontutan hartuak izan daitezkeenak, adibidez, memoriaren trukea (memory swap). Hori bera bakarrik ez da nahikoa izango, v8ren --max-old-space-size gabe, JavaScript abiatze inguruneak ez du zabor biltzea bultzatuko memoriaren mugatik gertu egotean, eta krask egingo du soilik ostatatutako ingurunearen % 50-60 erabiltzean. Ondorioz, ezarri v8n muga Dockeren memoria mugaren %75-100 izan dadin. + +

+ +### Kode adibidea: memoriaren muga Dockerrekin + +
+Bash + +```bash +docker run --memory 512m nire-node-aplikazioa +``` + +
+ +

+ +### Kode adibidea: memoriaren muga Kubernetes eta V8rekin + +
+Kubernetesen inplementaziorako yamla + +```yml +apiVersion: v1 +kind: Pod +metadata: + name: nire-node-aplikazioa +spec: + containers: + - name: nire-node-aplikazioa + image: nire-node-aplikazioa + resources: + requests: + memory: "400Mi" + limits: + memory: "500Mi" + command: ["node index.js --max-old-space-size=350"] +``` + +
+ +

+ +### Kubernetesen dokumentazioa: "Memoriaren muga zehaztu ezean" + +[K8Sen dokumentazioa](https://kubernetes.io/docs/tasks/configure-pod-container/assign-memory-resource/) + +> Edukiontziak ez du erabiltzen duen memoriaren gehieneko muga. Egikaritzen ari den Nodean erabilgarri dagoen memoria guztia erabil dezake edukiontziak , eta horrek OOM Killer errorea dei dezake. Gainera, OOM Kill bat gertatuz gero, mugarik gabeko edukiontzi batek aukera gehiago izango du akabatua izateko. + +

+ +### Dockeren dokumentazioa: "Jaurti OOME errore bat eta hasi prozesuak hiltzen" + +[Dockeren dokumentu ofiziala](https://docs.docker.com/config/containers/resource_constraints/) + +> Garrantzitsua da exekutatzen ari den edukiontzi bati ez uztea ostatatutako makinaren memoria gehiegi erabiltzen. Linux ostalarietan, kernelak sistemako funtzio garrantzitsuak egiteko haina memoria ez dagoela atzematen badu, OOME bat jaurtitzen du, Out Of Memory Exception (Memoria Faltaren Salbuespena), eta prozesuak akabatzen hasten da memoria eskuratzeko. + +

+ +### Node.jsren dokumentazioa: "V8k denbora gehiago pasako du zabor bilketan" + +[Node.jsren dokumentu ofiziala](https://nodejs.org/api/cli.html#cli_max_old_space_size_size_in_megabytes) + +> Ezarri V8ren atal zaharraren gehienezko memoria tamaina. Memoriaren kontsumoa mugara gerturatzen denean, V8k denbora gehiago pasako du zabor bilketan, erabili gabeko memoria askatzen baino. 2GBko memoria duen makina batean, komeni da 1536Mgb (1.5GB) ezartzea, beste erabiltzaileentzat memoria pixkat bat uzteko eta memoria trukea ekiditeko. diff --git a/sections/docker/memory-limit.french.md b/sections/docker/memory-limit.french.md new file mode 100644 index 000000000..93204f016 --- /dev/null +++ b/sections/docker/memory-limit.french.md @@ -0,0 +1,70 @@ +# Set memory limits using both Docker and v8 + +

+ +### One Paragraph Explainer + +A memory limit tells the process/container the maximum allowed memory usage - a request or usage beyond this number will kill the process (OOMKill). Applying this is a great practice to ensure one citizen doesn't drink all the juice alone and leaves other components to starve. Memory limits also allow the runtime to place a container in the right instance - placing a container that consumes 500MB in an instance with 300MB memory available will lead to failures. Two different options allow configuring this limit: V8 flags (--max-old-space-size) and the Docker runtime, both are absolutely needed. Ensure to always configure the Docker runtime limits as it has a much wider perspective for making the right health decisions: Given this limit, the runtime knows how to scale and create more resources. It can also make a thoughtful decision on when to crash - if a container has a short burst in memory request and the hosting instance is capable of supporting this, Docker will let the container stay alive. Last, with Docker the Ops experts can set various production memory configurations that can be taken into account like memory swap. This by itself won't be enough - Without setting v8's --max-old-space-size, the JavaScript runtime won't push the garbage collection when getting close to the limits and will also crash when utilizing only 50-60% of the host environment. Consequently, set v8's limit to be 75-100% of Docker's memory limit. + +

+ +### Code Example – Memory limit with Docker + +
+Bash + +```bash +docker run --memory 512m my-node-app +``` + +
+ +

+ +### Code Example – Memory limit with Kubernetes and v8 + +
+Kubernetes deployment yaml + +```yml +apiVersion: v1 +kind: Pod +metadata: + name: my-node-app +spec: + containers: + - name: my-node-app + image: my-node-app + resources: + requests: + memory: "400Mi" + limits: + memory: "500Mi" + command: ["node index.js --max-old-space-size=350"] +``` + +
+ +

+ +### Kubernetes documentation: "If you do not specify a memory limit" + +From [K8S documentation](https://kubernetes.io/docs/tasks/configure-pod-container/assign-memory-resource/) + +> The Container has no upper bound on the amount of memory it uses. The Container could use all of the memory available on the Node where it is running which in turn could invoke the OOM Killer. Further, in case of an OOM Kill, a container with no resource limits will have a greater chance of being killed. + +

+ +### Docker documentation: "it throws an OOME and starts killing processes " + +From [Docker official docs](https://docs.docker.com/config/containers/resource_constraints/) + +> It is important not to allow a running container to consume too much of the host machine’s memory. On Linux hosts, if the kernel detects that there is not enough memory to perform important system functions, it throws an OOME, or Out Of Memory Exception, and starts killing processes to free up memory. + +

+ +### Node.js documentation: "V8 will spend more time on garbage collection" + +From [Node.js official docs](https://nodejs.org/api/cli.html#cli_max_old_space_size_size_in_megabytes) + +> Sets the max memory size of V8's old memory section. As memory consumption approaches the limit, V8 will spend more time on garbage collection in an effort to free unused memory. On a machine with 2GB of memory, consider setting this to 1536 (1.5GB) to leave some memory for other uses and avoid swapping. \ No newline at end of file diff --git a/sections/docker/memory-limit.japanese.md b/sections/docker/memory-limit.japanese.md index 26f341b3c..d91b149e7 100644 --- a/sections/docker/memory-limit.japanese.md +++ b/sections/docker/memory-limit.japanese.md @@ -13,7 +13,7 @@
Bash -``` +```bash docker run --memory 512m my-node-app ``` @@ -26,7 +26,7 @@ docker run --memory 512m my-node-app
Kubernetes deployment yaml -``` +```yml apiVersion: v1 kind: Pod metadata: diff --git a/sections/docker/memory-limit.md b/sections/docker/memory-limit.md index f624d018b..8198228f8 100644 --- a/sections/docker/memory-limit.md +++ b/sections/docker/memory-limit.md @@ -13,7 +13,7 @@ A memory limit tells the process/container the maximum allowed memory usage - a
Bash -``` +```bash docker run --memory 512m my-node-app ``` @@ -26,7 +26,7 @@ docker run --memory 512m my-node-app
Kubernetes deployment yaml -``` +```yml apiVersion: v1 kind: Pod metadata: diff --git a/sections/docker/multi_stage_builds.basque.md b/sections/docker/multi_stage_builds.basque.md new file mode 100644 index 000000000..7155723d1 --- /dev/null +++ b/sections/docker/multi_stage_builds.basque.md @@ -0,0 +1,115 @@ +# Erabili etapa anitzeko konpilazioak + +### Azalpena + +Etapa anitzeko konpilazioek aukera ematen dute eraikuntzei eta exekuzio denborari dagozkion inguruneko xehetasunak bereizteko, hala nola eskuragarri dauden binarioak, agerian dauden inguruneko aldagaiak eta baita azpiko sistema eragilea ere. Zure Docker fitxategiak etapa anitzetan banatzeak azken irudia eta edukiontziaren tamaina murrizten lagunduko dizu, zure aplikazioa egikaritzeko behar duzuna bakarrik bidaliko baituzu. Batzuetan, konpilazio fasean soilik beharrezkoak diren tresnak sartu beharko dituzu, adibidez garapenerako menpekotasunak, hala nola TypeScripten CLI. Konpilazio fasean instalatu dezakezu, eta azken irteera exekuzio fasean bakarrik erabili. Horrek esan nahi du zure irudia txikitu egingo dela, menpekotasun batzuk ez baitira kopiatuko. Agian, egikaritze aldian egon behar ez luketen inguruneko aldagai batzuk agerian jarri beharko dituzu eraikuntzan (aztertu [nola saihestu konpilazio aldiko sekretuak](./avoid-build-time-secrets.basque.md)), hala nola API giltzak eta zerbitzu zehatzekin komunikatzeko erabiltzen diren sekretuak. Azken fasean, aurrez eraikitako baliabideak kopiatu ditzakezu, hala nola zure konpilazio karpeta edo soilik ekoizpenekoak diren menpekotasunak, hurrengo urratsean ere eskuratu ditzakezunak. + +### Adibidea + +Eman dezagun direktorio egitura hau + +``` +- Dockerfile +- src/ + - index.ts +- package.json +- yarn.lock +- .dockerignore +- docs/ + - README.md +``` +Dagoeneko zure aplikazioa eraikitzeko eta exekutatzeko beharrezkoak ez diren fitxategiak iragaziko ditu zure [.dockerignore](../docker/docker-ignore.basque.md)-k. + +``` +# Ez kopiatu existitzen diren node_modules karpetan, gure node_modules propioa berreskuratuko dugu + +# Docs are large, we don't need them in our Docker image +docs +``` + +#### Etapa anitzeko Dockerfile fitxategia + +Docker maiz etengabeko integrazio inguruneetan erabiltzen denez, `npm ci` komandoa erabiltzea gomendatzen da (`npm install` komandoa beharrean). Azkarragoa da, zorrotzagoa ere bai, eta inkoherentziak murrizten ditu package-lock.json fitxategian zehaztutako bertsioak soilik erabiliz gero. Begiratu [hau](https://docs.npmjs.com/cli/ci.html#description) informazio gehiago lortzeko. Adibide horrek yarn erabiltzen du pakete kudeatzaile gisa eta horretarako `yarn install --frozen-lockfile` [komandoa](https://classic.yarnpkg.com/en/docs/cli/install/) da `npm ci`-ren baliokidea. + +```dockerfile +FROM node:14.4.0 AS build + +COPY --chown=node:node . . +RUN yarn install --frozen-lockfile && yarn build + + +FROM node:14.4.0 + +USER node +EXPOSE 8080 + +# Aurreko etapatik emaitzak kopiatu +COPY --chown=node:node --from=build /home/node/app/dist /home/node/app/package.json /home/node/app/yarn.lock ./ +RUN yarn install --frozen-lockfile --production + +CMD [ "node", "dist/app.js" ] +``` + +#### Docker fitxategia etapa anitzekin eta oinarrizko irudiekin + +```dockerfile +FROM node:14.4.0 AS build + +COPY --chown=node:node . . +RUN yarn install --frozen-lockfile && yarn build + + +# Honek exekuzio garairako oinarri-irudi minimoa erabiliko du +FROM node:14.4.0-alpine + +USER node +EXPOSE 8080 + +# Kopiatu emaitzak aurreko etapatik +COPY --chown=node:node --from=build /home/node/app/dist /home/node/app/package.json /home/node/app/yarn.lock ./ +RUN yarn install --frozen-lockfile --production + +CMD [ "node", "dist/app.js" ] +``` + +#### Dockerfile osoa etapa anitzekin eta oinarrizko irudiekin + +Gure Docker fitxategiak bi fase izango ditu: bata, aplikazioa eraikitzekoa, Node.js Docker irudia erabiliz funtzio guztietan; eta bigarren fasea, aplikazioa exekutatzeko, Alpine irudi minimoan oinarritutakoa. Bigarren fasean konpilatutako fitxategiak bakarrik kopiatuko ditugu, eta gero produkzioaren menpekotasunak instalatuko ditugu. + +```dockerfile +# Funtzionalitate guztiak dituen Node.js oinarri-irudiarekin hasi +FROM node:14.4.0 AS build + +USER node +WORKDIR /home/node/app + +# Menpekotasun informazioa kopiatu eta menpekotasun guztiak instalatu +COPY --chown=node:node package.json yarn.lock ./ + +RUN yarn install --frozen-lockfile + +# Iturburu kodea kopiatu (eta beste fitxategi garrantzitsu guztiak) +COPY --chown=node:node src ./src + +# Kodea eraiki +RUN yarn build + + +# Exekuzio-garaiaren etapa +FROM node:14.4.0-alpine + +# Zehaztu erro erabiltzailea ez dena eta agerian utzi 8080 portua +USER node +EXPOSE 8080 + +WORKDIR /home/node/app + +# Menpekotasunen informazioa kopiatu eta soilik ekoizpenerako beharrezko dire menpekotasunak instalatu +COPY --chown=node:node package.json yarn.lock ./ +RUN yarn install --frozen-lockfile --production + +# Aurreko etapatik emaitzak kopiatu +COPY --chown=node:node --from=build /home/node/app/dist ./dist + +CMD [ "node", "dist/app.js" ] +``` diff --git a/sections/docker/multi_stage_builds.french.md b/sections/docker/multi_stage_builds.french.md new file mode 100644 index 000000000..b7d3ac854 --- /dev/null +++ b/sections/docker/multi_stage_builds.french.md @@ -0,0 +1,121 @@ +# Use multi-stage builds + +### One Paragraph Explainer + +Multi-stage builds allow to separate build- and runtime-specific environment details, such as available binaries, exposed environment variables, and even the underlying operating system. Splitting up your Dockerfiles into multiple stages will help to reduce final image and container size as you'll only ship what you really need to run your application. Sometimes you'll need to include tools that are only needed during the build phase, for example development dependencies such as the TypeScript CLI. You can install it during the build stage and only use the final output in the run stage. This also means your image will shrink as some dependencies won't get copied over. You might also have to expose environment variables during build that should not be present at runtime (see [avoid build time secrets](./avoid-build-time-secrets.md)), such as API Keys and secrets used for communicating with specific services. In the final stage, you can copy in pre-built resources such as your build folder, or production-only dependencies (which you can also fetch in a subsequent step). + +### Example + +Let's imagine the following directory structure + +``` +- Dockerfile +- src/ + - index.ts +- package.json +- yarn.lock +- .dockerignore +- docs/ + - README.md +``` + +Your [.dockerignore](../docker/docker-ignore.md) will already filter out files that won't be needed for building and running your application. + + +sections/docker/docker-ignore.md +``` +# Don't copy in existing node_modules, we'll fetch our own +node_modules + +# Docs are large, we don't need them in our Docker image +docs +``` + +#### Dockerfile with multiple stages + +Since Docker is often used in continuous integration environments it is recommended to use the `npm ci` command (instead of `npm install`). It is faster, stricter and reduces inconsistencies by using only the versions specified in the package-lock.json file. See [here](https://docs.npmjs.com/cli/ci.html#description) for more info. This example uses yarn as package manager for which the equivalent to `npm ci` is the `yarn install --frozen-lockfile` [command](https://classic.yarnpkg.com/en/docs/cli/install/). + +```dockerfile +FROM node:14.4.0 AS build + +COPY --chown=node:node . . +RUN yarn install --frozen-lockfile && yarn build + + +FROM node:14.4.0 + +USER node +EXPOSE 8080 + +# Copy results from previous stage +COPY --chown=node:node --from=build /home/node/app/dist /home/node/app/package.json /home/node/app/yarn.lock ./ +RUN yarn install --frozen-lockfile --production + +CMD [ "node", "dist/app.js" ] +``` + +#### Dockerfile with multiple stages and different base images + +```dockerfile +FROM node:14.4.0 AS build + +COPY --chown=node:node . . +RUN yarn install --frozen-lockfile && yarn build + + +# This will use a minimal base image for the runtime +FROM node:14.4.0-alpine + +USER node +EXPOSE 8080 + +# Copy results from previous stage +COPY --chown=node:node --from=build /home/node/app/dist /home/node/app/package.json /home/node/app/yarn.lock ./ +RUN yarn install --frozen-lockfile --production + +CMD [ "node", "dist/app.js" ] +``` + +#### Full Dockerfile with multiple stages and different base images + +Our Dockerfile will contain two phases: One for building the application using the fully-featured Node.js Docker image, +and a second phase for running the application, based on the minimal Alpine image. We'll only copy over the built files to our second stage, +and then install production dependencies. + +```dockerfile +# Start with fully-featured Node.js base image +FROM node:14.4.0 AS build + +USER node +WORKDIR /home/node/app + +# Copy dependency information and install all dependencies +COPY --chown=node:node package.json yarn.lock ./ + +RUN yarn install --frozen-lockfile + +# Copy source code (and all other relevant files) +COPY --chown=node:node src ./src + +# Build code +RUN yarn build + + +# Run-time stage +FROM node:14.4.0-alpine + +# Set non-root user and expose port 8080 +USER node +EXPOSE 8080 + +WORKDIR /home/node/app + +# Copy dependency information and install production-only dependencies +COPY --chown=node:node package.json yarn.lock ./ +RUN yarn install --frozen-lockfile --production + +# Copy results from previous stage +COPY --chown=node:node --from=build /home/node/app/dist ./dist + +CMD [ "node", "dist/app.js" ] +``` \ No newline at end of file diff --git a/sections/docker/multi_stage_builds.japanese.md b/sections/docker/multi_stage_builds.japanese.md index 1e35efe6f..cd160cf5c 100644 --- a/sections/docker/multi_stage_builds.japanese.md +++ b/sections/docker/multi_stage_builds.japanese.md @@ -2,7 +2,7 @@ ### 一段落説明 -マルチステージビルドでは、利用可能なバイナリや公開されている環境変数、さらには基礎となるOSなど、ビルドとランタイム固有の環境の詳細を分離することができます。Dockerfile を複数のステージに分割することで、アプリケーションの実行に本当に必要なものだけをリリースすることができるので、最終的なイメージやコンテナのサイズを小さくすることができます。ビルド段階でのみ必要となるツール、例えば TypeScript CLI のような開発依存のツールを含める必要があることもあるでしょう。これらのツールはビルド段階でインストールし、最終的な出力のみ実行段階で使用することができます。これは、いくつかの依存関係がコピーオーバーされないため、イメージが縮小されることを意味します。また、実行時には存在してはいけない API キーや特定のサービスとの通信に使われるシークレットなどの環境変数をビルド中に公開しなければならないかもしれません([ビルド時のシークレットを避ける](/sections/docker/avoid-build-time-secrets.japanese.md) を参照してください。) 最終ステージでは、ビルドフォルダのようなビルド済みのリソースや本番環境専用の依存関係 (これは後のステップで取得することもできます) をコピーすることができます。 +マルチステージビルドでは、利用可能なバイナリや公開されている環境変数、さらには基礎となるOSなど、ビルドとランタイム固有の環境の詳細を分離することができます。Dockerfile を複数のステージに分割することで、アプリケーションの実行に本当に必要なものだけをリリースすることができるので、最終的なイメージやコンテナのサイズを小さくすることができます。ビルド段階でのみ必要となるツール、例えば TypeScript CLI のような開発依存のツールを含める必要があることもあるでしょう。これらのツールはビルド段階でインストールし、最終的な出力のみ実行段階で使用することができます。これは、いくつかの依存関係がコピーオーバーされないため、イメージが縮小されることを意味します。また、実行時には存在してはいけない API キーや特定のサービスとの通信に使われるシークレットなどの環境変数をビルド中に公開しなければならないかもしれません([ビルド時のシークレットを避ける](./avoid-build-time-secrets.japanese.md) を参照してください。) 最終ステージでは、ビルドフォルダのようなビルド済みのリソースや本番環境専用の依存関係 (これは後のステップで取得することもできます) をコピーすることができます。 ### 例 @@ -19,7 +19,7 @@ - README.md ``` -[.dockerignore](/sections/docker/dockerignore.japanese.md) では、アプリケーションのビルドや実行に必要のないファイルをすでにフィルタリングしています。 +[.dockerignore](./docker-ignore.japanese.md) では、アプリケーションのビルドや実行に必要のないファイルをすでにフィルタリングしています。 ``` # 既存の node_modules をコピーしないで、自分たちで取得します。 @@ -39,6 +39,7 @@ FROM node:14.4.0 AS build COPY --chown=node:node . . RUN yarn install --frozen-lockfile && yarn build + FROM node:14.4.0 USER node @@ -59,6 +60,7 @@ FROM node:14.4.0 AS build COPY --chown=node:node . . RUN yarn install --frozen-lockfile && yarn build + # ランタイム用に最小のベースイメージを使用 FROM node:14.4.0-alpine @@ -94,6 +96,7 @@ COPY --chown=node:node src ./src # コードのビルド RUN yarn build + # ランタイムステージ FROM node:14.4.0-alpine diff --git a/sections/docker/multi_stage_builds.md b/sections/docker/multi_stage_builds.md index 8aae43cc5..de24b1d0b 100644 --- a/sections/docker/multi_stage_builds.md +++ b/sections/docker/multi_stage_builds.md @@ -2,7 +2,7 @@ ### One Paragraph Explainer -Multi-stage builds allow to separate build- and runtime-specific environment details, such as available binaries, exposed environment variables, and even the underlying operating system. Splitting up your Dockerfiles into multiple stages will help to reduce final image and container size as you'll only ship what you really need to run your application. Sometimes you'll need to include tools that are only needed during the build phase, for example development dependencies such as the TypeScript CLI. You can install it during the build stage and only use the final output in the run stage. This also means your image will shrink as some dependencies won't get copied over. You might also have to expose environment variables during build that should not be present at runtime (see [avoid build time secrets](/sections/docker/avoid-build-time-secrets.md)), such as API Keys and secrets used for communicating with specific services. In the final stage, you can copy in pre-built resources such as your build folder, or production-only dependencies (which you can also fetch in a subsequent step). +Multi-stage builds allow to separate build- and runtime-specific environment details, such as available binaries, exposed environment variables, and even the underlying operating system. Splitting up your Dockerfiles into multiple stages will help to reduce final image and container size as you'll only ship what you really need to run your application. Sometimes you'll need to include tools that are only needed during the build phase, for example development dependencies such as the TypeScript CLI. You can install it during the build stage and only use the final output in the run stage. This also means your image will shrink as some dependencies won't get copied over. You might also have to expose environment variables during build that should not be present at runtime (see [avoid build time secrets](./avoid-build-time-secrets.md)), such as API Keys and secrets used for communicating with specific services. In the final stage, you can copy in pre-built resources such as your build folder, or production-only dependencies (which you can also fetch in a subsequent step). ### Example @@ -41,6 +41,7 @@ FROM node:14.4.0 AS build COPY --chown=node:node . . RUN yarn install --frozen-lockfile && yarn build + FROM node:14.4.0 USER node @@ -61,6 +62,7 @@ FROM node:14.4.0 AS build COPY --chown=node:node . . RUN yarn install --frozen-lockfile && yarn build + # This will use a minimal base image for the runtime FROM node:14.4.0-alpine @@ -98,6 +100,7 @@ COPY --chown=node:node src ./src # Build code RUN yarn build + # Run-time stage FROM node:14.4.0-alpine diff --git a/sections/docker/restart-and-replicate-processes.basque.md b/sections/docker/restart-and-replicate-processes.basque.md new file mode 100644 index 000000000..e01c0977d --- /dev/null +++ b/sections/docker/restart-and-replicate-processes.basque.md @@ -0,0 +1,43 @@ +# Utzi Dockeren exekuzio denborari erreplikatu eta jardueraren iraupena kudeatzen + +

+ +### Azalpena + +Dockeren exekuzio denboraren kudeatzaileak, Kubernetes bezala, benetan onak dira edukiontzien osasun eta ezarpen erabakiak hartzen: edukiontzi kopurua maximizatzen, edukiontziak zonaldeen artean orekatzen eta klusterren faktore ugari kontuan hartzen dituzte erabaki horiek hartzen dituzten bitartean. Esan gabe doa: huts egiten duten prozesuak (hau da, edukiontziak) identifikatzen dituzte eta leku egokian berrabiarazten dituzte. Hala ere, batzuek kode pertsonalizatuak edo tresnak erabiltzeko tentazioa izan dezakete Node prozesua erreplikatuz PUZa erabili eta, huts eginez gero, prozesua berrabiarazte aldera (adibidez,PM2 kluster modulua, ). Tokiko tresna horiek ez dituzte kluster mailako ikuspegia eta eskuragarri dauden datuak. Adibidez, instantzien baliabideek 3 edukiontzi eta 2 eskualde ostatatu ditzaketenean, edukiontziak hainbat eskualdetan hedatzen arduratuko da Kubernetes. Horrela, zonaldeak edo eskualdeak huts egitea gertatuz gero, aplikazioak bizirik jarraituko du. Aitzitik, tokiko tresnak erabiltzean prozesua berrekiteko, Dockeren kudeatzailea ez da erroreez jabetzen eta ezin du ondo pentsatutako erabakirik hartu, edukiontzia zonalde edo instantzia berri batean ipintzea bezala. + +

+ +### Kode adibidea: deitu Node.js zuzenean, tarteko tresnarik gabe + +
+ +Dockerfile fitxategia + +```dockerfile +FROM node:12-slim + +# Eraikitze logika hemen dago + +CMD ["node", "index.js"] +``` + +
+ +

+ +### Anti ereduaren kode adibidea: erabili prozesu kudeatzailea + +
+ +Dockerfile fitxategia + +```dockerfile +FROM node:12-slim + +# Eraikitze logika hemen dago + +CMD ["pm2-runtime", "indes.js"] +``` + +
diff --git a/sections/docker/restart-and-replicate-processes.french.md b/sections/docker/restart-and-replicate-processes.french.md new file mode 100644 index 000000000..3f6bff00a --- /dev/null +++ b/sections/docker/restart-and-replicate-processes.french.md @@ -0,0 +1,43 @@ +# Let the Docker orchestrator restart and replicate processes + +

+ +### One Paragraph Explainer + +Docker runtime orchestrators like Kubernetes are really good at making containers health and placement decisions: They will take care to maximize the number of containers, balance them across zones, and take into account many cluster factors while making these decisions. Goes without words, they identify failing processes (i.e., containers) and restart them in the right place. Despite that some may be tempted to use custom code or tools to replicate the Node process for CPU utilization or restart the process upon failure (e.g., Cluster module, PM2). These local tools don't have the perspective and the data that is available on the cluster level. For example, when the instances resources can host 3 containers and given 2 regions or zones, Kubernetes will take care to spread the containers across zones. This way, in case of a zonal or regional failure, the app will stay alive. On the contrary side when using local tools for restarting the process the Docker orchestrator is not aware of the errors and can not make thoughtful decisions like relocating the container to a new instance or zone. + +

+ +### Code Example – Invoking Node.js directly without intermediate tools + +
+ +Dockerfile + +```dockerfile +FROM node:12-slim + +# The build logic comes here + +CMD ["node", "index.js"] +``` + +
+ +

+ +### Code Example Anti Pattern – Using a process manager + +
+ +Dockerfile + +```dockerfile +FROM node:12-slim + +# The build logic comes here + +CMD ["pm2-runtime", "indes.js"] +``` + +
\ No newline at end of file diff --git a/sections/docker/restart-and-replicate-processes.japanese.md b/sections/docker/restart-and-replicate-processes.japanese.md index 0e285320f..95e8e05c7 100644 --- a/sections/docker/restart-and-replicate-processes.japanese.md +++ b/sections/docker/restart-and-replicate-processes.japanese.md @@ -14,8 +14,7 @@ Kubernetes のような Docker ランタイムオーケストレータは、コ Dockerfile -``` - +```dockerfile FROM node:12-slim # ビルドロジックはこちら @@ -32,7 +31,7 @@ CMD ["node", "index.js"] Dockerfile -``` +```dockerfile FROM node:12-slim # ビルドロジックはこちら diff --git a/sections/docker/restart-and-replicate-processes.md b/sections/docker/restart-and-replicate-processes.md index eaf8be505..1fa50bdff 100644 --- a/sections/docker/restart-and-replicate-processes.md +++ b/sections/docker/restart-and-replicate-processes.md @@ -14,8 +14,7 @@ Docker runtime orchestrators like Kubernetes are really good at making container Dockerfile -``` - +```dockerfile FROM node:12-slim # The build logic comes here @@ -33,12 +32,12 @@ CMD ["node", "index.js"] Dockerfile -``` +```dockerfile FROM node:12-slim # The build logic comes here -CMD ["pm2-runtime", "indes.js"] +CMD ["pm2-runtime", "index.js"] ```
diff --git a/sections/docker/scan-images.basque.md b/sections/docker/scan-images.basque.md new file mode 100644 index 000000000..9e35cce5b --- /dev/null +++ b/sections/docker/scan-images.basque.md @@ -0,0 +1,30 @@ +# Eskaneatu irudi osoa ekoiztu aurretik + +

+ +### Azalpena + +Kodea eskaneatzea ahultasunak aurkitzeko ekintza baliotsua da, baina ez du mehatxu guztietatik babesten. Zergatik? Sistema eragilean ere badirelako ahultasunak, eta Shell, Tarball eta OpenSSL bezalako binarioak exekuta ditzakeelako aplikazioak. Gainera, erasogarriak diren menpekotasunak kodea eskaneatu ondoren gehitu daitezke (adibidez hornikuntza katearen erasoak). Hori dela eta, zuzenena da bukaerako irudia eskaneatzea zehazki ekoizpenera bidali aurretik. Ideia horrek E2E proben antza du, zati bakoitza modu isolatuan probatu ondoren, guztiak batutako paketea probatzea komeni da. 3 eskaner familia nagusi daude: tokiko/IEko binarioak, cachean ahultasunak dituzten datu base eta guzti; hodeiko zerbitzu gisa antolatutako eskanerrak; eta baliabide sorta bat, dockera bera konpilatu bitartean eskaneatzen duena. Lehenengo taldea da ezagunena eta normalean azkarrena. Merezi du [Trivvy](https://github.com/aquasecurity/trivy), [Anchore](https://github.com/anchore/anchore) eta [Snyk](https://support.snyk.io/hc/en-us/articles/360003946897-Container-security-overview) bezalako tresnak ikertzea. IE hornitzaile gehienek lekuko plugin bat proposatzen dute, eskaner horiekin elkarrekintza errazten dutenak. Kontuan izan behar da eskaner horiek eremu handiak hartzen dituztela, eta, beraz, emaitzak izaten dituztela ia eskaneatze guztietan. Aztertu ez ote den komeni atalase maila handi samarra ezartzea larrialdiak izatea ekiditeko. + +

+ +### Kode adibidea: eskaneatu Trivvyrekin + +
+ +Bash + +```console +$ sudo apt-get install rpm +$ wget https://github.com/aquasecurity/trivy/releases/download/{TRIVY_VERSION}/trivy_{TRIVY_VERSION}_Linux-64bit.deb +$ sudo dpkg -i trivy_{TRIVY_VERSION}_Linux-64bit.deb +$ trivy image [YOUR_IMAGE_NAME] +``` + +
+ +

+ +### Txosten adibidea: Docker eskanerraren emaitzak (Anchoren eskutik) + +![Txosten adibideak](../../assets/images/anchore-report.png "Docker eskanerraren txostena") diff --git a/sections/docker/scan-images.french.md b/sections/docker/scan-images.french.md new file mode 100644 index 000000000..aa9ad2504 --- /dev/null +++ b/sections/docker/scan-images.french.md @@ -0,0 +1,30 @@ +# Scan the entire image before production + +

+ +### One Paragraph Explainer + +Scanning the code for vulnerabilities is a valuable act but it doesn't cover all the potential threats. Why? Because vulnerabilities also exist on the OS level and the app might execute those binaries like Shell, Tarball, OpenSSL. Also, vulnerable dependencies might be injected after the code scan (i.e. supply chain attacks) - hence scanning the final image just before production is in order. This idea resembles E2E tests - after testing the various pieces in-isolation, it's valuable to finally check the assembled deliverable. There are 3 main scanner families: Local/CI binaries with a cached vulnerabilities DB, scanners as a service in the cloud and a niche of tools which scan during the docker build itself. The first group is the most popular and usually the fastest - Tools like [Trivvy](https://github.com/aquasecurity/trivy), [Anchore](https://github.com/anchore/anchore) and [Snyk](https://support.snyk.io/hc/en-us/articles/360003946897-Container-security-overview) are worth exploring. Most CI vendors provide a local plugin that facilitates the interaction with these scanners. It should be noted that these scanners cover a lot of ground and therefore will show findings in almost every scan - consider setting a high threshold bar to avoid getting overwhelmed + +

+ +### Code Example – Scanning with Trivvy + +
+ +Bash + +```console +$ sudo apt-get install rpm +$ wget https://github.com/aquasecurity/trivy/releases/download/{TRIVY_VERSION}/trivy_{TRIVY_VERSION}_Linux-64bit.deb +$ sudo dpkg -i trivy_{TRIVY_VERSION}_Linux-64bit.deb +$ trivy image [YOUR_IMAGE_NAME] +``` + +
+ +

+ +### Report Example – Docker scan results (By Anchore) + +![Report examples](../../assets/images/anchore-report.png "Docker scan report") \ No newline at end of file diff --git a/sections/docker/scan-images.japanese.md b/sections/docker/scan-images.japanese.md index 16a1db03a..c8b2dbbe2 100644 --- a/sections/docker/scan-images.japanese.md +++ b/sections/docker/scan-images.japanese.md @@ -14,11 +14,11 @@ Bash -``` -sudo apt-get install rpm +```console +$ sudo apt-get install rpm $ wget https://github.com/aquasecurity/trivy/releases/download/{TRIVY_VERSION}/trivy_{TRIVY_VERSION}_Linux-64bit.deb $ sudo dpkg -i trivy_{TRIVY_VERSION}_Linux-64bit.deb -trivy image [YOUR_IMAGE_NAME] +$ trivy image [YOUR_IMAGE_NAME] ```
@@ -27,4 +27,4 @@ trivy image [YOUR_IMAGE_NAME] ### レポート例 – Docker スキャン結果 (Anchore) -![Report examples](/assets/images/anchore-report.png "Docker scan report") +![Report examples](../../assets/images/anchore-report.png "Docker scan report") diff --git a/sections/docker/scan-images.md b/sections/docker/scan-images.md index 3e09f81a4..32ea896f5 100644 --- a/sections/docker/scan-images.md +++ b/sections/docker/scan-images.md @@ -14,11 +14,11 @@ Scanning the code for vulnerabilities is a valuable act but it doesn't cover all Bash -``` -sudo apt-get install rpm +```console +$ sudo apt-get install rpm $ wget https://github.com/aquasecurity/trivy/releases/download/{TRIVY_VERSION}/trivy_{TRIVY_VERSION}_Linux-64bit.deb $ sudo dpkg -i trivy_{TRIVY_VERSION}_Linux-64bit.deb -trivy image [YOUR_IMAGE_NAME] +$ trivy image [YOUR_IMAGE_NAME] ```
@@ -27,4 +27,4 @@ trivy image [YOUR_IMAGE_NAME] ### Report Example – Docker scan results (By Anchore) -![Report examples](/assets/images/anchore-report.png "Docker scan report") +![Report examples](../../assets/images/anchore-report.png "Docker scan report") diff --git a/sections/docker/smaller_base_images.basque.md b/sections/docker/smaller_base_images.basque.md new file mode 100644 index 000000000..1cb0dbcfa --- /dev/null +++ b/sections/docker/smaller_base_images.basque.md @@ -0,0 +1,10 @@ +# Hobetsi Docker oinarrizko irudi txikiagoak + +Docker irudi handiek ahultasun gehiago sor ditzakete eta baliabideen kontsumoa handitu. Askotan, exekutatzeko garaian instalatutako zenbait pakete ez dituzu behar konpilatzeko orduan. Zenbat eta irudi handiagoak argitaratu eta gorde, garestiagoa izango da eskalatzerako orduan. Gerta daiteke irudi txikiak diseinuz ez etortzea aldez aurretik instalatuta ohiko liburutegi arruntetan (adibidez, curl), modulu natiboak sortu edo arazketak egiteko erabilgarriak diren paketeak sortzeko beharrezkoak direnak. Alpine Linuxen irudien aldaerak erabiltzeak aztarna murriztarazi dezake, erabilitako baliabideei eta sistema guztietan dauden eraso bektoreei dagokienez. Node.jsren v14.4.0 Docker irudiak gutxi gora behera 345MBko tamaina du; Alpine bertsioak, aldiz, 39MB, hau da, ia 10 aldiz txikiagoa da. Aukera bikaina da ere Debianen oinarritutako aldaera arina (Slim), 38 MB besterik ez duena eta Node.js exekutatzeko behar diren gutxieneko paketeak dituena. + +### Blogeko aipua: "Zure zerbitzuen abiaratzea azkarragoa eta seguruagoa izan dadin Docker irudiak txikiagoak izatea nahi baduzu, probatu Alpine." + +[Nick Janetakis](https://nickjanetakis.com/blog/the-3-biggest-wins-when-using-alpine-as-a-base-docker-image)-en bloga + +> Gaur egun jakina da Dockerek Alpine maiz erabiltzen duela Dockeren irudi ofizialetarako. Mugimendu hori 2016ko hasieran hasi zen gutxi gora-behera. [...] +> Zerbitzari berri batean Docker irudiak argitaratzean, espero dezakezu hasierako argitalpena pixka bat azkarragoa izatea. Sarea gero eta motelagoa izan, ezberdintasuna orduan eta handiagoa izango da. [...] Tamaina txikiaren beste abantailetako bat da erasotze azala txikiagoa dela. Zure sisteman pakete eta liburutegi asko ez dagoenean, oso gauza gutxi daude gaizki irten daitezkeenak. diff --git a/sections/docker/smaller_base_images.french.md b/sections/docker/smaller_base_images.french.md new file mode 100644 index 000000000..591011d34 --- /dev/null +++ b/sections/docker/smaller_base_images.french.md @@ -0,0 +1,12 @@ + +Large Docker images can lead to higher exposure to vulnerabilities and increased resource consumption. Often you don't need certain packages installed at runtime that are needed for building. +Pulling and storing larger images will become more expensive at scale, when dealing with larger images. By design minimal images may not come with common libraries needed for building native modules or packages useful for debugging (e.g. curl) pre-installed. +Using the Alpine Linux variants of images can lead to a reduced footprint in terms of resources used and the amount of attack vectors present in fully-featured systems. The Node.js v14.4.0 Docker image is ~345MB in size versus ~39MB for the Alpine version, which is almost 10x smaller. +A Slim variant based on Debian, which is only 38MB in size and contains the minimal packages needed to run Node.js, is also a great choice. + +### Blog Quote: "If you want to shrink your Docker images, have your services start faster and be more secure then try Alpine out." + +From [Nick Janetakis' blog](https://nickjanetakis.com/blog/the-3-biggest-wins-when-using-alpine-as-a-base-docker-image) + +> It’s no secret by now that Docker is heavily using Alpine as a base image for official Docker images. This movement started near the beginning of 2016. [...] + When pulling down new Docker images onto a fresh server, you can expect the initial pull to be quite a bit faster on Alpine. The slower your network is, the bigger the difference it will be. [...] Another perk of being much smaller in size is that the surface area to be attacked is much less. When there’s not a lot of packages and libraries on your system, there’s very little that can go wrong. \ No newline at end of file diff --git a/sections/docker/smaller_base_images.md b/sections/docker/smaller_base_images.md index d394954d3..fc5a951b7 100644 --- a/sections/docker/smaller_base_images.md +++ b/sections/docker/smaller_base_images.md @@ -1,4 +1,3 @@ -# Prefer smaller Docker base images Large Docker images can lead to higher exposure to vulnerabilities and increased resource consumption. Often you don't need certain packages installed at runtime that are needed for building. Pulling and storing larger images will become more expensive at scale, when dealing with larger images. By design minimal images may not come with common libraries needed for building native modules or packages useful for debugging (e.g. curl) pre-installed. diff --git a/sections/docker/use-cache-for-shorter-build-time.basque.md b/sections/docker/use-cache-for-shorter-build-time.basque.md new file mode 100644 index 000000000..b7d862dcc --- /dev/null +++ b/sections/docker/use-cache-for-shorter-build-time.basque.md @@ -0,0 +1,120 @@ +# Baliatu cachea konpilazio denborak murrizteko + +## Azalpena + +Docker irudiak geruzen konbinazioak dira. Izan ere, zure Dockerfile fitxategiko agindu bakoitzak geruza bat sortzen du. Dockeren daemonak konpilazioen arteko geruza horiek erabil ditzake, aginduak berdinak badira edo `COPY` edo `ADD` fitxategiak berdinak badira. ⚠️ Cachea ezin bada geruza jakin batean erabili, ondorengo geruza guztiak ere ezgaituak izango dira. Horrexegatik, ordena garrantzitsua da. Zure Dockerfile fitxategia zuzen diseinatzea ezinbestekoa da, zure konpilazioan atal mugikorren kopurua murrizteko; gutxien eguneratzen diren aginduak goialdean egon beharko lirateke, eta etengabe aldatzen ari diren aginduak (aplikazioaren kodea, esaterako), berriz, behe aldean. +Baita ere, garrantzitsua da jakitea operazio luzeak abiarazten dituzten aginduek puntu gorenaren inguruan egon beharko luketeela, horrela bermatuko delako bakarrik beharrezkoak direnean gertatzea (docker irudia eraikitzen duzun bakoitzean aldatzen ez badira behintzat). Cachetik Docker irudi bat berreraikitzea ia-ia berehalakoa izan daiteke era egokian eginez gero. + +![Dockeren geruzak](../../assets/images/docker_layers_schema.png) + +- [Digging into Docker layers](https://medium.com/@jessgreb01/digging-into-docker-layers-c22f948ed612)-etik hartutako irudia, jessgreb01-i esker\* + +### Arauak + +#### Ekidin une oro aldatzen den Avoid LABEL (etiketa) + +Zure Dockerfile fitxategiaren hasieran konpilazio zenbakia duen etiketaren bat badaukazu, cachea baliogabetua izango da konpilazio bakoitzean + +```Dockerfile +#Fitxategiaren hasiea +FROM node:10.22.0-alpine3.11 as builder + +# Ez egin hau hemen! +LABEL build_number="483" + +#... Dockerfile fitxategiaren gainontzeko guztia +``` + +#### Eduki .dockerignore fitxategi egokia + +[**Begiratu: docker ignoreren garrantzia**](./docker-ignore.basque.md) + +Cachearen logika hondatu dezaketen fitxategien kopia ekiditen dute Docker ignorek, adibidez proben emaitzen txostenak, erregistroak edota aldi baterako fitxategiak. + +#### Instalatu lehenik "sistemaren" paketeak + +Gomendagarria da erabiltzen dituzun sistema pakete guztiak dituen docker irudi base bat sortzea. **Benetan** `apt`,`yum`,`apk` edo antzerako komandoak erabiliz paketeak instalatzeko beharra baduzu, horiek izan beharko lirateke zure lehenengo aginduak. Ez duzu make, gcc edo g ++ berriro instalatu nahi izango zure node aplikazioa konpilatzen duzun bakoitzean. **Ez instalatu paketea erosoa delako soilik, ekoizpen aplikazio bat da.** + +#### Lehendabizi, GEHITU soilik zure package.json eta lockfile + +```Dockerfile +COPY "package.json" "package-lock.json" "./" +RUN npm ci +``` + +lockfile eta package.json gutxiagotan aldatzen dira. Beraiek lehendabizi kopiatzeak `npm install` etapa cachean utziko du, horrek denbora baliotsua aurrezten du. + +### Ondoren kopiatu zure fitxategiak eta exekutatu konpilazio etapa (beharrezkoa bada) + +```Dockerfile +COPY . . +RUN npm run build +``` + +## Adibideak + +### Onarrizko adibidea sistema eragileko menpekotasunak behar dituzten node_modulesekin + +```Dockerfile +#Sortu node irudi bertsioaren ezizena +FROM node:10.22.0-alpine3.11 as builder + +RUN apk add --no-cache \ + build-base \ + gcc \ + g++ \ + make + +USER node +WORKDIR /app +COPY "package.json" "package-lock.json" "./" +RUN npm ci --production +COPY . "./" + + +FROM node as app + +USER node +WORKDIR /app +COPY --from=builder /app/ "./" +RUN npm prune --production + +CMD ["node", "dist/server.js"] +``` + +### Konpilazio etaparen adibidea (esaterako typescript erabiltzerakoan) + +```Dockerfile +#Sortu node irudi bertsioaren ezizena +FROM node:10.22.0-alpine3.11 as builder + +RUN apk add --no-cache \ + build-base \ + gcc \ + g++ \ + make + +USER node +WORKDIR /app +COPY "package.json" "package-lock.json" "./" +RUN npm ci +COPY . . +RUN npm run build + + +FROM node as app + +USER node +WORKDIR /app +# Behar ditugun fitxategiak bakarrik kopiatu +COPY --from=builder /app/node_modules node_modules +COPY --from=builder /app/package.json . +COPY --from=builder /app/dist dist +RUN npm prune --production + +CMD ["node", "dist/server.js"] +``` + +## Esteka erabilgarriak + +Dockeren dokumentazioa: https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#leverage-build-cache diff --git a/sections/docker/use-cache-for-shorter-build-time.french.md b/sections/docker/use-cache-for-shorter-build-time.french.md new file mode 100644 index 000000000..e69d3841d --- /dev/null +++ b/sections/docker/use-cache-for-shorter-build-time.french.md @@ -0,0 +1,119 @@ +# Leverage caching to reduce build times + +## One paragraph explainer + +Docker images are a combination of layers, each instruction in your Dockerfile creates a layer. The docker daemon can reuse those layers between builds if the instructions are identical or in the case of a `COPY` or `ADD` files used are identical. ⚠️ If the cache can't be used for a particular layer all the subsequent layers will be invalidated too. That's why order is important. It is crucial to layout your Dockerfile correctly to reduce the number of moving parts in your build; the less updated instructions should be at the top and the ones constantly changing (like app code) should be at the bottom. It's also important to think that instructions that trigger long operation should be close to the top to ensure they happen only when really necessary (unless it changes every time you build your docker image). Rebuilding a whole docker image from cache can be nearly instantaneous if done correctly. + +![Docker layers](../../assets/images/docker_layers_schema.png) + +* Image taken from [Digging into Docker layers](https://medium.com/@jessgreb01/digging-into-docker-layers-c22f948ed612) by jessgreb01* + +### Rules + +#### Avoid LABEL that change all the time + +If you have a label containing the build number at the top of your Dockerfile, the cache will be invalidated at every build + +```Dockerfile +#Beginning of the file +FROM node:10.22.0-alpine3.11 as builder + +# Don't do that here! +LABEL build_number="483" + +#... Rest of the Dockerfile +``` + +#### Have a good .dockerignore file + +[**See: On the importance of docker ignore**](./docker-ignore.md) + +The docker ignore avoids copying files that could bust our cache logic, like tests results reports, logs or temporary files. + +#### Install "system" packages first + +It is recommended to create a base docker image that has all the system packages you use. If you **really** need to install packages using `apt`,`yum`,`apk` or the likes, this should be one of the first instructions. You don't want to reinstall make,gcc or g++ every time you build your node app. +**Do not install package only for convenience, this is a production app.** + +#### First, only ADD your package.json and your lockfile + +```Dockerfile +COPY "package.json" "package-lock.json" "./" +RUN npm ci +``` + +The lockfile and the package.json change less often. Copying them first will keep the `npm install` step in the cache, this saves precious time. + +### Then copy your files and run build step (if needed) + +```Dockerfile +COPY . . +RUN npm run build +``` + +## Examples + +### Basic Example with node_modules needing OS dependencies +```Dockerfile +#Create node image version alias +FROM node:10.22.0-alpine3.11 as builder + +RUN apk add --no-cache \ + build-base \ + gcc \ + g++ \ + make + +USER node +WORKDIR /app +COPY "package.json" "package-lock.json" "./" +RUN npm ci --production +COPY . "./" + + +FROM node as app + +USER node +WORKDIR /app +COPY --from=builder /app/ "./" +RUN npm prune --production + +CMD ["node", "dist/server.js"] +``` + + +### Example with a build step (when using typescript for example) +```Dockerfile +#Create node image version alias +FROM node:10.22.0-alpine3.11 as builder + +RUN apk add --no-cache \ + build-base \ + gcc \ + g++ \ + make + +USER node +WORKDIR /app +COPY "package.json" "package-lock.json" "./" +RUN npm ci +COPY . . +RUN npm run build + + +FROM node as app + +USER node +WORKDIR /app +# Only copying the files that we need +COPY --from=builder /app/node_modules node_modules +COPY --from=builder /app/package.json . +COPY --from=builder /app/dist dist +RUN npm prune --production + +CMD ["node", "dist/server.js"] +``` + +## Useful links + +Docker docs: https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#leverage-build-cache \ No newline at end of file diff --git a/sections/docker/use-cache-for-shorter-build-time.japanese.md b/sections/docker/use-cache-for-shorter-build-time.japanese.md index fee9bbbe4..5a6c9a899 100644 --- a/sections/docker/use-cache-for-shorter-build-time.japanese.md +++ b/sections/docker/use-cache-for-shorter-build-time.japanese.md @@ -4,7 +4,7 @@ Docker イメージはレイヤーの組み合わせであり、Dockerfile 内の各指示はそれぞれレイヤーを作成します。もし指示が同じであるか、`COPY` や `ADD` の利用が同じであれば、docker デーモンはビルド間でそれらのレイヤーを再利用することができます。⚠️ キャッシュが特定のレイヤーで利用できなかった場合は、それ以降のすべてのレイヤーも無効になります。そのため、順番が重要なのです。Dockerfile を正しくレイアウトすることは、ビルドにおいて可変となっている部分の数を減らすために非常に重要です; あまり更新されない処理は Dockerfile の上の方に記述し、更新が多い処理(アプリケーションのコードなど)は下の方に記述するべきです。また、時間のかかるオペレーションをトリガーする指示は、(docker イメージをビルドするたびに変更されない限り)本当に必要なときにのみ実行されるように、上部に近い位置に配置するべきです。正しく行えば、ほぼ瞬時にキャッシュから Docker イメージ全体をリビルドすることができます。 -![Docker layers](/assets/images/docker_layers_schema.png) +![Docker layers](../../assets/images/docker_layers_schema.png) * jessgreb01 による [Digging into Docker layers](https://medium.com/@jessgreb01/digging-into-docker-layers-c22f948ed612) から画像引用* @@ -26,7 +26,7 @@ LABEL build_number="483" #### 良い .dockerignore ファイルを持つ -[**参照: docker ignore の重要性について**](/sections/docker/docker-ignore.md) +[**参照: docker ignore の重要性について**](./docker-ignore.md) docker ignore ファイルは、テスト結果レポートやログ、一時ファイルなど、キャッシュのロジックを壊す可能性のあるファイルのコピーを回避します。 @@ -71,7 +71,9 @@ COPY "package.json" "package-lock.json" "./" RUN npm ci --production COPY . "./" + FROM node as app + USER node WORKDIR /app COPY --from=builder /app/ "./" @@ -100,7 +102,9 @@ RUN npm ci COPY . . RUN npm run build + FROM node as app + USER node WORKDIR /app # 必要なファイルのみをコピーする diff --git a/sections/docker/use-cache-for-shorter-build-time.md b/sections/docker/use-cache-for-shorter-build-time.md index 66279a7b9..c7556b35b 100644 --- a/sections/docker/use-cache-for-shorter-build-time.md +++ b/sections/docker/use-cache-for-shorter-build-time.md @@ -4,7 +4,7 @@ Docker images are a combination of layers, each instruction in your Dockerfile creates a layer. The docker daemon can reuse those layers between builds if the instructions are identical or in the case of a `COPY` or `ADD` files used are identical. ⚠️ If the cache can't be used for a particular layer all the subsequent layers will be invalidated too. That's why order is important. It is crucial to layout your Dockerfile correctly to reduce the number of moving parts in your build; the less updated instructions should be at the top and the ones constantly changing (like app code) should be at the bottom. It's also important to think that instructions that trigger long operation should be close to the top to ensure they happen only when really necessary (unless it changes every time you build your docker image). Rebuilding a whole docker image from cache can be nearly instantaneous if done correctly. -![Docker layers](/assets/images/docker_layers_schema.png) +![Docker layers](../../assets/images/docker_layers_schema.png) * Image taken from [Digging into Docker layers](https://medium.com/@jessgreb01/digging-into-docker-layers-c22f948ed612) by jessgreb01* @@ -26,7 +26,7 @@ LABEL build_number="483" #### Have a good .dockerignore file -[**See: On the importance of docker ignore**](/sections/docker/docker-ignore.md) +[**See: On the importance of docker ignore**](./docker-ignore.md) The docker ignore avoids copying files that could bust our cache logic, like tests results reports, logs or temporary files. @@ -70,7 +70,9 @@ COPY "package.json" "package-lock.json" "./" RUN npm ci --production COPY . "./" + FROM node as app + USER node WORKDIR /app COPY --from=builder /app/ "./" @@ -98,7 +100,9 @@ RUN npm ci COPY . . RUN npm run build + FROM node as app + USER node WORKDIR /app # Only copying the files that we need diff --git a/sections/drafts/readme-general-toc-1.md b/sections/drafts/readme-general-toc-1.md index 463cedaed..3d13f35a9 100644 --- a/sections/drafts/readme-general-toc-1.md +++ b/sections/drafts/readme-general-toc-1.md @@ -1,12 +1,12 @@ - +

- Node.js Best Practices + Node.js Best Practices

-53 items Last update: 7 days ago Updated for Node v.8.4 +53 items Last update: 7 days ago Updated for Node v.8.4 - + # Welcome to Node.js Best Practices @@ -31,7 +31,7 @@ Welcome to the biggest compilation of Node.js best practices. The content below **Otherwise:** Developing a new feature with a change to few objects demands to evaluate how this changes might affect dozends of dependants and ach deployment becomes a fear. -🔗 [**Read More: Structure by feature*](/sections/errorhandling/asyncawait.md) +🔗 [**Read More: Structure by feature*](../errorhandling/asyncerrorhandling.md)

@@ -41,7 +41,7 @@ Welcome to the biggest compilation of Node.js best practices. The content below **Otherwise:** Application can be accessed by Express only and require to create complex testing mocks -🔗 [**Read More: Structure by feature*](/sections/errorhandling/asyncawait.md) +🔗 [**Read More: Structure by feature*](../errorhandling/asyncerrorhandling.md)

@@ -51,7 +51,7 @@ Welcome to the biggest compilation of Node.js best practices. The content below **Otherwise:** You end-up with a blackbox that is hard to reason about, then you start re-writing all logging statements to add additional information -🔗 [**Read More: Structure by feature*](/sections/errorhandling/asyncawait.md) +🔗 [**Read More: Structure by feature*](../errorhandling/asyncerrorhandling.md)


@@ -71,7 +71,7 @@ Welcome to the biggest compilation of Node.js best practices. The content below * **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 -🔗 [**Use async-await for async error handling**](/sections/errorhandling/asyncawait.md) +🔗 [**Use async-await for async error handling**](../errorhandling/asyncerrorhandling.md)


diff --git a/sections/drafts/readme-general-toc-2.md b/sections/drafts/readme-general-toc-2.md index fe3c5af07..586239afe 100644 --- a/sections/drafts/readme-general-toc-2.md +++ b/sections/drafts/readme-general-toc-2.md @@ -1,8 +1,8 @@ # Node.js Best Practices -53 items Last update: 7 days ago Updated for Node v.8.4 +53 items Last update: 7 days ago Updated for Node v.8.4 -![Node.js Best Practices](assets/images/banner-1.png) +![Node.js Best Practices](../../assets/images/banner-1.png) # Welcome to Node.js Best Practices @@ -25,7 +25,7 @@ Welcome to the biggest compilation of Node.js best practices. The content below **Otherwise:** Developing a new feature with a change to few objects demands to evaluate how this changes might affect dozends of dependants and ach deployment becomes a fear. -🔗 [**Read More: Structure by feature*](/sections/errorhandling/asyncawait.md) +🔗 [**Read More: Structure by feature*](../errorhandling/asyncerrorhandling.md)
@@ -35,7 +35,7 @@ Welcome to the biggest compilation of Node.js best practices. The content below **Otherwise:** Application can be accessed by Express only and require to create complex testing mocks -🔗 [**Read More: Structure by feature*](/sections/errorhandling/asyncawait.md) +🔗 [**Read More: Structure by feature*](../errorhandling/asyncerrorhandling.md)

@@ -45,7 +45,7 @@ Welcome to the biggest compilation of Node.js best practices. The content below **Otherwise:** You end-up with a blackbox that is hard to reason about, then you start re-writing all logging statements to add additional information -🔗 [**Read More: Structure by feature*](/sections/errorhandling/asyncawait.md) +🔗 [**Read More: Structure by feature*](../errorhandling/asyncerrorhandling.md)


# `Code Style Practices` @@ -61,7 +61,7 @@ Welcome to the biggest compilation of Node.js best practices. The content below **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 -🔗 [**Use async-await for async error handling**](/sections/errorhandling/asyncawait.md) +🔗 [**Use async-await for async error handling**](../errorhandling/asyncerrorhandling.md) diff --git a/sections/drafts/readme-general-toc-3.md b/sections/drafts/readme-general-toc-3.md index 6bb3f9c60..1a11e5745 100644 --- a/sections/drafts/readme-general-toc-3.md +++ b/sections/drafts/readme-general-toc-3.md @@ -1,12 +1,12 @@ - +

- Node.js Best Practices + Node.js Best Practices

-53 items Last update: 7 days ago Updated for Node v.8.4 +53 items Last update: 7 days ago Updated for Node v.8.4 - + # Welcome to Node.js Best Practices @@ -37,7 +37,7 @@ Welcome to the biggest compilation of Node.js best practices, based on our check **Otherwise:** Application can be accessed by Express only and require to create complex testing mocks -🔗 [**Read More: Structure by feature*](/sections/errorhandling/asyncawait.md) +🔗 [**Read More: Structure by feature*](../errorhandling/asyncerrorhandling.md)

@@ -48,7 +48,7 @@ Welcome to the biggest compilation of Node.js best practices, based on our check **Otherwise:** You end-up with a blackbox that is hard to reason about, then you start re-writing all logging statements to add additional information -🔗 [**Read More: Structure by feature*](/sections/errorhandling/asyncawait.md) +🔗 [**Read More: Structure by feature*](../errorhandling/asyncerrorhandling.md)


@@ -65,7 +65,7 @@ Welcome to the biggest compilation of Node.js best practices, based on our check **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 -🔗 [**Use async-await for async error handling**](/sections/errorhandling/asyncawait.md) +🔗 [**Use async-await for async error handling**](../errorhandling/asyncerrorhandling.md) diff --git a/sections/drafts/readme-general-toc-4.md b/sections/drafts/readme-general-toc-4.md index 19f42ea1c..3db7b68a7 100644 --- a/sections/drafts/readme-general-toc-4.md +++ b/sections/drafts/readme-general-toc-4.md @@ -1,12 +1,12 @@ - +

- Node.js Best Practices + Node.js Best Practices

-53 items Last update: 7 days ago Updated for Node v.8.4 +53 items Last update: 7 days ago Updated for Node v.8.4 - + # Welcome to Node.js Best Practices @@ -23,33 +23,33 @@ Welcome to the biggest compilation of Node.js best practices, based on our check

# `Project Setup Practices` -## ![](assets/images/checkbox-sm.png) 1. Structure your solution by feature ('microservices') +## ![](../../assets/images/checkbox-sm.png) 1. Structure your solution by feature ('microservices') -**TL&DR:** The worst large applications pitfal is a huge code base where hundreds of dependencies slow down developers as try to incorporate new features. Partioning into small units ensures that each unit is kept simple and very easy to maintain. This strategy pushes the complexity to the higher level - designing the cross-component interactions. +**TL&DR:** The worst large applications pitfal is a huge code base where hundreds of dependencies slow down developers as try to incorporate new features. Partitioning into small units ensures that each unit is kept simple and very easy to maintain. This strategy pushes the complexity to the higher level - designing the cross-component interactions. **Otherwise:** Developing a new feature with a change to few objects demands to evaluate how this changes might affect dozends of dependants and ach deployment becomes a fear. -🔗 [**Read More: Structure by feature*](/sections/errorhandling/asyncawait.md) +🔗 [**Read More: Structure by feature*](../errorhandling/asyncerrorhandling.md)

-## ![](assets/images/checkbox-sm.png) 2. Layer your app, keep Express within its boundaries +## ![](../../assets/images/checkbox-sm.png) 2. Layer your app, keep Express within its boundaries **TL&DR:** It's very common to see Express API passes the express objects (req, res) to business logic and data layers, sometimes even to every function - this makes your application depedant on and accessible by Express only. What if your code should be reached by testing console or CRON job? instead create your own context object with cross-cutting-concern properties like the user roles and inject into other layers, or use 'thread-level variables' libraries like continuation local storage **Otherwise:** Application can be accesses by Express only and require to create complex testing mocks -🔗 [**Read More: Structure by feature*](/sections/errorhandling/asyncawait.md) +🔗 [**Read More: Structure by feature*](../errorhandling/asyncerrorhandling.md)

-## ![](assets/images/checkbox-sm.png) 3. Configure ESLint with node-specific plugins +## ![](../../assets/images/checkbox-sm.png) 3. Configure ESLint with node-specific plugins **TL&DR:** Monitoring is a game of finding out issues before our 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 sug **Otherwise:** You end-up with a blackbox that is hard to reason about, then you start re-writing all logging statements to add additional information -🔗 [**Read More: Structure by feature*](/sections/errorhandling/asyncawait.md) +🔗 [**Read More: Structure by feature*](../errorhandling/asyncerrorhandling.md) @@ -60,45 +60,45 @@ Welcome to the biggest compilation of Node.js best practices, based on our check


# `Code Style Practices` -## ![](assets/images/checkbox-sm.png) 1. Use async-await +## ![](../../assets/images/checkbox-sm.png) 1. Use async-await **TL&DR:** Monitoring is a game of finding out issues before our 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 sug **Otherwise:** You end-up with a blackbox that is hard to reason about, then you start re-writing all logging statements to add additional information -🔗 [**Read More: Structure by feature*](/sections/errorhandling/asyncawait.md) +🔗 [**Read More: Structure by feature*](../errorhandling/asyncerrorhandling.md)

-## ![](assets/images/checkbox-sm.png) 2. Break into small classes or objects +## ![](../../assets/images/checkbox-sm.png) 2. Break into small classes or objects **TL&DR:** Monitoring is a game of finding out issues before our 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 sug **Otherwise:** You end-up with a blackbox that is hard to reason about, then you start re-writing all logging statements to add additional information -🔗 [**Read More: Structure by feature*](/sections/errorhandling/asyncawait.md) +🔗 [**Read More: Structure by feature*](../errorhandling/asyncerrorhandling.md)


# `Error Handling Practices`

⬆ Return to top

-## Use async-await for async error handling +## Use async-await 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 instead a reputable promise library or async-await which provides much 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 -🔗 [**Use async-await for async error handling**](/sections/errorhandling/asyncawait.md) +🔗 [**Use async-await for async error handling**](../errorhandling/asyncerrorhandling.md)

-## Use async-await for async error handling +## Use async-await 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 instead a reputable promise library or async-await which provides much 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 -🔗 [**Use async-await for async error handling**](/sections/errorhandling/asyncawait.md) +🔗 [**Use async-await for async error handling**](../errorhandling/asyncerrorhandling.md) diff --git a/sections/errorhandling/apmproducts.basque.md b/sections/errorhandling/apmproducts.basque.md index 50b8642ab..0ea3a2126 100644 --- a/sections/errorhandling/apmproducts.basque.md +++ b/sections/errorhandling/apmproducts.basque.md @@ -1,12 +1,12 @@ # Aurkitu erroreak eta jardunik gabeko uneak APM produktuak erabiliz -### Azalpen paragrafoa +### Azalpena -Salbuespena != Errorea. Erroreen kudeaketa tradizionalak kodearekin erlazionatutako arazotzat hartzen ditu salbuespenak, baina aplikazioen erroreak formularioko kode bide motelen, APIen jardunik gabeko uneen eta baliabide konputazionalen gabezien ondorio izan daitezke. Horra non APM produktuak oso erabilgarriak diren, 'lurperatutako' askotariko gaiak modu proaktiboan detektatzeko aukera ematen baitute gutxieneko konfigurazioarekin. APM produktuen ohiko funtzionalitateen artean daude, adibidez, HTTP APIak erroreak bidaltzen dituenean alerta jotzea, APIaren erantzunaren denbora aurretik zehaztutako denbora muga baino luzeagoa denean antzematea, ‘kode usainak’ hautematea, monitorizazio zerbitzariaren baliabideentzako funtzionalitateak, operazio inteligentziadun panelak (dashboard) IT metrikekin eta beste funtzionalitate batzuk oso erabilgarriak direnak. Hornitzaile gehienek dohaineko plana eskaintzen dute. +Salbuespena != Errorea. Erroreen kudeaketa tradizionalak kodearekin erlazionatutako arazotzat hartzen ditu salbuespenak, baina aplikazioen erroreak formularioko kode bide motelen, APIen jardunik gabeko uneen eta baliabide konputazionalen gabezien ondorio izan daitezke. Horra non APM produktuak oso erabilgarriak diren, "lurperatutako" askotariko gaiak modu proaktiboan detektatzeko aukera ematen baitute gutxieneko konfigurazioarekin. APM produktuen ohiko funtzionalitateen artean daude, adibidez, HTTP APIak erroreak bidaltzen dituenean alerta jotzea, APIaren erantzunaren denbora aurretik zehaztutako denbora muga baino luzeagoa denean antzematea, ‘kode usainak’ hautematea, monitorizazio zerbitzariaren baliabideentzako funtzionalitateak, operazio inteligentziadun panelak (dashboard) IT metrikekin eta beste funtzionalitate batzuk oso erabilgarriak direnak. Hornitzaile gehienek dohaineko plana eskaintzen dute ### Wikipedia APMri buruz -Informazioaren teknologien eta sistemen kudeaketaren alorretan, Application Performance Management (APM) software aplikazioen errendimendu eta erabilgarritasunaren monitorizazio eta kudeaketa da. APM aplikazioen errendimendu arazo konplexuak atzeman eta diagnostikatzen saiatzen da, esperotako zerbitzu maila mantentzeko. APM "IT metrikak negozioaren esanahira ([hau da,] balioa)" itzultzea da. Produktu eta segmentu nagusiak. APM "IT metrikak negozioaren esanahira ([hau da,] balioa)" itzultzea da. Produktu eta segmentu nagusiak. +Informazioaren teknologien eta sistemen kudeaketaren alorretan, Application Performance Management (APM) software aplikazioen errendimendu eta erabilgarritasunaren monitorizazio eta kudeaketa da. APM aplikazioen errendimendu arazo konplexuak atzeman eta diagnostikatzen saiatzen da, esperotako zerbitzu maila mantentzeko. APM "IT metrikak negozioaren esanahira ([esaterako] balioa)" itzultzea da. Produktu eta segmentu nagusiak. APM "IT metrikak negozioaren esanahira ([esaterako] balioa)" itzultzea da. Produktu eta segmentu nagusiak ### APM merkatua ulertzen @@ -14,14 +14,14 @@ APM produktuek 3 segmentu nagusi dituzte: 1. Webgune edo APIen monitorizazioa, martxan egondako denbora eta errendimuendua HTTP eskaeren bidez etengabe monitorizatzen dituzten kanpo zerbitzuak. Minutu gutxi batzuetan ezar daiteke. Hurrengo hauek dira aukeratutako lehiakide batzuk: [Pingdom](https://www.pingdom.com/), [Uptime Robot](https://uptimerobot.com/), eta [New Relic](https://newrelic.com/application-monitoring) -2. Kodearen instrumentazioa, kode motelaren atzematea, salbuespenen estadistikak, errendimenduaren monitorizazioa eta holako beste funtzionalitate batzuk erabiltzeko agente bat aplikazioan txertatzea eskatzen duen produktu familia da. Hurrengo hauek dira aukeratutako lehiakide batzuk: New Relic, App Dynamics +2. Kodearen instrumentazioa, kode motelaren atzematea, salbuespenen estatistikak, errendimenduaren monitorizazioa eta holako beste funtzionalitate batzuk erabiltzeko agente bat aplikazioan txertatzea eskatzen duen produktu familia da. Hurrengo hauek dira aukeratutako lehiakide batzuk: New Relic, App Dynamics -3. Adimen operatiboaren panela produktuen linea bat da, operazio taldeari metrika eta eduki aukeratuak eskaintzen dizkiona eta aplikazioaren errendimendua zein den jakitera behartzen duena. Horrek informazio iturri anitz (aplikazioen erregistroak, DB erregistroak, zerbitzarien erregistroa, etab.) eta aurrez aurreko arbelaren diseinua batzea eskatzen du. Hurrengo hauek dira aukeratutako lehiakide batzuk: [Datadog](https://www.datadoghq.com/), [Splunk](https://www.splunk.com/), [Zabbix](https://www.zabbix.com/) +3. Adimen operatiboaren panela produktuen linea bat da, operazio taldeari metrika eta eduki aukeratuak eskaintzen dizkiona eta aplikazioaren errendimendua zein den jakitera behartzen duena. Horrek informazio iturri anitz (aplikazioen erregistroak, DB erregistroak, zerbitzarien erregistroa, etab.) eta aurrez aurreko arbelaren diseinua batzea eskatzen du. Hurrengo hauek dira aukeratutako lehiakide batzuk: [Datadog](https://www.datadoghq.com/), [Splunk](https://www.splunk.com/), [Zabbix](https://www.zabbix.com/) ### Adibidea: UpTimeRobot.Com: webguneak monitorizatzeko panela -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/uptimerobot.jpg "Webgune monitorizazio aurreko panela") +![alt text](../../assets/images/uptimerobot.jpg "Webgune monitorizazio aurreko panela") ### Adibidea: AppDynamics.Com: hasieratik amaierarainoko monitorizazioa kode instrumentazioarekin konbinatutakoa -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/app-dynamics-dashboard.png "kode instrumentazioarekin konbinatutako hasieratik amaierarainoko monitorizazioa") +![alt text](../../assets/images/app-dynamics-dashboard.png "kode instrumentazioarekin konbinatutako hasieratik amaierarainoko monitorizazioa") diff --git a/sections/errorhandling/apmproducts.brazilian-portuguese.md b/sections/errorhandling/apmproducts.brazilian-portuguese.md index 1e7b824cb..459e50f10 100644 --- a/sections/errorhandling/apmproducts.brazilian-portuguese.md +++ b/sections/errorhandling/apmproducts.brazilian-portuguese.md @@ -22,7 +22,7 @@ Os produtos APM constituem 3 segmentos principais: ### Exemplo: UpTimeRobot.Com - Painel de monitoramento de site -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/uptimerobot.jpg "Painel de monitoramento de sites") +![alt text](../../assets/images/uptimerobot.jpg "Painel de monitoramento de sites") ### Example: AppDynamics.Com – monitoramento de ponta a ponta combinado com instrumentação de código -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/app-dynamics-dashboard.png "monitoramento de ponta a ponta combinado com instrumentação de código") +![alt text](../../assets/images/app-dynamics-dashboard.png "monitoramento de ponta a ponta combinado com instrumentação de código") diff --git a/sections/errorhandling/apmproducts.chinese.md b/sections/errorhandling/apmproducts.chinese.md index 8803f2791..0777b7359 100644 --- a/sections/errorhandling/apmproducts.chinese.md +++ b/sections/errorhandling/apmproducts.chinese.md @@ -21,7 +21,7 @@ APM 产品由3个主要部分构成: ### 示例: UpTimeRobot.Com – 网站监控仪表板 -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/uptimerobot.jpg "Website monitoring dashboard") +![alt text](../../assets/images/uptimerobot.jpg "Website monitoring dashboard") ### 示例: AppDynamics.Com – 与代码检测结合的端到端监视 -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/app-dynamics-dashboard.png "end to end monitoring combined with code instrumentation") +![alt text](../../assets/images/app-dynamics-dashboard.png "end to end monitoring combined with code instrumentation") diff --git a/sections/errorhandling/apmproducts.french.md b/sections/errorhandling/apmproducts.french.md new file mode 100644 index 000000000..bfe5f5916 --- /dev/null +++ b/sections/errorhandling/apmproducts.french.md @@ -0,0 +1,28 @@ +# Découvrez les erreurs et les indisponibilités à l'aide des produits de gestion de la performance applicative + + +### Un paragraphe d'explication + +Exception != Erreur. Le traitement traditionnel des erreurs suppose l'existence d'une exception en raison d'un problème lié au code, mais les erreurs d'application peuvent se présenter sous la forme de parcours de code lents, d'indisponibilité de l'API, de manque de ressources de calcul, etc. C’est là que les produits de gestion de la performance applicative (En anglais Application Performance Management : APM) sont utiles car ils permettent de détecter de manière proactive une grande variété de problèmes « cachés » avec une configuration minimale. Parmi les caractéristiques communes des produits APM, on trouve par exemple les alertes lorsque l'API HTTP renvoie des erreurs, la détection lorsque le temps de réponse de l'API tombe en dessous d'un certain seuil, la détection des « [codes smells](https://fr.wikipedia.org/wiki/Code_smell) », les fonctionnalités de surveillance des ressources du serveur, le tableau de bord de l'intelligence opérationnelle avec des mesures informatiques et plusieurs autres fonctionnalités utiles. La plupart des fournisseurs proposent un forfait gratuit. + +### APM sur Wikipédia + +Dans les domaines des technologies de l'information et de la gestion des systèmes, « Application Performance Management » (APM) est la surveillance et la gestion des performances et de la disponibilité des applications logicielles. APM s'efforce de détecter et de diagnostiquer les problèmes de performances des applications complexes pour maintenir un niveau de service souhaité. APM est « la traduction des métriques informatiques en signification métier (c'est-à-dire en valeur) ». + +### Comprendre le marché APM + +Les produits APM regroupent 3 pôles principaux : + +1. Surveillance de site Web ou d'API - services externes qui surveillent constamment la disponibilité et les performances via des requêtes HTTP. Peut être installé en quelques minutes. Voici quelques candidats sélectionnés : [Pingdom](https://www.pingdom.com/), [Uptime Robot](https://uptimerobot.com/) et [New Relic](https://newrelic.com/application-monitoring). + +2. Instrumentation de code - famille de produits qui nécessite d'incorporer un agent dans l'application pour utiliser les fonctionnalités telles que la détection de code lent, les statistiques d'exception, la surveillance des performances et bien d'autres. Voici quelques candidats sélectionnés : New Relic, App Dynamics. + +3. Tableau de bord de l'intelligence opérationnelle - cette gamme de produits vise à faciliter la tâche de l'équipe d'exploitation avec des mesures et un contenu organisé qui permettent de rester facilement au fait de la performance des applications. Cela implique généralement l'agrégation de plusieurs sources d'informations (journaux d'application, journaux de base de données, journaux des serveurs, etc.) et le travail de conception du tableau de bord initial. Voici quelques candidats sélectionnés : [Datadog](https://www.datadoghq.com/), [Splunk](https://www.splunk.com/), [Zabbix](https://www.zabbix.com/). + + + + ### Exemple : UpTimeRobot.Com - Tableau de bord de surveillance de site Web +![alt text](../../assets/images/uptimerobot.jpg "Tableau de bord de surveillance de site Web") + + ### Exemple : AppDynamics.Com - Surveillance de bout en bout combinée à une instrumentation de code +![alt text](../../assets/images/app-dynamics-dashboard.png "Surveillance de bout en bout combinée à une instrumentation de code") diff --git a/sections/errorhandling/apmproducts.japanese.md b/sections/errorhandling/apmproducts.japanese.md index 34370867c..5e8b56f80 100644 --- a/sections/errorhandling/apmproducts.japanese.md +++ b/sections/errorhandling/apmproducts.japanese.md @@ -22,7 +22,7 @@ APM 製品は 3 つの主要なセグメントを構成しています: ### 例: UpTimeRobot.Com – ウェブサイトモニタリングダッシュボード -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/uptimerobot.jpg "ウェブサイトモニタリングダッシュボード") +![alt text](../../assets/images/uptimerobot.jpg "ウェブサイトモニタリングダッシュボード") ### 例: AppDynamics.Com – コード計測が統合されたエンドツーエンドモニタリング -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/app-dynamics-dashboard.png "コード計測が統合されたエンドツーエンドモニタリング") +![alt text](../../assets/images/app-dynamics-dashboard.png "コード計測が統合されたエンドツーエンドモニタリング") diff --git a/sections/errorhandling/apmproducts.korean.md b/sections/errorhandling/apmproducts.korean.md index ad5081797..fd4ae438e 100644 --- a/sections/errorhandling/apmproducts.korean.md +++ b/sections/errorhandling/apmproducts.korean.md @@ -22,7 +22,7 @@ APM products constitute 3 major segments: ### Example: UpTimeRobot.Com – Website monitoring dashboard -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/uptimerobot.jpg "Website monitoring dashboard") +![alt text](../../assets/images/uptimerobot.jpg "Website monitoring dashboard") ### Example: AppDynamics.Com – end to end monitoring combined with code instrumentation -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/app-dynamics-dashboard.png "end to end monitoring combined with code instrumentation") +![alt text](../../assets/images/app-dynamics-dashboard.png "end to end monitoring combined with code instrumentation") diff --git a/sections/errorhandling/apmproducts.md b/sections/errorhandling/apmproducts.md index 5f302168d..ae6fc82ec 100644 --- a/sections/errorhandling/apmproducts.md +++ b/sections/errorhandling/apmproducts.md @@ -22,7 +22,7 @@ APM products constitute 3 major segments: ### Example: UpTimeRobot.Com – Website monitoring dashboard -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/uptimerobot.jpg "Website monitoring dashboard") +![alt text](../../assets/images/uptimerobot.jpg "Website monitoring dashboard") ### Example: AppDynamics.Com – end to end monitoring combined with code instrumentation -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/app-dynamics-dashboard.png "end to end monitoring combined with code instrumentation") +![alt text](../../assets/images/app-dynamics-dashboard.png "end to end monitoring combined with code instrumentation") diff --git a/sections/errorhandling/apmproducts.polish.md b/sections/errorhandling/apmproducts.polish.md index a53a4b176..2a10799a8 100644 --- a/sections/errorhandling/apmproducts.polish.md +++ b/sections/errorhandling/apmproducts.polish.md @@ -22,7 +22,7 @@ Produkty APM stanowią 3 główne segmenty: ### Przykład: UpTimeRobot.Com – Website monitoring dashboard -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/uptimerobot.jpg "Website monitoring dashboard") +![alt text](../../assets/images/uptimerobot.jpg "Website monitoring dashboard") ### Przykład: AppDynamics.Com – end to end monitoring combined with code instrumentation -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/app-dynamics-dashboard.png "end to end monitoring combined with code instrumentation") +![alt text](../../assets/images/app-dynamics-dashboard.png "end to end monitoring combined with code instrumentation") diff --git a/sections/errorhandling/apmproducts.russian.md b/sections/errorhandling/apmproducts.russian.md index 242b6786c..e4c23d814 100644 --- a/sections/errorhandling/apmproducts.russian.md +++ b/sections/errorhandling/apmproducts.russian.md @@ -22,7 +22,7 @@ ### Пример: UpTimeRobot.Com - панель мониторинга сайта -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/uptimerobot.jpg "Панель мониторинга сайта") +![alt text](../../assets/images/uptimerobot.jpg "Панель мониторинга сайта") ### Пример: AppDynamics.Com – сквозной мониторинг в сочетании с инструментарием кода -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/app-dynamics-dashboard.png "Сквозной мониторинг в сочетании с инструментарием кода") +![alt text](../../assets/images/app-dynamics-dashboard.png "Сквозной мониторинг в сочетании с инструментарием кода") diff --git a/sections/errorhandling/asyncerrorhandling.basque.md b/sections/errorhandling/asyncerrorhandling.basque.md index 790fd139e..0ae082ac9 100644 --- a/sections/errorhandling/asyncerrorhandling.basque.md +++ b/sections/errorhandling/asyncerrorhandling.basque.md @@ -1,8 +1,8 @@ # Erabili Async-Await edo errore asinkronoak kudeatzeko promesak -### Azalpen paragrafoa +### Azalpena -Callbackak ez dira kudea errazak programatzaile gehienek ez dituzte ondo ezagutzen eta. Callbackek etengabeko errore egiaztatzea eskatzen dute, kode korapilotsua jasanaraziz eta kodigoaren fluxuaren ulergarritasuna zailduz. BlueBird, async, eta Q bezalako promesa liburutegiek kodigo estilo estandarra RETURN eta THROW erabiliz paketatzen dute, programaren fluxua kontrolatzeko. Zehazki, kodigo nagusia funtzio bakoitzean erroreak kuadeatzetik askatzea ahalbidetzen duen try-catch errore kudeaketa estilo gogokoena onartzen dute +Callbackak ez dira kudea errazak programatzaile gehienek ez dituzte ondo ezagutzen eta. Callbackek etengabeko errore egiaztatzea eskatzen dute, kode korapilotsua jasanaraziz eta kodigoaren fluxuaren ulergarritasuna zailduz. BlueBird, async, eta Q bezalako promesa liburutegiek kodigo estilo estandarra RETURN eta THROW erabiliz paketatzen dute, programaren fluxua kontrolatzeko. Zehazki, kodigo nagusia funtzio bakoitzean erroreak kudeatzetik askatzea ahalbidetzen duen try-catch errore kudeaketa estilo gogokoena onartzen dute ### Kode adibidea: promesen erabilera erroreak antzemateko @@ -93,27 +93,26 @@ datuakEskuratu(
-### Blogeko aipua: "Promesekin arazo bat dugu" +### Blog aipua: "Promesekin arazo bat dugu" -pouchdb.com blogetik hartua +pouchdb.com bloga -> ……Izatez, callbackek zerbait oraindik maltzurragoa egiten dute: pilaz gabetzen gaituzte, programazio lengoaietan sarri egintzat jotzen duguna. Kodea pila gabe idaztea kotxe bat freno pedalik gabe gidatzea bezala da: ez zara konturatzen zein puntura arte -behar duzun erabiltzen saiatu eta ez dagoela konturatzen zaren momentura arte. Promesen helburu nagusia da asinkronoa (async) erabiltzean galdutako lengoaien oinarri guztiak berreskuratzea: return, throw eta pila. Baina promesak modu egokian erabiltzen jakin beharra dago beraiei probetxua ateratzeko. +> ……Izatez, callbackek zerbait oraindik maltzurragoa egiten dute: pilaz gabetzen gaituzte, programazio lengoaietan sarri egintzat jotzen duguna. Kodea pila gabe idaztea kotxe bat freno pedalik gabe gidatzea bezala da: ez zara konturatzen zein puntura arte behar duzun erabiltzen saiatu eta ez dagoela konturatzen zaren momentura arte. Promesen helburu nagusia da asinkronoa (async) erabiltzean galdutako lengoaien oinarri guztiak berreskuratzea: return, throw eta pila. Baina promesak modu egokian erabiltzen jakin beharra dago beraiei probetxua ateratzeko -### Blogeko aipua: "Promesen metodoa askoz ere trinkoagoa da" +### Blog aipua: "Promesen metodoa askoz ere trinkoagoa da" -gosquared.com blogetik hartua +gosquared.com bloga -> ………Promesen metodoa askoz ere trinkoagoa, argiagoa eta idatzeko azkarragoa da. Errore edo salbuespen bat gertatzen bada, .catch() kudeatzaile bakar batek maneiatzen du.Errore guztiak kudeatzeko leku bakarra edukitzeak erroreen egiaztatzea lanaren fase bakoitzean idatzi beharrik ez dagoela adierazten du. +> ………Promesen metodoa askoz ere trinkoagoa, argiagoa eta idazteko azkarragoa da. Errore edo salbuespen bat gertatzen bada, .catch() kudeatzaile bakar batek maneiatzen du. Errore guztiak kudeatzeko leku bakarra edukitzeak erroreen egiaztatzea lanaren fase bakoitzean idatzi beharrik ez dagoela adierazten du -### Blogeko aipua: "Promisak jatorrizko ES6 dira, eta sorgailuekin erabil daitezke" +### Blog aipua: "Promesak jatorrizko ES6 dira, eta sorgailuekin erabil daitezke" -StrongLoop blogetik hartua +StrongLoop bloga -> ….Callbackek erroreen kudeaketa istorio kaskarra dute. Promesak hobeak dira. Promesekin, erabili Expressen errore kudeaketa kapsulatua eta horrela salbuespenen bat ez antzemateko aukerak murriztuko dituzu. Promesak jatorriz ES6ak dira, eta generatzaileekin eta ES7ren async/await bezalako proposamenekin erabil daitezke Babel bezalako konpilatzaileetan. +> ……Callbackek erroreen kudeaketa istorio kaskarra dute. Promesak hobeak dira. Promesekin, erabili Expressen errore kudeaketa kapsulatua eta horrela salbuespenen bat ez antzemateko aukerak murriztuko dituzu. Promesak jatorriz ES6ak dira, eta generatzaileekin eta ES7ren async/await bezalako proposamenekin erabil daitezke Babel bezalako konpilatzaileetan -### Blogeko aipua: "Ohiko fluxu kontrol erregularren egitura guzti horiek guztiz apurtuta daude" +### Blog aipua: "Ohiko fluxu kontrol erregularren egitura guzti horiek guztiz apurtuta daude" -Benno’s blogetik hartua +Benno’s bloga > ……Asinkronoaren, hau da, callbacketan oinarritutako programazioaren gauza hoberenetako bat da ohituta zauden fluxu kontrol erregularren egitura guzti horiek guztiz apurtuta daudela. Hala ere, salbuespenen kudeaketa da niretzat apurtuen dagoena. Javascriptek nahiko try…catch egitura ezaguna hornitzen du. Salbuespenen arazoa da, erroreak pila batean ekiditeko aukera ona eman arren, errorea beste pila batean gertatzen bada guztiz alferrikakoak izaten bukatzen dutela… diff --git a/sections/errorhandling/asyncerrorhandling.chinese.md b/sections/errorhandling/asyncerrorhandling.chinese.md index ef2f12e51..24725eabd 100644 --- a/sections/errorhandling/asyncerrorhandling.chinese.md +++ b/sections/errorhandling/asyncerrorhandling.chinese.md @@ -1,25 +1,43 @@ -# 对于异步的错误处理,请使用Async-Await或者promise - +# 对于异步的错误处理,请使用 Async-Await 或者 promises ### 一段解释 +由于大多数的程序员不熟悉回调,不能很好的掌控回调函数,导致被迫到处检测错误,处理让人不快的代码嵌套和难以理解的代码流程。Promise 的库,比如 BlueBird,async,和 Q 封装了一些代码,使用者可以使用 RETURN 和 THROW 的方式来控制程序的流程。具体来说,就是它们支持最受欢迎的 try-catch 错误处理风格,这使得主流程代码从在每一个方法中处理错误的方式中解放出来。 -由于回调对于大多数的程序员来说不熟悉,被迫随处检测错误,让人不快的代码内嵌和难以理解的代码流程,它没有形成一定规模。promise的库,比如BlueBird,async,和Q封装了一种标准的代码风格, 它通过使用return和throw来控制程序流程。具体来说,它们支持最受欢迎的try-catch错误处理风格,这使得主流程代码从在每一个方法中处理错误的方式中解放出来。 - +### 代码示例 – 使用 promises 捕获错误 -### 代码示例 – 使用promise捕获错误 +```javascript +doWork() + .then(doWork) + .then(doOtherWork) + .then((result) => doWork) + .catch((error) => { + throw error; + }) + .then(verify); +``` +### 代码示例 - 使用 async/await 捕获错误 ```javascript -doWork() - .then(doWork) - .then(doOtherWork) - .then((result) => doWork) - .catch((error) => {throw error;}) - .then(verify); +async function executeAsyncTask() { + try { + const valueA = await functionA(); + const valueB = await functionB(valueA); + const valueC = await functionC(valueB); + return await functionD(valueC); + } catch (err) { + logger.error(err); + } finally { + await alwaysExecuteThisFunction(); + } +} ``` ### 代码示例 反模式 – 回调方式的错误处理 +
+Javascript + ```javascript getData(someParameter, function(err, result){ if(err != null) @@ -27,30 +45,61 @@ getData(someParameter, function(err, result){ getMoreData(a, function(err, result){ if(err != null) //做一些事情类似于调用给定的回调函数并传递错误 - getMoreData(b, function(c){ - getMoreData(d, function(e){ + getMoreData(b, function(c){ + getMoreData(d, function(e){ if(err != null) - //你有什么想法?  + //你有什么想法? + }); +}); +``` + +
+ +
+Typescript + +```typescript +getData(someParameter, function (err: Error | null, resultA: ResultA) { + if (err !== null) { + //做一些事情类似于调用给定的回调函数并传递错误 + getMoreData(resultA, function (err: Error | null, resultB: ResultB) { + if (err !== null) { + //做一些事情类似于调用给定的回调函数并传递错误 + getMoreData(resultB, function (resultC: ResultC) { + getMoreData(resultC, function (err: Error | null, d: ResultD) { + if (err !== null) { + // 你有什么想法? + } + }); + }); + } }); + } }); ``` -### 博客引用: "我们使用promise有一个问题" - 摘自博客pouchdb.com - - > ……实际上, 回调会做一些更险恶的事情: 他们剥夺了我们的stack, 这是我们通常在编程语言中想当然的事情。编写没有堆栈的代码很像驾驶一辆没有刹车踏板的汽车: 你没有意识到你有多么需要它, 直到你伸手去找它, 而它不在那里。promise的全部目的是让我们回到我们在异步时丢失的语言基础: return,throw和stack。但你必须知道如何正确使用promise, 以便利用他们。 +
+ +### 博客引用: "我们使用 promise 有一个问题" + +摘自博客 pouchdb.com + +> ……实际上, 回调会做一些更险恶的事情: 他们剥夺了我们的 stack, 这是我们通常在编程语言中想当然的事情。编写没有堆栈的代码很像驾驶一辆没有刹车踏板的汽车: 你没有意识到你有多么需要它, 直到你伸手去找它, 而它不在那里。promise 的全部目的是让我们回到我们在异步时丢失的语言基础: return,throw 和 stack。但你必须知道如何正确使用 promise, 以便利用他们。 + +### 博客引用: "promise 方法更加紧凑" -### 博客引用: "promise方法更加紧凑" - 摘自博客gosquared.com - - > ………promise的方法更紧凑, 更清晰, 写起来更快速。如果在任何ops中发生错误或异常,则由单个.catch()处理程序处理。有这个单一的地方来处理所有的错误意味着你不需要为每个阶段的工作写错误检查。 +摘自博客 gosquared.com -### 博客引用: "原生ES6支持promise,可以和generator一起使用" - 摘自博客StrongLoop - - > ….回调有一个糟糕的错误处理的报道。promise更好。将express内置的错误处理与promise结合起来, 大大降低了uncaught exception的几率。原生ES6支持promise, 通过编译器babel,它可以与generator,ES7提议的技术(比如async/await)一起使用。 +> ………promise 的方法更紧凑, 更清晰, 写起来更快速。如果在任何 ops 中发生错误或异常,则由单个.catch()处理程序处理。有这个单一的地方来处理所有的错误意味着你不需要为每个阶段的工作写错误检查。 + +### 博客引用: "原生 ES6 支持 promise,可以和 generator 一起使用" + +摘自博客 StrongLoop + +> ….回调有一个糟糕的错误处理的报道。promise 更好。将 express 内置的错误处理与 promise 结合起来, 大大降低了 uncaught exception 的几率。原生 ES6 支持 promise, 通过编译器 babel,它可以与 generator,ES7 提议的技术(比如 async/await)一起使用。 ### 博客引用: "所有那些您所习惯的常规的流量控制结构, 完全被打破" - 摘自博客Benno’s - - > ……关于基于异步、回调编程的最好的事情之一是, 基本上所有那些您习惯的常规流量控制结构, 完全被打破。然而, 我发现最易打破的是处理异常。Javascript提供了一个相当熟悉的try...catch结构来处理异常。异常的问题是, 它们提供了在一个调用堆栈上 short-cutting错误的很好的方法, 但最终由于不同堆栈上发生的错误导致完全无用… + +摘自博客 Benno’s + +> ……关于基于异步、回调编程的最好的事情之一是, 基本上所有那些您习惯的常规流量控制结构, 完全被打破。然而, 我发现最易打破的是处理异常。Javascript 提供了一个相当熟悉的 try...catch 结构来处理异常。异常的问题是, 它们提供了在一个调用堆栈上 short-cutting 错误的很好的方法, 但最终由于不同堆栈上发生的错误导致完全无用… diff --git a/sections/errorhandling/asyncerrorhandling.french.md b/sections/errorhandling/asyncerrorhandling.french.md new file mode 100644 index 000000000..29ebd9d0b --- /dev/null +++ b/sections/errorhandling/asyncerrorhandling.french.md @@ -0,0 +1,109 @@ +# Utilisez Async-Await ou les promesses pour le traitement des erreurs asynchrones + +### Un paragraphe d'explication + +Les fonctions de rappels n'évoluent pas bien car la plupart des programmeurs ne les connaissent pas bien. Elles obligent à vérifier les erreurs partout, à gérer l'imbrication de code désagréable et à rendre difficile le raisonnement sur le flux du code. Les bibliothèques de promesse comme BlueBird, async et Q contiennent un style de code standard en utilisant RETURN et THROW pour contrôler le flux du programme. Plus précisément, elles prennent en charge le style de gestion des erreurs de try-catch qui permet de libérer le chemin du code principal de la gestion des erreurs dans chaque fonction. + +### Exemple de code - utiliser des promesses pour détecter les erreurs + +```javascript +return fonctionA() + .then(fonctionB) + .then(fonctionC) + .then(fonctionD) + .catch((err) => logger.error(err)) + .then(toujoursExecuterCetteFonction) +``` + + +### Exemple de code - utiliser async/await pour détecter les erreurs + +```javascript +async function executeAsyncTask () { + try { + const valueA = await fonctionA(); + const valueB = await fonctionB(valueA); + const valueC = await fonctionC(valueB); + return await fonctionD(valueC); + } + catch (err) { + logger.error(err); + } finally { + await toujoursExecuterCetteFonction(); + } +} +``` + +### Contre exemple de code - gestion des erreurs avec des fonctions de rappel + +
+Javascript + +```javascript +getData(someParameter, function(err, result) { + if(err !== null) { + // faire quelque chose comme appeler la fonction de rappel donnée et passer l'erreur + getMoreData(a, function(err, result) { + if(err !== null) { + // faire quelque chose comme appeler la fonction de rappel donnée et passer l'erreur + getMoreData(b, function(c) { + getMoreData(d, function(e) { + if(err !== null ) { + // vous avez une idée ? + } + }) + }); + } + }); + } +}); +``` +
+ +
+Typescript + +```typescript +getData(someParameter, function(err: Error | null, resultA: ResultA) { + if(err !== null) { + // faire quelque chose comme appeler la fonction de rappel donnée et passer l'erreur + getMoreData(resultA, function(err: Error | null, resultB: ResultB) { + if(err !== null) { + // faire quelque chose comme appeler la fonction de rappel donnée et passer l'erreur + getMoreData(resultB, function(resultC: ResultC) { + getMoreData(resultC, function(err: Error | null, d: ResultD) { + if(err !== null) { + // vous avez une idée ? + } + }) + }); + } + }); + } +}); +``` +
+ +### Citation de blog : « Nous avons un problème avec les promesses » + + Extrait du blog de pouchdb.com + + > …. Et en fait, les fonctions de rappel font quelque chose d'encore plus sinistre : elles nous privent de la pile, ce que nous tenons généralement pour acquis en langage de programmation. Écrire du code sans pile, c'est un peu comme conduire une voiture sans pédale de frein : vous ne réalisez pas à quel point vous en avez besoin tant que vous ne l'avez pas atteint et qu'il n'est pas là. Le but des promesses est de nous rendre les bases linguistiques que nous avons perdues quand nous sommes devenus asynchrones : return, throw et la pile. Mais il faut savoir utiliser correctement les promesses pour en profiter. + +### Citation de blog : « La méthode des promesses est beaucoup plus compacte » + + Extrait du blog de gosquared.com + + > …. La méthode des promesses est beaucoup plus compacte, plus claire et plus rapide à écrire. Si une erreur ou une exception se produit dans l'une des opérations, elle est gérée par l'unique gestionnaire .catch (). Avoir cet emplacement unique pour gérer toutes les erreurs signifie que vous n'avez pas besoin d'écrire la vérification des erreurs pour chaque étape du travail. + +### Citation de blog : « Les promesses sont natives en ES6, elles peuvent être utilisées avec des générateurs » + + Extrait du blog de StrongLoop + +> …. Les fonctions de rappel ont un mauvais historique de gestion des erreurs. Les promesses sont meilleures. Marier la gestion des erreurs intégrée dans Express avec des promesses permet de réduire considérablement les chances d'une exception non capturée. Les promesses sont natives en ES6, elles peuvent être utilisées avec des générateurs et des propositions ES7 comme async/await via des compilateurs comme Babel. + +### Citation de blog : « Toutes ces constructions de contrôle de flux auxquelles vous êtes habitué sont complètement cassées » + +Extrait du blog de Benno’s + + > …L'un des meilleurs atouts de l'asynchrone, pour la programmation basée sur des fonctions de rappel, c'est que fondamentalement toutes ces constructions de contrôle de flux auxquelles vous êtes habitué sont complètement cassées. Cependant, celle que je trouve la plus cassée, c'est la gestion des exceptions. Javascript fournit une construction try…catch assez familière pour gérer les exceptions. Le problème avec les exceptions, c'est qu'elles fournissent un excellent moyen de court-circuiter les erreurs dans une pile d'appels, mais finissent par être complètement inutiles si l'erreur se produit sur une autre pile… diff --git a/sections/errorhandling/catchunhandledpromiserejection.basque.md b/sections/errorhandling/catchunhandledpromiserejection.basque.md index aa92e5e30..727ed1b99 100644 --- a/sections/errorhandling/catchunhandledpromiserejection.basque.md +++ b/sections/errorhandling/catchunhandledpromiserejection.basque.md @@ -2,9 +2,9 @@

-### Azalpen paragrafoa +### Azalpena -Normalean, Node.js/Express aplikazio kode moderno gehienek promesen barruan funtzionatzen dute, .then kudeatzailearen, callback funtzio baten edota catch bloke baten barruan. Harrigarria bada ere, garatzaile batek .catch klausula bat gehitu zuela gogoratu ezean, leku hauetan jaurtitako erroreak ez dira uncaughtException ebentu kudeatzaileaz kudeatuak izaten, eta desagertu egiten dira. Noderen bertsio berrienek ohartarazpen mezu bat gehitu dute tratatu gabeko errefusa agertzen denean; egia da horrek, gauzak ondo ez doazenean, ohartzen lagun dezakeela, baina argi dago ez dela erroreak kudeatzeko modu egokia. Konponbide samurrena da ez ahaztea promesa kateko dei bakoitzaren barruan .catch klausula erabiltzen eta errore kudeatzaile zentralizatu batera desbideratzea. Hala ere, hauskorra da erroreak kudeatzeko estrategia garatzailearen diziplinan soilik oinarritzea. Ondorioz, oso gomendagarria da atzera egite dotorea erabiltzea eta `process.on('unhandledRejection', callback)`ra harpidetzea, horrek ziurtatuko baitu promesa erroreek, bere tratamendua izango dutela, lokalki kudeatzen ez badira. +Normalean, Node.js/Express aplikazio kode moderno gehienek promesen barruan funtzionatzen dute, .then kudeatzailearen, callback funtzio baten edota catch bloke baten barruan. Harrigarria bada ere, garatzaile batek .catch klausula bat gehitu zuela gogoratu ezean, leku hauetan jaurtitako erroreak ez dira uncaughtException ebentu kudeatzaileaz kudeatuak izaten, eta desagertu egiten dira. Noderen bertsio berrienek ohartarazpen mezu bat gehitu dute tratatu gabeko errefusa agertzen denean; egia da horrek, gauzak ondo ez doazenean, ohartzen lagun dezakeela, baina argi dago ez dela erroreak kudeatzeko modu egokia. Konponbide samurrena da ez ahaztea promesa kateko dei bakoitzaren barruan .catch klausula erabiltzen eta errore kudeatzaile zentralizatu batera desbideratzea. Hala ere, hauskorra da erroreak kudeatzeko estrategia garatzailearen diziplinan soilik oinarritzea. Ondorioz, oso gomendagarria da atzera egite dotorea erabiltzea eta `process.on('unhandledRejection', callback)`-ra harpidetzea, horrek ziurtatuko baitu promesa erroreek, bere tratamendua izango dutela, lokalki kudeatzen ez badira

@@ -65,9 +65,9 @@ process.on("uncaughtException", (errorea: Error) => {

-### Blogeko aipua: ""Erroreren bat egiteko gai bazara, momenturen batean egin egingo duzu" +### Blog aipua: "Erroreren bat egiteko gai bazara, momenturen batean egin egingo duzu" -James Nelson blogetik hartua +James Nelson bloga > Proba dezagun zure ulermena. Hauetako zeinek uste duzu erakutsiko duela errore bat kontsolan? diff --git a/sections/errorhandling/catchunhandledpromiserejection.french.md b/sections/errorhandling/catchunhandledpromiserejection.french.md new file mode 100644 index 000000000..583cf3093 --- /dev/null +++ b/sections/errorhandling/catchunhandledpromiserejection.french.md @@ -0,0 +1,87 @@ +# Capturez les rejets de promesses non gérés + +

+ +### Un paragraphe d'explication + +En règle générale, la plupart du code d'application Node.js/Express moderne s'exécute dans le cadre de promesse - que ce soit dans le gestionnaire .then, un rappel de fonction ou dans un bloc catch. Étonnamment, à moins qu'un développeur n'ait pensé à ajouter une clause .catch, les erreurs lancées à ces endroits ne sont pas traitées par le gestionnaire d'événement uncaughtException et disparaissent. Les versions récentes de Node ont ajouté un message d'avertissement lorsqu'un rejet non géré apparaît, bien que cela puisse aider à remarquer quand les choses tournent mal, mais ce n'est évidemment pas une bonne méthode de gestion des erreurs. La solution simple consiste à ne jamais oublier d'ajouter des clauses .catch dans chaque appel de chaîne de promesse et de rediriger vers un gestionnaire d'erreurs centralisé. Cependant, la construction de votre stratégie de gestion des erreurs uniquement sur la discipline du développeur est quelque peu fragile. Par conséquent, il est fortement recommandé d'utiliser une solution de secours élégante et de vous abonner à `process.on('unhandledRejection', callback)` - cela garantira que toute erreur de promesse, si elle n'est pas traitée localement, sera traitée. + +

+ +### Exemple de code : ces erreurs ne seront détectées par aucun gestionnaire d'erreurs (sauf unhandledRejection) + +```javascript +DAL.getUserById(1).then((johnSnow) => { + // cette erreur disparaîtra + if(johnSnow.isAlive === false) + throw new Error('ahhhh'); +}); +``` + +

+ +### Exemple de code : capturer des promesses non résolues et rejetées + +
+Javascript + +```javascript +process.on('unhandledRejection', (reason, p) => { + // Je viens d'attraper un rejet de promesse non géré, + // puisque nous avons déjà un gestionnaire de secours pour les erreurs non gérées (voir ci-dessous), + // laissons throw et laissons-le gérer cela + throw reason; +}); + +process.on('uncaughtException', (error) => { + // Je viens de recevoir une erreur qui n'a jamais été traitée, il est temps de la gérer et de décider ensuite si un redémarrage est nécessaire + errorManagement.handler.handleError(error); + if (!errorManagement.handler.isTrustedError(error)) + process.exit(1); +}); +``` +
+ +
+Typescript + +```typescript +process.on('unhandledRejection', (reason: string, p: Promise) => { +// Je viens d'attraper un rejet de promesse non géré, +  // puisque nous avons déjà un gestionnaire de secours pour les erreurs non gérées (voir ci-dessous), +  // laissons throw et laissons-le gérer cela + throw reason; +}); + +process.on('uncaughtException', (error: Error) => { + // Je viens de recevoir une erreur qui n'a jamais été traitée, il est temps de la gérer et de décider ensuite si un redémarrage est nécessaire + errorManagement.handler.handleError(error); + if (!errorManagement.handler.isTrustedError(error)) + process.exit(1); +}); +``` +
+ +

+ +### Citation de blog : « Si vous pouvez faire une erreur, vous la ferez à un moment donné » + +Extrait du blog de James Nelson + + > Testons votre compréhension. Lequel des éléments suivants devrez afficher une erreur sur la console ? + +```javascript +Promise.resolve('promised value').then(() => { + throw new Error('error'); +}); + +Promise.reject('error value').catch(() => { + throw new Error('error'); +}); + +new Promise((resolve, reject) => { + throw new Error('error'); +}); +``` + +> Je ne sais pas pour vous, mais ma réponse est que je m'attends à ce que tous affichent une erreur. Cependant, la réalité est qu'un certain nombre d'environnements JavaScript modernes n'imprimeront d'erreurs pour aucun d'entre eux. Le problème avec l'être humain est que si vous pouvez faire une erreur, vous la ferez à un moment donné. En gardant cela à l'esprit, il semble évident que nous devons concevoir les choses de manière à ce que les erreurs fassent le moins de mal possible, ce qui signifie gérer les erreurs par défaut, et non les éliminer. diff --git a/sections/errorhandling/centralizedhandling.basque.md b/sections/errorhandling/centralizedhandling.basque.md index 8c43c3fab..1676370f2 100644 --- a/sections/errorhandling/centralizedhandling.basque.md +++ b/sections/errorhandling/centralizedhandling.basque.md @@ -1,8 +1,8 @@ # Kudeatu erroreak gune bakar batean, Express middleware erabili partez -### Azalpen paragrafoa +### Azalpena -Errore kudeaketarako ardura bakarreko objektu bat ez izateak, errore garrantzitsuak ezkutatzeko aukerak ugaritzen ditu kudeaketa ezegoki baten eraginpean. Errore kudeaketarako objektua, errorea begibistako bihurtzearen arduradun da, adibidez, egoki formateatutako erregistro batean idatziz, ebentuak [Sentry](https://sentry.io/), [Rollbar](https://rollbar.com/), edota [Raygun](https://raygun.com/) bezalako monitorizazio sistemaren batera bidaliz. [Express](http://expressjs.com/en/guide/error-handling.html#writing-error-handlers) bezalako web framework gehienak, errore kudeaketa middleware mekanismo bat proposatzen dute. Errore kudeaketa fluxu tipiko bat hau izan daiteke: moduluren batek errore bat jaurtitzen du -> API routerrak errorea harrapatzen du -> errorea middlewarera hedatzen du, (adibidez Express edo KOA), zeinek erroreak harrapatzeko ardura duen -> errore kudeatzaile zentralizatu bati deitzen zaio -> middlewareari esaten zaio ia errore hau konfiantzazkoa den (ez operazio errorea) aplikazioa dotoreki berrekiteko. Kontutan izan Express midelwarean erroreak kudeatzea praktika arrunta dela, okerra izan arren. Hau egiteak ez ditu kontutan hartzen weba ez diren bestelako interfazeetako erroreak. +Erroreak kudeatzeko objektu dedikaturik gabe, handiagoak dira erroreak inkoherentziaz kudeatzeko aukerak: web eskaeren barruan izandako erroreak eta hasierako fasean planteatutakoen edo programatutako lanek sortutakoen desberdinak izan daitezke. Horrek eragina izan dezake oker kudeatzen ari diren errore mota batzuetan. Erroreak kudeatzen dituen objektu bakar horren ardura da erroreak begi bistan jartzea, adibidez ondo formateatutako erregistro batean idatziz edo monitorizazio produktu batzuk erabiliz ([Prometheus](https://prometheus.io/), [CloudWatch](https://aws.amazon.com/cloudwatch/), [DataDog](https://www.datadoghq.com/) eta [Sentry](https://sentry.io/) bezalakoak); eta, gainera, berak erabakitzen du prozesuak huts egin behar duen ala ez. Web plataforma gehienek erroreak atzemateko middleware mekanismoa eskaintzen dute. Errore tipikoa izaten da middlewarearen erroreen kudeaketa kodea jartzea. Horrela, ezin izango duzu kudeatzaile bera berrerabili eszenatoki desberdinetan atzemandako erroreetarako, hala nola, programatutako lanak, harpidedunen mezu ilarak eta atzeman gabeko salbuespenak. Ondorioz, errorearen middlewareak erroreak atzeman eta kudeatzailera bidali beharko lituzke. Hau izan liteke errore kudeaketaren fluxu tipikoa: moduluren batzuek errore bat jaurtitzen dute -> API bideratzaileak errorea atzematen du -> erroreak atzemateaz arduratzen den middlewarera bidaltzen du (edo eskaera mailako erroreak atzemateko beste mekanismo batera) -> errore kudeatzaile zentralizatu bati deitzen zaio ### Kode adibidea: ohiko errore fluxua @@ -156,19 +156,19 @@ app.use((errorea: Error, req: Request, res: Response, next: NextFunction) => {
-### Blogeko aipua: "Batzuetan maila baxuagoek beren deitzaileari errorea bidaltzea baino ezer praktikoagorik ezin dute egin" +### Blog aipua: "Batzuetan maila baxuagoek beren deitzaileari errorea bidaltzea baino ezer praktikoagorik ezin dute egin" Joyent blogeko “Node.js errore kudeaketa" hitz gako bati esker sailkatua > …Errore bera pilaren maila askotan kudeatzen bukatuko duzu. Hau gertatzen da maila baxuenek beren deitzaileei (eta beste haiek beren deitzaileei, etab.) errorea bidaltzea baino beste ezer egokiagorik ezin dutenean egin. Askotan, soilik goi mailako deitzaileak daki zein den erantzun zuzena, ia ahalegin operazio berria den, erabiltzaileari errorearen berri eman behar dion, edo beste edozer. Baina horrek ez du esan nahi errore guztiak goi mailako callback bakar bati jakinarazi behar dizkiozunik, callback horrek ere errorea zein testuingurutan gertatu den ez daki eta… -### Blogeko aipua: "Errore bakoitza bakarka kudeatzea bikoizte galanta izan daiteke" +### Blog aipua: "Errore bakoitza bakarka kudeatzea bikoizte galanta izan daiteke" JS Recipes blogeko “Node.js errore kudeaketa" 17 hitz gakori esker sailkatua > ……Hackathoneko Starter api.js kontrolatzaile bakarrean, 79 errore objektu inguru daude. Errore bakoitza bakarka kudeatzeak kodea ikaragarri bikoiztea eragin dezake. Hurrengo egin dezakezun gauza hoberena da errore kudeaketa logika Express middleware bati uztea… -### Blogeko aipua: "HTTP erroreak ezin dira zure datu basearen kodean egon" +### Blog aipua: "HTTP erroreak ezin dira zure datu basearen kodean egon" Daily JS blogeko “Node.js errore kudeaketa" 14 hitz gakori esker sailkatua diff --git a/sections/errorhandling/centralizedhandling.chinese.md b/sections/errorhandling/centralizedhandling.chinese.md index cc95a2c63..06a4f31bc 100644 --- a/sections/errorhandling/centralizedhandling.chinese.md +++ b/sections/errorhandling/centralizedhandling.chinese.md @@ -43,11 +43,11 @@ app.use(function (err, req, res, next) { ```javascript module.exports.handler = new errorHandler(); -function errorHandler(){ +function errorHandler() { this.handleError = function (err) { return logger.logError(err).then(sendMailToAdminIfCritical).then(saveInOpsQueueIfCritical).then(determineIfOperationalError); } - +} ``` ### 代码示例 – 反模式:在中间件内处理错误 diff --git a/sections/errorhandling/centralizedhandling.french.md b/sections/errorhandling/centralizedhandling.french.md new file mode 100644 index 000000000..ca1f2849a --- /dev/null +++ b/sections/errorhandling/centralizedhandling.french.md @@ -0,0 +1,176 @@ +# Gérez les erreurs de manière centralisée, pas dans les middlewares + +### Un paragraphe d'explication + +Sans un objet dédié au traitement des erreurs, les risques de traitement incohérent des erreurs sont plus grands : les erreurs lancées à l'intérieur des requêtes web peuvent être traitées différemment de celles qui sont levées lors de la phase de démarrage et de celles qui sont levées par les jobs planifiés. Cela peut conduire à certains types d'erreurs qui sont mal gérés. Cet objet unique de traitement des erreurs est chargé de rendre l'erreur visible, par exemple, en écrivant dans un journal bien formaté, en envoyant des mesures à l'aide d'un produit de surveillance (comme [Prometheus](https://prometheus.io/), [CloudWatch](https://aws.amazon.com/cloudwatch/), [DataDog](https://www.datadoghq.com/) et [Sentry](https://sentry.io/)) et de décider si le processus doit planter. La plupart des frameworks web fournissent un mécanisme de middleware pour la détection des erreurs - une erreur typique consiste à placer le code de gestion des erreurs dans ce middelware. Ce faisant, vous ne pourrez pas réutiliser le même gestionnaire pour les erreurs qui sont détectées dans différents scénarios comme les tâches planifiées, les abonnés à la file d'attente des messages et les exceptions non détectées. Par conséquent, le middleware de gestion des erreurs ne doit que capturer les erreurs et les transmettre au gestionnaire. Un flux typique de traitement des erreurs pourrait être : un module lance une erreur -> le routeur API capture l'erreur -> il propage l'erreur au middleware (par exemple ou à un autre mécanisme de capture d'erreur au niveau de la requête) qui est responsable de la capture des erreurs -> un gestionnaire d'erreur centralisé est appelé. + +### Exemple de code - un flux d'erreur typique + +
+Javascript + +```javascript +// Strate de la DAL, nous ne gérons pas les erreurs ici +DB.addDocument(newCustomer, (error, result) => { + if (error) + throw new Error('Une bonne explication de l\'erreur à cet endroit', autres parametres utiles) +}); + +// Code de l'API route, nous interceptons les erreurs synchrone et asynchrone et les transmettons au middleware +try { + customerService.addNew(req.body).then((result) => { + res.status(200).json(result); + }).catch((error) => { + next(error) + }); +} +catch (error) { + next(error); +} + +// Gestion des erreurs du middleware, nous déléguons la gestion au gestionnaire d'erreurs centralisé +app.use(async (err, req, res, next) => { + await errorHandler.handleError(err, res);//Le gestionnaire d'erreur enverra une réponse +}); + +process.on("uncaughtException", error => { + errorHandler.handleError(error); +}); + +process.on("unhandledRejection", (reason) => { + errorHandler.handleError(reason); +}); +``` +
+ +
+Typescript + +```typescript +// Strate de la DAL, nous ne gérons pas les erreurs ici +DB.addDocument(newCustomer, (error: Error, result: Result) => { + if (error) + throw new Error('Une bonne explication de l\'erreur à cet endroit', autres parametres utiles) +}); + +// Code de l'API route, nous interceptons les erreurs synchrone et asynchrone et les transmettons au middleware +try { + customerService.addNew(req.body).then((result: Result) => { + res.status(200).json(result); + }).catch((error: Error) => { + next(error) + }); +} +catch (error) { + next(error); +} + +// Gestion des erreurs du middleware, nous déléguons la gestion au gestionnaire d'erreurs centralisé +app.use(async (err: Error, req: Request, res: Response, next: NextFunction) => { + await errorHandler.handleError(err, res); +}); + +process.on("uncaughtException", (error:Error) => { + errorHandler.handleError(error); +}); + +process.on("unhandledRejection", (reason) => { + errorHandler.handleError(reason); +}); +``` +
+ + +### Exemple de code - gestion des erreurs dans un objet dédié + +
+Javascript + +```javascript +module.exports.handler = new errorHandler(); + +function errorHandler() { + this.handleError = async (error, responseStream) => { + await logger.logError(error); + await fireMonitoringMetric(error); + await crashIfUntrustedErrorOrSendResponse(error, responseStream); + }; +} +``` +
+ +
+Typescript + +```typescript +class ErrorHandler { + public async handleError(error: Error, responseStream: Response): Promise { + await logger.logError(error); + await fireMonitoringMetric(error); + await crashIfUntrustedErrorOrSendResponse(error, responseStream); + }; +} + +export const handler = new ErrorHandler(); +``` +
+ + +### Contre exemple de code - gestion des erreurs dans le middleware + +
+Javascript + +```javascript +// middleware traitant l'erreur directement, qui va gérer les tâches Cron et tester les erreurs ? +app.use((err, req, res, next) => { + logger.logError(err); + if (err.severity == errors.high) { + mailer.sendMail(configuration.adminMail, 'Une erreur critique s\'est produite', err); + } + if (!err.isOperational) { + next(err); + } +}); +``` +
+ + +
+Typescript + +```typescript +// middleware traitant l'erreur directement, qui va gérer les tâches Cron et tester les erreurs ? +app.use((err: Error, req: Request, res: Response, next: NextFunction) => { + logger.logError(err); + if (err.severity == errors.high) { + mailer.sendMail(configuration.adminMail, 'Une erreur critique s\'est produite', err); + } + if (!err.isOperational) { + next(err); + } +}); +``` +
+ +### Illustration : Les acteurs et le flux du traitement des erreurs +![alt text](../../assets/images/error-handling-flow.png "Flux de traitement des erreurs") + + +### Citation de blog : « Parfois, les niveaux inférieurs ne peuvent rien faire d'utile, sauf propager l'erreur à leur appelant » + +Extrait du blog de Joyent classé en 1ere position pour les mots clés “Node.js error handling” + +> …Vous pouvez finir par gérer la même erreur à plusieurs niveaux de la pile. Cela se produit lorsque les niveaux inférieurs ne peuvent rien faire d'autre d'utile que de propager l'erreur à leur appelant, qui propage l'erreur à son appelant et ainsi de suite. Souvent, seul l'appelant de niveau supérieur sait quelle est la réponse appropriée, que ce soit pour réessayer l'opération, signaler une erreur à l'utilisateur ou autre chose. Mais cela ne signifie pas que vous devez essayer de signaler toutes les erreurs à une seule fonction de rappel de niveau supérieur, car cette fonction de rappel elle-même ne peut pas savoir dans quel contexte l'erreur s'est produite.… + +### Citation de blog : « Gérer chaque erreur individuellement entraînerait une énorme duplication » + +Extrait du blog de JS Recipes classé en 17eme position pour les mots clés “Node.js error handling” + +> ……Uniquement dans le contrôleur api.js de Hackathon Starter, il y a plus de 79 occurrences d'objets d'erreur. Gérer chaque erreur individuellement entraînerait une énorme duplication de code. La meilleure chose à faire est de déléguer toute la logique de gestion des erreurs à un middleware Express… + +### Citation de blog : « les erreurs HTTP n'ont pas leur place dans le code de votre base de données » + +Extrait du blog de Daily JS classé en 14eme position pour les mots clés “Node.js error handling” + +> ……Vous devez définir des propriétés utiles dans les objets d'erreur, mais utilisez ces propriétés de manière cohérente. Et ne traversez pas les flux : les erreurs HTTP n'ont pas leur place dans le code de votre base de données. Ou pour les développeurs dans les navigateurs, les erreurs Ajax ont une place dans le code qui parle au serveur, mais pas dans le code qui traite les templates de Mustache… diff --git a/sections/errorhandling/centralizedhandling.md b/sections/errorhandling/centralizedhandling.md index d674b72e7..7a8f7a6d6 100644 --- a/sections/errorhandling/centralizedhandling.md +++ b/sections/errorhandling/centralizedhandling.md @@ -35,11 +35,11 @@ app.use(async (err, req, res, next) => { process.on("uncaughtException", error => { errorHandler.handleError(error); - }); +}); - process.on("unhandledRejection", (reason) => { - errorHandler.handleError(reason); - }); +process.on("unhandledRejection", (reason) => { + errorHandler.handleError(reason); +}); ```
@@ -67,16 +67,16 @@ catch (error) { // Error handling middleware, we delegate the handling to the centralized error handler app.use(async (err: Error, req: Request, res: Response, next: NextFunction) => { -await errorHandler.handleError(err, res); + await errorHandler.handleError(err, res); }); process.on("uncaughtException", (error:Error) => { errorHandler.handleError(error); - }); +}); - process.on("unhandledRejection", (reason) => { - errorHandler.handleError(reason); - }); +process.on("unhandledRejection", (reason) => { + errorHandler.handleError(reason); +}); ```
@@ -93,7 +93,7 @@ function errorHandler() { this.handleError = async (error, responseStream) => { await logger.logError(error); await fireMonitoringMetric(error); - await crashIfUntrustedErrorOrSendResponse(error, responseStream); + await crashIfUntrustedErrorOrSendResponse(error, responseStream); }; } ``` @@ -107,8 +107,8 @@ class ErrorHandler { public async handleError(error: Error, responseStream: Response): Promise { await logger.logError(error); await fireMonitoringMetric(error); - await crashIfUntrustedErrorOrSendResponse(error, responseStream); - }; + await crashIfUntrustedErrorOrSendResponse(error, responseStream); + }; } export const handler = new ErrorHandler(); @@ -154,7 +154,7 @@ app.use((err: Error, req: Request, res: Response, next: NextFunction) => {
### Illustration: The error handling actors and flow -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/error-handling-flow.png "Error handling flow") +![alt text](../../assets/images/error-handling-flow.png "Error handling flow") ### Blog Quote: "Sometimes lower levels can’t do anything useful except propagate the error to their caller" diff --git a/sections/errorhandling/documentingusingswagger.basque.md b/sections/errorhandling/documentingusingswagger.basque.md index aaf33ee19..e88ba2e41 100644 --- a/sections/errorhandling/documentingusingswagger.basque.md +++ b/sections/errorhandling/documentingusingswagger.basque.md @@ -1,11 +1,10 @@ # Dokumentatu API erroreak OpenAPI (aurretik Swagger bezala ezagutua) edo GraphQL-ren laguntzarekin -### Azalpen paragrafoa +### Azalpena -REST APIek HTTP estatus kodigoak erabiliz bueltatzen dituzte emaitzak. APIaren erabiltzailearentzat guztiz beharrezkoa da APIaren egituraren eta baita ere errore posibleen berri izatea, erabiltzaileak errorea atzeman eta kontu handiz kudea dezake eta. Adibidez, zure APIaren dokumentazioak aurrez azaldu behar du 409 HTTP estatus kodea bueltatzen dela bezeroaren izena iada existitzen denean (APIak bezero berriak gordetzen dituela ziurtzat joz), APIaren erabiltzaileak egoera bakoitzerako bistaratze egokiena proposa dezan. OpenAPI (aintzina Swagger) APIaren dokumentaziorako eskema bat zehazten duen estandar bat da, dokumentazioa online modu errazean sortzea ahalbidetzen duten tresna ekosistema bat proposatuz. Begiratu hurrengo pantailako argazkiak beherago - -Dagoeneko GraphQL erabiltzen baduzu zure APIaren helburuetarako, zure eskemak iada zorrozki bermatzen du zein errorek zein itxura eduki beharko luketen ([dokumentuan laburbilduta](https://facebook.github.io/graphql/June2018/#sec-Errors)) eta nola kudeatu beharko liratekeen zure bezero tresnekin Gainera, komentarioz osatutako dokumentazioa ere gehi zenezake. +REST APIek HTTP estatus kodigoak erabiliz bueltatzen dituzte emaitzak. APIaren erabiltzailearentzat guztiz beharrezkoa da APIaren egituraren eta baita ere errore posibleen berri izatea, erabiltzaileak errorea atzeman eta kontu handiz kudea dezake eta. Adibidez, zure APIaren dokumentazioak aurrez azaldu behar du 409 HTTP estatus kodea bueltatzen dela bezeroaren izena iada existitzen denean (APIak bezero berriak gordetzen dituela ziurtzat joz), APIaren erabiltzaileak egoera bakoitzerako bistaratze egokiena proposa dezan. OpenAPI (aitzina Swagger) APIaren dokumentaziorako eskema bat zehazten duen estandar bat da, dokumentazioa online modu errazean sortzea ahalbidetzen duten tresna ekosistema bat proposatuz. Begiratu hurrengo pantailako argazkiak beherago +Dagoeneko GraphQL erabiltzen baduzu zure APIaren helburuetarako, zure eskemak iada zorrozki bermatzen du zein errorek zein itxura eduki beharko luketen ([dokumentuan laburbilduta](https://facebook.github.io/graphql/June2018/#sec-Errors)) eta nola kudeatu beharko liratekeen zure bezero tresnekin. Gainera, komentarioz osatutako dokumentazioa ere gehi zenezake ### GraphQL errore baten adibidea @@ -31,9 +30,7 @@ Dagoeneko GraphQL erabiltzen baduzu zure APIaren helburuetarako, zure eskemak ia "zutabea": 3 } ], - "bidea": [ - "filmea" - ] + "bidea": ["filmea"] } ], "datuak": { @@ -42,12 +39,12 @@ Dagoeneko GraphQL erabiltzen baduzu zure APIaren helburuetarako, zure eskemak ia } ``` -### Blogeko aipua: "Zure deitzaileei zein errore gertatu diren esan behar diezu" +### Blog aipua: "Zure deitzaileei zein errore gertatu diren esan behar diezu" Joyent blogeko “Node.js erregistratzea“ hitz gako bati esker sailkatua - > Erroreak nola kudeatu behar diren aztertu dugu, baina funtzio berri bat idazten ari zarenean, nola bidaltzen dizkiozu erroreak zure funtzioa deitu duen kodeari? …Zein errore gerta litezkeen edo haiekk zer esan nahi duten ez badakizu, esan nahi du zure programa ezin litekeela zuzena izan, txiripaz izan ezean. Beraz, funtzio berri bat idazten ari bazara, zure deitzailei zein errore gerta litezkeen eta haiek zer esan nahi duten esan behar diezu… +> Erroreak nola kudeatu behar diren aztertu dugu, baina funtzio berri bat idazten ari zarenean, nola bidaltzen dizkiozu erroreak zure funtzioa deitu duen kodeari? …Zein errore gerta litezkeen edo haiek zer esan nahi duten ez badakizu, esan nahi du zure programa ezin litekeela zuzena izan, txiripaz izan ezean. Beraz, funtzio berri bat idazten ari bazara, zure deitzaileei zein errore gerta litezkeen eta haiek zer esan nahi duten esan behar diezu… ### Tresna erabilgarria: Swagger Online Dokumentazio Sortzailea -![Swagger API Eskema](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/swaggerDoc.png "APIen errore kudeaketa") +![Swagger API Eskema](../../assets/images/swaggerDoc.png "APIen errore kudeaketa") diff --git a/sections/errorhandling/documentingusingswagger.brazilian-portuguese.md b/sections/errorhandling/documentingusingswagger.brazilian-portuguese.md index 4af6a9890..781337b42 100644 --- a/sections/errorhandling/documentingusingswagger.brazilian-portuguese.md +++ b/sections/errorhandling/documentingusingswagger.brazilian-portuguese.md @@ -49,4 +49,4 @@ Do blog Joyent, classificado como 1 para as palavras-chave “Node.js logging” ### Ferramenta Útil: Swagger Criação de Documentação Online -![Swagger API Scheme](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/swaggerDoc.png "lidando com erros API") +![Swagger API Scheme](../../assets/images/swaggerDoc.png "lidando com erros API") diff --git a/sections/errorhandling/documentingusingswagger.chinese.md b/sections/errorhandling/documentingusingswagger.chinese.md index 5d3998ac1..3cf8cc0e3 100644 --- a/sections/errorhandling/documentingusingswagger.chinese.md +++ b/sections/errorhandling/documentingusingswagger.chinese.md @@ -13,4 +13,4 @@ REST API使用HTTP代码返回结果, API用户不仅绝对需要了解API schem ### 有用的工具: Swagger 在线文档创建工具 -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/swaggerDoc.png "API error handling") \ No newline at end of file +![alt text](../../assets/images/swaggerDoc.png "API error handling") diff --git a/sections/errorhandling/documentingusingswagger.french.md b/sections/errorhandling/documentingusingswagger.french.md new file mode 100644 index 000000000..0b57ce6d3 --- /dev/null +++ b/sections/errorhandling/documentingusingswagger.french.md @@ -0,0 +1,52 @@ +# Documentez les erreurs de l'API à l'aide de Swagger ou GraphQL + +### Un paragraphe d'explication + +Les API REST renvoient des résultats à l'aide de codes d'état HTTP, il est absolument nécessaire que l'utilisateur de l'API soit informé non seulement du schéma de l'API, mais également des erreurs potentielles - l'appelant peut alors détecter une erreur et la gérer avec tact. Par exemple, la documentation de votre API peut indiquer à l'avance que l'état HTTP 409 est renvoyé lorsque le nom du client existe déjà (en supposant que l'API enregistre de nouveaux utilisateurs) afin que l'appelant puisse rendre en conséquence la meilleure expérience utilisateur pour la situation donnée. Swagger est une norme qui définit le schéma de la documentation de l'API offrant un éco-système d'outils permettant de créer facilement de la documentation en ligne, consulter les copies écrans ci-dessous. + +Si vous avez déjà adopté GraphQL pour vos points de terminaison de l'API, votre schéma contient déjà des garanties strictes quant à la nature des erreurs à rechercher ([celles décrites dans la spécification](https://facebook.github.io/graphql/June2018/#sec-Errors)) et comment elles doivent être traités par vos outils côté client. De plus, vous pouvez également les compléter avec une documentation basée sur des commentaires. + +### Exemple d'erreur GraphQL + +> Cet exemple utilise [SWAPI](https://graphql.org/swapi-graphql), l'API de Star Wars. + +```graphql +# devrait échouer car l'id n'est pas valide +{ + film(id: "1ZmlsbXM6MQ==") { + title + } +} +``` + +```json +{ + "errors": [ + { + "message": "Aucune entrée dans le cache local pour https://swapi.co/api/films/.../", + "locations": [ + { + "line": 2, + "column": 3 + } + ], + "path": [ + "film" + ] + } + ], + "data": { + "film": null + } +} +``` + +### Citation de blog : « Vous devez dire à vos appelants quelles erreurs peuvent se produire » + +Extrait du blog de Joyent classé en 1ere position pour les mots clés “Node.js logging” + + > Nous avons parlé de la façon de gérer les erreurs, mais lorsque vous écrivez une nouvelle fonction, comment envoyez-vous des erreurs au code qui a appelé votre fonction ? … Si vous ne savez pas quelles erreurs peuvent se produire ou si vous ne savez pas ce qu'elles signifient, alors votre programme ne peut être correct que par accident. Donc, si vous écrivez une nouvelle fonction, vous devez dire à vos appelants quelles erreurs peuvent se produire et ce qu'elles signifient… + +### Outil utile : créateur de documentation en ligne Swagger + +![Schéma d'API Swagger](../../assets/images/swaggerDoc.png "Gestion des erreurs de l'API") diff --git a/sections/errorhandling/documentingusingswagger.japanese.md b/sections/errorhandling/documentingusingswagger.japanese.md index 861add999..10882d198 100644 --- a/sections/errorhandling/documentingusingswagger.japanese.md +++ b/sections/errorhandling/documentingusingswagger.japanese.md @@ -49,4 +49,4 @@ REST API は HTTP ステータスコードを利用して結果を返します ### 便利ツール: Swagger Online Documentation Creator -![Swagger API スキーマ](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/swaggerDoc.png "API エラー処理") +![Swagger API スキーマ](../../assets/images/swaggerDoc.png "API エラー処理") diff --git a/sections/errorhandling/documentingusingswagger.korean.md b/sections/errorhandling/documentingusingswagger.korean.md index 3341b0c13..a101e668a 100644 --- a/sections/errorhandling/documentingusingswagger.korean.md +++ b/sections/errorhandling/documentingusingswagger.korean.md @@ -49,4 +49,4 @@ From the blog Joyent, ranked 1 for the keywords “Node.js logging” ### Useful Tool: Swagger Online Documentation Creator -![Swagger API Scheme](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/swaggerDoc.png "API error handling") +![Swagger API Scheme](../../assets/images/swaggerDoc.png "API error handling") diff --git a/sections/errorhandling/documentingusingswagger.md b/sections/errorhandling/documentingusingswagger.md index b91e7d05d..836f07364 100644 --- a/sections/errorhandling/documentingusingswagger.md +++ b/sections/errorhandling/documentingusingswagger.md @@ -49,4 +49,4 @@ From the blog Joyent, ranked 1 for the keywords “Node.js logging” ### Useful Tool: Swagger Online Documentation Creator -![Swagger API Scheme](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/swaggerDoc.png "API error handling") +![Swagger API Scheme](../../assets/images/swaggerDoc.png "API error handling") diff --git a/sections/errorhandling/documentingusingswagger.polish.md b/sections/errorhandling/documentingusingswagger.polish.md index e274fea45..b6f1dfcd8 100644 --- a/sections/errorhandling/documentingusingswagger.polish.md +++ b/sections/errorhandling/documentingusingswagger.polish.md @@ -49,4 +49,4 @@ Z bloga Joyent, w rankingu 1 dla słów kluczowych “Node.js logging” ### Przydatne narzędzie: Swagger Online Documentation Creator -![Swagger API Scheme](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/swaggerDoc.png "API error handling") +![Swagger API Scheme](../../assets/images/swaggerDoc.png "API error handling") diff --git a/sections/errorhandling/documentingusingswagger.russian.md b/sections/errorhandling/documentingusingswagger.russian.md index 2086e312f..f225e3ca8 100644 --- a/sections/errorhandling/documentingusingswagger.russian.md +++ b/sections/errorhandling/documentingusingswagger.russian.md @@ -49,4 +49,4 @@ API-интерфейсы REST возвращают результаты с ис ### Полезный инструмент: Swagger Online Documentation Creator -![Swagger API Scheme](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/swaggerDoc.png "API error handling") +![Swagger API Scheme](../../assets/images/swaggerDoc.png "API error handling") diff --git a/sections/errorhandling/failfast.basque.md b/sections/errorhandling/failfast.basque.md index c481e6a40..927d5c4ba 100644 --- a/sections/errorhandling/failfast.basque.md +++ b/sections/errorhandling/failfast.basque.md @@ -1,12 +1,12 @@ -# Huts egin azkar, balidatu argudioak liburutegi dedikatu baten laguntzarekin +# Huts eragin azkar, balidatu argudioak liburutegi dedikatu baten laguntzarekin -### Azalpen paragrafoa +### Azalpena -Denok dakigu argudioak egiaztatzea eta azkar huts egitea garrantzitsua dela ezkutuko erroreak ekiditeko (ikusi ereduaren aurkako kodearen adibidea behean). Bestela, irakurri zerbait programazio esplizituaren eta babes programazioaren gainean. Errealitatean, hori ekiditeko ohitura daukagu, kodea idazteak suposatzen duen gogaikarritasuna dela eta (adibidez pentsatu posta elektronikoa eta datak bezalako alorrak dituen JSON objektu hierarkiko bat balioztatzea). Joi eta Validator bezalako liburutegiek asko leuntzen dute lan hori. +Denok dakigu argudioak egiaztatzea eta azkar huts egitea garrantzitsua dela ezkutuko erroreak ekiditeko (ikusi ereduaren aurkako kodearen adibidea behean). Bestela, irakurri zerbait programazio esplizituaren eta babes programazioaren gainean. Errealitatean, hori ekiditeko ohitura daukagu, kodea idazteak suposatzen duen gogaikarritasuna dela eta (adibidez pentsatu posta elektronikoa eta datak bezalako alorrak dituen JSON objektu hierarkiko bat balioztatzea). Joi eta Validator bezalako liburutegiek asko leuntzen dute lan hori ### Wikipedia: programazio defentsiboa -Programazio defentsiboa softwarea eta iturburu kodea hobetzeko ikuspuntua da, kalitate orokorrari dagokionez, software errore eta arazo kopurua murriztuz. Iturburu kodea ulergarria izango bada, irakurgarria eta ulergarria izan behar da kode auditoria batean onartua izan dadin. Softwarea aurreikusteko moduko eran jokatzeko egin behar da, ustekabeko sarrerak edo erabiltzaile ekintzak gertatu arren. +Programazio defentsiboa softwarea eta iturburu kodea hobetzeko ikuspuntua da, kalitate orokorrari dagokionez, software errore eta arazo kopurua murriztuz. Iturburu kodea ulergarria izango bada, irakurgarria eta ulergarria izan behar da kode auditoria batean onartua izan dadin. Softwarea aurreikusteko moduko eran jokatzeko egin behar da, ustekabeko sarrerak edo erabiltzaile ekintzak gertatu arren ### Kode adibidea: balioztatu JSON sarrera koplexua ‘Joi’ erabiliz @@ -64,8 +64,8 @@ bidaliDeskontuTiketakInprimatzera(httpResponse, kiderenBat, -12);
-### Blogeko aipua: "Errore hauek zuzenean jaurti beharko zenituzke" +### Blog aipua: "Errore hauek zuzenean jaurti beharko zenituzke" -Joyent blogetik hartua +Joyent bloga -> Kasu degeneratu bat da norbaitek funtzio asinkrono bat callback gabe deitzea atzera deirik egin gabe. Errore horiek berehala jaurti beharko zenituzke programa apurtuta baitago eta hori arazteak gutxienez pila arrastoa eta errorearen lekuko fitxategia berreskuratzea eskatzen du. Hori egiteko, funtzioaren hasieran argudio guztien motak balioztatzea gomendatzen dugu. +> Kasu degeneratu bat da norbaitek funtzio asinkrono bat callback gabe deitzea atzera deirik egin gabe. Errore horiek berehala jaurti beharko zenituzke programa apurtuta baitago eta hori arazteak gutxienez pila arrastoa eta errorearen lekuko fitxategia berreskuratzea eskatzen du. Hori egiteko, funtzioaren hasieran argudio guztien motak balioztatzea gomendatzen dugu diff --git a/sections/errorhandling/failfast.french.md b/sections/errorhandling/failfast.french.md new file mode 100644 index 000000000..a3af42ac3 --- /dev/null +++ b/sections/errorhandling/failfast.french.md @@ -0,0 +1,67 @@ +# Échouez rapidement, valider les arguments à l'aide d'une bibliothèque dédiée + +### Un paragraphe d'explication + +Nous savons tous combien il est important de vérifier les arguments et d'échouer rapidement pour éviter les bogues cachés (voir le contre exemple de code ci-dessous). Si ce n'est pas le cas, renseignez-vous sur la programmation explicite et la programmation défensive. En réalité, nous avons tendance à l'éviter en raison de la pénibilité de son codage (par exemple, pensez à valider un objet JSON hiérarchique avec des champs comme l'email et les dates) - des bibliothèques comme Joi et Validator transforment cette tâche fastidieuse en un jeu d'enfant. + +### Wikipedia : la programmation défensive + +La programmation défensive est une approche pour améliorer les logiciels et le code source, en termes de qualité générale - en réduisant le nombre de bogues et de problèmes logiciels. Rendre le code source compréhensible - le code source doit être lisible et compréhensible afin qu'il soit approuvé lors d'un audit de code. Faire en sorte que le logiciel se comporte de manière prévisible malgré des entrées ou des actions utilisateur inattendues. + +### Exemple de code : validation d'une entrée JSON complexe à l'aide de « Joi » + +```javascript +const memberSchema = Joi.object().keys({ + password: Joi.string().regex(/^[a-zA-Z0-9]{3,30}$/), + birthyear: Joi.number().integer().min(1900).max(2013), + email: Joi.string().email() +}); + +function addNewMember(newMember) { + // les vérifications sont faites en premier + Joi.assert(newMember, memberSchema); // lève une exception si la validation échoue + // d'autres logiques ici +} +``` + + + +### Contre exemple de code : aucune validation ne donne de méchants bogues + +
+Javascript + +```javascript +// si discount est positif, redirige l'utilisateur pour imprimer ses coupons de réduction +function redirectToPrintDiscount(httpResponse, member, discount) { + if (discount != 0) { + httpResponse.redirect(`/discountPrintView/${member.id}`); + } +} + +redirectToPrintDiscount(httpResponse, someMember); +// J'ai oublié de passer le paramètre discount, pourquoi diable l'utilisateur a-t-il été redirigé vers l'écran de remise ? +``` +
+ +
+Typescript + +```typescript +// si discount est positif, redirige l'utilisateur pour imprimer ses coupons de réduction +function redirectToPrintDiscount(httpResponse: Response, member: Member, discount: number) { + if (discount != 0) { + httpResponse.redirect(`/discountPrintView/${member.id}`); + } +} + +redirectToPrintDiscount(httpResponse, someMember, -12); +// Nous avons passé un paramètre discount négatif, pourquoi diable l'utilisateur a-t-il été redirigé vers l'écran de remise ? +``` +
+ +### Citation de blog : « Vous devriez rejeter ces erreurs immédiatement » + + Extrait du blog de Joyent + + > Un cas de dégénération est celui où quelqu'un appelle une fonction asynchrone mais ne passe pas de fonction de rappel. Vous devriez rejeter ces erreurs immédiatement car le programme est cassé et la meilleure chance de le déboguer implique d'obtenir au moins une trace de pile et idéalement un fichier core au niveau de l'erreur. Pour ce faire, nous vous recommandons de valider les types de tous les arguments au début de la fonction. diff --git a/sections/errorhandling/failfast.md b/sections/errorhandling/failfast.md index 805d7ac9b..486ae45d5 100644 --- a/sections/errorhandling/failfast.md +++ b/sections/errorhandling/failfast.md @@ -11,7 +11,7 @@ Defensive programming is an approach to improve software and source code, in ter ### Code example: validating complex JSON input using ‘Joi’ ```javascript -var memberSchema = Joi.object().keys({ +const memberSchema = Joi.object().keys({ password: Joi.string().regex(/^[a-zA-Z0-9]{3,30}$/), birthyear: Joi.number().integer().min(1900).max(2013), email: Joi.string().email() diff --git a/sections/errorhandling/monitoring.french.md b/sections/errorhandling/monitoring.french.md new file mode 100644 index 000000000..85071884a --- /dev/null +++ b/sections/errorhandling/monitoring.french.md @@ -0,0 +1,17 @@ +# Surveillance + +### Un paragraphe d'explication + +> Au niveau le plus élémentaire, la surveillance signifie que vous pouvez facilement identifier quand de mauvaises choses se produisent en production. Par exemple, en étant averti par email ou Slack. Le défi est de choisir le bon ensemble d'outils qui répondra à vos besoins sans vous ruiner. Permettez-moi de vous suggérer de commencer par définir l'ensemble des paramètres de base qui doivent être surveillés pour garantir un état sain - CPU, RAM du serveur, RAM du processus de Node (moins de 1,4 GB), le nombre d'erreurs dans la dernière minute, le nombre de redémarrages du processus , temps de réponse moyen. Ensuite, passez en revue certaines fonctionnalités avancées dont vous pourriez avoir envie et ajoutez-les à votre liste de souhaits. Quelques exemples d'une fonction de surveillance de luxe : profilage de base de données, mesure interservices (c.-à-d. mesurer les transactions commerciales), intégration frontale, exposer les données brutes aux clients BI personnalisés, notifications Slack et bien d'autres. + +La réalisation des fonctionnalités avancées nécessite une configuration longue ou l'achat d'un produit commercial tel que Datadog, newrelic et similaires. Malheureusement, atteindre même les bases n'est pas une promenade de santé car certaines mesures sont liées au matériel (CPU) et d'autres vivent dans le processus de Node (erreurs internes), donc tous les outils simples nécessitent une configuration supplémentaire. Par exemple, les solutions de surveillance des fournisseurs de cloud (par exemple AWS CloudWatch, Google StackDriver) vous informeront immédiatement de la métrique du matériel, mais rien du comportement de l'application interne. À l'autre extrémité, les solutions basées sur les journaux telles que ElasticSearch manquent par défaut de la vue matérielle. La solution consiste à étendre votre choix avec des mesures manquantes, par exemple, un choix populaire consiste à envoyer des journaux d'application à la pile Elastic et à configurer un agent supplémentaire (par exemple Beat) pour partager des informations liées au matériel pour obtenir une image complète. + +### Citation de blog : « Nous avons un problème avec les promesses" + + Extrait du blog de pouchdb.com classé en 11eme position pour les mots clés “Node Promises” + + > … Nous vous recommandons de surveiller ces signaux pour tous vos services : Taux d'erreur : parce que les erreurs sont confrontées à l'utilisateur et affectent immédiatement vos clients. +Temps de réponse : car la latence affecte directement vos clients et votre entreprise. +Débit : le trafic vous aide à comprendre le contexte de l'augmentation des taux d'erreur et de la latence également. +Saturation : il indique à quel point votre service est « saturé ». Si l'utilisation du processeur est de 90%, votre système peut-il gérer plus de trafic ? +… diff --git a/sections/errorhandling/operationalvsprogrammererror.basque.md b/sections/errorhandling/operationalvsprogrammererror.basque.md index 95f102c87..7fb594357 100644 --- a/sections/errorhandling/operationalvsprogrammererror.basque.md +++ b/sections/errorhandling/operationalvsprogrammererror.basque.md @@ -1,8 +1,8 @@ # Bereizi eragiketa erroreak eta programazio erroreak -### Azalpen paragrafoa +### Azalpena -Ondorengo bi errore mota hauek bereizteak zure aplikazioaren matxura denbora gutxitu eta programazio errore eroak ekiditen lagunduko dizu. Batetik, eragiketa erroreak daude, gertatutako arazoa eta haren ondorioak ulertzen dituzunean (adibidez, HTTP zerbitzu bati egindako deiak huts egitea, konexio arazoak direla eta. Bestetik, errorea zergatik eta nondik etorri den ez dakizun egoerei programatze errore deritze (balio zehaztugabe bat irakurtzen saiatzen den kodea edo memoria ihes egiten dion datu basea izan daitezke). Eragiketa erroreak besteen aldean kudea errazak dira, eta normalean nahikoa izaten da errorea erregistratzea. Gauzak konplikatuagoak izan daitezke garatzaile errore bat tupustean agertzen denean, aplikazioa egoera aldakorrean aurki baitaiteke. Horrelakoetan, aplikazioa berrabiarazi baino irtenbide hoberik ez duzu +Ondorengo bi errore mota hauek bereizteak zure aplikazioaren matxura denbora gutxitu eta programazio errore eroak ekiditen lagunduko dizu. Batetik, eragiketa erroreak daude, gertatutako arazoa eta haren ondorioak ulertzen dituzunean (adibidez, HTTP zerbitzu bati egindako deiak huts egitea, konexio arazoak direla eta. Bestetik, errorea zergatik eta nondik etorri den ez dakizun egoerei programatze errore deritze (balio zehaztugabe bat irakurtzen saiatzen den kodea edo memoria ihes egiten dion datu basea izan daitezke). Eragiketa erroreak besteen aldean kudea errazak dira, eta normalean nahikoa izaten da errorea erregistratzea. Gauzak konplikatuagoak izan daitezke garatzaile errore bat tupustean agertzen denean, aplikazioa egoera aldakorrean aurki baitaiteke. Horrelakoetan, aplikazioa berrabiarazi baino irtenbide hoberik ez duzu ### Kode adibidea: erroreak eragiketa errore (konfiantzazko) bihurtu @@ -71,30 +71,30 @@ throw new AppErrorea(
-### Blogeko aipua: "Programatzaileen erroreak programazio erroreak dira programan" +### Blog aipua: "Programatzaileen erroreak programatze erroreak dira programan" Joyent blogeko “Node.js errore kudeaketa" hitz gako bati esker sailkatua -> …Programatzaile erroreak gainditzeko modurik hoberena berehala huts eragitea da. Huts egiteren bat gertatzean automatikoki berrekingo dituen berrekite sistemaren bat erabiliz exekutatu beharko zenituzte zure programak. Berrekite sistemei esker, huts egitea da modurik azkarrena programatzaile errore iragankorrak gertatzean zerbitzua berreskuratzeko modu fidagarrian… +> …Programatzaile erroreak gainditzeko modurik hoberena berehala huts eragitea da. Huts egiteren bat gertatzean automatikoki berrekingo dituen berrekite sistemaren bat erabiliz exekutatu beharko zenituzten zure programak. Berrekite sistemei esker, huts egitea da modurik azkarrena programatzaile errore iragankorrak gertatzean zerbitzua berreskuratzeko modu fidagarrian… -### Blogeko aipua: "Alde egiteko modu segururik ez dago zehaztugabeko egoera hauskorrik sortu gabe" +### Blog aipua: "Alde egiteko modu segururik ez dago zehaztugabeko egoera hauskorrik sortu gabe" -Node.js dokumentazio ofizialetik hartua +Node.js dokumentazio ofiziala -> …Throw-ek JavaScripten nola funtzionatzen duen kontuan izanda, ez dago ia inoiz ataza bati modu seguruan “bertan behera utzitako puntuan segida ematerik” erreferentziak galdu gabe edota bestelako egoera hauskor zehaztugaberik sortu gabe. Jaurtitako erroreei erantzuteko modurik seguruena prozesua gelditzea da. Jakina, web zerbitzari arruntetan, konexio ugari eduki ahal ditzakezu irekita, eta ez da zentzuzkoa tupustean haiek ixtea beste batek eragindako errore batengatik. Planteamendu hoberena da errorea bidali duen eskariari errore erantzun bat bidaltzea, besteei beren atazak bukatzeko denbora emanez, eta eskari berriei kasu egiteari utzi prozesu horretan. +> …Throw-ek JavaScripten nola funtzionatzen duen kontuan izanda, ez dago ia inoiz ataza bati modu seguruan “bertan behera utzitako puntuan segida ematerik” erreferentziak galdu gabe edota bestelako egoera hauskor zehaztugaberik sortu gabe. Jaurtitako erroreei erantzuteko modurik seguruena prozesua gelditzea da. Jakina, web zerbitzari arruntetan, konexio ugari eduki ahal ditzakezu irekita, eta ez da zentzuzkoa tupustean haiek ixtea beste batek eragindako errore batengatik. Planteamendu hoberena da errorea bidali duen eskariari errore erantzun bat bidaltzea, besteei beren atazak bukatzeko denbora emanez, eta eskari berriei kasu egiteari utzi prozesu horretan -### Blogeko aipua: "Bestela zure aplikazioaren egoera arriskuan jar dezakezu" +### Blog aipua: "Bestela zure aplikazioaren egoera arriskuan jar dezakezu" -debugable.com blogetik, “Node.js harrapatu gabeko exzepzioa" 3 hitz gakori esker sailkatua +debugable.com blogeko “Node.js atzeman gabeko salbuespena" 3 hitz gakoari esker sailkatua -> …Beraz, baldin eta benetan egiten ari zarena jakiten baduzu, “uncaughtException” exzepzio ebentua jaso ostean zure zerbitzuaren berrekite dotorea egin beharko zenuke. Bestela, zure aplikazioaren egoera arriskuan jar dezakezu, edota haren liburutegiak aldakor bihurtuarazi, mota guztietako errore zoroak eraginez… +> …Beraz, baldin eta benetan zer egiten ari zaren jakinez gero, “uncaughtException” salbuespen gertaera jaso ostean zure zerbitzuari berrekin beharko zenioke, behar bezala berrekin ere. Bestela, zure aplikazioaren egoera arriskuan jar dezakezu, edota haren liburutegiak aldakor bihurtuarazi, mota guztietako errore zoroak eraginez… -### Blogeko aipua: "Errore kudeaketaren inguruko hiru ideia eskola daude" +### Blog aipua: "Errore kudeaketaren inguruko hiru ideia eskola daude" -JS Recipes blogetik hartua +JS Recipes bloga > …Errore kudeaketaren inguruko hiru ideia eskola daude: 1. Utzi aplikazioak huts egin dezan eta ondoren berrekin. -2. Kudeatu errore posible guztiak kudeatu eta inoiz ez huts egin. +2. Kudeatu errore posible guztiak eta inoiz ez huts egin. 3. Bien arteko planteamendu bat. diff --git a/sections/errorhandling/operationalvsprogrammererror.chinese.md b/sections/errorhandling/operationalvsprogrammererror.chinese.md index c8c070e49..768dbb79f 100644 --- a/sections/errorhandling/operationalvsprogrammererror.chinese.md +++ b/sections/errorhandling/operationalvsprogrammererror.chinese.md @@ -34,8 +34,7 @@ throw new appError(errorManagement.commonErrors.InvalidInput, "Describe here wha ### 博客引用: "不伴随着创建一些未定义的脆性状态,没有安全的方式可以离开" 摘自Node.JS官方文档 - > …在 JavaScript 中, throw的工作性质, 几乎没有任何方法可以安全地"在你离开的地方重新捡起",没有泄漏引用, 或者创建一些其他形式的未定义的脆性状态,。对引发的错误进行响应的最安全方法是关闭进程。当然, 在普通的 web 服务器中, 您可能会打开许多连接, 并且由于其他人触发了错误而突然关闭这些连接是不合理的。更好的方法是向触发错误的请求发送错误响应, 同时让其他人在正常时间内完成, 并停止侦听该工作人员中的新请求。 - + > …从 JavaScript throw 的工作原理上讲, 几乎没有任何方法可以安全地“在你跌倒的地方重新爬起来”而不引发泄漏且不创建一些其他形式的未定义的脆性状态。响应(未定义的)抛出错误的最安全方法是关闭进程。当然, 通常 web 服务器可能会有许多连接正在通信, 由于某个人触发了错误而突然关闭那些连接是不合理的。更好的方法是让该工作进程向触发错误的请求发送错误响应, 同时保持其它请求正常进行直至完成, 并停止侦听的新的请求。(译者注:为优雅重启做准备) ### 博客引用: "否则,您置您应用的状态于风险之中" 摘自博客 debugable.com, 对于关键字“Node.JS uncaught exception”排名第3 diff --git a/sections/errorhandling/operationalvsprogrammererror.french.md b/sections/errorhandling/operationalvsprogrammererror.french.md new file mode 100644 index 000000000..165d8bb65 --- /dev/null +++ b/sections/errorhandling/operationalvsprogrammererror.french.md @@ -0,0 +1,85 @@ +# Distinguez les erreurs opérationnelles des erreurs de programmation + +### Un paragraphe d'explication + +La distinction des deux types d'erreur suivants minimisera l'indisponibilité de votre application et aidera à éviter les bogues fous : les erreurs opérationnelles se rapportent à des situations où vous comprenez ce qui s'est passé et son impact - par exemple, une requête vers un service HTTP a échoué en raison d'un problème de connexion. D'un autre côté, les erreurs de programmation se rapportent à des cas où vous n'avez aucune idée de la raison et parfois de l'origine d'une erreur - il peut s'agir d'un code qui a tenté de lire une valeur non définie ou d'un pool de connexions DB qui a une fuite mémoire. Les erreurs opérationnelles sont relativement faciles à gérer - la journalisation de l'erreur suffit généralement. Les choses deviennent compliquées lorsqu'une erreur de programmation apparaît, l'application peut être dans un état incohérent et il n'y a rien de mieux que de redémarrer en douceur. + +### Exemple de code - marquer une erreur comme opérationnelle (fiable) + +
+Javascript + +```javascript +// marquer un objet Error comme opérationnel +const myError = new Error('Comment puis-je ajouter un nouveau produit lorsqu\'aucune valeur n\'est fournie ?'); +myError.isOperational = true; + +// ou si vous utilisez une fabrique d'erreurs centralisée (voir d'autres exemples pour le point "Utilisez uniquement l'objet intégré Error") +class AppError { + constructor (commonType, description, isOperational) { + Error.call(this); + Error.captureStackTrace(this); + this.commonType = commonType; + this.description = description; + this.isOperational = isOperational; + } +}; + +throw new AppError(errorManagement.commonErrors.InvalidInput, 'Décrivez ici ce qui s\'est passé', true); + +``` +
+ +
+Typescript + +```typescript +// une fabrique d'erreurs centralisée (voir d'autres exemples pour le point "Utilisez uniquement l'objet intégré Error") +export class AppError extends Error { + public readonly commonType: string; + public readonly isOperational: boolean; + + constructor(commonType: string, description: string, isOperational: boolean) { + super(description); + + Object.setPrototypeOf(this, new.target.prototype); // restaure la chaîne du prototype + + this.commonType = commonType; + this.isOperational = isOperational; + + Error.captureStackTrace(this); + } +} + +// marquer un objet Error comme opérationnel (true) +throw new AppError(errorManagement.commonErrors.InvalidInput, 'Describe here what happened', true); + +``` +
+ +### Citation de blog : « Les erreurs du programmeur sont des bogues dans le programme » + +Extrait du blog de Joyent classé en 1ere position pour les mots clés “Node.js error handling” + + > …La meilleure façon de récupérer des erreurs de programmation est de planter immédiatement. Vous devez exécuter vos programmes à l'aide d'un « outil de redémarrage » qui redémarrera automatiquement le programme en cas de plantage. Avec un « outil de redémarrage » en place, le plantage est le moyen le plus rapide de restaurer un service fiable face à une erreur de programmation transitoire… + +### Citation de blog : « Aucune solution sûre pour sortir sans créer un état fragile indéfini » + +Extrait de la documentation officielle de Node.js + + > …De par la nature même du fonctionnement de throw en JavaScript, il n'y a presque jamais aucun moyen de « reprendre là où vous vous étiez arrêté » en toute sécurité, sans fuite de références, ou sans créer une autre sorte d'état fragile non défini. Le moyen le plus sûr de répondre à une erreur levée est d'arrêter le processus. Bien sûr, dans un serveur Web normal, de nombreuses connexions peuvent être ouvertes et il n'est pas raisonnable de les fermer brutalement car une erreur a été déclenchée par quelqu'un d'autre. La meilleure approche consiste à envoyer une réponse d'erreur à la demande qui a déclenché l'erreur tout en laissant les autres se terminer dans leur temps normal et à cesser d'écouter les nouvelles demandes de ce processus. + +### Citation de blog : « Sinon, vous risquez l'état de votre application » + +Extrait du blog de debugable.com classé en 3ème position pour les mots clés “Node.js uncaught exception” + + > …Donc, à moins que vous sachiez vraiment ce que vous faites, vous devez effectuer un redémarrage en douceur de votre service après avoir reçu un événement d'exception « uncaughtException ». Sinon, vous risquez que l'état de votre application, ou celui des bibliothèques tierces, ne devienne incohérent, conduisant à toutes sortes de bugs fous… + +### Citation de blog : « Il y a principalement trois écoles de réflexion sur la gestion des erreurs » + +Extrait du blog de JS Recipes + +> …Il y a principalement trois écoles de réflexion sur la gestion des erreurs : +1. Laissez l'application se planter et redémarrez-la. +2. Gérez toutes les erreurs possibles et ne plantez jamais. +3. Une approche équilibrée entre les deux diff --git a/sections/errorhandling/operationalvsprogrammererror.md b/sections/errorhandling/operationalvsprogrammererror.md index 69ccee2c3..162e09495 100644 --- a/sections/errorhandling/operationalvsprogrammererror.md +++ b/sections/errorhandling/operationalvsprogrammererror.md @@ -80,6 +80,6 @@ From the blog, debugable.com ranked 3 for the keywords “Node.js uncaught excep From the blog: JS Recipes > …There are primarily three schools of thoughts on error handling: -1. Let the application crash and restart it. -2. Handle all possible errors and never crash. -3. A balanced approach between the two +>1. Let the application crash and restart it. +>2. Handle all possible errors and never crash. +>3. A balanced approach between the two diff --git a/sections/errorhandling/returningpromises.basque.md b/sections/errorhandling/returningpromises.basque.md index 463eb78f7..41b8cb5bd 100644 --- a/sections/errorhandling/returningpromises.basque.md +++ b/sections/errorhandling/returningpromises.basque.md @@ -2,9 +2,9 @@
-### Azalpen paragrafoa +### Azalpena -Errore bat gertatzen denean fluxu sinkrono edo asinkrono batetik abiatuta, derrigorrezkoa da errore fluxuaren pila aztarna osoa edukitzea. Harrigarria bada ere, funtzio asinkrono batek (adibidez beste funtzio asinkrono bat deitzen duena) itxaron gabe (await) promesak itzultzen dituenean, errore bat gertatuko litzateke eta jatorrizko funtzio horren izena ez litzateke pilaren aztarnan agertu beharko. Horrek informazio partziala emango dio errorea diagnostikatzen duenari, are gehiago errorearen zergatiak jatorrizko funtzioan badu oinarria. Badago "zero-kostuko pila aztarna asinkronoak" deitzen den v8 funtzionalitate bat, pila aztarnak azken gertatu berri den `await`ean moztuak ez izatea ahalbidetzen duena. Garrantzirik gabeko inplementazio xehetasunak direla eta, horrek ez du funtzionatuko funtzioak bueltatzen duen balioa (sinkronoa edo asinkronoa), promesa bat baldin bada. Promesak deusezten direnean pilaren aztarnan zuloak egotea ekiditeoko, promesak beti esplizituki ebatzi behar ditugu `await` erabiliz beraiek funtzioetatik bueltatu baino lehen +Errore bat gertatzen denean fluxu sinkrono edo asinkrono batetik abiatuta, derrigorrezkoa da errore fluxuaren pila aztarna osoa edukitzea. Harrigarria bada ere, funtzio asinkrono batek (adibidez beste funtzio asinkrono bat deitzen duena) itxaron gabe (await) promesak itzultzen dituenean, errore bat gertatuko litzateke eta jatorrizko funtzio horren izena ez litzateke pilaren aztarnan agertu beharko. Horrek informazio partziala emango dio errorea diagnostikatzen duenari, are gehiago errorearen zergatiak jatorrizko funtzioan badu oinarria. Badago "zero-kostuko pila aztarna asinkronoak" deitzen den v8 funtzionalitate bat, pila aztarnak azken gertatu berri den `await`ean moztuak ez izatea ahalbidetzen duena. Garrantzirik gabeko inplementazio xehetasunak direla eta, horrek ez du funtzionatuko funtzioak bueltatzen duen balioa (sinkronoa edo asinkronoa) promesa bat baldin bada. Promesak deuseztatzen direnean pilaren aztarnan zuloak egotea ekiditeko, promesak beti esplizituki ebatzi behar ditugu `await` erabiliz beraiek funtzioetatik bueltatu baino lehen
@@ -137,9 +137,9 @@ Error: zati guztiak edukiz

-
+
-### Kode adibidea, anti eredua #3: callback asinkronoen erabilera zuzena callback sinkronoa espero zen lekuan +### #3 anti ereduaren kode adibidea: callback asinkronoen erabilera zuzena callback sinkronoa espero zen lekuan
Javascript

@@ -229,31 +229,31 @@ Zero kostuko pila aztarna asinkronoak" deitzen den v8 funtzionalitate bat ## Azalpen aurreratua -Oso ezberdinak dira funtzio sinkronoen pila aztarnen eta funtzio asinkronoen pila aztarnen mekanismoak v8ren ezarpenetan: pila aztarna asinkronoa oinarritua dago Node.js martxan dagoen sistema eragileak emandako **pila**n (programazio lengoaia gehienak bezala). Funtzio asinkrono bat exekutatzen ari denean, sistema eragileko **pila** agerian jartzen da funtzioa bere lehen `await`era iristen den momentuan. Beraz, pilaren aztarna nahasketa bat da, hain zuzen, sistema eragilearen pilaren eta baztertutako **promesa ebazpen katea**rena. Zero kostuko pila aztarna asinkronoen ezarpenak **promesa ebazpen katea** luzatzen du bakarrik promesa `itxaroten` [¹](#1) ari den bitartean. Funtzio asinkronoek bakarrik (`async`) itxaron (`await`) ahal dutenez, beti galduko da funtzio asinkronoa pilaren aztarna asinkrono batean, operazio asinkronoren bat izan bada funtzioa deitu eta gero [²](#2) +Oso ezberdinak dira funtzio sinkronoen pila aztarnen eta funtzio asinkronoen pila aztarnen mekanismoak v8ren ezarpenetan: pila aztarna asinkronoa oinarritua dago Node.js martxan dagoen sistema eragileak emandako **pila**n (programazio lengoaia gehienak bezala). Funtzio asinkrono bat exekutatzen ari denean, sistema eragileko **pila** agerian jartzen da funtzioa bere lehen `await`era iristen den momentuan. Beraz, pilaren aztarna nahasketa bat da, hain zuzen, sistema eragilearen pilaren eta baztertutako **promesa ebazpen katea**rena. Zero kostuko pila aztarna asinkronoen ezarpenak **promesaren ebazpen katea** luzatzen du bakarrik promesa `itxaroten` [¹](#1) ari den bitartean. Funtzio asinkronoek bakarrik (`async`) itxaron (`await`) ahal dutenez, beti galduko da funtzio asinkronoa pilaren aztarna asinkrono batean, operazio asinkronoren bat izan bada funtzioa deitu eta gero [²](#2) -### The tradeoff (sektorea) +### Erdibidea -`await` bakoitzak mikro ataza berri bat sortzen du gertaeraren begiztan. Beraz `await` gehiago gehitzeak errendimendu zigorra ekarriko luke. Hala ere, sareak edota datu baseak sortutako errendimendu isuna [ikaragarri handiagoa](https://colin-scott.github.io/personal_website/research/interactive_latency.html) da, eta, beraz gehitutako `await`aren zigorra ez da zerbitzariak edo CLIak garatzeko orduan kontutan hartu beharreko zerbait, eskaera edo komando bakoitzeko oso kode beroa izan ezean behintzat. Orduan, `await` ezabatzeak `return await`etan errendimendu bultzada nabarmena bilatzeko azken lekua izan beharko luke eta, zalantzarik gabe, inoiz ez litzateke aldez aurretik egin beharko +`await` bakoitzak mikro ataza berri bat sortzen du gertaeraren begiztan. Beraz, `await` gehiago gehitzeak errendimendu zigorra ekarriko luke. Hala ere, sareak edota datu baseak sortutako errendimendu isuna [ikaragarri handiagoa](https://colin-scott.github.io/personal_website/research/interactive_latency.html) da, eta, beraz, gehitutako `await`aren zigorra ez da zerbitzariak edo CLIak garatzeko orduan kontutan hartu beharreko zerbait, eskaera edo komando bakoitzeko oso kode beroa izan ezean behintzat. Orduan, `await`ak ezabatzeak `return await`etan errendimendu bultzada nabarmena bilatzeko azken lekua izan beharko luke eta, zalantzarik gabe, inoiz ez litzateke aldez aurretik egin beharko ### Zergatik jotzen zen await bueltatzea anti eredutzat iraganean -[Artikulu bikain](https://jakearchibald.com/2017/await-vs-return-vs-return-await/) ugari daude azaltzen dutenak zergatik `return await`ak ez diren inoiz `try` bloketik kanpo erabili behar, bai eta [ESLint arau](https://eslint.org/docs/rules/no-return-await) arau bat ere hori debekatzen duena. Horren arrazoia da async/await Node.js 0.10ko transpilagailuekin erabilgarri bihurtu izana (eta jatorrizko laguntza lortu dutela Node.js 7.6 bertsioan) eta "zero kostuko pila aztarna asinkronoak" Node.js 10en gehitua izana eta ondoren Node.js 12tik kendua, `return await` eta `return` guztiz parekoak ziren, edozein `try` kode bloketik kanpo. Oraindik ere berdina izaten jarraituko du seguraski ES motoreentzat. Horregatik, Node.jsentzat jardunbide egokiena da promesak kalkulatzea beraiek bueltatu aurretik. EcmaScriptentzat, ordea, hori ez jardunbide egokiena. +[Artikulu bikain](https://jakearchibald.com/2017/await-vs-return-vs-return-await/) ugari daude azaltzen dutenak zergatik `return await`ak ez diren inoiz `try` bloketik kanpo erabili behar, bai eta [ESLint arau](https://eslint.org/docs/rules/no-return-await) bat ere hori debekatzen duena. Horren arrazoia da async/await erabilgarri bihurtu izana Node.js 0.10ko transpilagailuekin (eta jatorrizko laguntza lortu dutela Node.js 7.6 bertsioan), eta "zero kostuko pila aztarna asinkronoak" Node.js 10era gehitua izana, eta ondoren Node.js 12tik kendua, `return await` eta `return` guztiz parekoak zirela, edozein `try` kode bloketik kanpo. Oraindik ere berdina izaten jarraituko du seguraski ES motoreentzat. Horregatik, Node.jsrentzat praktika onena da promesak kalkulatzea beraiek bueltatu aurretik. EcmaScriptentzat, ordea, hori ez praktika onena ### Oharrak: 1. Pila aztarna asinkronoak halako ezarpen korapilatsua izatearen beste arrazoi bat da pila aztarna beti modu sinkronoan eraiki behar dela, gertaeraren begiztaren [¹](#1) momentu berean -2. `throwAsync` barruan `await` gabe, gertaera begiztaren fase berean exekutatuko litzateke kodea. Hori, degeneratutako kasua da: sistema eragilearen **pila** ez litzateke hustuko, eta pila aztarna beteko litzateke funtzioaren emaitzari berariaz itxaron gabe ere. Normalean, promesen erabilerak operazio asinkrono batzuk edukitzen dituenez, pilaren aztarnaren zati batzuk galdu egingo lirateke +2. `throwAsync` barruan `await` gabe, gertaera begiztaren fase berean exekutatuko litzateke kodea. Hori, degeneratutako kasua da: sistema eragilearen **pila** ez litzateke hustuko, eta pila aztarna beteko litzateke funtzioaren emaitzari berariaz itxaron gabe ere. Normalean, promesen erabilerak operazio asinkrono batzuk edukitzen dituenez, pilaren aztarnaren zati batzuk galdu egingo lirateke -3. Zero kostuko pila aztarna asinkronoek ez lukete funtzionatuko promesa erabileren kasu korapilatsuetan: promesa bakar bati hainbat aldiz eta leku ezberdinetan itxaron beharra dagoenean, adibidez. +3. Zero kostuko pila aztarna asinkronoek ez lukete funtzionatuko promesa erabileren kasu korapilatsuetan: promesa bakar bati hainbat aldiz eta leku ezberdinetan itxaron beharra dagoenean, adibidez ### Erreferentziak: 1. [v8ko zero kostuko pila aztarna asinkronoak blog argitarapena](https://v8.dev/blog/fast-async) -
+
2. [zero kostuko pila aztarna asinkronoei inguruko dokumentazioa ezarpen xehetasunekin hemen]( https://docs.google.com/document/d/13Sy_kBIJGP0XT34V1CV3nkWya4TwYx9L3Yv45LdGB6Q/edit ) -
+
diff --git a/sections/errorhandling/returningpromises.french.md b/sections/errorhandling/returningpromises.french.md new file mode 100644 index 000000000..bdbe22e1a --- /dev/null +++ b/sections/errorhandling/returningpromises.french.md @@ -0,0 +1,285 @@ +# Le retour des promesses + +
+ +### Un paragraphe d'explication + +Lorsqu'une erreur se produit, qu'elle provienne d'un flux synchrone ou asynchrone, il est impératif de disposer d'une trace de pile complète du flux d'erreurs. Étonnamment, lorsqu'une fonction `async` renvoie une promesse sans `await` (par exemple, elle appelle une autre fonction `async`), si une erreur se produit, la fonction appelante n'apparaîtra pas dans la trace de la pile. La personne qui diagnostiquera l'erreur ne disposera donc que d'une information partielle - d'autant plus si la cause de l'erreur se situe dans cette fonction d'appel. Il existe une fonctionnalité v8 appelée "zero-cost async stacktraces" qui permet de ne pas couper les traces de pile sur les `await` les plus récents. Mais sans certaines modalités de mise en œuvre non négligeables, elle ne fonctionnera pas si la valeur de retour d'une fonction (sync ou async) est une promesse. Donc, pour éviter les trous dans les traces de pile lorsque des promesses retournées sont rejetées, nous devons toujours résoudre explicitement les promesses avec `await` avant de les retourner à partir des fonctions. + +
+ +### Exemple de code incorrect : appel d'une fonction async sans await + +

Javascript +

+ +```javascript +async function throwAsync(msg) { + await null // il faut attendre au moins quelque chose pour être vraiment asynchrone (voir note n° 2) + throw Error(msg) +} + +async function returnWithoutAwait () { + return throwAsync('manque returnWithoutAwait dans la trace de pile') +} + +// 👎 N'aura PAS la fonction returnWithoutAwait dans la trace de pile +returnWithoutAwait().catch(console.log) +``` + +log reçu + +``` +Error: manque returnWithoutAwait dans la trace de pile + at throwAsync ([...]) +``` +

+
+ +### Exemple de code : appel d'une fonction async avec await approprié + +
Javascript +

+ +```javascript +async function throwAsync(msg) { + await null // il faut attendre au moins quelque chose pour être vraiment asynchrone (voir note n° 2) + throw Error(msg) +} + +async function returnWithAwait() { + return await throwAsync('avec toutes les instructions présentes') +} + +// 👍 aura la fonction returnWithoutAwait dans la trace de pile +returnWithAwait().catch(console.log) +``` + +log reçu + +``` +Error: avec toutes les instructions présentes + at throwAsync ([...]) + at async returnWithAwait ([...]) +``` + +

+
+ +
+ +### Exemple de code incorrect : retourner une promesse sans marquer la fonction comme async + +
Javascript +

+ +```javascript +async function throwAsync () { + await null // il faut attendre au moins quelque chose pour être vraiment asynchrone (voir note n° 2) + throw Error('manque syncFn dans la trace de pile') +} + +function syncFn () { + return throwAsync() +} + +async function asyncFn () { + return await syncFn() +} + +// 👎 syncFn manquera dans la trace de pile parce qu'elle renverra une promesse alors qu'elle est sync +asyncFn().catch(console.log) +``` + +log reçu + +``` +Error: manque syncFn dans la trace de pile + at throwAsync ([...]) + at async asyncFn ([...]) +``` + +

+
+ +### Exemple de code : marquer la fonction comme async car elle renvoie une promesse + +
Javascript +

+ +```javascript +async function throwAsync () { + await null // il faut attendre au moins quelque chose pour être vraiment asynchrone (voir note n° 2) + throw Error('avec toutes les instructions présentes') +} + +async function changedFromSyncToAsyncFn () { + return await throwAsync() +} + +async function asyncFn () { + return await changedFromSyncToAsyncFn() +} + +// 👍 maintenant changedFromSyncToAsyncFn sera présent dans la trace de la pile +asyncFn().catch(console.log) +``` + +log reçu + +``` +Error: avec toutes les instructions présentes + at throwAsync ([...]) + at changedFromSyncToAsyncFn ([...]) + at async asyncFn ([...]) +``` + +

+
+ +
+ +### Exemple de code incorrect : utilisation directe du rappel async lorsque le rappel sync est attendu + +
Javascript +

+ +```javascript +async function getUser (id) { + await null + if (!id) throw Error('la trace de pile n\'indique pas l\'endroit où getUser a été appelé') + return {id} +} + +const userIds = [1, 2, 0, 3] + +// 👎 la trace de pile aura la fonction getUser mais ne donnera aucune indication sur l'endroit où elle a été appelée +Promise.all(userIds.map(getUser)).catch(console.log) +``` + +log reçu + +``` +Error: la trace de pile n'indique pas l'endroit où getUser a été appelé + at getUser ([...]) + at async Promise.all (index 2) +``` + +*Remarque complémentaire* : on pourrait croire que `Promise.all (index 2)` peut aider à comprendre l'endroit où `getUser` a été appelé, +mais en raison d'un [bogue complètement différent dans la v8](https://bugs.chromium.org/p/v8/issues/detail?id=9023), `(index 2)` est +une ligne interne de v8 + +

+
+ +### Exemple de code : envelopper le rappel async dans une fonction async factice avant de le passer en rappel sync + +
Javascript +

+ +*Remarque 1* : si vous contrôlez le code de la fonction qui appelle le rappel, changez simplement cette fonction +en async et ajoutez `await` avant l'appel du rappel. Ci-dessous, je suppose que vous n'êtes pas en charge du code qui appelle +le rappel (ou que son changement est inacceptable, par exemple en raison de la rétrocompatibilité) + +*Remarque 2* : très souvent, l'utilisation du rappel async dans les endroits où l'on s'attend à ce qu'il soit sync ne fonctionnerait pas du tout. Il ne s'agit pas +de savoir comment réparer le code qui ne fonctionne pas - il s'agit de savoir comment réparer la trace de pile au cas où le code fonctionne déjà +comme prévu + +```javascript +async function getUser (id) { + await null + if (!id) throw Error('avec toutes les instructions présentes') + return {id} +} + +const userIds = [1, 2, 0, 3] + +// 👍 maintenant la ligne ci-dessous est dans la trace de la pile +Promise.all(userIds.map(async id => await getUser(id))).catch(console.log) +``` + +log reçu + +``` +Error: avec toutes les instructions présentes + at getUser ([...]) + at async ([...]) + at async Promise.all (index 2) +``` + +grâce au `await` explicite dans `map`, la fin de la ligne `at async ([...])` indique l'endroit exact où +`getUser` est appelé + +*Remarque complémentaire* : si la fonction async qui enveloppe `getUser` n'a pas `await` avant le retour (exemple incorrect n°1 + exemple incorrect n°3) +alors il ne restera qu'une seule instruction dans la trace de la pile : + +```javascript +[...] + +// 👎 exemple incorrect n°1 + exemple incorrect n°3 - une seule instruction dans la trace de la pile +Promise.all(userIds.map(async id => getUser(id))).catch(console.log) +``` + +log reçu + +``` +Error: [...] + at getUser ([...]) +``` + +

+
+ +
+ +## Explication approfondie + +Les mécanismes des traces de piles des fonctions de sync et des fonctions async dans l'implémentation de la v8 sont très différents : +La trace de pile sync est basée sur la **pile** fournie par le système d'exploitation sur lequel tourne Node.js (comme dans la plupart des langages +de programmation). Lorsqu'une fonction async est en cours d'exécution, la **pile** du système d'exploitation l'a sort dès que la +fonction est arrivée à son premier `await`. Donc la trace de pile async est un mélange de la **pile** du système d'exploitation et d'une +**chaîne de résolution des promesses** rejetées. L'implémentation "zero-cost async stacktraces" étend la **chaîne de résolution des promesses** +uniquement lorsque la promesse est `awaited` [¹](#1). Parce que seules les fonctions `async` peuvent `await`, +la fonction sync sera toujours manquante dans la trace de la pile async si une opération async a été effectuée après que la fonction +a été appelé [²](#2) + +### Le compromis + +Chaque `await` crée une nouvelle micro-tâche dans la boucle d'événement, donc l'ajout d'autres `await` dans le code +introduit une certaine pénalité de performance. Néanmoins, la pénalité de performance introduite par le réseau ou +la base de données est [énormément plus grande](https://colin-scott.github.io/personal_website/research/interactive_latency.html) +donc la pénalité supplémentaire `await` n'est pas quelque chose qui devrait être considéré pendant le développement de serveurs web ou de CLI +sauf pour un code très chaud par requête ou commande. Donc, la suppression de `await` dans +les `return await` devrait être l'un des derniers moyens pour améliorer sensiblement les performances +et ne doit absolument pas être fait en amont. + + +### Pourquoi return await était considéré comme incorrect dans le passé + +Un certain nombre d'[excellents articles](https://jakearchibald.com/2017/await-vs-return-vs-return-await/) expliquent +pourquoi `return await` ne devrait jamais être utilisée en dehors du bloc `try` et même une +[règle ESLint](https://eslint.org/docs/rules/no-return-await) l'interdit. La raison, c'est que depuis que async/await +est disponible avec des transpileurs dans Node.js 0.10 (et a obtenu un support natif dans Node.js 7.6) et jusqu'à ce +que "zero-cost async stacktraces" a été introduit dans Node.js 10 et démarqué dans Node.js 12, `return await` était absolument +équivalent à `return` pour tout code en dehors du bloc `try`. Il se peut que ce soit encore le cas pour certains autres moteurs ES. +C'est pourquoi la résolution des promesses avant de les retourner est la meilleure pratique pour Node.js et non pour EcmaScript en général + +### Remarques : + +1. Une autre raison pour laquelle la trace de pile async a une implémentation aussi délicate, c'est que la trace de pile +doit toujours être construite de manière synchrone, sur le même rythme que la boucle d'événement [¹](#1) +2. Sans `await` dans `throwAsync`, le code serait exécuté dans la même phase de la boucle d'événements. C'est un cas +dégradé où la **pile** de l'OS ne serait pas vide et la trace de pile serait pleine même sans attendre +explicitement le résultat de la fonction. Habituellement, l'utilisation des promesses inclut des opérations asynchrones +et des parties de la trace de la pile sont perdues +3. Zero-cost async stacktraces ne fonctionnera toujours pas pour les usages compliqués de la promesse, par exemple la promesse unique +attendue à plusieurs reprises dans différents endroits + +### Références : + 1. [article de blog sur zero-cost async stacktraces en v8](https://v8.dev/blog/fast-async) +
+ + 2. [Document sur zero-cost async stacktraces avec les détails de mise en œuvre mentionnés ici]( + https://docs.google.com/document/d/13Sy_kBIJGP0XT34V1CV3nkWya4TwYx9L3Yv45LdGB6Q/edit + ) +
diff --git a/sections/errorhandling/returningpromises.md b/sections/errorhandling/returningpromises.md index 7ba1861ca..11ebc5a67 100644 --- a/sections/errorhandling/returningpromises.md +++ b/sections/errorhandling/returningpromises.md @@ -4,7 +4,7 @@ ### One Paragraph Explainer -When an error occurs, whether from a synchronous or asynchronous flow, it's imperative to have a full stacktrace of the error flow. Surprisingly, if an async function returns a promise (e.g., calls other async function) without awaiting, should an error occur then the caller function won't appear in the stacktrace. This will leave the person who diagnoses the error with partial information - All the more if the error cause lies within that caller function. There is a feature v8 called "zero-cost async stacktraces" that allow stacktraces not to be cut on the most recent `await`. But due to non-trivial implementation details, it will not work if the return value of a function (sync or async) is a promise. So, to avoid holes in stacktraces when returned promises would be rejected, we must always explicitly resolve promises with `await` before returning them from functions +When an error occurs, whether from a synchronous or asynchronous flow, it's imperative to have a full stacktrace of the error flow. Surprisingly, if an async function returns a promise (e.g. calls other async function) without awaiting, should an error occur then the caller function won't appear in the stacktrace. This will leave the person who diagnoses the error with partial information - All the more if the error cause lies within that caller function. There is a v8 feature called "zero-cost async stacktraces" that allows stacktraces to not be cut on the most recent `await`. But due to non-trivial implementation details, it will not work if the return value of a function (sync or async) is a promise. So, to avoid holes in stacktraces when returned promises would be rejected, we must always explicitly resolve promises with `await` before returning them from functions
@@ -87,7 +87,7 @@ async function asyncFn () { return await syncFn() } -// 👎 syncFn would be missing in the stacktrace because it returns a promise while been sync +// 👎 syncFn would be missing in the stacktrace because it returns a promise while being sync asyncFn().catch(console.log) ``` @@ -137,7 +137,7 @@ Error: with all frames present

-
+
### Code Example Anti-pattern #3: direct usage of async callback where sync callback is expected @@ -165,7 +165,7 @@ Error: stacktrace is missing the place where getUser has been called at async Promise.all (index 2) ``` -*Side-note*: it may looks like `Promise.all (index 2)` can help understanding the place where `getUser` has been called, +*Side-note*: it may look like `Promise.all (index 2)` can help understanding the place where `getUser` has been called, but due to a [completely different bug in v8](https://bugs.chromium.org/p/v8/issues/detail?id=9023), `(index 2)` is a line from internals of v8 @@ -177,9 +177,9 @@ a line from internals of v8
Javascript

-*Note 1*: in case if you control the code of the function that would call the callback - just change that function to -async and add `await` before the callback call. Below I assume that you are not in charge of the code that is calling -the callback (or it's change is unacceptable for example because of backward compatibility) +*Note 1*: if you control the code of the function that would call the callback - just change that function to +`async` and add `await` before the callback call. Below I assume that you are not in charge of the code that is calling +the callback (or its change is unacceptable for example because of backward compatibility) *Note 2*: quite often usage of async callback in places where sync one is expected would not work at all. This is not about how to fix the code that is not working - it's about how to fix stacktrace in case if code is already working as @@ -210,8 +210,8 @@ Error: with all frames present where thanks to explicit `await` in `map`, the end of the line `at async ([...])` would point to the exact place where `getUser` has been called -*Side-note*: if async function that wrap `getUser` would miss `await` before return (anti-pattern #1 + anti-pattern #3) -then only one frame would left in the stacktrace: +*Side-note*: if async function that wrap `getUser` lacks `await` before return (anti-pattern #1 + anti-pattern #3) +then only one frame would be left in the stacktrace: ```javascript [...] @@ -235,12 +235,12 @@ Error: [...] ## Advanced explanation The mechanisms behind sync functions stacktraces and async functions stacktraces in v8 implementation are quite different: -sync stacktrace is based on **stack** provided by operating system Node.js is running on (just like in most programming -languages). When an async function is executing, the **stack** of operating system is popping it out as soon as the -function is getting to it's first `await`. So async stacktrace is a mix of operating system **stack** and a rejected -**promise resolution chain**. Zero-cost async stacktraces implementation is extending the **promise resolution chain** +sync stacktrace is based on **stack** provided by the operating system Node.js is running on (just like in most programming +languages). When an async function is executing, the **stack** of the operating system is popping it out as soon as the +function gets to its first `await`. So async stacktrace is a mix of operating system **stack** and a rejected +**promise resolution chain**. Zero-cost async stacktraces implementation extends the **promise resolution chain** only when the promise is getting `awaited` [¹](#1). Because only `async` functions may `await`, -sync function would always be missed in async stacktrace if any async operation has been performed after the function +sync function would always be missing from async stacktrace if any async operation has been performed after the function has been called [²](#2) ### The tradeoff @@ -256,30 +256,30 @@ definitely should never be done up-front ### Why return await was considered as anti-pattern in the past -There is a number of [excellent articles](https://jakearchibald.com/2017/await-vs-return-vs-return-await/) explained +There is a number of [excellent articles](https://jakearchibald.com/2017/await-vs-return-vs-return-await/) explaining why `return await` should never be used outside of `try` block and even an [ESLint rule](https://eslint.org/docs/rules/no-return-await) that disallows it. The reason for that is the fact that since async/await become available with transpilers in Node.js 0.10 (and got native support in Node.js 7.6) and until "zero-cost async stacktraces" was introduced in Node.js 10 and unflagged in Node.js 12, `return await` was absolutely equivalent to `return` for any code outside of `try` block. It may still be the same for some other ES engines. This -is why resolving promises before returning them is the best practice for Node.js and not for the EcmaScript in general +is why resolving promises before returning them is the best practice for Node.js and not for ECMAScript in general ### Notes: -1. One another reason why async stacktrace has such tricky implementation is the limitation that stacktrace +1. One other reason why async stacktrace has such tricky implementation is the limitation that stacktrace must always be built synchronously, on the same tick of event loop [¹](#1) 2. Without `await` in `throwAsync` the code would be executed in the same phase of event loop. This is a degenerated case when OS **stack** would not get empty and stacktrace be full even without explicitly -awaiting the function result. Usually usage of promises include some async operations and so parts of +awaiting the function result. Common usage of promises includes some async operations and so parts of the stacktrace would get lost 3. Zero-cost async stacktraces still would not work for complicated promise usages e.g. single promise awaited many times in different places ### References: 1. [Blog post on zero-cost async stacktraces in v8](https://v8.dev/blog/fast-async) -
+
2. [Document on zero-cost async stacktraces with mentioned here implementation details]( https://docs.google.com/document/d/13Sy_kBIJGP0XT34V1CV3nkWya4TwYx9L3Yv45LdGB6Q/edit ) -
+
diff --git a/sections/errorhandling/returningpromises.russian.md b/sections/errorhandling/returningpromises.russian.md index ed58d69f8..01df84106 100644 --- a/sections/errorhandling/returningpromises.russian.md +++ b/sections/errorhandling/returningpromises.russian.md @@ -12,7 +12,7 @@
-### Анти-паттерн №1: return \ +### Анти-паттерн №1: return `promise`

Javascript

@@ -41,7 +41,7 @@ Error: missing returnWithoutAwait in the stacktrace

-### Как правильно: return await \ +### Как правильно: return await `promise`
Javascript

@@ -142,7 +142,7 @@ Error: with all frames present

-
+
### Анти-паттерн №3: прямая передача асинхронного коллбэка в месте где ожидается синхронный коллбек @@ -281,9 +281,9 @@ Error: [...] ### References: 1. [Блогпост о бесплатных асинхронных стектрейсах в v8](https://v8.dev/blog/fast-async) -
+
2. [Документ о бесплатных асинхронных стектрейсах в v8 с упомянутыми тут деталями реализации]( https://docs.google.com/document/d/13Sy_kBIJGP0XT34V1CV3nkWya4TwYx9L3Yv45LdGB6Q/edit ) -
+
diff --git a/sections/errorhandling/shuttingtheprocess.basque.md b/sections/errorhandling/shuttingtheprocess.basque.md index 835b3494b..693bad28e 100644 --- a/sections/errorhandling/shuttingtheprocess.basque.md +++ b/sections/errorhandling/shuttingtheprocess.basque.md @@ -1,8 +1,8 @@ # Irten prozesutik elegantziarekin kanpoko norbait iristen denean hirira -### Azalpen paragrafoa +### Azalpena -Zure kodearen lekuren batean, erroreren bat gertatzen denean erroreen kudeaketa objektuaren ardura da erabakitzea nola jokatu, eta, errorea konfiantzazkoa bada, nahikoa izango da erregistro fitxategian idaztea; errorea operazionala bada, berriz, irakurri azalpen osatuagoa #3 jarraibide egokian). Gauzak okertzen dira errorea ezezaguna denean, horrek osagairen bat egoera txarrean dagoela eta hurrengo eskaera guztiek huts egiteko aukera handia dutela esan nahi du eta. Adibidez, eman dezagun, singleton bat edukita, token batek salbuespen bat igorri duela eta ondoren bere egoera galdu duen zerbitzu batekin arazoa duela; hortik aurrera ustekabean joka dezake eta eskaera guztiek huts egitea eragin. Egoera horren aurrean, prozesua gelditu eta 'Berrekite tresna' erabili (Forever, PM2, etab. bezalakoak) egoera garbi batekin berriz hasteko. +Zure kodearen lekuren batean, erroreren bat gertatzen denean erroreen kudeaketa objektuaren ardura da erabakitzea nola jokatu, eta, errorea konfiantzazkoa bada, nahikoa izango da erregistro fitxategian idaztea; errorea operazionala bada, berriz, irakurri azalpen osatuagoa #3 jarraibide egokian). Gauzak okertzen dira errorea ezezaguna denean, horrek osagairen bat egoera txarrean dagoela eta hurrengo eskaera guztiek huts egiteko aukera handia dutela esan nahi du eta. Adibidez, eman dezagun, singleton bat edukita, token batek salbuespen bat igorri duela eta ondoren bere egoera galdu duen zerbitzu batekin arazoa duela; hortik aurrera ustekabean joka dezake eta eskaera guztiek huts egitea eragin. Egoera horren aurrean, prozesua gelditu eta 'Berrekite tresna' erabili (Forever, PM2, etab. bezalakoak) egoera garbi batekin berriz hasteko ### Kode adibidea: huts eragin ala ez erabakitzen @@ -77,23 +77,23 @@ export const kudeatzailea = new ErroreKudeatzailea(); ```
-### Blogeko aipua: "Irtenbiderik hoberena huts egitea da" +### Blog aipua: "Irtenbiderik hoberena huts eragitea da" -Joyent blogetik hartua +Joyent bloga > …Programatzaileen erroreak konpontzeko modurik hoberena berehala krak egitea da. Programaren batek huts eginez gero, berrabiarazle bat erabiliz exekutatu beharko zenuke, automatikoki berrabiaraziko baitu. Berrabiarazlea dagoenean, huts egitea da programa fidagarria berreskuratzeko biderik azkarrena programatzailearen errore iragankor baten aurrean ... -### Blogeko aipua: "Errore kudeaketaren inguruko hiru ideia eskola daude" +### Blog aipua: "Errore kudeaketaren inguruko hiru ideia eskola daude" -JS Recipes blogetik hartua +JS Recipes bloga > …Errore kudeaketaren inguruko hiru ideia eskola nagusi daude: 1. Utzi aplikazioari huts egiten eta ondoren berrabiarazi 2. Errore posible guztiak kudeatu eta inoiz ez huts egin 3. Bien arteko planteamendu bat -### Blogeko aipua: "Ez dago modu segururik irteteko zehaztugabeko egoera hauskorrik sortu gabe" +### Blog aipua: "Ez dago modu segururik irteteko zehaztugabeko egoera hauskorrik sortu gabe" -Node.js dokumentazio ofizialetik hartua +Node.js dokumentazio ofiziala -> …JavaScripten lanak nola exekutatzen diren kontuan izanda, ez dago ia inoiz lan bati ziurtasunez jarraipena emateko biderik utzitako puntuan hasita, erreferentziak galdu gabe edota bestelako zehaztugabeko egoera hauskorrik sortu gabe. Jaurtitako errore bati erantzuteko modurik seguruena prozesua itzaltzea da. Jakina, web zerbitzari arruntetan, konekxio ugari eduki ahal dituzu irekita, eta ez da zentzuzkoa tupustean haiek ixtea beste batek eragindako errore batengatik. Planteamendu hoberena da bidaltzea errore erantzun bat errorea bidali duen eskariari, besteei beren atazak bukatzeko denbora utziz, eta eskari berriei kasu egiteari uztea prozesu horretan. +> …JavaScripten lanak nola exekutatzen diren kontuan izanda, ez dago ia inoiz lan bati ziurtasunez jarraipena emateko biderik utzitako puntuan hasita, erreferentziak galdu gabe edota bestelako zehaztugabeko egoera hauskorrik sortu gabe. Jaurtitako errore bati erantzuteko modurik seguruena prozesua itzaltzea da. Jakina, web zerbitzari arruntetan, konexio ugari eduki ahal dituzu irekita, eta ez da zentzuzkoa tupustean haiek ixtea beste batek eragindako errore batengatik. Planteamendu hoberena da bidaltzea errore erantzun bat errorea bidali duen eskariari, besteei beren atazak bukatzeko denbora utziz, eta eskari berriei kasu egiteari uztea prozesu horretan diff --git a/sections/errorhandling/shuttingtheprocess.french.md b/sections/errorhandling/shuttingtheprocess.french.md new file mode 100644 index 000000000..517ac53e5 --- /dev/null +++ b/sections/errorhandling/shuttingtheprocess.french.md @@ -0,0 +1,99 @@ +# Quittez le processus avec élégance lorsqu'un étranger arrive en ville + +### Un paragraphe d'explication + +Quelque part dans votre code, un objet gestionnaire d'erreur est chargé de décider comment procéder lorsqu'une erreur est levée - si l'erreur est fiable (c.-à-d. une erreur opérationnelle, voir plus d'explications dans la bonne pratique n° 3), alors l'écriture dans le fichier journal peut être suffisante. Les choses deviennent floues si l'erreur n'est pas familière - cela signifie que certains composants peuvent être dans un état défectueux et toutes les demandes futures sont susceptibles d'échouer. Par exemple, en supposant un service émetteur de jetons avec un état unique qui a levé une exception et a perdu son état - à partir de ce moment, il pourrait se comporter de manière inattendue et entraîner l'échec de toutes les demandes. Dans ce scénario, arrêtez le processus et utilisez un « outil de redémarrage » (comme Forever, PM2, etc.) pour recommencer avec un état propre. + +### Exemple de code : décider s'il faut planter + +
+Javascript + +```javascript +// En supposant que les développeurs marquent les erreurs opérationnelles connues avec error.isOperational = true, lisez la bonne pratique n° 3 +process.on('uncaughtException', (error) => { + errorManagement.handler.handleError(error); + if(!errorManagement.handler.isTrustedError(error)) + process.exit(1) +}); + +// le gestionnaire d'erreurs centralisé encapsule la logique liée à la gestion des erreurs +function errorHandler() { + this.handleError = (error) => { + return logger.logError(error) + .then(sendMailToAdminIfCritical) + .then(saveInOpsQueueIfCritical) + .then(determineIfOperationalError); + } + + this.isTrustedError = (error) => { + return error.isOperational; + } +} +``` +
+ +
+Typescript + +```typescript +// En supposant que les développeurs marquent les erreurs opérationnelles connues avec error.isOperational = true, lisez la bonne pratique n° 3 +process.on('uncaughtException', (error: Error) => { + errorManagement.handler.handleError(error); + if(!errorManagement.handler.isTrustedError(error)) + process.exit(1) +}); + +// objet d'erreur centralisé qui dérive de l'Error de Node +export class AppError extends Error { + public readonly isOperational: boolean; + + constructor(description: string, isOperational: boolean) { + super(description); + Object.setPrototypeOf(this, new.target.prototype); // restaurer la chaîne du prototype + this.isOperational = isOperational; + Error.captureStackTrace(this); + } +} + +// le gestionnaire d'erreurs centralisé encapsule la logique liée à la gestion des erreurs +class ErrorHandler { + public async handleError(err: Error): Promise { + await logger.logError(err); + await sendMailToAdminIfCritical(); + await saveInOpsQueueIfCritical(); + await determineIfOperationalError(); + }; + + public isTrustedError(error: Error) { + if (error instanceof AppError) { + return error.isOperational; + } + return false; + } +} + +export const handler = new ErrorHandler(); +``` +
+ +### Citation de blog : « La meilleure façon est de planter » + +Extrait du blog de Joyent + +> …La meilleure façon de récupérer des erreurs de programmation est de planter immédiatement. Vous devez exécuter vos programmes à l'aide d'un « outil de redémarrage » qui redémarrera automatiquement le programme en cas de plantage. Avec un « outil de redémarrage » en place, le plantage est le moyen le plus rapide de restaurer un service fiable face à une erreur de programmation transitoire… + +### Citation de blog : « Il y a principalement trois écoles de réflexion sur la gestion des erreurs » + +Extrait du blog de JS Recipes + +> …Il y a principalement trois écoles de réflexion sur la gestion des erreurs : +1. Laissez l'application se planter et redémarrez-la. +2. Gérez toutes les erreurs possibles et ne plantez jamais. +3. Une approche équilibrée entre les deux + +### Citation de blog : « Aucune solution sûre pour sortir sans créer un état fragile indéfini » + +Extrait de la documentation officielle de Node.js + +> …De par la nature même du fonctionnement de throw en JavaScript, il n'y a presque jamais aucun moyen de « reprendre là où vous vous étiez arrêté » en toute sécurité, sans fuite de références, ou sans créer une autre sorte d'état fragile non défini. Le moyen le plus sûr de répondre à une erreur levée est d'arrêter le processus. Bien sûr, dans un serveur Web normal, de nombreuses connexions peuvent être ouvertes et il n'est pas raisonnable de les fermer brutalement car une erreur a été déclenchée par quelqu'un d'autre. La meilleure approche consiste à envoyer une réponse d'erreur à la demande qui a déclenché l'erreur tout en laissant les autres se terminer dans leur temps normal et à cesser d'écouter les nouvelles demandes de ce processus. diff --git a/sections/errorhandling/shuttingtheprocess.md b/sections/errorhandling/shuttingtheprocess.md index e7f8b9ee3..69dd6ee0a 100644 --- a/sections/errorhandling/shuttingtheprocess.md +++ b/sections/errorhandling/shuttingtheprocess.md @@ -88,9 +88,9 @@ From the blog Joyent From the blog: JS Recipes > …There are primarily three schools of thoughts on error handling: -1. Let the application crash and restart it. -2. Handle all possible errors and never crash. -3. A balanced approach between the two +>1. Let the application crash and restart it. +>2. Handle all possible errors and never crash. +>3. A balanced approach between the two ### Blog Quote: "No safe way to leave without creating some undefined brittle state" diff --git a/sections/errorhandling/testingerrorflows.basque.md b/sections/errorhandling/testingerrorflows.basque.md index 8d53e46a9..994251bf7 100644 --- a/sections/errorhandling/testingerrorflows.basque.md +++ b/sections/errorhandling/testingerrorflows.basque.md @@ -1,8 +1,8 @@ # Testeatu erroreen fluxua zure test framework gustukoena erabiliz -### Azalpen paragrafoa +### Azalpena -Bide ‘alaiak’ probatzea ez da hutsegiteak probatzea baino hobea. Probako kodeen estaldura ona da salbuespenezko bideak probatzeko. Bestela, ez dago inolako konfidantzarik salbuespenak zuzen kudeatuta dauden. Unitateen azterketa esparru guztiek, [Mocha](https://mochajs.org/) edo [Chai](http://chaijs.com/) bezala, onartzen dituzte salbuespen probak (kode adibideak beherago). Gogaikarria iruditzen bazaizu funtzio eta salbuespen bakoitza probatzea, REST APIen HTTP erroreak bakarrik probatzea erabaki zenezake. +Bide ‘alaiak’ probatzea ez da hutsegiteak probatzea baino hobea. Probako kodeen estaldura ona da salbuespenezko bideak probatzeko. Bestela, ez dago inolako konfidantzarik salbuespenak zuzen kudeatuta dauden. Unitateen azterketa esparru guztiek, [Mocha](https://mochajs.org/) eta [Chai](http://chaijs.com/)k bezala, onartzen dituzte salbuespen probak (kode adibideak beherago). Gogaikarria iruditzen bazaizu funtzio eta salbuespen bakoitza probatzea, REST APIen HTTP erroreak bakarrik probatzea erabaki zenezake ### Kode adibidea: ziurtatu salbuespen egokia jaurtitzen dela Mocha eta Chai erabiliz diff --git a/sections/errorhandling/testingerrorflows.french.md b/sections/errorhandling/testingerrorflows.french.md new file mode 100644 index 000000000..2e385ecbb --- /dev/null +++ b/sections/errorhandling/testingerrorflows.french.md @@ -0,0 +1,81 @@ +# Testez les flux d'erreurs en utilisant votre framework de test préféré + +### Un paragraphe d'explication + +Tester les chemins « du bonheur » n’est pas mieux que de tester les échecs. Une bonne couverture du code de test exige de tester des chemins inhabituels. Sinon, il n'est pas certain que les exceptions soient effectivement gérées correctement. Chaque framework de tests unitaires, comme [Mocha](https://mochajs.org/) et [Chai](http://chaijs.com/), prend en charge les tests d'exception (exemples de code ci-dessous). Si vous trouvez fastidieux de tester chaque fonction interne et chaque exception, vous pouvez vous contenter de tester uniquement les erreurs HTTP de l'API REST. + +### Exemple de code : s'assurer que la bonne exception est levée à l'aide de Mocha & Chai + +
+Javascript + +```javascript +describe('Facebook chat', () => { + it('Avertit en cas de nouveau message dans la discussion', () => { + const chatService = new chatService(); + chatService.participants = getDisconnectedParticipants(); + expect(chatService.sendMessage.bind({ message: 'Salut' })).to.throw(ConnectionError); + }); +}); +``` +
+ +
+Typescript + +```typescript +describe('Facebook chat', () => { + it('Avertit en cas de nouveau message dans la discussion', () => { + const chatService = new chatService(); + chatService.participants = getDisconnectedParticipants(); + expect(chatService.sendMessage.bind({ message: 'Salut' })).to.throw(ConnectionError); + }); +}); +``` +
+ +### Exemple de code: s'assurer que l'API renvoie le bon code erreur HTTP + +
+Javascript + +```javascript +it('Crée un nouveau groupe Facebook', () => { + const invalidGroupInfo = {}; + return httpRequest({ + method: 'POST', + uri: 'facebook.com/api/groups', + resolveWithFullResponse: true, + body: invalidGroupInfo, + json: true + }).then((response) => { + expect.fail('si nous devions exécuter le code dans ce bloc, aucune erreur n\'a été levée dans l\'opération ci-dessus') + }).catch((response) => { + expect(400).to.equal(response.statusCode); + }); +}); +``` +
+ +
+Typescript + +```typescript +it('Crée un nouveau groupe Facebook', async () => { + let invalidGroupInfo = {}; + try { + const response = await httpRequest({ + method: 'POST', + uri: 'facebook.com/api/groups', + resolveWithFullResponse: true, + body: invalidGroupInfo, + json: true + }) + // si nous devions exécuter le code dans ce bloc, aucune erreur n'a été levée dans l'opération ci-dessus + expect.fail('La requête aurait dû échouer') + } catch(response) { + expect(400).to.equal(response.statusCode); + } +}); +``` +
\ No newline at end of file diff --git a/sections/errorhandling/testingerrorflows.md b/sections/errorhandling/testingerrorflows.md index 552ca1f53..ac03f4146 100644 --- a/sections/errorhandling/testingerrorflows.md +++ b/sections/errorhandling/testingerrorflows.md @@ -10,72 +10,69 @@ Testing ‘happy’ paths is no better than testing failures. Good testing code Javascript ```javascript -describe('Facebook chat', () => { - it('Notifies on new chat message', () => { +describe("Facebook chat", () => { + it("Notifies on new chat message", () => { const chatService = new chatService(); chatService.participants = getDisconnectedParticipants(); - expect(chatService.sendMessage.bind({ message: 'Hi' })).to.throw(ConnectionError); + expect(chatService.sendMessage.bind({ message: "Hi" })).to.throw(ConnectionError); }); }); ``` + +### Code example: ensuring API returns the right HTTP error code and log properly +
-Typescript +Javascript -```typescript -describe('Facebook chat', () => { - it('Notifies on new chat message', () => { - const chatService = new chatService(); - chatService.participants = getDisconnectedParticipants(); - expect(chatService.sendMessage.bind({ message: 'Hi' })).to.throw(ConnectionError); +```javascript +test("When exception is throw during request, Then logger reports the mandatory fields", async () => { + //Arrange + const orderToAdd = { + userId: 1, + productId: 2, + }; + + sinon + .stub(OrderRepository.prototype, "addOrder") + .rejects(new AppError("saving-failed", "Order could not be saved", 500)); + const loggerDouble = sinon.stub(logger, "error"); + + //Act + const receivedResponse = await axiosAPIClient.post("/order", orderToAdd); + + //Assert + expect(receivedResponse.status).toBe(500); + expect(loggerDouble.lastCall.firstArg).toMatchObject({ + name: "saving-failed", + status: 500, + stack: expect.any(String), + message: expect.any(String), }); }); ``` +
-### Code example: ensuring API returns the right HTTP error code +### Code example: ensuring that are uncaught exceptions are handled as well
Javascript ```javascript -it('Creates new Facebook group', () => { - const invalidGroupInfo = {}; - return httpRequest({ - method: 'POST', - uri: 'facebook.com/api/groups', - resolveWithFullResponse: true, - body: invalidGroupInfo, - json: true - }).then((response) => { - expect.fail('if we were to execute the code in this block, no error was thrown in the operation above') - }).catch((response) => { - expect(400).to.equal(response.statusCode); - }); -}); -``` -
+test("When unhandled exception is throw, Then the logger reports correctly", async () => { + //Arrange + await api.startWebServer(); + const loggerDouble = sinon.stub(logger, "error"); + const errorToThrow = new Error("An error that wont be caught 😳"); -
-Typescript - -```typescript -it('Creates new Facebook group', async () => { - let invalidGroupInfo = {}; - try { - const response = await httpRequest({ - method: 'POST', - uri: 'facebook.com/api/groups', - resolveWithFullResponse: true, - body: invalidGroupInfo, - json: true - }) - // if we were to execute the code in this block, no error was thrown in the operation above - expect.fail('The request should have failed') - } catch(response) { - expect(400).to.equal(response.statusCode); - } + //Act + process.emit("uncaughtException", errorToThrow); + + // Assert + expect(loggerDouble.calledWith(errorToThrow)); }); ``` -
\ No newline at end of file + + diff --git a/sections/errorhandling/usematurelogger.basque.md b/sections/errorhandling/usematurelogger.basque.md index d0fbd865d..2c20e5497 100644 --- a/sections/errorhandling/usematurelogger.basque.md +++ b/sections/errorhandling/usematurelogger.basque.md @@ -1,14 +1,13 @@ # Erabili erregistratze tresna heldu bat erroreen ikusgaitasuna handitzeko -### Azalpen paragrafoa +### Azalpena - -Gustuko dugu console.log, baina [Pino][pino] bezalako erregistratzaile tresna ospetsu eta iraunkorra (errendimenduan zentratutako aukera berriagoa) ezinbestekoa da proiektu serioetarako. Errendimendu handiko erregistratze tresnek erroreak eta arazo posibleak identifikatzen laguntzen dute. Erregistratze aholkuen artean: +Gustuko dugu console.log, baina [Pino][pino] bezalako erregistratzaile tresna ospetsu eta iraunkorra (errendimenduan zentratutako aukera berriagoa) ezinbestekoa da proiektu serioetarako. Errendimendu handiko erregistratze tresnek erroreak eta arazo posibleak identifikatzen laguntzen dute. Erregistratze aholkuen artean: 1. Maiz erregistratu maila ezberdinak erabiliz (debug, info, error) 2. Erregistratzerako orduan, eman testuinguruaren informazioa JSON objektu eran 3. Monitorizatu erregistro kontsultak API batekin (erregistro sistema ezberdinetarako erabilgarria) edota erregistro ikustailearen software batekin -4. Erakutsi erregistroen informazioa [Splunk][splunk] bezalako operazio inteligentzia tresnekin +4. Erakutsi erregistroen informazioa [Splunk][splunk] bezalako operazio inteligentzia tresnekin [pino]: https://www.npmjs.com/package/pino [splunk]: https://www.splunk.com/ @@ -25,19 +24,18 @@ const erregistratzailea = pino(); erregistratzailea.info({ anything: 'Hau metadatua da' }, 'Frogatu Erregistro Mezua %s parametroren batekin', 'parametroren bat'); ``` -### Blogeko aipua: "Erregistratzailearen betebeharrak" +### Blog aipua: "Erregistratzailearen betebeharrak" -StrongLoop blogetik hartua ("Winston eta Bunyanen Node.js Erregistratzaile sistemak konparatzen" Alex Corbatcheven eskutik, 2014ko ekainaren 24a): +StrongLoop bloga ("Winston eta Bunyanen Node.js Erregistratzaile sistemak konparatzen" Alex Corbatcheven eskutik, 2014ko ekainaren 24a): > Identifika ditzagun betebehar gutxi batzuk (erregistratzaile batentzat): > > 1. Denboran seilatu erregistro ilara bakoitza. Nahiko argi dago, erregistroko sarrera bakoitza noiz gertatu den esateko gai izan behar duzu > 2. Erregistro formatua ulergarria izan behar da bai gizakientzat eta baita makinentzat ere -> 3. Korronte ezberdin ugari onartu behar ditu. Adibidez, errore erregistroak fitxategi batean idazten ari den unean errorereb bat atzemanez gero, fitxategi beraren barruan idatzi, errorearen fitxategian ere idatzi, eta posta elektronikoa bidali, dena aldi berean, egiteko aukera eman behar du +> 3. Korronte ezberdin ugari onartu behar ditu. Adibidez, errore erregistroak fitxategi batean idazten ari den unean erroreren bat atzemanez gero, fitxategi beraren barruan idatzi, errorearen fitxategian ere idatzi, eta posta elektronikoa bidali, dena aldi berean, egiteko aukera eman behar du ### Non dago Winston? -Zergatik ohiko faboritoak (adibidez, Winston) ez dauden aholkatutako jardunbide -onenen egungo zerrendan jakiteko, begiratu [#684][#684]an +Zergatik ohiko faboritoak (adibidez, Winston) ez dauden aholkatutako pratika onenen egungo zerrendan jakiteko, begiratu # [#684][#684]an [#684]: https://github.com/goldbergyoni/nodebestpractices/issues/684 diff --git a/sections/errorhandling/usematurelogger.french.md b/sections/errorhandling/usematurelogger.french.md new file mode 100644 index 000000000..e9fb1fc87 --- /dev/null +++ b/sections/errorhandling/usematurelogger.french.md @@ -0,0 +1,41 @@ +# Utilisez un outil de journalisation mature pour augmenter la visibilité des erreurs + +### Un paragraphe d'explication + +Nous adorons console.log mais un logger réputé et persistant comme [Pino][pino] (une option plus récente axée sur les performances) est obligatoire pour les projets sérieux. +Des outils de journalisation très performants permettent d'identifier les erreurs et les problèmes éventuels. Les recommandations en matière de journalisation sont : + +1. Enregistrer fréquemment en utilisant différents niveaux (débogage, info, erreur). +2. Lors de la journalisation, fournir des informations contextuelles sous forme d'objets JSON. +3. Surveiller et filtrer les journaux à l'aide d'une API d'interrogation des journaux (intégrée à de nombreux enregistreurs) ou d'un logiciel de visualisation des journaux. +4. Exposer et conserver les déclarations de journal avec des outils de renseignement opérationnel tels que [Splunk][splunk]. + +[pino]: https://www.npmjs.com/package/pino +[splunk]: https://www.splunk.com/ + +### Exemple de code + +```javascript +const pino = require('pino'); + +// votre objet de journalisation centralisé +const logger = pino(); + +// code personnalisé quelque part à l'aide de l'outil de journalisation +logger.info({ anything: 'This is metadata' }, 'Test Log Message with some parameter %s', 'some parameter'); +``` + +### Citation de blog : « Exigences d'un outil de journalisation » + + Extrait du blog de Strong Loop ("Comparing Winston and Bunyan Node.js Logging" par Alex Corbatchev, 24 juin 2014) : + +> Permet d'identifier quelques exigences (pour un outil de journalisation) : +> 1. Chaque ligne du journal est horodatée. Celle-ci est assez explicite - vous devriez pouvoir dire quand chaque entrée du journal s'est produite. +> 2. Le format d'enregistrement doit être facilement assimilable par les humains ainsi que par les machines. +> 3. Permet plusieurs flux de destination configurables. Par exemple, vous pouvez écrire des journaux de trace dans un fichier, mais lorsqu'une erreur se produit, cela écrit dans le même fichier, puis dans le fichier d'erreur et envoi un e-mail en même temps… + +### Où est Winston ? + +Pour plus d'informations sur les raisons pour lesquelles les favoris traditionnels (par exemple, Winston) peuvent ne pas être inclus dans la liste actuelle des meilleures pratiques recommandées, veuillez consulter [#684][#684]. + +[#684]: https://github.com/goldbergyoni/nodebestpractices/issues/684 diff --git a/sections/errorhandling/useonlythebuiltinerror.basque.md b/sections/errorhandling/useonlythebuiltinerror.basque.md index 407c7ea66..008ddd5f8 100644 --- a/sections/errorhandling/useonlythebuiltinerror.basque.md +++ b/sections/errorhandling/useonlythebuiltinerror.basque.md @@ -1,8 +1,8 @@ # Erabili soilik “Errorea” objektu kapsulatua -### Azalpen paragrafoa +### Azalpena -JavaScriptek berezko permisibitatea du, eta, bere kode fluxuaren aukera ugariarekin (adibidez EventEmitter, Callbackak, Promesak ...), garatzaileek erroreak kudeatzeko modu anitzak edukitzea eragiten du: batzuek stringak erabiltzen dituzte, besteek beren mota pertsonalizatuak zehazten dituzte. Node.jsen "Errorea" objektu kapsulatua erabiltzeak zure kodearen eta bestelako liburutegien arteko uniformetasuna gordetzen laguntzen du, eta gainera StracTracea bezalako informazio esanguratsua gordetzen du. Salbuespen bat jaurtitzean, jarraibide egokia da errorearen izena edo erlazionatutako HTTP errore kodea bezalako testuinguru ezaugarriekin osatzea. Uniformetasun eta praktika hau lortzeko, saiatu "Errorea" objektua beharrezko ezaugarriekin osatzen, baina kontu izan gehiegitan ez egiten. Orokorrean ideia ona da "Errorea" objektu kapsulatua behin bakarrik osatzea AppErrore batekin aplikazioaren maila guztietako erroreentzat, eta beharrezko duzun informazioa argumentu gisa pasatuz errore klase ezberdinak ezberdintzeko. Ez da beharrezkoa "Errorea" objektua askotan osatzea (errore kasu bakoitzerako behin, adibidez DbError, HttpError...). Begiratu ondorengo kode adibideak +JavaScriptek berezko permisibitatea du, eta, bere kode fluxuaren aukera ugariarekin (adibidez EventEmitter, Callbackak, Promesak ...), garatzaileek erroreak kudeatzeko modu anitzak edukitzea eragiten du: batzuek stringak erabiltzen dituzte, besteek beren mota pertsonalizatuak zehazten dituzte. Node.jsren "Errorea" objektu kapsulatua erabiltzeak zure kodearen eta bestelako liburutegien arteko uniformetasuna gordetzen laguntzen du, eta gainera StracTracea bezalako informazio esanguratsua gordetzen du. Salbuespen bat jaurtitzean, jarraibide egokia da errorearen izena edo erlazionatutako HTTP errore kodea bezalako testuinguru ezaugarriekin osatzea. Uniformetasun eta praktika hau lortzeko, saiatu "Errorea" objektua beharrezko ezaugarriekin osatzen, baina kontu izan gehiegitan ez egiten. Orokorrean ideia ona da "Errorea" objektu kapsulatua behin bakarrik osatzea AppErrore batekin aplikazioaren maila guztietako erroreentzat, eta beharrezko duzun informazioa argumentu gisa pasatuz errore klase ezberdinak ezberdintzeko. Ez da beharrezkoa "Errorea" objektua askotan osatzea (errore kasu bakoitzerako behin, adibidez DbError, HttpError...). Begiratu ondorengo kode adibideak ### Kode adibidea: era zuzenean egin @@ -113,24 +113,24 @@ _`Object.setPrototypeOf`ri buruzko azalpena Typescripten: https://www.typescript ### Blogeko aipua: "Ez diot interesik ikusten mota ezberdin ugari edukitzeari" -Ben Nadel blogeko “Node.js errore objektua” 5 hitz gakori esker sailkatua +Ben Nadel-en blogeko “Node.js errore objektua” 5 hitz gakori esker sailkatua > …”Nik neuk, ez diot interesik ikusten errore objektu klase ezberdin ugari edukitzeari [bakarra edukitzearekin alderatuz]. Ez dirudi JavaScriptek, lengoaia gisa, eraikitzailez oinarritutako errore harrapaketa hornitzen duenik. Horrela, objektu baten ezaugarriak bereizteak Eraikitzaile klaseak bereiztea baino errazagoa dirudi… -### Blogeko aipua: "String bat ez da errore bat" +### Blog aipua: "String bat ez da errore bat" devthought.com blogeko “Node.js errore objektua” 6 hitz gakori esker sailkatua -> …String baten ordez errore bat pasatzeak moduluen arteko elkarreragintasuna murrizten du. instanceof errore egiaztapen arrakastatsuak izan litezken kontratuak apurtzen ditu APIekin. Ikusiko dugun bezala, errore objektuek, eraikitzaileari pasatutako mezua kontserbatzeaz gain, Javascript motore modernoetan ezaugarri interesgarriak dituzte… +> …String baten ordez errore bat pasatzeak moduluen arteko elkarreragintasuna murrizten du. instanceof errore egiaztapen arrakastatsuak izan litezkeen kontratuak apurtzen ditu APIekin. Ikusiko dugun bezala, errore objektuek, eraikitzaileari pasatutako mezua kontserbatzeaz gain, Javascript motore modernoetan ezaugarri interesgarriak dituzte… -### Blogeko aipua: "Erroretik jaraunsteak ez du balio askorik gehitzen" +### Blog aipua: "Erroretik jaraunsteak ez du balio askorik gehitzen" -machadogj blogetik hartua +machadogj bloga > …Errore klasea jaraunsteko erraza ez izatea arazo bat da. Noski, klasea jaraunts dezakezu eta zure HttpError, DbError, etab. bezalako Error klase propioak sortu. Hala ere, horrek denbora eskatzen du, eta ez du balio askorik gehitzen [AppError batentzat behin bakarrik jaraunsteaz alderatuz], baldin eta klaseekin zerbait egiten ez bazabiltza. Batzuetan, soilik mezu bat gehitu nahi duzu eta barruko errorea mantendu; beste batzuetan, ordea, errorea parametroekin edo bestelako informazioekin osatu nahi zenezake… -### Blogeko aipua: "Node.jsek jaurtitako JavaScript eta System errore guztiak "Error" objektutik datoz" +### Blog aipua: "Node.jsk jaurtitako JavaScript eta System errore guztiak "Error" objektutik datoz" -Node.js dokumentazio ofizialetik hartua +Node.js dokumentazio ofiziala -> …Node.jsek jaurtitako JavaScript eta System errore guztiak JavaScripten "Error" klase estandarretik datoz edo "Error" objektuaren instantziak dira, eta gutxienez horrelako ezaugarri erabilgarriak hornitzea bermatzen dute. JavaScript Error objektu generiko bat da, errorea zergatik gertatu den inolako berariazko baldintzarik adierazten ez duena. Error objektuek "pila aztarna" bat atzematen dute, Error instantziatua izan den kodearen lekua zehaztuz, eta errorearen testu deskribapena eduki dezakete. Node.jsek sortutako errore guztiak, System eta JavaScript erroreak barne, Error klasetik eratorritakoak edo Error motaren instantziak izango dira… +> …Node.jsk jaurtitako JavaScript eta System errore guztiak JavaScripten "Error" klase estandarretik datoz edo "Error" objektuaren instantziak dira, eta gutxienez horrelako ezaugarri erabilgarriak hornitzea bermatzen dute. JavaScript Error objektu generiko bat da, errorea zergatik gertatu den inolako berariazko baldintzarik adierazten ez duena. Error objektuek "pila aztarna" bat atzematen dute, Error instantziatua izan den kodearen lekua zehaztuz, eta errorearen testu deskribapena eduki dezakete. Node.jsk sortutako errore guztiak, System eta JavaScript erroreak barne, Error klasetik eratorritakoak edo Error motaren instantziak izango dira… diff --git a/sections/errorhandling/useonlythebuiltinerror.french.md b/sections/errorhandling/useonlythebuiltinerror.french.md new file mode 100644 index 000000000..a8e2e7d56 --- /dev/null +++ b/sections/errorhandling/useonlythebuiltinerror.french.md @@ -0,0 +1,117 @@ +# Utilisez uniquement l'objet intégré Error + +### Un paragraphe d'explication + +La nature permissive de JavaScript ainsi que sa variété d'options de flux de code (par exemple, EventEmitter, fonction de rappel, promesses, etc.) peut faire varier considérablement la façon dont les développeurs génèrent des erreurs - certains utilisent des chaînes, d'autres définissent leurs propres types personnalisés. L'utilisation de l'objet Error intégré de Node.js aide à maintenir l'uniformité dans votre code et avec les bibliothèques tierces, il préserve également des informations importantes comme la StackTrace. Lors de la levée de l'exception, il est généralement recommandé de la remplir avec des propriétés contextuelles supplémentaires telles que le nom de l'erreur et le code d'erreur HTTP associé. Pour atteindre cette uniformité et ces pratiques, envisagez d'étendre l'objet Error avec des propriétés supplémentaires, mais attention à ne pas en faire trop. Il est généralement judicieux d'étendre l'objet Error une seule fois avec un AppError pour toutes les erreurs au niveau de l'application, et de passer en argument toutes les données dont vous avez besoin pour différencier les différents types d'erreurs. Il n'est pas nécessaire d'étendre l'objet Error plusieurs fois (une fois pour chaque cas d'erreur, comme DbError, HttpError). Consulter l'exemple de code ci-dessous. + +### Exemple de code - la bonne méthode + +```javascript +// lève une Error depuis une fonction typique, qu'elle soit synchrone ou asynchrone +if(!productToAdd) + throw new Error('Comment puis-je ajouter un nouveau produit lorsqu\'aucune valeur n\'est fournie ?'); + +// 'lève' une Error depuis EventEmitter +const myEmitter = new MyEmitter(); +myEmitter.emit('error', new Error('Oups !')); + +// 'lève' une Error depuis une promesse +const addProduct = async (productToAdd) => { + try { + const existingProduct = await DAL.getProduct(productToAdd.id); + if (existingProduct !== null) { + throw new Error('Le produit existe déjà !'); + } + } catch (err) { + // ... + } +} +``` + +### Exemple de code - la mauvaise méthode + +```javascript +// lève une chaîne qui ne contient aucune information de trace de pile et autres propriétés de données importantes +if(!productToAdd) + throw ('Comment puis-je ajouter un nouveau produit lorsqu\'aucune valeur n\'est fournie ?'); +``` + +### Exemple de code - une méthode encore meilleure + +
+Javascript + +```javascript +// objet d'erreur centralisé qui dérive de Error de Node +function AppError(name, httpCode, description, isOperational) { + Error.call(this); + Error.captureStackTrace(this); + this.name = name; + //...d'autres propriétés attribuées ici +}; + +AppError.prototype = Object.create(Error.prototype); +AppError.prototype.constructor = AppError; + +module.exports.AppError = AppError; + +// le client levant une exception +if(user == null) + throw new AppError(commonErrors.resourceNotFound, commonHTTPErrors.notFound, 'plus d\'explications', true) +``` +
+ +
+Typescript + +```typescript +// objet d'erreur centralisé qui dérive de Error de Node +export class AppError extends Error { + public readonly name: string; + public readonly httpCode: HttpCode; + public readonly isOperational: boolean; + + constructor(name: string, httpCode: HttpCode, description: string, isOperational: boolean) { + super(description); + + Object.setPrototypeOf(this, new.target.prototype); // restaure la chaîne du prototype + + this.name = name; + this.httpCode = httpCode; + this.isOperational = isOperational; + + Error.captureStackTrace(this); + } +} + +// le client levant une exception +if(user == null) + throw new AppError(commonErrors.resourceNotFound, commonHTTPErrors.notFound, 'plus d\'explications', true) +``` +
+ +*Explication sur `Object.setPrototypeOf` en Typescript : https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html#support-for-newtarget* + +### Citation de blog : « Je ne vois pas l'intérêt d'avoir beaucoup de types d'objets d'erreur différents » + +Extrait du blog de Ben Nadel classé en 5ème position pour les mots clés “Node.js error object” + +>… Personnellement, je ne vois pas l'intérêt d'avoir beaucoup de types d'objets d'erreur différents [comparé à l'extension d'une seule fois de AppError] - JavaScript, en tant que langage, ne semble pas répondre à la capture d'erreurs basée sur le constructeur. En tant que tel, la différenciation sur une propriété d'objet semble beaucoup plus facile que la différenciation sur un type de constructeur… + +### Citation de blog : « Une chaîne n'est pas une erreur » + +Extrait du blog de devthought.com classé en 6ème position pour les mots clés “Node.js error object” + +> …le passage d'une chaîne au lieu d'une erreur entraîne une interopérabilité réduite entre les modules. Il rompt les contrats avec les API qui pourraient effectuer des vérifications d'Error avec `instanceof`, ou qui veulent en savoir plus sur l'erreur. Les objets d'Error, comme nous le verrons, ont des propriétés très intéressantes dans les moteurs JavaScript modernes en plus de contenir le message transmis au constructeur… + +### Citation de blog : « L'héritage d'Error n'ajoute pas trop de valeur » + +Extrait du blog de machadogj + +> …Un problème que j'ai avec la classe Error est qu'il n'est pas si simple à étendre. Bien sûr, vous pouvez hériter de la classe et créer vos propres classes d'erreur comme HttpError, DbError, etc. Cependant, cela prend du temps et n'ajoute pas trop de valeur [que de l'étendre une seule fois pour une AppError] à moins que vous ne fassiez quelque chose avec des types. Parfois, vous voulez simplement ajouter un message et conserver l'erreur interne, et parfois vous voudrez peut-être étendre l'erreur avec des paramètres, etc.… + +### Citation de blog : « Toutes les erreurs JavaScript et Système levées par Node.js héritent de Error » + +Extrait de la documentation officielle de Node.js + +> …Toutes les erreurs JavaScript et Système levées par Node.js héritent de, ou sont des instances de, la classe Error du JavaScript standard et sont garantes de fournir au moins les propriétés disponibles sur cette classe. Un objet Error JavaScript générique n'indique aucune circonstance particulière expliquant pourquoi l'erreur s'est produite. Les objets d'erreur capturent une « trace de la pile » détaillant le point dans le code où l'erreur a été instanciée et peuvent fournir une description textuelle de l'erreur. Toutes les erreurs générées par Node.js, y compris toutes les erreurs système et JavaScript, seront des instances ou hériteront de la classe Error… diff --git a/sections/performance/block-loop.basque.md b/sections/performance/block-loop.basque.md new file mode 100644 index 000000000..adf5f3e63 --- /dev/null +++ b/sections/performance/block-loop.basque.md @@ -0,0 +1,53 @@ +# Ez blokeatu gertaeren begizta + +

+ +Nodek gertaeren begizta nagusiki hari bakarraren barruan kudeatzen du, hainbat ilaren artean txandakatuz. Prozesu horretan, bada eragile bat baino gehiago gertaeren begizta geldiaraz dezakeena, hala nola konplexutasun handiko ekintzak, json fitxategi handien sintaxi analisiak, logikaren erabilera sorta oso handietan, seguruak ez diren adierazpen erregularren kontsultak eta sarrera/irteera operazio garrantzitsuak. Ekidin ataza intentsibo horiek PUZetik zerbitzu dedikatu batera pasatzea (adibidez, ataza zerbitzaria) edo ataza luzeak urrats txikietan banatzea eta gero Worker Pool erabiltzea. Horiexek dira gertaeren begizta blokeatzea ekiditeko bideetako batzuk. + +### Adibidea: gertaeren begizta blokeatzea + +Ikusi [Node Clinic](https://clinicjs.org/documentation/doctor/05-fixing-event-loop-problem)-en adibide bat + +```javascript +function lokartu(ms) { + const etorkizuna = Date.now() + ms; + while (Date.now() < etorkizuna); +} + +server.get("/", (req, res, next) => { + lokartu(30); + res.send({}); + next(); +}); +``` + +Aplikazio honen probak egitean, 'while' komandoak sortutako latentzia ikusiko dugu + +### Egikaritu proben segida + +`clinic doctor --on-port 'autocannon localhost:$PORT' -- node slow-event-loop` + +### Emaitzak + +``` +┌────────────┬────────┬────────┬────────┬────────┬────────────────┬──────────┬───────────┐ +│ Statistika │ 2.5% │ 50% │ 97.5% │ 99% │ Baztazbestekoa │ Stdev │ Max │ +├────────────┼────────┼────────┼────────┼────────┼────────────────┼──────────┼───────────┤ +│ Latentzia │ 270 ms │ 300 ms │ 328 ms │ 331 ms │ 300.56 ms │ 38.55 ms │ 577.05 ms │ +└────────────┴────────┴────────┴────────┴────────┴────────────────┴──────────┴───────────┘ +┌────────────┬────────┬────────┬────────┬────────┬────────────────┬──────────┬───────────┐ +│ Statistika │ 1% │ 2.5% │ 50% │ 97.5% │ Baztazbestekoa │ Stdev │ Min │ +├────────────┼────────┼────────┼────────┼────────┼────────────────┼──────────┼───────────┤ +│ Req/Sec │ 31 │ 31 │ 33 │ 34 │ 32.71 │ 1.01 │ 31 │ +├────────────┼────────┼────────┼────────┼────────┼────────────────┼──────────┼───────────┤ +``` + +## Gertaeren begiztaren irudia + +![Gertaeren begiztaren irudia](../../assets/images/event-loop.png "Gertaeren begiztaren irudia") + +> Hemen duzu oinarrizko arau bat zure Node zerbitzaria azkarra izaten jarraitzeko: Node azkarra da une jakin batean bezero bakoitzarekin lotutako lana "txikia" denean. +> [Ez blokeatu gertaeren begizta (edota atazen begizta) | Node.js](https://nodejs.org/en/docs/guides/dont-block-the-event-loop/) + +> Gehiengo batek huts egiten du beren lehenengo NodeJS aplikazioak egiterako orduan, gertaeren begizta, erroreen kudeaketa eta asinkronoaren inguruko kontzeptuak ez ulertzeagatik. +> [Gertaeren begiztaren jarraibide egokiak — NodeJS gertaeren begizta, 5.partea](https://jsblog.insiderattack.net/event-loop-best-practices-nodejs-event-loop-part-5-e29b2b50bfe2) diff --git a/sections/performance/block-loop.french.md b/sections/performance/block-loop.french.md new file mode 100644 index 000000000..fd7c99b1f --- /dev/null +++ b/sections/performance/block-loop.french.md @@ -0,0 +1,58 @@ +# Don't block the event loop + +

+ +Node handles the Event Loop mostly on a single thread rotating through multiple queues. Operations with high complexity, large json parsing, applying logic over huge arrays, unsafe regex queries, and large IO operations are some of the operations that can cause the Event Loop to stall. Avoid this off-loading CPU intensive tasks to a dedicated service (e.g. job server), or breaking long tasks into small steps then using the Worker Pool are some examples of how to avoid blocking the Event Loop. + +### Example: blocking the event loop +Let's take a look at an example from [Node Clinic](https://clinicjs.org/documentation/doctor/05-fixing-event-loop-problem). +```javascript +function sleep (ms) { + const future = Date.now() + ms + while (Date.now() < future); +} + +server.get('/', (req, res, next) => { + sleep(30) + res.send({}) + next() +}) +``` + +And when we benchmark this app, we start to see the latency caused by the long +while loop. + +### Run the benchmark +`clinic doctor --on-port 'autocannon localhost:$PORT' -- node slow-event-loop` + +### The results + +``` +┌─────────┬────────┬────────┬────────┬────────┬───────────┬──────────┬───────────┐ +│ Stat │ 2.5% │ 50% │ 97.5% │ 99% │ Avg │ Stdev │ Max │ +├─────────┼────────┼────────┼────────┼────────┼───────────┼──────────┼───────────┤ +│ Latency │ 270 ms │ 300 ms │ 328 ms │ 331 ms │ 300.56 ms │ 38.55 ms │ 577.05 ms │ +└─────────┴────────┴────────┴────────┴────────┴───────────┴──────────┴───────────┘ +┌───────────┬─────────┬─────────┬─────────┬────────┬─────────┬───────┬─────────┐ +│ Stat │ 1% │ 2.5% │ 50% │ 97.5% │ Avg │ Stdev │ Min │ +├───────────┼─────────┼─────────┼─────────┼────────┼─────────┼───────┼─────────┤ +│ Req/Sec │ 31 │ 31 │ 33 │ 34 │ 32.71 │ 1.01 │ 31 │ +├───────────┼─────────┼─────────┼─────────┼────────┼─────────┼───────┼─────────┤ +``` + +## Image of the Event Loop +![Event Loop](../../assets/images/event-loop.png "Event Loop") + + +### "Here's a good rule of thumb for keeping your Node server speedy: _Node is fast when the work associated with each client at any given time is 'small'_." +From Node.js Documentation - [Don't Block the Event Loop (or the Worker Pool)](https://nodejs.org/en/docs/guides/dont-block-the-event-loop/) + +> The secret to the scalability of Node.js is that it uses a small number of threads to handle many clients. +> If Node.js can make do with fewer threads, then it can spend more of your system's time and memory working on clients rather than on paying space and time overheads for threads (memory, context-switching). +> But because Node.js has only a few threads, you must structure your application to use them wisely. +> +> Here's a good rule of thumb for keeping your Node.js server speedy: Node.js is fast when the work associated with each client at any given time is "small". +> This applies to callbacks on the Event Loop and tasks on the Worker Pool. + +### "Most people fail their first few NodeJS apps merely due to the lack of understanding of the concepts such as the Event Loop, Error handling and asynchrony" +From Deepal's Blog - [Event Loop Best Practices — NodeJS Event Loop Part 5](https://blog.insiderattack.net/event-loop-best-practices-nodejs-event-loop-part-5-e29b2b50bfe2) diff --git a/sections/performance/block-loop.japanese.md b/sections/performance/block-loop.japanese.md index 74ef88b1e..7d2a42f57 100644 --- a/sections/performance/block-loop.japanese.md +++ b/sections/performance/block-loop.japanese.md @@ -40,7 +40,7 @@ server.get('/', (req, res, next) => { ``` ## イベントループのイメージ図 -![イベントループ](/assets/images/event-loop.png "イベントループ") +![イベントループ](../../assets/images/event-loop.png "イベントループ") >ここに、Node サーバを高速に保つための良い経験則があります: Node は、与えられた時間にそれぞれのクライアントに関連する作業が 「小さい」 場合に高速です。 >[イベントループ(またはワーカープール)をブロックしない | Node.js](https://nodejs.org/en/docs/guides/dont-block-the-event-loop/) diff --git a/sections/performance/block-loop.md b/sections/performance/block-loop.md index 16d7e192b..cba98a3c4 100644 --- a/sections/performance/block-loop.md +++ b/sections/performance/block-loop.md @@ -41,10 +41,19 @@ while loop. ``` ## Image of the Event Loop -![Event Loop](/assets/images/event-loop.png "Event Loop") +![Event Loop](../../assets/images/event-loop.png "Event Loop") ->Here's a good rule of thumb for keeping your Node server speedy: Node is fast when the work associated with each client at any given time is "small". ->[Don't Block the Event Loop (or the Worker Pool) | Node.js](https://nodejs.org/en/docs/guides/dont-block-the-event-loop/) -> Most people fail their first few NodeJS apps merely due to the lack of understanding of the concepts such as the Event Loop, Error handling and asynchrony -[Event Loop Best Practices — NodeJS Event Loop Part 5](https://jsblog.insiderattack.net/event-loop-best-practices-nodejs-event-loop-part-5-e29b2b50bfe2) +### "Here's a good rule of thumb for keeping your Node server speedy: _Node is fast when the work associated with each client at any given time is 'small'_." +From Node.js Documentation - [Don't Block the Event Loop (or the Worker Pool)](https://nodejs.org/en/docs/guides/dont-block-the-event-loop/) + +> The secret to the scalability of Node.js is that it uses a small number of threads to handle many clients. +> If Node.js can make do with fewer threads, then it can spend more of your system's time and memory working on clients rather than on paying space and time overheads for threads (memory, context-switching). +> But because Node.js has only a few threads, you must structure your application to use them wisely. +> +> Here's a good rule of thumb for keeping your Node.js server speedy: Node.js is fast when the work associated with each client at any given time is "small". +> This applies to callbacks on the Event Loop and tasks on the Worker Pool. + +### "Most people fail their first few NodeJS apps merely due to the lack of understanding of the concepts such as the Event Loop, Error handling and asynchrony" +From Deepal's Blog - [Event Loop Best Practices — NodeJS Event Loop Part 5](https://blog.insiderattack.net/event-loop-best-practices-nodejs-event-loop-part-5-e29b2b50bfe2) + diff --git a/sections/performance/block-loop.polish.md b/sections/performance/block-loop.polish.md index 401677ac5..ab7cb013c 100644 --- a/sections/performance/block-loop.polish.md +++ b/sections/performance/block-loop.polish.md @@ -41,7 +41,7 @@ pętlą while. ``` ## Obraz pętli zdarzeń -![Event Loop](/assets/images/event-loop.png "Event Loop") +![Event Loop](../../assets/images/event-loop.png "Event Loop") >Here's a good rule of thumb for keeping your Node server speedy: Node is fast when the work associated with each client at any given time is "small". >[Don't Block the Event Loop (or the Worker Pool) | Node.js](https://nodejs.org/en/docs/guides/dont-block-the-event-loop/) diff --git a/sections/performance/block-loop.russian.md b/sections/performance/block-loop.russian.md index 6a0097782..88b24c4a4 100644 --- a/sections/performance/block-loop.russian.md +++ b/sections/performance/block-loop.russian.md @@ -41,7 +41,7 @@ while loop. ``` ## Изображение цикла событий -![Event Loop](/assets/images/event-loop.png "Event Loop") +![Event Loop](../../assets/images/event-loop.png "Event Loop") Вот хорошее эмпирическое правило для поддержания скорости вашего Node-сервера: Node работает быстро, когда работа, связанная с каждым клиентом в любой момент времени, "мала". >[Don't Block the Event Loop (or the Worker Pool) | Node.js](https://nodejs.org/en/docs/guides/dont-block-the-event-loop/) diff --git a/sections/performance/nativeoverutil.basque.md b/sections/performance/nativeoverutil.basque.md new file mode 100644 index 000000000..cc0a1ad68 --- /dev/null +++ b/sections/performance/nativeoverutil.basque.md @@ -0,0 +1,73 @@ +# Hobetsi jatorrizko JS metodoak Lodash bezalako erabiltzaileen baliabideak baino + +

+ +### Azalpena + +Batzuetan, hobe da jatorrizko metodoak erabiltzea _lodash_ edo _underscore_ bezalako liburutegiak erabili beharra izatea baino, liburutegi horiek errendimendu galera bat ekar baitezakete eta beharrezko baino memoria gehiago erabili. Jatorrizko funtzioak erabiltzeak [%50 inguruko erabateko irabazia](https://github.com/Berkmann18/NativeVsUtils/blob/master/analysis.xlsx) lor dezake, adibidez, funtzio hauek: `Array.concat`, `Array.fill`, `Array.filter`, `Array.map`, `(Array|String).indexOf`, `Object.find`, … + + + + +

+ +### Abididea: konparaketa probak - Lodash versus V8 (jatorrizkoa) + +Beheko grafikoak [Lodashen metodo ugariren proben erreferentzien](https://github.com/Berkmann18/NativeVsUtils/blob/master/nativeVsLodash.ods) batez bestekoa erakusten du. Horrek erakusten du Lodash metodoek batez beste %146,23 denbora gehiago behar dutela V8 metodoen ataza berdinak burutzeko. + +![esanahia](../../assets/images/sampleMeanDiag.png) + +### Kode adibidea: `_.concat`/`Array.concat`en proba + +```javascript +const _ = require("lodash"); +const __ = require("underscore"); +const Suite = require("benchmark").Suite; +const opts = require("./utils"); //cf. https://github.com/Berkmann18/NativeVsUtils/blob/master/utils.js + +const concatSuite = new Suite("concat", opts); +const array = [0, 1, 2]; + +concatSuite + .add("lodash", () => _.concat(array, 3, 4, 5)) + .add("underscore", () => __.concat(array, 3, 4, 5)) + .add("native", () => array.concat(3, 4, 5)) + .run({ async: true }); +``` + +Non hau bueltatzen duen: + +![output](../../assets/images/concat-benchmark.png) + +[Hemen](https://github.com/Berkmann18/NativeVsUtils/blob/master/index.txt) duzu proba erreferentzia puntuen zerrenda luzeago bat edo, bestela, [egikaritu hau](https://github.com/Berkmann18/NativeVsUtils/blob/master/index.js), hori bera erakutsiko dizu, baina koloretan. + +### Blog aipua: "(baliteke) Ez duzu Lodash/Underscoreren beharrik (ez izatea)" + +[Lodash eta Underscoren inguruko gaiei buruzko txostena](https://github.com/you-dont-need/You-Dont-Need-Lodash-Underscore). + +> JavaScripten baliabideen liburutegi moderno bikainak dira Lodash eta Underscore, eta Front-end garatzaileen artean oso erabiliak. Hala ere, nabigatzaile modernoak jomugatzat dituzunean, pentsa dezakezu ECMAScript5ek [ES5] eta ECMAScript2015ek [ES6] badituztela jatorriz funtzio horietako asko. Zure proiektuak menpekotasun gutxiago edukitzea nahi baduzu, eta argi badaukazu zein nabilgatzaile duzun helburutzat, baliteke behar ez izatea Lodash/Underscore. + +### Adibidea: jatorrizkoak ez diren metodoak erabiltzeko linting-a + +Badago [ESLint plugin](https://www.npmjs.com/package/eslint-plugin-you-dont-need-lodash-underscore) bat behar ez dituzun liburutegiak atzeman eta aholkuak ematen dizkizuna (behean duzu adibidea).
Plugin hori erabili nahi baduzu, gehitu `eslint-plugin-you-dont-need-lodash-underscore` plugina zure ESLint ezarpen fitxategiari: + +```json +{ + "extends": ["plugin:you-dont-need-lodash-underscore/compatible"] +} +``` + +### Adibidea: linter bat erabiliz, atzeman beharrezko ez diren v8 funtzionalitateen erabilera + +Eman begirada bat azpiko fitxategiari: + +```js +const _ = require("lodash"); +// ESLintek azpiko lerroa markatuko du iradokizun batekin +console.log(_.map([0, 1, 2, 4, 8, 16], (x) => `d${x}`)); +``` + +Hementxe dago ESLintek bistaratuko lukeena YDNLU plugina erabiliz. +![irteera](../../assets/images/ydnlu.png) + +Noski, adibide horrek ez du errealista ematen egungo kodeek dutena kontutan hartuta, baina bai balio du ulertzeko. diff --git a/sections/performance/nativeoverutil.brazilian-portuguese.md b/sections/performance/nativeoverutil.brazilian-portuguese.md index 22d80e426..e7fa0942e 100644 --- a/sections/performance/nativeoverutil.brazilian-portuguese.md +++ b/sections/performance/nativeoverutil.brazilian-portuguese.md @@ -47,7 +47,7 @@ Do [repositório sobre esse assunto que foca em Lodash e Underscore](https://git > O Lodash e o Underscore são ótimas bibliotecas de utilitários JavaScript moderno e são amplamente utilizados por desenvolvedores front-end. No entanto, quando você está focando nos navegadores modernos, você pode descobrir que existem muitos métodos que já são suportados nativamente graças ao ECMAScript5 [ES5] e ao ECMAScript2015 [ES6]. Se você quer que seu projeto exija menos dependências, e você conhece claramente o seu navegador de destino, talvez você não precise do Lodash/Underscore. ### Exemplo: Linting para uso de métodos não nativos -Existe um [plugin de ESLint](https://www.npmjs.com/package/eslint-plugin-you-dont-need-lodash-underscore) que detecta onde você está usando bibliotecas, mas não precisa, alertando com sugestões (veja o exemplo abaixo).
+Existe um [plugin de ESLint](https://www.npmjs.com/package/eslint-plugin-you-dont-need-lodash-underscore) que detecta onde você está usando bibliotecas, mas não precisa, alertando com sugestões (veja o exemplo abaixo).
A maneira de configurá-lo é adicionando o plugin `eslint-plugin-you-dont-need-lodash-underscore` no seu arquivo de configuração do ESLint: ```json { diff --git a/sections/performance/nativeoverutil.french.md b/sections/performance/nativeoverutil.french.md new file mode 100644 index 000000000..7b79ddc65 --- /dev/null +++ b/sections/performance/nativeoverutil.french.md @@ -0,0 +1,70 @@ +# Prefer native JS methods over user-land utils like Lodash + + +

+ +### One Paragraph Explainer + +Sometimes, using native methods is better than requiring _lodash_ or _underscore_ because those libraries can lead to performance loss or take up more space than needed. +The performance using native methods result in an [overall ~50% gain](https://github.com/Berkmann18/NativeVsUtils/blob/master/analysis.xlsx) which includes the following methods: `Array.concat`, `Array.fill`, `Array.filter`, `Array.map`, `(Array|String).indexOf`, `Object.find`, ... + + + + +

+ +### Example: benchmark comparison - Lodash vs V8 (Native) +The graph below shows the [mean of the benchmarks for a variety of Lodash methods](https://github.com/Berkmann18/NativeVsUtils/blob/master/nativeVsLodash.ods), this shows that Lodash methods take on average 146.23% more time to complete the same tasks as V8 methods. + +![meanDiag](../../assets/images/sampleMeanDiag.png) + +### Code Example – Benchmark test on `_.concat`/`Array.concat` +```javascript +const _ = require('lodash'); +const __ = require('underscore'); +const Suite = require('benchmark').Suite; +const opts = require('./utils'); //cf. https://github.com/Berkmann18/NativeVsUtils/blob/master/utils.js + +const concatSuite = new Suite('concat', opts); +const array = [0, 1, 2]; + +concatSuite.add('lodash', () => _.concat(array, 3, 4, 5)) + .add('underscore', () => __.concat(array, 3, 4, 5)) + .add('native', () => array.concat(3, 4, 5)) + .run({ 'async': true }); +``` + +Which returns this: + +![output](../../assets/images/concat-benchmark.png) + +You can find a bigger list of benchmarks [here](https://github.com/Berkmann18/NativeVsUtils/blob/master/index.txt) or alternatively [run this](https://github.com/Berkmann18/NativeVsUtils/blob/master/index.js) which would show the same but with colours. + +### Blog Quote: "You don't (may not) need Lodash/Underscore" + +From the [repo on this matter which focuses on Lodash and Underscore](https://github.com/you-dont-need/You-Dont-Need-Lodash-Underscore). + + > Lodash and Underscore are great modern JavaScript utility libraries, and they are widely used by Front-end developers. However, when you are targeting modern browsers, you may find out that there are many methods which are already supported natively thanks to ECMAScript5 [ES5] and ECMAScript2015 [ES6]. If you want your project to require fewer dependencies, and you know your target browser clearly, then you may not need Lodash/Underscore. + +### Example: Linting for non-native methods usage +There's an [ESLint plugin](https://www.npmjs.com/package/eslint-plugin-you-dont-need-lodash-underscore) which detects where you're using libraries but don't need to by warning you with suggestions (cf. example below).
+The way you set it up is by adding the `eslint-plugin-you-dont-need-lodash-underscore` plugin to your ESLint configuration file: +```json +{ + "extends": [ + "plugin:you-dont-need-lodash-underscore/compatible" + ] +} +``` + +### Example: detecting non-v8 util usage using a linter +Consider the file below: +```js +const _ = require('lodash'); +// ESLint will flag the line above with a suggestion +console.log(_.map([0, 1, 2, 4, 8, 16], x => `d${x}`)); +``` +Here's what ESLint would output when using the YDNLU plugin. +![output](../../assets/images/ydnlu.png) + +Of course, the example above doesn't seem realistic considering what actual codebases would have but you get the idea. diff --git a/sections/performance/nativeoverutil.japanese.md b/sections/performance/nativeoverutil.japanese.md index 809a7de07..c9875c59d 100644 --- a/sections/performance/nativeoverutil.japanese.md +++ b/sections/performance/nativeoverutil.japanese.md @@ -46,7 +46,7 @@ concatSuite.add('lodash', () => _.concat(array, 3, 4, 5)) > Lodash や Underscore は素晴らしいモダンな JavaScript ユーティリティライブラリであり、フロントエンド開発者に広く利用されています。しかし、最新のブラウザをターゲットにしている場合、ECMAScript5 [ES5] や ECMAScript2015 [ES6] のおかげで、すでにネイティブでサポートされているメソッドがたくさんあることに気づくかもしれません。プロジェクトに必要な依存関係を少なくしたく、ターゲットブラウザを明確に理解している場合は、Lodash/Underscore は必要ないかもしれません。 ### 例: 非ネイティブメソッドの使用法に対応した Lint -ライブラリを使っているが必要のない場所を検知して、提案付きで警告してくれる[ ESLint プラグイン](https://www.npmjs.com/package/eslint-plugin-you-dont-need-lodash-underscore)というものがあります。(下の例を参照)
+ライブラリを使っているが必要のない場所を検知して、提案付きで警告してくれる[ ESLint プラグイン](https://www.npmjs.com/package/eslint-plugin-you-dont-need-lodash-underscore)というものがあります。(下の例を参照)
設定方法は、ESLint の設定ファイルに `eslint-plugin-you-dont-need-lodash-underscore` プラグインを追加することです: ```json { diff --git a/sections/performance/nativeoverutil.md b/sections/performance/nativeoverutil.md index 48804fe99..fe8f092fc 100644 --- a/sections/performance/nativeoverutil.md +++ b/sections/performance/nativeoverutil.md @@ -46,7 +46,7 @@ From the [repo on this matter which focuses on Lodash and Underscore](https://gi > Lodash and Underscore are great modern JavaScript utility libraries, and they are widely used by Front-end developers. However, when you are targeting modern browsers, you may find out that there are many methods which are already supported natively thanks to ECMAScript5 [ES5] and ECMAScript2015 [ES6]. If you want your project to require fewer dependencies, and you know your target browser clearly, then you may not need Lodash/Underscore. ### Example: Linting for non-native methods usage -There's an [ESLint plugin](https://www.npmjs.com/package/eslint-plugin-you-dont-need-lodash-underscore) which detects where you're using libraries but don't need to by warning you with suggestions (cf. example below).
+There's an [ESLint plugin](https://www.npmjs.com/package/eslint-plugin-you-dont-need-lodash-underscore) which detects where you're using libraries but don't need to by warning you with suggestions (cf. example below).
The way you set it up is by adding the `eslint-plugin-you-dont-need-lodash-underscore` plugin to your ESLint configuration file: ```json { diff --git a/sections/performance/nativeoverutil.polish.md b/sections/performance/nativeoverutil.polish.md index 9df041bda..d0e0bb581 100644 --- a/sections/performance/nativeoverutil.polish.md +++ b/sections/performance/nativeoverutil.polish.md @@ -46,7 +46,7 @@ Z [repozytorium na ten temat, które koncentruje się na Lodash i Underscore](ht > Lodash and Underscore are great modern JavaScript utility libraries, and they are widely used by Front-end developers. However, when you are targeting modern browsers, you may find out that there are many methods which are already supported natively thanks to ECMAScript5 [ES5] and ECMAScript2015 [ES6]. If you want your project to require fewer dependencies, and you know your target browser clearly, then you may not need Lodash/Underscore. ### Przykład: Linting for non-native methods usage -Istnieje [wtyczka ESLint](https://www.npmjs.com/package/eslint-plugin-you-dont-need-lodash-underscore) która wykrywa, gdzie korzystasz z bibliotek, ale nie musisz, ostrzegając Cię sugestiami (porównaj z przykładem poniżej).
+Istnieje [wtyczka ESLint](https://www.npmjs.com/package/eslint-plugin-you-dont-need-lodash-underscore) która wykrywa, gdzie korzystasz z bibliotek, ale nie musisz, ostrzegając Cię sugestiami (porównaj z przykładem poniżej).
Sposób konfiguracji polega na dodaniu wtyczki `eslint-plugin-you-dont-need-lodash-underscore` do pliku konfiguracyjnego ESLint: ```json { diff --git a/sections/performance/nativeoverutil.russian.md b/sections/performance/nativeoverutil.russian.md index 0b3ff6e0c..be05f010b 100644 --- a/sections/performance/nativeoverutil.russian.md +++ b/sections/performance/nativeoverutil.russian.md @@ -47,7 +47,7 @@ concatSuite.add('lodash', () => _.concat(array, 3, 4, 5)) > Lodash и Underscore - отличные современные библиотеки утилит JavaScript, и они широко используются разработчиками Front-end. Однако, когда вы ориентируетесь на современные браузеры, вы можете обнаружить, что есть много методов, которые уже изначально поддерживаются благодаря ECMAScript5 [ES5] и ECMAScript2015 [ES6]. Если вы хотите, чтобы вашему проекту требовалось меньше зависимостей, и вы четко знаете целевой браузер, то вам может не потребоваться Lodash/Underscore. ### Пример: Linting для использования неродных методов -Существует [плагин ESLint](https://www.npmjs.com/package/eslint-plugin-you-dont-need-lodash-underscore), который определяет, где вы используете библиотеки, но не должен предупреждать вас с предложениями (см. пример ниже).
+Существует [плагин ESLint](https://www.npmjs.com/package/eslint-plugin-you-dont-need-lodash-underscore), который определяет, где вы используете библиотеки, но не должен предупреждать вас с предложениями (см. пример ниже).
Вы можете настроить его, добавив плагин `eslint-plugin-you-dont-need-lodash-underscore` в файл конфигурации ESLint: ```json { diff --git a/sections/production/LTSrelease.basque.md b/sections/production/LTSrelease.basque.md new file mode 100644 index 000000000..6069f91f3 --- /dev/null +++ b/sections/production/LTSrelease.basque.md @@ -0,0 +1,21 @@ +# Erabili Node.js LTS bertsioa ekoizpenean + +### Azalpena + +Ziurtatu ekoizpenean NTS.jsen LTS (Long Term Support) bertsioa erabiltzen ari zarela erroreen konponketa kritikoak, segurtasun eguneratzeak eta errendimendu hobekuntzak jasotzeko. + +Node.jsren LTS bertsioak gutxienez 18 hilabetez onartzen dira, eta bertsio zenbaki bikoitien bidez adierazten dira (adibidez, 4, 6, 8). Bertsioak onenak dira ekoizpenerako, LTS bertsio lerroa egonkortasunera eta segurtasunera bideratuta baitago, "Oraingo" bertsio lerroak, berriz, bizitza motzagoa eta maizago eguneratzen du kodea. LTS bertsioen aldaketak egonkortasuna, segurtasun eguneratzeak, npm eguneratze posibleak, dokumentazio eguneratzeak eta lehendik dauden aplikazioak ez apurtzeko frogatu daitezkeen zenbait errendimendu hobekuntzetara mugatzen dira. + +

+ +### Jarraitu irakurtzen + +🔗 [Node.jsren bertsioen definizioak](https://nodejs.org/en/about/releases/) + +🔗 [Node.js kaleratze egutegia](https://github.com/nodejs/Release) + +🔗 [Funtsezko urratsak; Rod Vagg-en epe luzeko laguntza Node.jsrentzat](https://medium.com/@nodesource/essential-steps-long-term-support-for-node-js-8ecf7514dbd) + +> ...Hauetako bakoitzaren bertsio inkrementalen egutegia erroreen konponketen, segurtasun konponketen eta beste aldaketa txiki baina garrantzitsu batzuen eskuragarritasunaren araberakoa izango da. Fokua egonkortasuna da, baina errore ezagunen kopurua minimizatzea eta segurtasun arazoak sortu ahala haien berri jakitea ere bada egonkortasuna bermatzea. + +

diff --git a/sections/production/LTSrelease.chinese.md b/sections/production/LTSrelease.chinese.md new file mode 100644 index 000000000..64f754ca3 --- /dev/null +++ b/sections/production/LTSrelease.chinese.md @@ -0,0 +1,20 @@ +# 使用 Node.js 的 LTS 版本 + +### 一段解释 + +确保您在正式环境中使用的是LTS(长期支持)版本的Node.js来获取关键错误的修复、安全更新和性能改进. + +LTS版本的Node.js至少支持18个月,并由偶数版本号(例如 4、6、8)表示。它们最适合生产环境,因为LTS的发行线专注于稳定性和安全性,而“Current”版本发布寿命较短,代码更新更加频繁。LTS版本的更改仅限于稳定性错误修复、安全更新、合理的npm更新、文档更新和某些可以证明不会破坏现有应用程序的性能改进。 + +

+ +### 继续读下去 + +🔗 [ Node.js版本定义 ](https://nodejs.org/en/about/releases/) + +🔗 [ Node.js发布时间表 ](https://github.com/nodejs/Release) + +🔗 [必要步骤:Long Term Support for Node.js by Rod Vagg(Node.js的长期支持by Rod Vagg)](https://medium.com/@nodesource/essential-steps-long-term-support-for-node-js-8ecf7514dbd) +> ...每个增量发布计划将由错误修复、安全修复和其他小但重要的更改的可用性来驱动。重点将放在稳定性上,但稳定性还包括最大程度地减少已知错误的数量,和持续关注重大的安全问题。 + +

diff --git a/sections/production/LTSrelease.french.md b/sections/production/LTSrelease.french.md new file mode 100644 index 000000000..e4abe1882 --- /dev/null +++ b/sections/production/LTSrelease.french.md @@ -0,0 +1,20 @@ +# Utilisez une version LTS de Node.js en production + +### Un paragraphe d'explication + +Assurez-vous d'utilise une version LTS (Long Term Support) de Node.js en production pour recevoir les corrections de bogues critiques, les mises à jour de sécurité et les améliorations de performance. + +Les versions LTS de Node.js sont prises en charge pendant au moins 18 mois et sont indiquées par des numéros de version pairs (par exemple 4, 6, 8). Elles sont idéales pour la production car la ligne de version LTS est axée sur la stabilité et la sécurité, alors que la ligne de version "Current" a une durée de vie plus courte et des mises à jour plus fréquentes du code. Les modifications apportées aux versions LTS se limitent à des corrections de bogues pour la stabilité, des mises à jour de sécurité, d'éventuelles mises à jour npm, des mises à jour de la documentation et certaines améliorations des performances dont il peut être prouvé qu'elles ne nuisent pas aux applications existantes. + +

+ +### A lire + +🔗 [Définitions des versions de Node.js](https://nodejs.org/en/about/releases/) + +🔗 [Calendrier de diffusion de Node.js](https://github.com/nodejs/Release) + +🔗 [Étapes essentielles : Support à long terme (Long Term Support) pour Node.js par Rod Vagg](https://medium.com/@nodesource/essential-steps-long-term-support-for-node-js-8ecf7514dbd) +> ...le calendrier des versions incrémentales de chacune d'entre elles sera déterminé par la disponibilité des corrections de bogues, des corrections de sécurité et d'autres changements, petits mais importants. L'accent sera mis sur la stabilité, mais la stabilité implique également de minimiser le nombre de bogues connus et de rester au fait des problèmes de sécurité au fur et à mesure qu'ils surviennent. + +

diff --git a/sections/production/apmproducts.basque.md b/sections/production/apmproducts.basque.md new file mode 100644 index 000000000..14580c477 --- /dev/null +++ b/sections/production/apmproducts.basque.md @@ -0,0 +1,25 @@ +# Erabiltzaile esperientzia segurua APM produktuekin + +

+ +### Azalpena + +APM (aplikazioaren errendimenduaren jarraipena) produktu familia bat da, aplikazioaren errendimendua hasieratik amaierara kontrolatzea helburu duena, baita bezeroaren ikuspegitik ere. Jarraipen tradizionaleko irtenbideak salbuespenetan eta metrika tekniko independenteetan oinarritzen dira (adibidez, erroreen jarraipena, zerbitzariaren amaiera puntu motelak, etab.). Mundu errealean, aldiz, gure aplikazioak erabiltzaile etsiak sor ditzake inolako kode salbuespenik gabe, adibidez, middleware zerbitzu batzuek oso geldo lan egiten badute. APM produktuek erabiltzaileen esperientzia neurtzen dute hasieratik bukaerara, adibidez, frontend interfazea eta banatutako zerbitzu anitzak biltzen dituen sistema ematen dutenean; APM produktu batzuek maila desberdinetako transakzio batek zenbateraino irauten duen jakin dezakete. Erabiltzailearen esperientzia ona den ala ez esan eta arazoa seinalatu dezake. Eskaintza erakargarri horrek prezio nahiko altua duenez, egokia da produktu konplexu eta jarraipen soiletik haratago joan beharra duten eskala handikoekin lan egiteko + +

+ +### APM adibidea: zerbitzuen arteko aplikazioen errendimendua ikusarazten duen produktu komertziala + +![APM adibidea](../../assets/images/apm1.png "APM adibidea") + +

+ +### APM adibidea: erabiltzailearen esperientziaren puntuazioa azpimarratzen duen produktu komertziala + +![APM adibidea](../../assets/images/apm2.png "APM adibidea") + +

+ +### APM adibidea: kode geldoen bideak nabarmentzen dituen produktu komertziala + +![APM adibidea](../../assets/images/apm3.png "APM adibidea") diff --git a/sections/production/apmproducts.brazilian-portuguese.md b/sections/production/apmproducts.brazilian-portuguese.md index ce46992b9..d51ebf68c 100644 --- a/sections/production/apmproducts.brazilian-portuguese.md +++ b/sections/production/apmproducts.brazilian-portuguese.md @@ -10,16 +10,16 @@ O APM (monitoramento de desempenho de aplicação) refere-se a uma família de p ### Exemplo de APM - um produto comercial que visualiza o desempenho de aplicações de serviço cruzado -![Exemplo de APM](/assets/images/apm1.png "Exemplo de APM") +![Exemplo de APM](../../assets/images/apm1.png "Exemplo de APM")

### Exemplo de APM - um produto comercial que enfatiza a pontuação da experiência do usuário -![Exemplo de APM](/assets/images/apm2.png "Exemplo de APM") +![Exemplo de APM](../../assets/images/apm2.png "Exemplo de APM")

### Exemplo de APM - um produto comercial que destaca caminhos de código lento -![Exemplo de APM](/assets/images/apm3.png "Exemplo de APM") +![Exemplo de APM](../../assets/images/apm3.png "Exemplo de APM") diff --git a/sections/production/apmproducts.chinese.md b/sections/production/apmproducts.chinese.md index 4c82d0739..1d4e32cc6 100644 --- a/sections/production/apmproducts.chinese.md +++ b/sections/production/apmproducts.chinese.md @@ -11,16 +11,16 @@ APM(应用程序性能监视)指的是一个产品系列, 目的是从端到 ### APM 示例 – 一种可视化显示跨服务应用性能的商业产品 -![APM example](/assets/images/apm1.png "APM example") +![APM example](../../assets/images/apm1.png "APM example")

### APM 示例 – 一种强调用户体验评分的商业产品 -![APM example](/assets/images/apm2.png "APM example") +![APM example](../../assets/images/apm2.png "APM example")

### APM 示例 – 一种突出显示慢速代码路径的商业产品 -![APM example](/assets/images/apm3.png "APM example") +![APM example](../../assets/images/apm3.png "APM example") diff --git a/sections/production/apmproducts.french.md b/sections/production/apmproducts.french.md new file mode 100644 index 000000000..959bcf009 --- /dev/null +++ b/sections/production/apmproducts.french.md @@ -0,0 +1,25 @@ +# Une expérience utilisateur sûre avec les produits APM + +

+ +### Un paragraphe d'explication + +APM (NdT, « Application Performance Monitoring » : surveillance des performances des applications) fait référence à une famille de produits qui vise à surveiller les performances des applications de bout en bout, également du point de vue du client. Alors que les solutions de surveillance classiques se concentrent sur les exceptions et les mesures techniques autonomes (par exemple, le suivi des erreurs, les points de terminaison de serveur lents, etc.), dans le monde réel, notre application pourrait décevoir des utilisateurs sans aucune erreur de code, par exemple, si certains services du middleware fonctionnent très lentement. Les produits APM mesurent l'expérience utilisateur de bout en bout, par exemple, prenons un système qui englobe l'interface utilisateur frontale et de multiples services distribués - certains produits APM peuvent dire à quelle vitesse s'effectue une transaction qui traverse plusieurs niveaux. Ils peuvent indiquer si l'expérience utilisateur est solide et indiquer le problème. Cette offre attrayante a un prix relativement élevé, elle est donc recommandée pour les produits à grande échelle et complexes qui nécessitent d'aller au-delà de la simple surveillance. + +

+ +### Exemple APM – un produit commercial qui visualise les performances des applications interservices + +![Exemple APM](../../assets/images/apm1.png "Exemple APM") + +

+ +### Exemple APM – un produit commercial qui met l'accent sur le score de l'expérience utilisateur + +![Exemple APM](../../assets/images/apm2.png "Exemple APM") + +

+ +### Exemple APM – un produit commercial qui met en évidence les chemins de code lents + +![Exemple APM](../../assets/images/apm3.png "Exemple APM") diff --git a/sections/production/apmproducts.japanese.md b/sections/production/apmproducts.japanese.md index 45650566b..d726dbf9a 100644 --- a/sections/production/apmproducts.japanese.md +++ b/sections/production/apmproducts.japanese.md @@ -10,16 +10,16 @@ APM(アプリケーション・パフォーマンス・モニタリング) ### APM の例 – サービス間のアプリパフォーマンスを可視化する商用製品 -![APM の例](/assets/images/apm1.png "APM の例") +![APM の例](../../assets/images/apm1.png "APM の例")

### APM の例 – ユーザーエクスペリエンススコアを重視した市販品 -![APM の例](/assets/images/apm2.png "APM の例") +![APM の例](../../assets/images/apm2.png "APM の例")

### APM の例 – 遅いコードパスをハイライトする商用製品 -![APM の例](/assets/images/apm3.png "APM の例") +![APM の例](../../assets/images/apm3.png "APM の例") diff --git a/sections/production/apmproducts.korean.md b/sections/production/apmproducts.korean.md index bd7e5754b..d5f0fbf80 100644 --- a/sections/production/apmproducts.korean.md +++ b/sections/production/apmproducts.korean.md @@ -10,16 +10,16 @@ APM (application performance monitoring) refers to a family of products that aim ### APM example – a commercial product that visualizes cross-service app performance -![APM example](/assets/images/apm1.png "APM example") +![APM example](../../assets/images/apm1.png "APM example")

### APM example – a commercial product that emphasizes the user experience score -![APM example](/assets/images/apm2.png "APM example") +![APM example](../../assets/images/apm2.png "APM example")

### APM example – a commercial product that highlights slow code paths -![APM example](/assets/images/apm3.png "APM example") +![APM example](../../assets/images/apm3.png "APM example") diff --git a/sections/production/apmproducts.md b/sections/production/apmproducts.md index bd7e5754b..d5f0fbf80 100644 --- a/sections/production/apmproducts.md +++ b/sections/production/apmproducts.md @@ -10,16 +10,16 @@ APM (application performance monitoring) refers to a family of products that aim ### APM example – a commercial product that visualizes cross-service app performance -![APM example](/assets/images/apm1.png "APM example") +![APM example](../../assets/images/apm1.png "APM example")

### APM example – a commercial product that emphasizes the user experience score -![APM example](/assets/images/apm2.png "APM example") +![APM example](../../assets/images/apm2.png "APM example")

### APM example – a commercial product that highlights slow code paths -![APM example](/assets/images/apm3.png "APM example") +![APM example](../../assets/images/apm3.png "APM example") diff --git a/sections/production/apmproducts.polish.md b/sections/production/apmproducts.polish.md index cbcb10697..f34c54ee9 100644 --- a/sections/production/apmproducts.polish.md +++ b/sections/production/apmproducts.polish.md @@ -10,16 +10,16 @@ APM (application performance monitoring) odnosi się do rodziny produktów, któ ### APM przykład - produkt komercyjny, który wizualizuje wydajność aplikacji między usługami -![APM example](/assets/images/apm1.png "APM example") +![APM example](../../assets/images/apm1.png "APM example")

### APM przykład - produkt komercyjny, który podkreśla ocenę doświadczenia użytkownika -![APM example](/assets/images/apm2.png "APM example") +![APM example](../../assets/images/apm2.png "APM example")

### APM przykład - produkt komercyjny, który wyróżnia wolne ścieżki kodu -![APM example](/assets/images/apm3.png "APM example") +![APM example](../../assets/images/apm3.png "APM example") diff --git a/sections/production/apmproducts.russian.md b/sections/production/apmproducts.russian.md index 6dda2dc50..9c019723f 100644 --- a/sections/production/apmproducts.russian.md +++ b/sections/production/apmproducts.russian.md @@ -10,16 +10,16 @@ APM (мониторинг производительности приложен ### Пример APM - коммерческий продукт, который визуализирует производительность кросс-сервисного приложения -![APM example](/assets/images/apm1.png "APM example") +![APM example](../../assets/images/apm1.png "APM example")

### Пример APM - коммерческий продукт, который подчеркивает оценку пользовательского опыта -![APM example](/assets/images/apm2.png "APM example") +![APM example](../../assets/images/apm2.png "APM example")

### Пример APM - коммерческий продукт, который выделяет медленные пути кода -![APM example](/assets/images/apm3.png "APM example") +![APM example](../../assets/images/apm3.png "APM example") diff --git a/sections/production/assigntransactionid.basque.md b/sections/production/assigntransactionid.basque.md new file mode 100644 index 000000000..01d89bcfd --- /dev/null +++ b/sections/production/assigntransactionid.basque.md @@ -0,0 +1,39 @@ +# Esleitu transakzio identifikazio bana adierazpen erregistro bakoitzari + +

+ +### Azalpena + +Ohiko erregistroa osagai eta eskaera guztien sarreren biltegia da. Lerro edo errore susmagarriren bat atzeman ondoren, zaila izaten da fluxu bereko beste lerro batzuekin bat etortzea (adibidez, "John" erabiltzailea zerbait erosten saiatu zen). Hori are kritikoagoa eta zailagoa bihurtzen da mikrozerbitzu ingurune batean eskaera/transakzio bat ordenagailu askotan zehar sor daitekeenean. Esleitu eskaera bateko sarrera guztiei transakzio identifikatzaile balio bakarra, eta, horrela, lerro bat atzematean, IDa/identifikazioa kopiatu eta antzeko transakzio IDa/identifikazioa duen lerro bakoitza bilatu ahal izango da eta. Hala ere, In Node hori lortzea ez da erraza, hari bakarra erabiltzen baita eskaera guztiei erantzuteko. Aztertu ez ote zaizun komeni liburutegi bat erabiltzea datuak bil ditzakeena eskaera mailan. Ikusi hurrengo diapositibako kode adibidea. Beste mikrozerbitzu batzuk deitzean, igorri transakzioaren IDa "x-transaction-id" bezalako HTTP goiburua erabiliz testuinguru bera mantentzeko. + +

+ +### Kode adibidea: Express konfigurazio tipikoa + +```javascript +// eskaera berria jasotzean, kontextu isolatu berria hasi eta transakzio identifikazioa ezarri. Hurrengo adibideak continuation-local-storage npm liburutegia erabiltzen du eskaerak isolatzeko + +const { createNamespace } = require("continuation-local-storage"); +const session = createNamespace("my session"); + +router.get("/:id", (req, res, next) => { + session.set("transactionId", "some unique GUID"); + someService.getById(req.params.id); + logger.info("Starting now to get something by id"); +}); + +// Orain, beste edozein zerbitzu edo osagarrik kotextuko datuak eskura ditzake +class someService { + getById(id) { + logger.info("Starting to get something by id"); + // beste logika hemen dator + } +} + +// Erregistroak transakzio identifikazioa gehi diezaieke sarrera bakoitzari, horrela eskaera bereko sarrerek balio bera edukiko dute +class logger { + info(message) { + console.log(`${message} ${session.get("transactionId")}`); + } +} +``` diff --git a/sections/production/assigntransactionid.french.md b/sections/production/assigntransactionid.french.md new file mode 100644 index 000000000..49339bed4 --- /dev/null +++ b/sections/production/assigntransactionid.french.md @@ -0,0 +1,198 @@ +# Attribuez un ‘TransactionId’ à chaque relevé du journal + +

+ +### Un paragraphe d'explication + +Un journal typique est un registre des entrées de tous les composants et requêtes. Lorsqu'une ligne ou une erreur suspecte est détectée, il devient difficile de faire correspondre d'autres lignes appartenant au même flux spécifique (par exemple, l'utilisateur "John" a essayé d'acheter quelque chose). Cela devient encore plus critique et difficile dans un environnement de micro-services lorsqu'une requête/transaction peut concerner plusieurs ordinateurs. Il convient de remédier à ce problème en attribuant une valeur d'identification de transaction unique à toutes les entrées d'une même requête, de sorte qu'en détectant une ligne, on puisse copier l'identifiant et rechercher toutes les lignes qui ont un identifiant de transaction similaire. Toutefois, la réalisation de cette opération dans Node n'est pas simple, car un seul processus est utilisé pour toutes les requêtes - envisagez d'utiliser une bibliothèque qui peut regrouper les données au niveau de la requête - voir l'exemple de code suivant. Lorsque vous appelez d'autres micro-services, transmettez l'identifiant de la transaction en utilisant une entête HTTP comme "x-transaction-id" pour conserver le même contexte. + +
+ +### Exemple de code : partage de TransactionId entre les fonctions de requête et entre les services à l'aide de [async-local-storage](https://nodejs.org/api/async_hooks.html#async_hooks_class_asynclocalstorage) + + **Qu'est ce que async-local-storage ?** Vous pouvez le considérer comme l'alternative de Node pour le stockage local des threads. + Il s'agit essentiellement d'un stockage pour les flux asynchrones dans Node. Vous pouvez en savoir plus [ici](https://www.freecodecamp.org/news/async-local-storage-nodejs/). + +```javascript +const express = require('express'); +const { AsyncLocalStorage } = require('async_hooks'); +const uuid = require('uuid/v4'); + +const asyncLocalStorage = new AsyncLocalStorage(); + +// Définit le TransactionId des requêtes entrantes +const transactionIdMiddleware = (req, res, next) => { + // Le premier argument de asyncLocalStorage.run est l'initialisation de l'état du stockage, le second argument est la fonction qui a accès à ce stockage + asyncLocalStorage.run(new Map(), () => { + // Essaye d'extraire le TransactionId de l'entête de la requête, ou en génére un nouveau s'il n'existe pas + const transactionId = req.headers['transactionId'] || uuid(); + + // Définit le TransactionId à l'intérieur du stockage + asyncLocalStorage.getStore().set('transactionId', transactionId); + + // En appelant next() dans la fonction, nous nous assurons que tous les autres middlewares fonctionnent dans le même contexte AsyncLocalStorage + next(); + }); +}; + +const app = express(); +app.use(transactionIdMiddleware); + +// Définit le TransactionId des requêtes sortantes +app.get('/', (req, res) => { + // Une fois que TransactionId a été initialisé dans le middleware, il est accessible à tout moment pour le flux de requêtes. + const transactionId = asyncLocalStorage.getStore().get('transactionId'); + + try { + // Ajoute TransactionId comme entête afin de le passer au service suivant + const response = await axios.get('https://externalService.com/api/getAllUsers', headers: { + 'x-transaction-id': transactionId + }); + } catch (err) { + // L'erreur est transmise au middleware, et il n'est pas nécessaire d'envoyer le TransactionId + next(err); + } + + logger.info('externalService a été appelé avec succès avec l\'entête TransactionId'); + + res.send('OK'); +}); + +// Un middleware de gestion des erreurs appelle le journal +app.use(async (err, req, res, next) => { + await logger.error(err); +}); + +// Le journal peut désormais ajouter le TransactionId à chaque entrée, de sorte que les entrées d'une même requête aient la même valeur +class logger { + error(err) { + console.error(`${err} ${asyncLocalStorage.getStore().get('transactionId')}`); + } + + info(message) { + console.log(`${message} ${asyncLocalStorage.getStore().get('transactionId')}`); + } +} +``` +
+ +
+Exemple de code : utilisation d'une bibliothèque pour simplifier la syntaxe + +Partage du TransactionId entre les fonctions de requête actuelles en utilisant [cls-rtracer](https://www.npmjs.com/package/cls-rtracer) (une bibliothèque basée sur async-local-storage, implémentée pour les middlewares Express & Koa et les plugins Fastify & Hapi) + +```javascript +const express = require('express'); +const rTracer = require('cls-rtracer'); + +const app = express(); + +app.use(rTracer.expressMiddleware()); + +app.get('/getUserData/{id}', async (req, res, next) => { + try { + const user = await usersRepo.find(req.params.id); + + // Le TransactionId est accessible de l'intérieur du journal, il n'est pas nécessaire de l'envoyer + logger.info(`les données de l'utilisateur ${user.id} ont été récupérées avec succès`); + + res.json(user); + } catch (err) { + // L'erreur est transmise au middleware + next(err); + } +}) + +// Un middleware de gestion des erreurs appelle le journal +app.use(async (err, req, res, next) => { + await logger.error(err); +}); + +// Le journal peut désormais ajouter le TransactionId à chaque entrée, de sorte que les entrées d'une même requête aient la même valeur +class logger { + error(err) { + console.error(`${err} ${rTracer.id()}`); + } + + info(message) { + console.log(`${message} ${rTracer.id()}`); + } +} +``` +
+ +Partage le TransactionId entre les micro services + +```javascript +// cls-tracer a la capacité de stocker le TransactionId sur les entêtes des requêtes sortantes de votre service, et d'extraire le TransactionId des entêtes des requêtes entrantes, en remplaçant simplement la configuration par défaut du middleware +app.use(rTracer.expressMiddleware({ + // Ajoute le TransactionId à l'entête + echoHeader: true, + // Respecte le TransactionId de l'entête + useHeader: true, + // Nom de l'entête TransactionId + headerName: 'x-transaction-id' +})); + +const axios = require('axios'); + +// Maintenant, le service extérieur obtiendra automatiquement le TransactionId actuel comme entête +const response = await axios.get('https://externalService.com/api/getAllUsers'); +``` +
+
+ +**REMARQUE : l'utilisation de async-local-storage est soumise à deux restrictions :** +1. Il nécessite Node v.14. +2. Il est basé sur une construction de niveau inférieur dans Node appelé async_hooks qui est encore expérimental, donc vous pouvez craindre des problèmes de performance. Même s'ils existent, ils sont très négligeables, mais vous devriez faire vos propres choix. + +
+ +
+Exemple de code - configuration Express typique sans dépendance de async-local-storage + +```javascript +// à la réception d'une nouvelle requête, commencez un nouveau contexte isolé et définissez un identifiant de transaction. L'exemple suivant utilise la bibliothèque npm continuation-local-storage pour isoler les requêtes + +const { createNamespace } = require('continuation-local-storage'); +const session = createNamespace('my session'); + +router.get('/:id', (req, res, next) => { + session.set('transactionId', 'un GUID unique'); + someService.getById(req.params.id); + logger.info('Début de l\'identification'); +}); + +// Désormais, tout autre service ou composant peut avoir accès aux données contextuelles par requête +class someService { + getById(id) { + logger.info('Début de l\'identification'); + // une autre logique vient ici + } +} + +// Le journal peut désormais ajouter l'identifiant de la transaction à chaque entrée, de sorte que les entrées d'une même requête aient la même valeur +class logger { + info (message) { + console.log(`${message} ${session.get('transactionId')}`); + } +} +``` +
+ +

+ +### Bon : Journaux avec un TransactionId attribué - peut être utilisé comme filtre pour ne voir qu'un seul flux +![alt text](https://i.ibb.co/YjJwgbN/logs-with-transaction-id.jpg "Journaux avec transaction id") +

+ +### Mauvais : journaux sans TransactionId - pas de possibilité d'utiliser un filtre et de ne voir qu'un seul flux, vous devez comprendre par vous-même quels journaux sont pertinents entre tous les « bruits » environnants +![alt text](https://i.ibb.co/PFgVNfn/logs-withtout-transaction-id.jpg "Journaux avec transaction id") + +

+ +### Citation de blog : « La notion d'ID de corrélation est simple. C'est une valeur qui est commune à toutes les requêtes, messages et réponses dans une transaction donnée. Avec cette simplification, vous obtenez beaucoup de pouvoir ». + +Extrait de [rapid7](https://blog.rapid7.com/2016/12/23/the-value-of-correlation-ids/) + +> Dans le passé, lorsque le comportement transactionnel se déroulait dans un seul domaine, dans le cadre de procédures par étapes, le suivi du comportement des requêtes et des réponses était une tâche simple. Cependant, aujourd'hui, une requête vers un domaine particulier peut impliquer une myriade de requêtes asynchrones ultérieures du domaine de départ vers d'autres domaines. Par exemple, vous envoyez une requête à Expedia, mais en coulisse, Expedia transmet votre requête sous forme de message à un gestionnaire de messages. Ce message est ensuite consommé par un hôtel, une compagnie aérienne et une agence de location de voitures qui répondent également de manière asynchrone. La question se pose donc, alors que votre seule requête est transmise à une multitude de consommateurs en cours de traitement, comment pouvons-nous suivre la transaction ? La réponse est : utiliser un identifiant de corrélation. \ No newline at end of file diff --git a/sections/production/bestateless.basque.md b/sections/production/bestateless.basque.md new file mode 100644 index 000000000..7144118ab --- /dev/null +++ b/sections/production/bestateless.basque.md @@ -0,0 +1,45 @@ +# Izan aberrigabea, hil zure zerbitzariak ia egunero + +

+ +### Azalpena + +Inoiz aurkitu duzu produkzio arazo larri bat, zerbitzari batek ezarpen edo datu batzuk falta zituela, adibidez? Baiezkotan, seguruenik, inplementazioaren parte ez den tokiko aktiboekiko menpekotasun ezbeharrezkoren batengatik izango zen. Produktu arrakastatsu askok Fenix hegaztiak balira bezala tratatzen dituzte zerbitzariak: behin eta berriro jaio eta hiltzen dira, inolako kalterik gabe. Beste modu batera esanda, zure kodea denbora batez exekutatzen duen hardwarea besterik ez da zerbitzaria, eta ondoren ordezkatua izan ohi da. Antolaketa horrek + +- eskalatzea ahalbidetzen du zerbitzariak dinamikoki gehituz eta kenduz albo efekturik gabe. +- mantentze lanak errazten ditu askatzen baikaitu zerbitzari bakoitza ebaluatzetik. + +

+ +### Anti ereduaren kode adibideak + +```javascript +// Akats arrunta 1: kargatutako fitxategiak zerbitzari batean era lokalean gordetzea +const multer = require("multer"); // express middlewarea fitxategien kargak kudeatzeko +const upload = multer({ dest: "uploads/" }); + +app.post("/photos/upload", upload.array("photos", 12), (req, res, next) => {}); + +// Akats arrunta 2: autentikazio sesioak fitxategi lokal batean edota memorian gordetzea +const FileStore = require("session-file-store")(session); +app.use( + session({ + store: new FileStore(options), + secret: "keyboard cat", + }) +); + +// Akats arrunta 3: objektu globalean informazioa gordetzea +Global.someCacheLike.result = { somedata }; +``` + +

+ +### Beste blogari batzuek diotena + +[Martin Fowler](https://martinfowler.com/bliki/PhoenixServer.html)en bloga: + +> ...Egun batean eragiketetarako ziurtagiri zerbitzua martxan jartzeko fantasia izan nuen. Zertan zetzan ebaluazioa baina? Lankide bat eta biok korporazioko datu zentrora joan eta produkzio zerbitzari kritikoetan hasi behar genuen lanean beisbol makila, motozerra bat eta ur pistola bana esketan genuela. Eragiketen talde horrek aplikazio guztiak berriro martxan jartzeko zenbat denbora behar zuen, horixe zen ebaluatu beharrekoa. Alimaleko fantasia inozoa dirudien arren, badago jakinduria ttantta bat horretan. +> Beisbol makilak erabiltzeari uko egin beharko bazenio ere, egokia litzateke zure zerbitzariak aldian behin erreko bazenitu. Zerbitzari batek fenix bat bezalakoa izan beharko luke, aldizka errautsetatik berpizten dena... + +

diff --git a/sections/production/bestateless.french.md b/sections/production/bestateless.french.md new file mode 100644 index 000000000..7f114fa44 --- /dev/null +++ b/sections/production/bestateless.french.md @@ -0,0 +1,42 @@ +# Soyez sans état, tuez vos serveurs presque tous les jours + +

+ +### Un paragraphe d'explication + +Avez-vous déjà rencontré un grave problème en production où il manquait un élément de configuration ou une donnée sur un serveur ? Cela est probablement dû à une dépendance inutile avec une ressource locale qui ne fait pas partie du déploiement. De nombreux produits à succès traitent les serveurs comme un oiseau phénix - il meurt et renaît périodiquement sans aucun dommage. En d'autres termes, un serveur n'est qu'une pièce de matériel qui exécute votre code pendant un certain temps et qui est ensuite remplacé. +Cette approche + +- permet une mise à l'échelle par l'ajout et la suppression dynamiques de serveurs sans aucun effet secondaire. +- simplifie la maintenance car elle libère notre esprit de l'évaluation de l'état de chaque serveur. + +

+ +### Exemple de code incorrect + +```javascript +// Erreur typique 1 : enregistrement des fichiers téléchargés localement sur un serveur +const multer = require('multer'); // un middleware express pour gérer les téléchargements en plusieurs parties +const upload = multer({ dest: 'uploads/' }); + +app.post('/photos/upload', upload.array('photos', 12), (req, res, next) => {}); + +// Erreur typique 2 : stockage des sessions d'authentification (passeport) dans un fichier ou une mémoire locale +const FileStore = require('session-file-store')(session); +app.use(session({ + store: new FileStore(options), + secret: 'keyboard cat' +})); + +// Erreur typique 3 : stockage d'informations sur l'objet global +Global.someCacheLike.result = { somedata }; +``` + +

+ +### Ce que disent les autres blogueurs + +Extrait du blog de [Martin Fowler](https://martinfowler.com/bliki/PhoenixServer.html) : +> ...Un jour, j'ai eu le délire de lancer un service de certification des exploitations. L'évaluation de la certification consisterait pour un collègue et moi à nous rendre au centre de données de l'entreprise et à nous occuper des serveurs de production critiques avec une batte de base-ball, une tronçonneuse et un pistolet à eau. L'évaluation serait basée sur le temps qu'il faudrait à l'équipe d'exploitation pour remettre toutes les applications en marche. C'est peut-être une idée folle, mais il y a là une pincée de bon sens. Bien que vous deviez renoncer aux battes de base-ball, il est bon de détruire virtuellement vos serveurs à intervalles réguliers. Un serveur doit être comme un phénix, renaissant régulièrement de ses cendres... + +

diff --git a/sections/production/createmaintenanceendpoint.basque.md b/sections/production/createmaintenanceendpoint.basque.md new file mode 100644 index 000000000..1ca7f1556 --- /dev/null +++ b/sections/production/createmaintenanceendpoint.basque.md @@ -0,0 +1,48 @@ +# Sortu mantentze lanen amaiera puntua + +

+ +### Azalpena + +Mantentze lanen amaiera puntua oso HTTP API segurua da, aplikazioaren kodearen parte dena, eta bere helburua da operazioek edo ekoizpen taldeek mantentze funtzionalitatea kontrolatzeko eta erakusteko erabilia izatea. Adibidez, prozesuaren biltegiratzea (memoriaren argazkia) itzul dezake, memoria ihes batzuk dauden ala ez jakinarazi eta REPL komandoak zuzenean exekutatzeko baimena eman dezake. Amaiera hori beharrezkoa da ohiko DevOps tresnek (kontrolagailuak, erregistroak eta abar) ezin dutenean informazio mota zehatz bat bildu edo tresna horiek ez erostea edo ez instalatzea aukeratzen duzunean. Urrezko araua da produkzioa kontrolatzeko eta mantentzeko kanpoko tresna profesionalak erabiltzea, sendoagoak eta zehatzagoak izan ohi dira eta. Hori esanda, litekeena da tresna generikoek atera ezin izatea Noderen edo zure aplikazioren berariazko informaziorik. Adibidez, GC-k ziklo bat burutu duen momentuan memoriaren argazki bat sortu nahi baduzu, npm liburutegi gutxi egongo dira prest lan hori zuretzat egiteko, baina jarraipena egiteko tresna ezagunek funtzionaltasun hori galdu egingo dute. Garrantzitsua da amaiera puntu horren sarbidea mugatzea, administratzaileak soilik sartu ahal izateko, DDOS erasoen jomuga bihur baitaiteke. + +

+ +### Kode adibidea: kodearen bidez pilaketa sorta sortzea + +```javascript +const heapdump = require("heapdump"); + +// Egiaztatu ia eskaera baimendua den +function baimenaDu(req) { + // ... +} + +router.get("/ops/heapdump", (req, res, next) => { + if (!baimenaDu(req)) { + return res.status(403).send("Ez duzu baimenik!"); + } + + logger.info("heapdump-a generatzen"); + + heapdump.writeSnapshot((err, fitxategiarenIzena) => { + console.log( + "heapdump fitxategia prest dago eskariari bidaltzeko", + fitxategiarenIzena + ); + fs.readFile(fitxategiarenIzena, "utf-8", (err, data) => { + res.end(data); + }); + }); +}); +``` + +

+ +### Gomendatutako baliabideak + +[Zure Node.js aplikazioaren ekoizpena prestatzea (diapositibak)](http://naugtur.pl/pres3/node2prod) + +▶ [Zure Node.js aplikazioaren ekoizpena prestatzea (bideoa)](https://www.youtube.com/watch?v=lUsNne-_VIk) + +![Zure Node.js aplikazioaren ekoizpena prestatzea](../../assets/images/createmaintenanceendpoint1.png "Zure Node.js aplikazioaren ekoizpena prestatzea") diff --git a/sections/production/createmaintenanceendpoint.brazilian-portuguese.md b/sections/production/createmaintenanceendpoint.brazilian-portuguese.md index 1b0a15bbf..7f93feef8 100644 --- a/sections/production/createmaintenanceendpoint.brazilian-portuguese.md +++ b/sections/production/createmaintenanceendpoint.brazilian-portuguese.md @@ -42,4 +42,4 @@ router.get('/ops/heapdump', (req, res, next) => { ▶ [Preparando sua aplicação Node.js para produção (Video)](https://www.youtube.com/watch?v=lUsNne-_VIk) -![Preparando sua aplicação Node.js para produção](/assets/images/createmaintenanceendpoint1.png "Preparando sua aplicação Node.js para produção") +![Preparando sua aplicação Node.js para produção](../../assets/images/createmaintenanceendpoint1.png "Preparando sua aplicação Node.js para produção") diff --git a/sections/production/createmaintenanceendpoint.chinese.md b/sections/production/createmaintenanceendpoint.chinese.md index 90f7f84a8..68ce7b5f9 100644 --- a/sections/production/createmaintenanceendpoint.chinese.md +++ b/sections/production/createmaintenanceendpoint.chinese.md @@ -34,4 +34,4 @@ router.get('/ops/headump', (req, res, next) => { ▶ [Getting your Node.js app production ready (Video)](https://www.youtube.com/watch?v=lUsNne-_VIk) -![Getting your Node.js app production ready](/assets/images/createmaintenanceendpoint1.png "Getting your Node.js app production ready") +![Getting your Node.js app production ready](../../assets/images/createmaintenanceendpoint1.png "Getting your Node.js app production ready") diff --git a/sections/production/createmaintenanceendpoint.french.md b/sections/production/createmaintenanceendpoint.french.md new file mode 100644 index 000000000..96bc5b42a --- /dev/null +++ b/sections/production/createmaintenanceendpoint.french.md @@ -0,0 +1,45 @@ +# Créez un « point de terminaison de maintenance » + +

+ +### Un paragraphe d'explication + +Un point de terminaison de maintenance est une API HTTP hautement sécurisée qui fait partie du code de l'application et dont l'objectif est d'être utilisé par l'équipe d'exploitation/production pour surveiller et exposer les fonctionnalités de maintenance. Par exemple, il peut retourner un vidage de mémoire (instantané de la mémoire) du processus, signaler s'il y a des fuites de mémoire et même permettre d'exécuter directement des commandes REPL. Ce point de terminaison est nécessaire lorsque les outils DevOps classiques (produits de surveillance, journaux, etc.) ne parviennent pas à collecter un certain type d'informations spécifiques ou si vous choisissez de ne pas acheter/installer de tels outils. La règle d'or est d'utiliser des outils professionnels et externes pour le suivi et la maintenance de la production, ceux-ci sont généralement plus robustes et plus précis. Cela dit, il est probable que les outils génériques ne parviennent pas à extraire des informations spécifiques de Node ou de votre application - par exemple, si vous souhaitez générer un instantané de mémoire au moment où le GC (Garbage collection, NdT : [« Ramasse-miettes »](https://fr.wikipedia.org/wiki/Ramasse-miettes_(informatique))) a terminé un cycle - quelques bibliothèques npm se feront un plaisir de vous le faire, mais les outils de surveillance populaires manqueront probablement cette fonctionnalité. Il est important de garder ce point de terminaison privé et accessible uniquement par les administrateurs, car il peut devenir la cible d'une attaque DDOS. + +

+ +### Exemple de code : génération d'un vidage mémoire via du code + +```javascript +const heapdump = require('heapdump'); + +// Vérifie si la requête est autorisée +function isAuthorized(req) { + // ... +} + +router.get('/ops/heapdump', (req, res, next) => { + if (!isAuthorized(req)) { + return res.status(403).send('Vous n\'êtes pas autorisé !'); + } + + logger.info('À propos de la génération du vidage mémoire'); + + heapdump.writeSnapshot((err, filename) => { + console.log('le fichier heapdump est prêt à être envoyé au demandeur', filename); + fs.readFile(filename, 'utf-8', (err, data) => { + res.end(data); + }); + }); +}); +``` + +

+ +### Ressources recommandées + +[Préparez votre application Node.js pour la production (Slides)](http://naugtur.pl/pres3/node2prod) + +▶ [Préparez votre application Node.js pour la production (Vidéo)](https://www.youtube.com/watch?v=lUsNne-_VIk) + +![Préparez votre application Node.js pour la production](../../assets/images/createmaintenanceendpoint1.png "Préparez votre application Node.js pour la production") diff --git a/sections/production/createmaintenanceendpoint.japanese.md b/sections/production/createmaintenanceendpoint.japanese.md index 93b73b0fe..0e54d9874 100644 --- a/sections/production/createmaintenanceendpoint.japanese.md +++ b/sections/production/createmaintenanceendpoint.japanese.md @@ -42,4 +42,4 @@ router.get('/ops/heapdump', (req, res, next) => { ▶ [Node.js アプリの制作準備 (ビデオ)](https://www.youtube.com/watch?v=lUsNne-_VIk) -![Node.js アプリの制作準備](/assets/images/createmaintenanceendpoint1.png "Node.js アプリの制作準備") +![Node.js アプリの制作準備](../../assets/images/createmaintenanceendpoint1.png "Node.js アプリの制作準備") diff --git a/sections/production/createmaintenanceendpoint.korean.md b/sections/production/createmaintenanceendpoint.korean.md index 405ad5bc0..023f9ad80 100644 --- a/sections/production/createmaintenanceendpoint.korean.md +++ b/sections/production/createmaintenanceendpoint.korean.md @@ -42,4 +42,4 @@ router.get('/ops/heapdump', (req, res, next) => { ▶ [Getting your Node.js app production ready (Video)](https://www.youtube.com/watch?v=lUsNne-_VIk) -![Getting your Node.js app production ready](/assets/images/createmaintenanceendpoint1.png "Getting your Node.js app production ready") +![Getting your Node.js app production ready](../../assets/images/createmaintenanceendpoint1.png "Getting your Node.js app production ready") diff --git a/sections/production/createmaintenanceendpoint.md b/sections/production/createmaintenanceendpoint.md index 2db04a8b6..179958705 100644 --- a/sections/production/createmaintenanceendpoint.md +++ b/sections/production/createmaintenanceendpoint.md @@ -42,4 +42,4 @@ router.get('/ops/heapdump', (req, res, next) => { ▶ [Getting your Node.js app production ready (Video)](https://www.youtube.com/watch?v=lUsNne-_VIk) -![Getting your Node.js app production ready](/assets/images/createmaintenanceendpoint1.png "Getting your Node.js app production ready") +![Getting your Node.js app production ready](../../assets/images/createmaintenanceendpoint1.png "Getting your Node.js app production ready") diff --git a/sections/production/createmaintenanceendpoint.polish.md b/sections/production/createmaintenanceendpoint.polish.md index 5ba559493..b2e643d0d 100644 --- a/sections/production/createmaintenanceendpoint.polish.md +++ b/sections/production/createmaintenanceendpoint.polish.md @@ -42,4 +42,4 @@ router.get('/ops/heapdump', (req, res, next) => { ▶ [Getting your Node.js app production ready (Video)](https://www.youtube.com/watch?v=lUsNne-_VIk) -![Getting your Node.js app production ready](/assets/images/createmaintenanceendpoint1.png "Getting your Node.js app production ready") +![Getting your Node.js app production ready](../../assets/images/createmaintenanceendpoint1.png "Getting your Node.js app production ready") diff --git a/sections/production/createmaintenanceendpoint.russian.md b/sections/production/createmaintenanceendpoint.russian.md index b2dd7a66f..20754e555 100644 --- a/sections/production/createmaintenanceendpoint.russian.md +++ b/sections/production/createmaintenanceendpoint.russian.md @@ -42,4 +42,4 @@ router.get('/ops/heapdump', (req, res, next) => { ▶ [Подготовка вашего приложения Node.js к производственому запуску (видео)](https://www.youtube.com/watch?v=lUsNne-_VIk) -![Подготовка вашего приложения Node.js к производственому запуску](/assets/images/createmaintenanceendpoint1.png "Подготовка вашего приложения Node.js к производственому запуску") +![Подготовка вашего приложения Node.js к производственому запуску](../../assets/images/createmaintenanceendpoint1.png "Подготовка вашего приложения Node.js к производственому запуску") diff --git a/sections/production/delegatetoproxy.basque.md b/sections/production/delegatetoproxy.basque.md new file mode 100644 index 000000000..e182d6be9 --- /dev/null +++ b/sections/production/delegatetoproxy.basque.md @@ -0,0 +1,52 @@ +# Delegatu ahal den guztia (adibidez, eduki estatikoa, gzip) alderantzizko proxy batean + +

+ +### Azalpena + +Oso tentagarria da cargo-cult Express-a kargatzea, eta haren middleware eskaintza aberatsa erabiltzea sarearekin zerikusia duten zereginetarako, hala nola, fitxategi estatikoak zerbitzatzea, gzip kodetzea, eskaerak murriztea, SSL amaierak, etab. Hori denbora alperrik galtzea da, zeren eta, azpiprozesu bakarrekoa izanik, PUZa denbora luzez edukiko baitu lanean (Gogoan izan Noderen exekuzio eredua optimizatuta dagoela zeregin laburretarako edo E / S zeregin asinkronizatuetarako). Egokiagoa da sareko zereginetan erabili ohi den tresnaren bat erabiltzea. Ezagunenak nginx eta HAproxy dira, hodeiko saltzaile handienek Node.jsren prozesuetan sarrerako karga arintzeko ere erabiltzen dituztenak. + +

+ +### Nginx konfigurazio adibidea: erabili nginx zerbitzariaren erantzunak konprimatzeko + +```nginx +# konfiguratu gzip konprimatzea +gzip on; +gzip_comp_level 6; +gzip_vary on; + +# konfiguratu upstream +upstream nireAplikazioa { + server 127.0.0.1:3000; + server 127.0.0.1:3001; + keepalive 64; +} + +# web zebitzaria zehaztu +server { + # konfiguratu zerbitzaria ssl-arekin eta errore orriekin + listen 80; + listen 443 ssl; + ssl_certificate /some/location/sillyfacesociety.com.bundle.crt; + error_page 502 /errors/502.html; + + # eduki estatikoa kudeatu + location ~ ^/(images/|img/|javascript/|js/|css/|stylesheets/|flash/|media/|static/|robots.txt|humans.txt|favicon.ico) { + root /usr/local/silly_face_society/node/public; + access_log off; + expires max; +} +``` + +

+ +### Beste blogari batzuek diotena + +- [Mubaloo](http://mubaloo.com/best-practices-deploying-node-js-applications) bloga + +> …Oso erraza da tranpa honetan erortzea - ​​Express bezalako pakete bat ikusten duzu eta pentsatzen duzu "Ikaragarria! Has gaitezen ". Ekin diozu kodetzeari eta nahi duzuna egiten duen aplikazioa duzu. Hori bikaina da eta, egia esan, ia-ia irabazia duzu borroka . Hala ere, gerra galduko duzu zure aplikazioa zerbitzari batera igotzen baduzu eta zure HTTP atakan entzuten baduzu. Izan ere, oso gauza erabakigarria ahaztu duzu: Node ez da web zerbitzaria. **Zure aplikaziora trafiko bolumen handia iristen hasi bezain laster, ohartuko zara gauzak gaizki hasten direla: konexioak erori egin dira, aktiboak zerbitzurik gabe daude edo, okerrenean, zure zerbitzariak huts egin du. Izan ere, egiten ari zarena da Noderi eskatzea bere gain har ditzala web zerbitzari zaildu batek oso ondo egiten dituen gauza korapilatsu guztiak. Zergatik asmatu gurpila?** > **Node eskaera bakarrerako da, irudi bakarrerako. Zure aplikazioak datu basea irakurtzea edo logika korapilatsua kudeatzea bezalako gauza garrantzitsuetarako erabil lezakeen memoria alperrik xahutzen ari da ez dagokion zereginetan. Zergatik alboratu zure eskaera erosotasunagatik?** + +- [Argteam](http://blog.argteam.com/coding/hardening-node-js-for-production-part-2-using-nginx-to-avoid-node-js-load) bloga + +> Express.jsk middleware konektatuen bidez fitxategi estatikoen kudeaketa integratua egiten duen arren, ez zenuke inoiz erabili beharko. **Nginx-ek askoz hobeto kudea ditzake fitxategi estatikoak eta ekidin dezake eduki ez dinamikoko eskaerek blokeatzea gure node prozesuak**… diff --git a/sections/production/delegatetoproxy.french.md b/sections/production/delegatetoproxy.french.md new file mode 100644 index 000000000..423ed8238 --- /dev/null +++ b/sections/production/delegatetoproxy.french.md @@ -0,0 +1,51 @@ +# Déléguez tout ce qui est possible (par exemple gzip, SSL) à un proxy inverse + +

+ +### Un paragraphe d'explication + +Il est très tentant de faire appel à cargo-cult d'Express et d'utiliser son riche middleware pour les tâches liées au réseau, comme le service de fichiers statiques, l'encodage gzip, les requêtes de restriction, la terminaison SSL, etc. C'est une perte de performance due à son modèle de processus unique qui gardera le CPU occupé pendant de longues périodes (Rappelez-vous, le modèle d'exécution de Node est optimisé pour des tâches courtes ou des tâches liées à des E/S asynchrones). Une meilleure approche est d'utiliser un outil qui maîtrise les tâches réseau - les plus populaires sont nginx et HAproxy qui sont également utilisés par les plus grands vendeurs du cloud pour alléger la charge entrante sur les processus node.js. + +

+ +### Exemple de configuration Nginx - Utilisation de nginx pour compresser les réponses du serveur + +```nginx +# configure la compression gzip +gzip on; +gzip_comp_level 6; +gzip_vary on; + +# configure upstream +upstream myApplication { + server 127.0.0.1:3000; + server 127.0.0.1:3001; + keepalive 64; +} + +# définition du serveur web +server { + # configure le serveur avec ssl et des pages d'erreur + listen 80; + listen 443 ssl; + ssl_certificate /some/location/sillyfacesociety.com.bundle.crt; + error_page 502 /errors/502.html; + + # gestion du contenu statique + location ~ ^/(images/|img/|javascript/|js/|css/|stylesheets/|flash/|media/|static/|robots.txt|humans.txt|favicon.ico) { + root /usr/local/silly_face_society/node/public; + access_log off; + expires max; +} +``` + +

+ +### Ce que disent les autres blogueurs + +* Extrait du blog de [Mubaloo](http://mubaloo.com/best-practices-deploying-node-js-applications): +> …Il est très facile de tomber dans ce piège - Vous voyez un paquet comme Express et pensez « Génial ! Commençons » - vous codez et vous avez une application qui fait ce que vous voulez. C'est excellent et, pour être honnête, vous avez gagné beaucoup de bataille. Cependant, vous perdrez la guerre si vous téléchargez votre application sur un serveur et que vous la faites écouter sur votre port HTTP parce que vous avez oublié une chose très cruciale : Node n'est pas un serveur Web. **Aussitôt qu'un volume de trafic quelconque commence à toucher votre application, vous remarquerez que les choses commencent à mal tourner : les connexions sont interrompues, les ressources cessent d'être servis ou, au pire, votre serveur se plante. Ce que vous faites est d'essayer de faire en sorte que Node s'occupe de toutes les choses compliquées qu'un serveur web éprouvé fait très bien. Pourquoi réinventer la roue ?** +> **C'est juste pour une requête ou une image et en gardant à l'esprit que cette mémoire peut être utilisée par votre application pour des choses plus importantes comme la lecture d'une base de données ou la manipulation d'une logique compliquée, pourquoi paralyser votre application pour des raisons de commodité ?** + +* Extrait du blog de [Argteam](http://blog.argteam.com/coding/hardening-node-js-for-production-part-2-using-nginx-to-avoid-node-js-load) : +> Bien qu'express.js ait une gestion intégrée des fichiers statiques via un middleware de connexion, vous ne devez jamais l'utiliser. **Nginx peut faire un bien meilleur travail de gestion des fichiers statiques et peut empêcher les requêtes de contenu non dynamique de saturer nos processus de Node**… diff --git a/sections/production/detectvulnerabilities.basque.md b/sections/production/detectvulnerabilities.basque.md new file mode 100644 index 000000000..c19b298df --- /dev/null +++ b/sections/production/detectvulnerabilities.basque.md @@ -0,0 +1,19 @@ +# Erabili menpekotasunak automatikoki atzematen dituzten tresnak + +

+ +### Azalpena + +Noderen aplikazio modernoek hamarnaka eta batzuetan ehunaka menpekotasun dituzte. Erabiltzen dituzun menpekotasunen batek segurtasun ahultasun ezaguna badu, zure aplikazioa ere ahula da. +Tresna hauek automatikoki egiaztatzen dituzte zure menpekotasunetako segurtasun ahultasunak: + +- [npm audit](https://docs.npmjs.com/cli/audit) - npm auditoria +- [snyk](https://snyk.io/) - etengabe bilatu eta konpondu ahultasunak zure menpekotasunetan + +

+ +### Beste blogari batzuek diotena + +[StrongLoop](https://strongloop.com/strongblog/best-practices-for-express-in-production-part-one-security/) bloga: + +> ...Zure aplikazioaren menpekotasunak kudeatzeko erabiltzea indartsua eta erosoa da. Erabiltzen dituzun paketeek zure aplikazioan ere eragina izan dezaketen segurtasun ahultasun larriak izan ditzakete. Zure aplikazioaren segurtasuna zure menpekotasunen "esteka ahulena" bezain sendoa da. Zorionez, bi tresna lagungarri daude erabiltzen dituzun hirugarren paketeak ziurtatzeko erabil ditzakezunak: nsp eta requireSafe. Bi tresna horiek gauza bera egiten dute neurri handi batean. Beraz, biak erabiltzea gehiegizkoa izan badaiteke ere, "hobe seguru jokatzea, damutzea baino". Hitz horiek, segurtasunari dagokionez, zuzenak eta egokiak dira... diff --git a/sections/production/detectvulnerabilities.french.md b/sections/production/detectvulnerabilities.french.md new file mode 100644 index 000000000..5768a042d --- /dev/null +++ b/sections/production/detectvulnerabilities.french.md @@ -0,0 +1,20 @@ +# Utilisez des outils qui détectent automatiquement les dépendances vulnérables + +

+ +### Un paragraphe d'explication + +Les applications modernes de Node ont des dizaines et parfois des centaines de dépendances. Si l'une des dépendances que +vous utilisez présente une faille de sécurité connue, votre application est également vulnérable. +Les outils suivants vérifient automatiquement les vulnérabilités de sécurité connues dans vos dépendances : + +- [npm audit](https://docs.npmjs.com/cli/audit) - audit de npm +- [snyk](https://snyk.io/) - Trouve et corrige continuellement les vulnérabilités de vos dépendances + +

+ +### Ce que disent les autres blogueurs + +Extrait du blog de [StrongLoop](https://strongloop.com/strongblog/best-practices-for-express-in-production-part-one-security/) : + +> ...L'utilisation pour gérer les dépendances de votre application est puissante et pratique. Mais les paquets que vous utilisez peuvent contenir des vulnérabilités de sécurité critiques qui pourraient également affecter votre application. La sécurité de votre application est uniquement assurée par le « maillon le plus faible » de vos dépendances. Heureusement, il existe deux outils utiles pour garantir la sécurité des paquets tiers que vous utilisez : nsp et requireSafe. Ces deux outils font en grande partie la même chose, donc les utiliser tous les deux peut être excessif, mais « mieux vaut prévenir que guérir » sont des mots à respecter en matière de sécurité... diff --git a/sections/production/frontendout.basque.md b/sections/production/frontendout.basque.md new file mode 100644 index 000000000..6e3a69a83 --- /dev/null +++ b/sections/production/frontendout.basque.md @@ -0,0 +1,47 @@ +# Atera frontend modulu eko aktiboak Nodetik + +

+ +### Azalpena + +Web aplikazio klasiko batean backend-ak elementu grafikoak helarazten dizkio +nabigatzaileari. Noderen munduan oso ohikoa da Express middleware estatikoa erabiltzea bezeroaren fitxategi estatikoak optimizatzeko. BAINA Node ez da web aplikazio tipikoa, fitxategi asko aldi berean hornitzeko optimizatuta ez dagoen hari bakarra erabiltzen baitu. Horren ordez, aztertu ez ote den hobe erabiltzea alderantzizko proxy bat (adibidez, nginx, HAProxy), hodeiko biltegiren bat edo CDN (adibidez, AWS S3, Azure Blob Storage, etab.), zeregin horretarako optimizazio asko erabiltzen dituen eta errendimendu askoz hobea lortzen duena. Adibidez, nginx bezalako middleware espezializatuak zuzeneko lotuneak dauzka fitxategi sistemaren eta sareko txartelaren artean, eta prozesu anitzeko antolaketa erabiltzen du eskaera anitzen arteko esku hartzea minimizatzeko. + +Hauetako bat izan daiteke zure irtenbide egokiena: + +1. Alderantzizko proxy bat erabiltzea: zure fitxategi estatikoak Node aplikazioaren ondoan kokatuko dira, eta Node aplikazioaren aurrean jartzen den proxy batek (adibidez, nginx) bideratuko ditu fitxategien karpeta estatikoari egindako eskaerak. + Horrela, zure Node aplikazioa arduratzen da fitxategi estatikoak hedatzeaz, baina ez zerbitzatzeaz. Zure frontden/interfazeko lankideari asko gustatuko zaio antolaketa hau, frontden/interfazeko eskaerak galarazten baititu. + +2. Hodeian biltegiratzea: zure fitxategi estatikoak EZ dira zure Node aplikazioaren edukiaren zati izango, eginkizun horretarako sortu diren AWS S3, Azure BlobStorage edo antzeko beste zerbitzu batzuetara igoko dira eta. Antolaketa hau erabiliz, zure Node aplikazioak ez du fitxategi estatikoak hedatzeko ardurarik izango, ezta horiek zerbitzatzeko ere; beraz, Node eta Frontenda/interfazea erabat banatuta egongo dira, edonola ere talde desberdinek kudeatuta baitaude. + +

+ +### Ezarpen adibidea: nginxen ohiko ezarpena fitxategi estatikoak zerbitzatzeko + +```nginx +# konfiguratu gzip konprimatzea +gzip on; +keepalive 64; + +# web zerbitzaria zehaztu +server { +listen 80; +listen 443 ssl; + +# eduki estatikoa kudeatu +location ~ ^/(images/|img/|javascript/|js/|css/|stylesheets/|flash/|media/|static/|robots.txt|humans.txt|favicon.ico) { +root /usr/local/silly_face_society/node/public; +access_log off; +expires max; +} +``` + +

+ +### Beste blogari batzuek diotena + +[StrongLoop](https://strongloop.com/strongblog/best-practices-for-express-in-production-part-two-performance-and-reliability/) bloga: + +> …Garapenean, [res.sendFile()](http://expressjs.com/4x/api.html#res.sendFile) erabil dezakezu fitxategi estatikoak hornitzeko. Baina ez egin hori ekoizpenean, funtzio horrek fitxategi sistematik irakurtzen baitu fitxategi eskaera bakoitza; beraz, denbora asko beharko erantzuteko, eta aplikazioaren errendimendu orokorrari eragingo dio. Kontuan izan res.sendFile () ez dela sendfile sistemaren deiarekin inplementatzen, eta hori askoz ere eraginkorragoa izango litzateke. Horren ordez, erabili zerbitzu estatikoa duen middlewareren bat (edo baliokidea den zerbait), hau da, Express aplikazioetarako fitxategiak hornitzeko optimizatuta dagoen tresnaren bat. Aukera hobea da alderantzizko proxy bat erabiltzea fitxategi estatikoak hornitzeko. Informazio gehiago nahi baduzu, ikusi “Erabili alderantzizko proxy bat”… + +

diff --git a/sections/production/frontendout.french.md b/sections/production/frontendout.french.md new file mode 100644 index 000000000..8de2da260 --- /dev/null +++ b/sections/production/frontendout.french.md @@ -0,0 +1,45 @@ +# Retirez vos ressources frontend de Node + +

+ +### Un paragraphe d'explication + +Dans une application web classique, le backend fournit le frontend/les graphiques au navigateur. Une approche très courante dans le monde de Node consiste à utiliser le middleware statique Express pour transmettre les fichiers statiques au client. MAIS - Node n'est pas une application web classique car il utilise un seul processus qui n'est pas optimisé pour servir plusieurs fichiers à la fois. Il faut plutôt envisager d'utiliser un proxy inverse (par exemple nginx, HAProxy), un stockage dans le cloud ou un CDN (par exemple, AWS S3, Azure Blob Storage, etc.) qui utilisent de nombreuses optimisations pour cette tâche et obtiennent un bien meilleur débit. Par exemple, un middleware spécialisé comme nginx comporte des hooks directs entre le système de fichiers et la carte réseau et utilise une approche multi-processus pour minimiser l'intervention parmi les multiples requêtes. + +Votre solution optimale pourrait prendre l'une des formes suivantes : + +1. En utilisant un proxy inverse - vos fichiers statiques seront situés juste à côté de votre application Node, seules les requêtes vers le dossier des fichiers statiques seront servies par un proxy qui se trouve devant votre application Node comme nginx. En utilisant cette approche, votre application Node est responsable du déploiement des fichiers statiques mais pas de leur distribution. Le responsable de votre application frontend aimera cette approche car elle permet d'éviter les requêtes d'origine croisée depuis le frontend. + +2. Stockage dans le cloud - vos fichiers statiques NE feront PAS partie du contenu de votre application Node, ils seront téléchargés vers des services comme AWS S3, Azure BlobStorage, ou d'autres services similaires qui sont conçus pour cette mission. En utilisant cette approche, votre application Node n'est pas responsable du déploiement des fichiers statiques ni de leur utilisation, d'où un dissociation complète entre Node et le Frontend qui est de toute façon géré par des équipes différentes. + +

+ +### Exemple de configuration : configuration typique de nginx pour servir des fichiers statiques + +```nginx +# configuration de la compression gzip +gzip on; +keepalive 64; + +# définition du serveur web +server { +listen 80; +listen 443 ssl; + +# gestion du contenu statique +location ~ ^/(images/|img/|javascript/|js/|css/|stylesheets/|flash/|media/|static/|robots.txt|humans.txt|favicon.ico) { +root /usr/local/silly_face_society/node/public; +access_log off; +expires max; +} +``` + +

+ +### Ce que disent les autres blogueurs + +Extrait du blog de [StrongLoop](https://strongloop.com/strongblog/best-practices-for-express-in-production-part-two-performance-and-reliability/): + +>…En développement, vous pouvez utiliser [res.sendFile()](http://expressjs.com/4x/api.html#res.sendFile) pour fournir des fichiers statiques. Mais ne le faites pas en production, car cette fonction doit lire dans le système de fichiers pour chaque requête de fichier, elle rencontrera donc une latence importante et affectera la performance globale de l'application. Remarquez que res.sendFile() n'est pas implémentée avec l'appel système sendfile, ce qui la rendrait bien plus efficace. Utilisez plutôt un middleware de type serveur statique (ou quelque chose d'équivalent), qui est optimisé pour servir des fichiers pour les applications Express. Une option encore meilleure est d'utiliser un proxy inverse pour servir des fichiers statiques; consultez Utiliser un proxy inverse pour plus d'informations… + +

diff --git a/sections/production/guardprocess.basque.md b/sections/production/guardprocess.basque.md new file mode 100644 index 000000000..3b82b5f34 --- /dev/null +++ b/sections/production/guardprocess.basque.md @@ -0,0 +1,19 @@ +# Babestu eta berrabiarazi zure prozesua huts egitean (tresna egokiak erabiliz) + +

+ +### Azalpena + +Oinarrizko mailan, Node prozesuak babestu eta berrabiarazi behar dira hutsegiteak gertatzen direnean. Hitz gutxitan, aplikazio txikientzat eta edukiontzirik erabiltzen ez dutenentzat, [PM2](https://www.npmjs.com/package/pm2-docker) bezalako tresnak ezin hobeak dira sinpletasuna, berrabiarazteko gaitasunak eta Noderekin integrazio aberatsa ere eskaintzen baitute. Linuxekin ondo moldatzen direnek systemd erabil dezakete eta Node zerbitzu gisa exekutatu. Askoz errazagoa da Docker edo edozein edukiontzi teknologia erabiltzen duten aplikazioen egoera, izan ere, eskuarki klusterrak antolatu eta kudeatzeko tresnak izaten dituzte (adibidez, [AWS ECS](http://docs.aws.amazon.com/AmazonECS/latest/developerguide/Welcome.html), [Kubernetes](https://kubernetes.io/), etab.), edukiontziak inplementatu, kontrolatu eta konpontzen dituztenak. Klusterrak kudeatzeko tresna baliagarri horiek guztiak edukita (edukiontziak berrabiaraztekoak barne), zergatik korapilatu PM2 bezalako beste tresna batzuekin? Ez dago erabateko irtenbiderik eskaintzen duen erantzunik. Badira pisuzko arrazoiak PM2 edukiontzien barruan mantentzeko lehen mailako babesgarri gisa (batez ere bere [pm2-docker](https://www.npmjs.com/package/pm2-docker) bertsioa, berariaz edukiontzientzat prestatua): askoz ere bizkorragoa da prozesua berrabiaraztea, eta Noderen ezaugarri zehatzak eskaintzea, hala nola, kodea markatzea, ostatatzeko edukiontziak hala eskatzen duenean. Beste batzuek beharrezkoak ez diren geruzak ekiditea aukeratu dezakete. Amaitzeko, ez dago guztientzako moduko irtenbiderik, eta garrantzitsuena da zer aukera dauden jakitea. + +

+ +### Beste blogari batzuek diotena + +- [Express Produkzioaren Praktika Onak](https://expressjs.com/en/advanced/best-practice-performance.html): bloga: + +> ... Garapenean, zure aplikazioa komando lerrotik hasi zenuen node server.js edo antzeko zerbait erabiliz. **Baina hori bera ekoizpenean egitea hondamendiaren errezeta da. Aplikazioak huts egiten badu, lineaz kanpo egongo da** berrabiarazi arte. Aplikazioak huts egiten badu berrabiarazten dela ziurtatzeko, erabili prozesu kudeatzailea. Prozesuen kudeatzailea inplementazioa errazten duen, erabilgarritasun handia eskaintzen duen eta aplikazioa exekuzio garaian kudeatzeko aukera ematen duen "edukiontzia" da. + +- Medium blogeko [Noderen klusterrak ulertzea](https://medium.com/@CodeAndBiscuits/understanding-nodejs-clustering-in-docker-land-64ce2306afef#.cssigr5z3) artikulua: + +> ... Oso garrantzitsua da Node.js Clustering Docker-Land ulertzea. “Docker edukiontziak ingurune birtual arinak eta errazak dira, prozesuak ahalik eta gehien sinplifikatzeko diseinatuak. Baliabide propioak kudeatu eta koordinatzen dituzten prozesuak jada ez dira hain baliotsuak. **Gaur egun, ordea, Kubernetes, Mesos eta Cattle bezalako kudeaketa pilek aldarrikatzen dute baliabide horiek guztiak azpiegitura osoan kudeatu behar direla**. "Antolatzaileek" esleitzen dituzte PUZeko eta memoriako baliabideak; eta sareko baliabideak, pilak emandako karga orekatzaileek. diff --git a/sections/production/guardprocess.french.md b/sections/production/guardprocess.french.md new file mode 100644 index 000000000..c508a4d36 --- /dev/null +++ b/sections/production/guardprocess.french.md @@ -0,0 +1,17 @@ +# Protégez et redémarrez votre processus en cas d'échec (en utilisant le bon outil) + +

+ +### Un paragraphe d'explication + +A la base, les processus de Node doivent être protégés et redémarrés en cas de défaillance. Autrement dit, pour les petites applications et celles qui n'utilisent pas de conteneurs - des outils comme [PM2](https://www.npmjs.com/package/pm2-docker) sont parfaits car ils apportent la simplicité, des capacités de redémarrage et également une intégration riche avec Node. D'autres personnes avec de solides compétences Linux peuvent utiliser systemd et exécuter Node en tant que service. Les choses deviennent plus intéressantes pour les applications qui utilisent Docker ou n'importe quelle technologie de conteneur, car ils sont généralement accompagnées d'outils de gestion et d'orchestration de cluster (par exemple [AWS ECS](http://docs.aws.amazon.com/AmazonECS/latest/developerguide/Welcome.html), [Kubernetes](https://kubernetes.io/), etc.) qui déploient, surveillent et réparent les conteneurs. Avec toutes ces fonctionnalités riches de gestion de cluster, y compris le redémarrage des conteneurs, pourquoi jouer avec d'autres outils comme PM2 ? Il n'y a pas de réponse à toute épreuve. Il existe de bonnes raisons de conserver PM2 dans les conteneurs (principalement sa version spécifique aux conteneurs [pm2-docker](https://www.npmjs.com/package/pm2-docker)) comme premier niveau de protection - il est beaucoup plus rapide de redémarrer un processus et de fournir des fonctionnalités spécifiques de Node comme le marquage du code lorsque le conteneur d'hébergement demande de redémarrer correctement. D'autres pourraient choisir d'éviter les couches inutiles. Pour conclure cet article, aucune solution ne conviendra à tous et l'important est de connaître les options. + +

+ +### Ce que disent les autres blogueurs + +* Extrait des [Bonnes pratiques d'Express en production](https://expressjs.com/en/advanced/best-practice-performance.html) : +> ... Lors du développement, vous avez démarré votre application simplement à partir de la ligne de commande avec server.js de Node ou quelque chose de similaire. **Mais faire cela en production est une recette catastrophique. Si l'application se bloque, elle sera hors ligne** jusqu'à ce que vous la redémarriez. Pour vous assurer que votre application redémarre en cas de panne, utilisez un gestionnaire de processus. Un gestionnaire de processus est un « conteneur » pour les applications qui facilite le déploiement, offre une haute disponibilité et vous permet de gérer l'application au moment de l'exécution. + +* Extrait du blog Medium [Comprendre le clustering de Node](https://medium.com/@CodeAndBiscuits/understanding-nodejs-clustering-in-docker-land-64ce2306afef#.cssigr5z3) : +> ... Comprendre le clustering de Node.js dans Docker-Land : « Les conteneurs Docker sont des environnements virtuels légers et rationalisés, conçus pour simplifier les processus au strict minimum. Les processus qui gèrent et coordonnent leurs propres ressources n'ont plus la même valeur. **Au lieu de cela, les couches de gestion comme Kubernetes, Mesos et Cattle ont popularisé le concept selon lequel ces ressources devraient être gérées au niveau de l'infrastructure**. Les ressources CPU et mémoire sont allouées par des « planificateurs » et les ressources réseau sont gérées par des équilibreurs de charge (NdT, « load balancers ») fournis par la couche. diff --git a/sections/production/guardprocess.md b/sections/production/guardprocess.md index 719e85a73..29447cc30 100644 --- a/sections/production/guardprocess.md +++ b/sections/production/guardprocess.md @@ -4,7 +4,7 @@ ### One Paragraph Explainer -At the base level, Node processes must be guarded and restarted upon failures. Simply put, for small apps and those who don’t use containers – tools like [PM2](https://www.npmjs.com/package/pm2-docker) are perfect as they bring simplicity, restarting capabilities and also rich integration with Node. Others with strong Linux skills might use systemd and run Node as a service. Things get more interesting for apps that use Docker or any container technology since those are usually accompanied by cluster management and orchestration tools (e.g. [AWS ECS](http://docs.aws.amazon.com/AmazonECS/latest/developerguide/Welcome.html), [Kubernetes](https://kubernetes.io/), etc) that deploy, monitor and heal containers. Having all those rich cluster management features including container restart, why mess up with other tools like PM2? There’s no bulletproof answer. There are good reasons to keep PM2 within containers (mostly its containers specific version [pm2-docker](https://www.npmjs.com/package/pm2-docker)) as the first guarding tier – it’s much faster to restart a process and provide Node-specific features like flagging to the code when the hosting container asks to gracefully restart. Other might choose to avoid unnecessary layers. To conclude this write-up, no solution suits them all and getting to know the options is the important thing +At the base level, Node processes must be guarded and restarted upon failures. Simply put, for small apps and those who don’t use containers – tools like [PM2](https://www.npmjs.com/package/pm2) are perfect as they bring simplicity, restarting capabilities and also rich integration with Node. Others with strong Linux skills might use systemd and run Node as a service. Things get more interesting for apps that use Docker or any container technology since those are usually accompanied by cluster management and orchestration tools (e.g. [AWS ECS](http://docs.aws.amazon.com/AmazonECS/latest/developerguide/Welcome.html), [Kubernetes](https://kubernetes.io/), etc) that deploy, monitor and heal containers. Having all those rich cluster management features including container restart, why mess up with other tools like PM2? There’s no bulletproof answer. There are good reasons to keep PM2 within containers (mostly its containers specific version [pm2-docker](https://www.npmjs.com/package/pm2-docker)) as the first guarding tier – it’s much faster to restart a process and provide Node-specific features like flagging to the code when the hosting container asks to gracefully restart. Other might choose to avoid unnecessary layers. To conclude this write-up, no solution suits them all and getting to know the options is the important thing

diff --git a/sections/production/installpackageswithnpmci.basque.md b/sections/production/installpackageswithnpmci.basque.md new file mode 100644 index 000000000..7eaf296f4 --- /dev/null +++ b/sections/production/installpackageswithnpmci.basque.md @@ -0,0 +1,35 @@ +# Instalatu npm ci paketeak ekoizpenean + +

+ +### Azalpena + +Zure menpekotasunak blokeatu dituzu [**Blokeatu menpekotasunak**](./lockdependencies.basque.md) jarraituz, baina orain ziurtatu behar duzu pakete bertsio zehatzak erabiltzen direla ekoizpenean. + +Paketeak instalatzeko `npm ci` erabiltzen baduzu, hori eta gehiago lortuko duzu. + +- Zure `package.json` eta `package-lock.json` bat ez badatoz (hala behar lukete) edo blokeo fitxategirik ez baduzu, huts egingo du instalazioak +- `node_modules` karpeta badago, automatikoki kenduko du instalatu aurretik +- Azkarragoa da! [Argitaratutako bloga](https://blog.npmjs.org/post/171556855892/introducing-npm-ci-for-faster-more-reliable)ren arabera, ia bi aldiz azkarragoa + +### Noiz egon daiteke erabilgarri? + +Ziur egon IE inguruneak edo QAk probatuko duzula zure softwarea geroago ekoizpenera bidaliko duzun pakete bertsio berarekin. +Gainera, arrazoiren batengatik norbaitek package.json eskuz aldatzen badu, ez cli komando baten bidez, baizik eta package.json zuzenean editatuz, tarte bat sortzen da package.json eta package-lock.jsonen artean, eta errore bat jaurtitzen da. + +### npmek dioena + +[npm ciren dokumentazio](https://docs.npmjs.com/cli/ci.html)tik hartua + +> Komando hau npm-installen antzekoa da, salbu eta ingurune automatizatuetan erabiltzeko dela, hala nola, proba plataformetan, etengabeko integrazio eta inplementazioetan, edo zure menpekotasunen instalazio garbia egiten ari zarela ziurtatu nahi duzun edozein egoeratan. + +[`ci` komandoaren jaregitea iragartzen duen blogeko mezua](https://blog.npmjs.org/post/171556855892/introducing-npm-ci-for-faster-more-reliable) + +> Komandoak hobekuntza handiak eskaintzen dizkie eraikuntzen errendimenduari eta fidagarritasunari etengabeko integrazio/ inplementazio prozesuetarako, esperientzia koherentea eta azkarra eskainiz CI/CD erabiltzen duten garatzaileei beren lan-fluxuan. + +[npmjs: menpekotasunak versus garatze-menpekotasunak (npmjs: dependencies and devDepencies)](https://docs.npmjs.com/specifying-dependencies-and-devdependencies-in-a-package-json-file) + +> "dependencies": zure aplikazioak ekoizpenean eskatzen dituen paketeak. +> "devDependencies": tokiko garapenerako eta probetarako soilik behar diren paketeak. + +

diff --git a/sections/production/installpackageswithnpmci.french.md b/sections/production/installpackageswithnpmci.french.md new file mode 100644 index 000000000..6b0a63f55 --- /dev/null +++ b/sections/production/installpackageswithnpmci.french.md @@ -0,0 +1,30 @@ +# Installez vos paquets avec npm ci en production + +

+ +### Un paragraphe d'explication + +Vous avez verrouillé vos dépendances en utilisant [**Verrouillez les dépendances**](./lockdependencies.french.md), mais maintenant, vous devez vous assurer que ces versions précises des paquets sont utilisées en production. + +L'utilisation de `npm ci` pour installer des paquets fera exactement cela et plus encore. +* Il échouera si votre `package.json` et votre `package-lock.json` ne correspondent pas (ils devraient) ou si vous n'avez pas de fichier lock +* Si un dossier `node_modules` est présent, il sera automatiquement supprimé avant l'installation +* C'est plus rapide ! Près de deux fois plus rapide selon [l'article de version du blog](https://blog.npmjs.org/post/171556855892/introducing-npm-ci-for-faster-more-reliable) + +### Quand cela peut-il être utile ? +Vous avez la garantie que votre environnement CI ou de qualité testera votre logiciel avec exactement la même version que celle que vous enverrez plus tard en production. +De plus, si pour une raison quelconque quelqu'un modifie manuellement le fichier package.json, sans utiliser une commande du cli mais plutôt en éditant directement le fichier package.json, un écart entre le package.json et le package-lock.json est engendré et une erreur sera levée. + +### Ce que dit npm + +Extrait de la [documentation npm ci](https://docs.npmjs.com/cli/ci.html) +> Cette commande est similaire à npm-install, sauf qu'elle est destinée à être utilisée dans des environnements automatisés tels que les plateformes de test, l'intégration continue et le déploiement, ou toute situation où vous voulez vous assurer que vous faites une installation propre de vos dépendances. + +[Article du blog annonçant la sortie de la commande `ci`](https://blog.npmjs.org/post/171556855892/introducing-npm-ci-for-faster-more-reliable) +> La commande offre des améliorations considérables à la fois en termes de performance et de fiabilité des builds pour les intégrations continues/processus de déploiement continus, offrant une expérience cohérente et rapide aux développeurs qui utilisent les CI/CD dans leur flux de travail. + +[npmjs: dependencies et devDepencies](https://docs.npmjs.com/specifying-dependencies-and-devdependencies-in-a-package-json-file) +> "dependencies": Paquets requis par votre application en production. +> "devDependencies": Paquets qui ne sont nécessaires que pour le développement local et les tests. + +

diff --git a/sections/production/installpackageswithnpmci.japanese.md b/sections/production/installpackageswithnpmci.japanese.md index a17cca0dc..88c2d184e 100644 --- a/sections/production/installpackageswithnpmci.japanese.md +++ b/sections/production/installpackageswithnpmci.japanese.md @@ -4,7 +4,7 @@ ### 一段落説明 -[**依存関係をロックする**](/sections/production/lockdependencies.japanese.md) に従って依存関係をロックしましたが、本番環境で使用されているパッケージのバージョンが正確であることを確認する必要があります。 +[**依存関係をロックする**](./lockdependencies.japanese.md) に従って依存関係をロックしましたが、本番環境で使用されているパッケージのバージョンが正確であることを確認する必要があります。 パッケージのインストールに `npm ci` を使うと、まさにそれ以上のことができます。 * `package.json` と `package-lock.json` が一致していない (一致しているはずの) 場合や、ロックファイルがない場合は失敗します。 diff --git a/sections/production/installpackageswithnpmci.md b/sections/production/installpackageswithnpmci.md index ed7e497ce..bc43a4022 100644 --- a/sections/production/installpackageswithnpmci.md +++ b/sections/production/installpackageswithnpmci.md @@ -4,7 +4,7 @@ ### One Paragraph Explainer -You locked your dependencies following [**Lock dependencies**](/sections/production/lockdependencies.md) but you now need to make sure those exact package versions are used in production. +You locked your dependencies following [**Lock dependencies**](./lockdependencies.md) but you now need to make sure those exact package versions are used in production. Using `npm ci` to install packages will do exactly that and more. * It will fail if your `package.json` and your `package-lock.json` do not match (they should) or if you don't have a lock file diff --git a/sections/production/lockdependencies.basque.md b/sections/production/lockdependencies.basque.md new file mode 100644 index 000000000..210e11ad4 --- /dev/null +++ b/sections/production/lockdependencies.basque.md @@ -0,0 +1,69 @@ +# Blokeatu menpekotasunak + +

+ +### Azalpena + +Zure kodea kanpoko pakete askoren menpe dago. Esan dezagun momentjs-2.1.4 ‘behar‘ eta erabiltzen duela eta, lehenespenez, ekoizpenean erabiltzen duzunean, npmek zmomentjs 2.1.5 eskura dezake, tamalez errore berri batzuk ekarriko dituena mahaira. Npm konfigurazio fitxategiak eta `–save-exact=true` argumentuak erabiltzeak adierazten dio npm-ri instalatutako bertsio berbera erabili behar duela, eta, beraz, `npm install` exekutatzen duzun hurrengo aldian (ekoizpenean edo probak egiteko bidali nahi duzu Docker edukiontzi baten barruan) menpeko bertsio bera eskuratuko du. Horren ordez, aukera egokia eta ezaguna da `.shrinkwrap` fitxategia erabiltzea (npm erabiliz erraz sortzen dena), berak adieraziko baitu zein pakete eta bertsio instalatu beharko liratekeen inongo inguruneak tentaziorik izan ez dezan espero baino bertsio berriagorik bilatzeko. + +- **Eguneratzea:** npm 5etik aurrera, menpekotasunak automatikoki blokeatzen dira .shrinkwrap erabiliz gero. Yarn pakete kudeatzaile sortu berriak ere menpekotasunak blokeatzen ditu lehenespenez. + +

+ +### Kode adibidea: .npmrc fitxategi mota bat da, npmri agindua ematen diona bertsio zehatzak erabiltzeko + +```npmrc +// gorde hau .npmrc fitxategi gisa zure proiektuan +save-exact:true +``` + +

+ +### Kode adibidea: shrinkwrap.json fitxategia, menpekotasun zuhaitz zehatza osatzen duena + +```json +{ + "name": "A", + "dependencies": { + "B": { + "version": "0.0.1", + "dependencies": { + "C": { + "version": "0.1.0" + } + } + } + } +} +``` + +

+ +### Kode adibidea: npm 5 menpekotasunak blokeatzeko fitxategia - package-lock.json + +```json +{ + "name": "package-name", + "version": "1.0.0", + "lockfileVersion": 1, + "dependencies": { + "cacache": { + "version": "9.2.6", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-9.2.6.tgz", + "integrity": "sha512-YK0Z5Np5t755edPL6gfdCeGxtU0rcW/DBhYhYVDckT+7AFkCCtedf2zru5NRbBLFk6e7Agi/RaqTOAfiaipUfg==" + }, + "duplexify": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.0.tgz", + "integrity": "sha1-GqdzAC4VeEV+nZ1KULDMquvL1gQ=", + "dependencies": { + "end-of-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.0.0.tgz", + "integrity": "sha1-1FlucCc0qT5A6a+GQxnqvZn/Lw4=" + } + } + } + } +} +``` diff --git a/sections/production/lockdependencies.french.md b/sections/production/lockdependencies.french.md new file mode 100644 index 000000000..6702b633d --- /dev/null +++ b/sections/production/lockdependencies.french.md @@ -0,0 +1,69 @@ +# Verrouillez les dépendances + +

+ +### Un paragraphe d'explication + +Votre code dépend de nombreux paquets externes, disons qu'il "requiert" et utilise momentjs-2.1.4, puis par défaut lorsque vous déployez en production, npm peut récupérer momentjs 2.1.5, ce qui malheureusement apporte quelques nouveaux bogues. L'utilisation de fichiers de configuration npm et de l'argument ```–save-exact=true``` indique à npm de se référer à la version *strictement* identique à celle qui a été installée, donc la prochaine fois que vous exécuterez ```npm install``` (en production ou dans un conteneur Docker que vous prévoyez d'expédier pour test), la même version dépendante sera récupérée. Une approche alternative et populaire utilise un fichier `.shrinkwrap` (facilement généré à l'aide de npm) qui indique exactement quels packages et versions doivent être installés afin qu'aucun environnement ne soit tenté de récupérer des versions plus récentes que prévu. + +* **Mise à jour :** à partir de npm 5, les dépendances sont verrouillées automatiquement à l'aide de .shrinkwrap. Yarn, un nouveau gestionnaire de packages, verrouille également les dépendances par défaut. + +

+ +### Exemple de code : fichier .npmrc qui demande à npm d'utiliser des versions exactes + +```npmrc +// enregistrez-le en tant que fichier .npmrc dans le répertoire du projet +save-exact:true +``` + +

+ +### Exemple de code : fichier shrinkwrap.json qui extrait l'arbre exact des dépendances + +```json +{ + "name": "A", + "dependencies": { + "B": { + "version": "0.0.1", + "dependencies": { + "C": { + "version": "0.1.0" + } + } + } + } +} +``` + +

+ +### Exemple de code : fichier de verrouillage des dépendances npm 5 - package-lock.json + +```json +{ + "name": "package-name", + "version": "1.0.0", + "lockfileVersion": 1, + "dependencies": { + "cacache": { + "version": "9.2.6", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-9.2.6.tgz", + "integrity": "sha512-YK0Z5Np5t755edPL6gfdCeGxtU0rcW/DBhYhYVDckT+7AFkCCtedf2zru5NRbBLFk6e7Agi/RaqTOAfiaipUfg==" + }, + "duplexify": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.0.tgz", + "integrity": "sha1-GqdzAC4VeEV+nZ1KULDMquvL1gQ=", + "dependencies": { + "end-of-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.0.0.tgz", + "integrity": "sha1-1FlucCc0qT5A6a+GQxnqvZn/Lw4=" + } + } + } + } +} +``` diff --git a/sections/production/lockdependencies.md b/sections/production/lockdependencies.md index 1698c9bbb..61800062f 100644 --- a/sections/production/lockdependencies.md +++ b/sections/production/lockdependencies.md @@ -4,9 +4,7 @@ ### One Paragraph Explainer -Your code depends on many external packages, let’s say it ‘requires’ and use momentjs-2.1.4, then by default when you deploy to production npm might fetch momentjs 2.1.5 which unfortunately brings some new bugs to the table. Using npm config files and the argument ```–save-exact=true``` instructs npm to refer to the *exact* same version that was installed so the next time you run ```npm install``` (in production or within a Docker container you plan to ship forward for testing) the same dependent version will be fetched. An alternative and popular approach is using a `.shrinkwrap` file (easily generated using npm) that states exactly which packages and versions should be installed so no environment can get tempted to fetch newer versions than expected. - -* **Update:** as of npm 5, dependencies are locked automatically using .shrinkwrap. Yarn, an emerging package manager, also locks down dependencies by default. +Your code depends on many external packages, let’s say it ‘requires’ and use momentjs-2.1.4, then by default when you deploy to production npm might fetch momentjs 2.1.5 which unfortunately brings some new bugs to the table. Using npm config files and the argument `–save-exact=true` instructs npm to refer to the _exact_ same version that was installed so the next time you run `npm install` (in production or within a Docker container you plan to ship forward for testing) the same dependent version will be fetched. Due to this, starting from npm version 5 a package-lock.json file is generated in every install. This lock file pins all the dependencies and child dependencies versions. When the file is committed, any future install the gets a copy of the app will install the same dependencies version

@@ -19,51 +17,31 @@ save-exact:true

-### Code example: shrinkwrap.json file that distills the exact dependency tree - -```json -{ - "name": "A", - "dependencies": { - "B": { - "version": "0.0.1", - "dependencies": { - "C": { - "version": "0.1.0" - } - } - } - } -} -``` - -

- ### Code example: npm 5 dependencies lock file – package-lock.json ```json { - "name": "package-name", - "version": "1.0.0", - "lockfileVersion": 1, - "dependencies": { - "cacache": { - "version": "9.2.6", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-9.2.6.tgz", - "integrity": "sha512-YK0Z5Np5t755edPL6gfdCeGxtU0rcW/DBhYhYVDckT+7AFkCCtedf2zru5NRbBLFk6e7Agi/RaqTOAfiaipUfg==" - }, - "duplexify": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.0.tgz", - "integrity": "sha1-GqdzAC4VeEV+nZ1KULDMquvL1gQ=", - "dependencies": { - "end-of-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.0.0.tgz", - "integrity": "sha1-1FlucCc0qT5A6a+GQxnqvZn/Lw4=" - } - } + "name": "package-name", + "version": "1.0.0", + "lockfileVersion": 1, + "dependencies": { + "cacache": { + "version": "9.2.6", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-9.2.6.tgz", + "integrity": "sha512-YK0Z5Np5t755edPL6gfdCeGxtU0rcW/DBhYhYVDckT+7AFkCCtedf2zru5NRbBLFk6e7Agi/RaqTOAfiaipUfg==" + }, + "duplexify": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.0.tgz", + "integrity": "sha1-GqdzAC4VeEV+nZ1KULDMquvL1gQ=", + "dependencies": { + "end-of-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.0.0.tgz", + "integrity": "sha1-1FlucCc0qT5A6a+GQxnqvZn/Lw4=" } + } } + } } ``` diff --git a/sections/production/logrouting.basque.md b/sections/production/logrouting.basque.md new file mode 100644 index 000000000..5b8040d79 --- /dev/null +++ b/sections/production/logrouting.basque.md @@ -0,0 +1,95 @@ +# Aplikazioaren kodeak ez luke erregistroen bideraketa kudeatu beharko + +

+ +### Azalpena + +Aplikazioaren kodeak ez luke erregistroen bideraketa kudeatu behar, baina erregistro tresnaren bat erabili beharko luke `stdout/stderr`-era idazteko. "Erregistroen bideratzeak" esan nahi du zure eskaerara edo eskaera prozesua ez den beste kokapen batera eraman eta bultzatzea erregistroak, adibidez, erregistroak fitxategi batean, datu basean eta abar idaztea. Bi dira, batez ere, horren arrazoiak: 1) kezkak bereiztea eta 2) [aplikazio modernoen 12 faktoreko praktika onak](https://12factor.net/logs). + +"Kezkak bereiztea" esatean, askotan pentsatzen dugu zerbitzuen arteko kode zatiei eta zerbitzuen euren arteko loturei buruz ari garela, baina hori "azpiegitura" osagaiei ere aplikatzen zaie. Aplikazioaren kodeak ez luke kudeatu behar azpiegiturak/exekuzio inguruneak (egun gehienetan, edukiontziak) kudeatu beharko lukeen zerbait. Zer gertatzen da aplikazioko erregistroen kokapenak zehazten badituzu, baina geroago kokapen hori aldatu behar baduzu? Horrek kode aldaketa eta inplementazioa eragiten ditu. Edukiontzietan/hodeian oinarritutako plataformekin lan egiten denean, edukiontziak biratu eta itxi egin daitezke errendimendu eskaeretara eskalatzean, eta, beraz, ezin dugu ziurtatu non amaituko diren erregistroen fitxategiak. Exekuzio inguruneak (edukiontziak) erabaki beharko luke nora bideratuko diren erregistro fitxategiak. Aplikazioak zer behar duen erregistratu beharko luke `stdout` / `stderr`-en, eta exekuzio ingurunea konfiguratuta egon beharko litzateke erregistro fluxua han jaso eta joan behar duen lekura bideratzeko. Halaber, erregistroen helmugak zehaztu edo / eta aldatu behar dituzten taldeko kideak askotan ez dira aplikazioen garatzaileak, baizik eta DevOps-eko kideak, eta agian ez dute aplikazioaren kodea ezagutzen. Horrek eragozten die aldaketak erraz egitea. +Anti ereduaren kode adibidea: erregistroaren bideratzea aplikazioari hertsiki lotua + +

+ +### Anti ereduaren kode adibidea: erregistroaren bideratzea aplikazioari hertsiki lotua + +```javascript +const { createLogger, transports, winston } = require("winston"); +/** + * `winston-mongodb` eskatzeak + * `winston.transports.MongoDB` agerian utziko du + */ +require("winston-mongodb"); + +// bi fitxategi ezberdin erregistratu, honela aplikazioa hauekin lotuta egongo da +const logger = createLogger({ + transports: [new transports.File({ filename: "combined.log" })], + exceptionHandlers: [new transports.File({ filename: "exceptions.log" })], +}); + +// MongoDB-n erregistratu, honela aplikazioa hauekin lotuta egongo da +winston.add(winston.transports.MongoDB, options); +``` + +Horrela eginez gero, aplikazioak kudeatuko ditu bai aplikazio/ negozio logika, bai erregistroen bideratze logika! + +

+ +### Kodea adibidea: erregistroen tratamendu onena + Docker adibidea + +In the application: + +```javascript +const logger = new winston.Logger({ + level: "info", + transports: [new winston.transports.Console()], +}); + +logger.log( + "info", + "Test Log Message with some parameter %s", + "some parameter", + { anything: "This is metadata" } +); +``` + +Then, in the docker container `daemon.json`: + +```json5 +{ + "log-driver": "splunk", // Splunk erabiliaz, adibide gisa, beste gordetze mota bat izango genuke + "log-opts": { + "splunk-token": "", + "splunk-url": "", + //... + }, +} +``` + +Beraz adibide honek `log -> stdout -> Docker container -> Splunk`-en antza du + +

+ +### Blogaren aipua: "O'Reilly" + +[O'Reilly](https://www.oreilly.com/ideas/a-cloud-native-approach-to-logs) bloga, + +> Zerbitzari kopuru konkretu batean instantzia kopuru finko bat duzunean, ematen du erregistroak diskoan gordetzea zentzuzkoa dela. Hala ere, zure aplikazioa dinamikoki exekutatzen ari den instantzia batetik 100era pasa daitekeenean eta instantzia horiek non exekutatzen diren ez dakizunean, zure hodei hornitzaileak erregistro horiek zure partez gehitu beharko ditu zure partez. + +

+ +### Aipua: "12 faktorea" + +[Saioa hasteko 12 faktoreko praktika onenak](https://12factor.net/logs) testutik hartua: + +> Hamabi faktoreko aplikazio bat ez da inoiz bere irteera korrontea bideratzeaz edo biltegiratzeaz arduratzen. Ez luke saiatu behar erregistro fitxategietan idazten edo kudeatzen. Horren ordez, exekutatzen ari den prozesu bakoitzak bere gertaeren korrontea, bufferrik gabekoa, stdout-era idazten du. + +> Proba edo produkzio inplementazioetan, exekuzio inguruneak harrapatuko du prozesu bakoitzeko korrontea, aplikazioko beste korronte guztiekin batera bildu eta azken helmuga batera edo gehiagora bideratuko ditu ikusteko eta epe luzerako artxibatzeko. Aplikazioak ezin ditu artxiboko helmuga horiek ikusi, ezta konfiguratu ere, eta exekuzio ingurunea da kudeatzen dituen bakarra. + +

+ +### Adibidea: arkitekturaren ikuspegi orokorra Docker eta Splunk erabiliz adibide gisa + +![alt text](../../assets/images/logging-overview.png "Arkitekturaren ikuspegi orokorra") + +

diff --git a/sections/production/logrouting.brazilian-portuguese.md b/sections/production/logrouting.brazilian-portuguese.md index 5fb771a96..f18d24c97 100644 --- a/sections/production/logrouting.brazilian-portuguese.md +++ b/sections/production/logrouting.brazilian-portuguese.md @@ -79,6 +79,6 @@ Do [guia de boas práticas 12-Factor](https://12factor.net/logs), ### Exemplo: Visão geral da arquitetura usando o Docker e o Splunk como exemplo -![alt text](/assets/images/logging-overview.png "Visão geral de roteamento de log") +![alt text](../../assets/images/logging-overview.png "Visão geral de roteamento de log")

diff --git a/sections/production/logrouting.french.md b/sections/production/logrouting.french.md new file mode 100644 index 000000000..ebba94f23 --- /dev/null +++ b/sections/production/logrouting.french.md @@ -0,0 +1,87 @@ +# Votre application ne doit pas gérer la redirection du journal + +

+ +### Un paragraphe d'explication + +Le code de l'application ne devrait pas gérer le routage des journaux, mais plutôt utiliser un utilitaire de journalisation pour écrire dans `stdout/stderr`. Le « routage des journaux » signifie qu'il faut récupérer et pousser les journaux vers un autre endroit que votre application ou processus d'application, par exemple, écrire les journaux dans un fichier, une base de données, etc. La raison en est essentiellement double : 1) la séparation des préoccupations et 2) [12-Factor les meilleures pratiques pour les applications modernes](https://12factor.net/logs). + +Nous pensons souvent à la « séparation des préoccupations » en termes de morceaux de code entre les services et entre les services eux-mêmes, mais cela s'applique également aux éléments plus « infrastructurels ». Votre code d'application ne doit pas gérer quelque chose qui devrait être géré par l'infrastructure/l'environnement d'exécution (le plus souvent de nos jours, les conteneurs). Que se passe-t-il si vous définissez les emplacements des journaux dans votre application, mais que vous devez ensuite modifier cet emplacement ? Cela entraîne un changement de code et un déploiement. Lorsque l'on travaille avec des plateformes basées sur des conteneurs ou le cloud, les conteneurs peuvent démarrer et s'arrêter lors de la mise à l'échelle en fonction des exigences de performance, donc nous ne pouvons pas savoir où un fichier journal sera placé. L'environnement d'exécution (conteneur) devrait plutôt décider où les fichiers journaux sont dirigés. L'application doit simplement enregistrer ce dont elle a besoin dans `stdout` / `stderr`, et l'environnement d'exécution doit être configuré pour récupérer le flux de données de cet enregistrement et le diriger vers l'endroit où il doit aller. De plus, les membres de l'équipe qui doivent spécifier et/ou modifier les destinations des journaux ne sont souvent pas des développeurs d'applications mais font partie de DevOps, et ils peuvent ne pas être familiers avec le code de l'application. Cela les empêche d'apporter facilement des modifications. + +

+ +### Exemple de code incorrect : acheminement des logs étroitement couplé à l'application + +```javascript +const { createLogger, transports, winston } = require('winston'); +/** + * Le fait d'exiger `winston-mongodb` exposera + * `winston.transports.MongoDB` + */ +require('winston-mongodb'); + +// journalisation vers deux fichiers différents, sur lesquels l'application doit maintenant se concentrer +const logger = createLogger({ + transports: [ + new transports.File({ filename: 'combined.log' }), + ], + exceptionHandlers: [ + new transports.File({ filename: 'exceptions.log' }) + ] +}); + +// journalisation vers MongoDB, which the application now must be concerned with +winston.add(winston.transports.MongoDB, options); +``` +En procédant ainsi, l'application gère à la fois la logique applicative/métier ET la logique de routage des journaux ! + +

+ +### Exemple de code - Meilleure gestion des journaux + exemple Docker +Dans l'application : +```javascript +const logger = new winston.Logger({ + level: 'info', + transports: [ + new (winston.transports.Console)() + ] +}); + +logger.log('info', 'Test message du journal avec certains paramètres %s', 'certains paramètres', { anything: 'Voici les métadonnées' }); +``` +Puis, dans le conteneur du docker `daemon.json` : +```json5 +{ + "log-driver": "splunk", // en utilisant Splunk comme exemple, il pourrait s'agir d'un autre type de stockage + "log-opts": { + "splunk-token": "", + "splunk-url": "", + //... + } +} +``` +Cet exemple se présente donc comme suit : `log -> stdout -> conteneur Docker -> Splunk` + +

+ +### Citation du blog : « O'Reilly » + +Extrait du [blog de O'Reilly](https://www.oreilly.com/ideas/a-cloud-native-approach-to-logs), + > Lorsque vous avez un nombre fixe d'instances sur un nombre fixe de serveurs, le stockage des journaux sur disque semble logique. Cependant, lorsque votre application peut passer dynamiquement d'une instance à 100, et que vous n'avez aucune idée de l'endroit où ces instances sont exécutées, vous avez besoin que votre fournisseur du cloud s'occupe de l'agrégation de ces journaux en votre nom. + +

+ +### Citation : « 12-Factor » + +Extrait de [12-Factor les meilleures pratiques pour la journalisation](https://12factor.net/logs), + > Une application à douze facteurs ne se préoccupe jamais du routage ou du stockage de son flux de sortie. Elle ne doit pas essayer d'écrire dans les fichiers journaux ou de les gérer. Au lieu de cela, chaque processus en cours d'exécution écrit son flux d'événements, sans bufferisation, sur stdout. + + > Lors des déploiements d'environnement de test ou de production, chaque flux de processus sera capturé par l'environnement d'exécution, regroupé avec tous les autres flux de l'application, et acheminé vers une ou plusieurs destinations finales pour être visionné et archivé à long terme. Ces destinations d'archivage ne sont pas visibles ou configurables par l'application, mais sont entièrement gérées par l'environnement d'exécution. + +

+ + ### Exemple : aperçu de l'architecture en utilisant Docker et Splunk comme exemple + +![alt text](../../assets/images/logging-overview.png "Aperçu du routage des journaux") + +

diff --git a/sections/production/logrouting.japanese.md b/sections/production/logrouting.japanese.md index a402215f6..666f27da7 100644 --- a/sections/production/logrouting.japanese.md +++ b/sections/production/logrouting.japanese.md @@ -82,6 +82,6 @@ logger.log('info', 'Test Log Message with some parameter %s', 'some parameter', ### 例: Docker と Splunk を例にしたアーキテクチャの概要 -![alt text](/assets/images/logging-overview.png "ログルーティングの概要") +![alt text](../../assets/images/logging-overview.png "ログルーティングの概要")

diff --git a/sections/production/logrouting.md b/sections/production/logrouting.md index 9fac3f52a..e290263fb 100644 --- a/sections/production/logrouting.md +++ b/sections/production/logrouting.md @@ -82,6 +82,6 @@ From the [12-Factor best practices for logging](https://12factor.net/logs), ### Example: Architecture overview using Docker and Splunk as an example -![alt text](/assets/images/logging-overview.png "Log routing overview") +![alt text](../../assets/images/logging-overview.png "Log routing overview")

diff --git a/sections/production/logrouting.polish.md b/sections/production/logrouting.polish.md index fb0509d8b..02116825c 100644 --- a/sections/production/logrouting.polish.md +++ b/sections/production/logrouting.polish.md @@ -82,6 +82,6 @@ Z [12-Factor best practices for logging](https://12factor.net/logs), ### Przykład: Przegląd architektury na przykładzie Docker i Splunk -![alt text](/assets/images/logging-overview.png "Log routing overview") +![alt text](../../assets/images/logging-overview.png "Log routing overview")

diff --git a/sections/production/logrouting.russian.md b/sections/production/logrouting.russian.md index 3814143c2..be00f9eeb 100644 --- a/sections/production/logrouting.russian.md +++ b/sections/production/logrouting.russian.md @@ -82,6 +82,6 @@ logger.log('info', 'Test Log Message with some parameter %s', 'some parameter', ### Пример: обзор архитектуры с использованием Docker и Splunk в качестве примера -![alt text](/assets/images/logging-overview.png "Log routing overview") +![alt text](../../assets/images/logging-overview.png "Log routing overview")

diff --git a/sections/production/measurememory.basque.md b/sections/production/measurememory.basque.md new file mode 100644 index 000000000..b3ca472cb --- /dev/null +++ b/sections/production/measurememory.basque.md @@ -0,0 +1,25 @@ +# Neurtu eta zaindu memoriaren erabilera + +

+ +### Azalpena + +Mundu perfektu batean, web garatzaile batek ez luke memoria ihesei aurre egin beharko. Egia esan, memoria arazoak Nodek duen arazo ezaguna da eta ezagutu egin behar dena. Node erabiltzen denean, batez ere, memoriaren erabilera etengabe kontrolatu beharra dago. Garapen eta produkzio txikiko guneetan, neurketa eskuz egin dezakezu Linux komandoak edo npm tresnak eta liburutegiak erabiliz, nodo-inspector eta memwatch bezalakoak. Eskuzko jarduera horren eragozpen nagusia da eskatzen dutela jarraipena gizaki batek egitea modu aktiboan. Ekoizpen gune serioetarako, guztiz funtsezkoa da kontrol tresna sendoak erabiltzea, adibidez (AWS CloudWatch, DataDog edo antzeko edozein sistema proaktibo), iragazkia gertatzen denean ohartarazten duena. Badaude garapen praktika gutxi batzuk ere ihesak saihesteko: saihestu datuak gordetzea maila globalean, erabili tamaina dinamikoa duten datuentzako fluxuak, mugatu aldagaiak let eta const erabiliz. + +

+ +### Beste blogari batzuek diotena + +[Dyntrace](https://www.dynatrace.com/news/blog/understanding-garbage-collection-and-hunting-memory-leaks-in-node-js/) bloga: + +> ... ”Dagoeneko badakigun bezala, Node.jsren V8k jatorrizko kodean konpilatzen du JavaScript. Sortzen diren jatorrizko datu egiturek ez dute zerikusi handirik jatorrizko irudikapenarekin, eta V8k kudeatzen ditu soilik. Horrek esan nahi du ezin dugula memoria aktiboki esleitu edo banatu JavaScripten. V8k zabor bilketa izeneko mekanismo ezaguna erabiltzen du arazo horri aurre egiteko". + +[Dyntrace](http://blog.argteam.com/coding/hardening-node-js-for-production-part-2-using-nginx-to-avoid-node-js-load) bloga: + +> ... ... "Adibide honek ageriko emaitzak lortzen baditu ere, prozesua beti berdina da: sortu pila zabortegiak denbora pixka bat eta memoria asko esleituta. Konparatu zabortegi batzuk zer hazten ari den jakiteko" + +[Rising Stack](https://blog.risingstack.com/finding-a-memory-leak-in-node-js/) bloga: + +> ... “hutsegitea, Node.js 1,5 GB memoria inguru erabiltzen saiatuko da, eta hori mugatu egin behar da memoria gutxiago duten sistemetan exekutatzen denean. Hori da espero den jokabidea, zabor bilketa oso operazio garestia baita. Horren irtenbidea izan zen Node.js prozesuari beste parametro bat gehitzea: nodo –max_old_space_size = 400 server.js –production . " + +“Zergatik da garestia zabor bilketa? V8 JavaScript motorrak zaborra biltzeko erabiltzen duen mekanismoa mundu osoa gelditzeko modukoa da. Praktikan, horrek esan nahi du programak exekuzioa gelditu egiten duela zabor bilketa martxan dagoen bitartean". diff --git a/sections/production/measurememory.brazilian-portuguese.md b/sections/production/measurememory.brazilian-portuguese.md index 9bcaa29be..1792e3b15 100644 --- a/sections/production/measurememory.brazilian-portuguese.md +++ b/sections/production/measurememory.brazilian-portuguese.md @@ -10,7 +10,7 @@ Em um mundo perfeito, um desenvolvedor Web não deve lidar com vazamentos de mem ### O que Outros Blogueiros Dizem -* Do blog [Dyntrace](http://apmblog.dynatrace.com/): +* Do blog [Dyntrace](https://www.dynatrace.com/news/blog/understanding-garbage-collection-and-hunting-memory-leaks-in-node-js/): > ... ”Como já aprendemos, no Node.js o JavaScript é compilado para código nativo pelo V8. As estruturas de dados nativas resultantes não têm muito a ver com a representação original e são gerenciadas exclusivamente pelo V8. Isso significa que não podemos alocar ou desalocar ativamente a memória em JavaScript. O V8 usa um mecanismo bem conhecido chamado coleta de lixo para resolver esse problema.” * Do blog [Dyntrace](http://blog.argteam.com/coding/hardening-node-js-for-production-part-2-using-nginx-to-avoid-node-js-load): @@ -18,7 +18,7 @@ Em um mundo perfeito, um desenvolvedor Web não deve lidar com vazamentos de mem Crie dumps de heap com algum tempo e uma boa quantidade de alocação de memória entre Compare alguns dumps para descobrir o que está crescendo” -* Do blog [Dyntrace](http://blog.argteam.com/coding/hardening-node-js-for-production-part-2-using-nginx-to-avoid-node-js-load): +* Do blog [Rising Stack](https://blog.risingstack.com/finding-a-memory-leak-in-node-js/): > ... “falha, o Node.js tentará usar cerca de 1,5 GB de memória, que deve ser limitado quando executado em sistemas com menos memória. Esse é o comportamento esperado, pois a coleta de lixo é uma operação muito cara. A solução para isso foi adicionar um parâmetro extra ao processo Node.js: node –max_old_space_size=400 server.js –production ” diff --git a/sections/production/measurememory.chinese.md b/sections/production/measurememory.chinese.md index 97cdd9c1f..63a06d4c0 100644 --- a/sections/production/measurememory.chinese.md +++ b/sections/production/measurememory.chinese.md @@ -11,13 +11,13 @@ ### 其他博客说了什么 -* 摘自博客 [Dyntrace](http://apmblog.dynatrace.com/): +* 摘自博客 [Dyntrace](https://www.dynatrace.com/news/blog/understanding-garbage-collection-and-hunting-memory-leaks-in-node-js/): > ... ”正如我们所了解到的,在Node.js 中,JavaScript被V8编译为机器码。由此产生的机器码数据结构与原始表达没有多大关系,只能由V8管理. 这意味着我们不能主动分配或释放JavaScript中的内存. V8 使用了一个众所周知的垃圾收集机制来解决这个问题.” * 摘自博客 [Dyntrace](http://blog.argteam.com/coding/hardening-node-js-for-production-part-2-using-nginx-to-avoid-node-js-load): > ... “虽然这个例子导致了明显的结果,但这个过程总是一样的:用一些时间和相当数量的内存分配创建heap dumps,比较dumps,以找出正在增长的内存泄露。” -* 摘自博客 [Dyntrace](http://blog.argteam.com/coding/hardening-node-js-for-production-part-2-using-nginx-to-avoid-node-js-load): +* 摘自博客 [Rising Stack](https://blog.risingstack.com/finding-a-memory-leak-in-node-js/): > ... “故障, 在内存较少的系统上运行时必须限制内存,Node.js会尝试使用大约1.5GB的内存。这是预期的行为,垃圾收集是一个代价很高的操作。 解决方案是为Node.js进程添加一个额外的参数: node –max_old_space_size=400 server.js –production ” diff --git a/sections/production/measurememory.french.md b/sections/production/measurememory.french.md new file mode 100644 index 000000000..b8f2256bd --- /dev/null +++ b/sections/production/measurememory.french.md @@ -0,0 +1,25 @@ +# Mesurez et protégez l'utilisation de la mémoire + +

+ +### Un paragraphe d'explication + +Dans un monde parfait, un développeur web ne devrait pas s'occuper des fuites de mémoire. En réalité, les problèmes de mémoire sont des phénomènes connus de Node dont il faut être conscient. Surtout, l'utilisation de la mémoire doit être constamment surveillée. Dans les sites de développement et les petits sites de production, vous pouvez mesurer manuellement en utilisant des commandes Linux ou des outils et des bibliothèques npm comme node-inspector et memwatch. Le principal inconvénient de ces activités manuelles est qu'elles nécessitent un être humain qui surveille activement - pour les sites de production sérieux, il est absolument vital d'utiliser des outils de surveillance robustes (AWS CloudWatch, DataDog ou tout autre système proactif similaire), par exemple qui alertent lorsqu'une fuite se produit. Il existe également peu de recommandations de développement pour anticiper des fuites : évitez de stocker les données au niveau global, utilisez des flux (NdT *streams*) pour les données de taille dynamique, limitez la portée des variables en utilisant des let et des const. + +

+ +### Ce que disent les autres blogueurs + +* Extrait du blog de [Dyntrace](https://www.dynatrace.com/news/blog/understanding-garbage-collection-and-hunting-memory-leaks-in-node-js/) : +> ... « Comme nous l'avons déjà appris, dans Node.js, JavaScript est compilé en code natif par V8. Les structures de données natives résultantes n'ont pas grand-chose à voir avec leur représentation d'origine et sont uniquement gérées par V8. Cela signifie que nous ne pouvons pas allouer ou désallouer activement de la mémoire en JavaScript. V8 utilise un mécanisme bien connu appelé le [ramasse-miettes](https://fr.wikipedia.org/wiki/Ramasse-miettes_(informatique)) (NdT *garbage collection*) pour résoudre ce problème. » + +* Extrait du blog de [Dyntrace](http://blog.argteam.com/coding/hardening-node-js-for-production-part-2-using-nginx-to-avoid-node-js-load) : +> ... « Bien que cet exemple mène à des résultats évidents, le processus est toujours le même : +Créez des copies de mémoires sur une certaine période avec une bonne quantité d'allocation de mémoire entre les deux +Comparez ces copies pour découvrir ce qui augmente » + +* Extrait du blog de [Rising Stack](https://blog.risingstack.com/finding-a-memory-leak-in-node-js/) : +> ... « Par défaut, Node.js essaiera d'utiliser environ 1,5GB de mémoire, ce qui doit être plafonné lors de l'exécution sur des systèmes avec moins de mémoire. C'est le comportement attendu car la récupération de place est une opération très coûteuse. +La solution pour cela a été d'ajouter un paramètre supplémentaire au processus de Node.js : +node –max_old_space_size=400 server.js –production » +« Pourquoi le ramasse-miettes coûte-t-il aussi cher ? Le moteur JavaScript V8 utilise un mécanisme d'arrêt lors du ramasse-miettes. En pratique, cela signifie que le programme arrête son exécution pendant que la récupération du ramasse-miettes est en cours. » diff --git a/sections/production/measurememory.japanese.md b/sections/production/measurememory.japanese.md index a9448efaf..ba3307ed9 100644 --- a/sections/production/measurememory.japanese.md +++ b/sections/production/measurememory.japanese.md @@ -10,7 +10,7 @@ ### 他のブロガーが言っていること -* ブログ [Dyntrace](http://apmblog.dynatrace.com/) より: +* ブログ [Dyntrace](https://www.dynatrace.com/news/blog/understanding-garbage-collection-and-hunting-memory-leaks-in-node-js/) より: > ... ”すでに学習したように、Node.js JavaScript は V8 でネイティブコードにコンパイルされています。結果として得られるネイティブなデータ構造は、元の表現とはあまり関係がなく、もっぱら V8 によって管理されています。つまり、JavaScript では能動的にメモリを割り当てたり、解放したりすることができません。V8 はこの問題に対処するために、ガベージコレクションと呼ばれるよく知られたメカニズムを使用しています。” * ブログ [Dyntrace](http://blog.argteam.com/coding/hardening-node-js-for-production-part-2-using-nginx-to-avoid-node-js-load) より: @@ -18,7 +18,7 @@ ある程度の時間をかけてヒープダンプを作成し、その間にかなりの量のメモリ割り当てを行います。 いくつかのダンプを比較して、何が成長しているかを確認します。” -* ブログ [Dyntrace](http://blog.argteam.com/coding/hardening-node-js-for-production-part-2-using-nginx-to-avoid-node-js-load) より: +* ブログ [Rising Stack](https://blog.risingstack.com/finding-a-memory-leak-in-node-js/) より: > ... “デフォルトでは、Node.js は約1.5 GB のメモリを使用しようとしますが、メモリの少ないシステムで実行する場合は上限を設定する必要があります。ガベージコレクションは非常にコストのかかる操作なので、これは予想される動作です。 これを解決するには、Node.js のプロセスに余分なパラメータを追加する必要がありました。: node –max_old_space_size=400 server.js –production ” diff --git a/sections/production/measurememory.korean.md b/sections/production/measurememory.korean.md index 3b5b31d21..d4946c0ff 100644 --- a/sections/production/measurememory.korean.md +++ b/sections/production/measurememory.korean.md @@ -10,7 +10,7 @@ In a perfect world, a web developer shouldn’t deal with memory leaks. In reali ### What Other Bloggers Say -* From the blog [Dyntrace](http://apmblog.dynatrace.com/): +* From the blog [Dyntrace](https://www.dynatrace.com/news/blog/understanding-garbage-collection-and-hunting-memory-leaks-in-node-js/): > ... ”As we already learned, in Node.js JavaScript is compiled to native code by V8. The resulting native data structures don’t have much to do with their original representation and are solely managed by V8. This means that we cannot actively allocate or deallocate memory in JavaScript. V8 uses a well-known mechanism called garbage collection to address this problem.” * From the blog [Dyntrace](http://blog.argteam.com/coding/hardening-node-js-for-production-part-2-using-nginx-to-avoid-node-js-load): @@ -18,7 +18,7 @@ In a perfect world, a web developer shouldn’t deal with memory leaks. In reali Create heap dumps with some time and a fair amount of memory allocation in between Compare a few dumps to find out what’s growing” -* From the blog [Dyntrace](http://blog.argteam.com/coding/hardening-node-js-for-production-part-2-using-nginx-to-avoid-node-js-load): +* From the blog [Rising Stack](https://blog.risingstack.com/finding-a-memory-leak-in-node-js/): > ... “fault, Node.js will try to use about 1.5GBs of memory, which has to be capped when running on systems with less memory. This is the expected behavior as garbage collection is a very costly operation. The solution for it was adding an extra parameter to the Node.js process: node –max_old_space_size=400 server.js –production ” diff --git a/sections/production/measurememory.md b/sections/production/measurememory.md index 3b5b31d21..d4946c0ff 100644 --- a/sections/production/measurememory.md +++ b/sections/production/measurememory.md @@ -10,7 +10,7 @@ In a perfect world, a web developer shouldn’t deal with memory leaks. In reali ### What Other Bloggers Say -* From the blog [Dyntrace](http://apmblog.dynatrace.com/): +* From the blog [Dyntrace](https://www.dynatrace.com/news/blog/understanding-garbage-collection-and-hunting-memory-leaks-in-node-js/): > ... ”As we already learned, in Node.js JavaScript is compiled to native code by V8. The resulting native data structures don’t have much to do with their original representation and are solely managed by V8. This means that we cannot actively allocate or deallocate memory in JavaScript. V8 uses a well-known mechanism called garbage collection to address this problem.” * From the blog [Dyntrace](http://blog.argteam.com/coding/hardening-node-js-for-production-part-2-using-nginx-to-avoid-node-js-load): @@ -18,7 +18,7 @@ In a perfect world, a web developer shouldn’t deal with memory leaks. In reali Create heap dumps with some time and a fair amount of memory allocation in between Compare a few dumps to find out what’s growing” -* From the blog [Dyntrace](http://blog.argteam.com/coding/hardening-node-js-for-production-part-2-using-nginx-to-avoid-node-js-load): +* From the blog [Rising Stack](https://blog.risingstack.com/finding-a-memory-leak-in-node-js/): > ... “fault, Node.js will try to use about 1.5GBs of memory, which has to be capped when running on systems with less memory. This is the expected behavior as garbage collection is a very costly operation. The solution for it was adding an extra parameter to the Node.js process: node –max_old_space_size=400 server.js –production ” diff --git a/sections/production/measurememory.polish.md b/sections/production/measurememory.polish.md index ef31ca86d..1e68071cb 100644 --- a/sections/production/measurememory.polish.md +++ b/sections/production/measurememory.polish.md @@ -10,7 +10,7 @@ W idealnym świecie programista nie powinien zajmować się wyciekami pamięci. ### Co mówią inni blogerzy -* Z bloga [Dyntrace](http://apmblog.dynatrace.com/): +* Z bloga [Dyntrace](https://www.dynatrace.com/news/blog/understanding-garbage-collection-and-hunting-memory-leaks-in-node-js/): > ... ”As we already learned, in Node.js JavaScript is compiled to native code by V8. The resulting native data structures don’t have much to do with their original representation and are solely managed by V8. This means that we cannot actively allocate or deallocate memory in JavaScript. V8 uses a well-known mechanism called garbage collection to address this problem.” * Z bloga [Dyntrace](http://blog.argteam.com/coding/hardening-node-js-for-production-part-2-using-nginx-to-avoid-node-js-load): @@ -18,7 +18,7 @@ W idealnym świecie programista nie powinien zajmować się wyciekami pamięci. Create heap dumps with some time and a fair amount of memory allocation in between Compare a few dumps to find out what’s growing” -* Z bloga [Dyntrace](http://blog.argteam.com/coding/hardening-node-js-for-production-part-2-using-nginx-to-avoid-node-js-load): +* Z bloga [Rising Stack](https://blog.risingstack.com/finding-a-memory-leak-in-node-js/): > ... “fault, Node.js will try to use about 1.5GBs of memory, which has to be capped when running on systems with less memory. This is the expected behavior as garbage collection is a very costly operation. The solution for it was adding an extra parameter to the Node.js process: node –max_old_space_size=400 server.js –production ” diff --git a/sections/production/measurememory.russian.md b/sections/production/measurememory.russian.md index 494d37cb2..08cd29b73 100644 --- a/sections/production/measurememory.russian.md +++ b/sections/production/measurememory.russian.md @@ -10,7 +10,7 @@ ### Что говорят другие блоггеры -* Из блога [Dyntrace](http://apmblog.dynatrace.com/): +* Из блога [Dyntrace](https://www.dynatrace.com/news/blog/understanding-garbage-collection-and-hunting-memory-leaks-in-node-js/): > ... "Как мы уже узнали, в Node.js JavaScript компилируется в нативный код V8. Получающиеся в результате собственные структуры данных не имеют большого отношения к их исходному представлению и управляются исключительно V8. Это означает, что мы не можем активно выделять или освобождать память в JavaScript. V8 использует хорошо известный механизм сбора мусора для решения этой проблемы". * Из блога [Dyntrace](http://blog.argteam.com/coding/hardening-node-js-for-production-part-2-using-nginx-to-avoid-node-js-load): @@ -18,7 +18,7 @@ Создайте дампы кучи с некоторым временем и достаточным количеством памяти, выделяемой между ними Сравните несколько свалок, чтобы узнать, что растет" -* Из блога [Dyntrace](http://blog.argteam.com/coding/hardening-node-js-for-production-part-2-using-nginx-to-avoid-node-js-load): +* Из блога [Rising Stack](https://blog.risingstack.com/finding-a-memory-leak-in-node-js/): > ... "ошибка, Node.js попытается использовать около 1,5ГБ памяти, которая должна быть ограничена при работе в системах с меньшим объемом памяти. Это ожидаемое поведение, поскольку сборка мусора является очень дорогостоящей операцией. Решением для этого было добавление дополнительного параметра в процесс Node.js: node –max_old_space_size=400 server.js –production" diff --git a/sections/production/monitoring.basque.md b/sections/production/monitoring.basque.md new file mode 100644 index 000000000..b12599773 --- /dev/null +++ b/sections/production/monitoring.basque.md @@ -0,0 +1,39 @@ +# Monitorizazioa! + +

+ +### Azalpena + +Mailarik oinarrizkoenean, kontrolak esan nahi du produkzioan _erraz_ identifikatu ahal izango duzula gauza txarrak noiz gertatzen diren, posta elektronikoz edo Slack bidez jakinaraziz, adibidez. Zure eskakizunak aseko dituen tresna multzo egokia aukeratzea da erronka, zure ekonomia lur jota geratu gabe. Proposatzen dizut zehatz dezazun egoera osasuntsu bat bermatzeko ezarri beharreko metrika multzo nagusia: PUZa, zerbitzariaren RAMa, Nodo prozesuaren RAMa (1,4 GB baino gutxiago), azken minutuko errore kopurua, prozesuaren berrabiarazte kopurua eta batez besteko erantzun denbora. Ondoren, aukeratu zure gustuko ezaugarri aurreratuak eta gehitu zure nahien zerrendara. Luxuzko monitorizazio funtzioaren adibide batzuk: DB profilak, zerbitzu gurutzatuak neurtzea (hau da, negozio transakzioa neurtzea), front-end integrazioa, datu gordinak BI pertsonalizatutako bezeroen aurrean uztea, Slack jakinarazpenak eta beste hainbat. + +Funtzio aurreratuak lortu nahi badituzu, konfigurazio luzea egin beharko duzu edo, bestela, Datadog, NewRelic eta antzeko produktu komertzialak erosi beharko dituzu. Zoritxarrez, oinarriak ere lortzea ez da parkean paseoan ibiltzea. Izan ere, metrika batzuk (PUZ) hardwarearekin lotuta daude eta beste batzuk nodoaren prozesuan bizi dira (barne erroreak), eta, beraz, tresna zuzen guztiek konfigurazio osagarria eskatzen dute. Adibidez, saltzaileen hodeiko kontrol irtenbideek (adibidez, [AWS CloudWatch](https://aws.amazon.com/cloudwatch/), [Google StackDriver](https://cloud.google.com/stackdriver/)) berehala emango dizute hardwarearen metrikaren berri, baina ez barneko aplikazioaren portaerarena. Beste aldetik, egunkarietan oinarritutako ElasticSearch bezalako irtenbideek ez dute lehenetsita hardwarearen ikuspegia. Irtenbidea zure aukera handitzea da falta diren metrikekin osatuz; adibidez, aukera ezagun bat aplikazioen erregistroak [Elastic stack](https://www.elastic.co/products)era bidaltzea da eta agente osagarri batzuk konfiguratzea (adibidez, [Beat](https://www.elastic.co/products)) hardwarearekin lotutako informazioa partekatuz argazki osoa lortzeko. + +

+ +### Jarraipen adibidea: AWS cloudwatch panel lehenetsia. Zaila da aplikazioko metrika ateratzea + +![AWS cloudwatch panel lehenetsia. Zaila da aplikazioko metrika ateratzea](../../assets/images/monitoring1.png) + +

+ +### Jarraipen adibidea: StackDriver panel lehenetsia. Zaila da aplikazioko metrika ateratzea + +![StackDriver panel lehenetsia. Zaila da aplikazioko metrika ateratzea](../../assets/images/monitoring2.jpg) + +

+ +### Adibidea: Grafana datu gordinak bistaratzen dituen UI geruza gisa + +![Grafana datu gordinak bistaratzen dituen UI geruza gisa](../../assets/images/monitoring3.png) + +

+ +### Beste blogari batzuek diotena + +[Rising Stack](https://blog.risingstack.com/node-js-performance-monitoring-with-prometheus/) bloga : + +> …Zure zerbitzu guztietako seinale horiek ikustea gomendatzen dizugu. +> Errorea: erroreek erabiltzaileei aurre egiten dietelako eta zure bezeroei berehala eragiten dietelako +> Erantzuteko denbora: latentziak zure bezeroei eta negozioari zuzenean eragiten dielako. +> Trafikoa: trafikoak errore tasaren hazkundearen testuingurua ulertzen laguntzen dizu, bai eta latentzia ere. +> Saturazioa: zure zerbitzua zeinen "betea" den adierazten du. PUZaren erabilera % 90 bada, zure sistemak trafiko gehiago kudeatu al dezake? … diff --git a/sections/production/monitoring.brazilian-portuguese.md b/sections/production/monitoring.brazilian-portuguese.md index b45947ce3..0b2b4fb7d 100644 --- a/sections/production/monitoring.brazilian-portuguese.md +++ b/sections/production/monitoring.brazilian-portuguese.md @@ -12,25 +12,25 @@ Atingir os recursos avançados exige uma configuração demorada ou a compra de ### Exemplo de monitoramento: painel padrão do AWS cloudwatch. Difícil de extrair métricas na aplicação -![Painel padrão do AWS cloudwatch. Difícil de extrair métricas na aplicação](/assets/images/monitoring1.png) +![Painel padrão do AWS cloudwatch. Difícil de extrair métricas na aplicação](../../assets/images/monitoring1.png)

### Exemplo de monitoramento: painel padrão do StackDriver. Difícil de extrair métricas na aplicação -![Painel padrão do StackDriver. Difícil de extrair métricas na aplicação](/assets/images/monitoring2.jpg) +![Painel padrão do StackDriver. Difícil de extrair métricas na aplicação](../../assets/images/monitoring2.jpg)

### Exemplo de monitoramento: Grafana como camada de interface do usuário que visualiza dados brutos -![Grafana como camada de interface do usuário que visualiza dados brutos](/assets/images/monitoring3.png) +![Grafana como camada de interface do usuário que visualiza dados brutos](../../assets/images/monitoring3.png)

### O que Outros Blogueiros Dizem -Do blog [Rising Stack](http://mubaloo.com/best-practices-deploying-node-js-applications/): +Do blog [Rising Stack](https://blog.risingstack.com/node-js-performance-monitoring-with-prometheus/): > …Recomendamos que você observe esses sinais para todos os seus serviços: > Taxa de erros: porque os erros são enfrentados pelo usuário e afetam imediatamente seus clientes. diff --git a/sections/production/monitoring.chinese.md b/sections/production/monitoring.chinese.md index 9f28a6fe2..c0edcc6f4 100644 --- a/sections/production/monitoring.chinese.md +++ b/sections/production/monitoring.chinese.md @@ -13,24 +13,24 @@ ### 监控示例:AWS cloudwatch默认仪表板。很难提取应用内指标 -![AWS cloudwatch default dashboard. Hard to extract in-app metrics](/assets/images/monitoring1.png) +![AWS cloudwatch default dashboard. Hard to extract in-app metrics](../../assets/images/monitoring1.png)

### 监控示例:StackDriver默认仪表板。很难提取应用内指标 -![StackDriver default dashboard. Hard to extract in-app metrics](/assets/images/monitoring2.jpg) +![StackDriver default dashboard. Hard to extract in-app metrics](../../assets/images/monitoring2.jpg)

### 监控示例:Grafana作为可视化原始数据的UI层 -![Grafana as the UI layer that visualizes raw data](/assets/images/monitoring3.png) +![Grafana as the UI layer that visualizes raw data](../../assets/images/monitoring3.png)

### 其他博主说了什么 - 摘自博客 [Rising Stack](http://mubaloo.com/best-practices-deploying-node-js-applications/): + 摘自博客 [Rising Stack](https://blog.risingstack.com/node-js-performance-monitoring-with-prometheus/): > ...我们建议您为所有服务监听这些信号: > 错误率:因为错误是用户面对的,并立即会影响您的客户。 diff --git a/sections/production/monitoring.french.md b/sections/production/monitoring.french.md new file mode 100644 index 000000000..99ba7f292 --- /dev/null +++ b/sections/production/monitoring.french.md @@ -0,0 +1,39 @@ +# Surveillance ! + +

+ +### Un paragraphe d'explication + +Au niveau le plus élémentaire, la surveillance signifie que vous pouvez facilement identifier quand de mauvaises choses se produisent en production. Par exemple, en étant averti par email ou Slack. Le défi est de choisir le bon ensemble d'outils qui répondra à vos besoins sans vous ruiner. Permettez-moi de vous suggérer de commencer par définir l'ensemble des paramètres de base qui doivent être surveillés pour garantir un état sain - CPU, RAM du serveur, RAM du processus de Node (moins de 1,4 GB), le nombre d'erreurs dans la dernière minute, le nombre de redémarrages du processus , temps de réponse moyen. Ensuite, passez en revue certaines fonctionnalités avancées dont vous pourriez avoir envie et ajoutez-les à votre liste de souhaits. Quelques exemples d'une fonction de surveillance de luxe : profilage de base de données, mesure interservices (c.-à-d. mesurer les transactions commerciales), intégration frontale, exposer les données brutes aux clients BI personnalisés, notifications Slack et bien d'autres. + +La réalisation des fonctionnalités avancées nécessite une configuration longue ou l'achat d'un produit commercial tel que Datadog, newrelic et similaires. Malheureusement, atteindre même les bases n'est pas une promenade de santé car certaines mesures sont liées au matériel (CPU) et d'autres vivent dans le processus de Node (erreurs internes), donc tous les outils simples nécessitent une configuration supplémentaire. Par exemple, les solutions de surveillance des fournisseurs de cloud (par exemple [AWS CloudWatch](https://aws.amazon.com/cloudwatch/), [Google StackDriver](https://cloud.google.com/stackdriver/)) vous informeront immédiatement de la métrique du matériel, mais rien du comportement de l'application interne. À l'autre extrémité, les solutions basées sur les journaux telles que ElasticSearch manquent par défaut de la vue matérielle. La solution consiste à étendre votre choix avec des mesures manquantes, par exemple, un choix populaire consiste à envoyer des journaux d'application à la [pile Elastic](https://www.elastic.co/products) et à configurer un agent supplémentaire (par exemple [Beat](https://www.elastic.co/products)) pour partager des informations liées au matériel pour obtenir une image complète. + +

+ +### Exemple de surveillance : tableau de bord par défaut AWS cloudwatch. Difficile d'extraire des mesures intégrées à l'application + +![Tableau de bord par défaut AWS cloudwatch. Difficile d'extraire des mesures intégrées à l'application](../../assets/images/monitoring1.png) + +

+ +### Exemple de surveillance : tableau de bord par défaut de StackDriver. Difficile d'extraire des mesures intégrées à l'application + +![Tableau de bord par défaut de StackDriver. Difficile d'extraire des mesures intégrées à l'application](../../assets/images/monitoring2.jpg) + +

+ +### Exemple de surveillance : Grafana comme couche d'interface utilisateur qui visualise les données brutes + +![Grafana comme couche d'interface utilisateur qui visualise les données brutes](../../assets/images/monitoring3.png) + +

+ +### Ce que disent les autres blogueurs + +Extrait du blog de [Rising Stack](https://blog.risingstack.com/node-js-performance-monitoring-with-prometheus/) : + +> …Nous vous recommandons de surveiller ces signaux pour tous vos services : +> Taux d'erreur : parce que les erreurs sont confrontées à l'utilisateur et affectent immédiatement vos clients. +> Temps de réponse : car la latence affecte directement vos clients et votre entreprise. +> Débit : le trafic vous aide à comprendre le contexte de l'augmentation des taux d'erreur et de la latence également. +> Saturation : il indique à quel point votre service est « saturé ». Si l'utilisation du processeur est de 90%, votre système peut-il gérer plus de trafic ? … diff --git a/sections/production/monitoring.japanese.md b/sections/production/monitoring.japanese.md index 14599b84e..b7c943718 100644 --- a/sections/production/monitoring.japanese.md +++ b/sections/production/monitoring.japanese.md @@ -12,24 +12,24 @@ ### モニタリング例: AWS cloudwatch のデフォルトダッシュボード。アプリ内メトリクスの抽出が難しい -![AWS cloudwatch のデフォルトダッシュボード。アプリ内メトリクスの抽出が難しい](/assets/images/monitoring1.png) +![AWS cloudwatch のデフォルトダッシュボード。アプリ内メトリクスの抽出が難しい](../../assets/images/monitoring1.png)

### モニタリング例: StackDriver のデフォルトダッシュボード。アプリ内メトリクスの抽出が難しい -![StackDriver のデフォルトダッシュボード。アプリ内メトリクスの抽出が難しい](/assets/images/monitoring2.jpg) +![StackDriver のデフォルトダッシュボード。アプリ内メトリクスの抽出が難しい](../../assets/images/monitoring2.jpg)

### モニタリング例: 生データを可視化するUIレイヤーとしての Grafana -![生データを可視化するUIレイヤーとしての Grafana ](/assets/images/monitoring3.png) +![生データを可視化するUIレイヤーとしての Grafana ](../../assets/images/monitoring3.png)

### 他のブロガーが言っていること -[Rising Stack](http://mubaloo.com/best-practices-deploying-node-js-applications/) のブログより: +[Rising Stack](https://blog.risingstack.com/node-js-performance-monitoring-with-prometheus/) のブログより: > ...すべてのサービスのために、これらの信号を見ることをお勧めします: > エラー率: なぜなら、エラーはユーザーが直面するものであり、すぐに顧客に影響を与えるからです。 diff --git a/sections/production/monitoring.korean.md b/sections/production/monitoring.korean.md index 75b0f753e..8d05329ea 100644 --- a/sections/production/monitoring.korean.md +++ b/sections/production/monitoring.korean.md @@ -12,25 +12,25 @@ Achieving the advanced features demands lengthy setup or buying a commercial pro ### Monitoring example: AWS cloudwatch default dashboard. Hard to extract in-app metrics -![AWS cloudwatch default dashboard. Hard to extract in-app metrics](/assets/images/monitoring1.png) +![AWS cloudwatch default dashboard. Hard to extract in-app metrics](../../assets/images/monitoring1.png)

### Monitoring example: StackDriver default dashboard. Hard to extract in-app metrics -![StackDriver default dashboard. Hard to extract in-app metrics](/assets/images/monitoring2.jpg) +![StackDriver default dashboard. Hard to extract in-app metrics](../../assets/images/monitoring2.jpg)

### Monitoring example: Grafana as the UI layer that visualizes raw data -![Grafana as the UI layer that visualizes raw data](/assets/images/monitoring3.png) +![Grafana as the UI layer that visualizes raw data](../../assets/images/monitoring3.png)

### What Other Bloggers Say -From the blog [Rising Stack](http://mubaloo.com/best-practices-deploying-node-js-applications/): +From the blog [Rising Stack](https://blog.risingstack.com/node-js-performance-monitoring-with-prometheus/): > …We recommend you to watch these signals for all of your services: > Error Rate: Because errors are user facing and immediately affect your customers. diff --git a/sections/production/monitoring.md b/sections/production/monitoring.md index 75b0f753e..8d05329ea 100644 --- a/sections/production/monitoring.md +++ b/sections/production/monitoring.md @@ -12,25 +12,25 @@ Achieving the advanced features demands lengthy setup or buying a commercial pro ### Monitoring example: AWS cloudwatch default dashboard. Hard to extract in-app metrics -![AWS cloudwatch default dashboard. Hard to extract in-app metrics](/assets/images/monitoring1.png) +![AWS cloudwatch default dashboard. Hard to extract in-app metrics](../../assets/images/monitoring1.png)

### Monitoring example: StackDriver default dashboard. Hard to extract in-app metrics -![StackDriver default dashboard. Hard to extract in-app metrics](/assets/images/monitoring2.jpg) +![StackDriver default dashboard. Hard to extract in-app metrics](../../assets/images/monitoring2.jpg)

### Monitoring example: Grafana as the UI layer that visualizes raw data -![Grafana as the UI layer that visualizes raw data](/assets/images/monitoring3.png) +![Grafana as the UI layer that visualizes raw data](../../assets/images/monitoring3.png)

### What Other Bloggers Say -From the blog [Rising Stack](http://mubaloo.com/best-practices-deploying-node-js-applications/): +From the blog [Rising Stack](https://blog.risingstack.com/node-js-performance-monitoring-with-prometheus/): > …We recommend you to watch these signals for all of your services: > Error Rate: Because errors are user facing and immediately affect your customers. diff --git a/sections/production/monitoring.polish.md b/sections/production/monitoring.polish.md index 4cb478e56..c5d39dd74 100644 --- a/sections/production/monitoring.polish.md +++ b/sections/production/monitoring.polish.md @@ -12,25 +12,25 @@ Osiągnięcie zaawansowanych funkcji wymaga długiej konfiguracji lub zakupu kom ### Przykład monitorowania: domyślny pulpit nawigacyjny AWS Cloudwatch. Trudno wyodrębnić dane w aplikacji -![AWS cloudwatch default dashboard. Hard to extract in-app metrics](/assets/images/monitoring1.png) +![AWS cloudwatch default dashboard. Hard to extract in-app metrics](../../assets/images/monitoring1.png)

### Przykład monitorowania: domyślny pulpit nawigacyjny StackDriver. Trudno wyodrębnić dane w aplikacji -![StackDriver default dashboard. Hard to extract in-app metrics](/assets/images/monitoring2.jpg) +![StackDriver default dashboard. Hard to extract in-app metrics](../../assets/images/monitoring2.jpg)

### Przykład monitorowania: Grafana jako warstwa interfejsu użytkownika, która wizualizuje surowe dane -![Grafana as the UI layer that visualizes raw data](/assets/images/monitoring3.png) +![Grafana as the UI layer that visualizes raw data](../../assets/images/monitoring3.png)

### Co mówią inni blogerzy -Z bloga [Rising Stack](http://mubaloo.com/best-practices-deploying-node-js-applications/): +Z bloga [Rising Stack](https://blog.risingstack.com/node-js-performance-monitoring-with-prometheus/): > …We recommend you to watch these signals for all of your services: > Error Rate: Because errors are user facing and immediately affect your customers. diff --git a/sections/production/monitoring.russian.md b/sections/production/monitoring.russian.md index 834ac395f..20b3de311 100644 --- a/sections/production/monitoring.russian.md +++ b/sections/production/monitoring.russian.md @@ -12,25 +12,25 @@ ### Пример мониторинга: панель инструментов AWS cloudwatch по умолчанию. Трудно извлечь метрики в приложении -![AWS cloudwatch default dashboard. Hard to extract in-app metrics](/assets/images/monitoring1.png) +![AWS cloudwatch default dashboard. Hard to extract in-app metrics](../../assets/images/monitoring1.png)

### Пример мониторинга: панель мониторинга по умолчанию для StackDriver. Трудно извлечь метрики в приложении -![StackDriver default dashboard. Hard to extract in-app metrics](/assets/images/monitoring2.jpg) +![StackDriver default dashboard. Hard to extract in-app metrics](../../assets/images/monitoring2.jpg)

### Пример мониторинга: Grafana как слой пользовательского интерфейса, который визуализирует необработанные данные -![Grafana as the UI layer that visualizes raw data](/assets/images/monitoring3.png) +![Grafana as the UI layer that visualizes raw data](../../assets/images/monitoring3.png)

### Что говорят другие блоггеры -Из блога [Rising Stack](http://mubaloo.com/best-practices-deploying-node-js-applications/): +Из блога [Rising Stack](https://blog.risingstack.com/node-js-performance-monitoring-with-prometheus/): > … Мы рекомендуем вам смотреть эти сигналы для всех ваших услуг: > Частота ошибок: потому что ошибки связаны с пользователем и сразу же влияют на ваших клиентов. diff --git a/sections/production/productioncode.basque.md b/sections/production/productioncode.basque.md new file mode 100644 index 000000000..f06216754 --- /dev/null +++ b/sections/production/productioncode.basque.md @@ -0,0 +1,16 @@ +# Neurtu eta zaindu memoriaren erabilera + +

+ +### Azalpena + +Hona hemen produkzioaren mantentzean eta egonkortasunean asko eragiten duten garapen aholkuen zerrenda: + +- Hamabi faktoreen gida: ezagutu [hamabi faktoreen](https://12factor.net/) gida +- Izan aberrigabea: ez gorde daturik tokiko web zerbitzari jakin batean (ikusi buleta bereizia: 'Izan aberrigabea) +- Cachea: erabili asko cachea, baina inoiz ez huts eragin cache ez datorrelako bat +- Probatu memoria: neurtu memoriaren erabilera eta ihesak zure garapen fluxuaren zati gisa; "memwatch" bezalako tresnek asko erraz dezakete zeregin hori +- Izen funtzioak: gutxitu funtzio anonimoen erabilera (hau da, lineako deiak itzultzea), memoria profilatzaile tipiko batek metodoaren izen bakoitzeko memoria erabiliko baitu +- Erabili CI tresnak: erabili CI tresna hutsegiteak antzemateko produkziora bidali aurretik. Adibidez, erabili ESLint erreferentzia erroreak eta zehaztu gabeko aldagaiak antzemateko. Erabili –trace-sync-io API sinkronoak erabiltzen dituen kodea identifikatzeko (bertsio asinkronoaren ordez) +- Erregistratze zentzuzkoa: sartu egunkari adierazpen bakoitzean testuinguruaren informazioa ahal baduzu JSON formatuan, Elastic bezalako erregistroen tresnek propietate horiek bilatu ahal ditzaten (ikusi buleta bereizia 'Areagotu ikusgarritasuna erregistro adimendunak erabiliz'). Gainera, sartu eskaera bakoitza identifikatzen duen eta transakzioa deskribatzen duten lerroak erlazionatzeko aukera ematen duen transakzio IDa (ikusi buleta bereizia: 'Sartu Transakzio IDa') +- Akatsen kudeaketa: erroreen tratamendua Akilesen orpoa da Node.js ekoizpen guneetan. Noderen prozesu asko blokeatzen dira errore txikien ondorioz, beste batzuek bizirik jarraitzen duten bitartean errore egoeran, huts egin beharrean. Oso garrantzitsua da erabakitzea zer estrategia jarraituko duzun erroreak kudeatzeko. Irakurri hemen nire [praktika onak erroreak kudeatzeko](http://goldbergyoni.com/checklist-best-practices-of-node-js-error-handling/) diff --git a/sections/production/productioncode.french.md b/sections/production/productioncode.french.md new file mode 100644 index 000000000..e9e44d09c --- /dev/null +++ b/sections/production/productioncode.french.md @@ -0,0 +1,16 @@ +# Préparez votre code pour la production + +

+ +### Un paragraphe d'explication + +Voici une liste de conseils de développement qui ont un impact important sur la maintenance et la stabilité de la production : + +* Le guide douze facteurs – Familiarisez-vous avec le guide [Douze facteurs](https://12factor.net/fr/) +* Soyez sans état – N'enregistrez aucune donnée localement sur un serveur web spécifique (consultez le point – « Soyez sans état ») +* Mettez en cache – Utilisez beaucoup le cache, mais ne faites jamais échouer en raison de la non-concordance du cache +* Testez la mémoire – Mesurez l'utilisation de la mémoire et les fuites dans le cadre de votre flux de développement, des outils tels que « memwatch » peuvent grandement faciliter cette tâche +* Nommez les fonctions – Minimisez l'utilisation des fonctions anonymes (c'est à dire de fonction de rappel en ligne) car un profileur de mémoire classique fournit l'utilisation de la mémoire avec le nom de la méthode +* Utilisez les outils CI – Utilisez l'outil CI pour détecter les échecs avant d'envoyer en production. Par exemple, utilisez ESLint pour détecter les erreurs de référence et les variables non définies. Utilisez –trace-sync-io pour identifier le code qui utilise des API synchrones (au lieu de la version asynchrone) +* Journalisez à bon escient – Incluez dans le journal des informations contextuelles pour chaque instruction, si possible au format JSON, afin que les outils d'agrégation de journaux tels qu'Elastic puissent rechercher ces propriétés (consultez le point - « Augmentez la clarté à l'aide de la journalisation intelligente »). Incluez également l'ID de transaction qui identifie chaque requête et permet de corréler les lignes qui décrivent la même transaction (consultez le point - « Attribuez un ID de transaction à chaque relevé du journal ») +* Gérez les erreurs – La gestion des erreurs est le talon d'Achille des sites de production de Node.js - de nombreux processus Node se bloquent en raison d'erreurs mineures tandis que d'autres restent en vie dans un état défectueux au lieu de se bloquer. La définition de votre stratégie de traitement des erreurs est absolument essentielle, lisez ici mes [meilleures pratiques de gestion des erreurs](http://goldbergyoni.com/checklist-best-practices-of-node-js-error-handling/) diff --git a/sections/production/productioncode.md b/sections/production/productioncode.md index a86047312..6fb624a6c 100644 --- a/sections/production/productioncode.md +++ b/sections/production/productioncode.md @@ -6,11 +6,12 @@ Following is a list of development tips that greatly affect the production maintenance and stability: -* The twelve-factor guide – Get familiar with the [Twelve factors](https://12factor.net/) guide -* Be stateless – Save no data locally on a specific web server (see separate bullet – ‘Be Stateless’) -* Cache – Utilize cache heavily, yet never fail because of cache mismatch -* Test memory – gauge memory usage and leaks as part your development flow, tools such as ‘memwatch’ can greatly facilitate this task -* Name functions – Minimize the usage of anonymous functions (i.e. inline callback) as a typical memory profiler will provide memory usage per method name -* Use CI tools – Use CI tool to detect failures before sending to production. For example, use ESLint to detect reference errors and undefined variables. Use –trace-sync-io to identify code that uses synchronous APIs (instead of the async version) -* Log wisely – Include in each log statement contextual information, hopefully in JSON format so log aggregators tools such as Elastic can search upon those properties (see separate bullet – ‘Increase visibility using smart logs’). Also, include transaction-id that identifies each request and allows to correlate lines that describe the same transaction (see separate bullet – ‘Include Transaction-ID’) -* Error management – Error handling is the Achilles’ heel of Node.js production sites – many Node processes are crashing because of minor errors while others hang on alive in a faulty state instead of crashing. Setting your error handling strategy is absolutely critical, read here my [error handling best practices](http://goldbergyoni.com/checklist-best-practices-of-node-js-error-handling/) +- The twelve-factor guide – Get familiar with the [Twelve factors](https://12factor.net/) guide +- Be stateless – Save no data locally on a specific web server (see separate bullet – ‘Be Stateless’) +- Cache – Utilize cache heavily, yet never fail because of cache mismatch +- Test memory – gauge memory usage and leaks as part your development flow, tools such as ‘memwatch’ can greatly facilitate this task +- Name functions – Minimize the usage of anonymous functions (i.e. inline callback) as a typical memory profiler will provide memory usage per method name +- Use CI tools – Use CI tool to detect failures before sending to production. For example, use ESLint to detect reference errors and undefined variables. Use –trace-sync-io to identify code that uses synchronous APIs (instead of the async version) +- Log wisely – Include in each log statement contextual information, hopefully in JSON format so log aggregators tools such as Elastic can search upon those properties (see separate bullet – ‘Increase visibility using smart logs’). Also, include transaction-id that identifies each request and allows to correlate lines that describe the same transaction (see separate bullet – ‘Include Transaction-ID’) +- Test like production - Make developers machine quite close to the production infrastructure (e.g., with Docker-Compose). Avoid if/else clauses in testing that check if we're in testing environment but rather run the same code always +- Error management – Error handling is the Achilles’ heel of Node.js production sites – many Node processes are crashing because of minor errors while others hang on alive in a faulty state instead of crashing. Setting your error handling strategy is absolutely critical, read here my [error handling best practices](http://goldbergyoni.com/checklist-best-practices-of-node-js-error-handling/) diff --git a/sections/production/setnodeenv.basque.md b/sections/production/setnodeenv.basque.md new file mode 100644 index 000000000..87d0d9286 --- /dev/null +++ b/sections/production/setnodeenv.basque.md @@ -0,0 +1,35 @@ +# Ezarri NODE_ENV = produkzioa + +

+ +### Azalpena + +Prozesuaren ingurune aldagaiak balio giltzen bikoteen multzo bat dira, eskuarki ezarpenetan erabiltzen direnak eta exekutatzen ari den edozein programatan eskuragarri daudenak. +Edozein aldagai erabil daitekeen arren, Nodek NODE_ENV izeneko aldagaia erabilera bultzatzen du, oraintxe bertan ekoizten ari garen ala ez adierazteko. Determinazio horri esker, osagaiek diagnostiko hobeak egin ditzakete garapenean zehar, adibidez cachea desgaituz edo hitz erregistroen adierazpenak igorriz. Edozein ezarpen tresna modernok (Chef, Puppet, CloudFormation, besteak) inguruneko aldagaiak ezartzea onartzen du hedapenean. + +

+ +### Kode adibidea: NODE_ENV ingurumen aldagaia ezarri eta irakurtzea + +```shell script +// Ingurumen aldagaiak bash-en ezarri node prozesua hasi aurretik +$ NODE_ENV=development +$ node +``` + +```javascript +// Kodea erabiliz ingurumen aldagaia irakurri +if (process.env.NODE_ENV === "production") useCaching = true; +``` + +

+ +### Beste blogari batzuek diotena + +[Dynatrace](https://www.dynatrace.com/blog/the-drastic-effects-of-omitting-node_env-in-your-express-js-applications/) bloga: + +> ...Node.jsk badu uneko modua ezartzean NODE_ENV izeneko aldagaia erabiltzeko konbentzioa. Izan ere, NODE_ENV irakurtzen du eta, konfiguratuta ez badago, 'garapena' ezarpena lehenesten dio. Argi ikusten dugu NODE_ENV ekoizpenean ezartzean, Node.jsk kudea dezakeen eskaera kopurua bi heren inguruko hazkundea duela PUZaren erabilera zertxobait jaisten den bitartean. _Azpimarratu beharra dago NODE_ENV ekoizpenean ezartzeak zure aplikazioa 3 aldiz azkarragoa bihurtzen duela._ + +![NODE_ENV=produkzioa](../../assets/images/setnodeenv1.png "NODE_ENV=produkzioa") + +

diff --git a/sections/production/setnodeenv.brazilian-portuguese.md b/sections/production/setnodeenv.brazilian-portuguese.md index dc0637487..8059ed20b 100644 --- a/sections/production/setnodeenv.brazilian-portuguese.md +++ b/sections/production/setnodeenv.brazilian-portuguese.md @@ -27,6 +27,6 @@ if (process.env.NODE_ENV === “production”) Do blog [dynatrace](https://www.dynatrace.com/blog/the-drastic-effects-of-omitting-node_env-in-your-express-js-applications/): > ...No Node.js há uma convenção para usar uma variável chamada NODE_ENV para definir o modo atual. Vimos que, de fato, NODE_ENV é lida e o padrão é "development", se não estiver definido. Observamos claramente que, configurando NODE_ENV para produção, o número de requisições que o Node.js pode manipular aumenta em cerca de dois terços, enquanto o uso da CPU cai um pouco. Deixe-me enfatizar isso: A configuração NODE_ENV para produção torna sua aplicação 3 vezes mais rápida!* -![NODE_ENV=production](/assets/images/setnodeenv1.png "NODE_ENV=production") +![NODE_ENV=production](../../assets/images/setnodeenv1.png "NODE_ENV=production")

diff --git a/sections/production/setnodeenv.chinese.md b/sections/production/setnodeenv.chinese.md index 0b9251f5b..6666488a7 100644 --- a/sections/production/setnodeenv.chinese.md +++ b/sections/production/setnodeenv.chinese.md @@ -30,7 +30,7 @@ If(process.env.NODE_ENV === “production”) > ...在node.js中有一个约定, 它使用名为NODE_ENV的变量来设置当前工作模式。我们看到它实际上是读取NODE_ENV,如果它没有设置,则默认为“development”。我们清楚的看到,通过设置NODE_ENV为production,node.js可以处理请求的数量可以提高大约三分之二,而CPU的使用率会略有下降。 *让我强调一下:设置NODE_ENV为production可以让你的应用程序快3倍!* -![NODE_ENV=production](/assets/images/setnodeenv1.png "NODE_ENV=production") +![NODE_ENV=production](../../assets/images/setnodeenv1.png "NODE_ENV=production")

diff --git a/sections/production/setnodeenv.french.md b/sections/production/setnodeenv.french.md new file mode 100644 index 000000000..ceb10410a --- /dev/null +++ b/sections/production/setnodeenv.french.md @@ -0,0 +1,34 @@ +# Définissez NODE_ENV = production + +

+ +### Un paragraphe d'explication + +Les variables d'environnement de processus sont un ensemble de paires de clé-valeur mises à la disposition de tout programme en cours d'exécution, généralement à des fins de configuration. Bien que toutes les variables puissent être utilisées, Node encourage d'utiliser par convention une variable appelée NODE_ENV pour signaler si nous sommes en production en ce moment. Cette indication permet aux composants de fournir de meilleurs diagnostics pendant le développement, par exemple en désactivant la mise en cache ou en diffusant des déclarations verbeuses dans le journal. Tout outil de déploiement moderne (Chef, Puppet, CloudFormation, autres) permet de définir des variables d'environnement pendant le déploiement. + +

+ +### Exemple de code : définition et lecture de la variable d'environnement NODE_ENV + +```shell script +// Définition des variables d environnement en bash avant de lancer le processus node +$ NODE_ENV=development +$ node +``` + +```javascript +// Lecture de la variable d'environnement à l'aide d'un code +if (process.env.NODE_ENV === 'production') + useCaching = true; +``` + +

+ +### Ce que disent les autres blogueurs + +Extrait du blog de [dynatrace](https://www.dynatrace.com/blog/the-drastic-effects-of-omitting-node_env-in-your-express-js-applications/) : +> ...Dans Node.js, il y a une convention pour définir le mode actuel, c'est d'utiliser une variable appelée NODE_ENV. Nous constatons qu'en fait, il lit NODE_ENV et se met par défaut en « development » si elle n'est pas définie. Nous voyons clairement qu'en définissant NODE_ENV sur production, le nombre de requêtes que Node.js peut traiter augmente d'environ deux tiers alors que l'utilisation du CPU diminue même légèrement. *Permettez-moi d'insister sur ce point : en mettant NODE_ENV sur production, votre application est 3 fois plus rapide !* + +![NODE_ENV=production](../../assets/images/setnodeenv1.png "NODE_ENV=production") + +

diff --git a/sections/production/setnodeenv.japanese.md b/sections/production/setnodeenv.japanese.md index 318a8e38d..f5ac6219a 100644 --- a/sections/production/setnodeenv.japanese.md +++ b/sections/production/setnodeenv.japanese.md @@ -29,6 +29,6 @@ if (process.env.NODE_ENV === 'production') ブログ [dynatrace](https://www.dynatrace.com/blog/the-drastic-effects-of-omitting-node_env-in-your-express-js-applications/) より: > ...Node.js では、現在のモードを設定するために node_env という変数を使用する慣習があります。実際には NODE_ENV を読み込んで、設定されていない場合は「development」にデフォルトで設定されていることがわかります。NODE_ENV を本番環境に設定することで、Node.js が処理できるリクエスト数が約3分の2に跳ね上がり、CPU の使用率はわずかに低下することが明らかになっています。*これだけは強調しておきます: NODE_ENV を本番環境に設定すると、アプリケーションが3倍速くなります!* -![NODE_ENV=production](/assets/images/setnodeenv1.png "NODE_ENV=production") +![NODE_ENV=production](../../assets/images/setnodeenv1.png "NODE_ENV=production")

diff --git a/sections/production/setnodeenv.korean.md b/sections/production/setnodeenv.korean.md index 31bd6d017..c2ab68c0d 100644 --- a/sections/production/setnodeenv.korean.md +++ b/sections/production/setnodeenv.korean.md @@ -27,6 +27,6 @@ if (process.env.NODE_ENV === “production”) From the blog [dynatrace](https://www.dynatrace.com/blog/the-drastic-effects-of-omitting-node_env-in-your-express-js-applications/): > ...In Node.js there is a convention to use a variable called NODE_ENV to set the current mode. We see that it, in fact, reads NODE_ENV and defaults to ‘development’ if it isn’t set. We clearly see that by setting NODE_ENV to production the number of requests Node.js can handle jumps by around two-thirds while the CPU usage even drops slightly. *Let me emphasize this: Setting NODE_ENV to production makes your application 3 times faster!* -![NODE_ENV=production](/assets/images/setnodeenv1.png "NODE_ENV=production") +![NODE_ENV=production](../../assets/images/setnodeenv1.png "NODE_ENV=production")

diff --git a/sections/production/setnodeenv.md b/sections/production/setnodeenv.md index 4c721fec4..59337b215 100644 --- a/sections/production/setnodeenv.md +++ b/sections/production/setnodeenv.md @@ -29,6 +29,12 @@ if (process.env.NODE_ENV === 'production') From the blog [dynatrace](https://www.dynatrace.com/blog/the-drastic-effects-of-omitting-node_env-in-your-express-js-applications/): > ...In Node.js there is a convention to use a variable called NODE_ENV to set the current mode. We see that it, in fact, reads NODE_ENV and defaults to ‘development’ if it isn’t set. We clearly see that by setting NODE_ENV to production the number of requests Node.js can handle jumps by around two-thirds while the CPU usage even drops slightly. *Let me emphasize this: Setting NODE_ENV to production makes your application 3 times faster!* -![NODE_ENV=production](/assets/images/setnodeenv1.png "NODE_ENV=production") +![NODE_ENV=production](../../assets/images/setnodeenv1.png "NODE_ENV=production") + +

+ + +From the Synk blog [10 best practices to containerize Node.js web applications with Docker](https://snyk.io/blog/10-best-practices-to-containerize-nodejs-web-applications-with-docker/#:~:text=Some%20frameworks%20and,As%20an%20example): +> ...Some frameworks and libraries may only turn on the optimized configuration that is suited to production if that NODE_ENV environment variable is set to production. Putting aside our opinion on whether this is a good or bad practice for frameworks to take, it is important to know this.

diff --git a/sections/production/setnodeenv.polish.md b/sections/production/setnodeenv.polish.md index cdad19cdf..5e5465fe2 100644 --- a/sections/production/setnodeenv.polish.md +++ b/sections/production/setnodeenv.polish.md @@ -29,6 +29,6 @@ if (process.env.NODE_ENV === 'production') Z bloga [dynatrace](https://www.dynatrace.com/blog/the-drastic-effects-of-omitting-node_env-in-your-express-js-applications/): > ...In Node.js there is a convention to use a variable called NODE_ENV to set the current mode. We see that it, in fact, reads NODE_ENV and defaults to ‘development’ if it isn’t set. We clearly see that by setting NODE_ENV to production the number of requests Node.js can handle jumps by around two-thirds while the CPU usage even drops slightly. *Let me emphasize this: Setting NODE_ENV to production makes your application 3 times faster!* -![NODE_ENV=production](/assets/images/setnodeenv1.png "NODE_ENV=production") +![NODE_ENV=production](../../assets/images/setnodeenv1.png "NODE_ENV=production")

diff --git a/sections/production/setnodeenv.russian.md b/sections/production/setnodeenv.russian.md index 30aced098..caa69364e 100644 --- a/sections/production/setnodeenv.russian.md +++ b/sections/production/setnodeenv.russian.md @@ -29,6 +29,6 @@ if (process.env.NODE_ENV === 'production') Из блога [dynatrace](https://www.dynatrace.com/blog/the-drastic-effects-of-omitting-node_env-in-your-express-js-applications/): > ... В Node.js существует соглашение об использовании переменной NODE_ENV для установки текущего режима. Мы видим, что на самом деле он читает NODE_ENV и по умолчанию принимает значение "development", если он не установлен. Мы ясно видим, что установив NODE_ENV в рабочее состояние, количество запросов Node.js может обрабатывать скачки примерно на две трети, в то время как загрузка ЦП даже немного падает. *Позвольте мне подчеркнуть это: установка NODE_ENV в рабочий режим делает ваше приложение в 3 раза быстрее!* -![NODE_ENV=production](/assets/images/setnodeenv1.png "NODE_ENV=production") +![NODE_ENV=production](../../assets/images/setnodeenv1.png "NODE_ENV=production")

diff --git a/sections/production/smartlogging.basque.md b/sections/production/smartlogging.basque.md new file mode 100644 index 000000000..3810526f0 --- /dev/null +++ b/sections/production/smartlogging.basque.md @@ -0,0 +1,41 @@ +# Gardentasuna handitu erregistratze plataforma adimendunak erabiliz + +

+ +### Azalpena + +Erregistroen adierazpenak inprimatzen dituzu eta, jakina, produkzioari buruzko informazioa biltzen duen interfazearen beharra duzu, erroreen eta oinarrizko metriken jarraipena egiteko (adibidez, zenbat errore gertatzen diren orduoro eta zein den APIaren amaierako puntu motelena). Hori horrela izanik, zergatik ez duzu ahalegin neurritsua egiten laukitxo guztiak markatuko dituen erregistro esparru sendo batean? Hori lortzeko, gogoeta egin eta erabakia hiru urratsetan hartu behar duzu: + +**1. Erregistro adimenduna:** gutxi-gutxienez [Winston](https://github.com/winstonjs/winston), [Bunyan](https://github.com/trentm/node-bunyan) bezalako erregistro liburutegi entzutetsuren bat erabili behar duzu eta transakzio bakoitzaren hasieran eta amaieran informazio esanguratsua idatzi. Pentsatu ez ote den komeni, eragiketa taldeak eremu horietan jardun dezan, erregistro adierazpenak JSON gisa formateatzea eta testuinguruaren propietate guztiak eskaintzea (adibidez, erabiltzailearen IDa, eragiketa mota, etab.). Sartu transakzio ID bakarra erregistro lerro bakoitzean. Informazio gehiago nahi izanez gero, idatzi "Idatzi transakzio id-a erregistroan" azpian dagoen bulletean. Azkenik, kontuan hartu behar da ez ote den komeni sistemaren baliabideak erregistratuko dituen eragileren bat (memoria, adibidez) eta PUZa (Elastic Beat, esaterako) sartzea. + +**2. Agregazio adimenduna:** zure zerbitzariaren fitxategi sisteman informazio zabala eskuratu duzunean, garaia da aldizka datu horiek agregatu, erraztu eta bistaratzen dituen sistema batera bultzatzeko. Pila elastikoa, adibidez, oso aukera popularra eta ezaguna da, datuak bildu eta bistaratzeko osagai guztiak eskaintzen dituena. Produktu komertzial askok antzeko funtzionalitatea eskaintzen dute, baina konfigurazio denbora asko murrizten dute eta ez dute ostatatu beharrik. + +**3. Bistaratze adimenduna:** orain informazioa batu eta bila daiteke; bat pozik egon daiteke erregistroak erraz bilatzeko ahalmena duelako bakarrik; baina hori askoz ere gehiago lor daiteke kodetu beharrik izan gabe edo ahalegin handirik egin gabe. Orain metrika operatibo garrantzitsuak erakusteko moduan gaude: hala nola, errore tasa, batez besteko PUZa egunean zehar, zenbat erabiltzaile berri sartu diren azken orduan eta gure aplikazioa gobernatzen eta hobetzen laguntzen duen beste edozein metrika. + +

+ +### Bistaratze adibidea: Kibana-k (Elastic stack-en zati bat) erregistroen edukian bilaketa aurreratua errazten du + +![Kibana-k (Elastic stack-en zati bat) erregistroen edukian bilaketa aurreratua errazten du](../../assets/images/smartlogging1.png "Kibana-k (Elastic stack-en zati bat) erregistroen edukian bilaketa aurreratua errazten du") + +

+ +### Bistaratze adibidea: Kibana-k (Elastic stack-eko zati bat) erregistroetan oinarritutako datuak bistaratzen ditu + +![Kibana-k (Elastic stack-eko zati bat) erregistroetan oinarritutako datuak bistaratzen ditu](../../assets/images/smartlogging2.jpg "Kibana-k (Elastic stack-eko zati bat) erregistroetan oinarritutako datuak bistaratzen ditu") + +

+ +### Blogeko aipua: erregistroaren eskakizunak + +[Strong Loop](https://strongloop.com/strongblog/compare-node-js-logging-winston-bunyan/) bloga + +> Hona hemen jarraibide batzuk (erregistratzaile batentzat): +> +> 1. Erregistro lerro bakoitzeko denbora marka. Hau nahiko argia da, erregistro sarrera bakoitza noiz gertatu den jakin beharko zenuke. +> 2. Gizakiek nahiz makinek erraz uler dezakete Erregistro formatua. +> 3. Konfiguragarriak diren hainbat helmuga fluxu izateko aukera ematen du. Adibidez, erroreren bat gertatzen bada jarraipen erregistroak idazten ari zarenean fitxategi batean, lehenengo idatzi fitxategi horretan eta gero errore fitxategian, eta bidali mezu elektronikoa aldi berean ... + +

+ +

diff --git a/sections/production/smartlogging.brazilian-portuguese.md b/sections/production/smartlogging.brazilian-portuguese.md index d1ccbaac4..02c88711f 100644 --- a/sections/production/smartlogging.brazilian-portuguese.md +++ b/sections/production/smartlogging.brazilian-portuguese.md @@ -16,13 +16,13 @@ Já que você imprime declarações de log de qualquer maneira e obviamente prec ### Exemplo de visualização: Kibana (parte do stack Elastic) facilita a pesquisa avançada no conteúdo do log -![Kibana facilita a pesquisa avançada no conteúdo do log](/assets/images/smartlogging1.png "Kibana facilita a pesquisa avançada no conteúdo do log") +![Kibana facilita a pesquisa avançada no conteúdo do log](../../assets/images/smartlogging1.png "Kibana facilita a pesquisa avançada no conteúdo do log")

### Exemplo de visualização: Kibana (parte do stack Elastic) visualiza dados com base em logs -![Kibana visualiza dados com base em logs](/assets/images/smartlogging2.jpg "Kibana visualiza dados com base em logs") +![Kibana visualiza dados com base em logs](../../assets/images/smartlogging2.jpg "Kibana visualiza dados com base em logs")

diff --git a/sections/production/smartlogging.chinese.md b/sections/production/smartlogging.chinese.md index 6824835aa..9bd9ced11 100644 --- a/sections/production/smartlogging.chinese.md +++ b/sections/production/smartlogging.chinese.md @@ -17,12 +17,12 @@ ### 可视化示例: Kibana(Elastic stack的一部分)促进了对日志内容的高级搜索 -![Kibana facilitates advanced searching on log content](/assets/images/smartlogging1.png "Kibana facilitates advanced searching on log content") +![Kibana facilitates advanced searching on log content](../../assets/images/smartlogging1.png "Kibana facilitates advanced searching on log content")

### 可视化示例: Kibana(Elastic stack的一部分)基于日志来可视化数据 -![Kibana visualizes data based on logs](/assets/images/smartlogging2.jpg "Kibana visualizes data based on logs") +![Kibana visualizes data based on logs](../../assets/images/smartlogging2.jpg "Kibana visualizes data based on logs")

diff --git a/sections/production/smartlogging.french.md b/sections/production/smartlogging.french.md new file mode 100644 index 000000000..ff1fbe0d3 --- /dev/null +++ b/sections/production/smartlogging.french.md @@ -0,0 +1,40 @@ +# Rendez votre application plus claire à l'aide de journaux intelligents + +

+ +### Un paragraphe d'explication + +Puisque vous produisez de toute façon des relevés de log et que vous avez manifestement besoin d'une interface qui regroupe les informations de production et qui vous permette de suivre les erreurs et les mesures de base (par exemple, combien d'erreurs se produisent chaque heure ? Quel est le point de terminaison de votre API le plus lent ?), pourquoi ne pas investir un effort modéré dans un framework robuste de log qui cochera toutes les cases ? Pour y parvenir, il faut prendre une décision réfléchie en trois étapes : + +**1. enregistrement intelligent** – au minimum, vous devez utiliser une bibliothèque de journalisation réputée comme [Winston](https://github.com/winstonjs/winston), [Bunyan](https://github.com/trentm/node-bunyan) et écrire des informations significatives à chaque début et fin de transaction. Pensez également à formater les relevés du journal en JSON et à fournir toutes les propriétés contextuelles (par exemple, l'ID utilisateur, le type d'opération, etc.) afin que l'équipe d'exploitation puisse agir sur ces champs. Incluez également un ID de transaction unique sur chaque ligne de journal, pour plus d'informations, reportez-vous à l'un des points suivants « Attribuez un ID de transaction à chaque relevé du journal ». Un dernier point à considérer, c'est également d'inclure un agent qui enregistre les ressources système de la mémoire et du processeur comme Elastic Beat. + +**2. agrégation intelligente** – une fois que vous disposez d'informations complètes sur le système de fichiers de votre serveur, il est temps de les pousser périodiquement vers un système qui agrège, facilite et visualise ces données. Elastic stack, par exemple, est un choix populaire et gratuit qui offre tous les composants pour agréger et visualiser les données. De nombreux produits commerciaux offrent des fonctionnalités similaires, mais ils réduisent considérablement le temps d'installation et ne nécessitent pas d'hébergement. + +**3. visualisation intelligente** – maintenant que l'information est agrégée et consultable, on ne peut être que satisfait de la puissance d'une recherche facile dans les logs mais cela peut aller beaucoup plus loin sans codage ni effort. Nous pouvons maintenant afficher d'importantes mesures opérationnelles comme le taux d'erreur, le CPU moyen au cours de la journée, le nombre de nouveaux utilisateurs qui se sont inscrits au cours de la dernière heure et toute autre mesure qui aide à gérer et à améliorer notre application. + +

+ +### Exemple de visualisation : Kibana (faisant partie de Elastic stack) facilite la recherche avancée sur le contenu des journaux + +![Kibana facilite la recherche avancée sur le contenu des journaux](../../assets/images/smartlogging1.png "Kibana facilite la recherche avancée sur le contenu des journaux") + +

+ +### Exemple de visualisation : Kibana (qui fait partie de Elastic stack) visualise les données sur la base des journaux + +![Kibana visualise les données sur la base des journaux](../../assets/images/smartlogging2.jpg "Kibana visualise les données sur la base des journaux") + +

+ +### Citation de blog : « Exigences pour un enregistreur de journal » + +Extrait du blog [Strong Loop](https://strongloop.com/strongblog/compare-node-js-logging-winston-bunyan/) : + +> Permet d'identifier quelques exigences (pour un outil de journalisation) : +1. Chaque ligne du journal est horodatée. Celle-ci est assez explicite - vous devriez pouvoir dire quand chaque entrée du journal s'est produite. +2. Le format d'enregistrement doit être facilement assimilable par les humains ainsi que par les machines. +3. Permet plusieurs flux de destination configurables. Par exemple, vous pouvez écrire des journaux de trace dans un fichier, mais lorsqu'une erreur se produit, cela écrit dans le même fichier, puis dans le fichier d'erreur et envoi un e-mail en même temps… + +

+ +

diff --git a/sections/production/smartlogging.japanese.md b/sections/production/smartlogging.japanese.md index 30a1cd3cc..7ae0e2fe0 100644 --- a/sections/production/smartlogging.japanese.md +++ b/sections/production/smartlogging.japanese.md @@ -16,13 +16,13 @@ ### 可視化の例: Kibana (Elastic stack の一部) はログコンテンツの高度な検索を容易にします -![Kibana はログコンテンツの高度な検索を容易にします](/assets/images/smartlogging1.png "Kibana はログコンテンツの高度な検索を容易にします") +![Kibana はログコンテンツの高度な検索を容易にします](../../assets/images/smartlogging1.png "Kibana はログコンテンツの高度な検索を容易にします")

### 可視化の例: Kibana (Elastic stack の一部) はログに基づいてデータを可視化します -![Kibana はログを元にデータを可視化する](/assets/images/smartlogging2.jpg "Kibana はログを元にデータを可視化する") +![Kibana はログを元にデータを可視化する](../../assets/images/smartlogging2.jpg "Kibana はログを元にデータを可視化する")

diff --git a/sections/production/smartlogging.korean.md b/sections/production/smartlogging.korean.md index bcb7bc4af..6983967e7 100644 --- a/sections/production/smartlogging.korean.md +++ b/sections/production/smartlogging.korean.md @@ -16,13 +16,13 @@ Since you print out log statements anyway and you're obviously in a need of some ### Visualization Example: Kibana (part of the Elastic stack) facilitates advanced searching on log content -![Kibana facilitates advanced searching on log content](/assets/images/smartlogging1.png "Kibana facilitates advanced searching on log content") +![Kibana facilitates advanced searching on log content](../../assets/images/smartlogging1.png "Kibana facilitates advanced searching on log content")

### Visualization Example: Kibana (part of the Elastic stack) visualizes data based on logs -![Kibana visualizes data based on logs](/assets/images/smartlogging2.jpg "Kibana visualizes data based on logs") +![Kibana visualizes data based on logs](../../assets/images/smartlogging2.jpg "Kibana visualizes data based on logs")

diff --git a/sections/production/smartlogging.md b/sections/production/smartlogging.md index 5a8161e3e..b67db66a9 100644 --- a/sections/production/smartlogging.md +++ b/sections/production/smartlogging.md @@ -16,13 +16,13 @@ Since you print out log statements anyway and you're obviously in a need of some ### Visualization Example: Kibana (part of the Elastic stack) facilitates advanced searching on log content -![Kibana facilitates advanced searching on log content](/assets/images/smartlogging1.png "Kibana facilitates advanced searching on log content") +![Kibana facilitates advanced searching on log content](../../assets/images/smartlogging1.png "Kibana facilitates advanced searching on log content")

### Visualization Example: Kibana (part of the Elastic stack) visualizes data based on logs -![Kibana visualizes data based on logs](/assets/images/smartlogging2.jpg "Kibana visualizes data based on logs") +![Kibana visualizes data based on logs](../../assets/images/smartlogging2.jpg "Kibana visualizes data based on logs")

diff --git a/sections/production/smartlogging.polish.md b/sections/production/smartlogging.polish.md index 6c82faa98..72f600c78 100644 --- a/sections/production/smartlogging.polish.md +++ b/sections/production/smartlogging.polish.md @@ -16,13 +16,13 @@ Ponieważ i tak drukujesz instrukcje dziennika i oczywiście potrzebujesz interf ### Przykład wizualizacji: Kibana (część Elastic stack) ułatwia zaawansowane wyszukiwanie zawartości dziennika -![Kibana facilitates advanced searching on log content](/assets/images/smartlogging1.png "Kibana facilitates advanced searching on log content") +![Kibana facilitates advanced searching on log content](../../assets/images/smartlogging1.png "Kibana facilitates advanced searching on log content")

### Przykład wizualizacji: Kibana (część Elastic stack) wizualizuje dane na podstawie logów -![Kibana visualizes data based on logs](/assets/images/smartlogging2.jpg "Kibana visualizes data based on logs") +![Kibana visualizes data based on logs](../../assets/images/smartlogging2.jpg "Kibana visualizes data based on logs")

diff --git a/sections/production/smartlogging.russian.md b/sections/production/smartlogging.russian.md index ca2f0046a..4f7bd482f 100644 --- a/sections/production/smartlogging.russian.md +++ b/sections/production/smartlogging.russian.md @@ -16,13 +16,13 @@ ### Пример визуализации: Kibana (часть стека Elastic) облегчает расширенный поиск по содержимому журнала -![Kibana facilitates advanced searching on log content](/assets/images/smartlogging1.png "Kibana facilitates advanced searching on log content") +![Kibana facilitates advanced searching on log content](../../assets/images/smartlogging1.png "Kibana facilitates advanced searching on log content")

### Пример визуализации: Kibana (часть стека Elastic) визуализирует данные на основе журналов -![Kibana visualizes data based on logs](/assets/images/smartlogging2.jpg "Kibana visualizes data based on logs") +![Kibana visualizes data based on logs](../../assets/images/smartlogging2.jpg "Kibana visualizes data based on logs")

diff --git a/sections/production/utilizecpu.basque.md b/sections/production/utilizecpu.basque.md new file mode 100644 index 000000000..17bae37de --- /dev/null +++ b/sections/production/utilizecpu.basque.md @@ -0,0 +1,31 @@ +# Erabili PUZeko nukleo guztiak + +

+ +### Azalpena + +Agian ez da harritzekoa Nodek, bere oinarrizko forman, hari bakarra = prozesu bakarra = PUZ bakarra exekutatzea. 4 edo 8 PUZeko hardware sendoa ordaintzea eta bakarra erabiltzea zoragarria da, ezta? Node Cluster modulua da tamaina ertaineko aplikazioetara egokitzen den irtenbiderik azkarrena. 10 kode lerrotan nukleo logiko bakoitzerako prozesua sortzen du eta prozesuen arteko eskaerak biribilgune estiloan (round-robin) bideratzen ditu. Are hobe, erabili PM2, izan ere, monitoretzako erabiltzailearen interfaze soil eta ezin hobearekin biltzen baitu kluster modulua. Soluzio horrek ohiko aplikazioetan ondo funtzionatzen duen arren, gerta liteke eskas ibiltzea goi mailako errendimendua eta DevOps fluxu sendoa eskatzen duten aplikazioetan. Erabilera aurreratuetarako, aztertu ez ote zaizun komeni Node prozesua erreplikatzea pertsonalizatutako inplementazioko scripten baten bidez, eta orekatzea nginx bezalako tresna espezializatuak erabiliz; edo, bestela, erabili AWS ECS edo Kubernetees bezalako edukiontzi motorren bat prozesuak inplementatzeko eta erreplikatzeko, oso ezaugarri aurreratuak dituzte eta. + +Erabilera aurreratuen kasuetarako, pentsa ezazu NODE prozesua errepikatzea pertsonalizatutako inplementazioko scriptaren bidez eta orekatu nginx bezalako tresna espezializatua erabiliz edo erabili edukiontzi motorra, hala nola AWS ECS edo Kubernetees, prozesuak inplementatzeko eta erreplikatzeko ezaugarri aurreratuak dituztenak. + +

+ +### Alderaketa: Noderen klusterra versus nginx + +![Noderen klusterra versus nginx](../../assets/images/utilizecpucores1.png "Noderen klusterra versus nginx") + +

+ +### Beste blogari batzuek diotena + +- [Node.jsren dokumentazioa](https://nodejs.org/api/cluster.html#cluster_how_it_works): + +> ... Bigarren planteamendua, teorian Node klusterrak eman beharko luke errendimendu onena. Praktikan, ordea, banaketa oso desorekatua izan ohi da sistema eragilearen antolatzaileen gorabeheren ondorioz. Atzeman da hainbat kasutan konexio guztien % 70a baino gehiago kargak bi prozesutan soilik egin direla, zortzitan egin beharrean... + +- [StrongLoop](https://strongloop.com/strongblog/best-practices-for-express-in-production-part-two-performance-and-reliability/) bloga: + +> ... Noderen kluster moduluarekin posible da klusterrak batzea. Horrek ahalbidetzen du prozesu maisu batek lan prozesuak sortzea eta sarrerako konexioak langileen artean banatzea. Hala ere, modulu hori zuzenean erabiltzea baino hobe da lan hori automatikoki egiten duten tresna ugarietako bat erabiltzea; adibidez, node-pm edo cluster-service ... + +- Medium blogeko [Node.js process load balance performance: comparing cluster module, iptables, and Nginx](https://medium.com/@fermads/node-js-process-load-balancing-comparing-cluster-iptables-and-nginx-6746aaf38272) artikulua: + +> ... Noderen klusterra erraza da inplementatzen eta konfiguratzen. Izan ere, osagaiak Noderen eremuan gordetzen dira beste software baten menpe egon gabe. Gogoratu zure prozesu nagusiak zure langile prozesuak bezainbeste funtzionatuko duela, eta bere eskaera tasa beste irtenbideena baino apur bat txikiagoa izango dela ... diff --git a/sections/production/utilizecpu.brazilian-portuguese.md b/sections/production/utilizecpu.brazilian-portuguese.md index 910b7278d..e1df7b19c 100644 --- a/sections/production/utilizecpu.brazilian-portuguese.md +++ b/sections/production/utilizecpu.brazilian-portuguese.md @@ -10,7 +10,7 @@ Pode não ser uma surpresa que, em sua forma básica, o Node seja executado em u ### Comparação: balanceamento usando o cluster do Node versus o nginx -![Balanceamento usando o cluster do Node versus o nginx](/assets/images/utilizecpucores1.png "Balanceamento usando o cluster do Node versus o nginx") +![Balanceamento usando o cluster do Node versus o nginx](../../assets/images/utilizecpucores1.png "Balanceamento usando o cluster do Node versus o nginx")

diff --git a/sections/production/utilizecpu.chinese.md b/sections/production/utilizecpu.chinese.md index 027a459af..9255adbb4 100644 --- a/sections/production/utilizecpu.chinese.md +++ b/sections/production/utilizecpu.chinese.md @@ -13,7 +13,7 @@ ### 比较:使用Node的clustre vs nginx做负载均衡 -![Balancing using Node’s cluster vs nginx](/assets/images/utilizecpucores1.png "Balancing using Node’s cluster vs nginx") +![Balancing using Node’s cluster vs nginx](../../assets/images/utilizecpucores1.png "Balancing using Node’s cluster vs nginx")

diff --git a/sections/production/utilizecpu.french.md b/sections/production/utilizecpu.french.md new file mode 100644 index 000000000..695631f50 --- /dev/null +++ b/sections/production/utilizecpu.french.md @@ -0,0 +1,26 @@ +# Utilisez tous les cœurs du CPU + +

+ +### Un paragraphe d'explication + +Il n'est pas surprenant que dans sa forme de base, Node fonctionne sur un unique thread=un unique processus=un seul CPU. Payer pour du matériel costaud avec 4 ou 8 CPU et n'en utiliser qu'un seul semble fou, non ? La solution la plus rapide qui convient aux applications de taille moyenne est l'utilisation du module Cluster de Node qui, en 10 lignes de code, génère un processus pour chaque cœur logique et achemine les requêtes entre les processus dans un style à tour de rôle. Mieux encore, utilisez PM2 qui enrobe le module de clustering avec une interface simple et une interface utilisateur de surveillance sympa. Bien que cette solution fonctionne bien pour les applications traditionnelles, elle pourrait ne pas convenir aux applications qui exigent des performances de premier ordre et un flux DevOps robuste. Pour ces cas d'utilisation avancés, envisagez de répliquer le processus NODE à l'aide d'un script de déploiement personnalisé et d'équilibrage (NdT, « balancing ») en utilisant un outil spécialisé tel que nginx ou utilisez un moteur de conteneur tel que AWS ECS ou Kubernetees qui disposent de fonctionnalités avancées pour le déploiement et la réplication des processus. + +

+ +### Comparaison : équilibrage à l'aide du cluster de Node vs nginx + +![Équilibrage à l'aide du cluster de Node vs nginx](../../assets/images/utilizecpucores1.png "Équilibrage à l'aide du cluster de Node vs nginx") + +

+ +### Ce que disent les autres blogueurs + +* Extrait de la [documentation de Node.js](https://nodejs.org/api/cluster.html#cluster_how_it_works): +> ... La seconde approche, les clusters de Node, devrait, en théorie, donner les meilleures performances. Dans la pratique, cependant, la distribution a tendance à être très déséquilibrée en raison des aléas du planificateur du système d'exploitation. Des charges ont été observées où plus de 70% de toutes les connexions se sont uniquement terminées sur deux processus, sur un total de huit ... + +* Extrait du blog de [StrongLoop](https://strongloop.com/strongblog/best-practices-for-express-in-production-part-two-performance-and-reliability/): +> ... Le clustering est rendu possible avec le module de cluster de Node. Cela permet à un processus maître de générer des processus de travail et de répartir les connexions entrantes entre les processus de travail. Cependant, plutôt que d'utiliser directement ce module, il est préférable d'utiliser l'un des nombreux outils qui le font automatiquement pour vous; par exemple node-pm ou cluster-service ... + +* Extrait de l'article [Performance de l'équilibre de charge du processus Node.js : comparaison entre le module de cluster, iptables et Nginx](https://medium.com/@fermads/node-js-process-load-balancing-comparing-cluster-iptables-and-nginx-6746aaf38272) de Medium +> ... Le cluster Node est simple à implémenter et à configurer, les choses sont conservées dans le domaine Node sans dépendre d'autres logiciels. N'oubliez pas que votre processus maître fonctionnera presque autant que vos processus de travail et avec un peu moins de taux de requête que les autres solutions. ... diff --git a/sections/production/utilizecpu.japanese.md b/sections/production/utilizecpu.japanese.md index e96f90521..74874a23c 100644 --- a/sections/production/utilizecpu.japanese.md +++ b/sections/production/utilizecpu.japanese.md @@ -10,7 +10,7 @@ ### 比較: Node クラスタと nginx それぞれを使ったバランシング -![バランシングの比較 Node クラスタ vs nginx](/assets/images/utilizecpucores1.png "バランシングの比較 Node クラスタ vs nginx") +![バランシングの比較 Node クラスタ vs nginx](../../assets/images/utilizecpucores1.png "バランシングの比較 Node クラスタ vs nginx")

diff --git a/sections/production/utilizecpu.korean.md b/sections/production/utilizecpu.korean.md index 301a0fc78..5c18f204d 100644 --- a/sections/production/utilizecpu.korean.md +++ b/sections/production/utilizecpu.korean.md @@ -10,7 +10,7 @@ It might not come as a surprise that in its basic form, Node runs over a single ### Comparison: Balancing using Node’s cluster vs nginx -![Balancing using Node’s cluster vs nginx](/assets/images/utilizecpucores1.png "Balancing using Node’s cluster vs nginx") +![Balancing using Node’s cluster vs nginx](../../assets/images/utilizecpucores1.png "Balancing using Node’s cluster vs nginx")

diff --git a/sections/production/utilizecpu.md b/sections/production/utilizecpu.md index 301a0fc78..5c18f204d 100644 --- a/sections/production/utilizecpu.md +++ b/sections/production/utilizecpu.md @@ -10,7 +10,7 @@ It might not come as a surprise that in its basic form, Node runs over a single ### Comparison: Balancing using Node’s cluster vs nginx -![Balancing using Node’s cluster vs nginx](/assets/images/utilizecpucores1.png "Balancing using Node’s cluster vs nginx") +![Balancing using Node’s cluster vs nginx](../../assets/images/utilizecpucores1.png "Balancing using Node’s cluster vs nginx")

diff --git a/sections/production/utilizecpu.polish.md b/sections/production/utilizecpu.polish.md index c75984962..19f706ac8 100644 --- a/sections/production/utilizecpu.polish.md +++ b/sections/production/utilizecpu.polish.md @@ -10,7 +10,7 @@ Nic dziwnego, że w swojej podstawowej formie Node działa na jednym wątku = po ### Porównanie: równoważenie za pomocą Node cluster vs nginx -![Balancing using Node’s cluster vs nginx](/assets/images/utilizecpucores1.png "Balancing using Node’s cluster vs nginx") +![Balancing using Node’s cluster vs nginx](../../assets/images/utilizecpucores1.png "Balancing using Node’s cluster vs nginx")

diff --git a/sections/production/utilizecpu.russian.md b/sections/production/utilizecpu.russian.md index c6213998d..866afb499 100644 --- a/sections/production/utilizecpu.russian.md +++ b/sections/production/utilizecpu.russian.md @@ -10,7 +10,7 @@ ### Сравнение: балансировка с использованием кластера Node против nginx -![Balancing using Node’s cluster vs nginx](/assets/images/utilizecpucores1.png "Balancing using Node’s cluster vs nginx") +![Balancing using Node’s cluster vs nginx](../../assets/images/utilizecpucores1.png "Balancing using Node’s cluster vs nginx")

diff --git a/sections/projectstructre/breakintcomponents.basque.md b/sections/projectstructre/breakintcomponents.basque.md index 0b3124a49..a5483d82d 100644 --- a/sections/projectstructre/breakintcomponents.basque.md +++ b/sections/projectstructre/breakintcomponents.basque.md @@ -2,21 +2,21 @@

-### Azalpen paragrafoa +### Azalpena -Tamaina ertaineko nahiz handiko aplikazioetarako, monolitoak benetan kaltegarriak dira. Menpekotasun asko dituen software handi bat edukitzea zaila da hausnartzeko eta maiz espageti kodea eragiten du. Arkitektu azkarrek ere, piztia mantsotzeko eta zatikatzeko haina gaitasun dituztenek, diseinuan esfortzu mental handiak egiten dituzte, eta aldaketa bakoitzak menpeko beste objektuekiko eragina arretaz aztertzea eskatzen du. Azken irtebidea software txikia garatzean datza: banandu kode pila osoa fitxategiak beste inorekin partekatzen ez dituzten aparteko osagaietan, bakoitza fitxategi gutxi batzuekin osatua egonik (APIa, zerbitzuak, datuen sarbidea, egiaztatzeak, etab.) oso erraza da hausnartzeko. Askok 'mikrozerbitzu' egitura deitzen diote horri, garrantzitsua da ulertzea mikrozerbitzuak oinarri sorta bat direla eta ez derrigorrez jarraitu beharreko zehaztapenak. Printzipio ugari erabil ditzakezu mikrozerbitzudun egitura handi batean edota gutxi batzuk soilik. Biak dira zuzenak zure softwarearen konplexutasuna baxua den bitartean. Gutxienez, egin zenezakeen beste zerbait da osagaien artean oinarrizko mugak sortzea, zure proiektuaren erroan karpeta bat egokitzea osagai logiko bakoitzarentzat eta autonono bihurtzea: beste osagaiek haren funtzionalitatea erabili ahal izango dute soilik bere interfaze publikotik edo APItik pasatuz. Hau oinarrizkoa da zure osagaiak sinpleak izateko, menpekotasunen korapiloa ekiditeko eta zure aplikazioa mikrozerbitzu egitura handietarako prestatzeko. +Tamaina ertaineko nahiz handiko aplikazioetarako, monolitoak benetan kaltegarriak dira. Menpekotasun asko dituen software handi bat edukitzea zaila da hausnartzeko eta maiz espageti kodea eragiten du. Arkitekto azkarrek ere, piztia mantsotzeko eta zatikatzeko haina gaitasun dituztenek, diseinuan esfortzu mental handiak egiten dituzte, eta aldaketa bakoitzak menpeko beste objektuekiko eragina arretaz aztertzea eskatzen du. Azken irtenbidea software txikia garatzean datza: banandu kode pila osoa fitxategiak beste inorekin partekatzen ez dituzten aparteko osagaietan, bakoitza fitxategi gutxi batzuekin osatua egonik (APIa, zerbitzuak, datuen sarbidea, egiaztatzeak, etab.) oso erraza da hausnartzeko. Askok 'mikrozerbitzu' egitura deitzen diote horri, garrantzitsua da ulertzea mikrozerbitzuak oinarri sorta bat direla eta ez derrigorrez jarraitu beharreko zehaztapenak. Printzipio ugari erabil ditzakezu mikrozerbitzudun egitura handi batean edota gutxi batzuk soilik. Biak dira zuzenak zure softwarearen konplexutasuna baxua den bitartean. Gutxienez, egin zenezakeen beste zerbait da osagaien artean oinarrizko mugak sortzea, zure proiektuaren erroan karpeta bat egokitzea osagai logiko bakoitzarentzat eta autonono bihurtzea: beste osagaiek haren funtzionalitatea erabili ahal izango dute soilik bere interfaze publikotik edo APItik pasatuz. Hori oinarrizkoa da zure osagaiak sinpleak izateko, menpekotasunen korapiloa ekiditeko eta zure aplikazioa mikrozerbitzu egitura handietarako prestatzeko.

-### Blogeko aipua: "Eskalatzeak aplikazio osoaren eskalatzea eskatzen du" +### Blog aipua: "Eskalatzeak aplikazio osoaren eskalatzea eskatzen du" -MartinFowler.com blogetik hartua +[MartinFowler.com](https://martinfowler.com/articles/microservices.html) bloga -> Aplikazio monolitikoak arrakastatsuak izan daitezke, baina jendeak gero eta frustrazio gehiago ditu beraiekin, batez ere gero eta aplikazio gehiago inplementatzen direlako lainoan. Aldaketa zikloak elkarrekin lotuta daude: aplikazioaren zati txiki batean egindako aldaketak monolito osoa bersortzea eta inplementatzea eskatzen du. Askotan zaila da denbora aurrera joan ahala moduluzko egitura egokia mantentzea, modulu batean bakarrik eragina izango dituzten aldaketak mantentzea. Eskalatzeak aplikazio osoaren eskalatzea eskatzen du +> Aplikazio monolitikoak arrakastatsuak izan daitezke, baina jendeak gero eta frustrazio gehiago ditu beraiekin, batez ere gero eta aplikazio gehiago inplementatzen direlako lainoan. Aldaketa zikloak elkarrekin lotuta daude: aplikazioaren zati txiki batean egindako aldaketak monolito osoa birsortzea eta inplementatzea eskatzen du. Askotan zaila da denbora aurrera joan ahala moduluzko egitura egokia mantentzea, modulu batean bakarrik eragina izango dituzten aldaketak mantentzea. Eskalatzeak aplikazio osoaren eskalatzea eskatzen du

-### Blogeko aipua: "Zergatik egiten du garrasi zure aplikazioaren egiturak?" +### Blog aipua: "Zergatik egiten du garrasi zure aplikazioaren egiturak?" -[uncle-bob](https://8thlight.com/blog/uncle-bob/2011/09/30/Screaming-Architecture.html) blogetik hartua +[uncle-bob](https://blog.cleancoder.com/uncle-bob/2011/09/30/Screaming-Architecture.html) bloga > ...Liburutegi baten egitura begiratuko bazenu, ziurrenik sarrera handi batekin aurkituko zinateke, erregistro bulego lekuekin, irakurketa lekuekin, biltzar toki txikiekin, eta liburutegiko liburu guztiak edukitzeko beste apal dituzten galeria ugarirekin. Egitura horrek honakoa oihukatu beharko luke: Liburutegia.
@@ -26,10 +26,10 @@ Beraz, zer oihukatzen du zure aplikazioaren egiturak? Zure direktorioko egiturar ### Zuzena: antolatu zure proiektua aparteko osagaietan -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/structurebycomponents.PNG "Antolatu proiektua osagaietan") +![alt text](../../assets/images/structurebycomponents.PNG "Antolatu proiektua osagaietan")

### Okerra: taldekatu zure fitxategiak rol teknikoen arabera -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/structurebyroles.PNG "Antolatu proiektua rol teknikoen arabera") +![alt text](../../assets/images/structurebyroles.PNG "Antolatu proiektua rol teknikoen arabera") diff --git a/sections/projectstructre/breakintcomponents.brazilian-portuguese.md b/sections/projectstructre/breakintcomponents.brazilian-portuguese.md index 660b0be9d..f208f3b2c 100644 --- a/sections/projectstructre/breakintcomponents.brazilian-portuguese.md +++ b/sections/projectstructre/breakintcomponents.brazilian-portuguese.md @@ -9,7 +9,7 @@ Para aplicações de tamanho médio e acima, os monólitos são muito ruins - te ### Citação de Blog: "O escalonamento requer escalonamento de todo o aplicativo" - Do blog MartinFowler.com + Do blog [MartinFowler.com](https://martinfowler.com/articles/microservices.html) > Aplicações monolíticas podem ser bem-sucedidas, mas cada vez mais as pessoas estão sentindo frustrações com elas - especialmente à medida que mais aplicativos são implantados na nuvem. Os ciclos de mudança estão interligados - uma alteração feita em uma pequena parte do aplicativo requer que todo o monólito seja reconstruído e implantado. Ao longo do tempo, muitas vezes é difícil manter uma boa estrutura modular, tornando mais difícil manter as alterações que devem afetar apenas um módulo dentro desse módulo. O escalonamento requer escalonamento de todo o aplicativo, em vez de partes dele que exigem maior recurso. @@ -17,7 +17,7 @@ Para aplicações de tamanho médio e acima, os monólitos são muito ruins - te ### Citação de Blog: "Então, o que a arquitetura do seu aplicativo grita?" - Do blog [uncle-bob](https://8thlight.com/blog/uncle-bob/2011/09/30/Screaming-Architecture.html) + Do blog [uncle-bob](https://blog.cleancoder.com/uncle-bob/2011/09/30/Screaming-Architecture.html) > ...se você estivesse olhando para a arquitetura de uma biblioteca, provavelmente veria uma grande entrada, uma área para funcionários de check-in-out, áreas de leitura, pequenas salas de conferência e galeria após galeria, capaz de guardar estantes de livros para todos os livros. a biblioteca. Essa arquitetura iria gritar: Biblioteca.
@@ -27,10 +27,10 @@ Então, o que a arquitetura da sua aplicação grita? Quando você olha para a e ### Bom: estruture sua solução por componentes independentes -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/structurebycomponents.PNG "Solução de estruturação por componentes") +![alt text](../../assets/images/structurebycomponents.PNG "Solução de estruturação por componentes")

### Ruim: Agrupe seus arquivos por papel técnico -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/structurebyroles.PNG "Solução de estruturação por funções técnicas") +![alt text](../../assets/images/structurebyroles.PNG "Solução de estruturação por funções técnicas") diff --git a/sections/projectstructre/breakintcomponents.chinese.md b/sections/projectstructre/breakintcomponents.chinese.md index d4ae21dff..7c43b787b 100644 --- a/sections/projectstructre/breakintcomponents.chinese.md +++ b/sections/projectstructre/breakintcomponents.chinese.md @@ -11,14 +11,14 @@ ### 博客引用: "伸缩需要对整个应用程序进行伸缩设计" - 摘自博客 MartinFowler.com - + 摘自博客 [MartinFowler.com](https://martinfowler.com/articles/microservices.html) + > 单个应用程序可以成功, 但越来越多的人对它们感到失望 - 尤其是随着更多的应用程序被部署到云中。更改周期被捆绑在一起 - 对应用程序的一小部分进行更改, 需要重建和部署整个整体。随着时间的推移, 通常很难保持一个良好的模块化结构, 这使得更改哪怕只会影响该模块中的一个模块变得更加困难。伸缩设计需要扩展整个应用程序, 而不是它的部分,这往往需要更多资源。

### 博客引用: "那么, 你的应用程序的架构声明了什么?" - 摘自博客 [uncle-bob](https://8thlight.com/blog/uncle-bob/2011/09/30/Screaming-Architecture.html) + 摘自博客 [uncle-bob](https://blog.cleancoder.com/uncle-bob/2011/09/30/Screaming-Architecture.html) > ...如果你正在寻找一个图书馆的建筑架构, 你可能会看到一个盛大的入口, 一个 check-in-out 的文员, 阅读区, 小会议室, 画廊, 画廊后面容纳了装载所有图书馆书籍的书架。建筑会声明: 图书馆.
那么, 应用程序的体系架构会声明什么呢? 当您查看顶级目录结构和最高级别包中的源文件时; 他们声明: 医疗保健系统, 或会计系统, 或库存管理系统? 或者他们声明: Rails, 或Spring/Hibernate, 或 ASP?. @@ -27,10 +27,10 @@

### 推荐: 通过独立组件构建解决方案 -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/structurebycomponents.PNG "Structuring solution by components") +![alt text](../../assets/images/structurebycomponents.PNG "Structuring solution by components")

### 避免: 按技术角色对文件进行分组 -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/structurebyroles.PNG "Structuring solution by technical roles") +![alt text](../../assets/images/structurebyroles.PNG "Structuring solution by technical roles") diff --git a/sections/projectstructre/breakintcomponents.french.md b/sections/projectstructre/breakintcomponents.french.md new file mode 100644 index 000000000..2fa18c5e9 --- /dev/null +++ b/sections/projectstructre/breakintcomponents.french.md @@ -0,0 +1,37 @@ +# Organisez votre projet en composants + +

+ +### Un paragraphe d'explication + +Pour les applications de taille moyenne et supérieure, les monolithes sont vraiment mauvais - avoir un gros logiciel avec de nombreuses dépendances est difficile à appréhender et mène souvent à du code spaghetti. Même les architectes intelligents - ceux qui sont suffisamment qualifiés pour apprivoiser la bête et la « modulariser » - consacrent un temps considérable à sa conception, et chaque changement nécessite d'évaluer soigneusement l'impact sur d'autres objets dépendants. La solution ultime est de développer de petits logiciels : divisez la pile entière en composants autonomes qui ne partagent pas de fichiers avec d'autres, chacun constituant très peu de fichiers (par exemple API, service, accès aux données, test, etc.) de sorte qu'il soit très facile à raisonner à ce sujet. Certains peuvent appeler cette architecture de « microservices » - il est important de comprendre que les microservices ne sont pas une spécification que vous devez suivre, mais plutôt un ensemble de principes. Vous pouvez adopter tous les principes dans une architecture de microservices ou en adopter seulement quelques-uns. Les deux sont bons tant que la complexité du logiciel est faible. Le moins que vous puissiez faire est de créer des frontières de base entre les composants, d'assigner un dossier à la racine de votre projet pour chaque composant métier et de le rendre autonome - les autres composants ne sont autorisés à utiliser ses fonctionnalités que via son interface publique ou son API. C'est la base pour garder vos composants simples, éviter l'enfer des dépendances et ouvrir à l'avenir la voie à des véritables microservices une fois que votre application se développera. + +

+ +### Citation de blog : « La mise à l'échelle nécessite la mise à l'échelle de l'application entière » + + Extrait du blog de [MartinFowler.com](https://martinfowler.com/articles/microservices.html) + +> Les applications monolithiques peuvent réussir, mais de plus en plus de personnes ressentent des frustrations à leur égard, d'autant plus que davantage d'applications sont déployées dans le cloud. Les cycles de changement sont liés les uns aux autres - une modification apportée à une petite partie de l'application nécessite la reconstruction et le déploiement du monolithe entier. Au fil du temps, il est souvent difficile de conserver une bonne structure modulaire, ce qui rend plus difficile la conservation des modifications qui ne devraient affecter qu'un module au sein de ce module. La mise à l'échelle nécessite la mise à l'échelle de l'application entière plutôt que les parties concernées, cela nécessitent donc plus de ressources. + +

+ +### Citation de blog : « Alors, est-ce que est l'architecture de votre application parle d'elle-même ? » + + Extrait du blog de [uncle-bob](https://blog.cleancoder.com/uncle-bob/2011/09/30/Screaming-Architecture.html) + +> ...si vous regardiez l'architecture d'une bibliothèque, vous verriez probablement une grande entrée, un espace pour les préposés à l'enregistrement, des salles de lecture, de petites salles de conférence et des galeries pouvant accueillir tous les livres de la bibliothèque. Cette architecture parle d'elle-même : c'est une Bibliothèque.
> + +Alors, est-ce que est l'architecture de votre application parle d'elle-même ? Quand vous regardez la structure du répertoire du niveau supérieur, et les fichiers sources dans le paquet du niveau supérieur, est-ce qu'ils parlent d'eux-mêmes : c'est un système de soins de santé, un système de comptabilité ou un système de gestion des stocks ? Ou est-ce qu'ils vous parlent de : Rails, Spring/Hibernate ou ASP ? + +

+ +### Bon : Organisez votre solution avec des composants autonomes + +![alt text](../../assets/images/structurebycomponents.PNG "Solution d'organisation par composants") + +

+ +### Mauvais : Regroupez vos fichiers selon leur rôle technique + +![alt text](../../assets/images/structurebyroles.PNG "Solution d'organisation par rôles techniques") diff --git a/sections/projectstructre/breakintcomponents.japanese.md b/sections/projectstructre/breakintcomponents.japanese.md index 43615342e..4d5e1f32e 100644 --- a/sections/projectstructre/breakintcomponents.japanese.md +++ b/sections/projectstructre/breakintcomponents.japanese.md @@ -10,7 +10,7 @@ ### ブログ引用: "Scaling requires scaling of the entire application" (スケーリングにはアプリケーション全体のスケーリングが必要) - ブログ MartinFowler.com より + ブログ [MartinFowler.com](https://martinfowler.com/articles/microservices.html) より > モノリシック・アプリケーションは成功を収めることができますが、人々はモノリシック・アプリケーションに不満を感じるようになってきています - 特に多くのアプリケーションがクラウドにデプロイされるようになってきているためです。変更サイクル同士は連動しています - アプリケーションのごく一部に変更を加えると、モノリス全体を再構築してデプロイする必要があります。時間が経つにつれて、良いモジュール構造を維持することが難しくなり、そのモジュール内の1つのモジュールだけに影響するように変更を維持することが難しくなります。スケーリングでは、アプリケーションの一部だけでなく、アプリケーション全体を拡張する必要があり、多くの場合、より多くのリソースを必要とします。 @@ -18,7 +18,7 @@ ### ブログ引用: "So what does the architecture of your application scream?" (では、アプリケーションのアーキテクチャは何を叫んでいるのでしょうか?) - ブログ [uncle-bob](https://8thlight.com/blog/uncle-bob/2011/09/30/Screaming-Architecture.html) より + ブログ [uncle-bob](https://blog.cleancoder.com/uncle-bob/2011/09/30/Screaming-Architecture.html) より > ...図書館の建築を眺めていると、あなたはおそらく壮大な入り口、図書館員のためのエリア、読書エリア、小さな会議室、そしてギャラリーの奥には図書館の本をすべて収納した棚があるのが見えるだろう。その建築は悲鳴を上げるだろう。図書館と。
@@ -28,10 +28,10 @@ ### 良い: 自己完結型のコンポーネントでソリューションを構築する -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/structurebycomponents.PNG "コンポーネントによるソリューションの構築") +![alt text](../../assets/images/structurebycomponents.PNG "コンポーネントによるソリューションの構築")

### 悪い: 技術的な役割ごとにファイルをグループ化 -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/structurebyroles.PNG "技術的な役割によるソリューションの構築") +![alt text](../../assets/images/structurebyroles.PNG "技術的な役割によるソリューションの構築") diff --git a/sections/projectstructre/breakintcomponents.korean.md b/sections/projectstructre/breakintcomponents.korean.md index a35f23509..95072145a 100644 --- a/sections/projectstructre/breakintcomponents.korean.md +++ b/sections/projectstructre/breakintcomponents.korean.md @@ -10,7 +10,7 @@ ### 블로그 인용: "확장하려면 애플리케이션 전체를 확장해야한다" -MartinFowler.com 블로그로부터 +[MartinFowler.com](https://martinfowler.com/articles/microservices.html) 블로그로부터 > 단일암체 애플리케이션도 성공적일 수 있지만, 점점 더 많은 사람들이 불만을 느끼고 있다 - 특히 더 많은 애플리케이션들이 클라우드로 전개될수록. 변화 주기는 다 같이 묶여 있다 - 애플리케이션의 조그마한 부분을 바꾸면 단일암체 전체를 재건하고 재배치하여야 한다. 시간이 흐를수록 좋은 모듈식의 구조를 유지하는것이 힘들어지고, 모듈 하나에만 작용해야 할 변화가 그 모듈 이내에서만 작용하도록 하는것이 힘들어진다. 더 많은 자원을 필요로 하는 부분만 확장하는 것이 아니라, 확장하려면 애플리케이션 전체를 확장해야한다. @@ -18,7 +18,7 @@ MartinFowler.com 블로그로부터 ### 블로그 인용: "그러니 당신의 어플리케이션의 설계를 보면 어떤 감이 오는가?" -[uncle-bob](https://8thlight.com/blog/uncle-bob/2011/09/30/Screaming-Architecture.html)블로그로부터 +[uncle-bob](https://blog.cleancoder.com/uncle-bob/2011/09/30/Screaming-Architecture.html) 블로그로부터 > ...도서관 설계도를 보면, 아마도 커다란 입구, 체크인/체크아웃 구역, 독서실, 소규모 회의실들, 도서관의 모든 책을 수용할 수 있게 책꽂이들을 놓을 만한 공간들이 보일 것이다. 설계도를 보면 도서관이라고 바로 감이 올 것이다.
@@ -28,10 +28,10 @@ MartinFowler.com 블로그로부터 ### 좋은예: 자족적인 컴포넌트 기반으로 설계하라 -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/structurebycomponents.PNG "Structuring solution by components") +![alt text](../../assets/images/structurebycomponents.PNG "Structuring solution by components")

### 나쁜예: 파일을 기술적인 역할별로 모아라 -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/structurebyroles.PNG "Structuring solution by technical roles") +![alt text](../../assets/images/structurebyroles.PNG "Structuring solution by technical roles") diff --git a/sections/projectstructre/breakintcomponents.md b/sections/projectstructre/breakintcomponents.md index 69cf5761c..91df46d17 100644 --- a/sections/projectstructre/breakintcomponents.md +++ b/sections/projectstructre/breakintcomponents.md @@ -4,13 +4,13 @@ ### One Paragraph Explainer -For medium sized apps and above, monoliths are really bad - having one big software with many dependencies is just hard to reason about and often leads to spaghetti code. Even smart architects — those who are skilled enough to tame the beast and 'modularize' it — spend great mental effort on design, and each change requires carefully evaluating the impact on other dependent objects. The ultimate solution is to develop small software: divide the whole stack into self-contained components that don't share files with others, each constitutes very few files (e.g. API, service, data access, test, etc.) so that it's very easy to reason about it. Some may call this 'microservices' architecture — it's important to understand that microservices are not a spec which you must follow, but rather a set of principles. You may adopt many principles into a full-blown microservices architecture or adopt only a few. Both are good as long as you keep the software complexity low. The very least you should do is create basic borders between components, assign a folder in your project root for each business component and make it self-contained - other components are allowed to consume its functionality only through its public interface or API. This is the foundation for keeping your components simple, avoid dependency hell and pave the way to full-blown microservices in the future once your app grows. +For medium sized apps and above, *non-modular* monoliths are really bad - having one big software with 'spaghetti' of dependencies is just hard to reason about. The ultimate solution is to develop smaller software: divide the whole stack into self-contained components that don't share files with others, each is a standalone logical app (e.g. has its own API, service, data access, test, etc.) so that onboarding into it and changing the code is much easier than dealing with the whole system. Some may call this 'microservices' architecture — it's important to understand that microservices are not a spec which you must follow, but rather a set of principles. You may adopt many principles into a full-blown microservices architecture or adopt only a few. The very least you should do is create basic borders between components, assign a folder or repository in your system root for each business component and make it self-contained. Other components are allowed to consume its functionality only through its public interface or API. This is the foundation for keeping your components simple, avoid dependency hell and pave the way to full-blown microservices in the future once your app grows

### Blog Quote: "Scaling requires scaling of the entire application" - From the blog MartinFowler.com + From the blog [MartinFowler.com](https://martinfowler.com/articles/microservices.html) > Monolithic applications can be successful, but increasingly people are feeling frustrations with them - especially as more applications are being deployed to the cloud. Change cycles are tied together - a change made to a small part of the application requires the entire monolith to be rebuilt and deployed. Over time it's often hard to keep a good modular structure, making it harder to keep changes that ought to only affect one module within that module. Scaling requires scaling of the entire application rather than parts of it that require greater resource. @@ -18,7 +18,7 @@ For medium sized apps and above, monoliths are really bad - having one big softw ### Blog Quote: "So what does the architecture of your application scream?" - From the blog [uncle-bob](https://8thlight.com/blog/uncle-bob/2011/09/30/Screaming-Architecture.html) + From the blog [uncle-bob](https://blog.cleancoder.com/uncle-bob/2011/09/30/Screaming-Architecture.html) > ...if you were looking at the architecture of a library, you’d likely see a grand entrance, an area for check-in-out clerks, reading areas, small conference rooms, and gallery after gallery capable of holding bookshelves for all the books in the library. That architecture would scream: Library.
@@ -28,10 +28,38 @@ So what does the architecture of your application scream? When you look at the t ### Good: Structure your solution by self-contained components -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/structurebycomponents.PNG "Structuring solution by components") +```bash +my-system +├─ apps (components) +│ ├─ orders +│ │ ├─ package.json +│ │ ├─ api +│ │ ├─ domain +│ │ ├─ data-access +│ ├─ users +│ ├─ payments +├─ libraries (generic cross-component functionality) +│ ├─ logger +│ ├─ authenticator +``` +

### Bad: Group your files by technical role -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/structurebyroles.PNG "Structuring solution by technical roles") +```bash +my-system +├─ controllers +│ ├─ user-controller.js +│ ├─ order-controller.js +│ ├─ payment-controller.js +├─ services +│ ├─ user-service.js +│ ├─ order-service.js +│ ├─ payment-service.js +├─ models +│ ├─ user-model.js +│ ├─ order-model.js +│ ├─ payment-model.js +``` \ No newline at end of file diff --git a/sections/projectstructre/breakintcomponents.polish.md b/sections/projectstructre/breakintcomponents.polish.md index 62098e97b..17a7ea2ed 100644 --- a/sections/projectstructre/breakintcomponents.polish.md +++ b/sections/projectstructre/breakintcomponents.polish.md @@ -9,7 +9,7 @@ W przypadku średnich aplikacji i wyższych monolity są naprawdę złe - posiad ### Cytat z Bloga: "Skalowanie wymaga skalowania całej aplikacji" - Z bloga MartinFowler.com + Z bloga [MartinFowler.com](https://martinfowler.com/articles/microservices.html) > Monolithic applications can be successful, but increasingly people are feeling frustrations with them - especially as more applications are being deployed to the cloud. Change cycles are tied together - a change made to a small part of the application requires the entire monolith to be rebuilt and deployed. Over time it's often hard to keep a good modular structure, making it harder to keep changes that ought to only affect one module within that module. Scaling requires scaling of the entire application rather than parts of it that require greater resource. @@ -17,7 +17,7 @@ W przypadku średnich aplikacji i wyższych monolity są naprawdę złe - posiad ### Cytat z Bloga: "Więc co krzyczy architektura Twojej aplikacji?" - Z bloga [uncle-bob](https://8thlight.com/blog/uncle-bob/2011/09/30/Screaming-Architecture.html) + Z bloga [uncle-bob](https://blog.cleancoder.com/uncle-bob/2011/09/30/Screaming-Architecture.html) > ...if you were looking at the architecture of a library, you’d likely see a grand entrance, an area for check-in-out clerks, reading areas, small conference rooms, and gallery after gallery capable of holding bookshelves for all the books in the library. That architecture would scream: Library.
@@ -27,10 +27,10 @@ Więc co krzyczy architektura twojej aplikacji? Gdy spojrzysz na strukturę kata ### Dobre: Skonstruuj swoje rozwiązanie według samodzielnych komponentów -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/structurebycomponents.PNG "Structuring solution by components") +![alt text](../../assets/images/structurebycomponents.PNG "Structuring solution by components")

### Złe: Pogrupuj pliki według roli technicznej -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/structurebyroles.PNG "Structuring solution by technical roles") +![alt text](../../assets/images/structurebyroles.PNG "Structuring solution by technical roles") diff --git a/sections/projectstructre/breakintcomponents.russian.md b/sections/projectstructre/breakintcomponents.russian.md index 7e5c36706..cd7647b4f 100644 --- a/sections/projectstructre/breakintcomponents.russian.md +++ b/sections/projectstructre/breakintcomponents.russian.md @@ -10,7 +10,7 @@ ### Цитата из блога: "Масштабирование требует масштабирования всего приложения" -Из блога MartinFowler.com +Из блога [MartinFowler.com](https://martinfowler.com/articles/microservices.html) > Монолитные приложения могут быть успешными, но люди все чаще испытывают разочарование в связи с ними, особенно когда в облаке развертывается все бо̀льшие приложений. Циклы изменений связаны друг с другом - изменение, внесенное в небольшую часть приложения, требует перестройки и развертывания всего монолита. Со временем зачастую трудно сохранить хорошую модульную структуру, что усложняет сохранение изменений, которые должны затрагивать только один модуль в этом модуле. Масштабирование требует масштабирования всего приложения, а не его частей, которые требуют больших ресурсов. @@ -18,7 +18,7 @@ ### Цитата из блога: "Так что же кричит в архитектуре вашего приложения?" -Из блога [uncle-bob](https://8thlight.com/blog/uncle-bob/2011/09/30/Screaming-Architecture.html) +Из блога [uncle-bob](https://blog.cleancoder.com/uncle-bob/2011/09/30/Screaming-Architecture.html) > ... если бы вы смотрели на архитектуру библиотеки, вы бы, скорее всего, увидели парадный вход, зону для клерков, места для чтения, небольшие конференц-залы и галерею за галереей, способную вместить книжные полки для все книги в библиотеке. Эта архитектура будет кричать: "Библиотека!".
@@ -28,10 +28,10 @@ ### Хорошо: структурируйте свое решение по отдельным компонентам -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/structurebycomponents.PNG "Structuring solution by components") +![alt text](../../assets/images/structurebycomponents.PNG "Structuring solution by components")

### Плохо: сгруппируйте файлы по техническим ролям -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/structurebyroles.PNG "Structuring solution by technical roles") +![alt text](../../assets/images/structurebyroles.PNG "Structuring solution by technical roles") diff --git a/sections/projectstructre/choose-framework.md b/sections/projectstructre/choose-framework.md new file mode 100644 index 000000000..6af330a0f --- /dev/null +++ b/sections/projectstructre/choose-framework.md @@ -0,0 +1,39 @@ +# Consider all the consequences when choosing the main framework + +

+ +### Recommended frameworks: Pros and cons + +Unlike other choices, choosing the core framework determines strategic factors like the development style and how likely the team is to hit a wall. We believe that framework popularity is a supreme consideration and put our focus on the top 4 most popular frameworks in terms of downloads and GitHub stars. The text below outlines the pros and cons of each framework and how to match a framework to the right application type + +**express.js** + +Pros: Unmatched popularity; gigantic eco-system of extensions and middleware; simple to learn and use; familiar to almost every Node.js developer; tons of community articles and videos are based on express + +Cons: Covers a small subset of a typical application needs - merely a web server that invokes the app function per URL. Choosing express means leaving a handful of app concerns uncovered; outdated mechanics - no native support for async-await; barely maintained and updated; Slower than others + +**Nest.js** + +Pros: More batteries than any other option - covers many application concern including message queues, scheduled jobs and more; OOP-style is an advantage for teams who appreciate this design style; awesome docs; well-maintained; high popularity with a vibrant community + +Cons: High-level abstractions that cloud built-in Node.js conventions; The inclusion of many features, heavy usage of TypeScript and reference to sophisticated patterns might push teams for increased complexity; Steeper learning curve due to a handful of unique narratives (e.g., interceptors, guards, modules, and more); Highly opinionated + +**Fastify** + +Pros: Relatively simple and lean; mostly based on Node.js/JavaScript standards; relatively shallow learning curve; with its official plugins cover many application concerns though not as rich as Nest.js; + +Cons: Younger than others and not as popular yet; smaller eco-system compared to express and Nest.js + +**Koa** + +Pros: When compared with express: it's Simpler and nimbler; modern API with async/await support; better performance + +Cons: Covers a small subset of a typical application needs - leaves a handful of app concerns uncovered; Not as popular as express and Nest.js + +### A brief choosing guide + +**Prefer express.js when** - having an experienced architect onboard _and_ in a need to control the fine-grained pieces of the puzzle. In this circumstances, Koa is also a solid option with a more modern API than express but a much smaller eco-system + +**Prefer Fastify when -** The app consists of reasonably-sized components/Microservices (i.e., not a huge monolith); for teams who have solid JavaScript & Node.js knowledge; when sticking to Node.js narratives and spirit is desirable + +**Prefer Nest.js when** - It's desirable to design and code in OOP style; when the team is highly experienced with Java/Spring/Angular or similar; for large size app that can't be broken down (i.e. monolith) to autonomous component; for a team that lacks fundamental JavaScript/Node.js skills (not exclusively, this yet another consideration); when the decision-making overhead should be minimized; when the time to the first delivery is a critical factor diff --git a/sections/projectstructre/configguide.basque.md b/sections/projectstructre/configguide.basque.md index 086bd2b79..6061e5bf2 100644 --- a/sections/projectstructre/configguide.basque.md +++ b/sections/projectstructre/configguide.basque.md @@ -2,21 +2,21 @@

-### Azalpen paragrafoa +### Azalpena Konfigurazio datuekin jardutean, hainbat gauza gogaikarri eta moteltzaile aurki genitzake: -1. prozesuaren inguruneko aldagaiak erabiliz giltza guztiak ezartzea benetan gogaikarria bihurtzen da 100 giltza injektatu behar ditugunean (haiek soilik konfigurazio fitxategi batean argitaratu partez), hala ere, fitxategiekin jardutean, soilik DevOps administrariak dira gai jokaera aldatzeko, kodea aldatu gabe. Konfigurazio sistema fidagarri batek konfigurazio fitxategiak eta prozesu aldagaien berridazketa konbinatu beharko lituzke +1. prozesuaren inguruneko aldagaiak erabiliz giltza guztiak ezartzea benetan gogaikarria bihurtzen da 100 giltza injektatu behar ditugunean (haiek soilik konfigurazio fitxategi batean argitaratu partez), hala ere, fitxategiekin jardutean, soilik DevOps administrariak dira gai jokaera aldatzeko, kodea aldatu gabe. Konfigurazio sistema fidagarriek konfigurazio fitxategiak eta prozesu aldagaien berridazketa konbinatu beharko lituzkete -2. giltza guztiak JSON batean zehaztean, balioak aurkitu eta aldatzea frustragarria da zerrenda handitzen doan heinean. Ataletan antolatuta dagoen JSON fitxategi hierarkiko batek arazo hau konpondu dezake. Gainera, konfigurazio liburutegi gutxi batzuek konfigurazioa hainbat fitxategitan gordetzea ahalbidetzen dute eta guztiak exekuzio garaian bateratzea. Begiratu beheko adibidea +2. giltza guztiak JSON batean zehaztean, balioak aurkitu eta aldatzea frustragarria da zerrenda handitzen doan heinean. Ataletan antolatuta dagoen JSON fitxategi hierarkiko batek arazo hori konpondu dezake. Gainera, konfigurazio liburutegi gutxi batzuek konfigurazioa hainbat fitxategitan gordetzea ahalbidetzen dute eta guztiak exekuzio garaian bateratzea. Begiratu beheko adibidea -3. jakina da ez dela gomendagarria datu baseko pasahitza bezalako informazio garrantzitsua gordetzea, baina ez da irtenbide azkar eta praktikorik existitze erronka honetarako. Konfigurazio liburutegi batzuek fitxategiak enkriptatzeko aukera ematen dute, beste batzuek GIT argitarapen prozesuen bitartean enkriptatzen dituzte balio horiek edota ez dituzte balio errealak gordetzen, baizik eta ingurune aldagaien bidez zehazten dituzte inplementazio prozesuaren bitartean +3. jakina da ez dela gomendagarria datu baseko pasahitza bezalako informazio garrantzitsua gordetzea, baina ez da irtenbide azkar eta praktikorik existitzen erronka honetarako. Konfigurazio liburutegi batzuek fitxategiak enkriptatzeko aukera ematen dute, beste batzuek GIT argitarapen prozesuen bitartean enkriptatzen dituzte balio horiek edota ez dituzte balio errealak gordetzen, baizik eta ingurune aldagaien bidez zehazten dituzte inplementazio prozesuaren bitartean 4. konfigurazio egoera aurreratu batzuek konfigurazio giltzak komando sarrera bidez (vargs) injektatzea eskatzen dute, edota konfigurazio informazioa sinkronizatzea Redis bezalako cache memoria erabiliz, zerbitzari ugarik konfigurazio datu berak erabiltzea ahalbidetuz -5. aplikazioak ahalik eta azkarren huts egin behar du eta berehalako erantzuna eman aplikazioaren abiaraztean, beharrezko ingurune aldagaiak zehaztuta ez badaude. Konfigurazioa balioztatzeko [convict](https://www.npmjs.com/package/convict) erabiliz lor daiteke hori +5. aplikazioak ahalik eta azkarren huts egin behar du eta berehalako erantzuna eman aplikazioaren abiaraztean, beharrezko ingurune aldagaiak zehaztuta ez badaude. Konfigurazioa balioztatzeko [convict](https://www.npmjs.com/package/convict) erabiliz lor daiteke hori -Konfigurazio liburutegi batzuek aipatutako funtzionalitate gehienak dohainik eskaintzen dituzte. Eman begirada bat [rc](https://www.npmjs.com/package/rc), [nconf](https://www.npmjs.com/package/nconf), [config](https://www.npmjs.com/package/config), eta [convict](https://www.npmjs.com/package/convict) bezalako npm liburutegiei, non aipatutako ezaugarri gehienak betetzen dituzten +Konfigurazio liburutegi batzuek aipatutako funtzionalitate gehienak dohainik eskaintzen dituzte. Eman begiratu bat [rc](https://www.npmjs.com/package/rc), [nconf](https://www.npmjs.com/package/nconf), [config](https://www.npmjs.com/package/config), eta [convict](https://www.npmjs.com/package/convict) bezalako npm liburutegiei, non aipatutako ezaugarri gehienak betetzen dituzten

@@ -33,7 +33,7 @@ Konfigurazio liburutegi batzuek aipatutako funtzionalitate gehienak dohainik esk }, credit: { initialLimit: 100, - // Set low for development + // Ezarri balio txikia garapenerako initialDays: 1, }, }, diff --git a/sections/projectstructre/configguide.french.md b/sections/projectstructre/configguide.french.md new file mode 100644 index 000000000..8cf42d94d --- /dev/null +++ b/sections/projectstructre/configguide.french.md @@ -0,0 +1,43 @@ +# Utilisez une configuration respectueuse de l'environnement, sécurisée et hiérarchique + +

+ +### Un paragraphe d'explication + +Lorsqu'il s'agit de données de configuration, beaucoup de choses peuvent tout simplement vous énerver et vous freiner : + +1. le paramétrage de toutes les clés à l'aide de variables d'environnement de processus devient très fastidieux lorsqu'il faut injecter 100 clés (au lieu de simplement les livrer dans un fichier de configuration), cependant, lorsque l'on traite uniquement des fichiers, les administrateurs DevOps ne peuvent pas modifier le comportement sans modifier le code. Une solution de configuration fiable doit combiner les deux : fichiers de configuration + écrasements des variables de processus. + +2. lorsque vous spécifiez toutes les clés d'un JSON plat, il devient frustrant de trouver et de modifier des entrées lorsque la liste s'allonge. Un fichier JSON hiérarchique regroupé en sections peut résoudre ce problème + quelques bibliothèques de configuration permettent de stocker la configuration dans plusieurs fichiers et de de prendre soin de les unifier lors de l'exécution. Voir l'exemple ci-dessous + +3. le stockage d'informations sensibles comme le mot de passe de la base de données n'est évidemment pas recommandé, mais aucune solution rapide et pratique n'existe pour ce défi. Certaines bibliothèques de configuration permettent de crypter les fichiers, d'autres cryptent ces entrées pendant les commits GIT ou simplement ne stockent pas les valeurs réelles de ces entrées et spécifient la valeur réelle pendant le déploiement via les variables d'environnement. + +4. certains scénarios de configuration avancés nécessitent d'injecter des valeurs de configuration via la ligne de commande (vargs) ou de synchroniser les informations de configuration via un cache centralisé comme Redis afin que plusieurs serveurs utilisent les mêmes données de configuration. + +5. l'application doit échouer le plus rapidement possible et fournir un retour immédiat si les variables d'environnement requises ne sont pas présentes au démarrage, ceci peut être réalisé en utilisant [convict](https://www.npmjs.com/package/convict) pour valider la configuration. + +Certaines bibliothèques de configuration peuvent fournir gratuitement la plupart de ces fonctionnalités, jetez un œil aux bibliothèques npm comme [rc](https://www.npmjs.com/package/rc), [nconf](https://www.npmjs.com/package/nconf), [config](https://www.npmjs.com/package/config) et [convict](https://www.npmjs.com/package/convict) qui traitent un bon nombre de ces exigences. + +

+ +### Exemple de code - la configuration hiérarchique aide à trouver des entrées et à maintenir d'énormes fichiers de configuration + +```json5 +{ + // Configurations du module Customer + "Customer": { + "dbConfig": { + "host": "localhost", + "port": 5984, + "dbName": "customers" + }, + "credit": { + "initialLimit": 100, + // Régler un niveau bas pour le développement + "initialDays": 1 + } + } +} +``` + +

diff --git a/sections/projectstructre/createlayers.basque.md b/sections/projectstructre/createlayers.basque.md index c8f5aa631..6c13bc0ee 100644 --- a/sections/projectstructre/createlayers.basque.md +++ b/sections/projectstructre/createlayers.basque.md @@ -4,10 +4,10 @@ ### Osagaien kodea geruzatan banandu: web, zerbitzuak, eta Datuen Sarbide Geruza (DSG) (Ingelesez Data Access Layer, DAL) -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/structurebycomponents.PNG "Osagaien kodea geruzatan banandu") +![alt text](../../assets/images/structurebycomponents.PNG "Osagaien kodea geruzatan banandu")

### Minutu bateko azalpena: geruzak nahastearen eragozpena -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/keepexpressinweb.gif "Geruzak nahastearen eragozpena") +![alt text](../../assets/images/keepexpressinweb.gif "Geruzak nahastearen eragozpena") diff --git a/sections/projectstructre/createlayers.brazilian-portuguese.md b/sections/projectstructre/createlayers.brazilian-portuguese.md index 8990640f5..8d015ce45 100644 --- a/sections/projectstructre/createlayers.brazilian-portuguese.md +++ b/sections/projectstructre/createlayers.brazilian-portuguese.md @@ -4,10 +4,10 @@ ### Separe o código do componente em camadas: web, serviços e DAL -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/structurebycomponents.PNG "Separe o código do componente em camadas") +![alt text](../../assets/images/structurebycomponents.PNG "Separe o código do componente em camadas")

### Explicação em 1 minuto: A desvantagem de misturar camadas -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/keepexpressinweb.gif "A desvantagem de misturar camadas") +![alt text](../../assets/images/keepexpressinweb.gif "A desvantagem de misturar camadas") diff --git a/sections/projectstructre/createlayers.chinese.md b/sections/projectstructre/createlayers.chinese.md index 0ab1cc1e9..4d431f0f9 100644 --- a/sections/projectstructre/createlayers.chinese.md +++ b/sections/projectstructre/createlayers.chinese.md @@ -3,9 +3,9 @@

### 将组件代码分成web, services, DAL层 -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/structurebycomponents.PNG "Separate component code into layers") +![alt text](../../assets/images/structurebycomponents.PNG "Separate component code into layers")

### 1分钟说明:混合层的缺点 -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/keepexpressinweb.gif "The downside of mixing layers") +![alt text](../../assets/images/keepexpressinweb.gif "The downside of mixing layers") diff --git a/sections/projectstructre/createlayers.french.md b/sections/projectstructre/createlayers.french.md new file mode 100644 index 000000000..a6d4d4d7e --- /dev/null +++ b/sections/projectstructre/createlayers.french.md @@ -0,0 +1,13 @@ +# Organisez vos composants en strates, laissez Express gérer ses responsabilités + +

+ + ### Séparez le code des composants en strates : web, services et couche d'accès aux données (DAL) + +![alt text](../../assets/images/structurebycomponents.PNG "Séparez le code des composants en strates") + +

+ +### Explication en 1 min : l'inconvénient de mélanger les strates + +![alt text](../../assets/images/keepexpressinweb.gif "L'inconvénient de mélanger les strates") diff --git a/sections/projectstructre/createlayers.japanese.md b/sections/projectstructre/createlayers.japanese.md index e6c1356cf..dda7fb23c 100644 --- a/sections/projectstructre/createlayers.japanese.md +++ b/sections/projectstructre/createlayers.japanese.md @@ -4,10 +4,10 @@ ### コンポーネントコードをウェブ、サービス、DAL のレイヤーに分ける -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/structurebycomponents.PNG "コンポーネントコードを階層化する") +![alt text](../../assets/images/structurebycomponents.PNG "コンポーネントコードを階層化する")

### 1分解説: レイヤーを混ぜることのデメリット -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/keepexpressinweb.gif "レイヤーを混ぜることのデメリット") +![alt text](../../assets/images/keepexpressinweb.gif "レイヤーを混ぜることのデメリット") diff --git a/sections/projectstructre/createlayers.korean.md b/sections/projectstructre/createlayers.korean.md index c1d89a628..0278b8f20 100644 --- a/sections/projectstructre/createlayers.korean.md +++ b/sections/projectstructre/createlayers.korean.md @@ -4,10 +4,10 @@ ### 컴포넌트 코드를 웹, 서비스, 데이터 접근 언어(DAL) 계층으로 나누어라 -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/structurebycomponents.PNG "Separate component code into layers") +![alt text](../../assets/images/structurebycomponents.PNG "Separate component code into layers")

### 1분 설명: 계층을 섞으면 불리한 점 -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/keepexpressinweb.gif "The downside of mixing layers") +![alt text](../../assets/images/keepexpressinweb.gif "The downside of mixing layers") diff --git a/sections/projectstructre/createlayers.md b/sections/projectstructre/createlayers.md index 802452b28..f67f88cec 100644 --- a/sections/projectstructre/createlayers.md +++ b/sections/projectstructre/createlayers.md @@ -2,12 +2,27 @@

- ### Separate component code into layers: web, services, and Data Access Layer (DAL) +### Separate component code into 3 layers -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/structurebycomponents.PNG "Separate component code into layers") +The root of every component should hold 3 folders that represent common concerns and stages of every transaction: -

+```bash +my-system +├─ apps (components) +│ ├─ component-a + │ ├─ entry-points + │ │ ├─ api # controller comes here + │ │ ├─ message-queue # message consumer comes here + │ ├─ domain # features and flows: DTO, services, logic + │ ├─ data-access # DB calls w/o ORM +``` -### 1 min explainer: The downside of mixing layers +**- Entry-points -** This is where requests and flows start, whether it's REST API, Graph, message queue, scheduled jobs or any other _door_ to the application. This layer's responsibility is quite minimal - adapt the payload (e.g., JSON) to the app format, including first validation, call the logic/domain layer and return a response. This is typically achieved with a few lines of code. Many use the term "controller" for this type of code also technically, its just an adapter -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/keepexpressinweb.gif "The downside of mixing layers") +**- Domain -** This is where the app flows, logic and data live. This layer accepts protocol-agnostic payload, plain JavaScript object and returns one as well. Technically it contains common code objects like services, dto/entities, and clients that call external services. It also typically calls the data-access layer to retrieve or persist information + +**- Data-access -** This is where the app holds code that interacts with DB. Ideally, it should externalize an interface that returns/gets plain JavaScript object that is DB agnostic (also known as the repository-pattern). This layer involves DB helper utilities like query builders, ORMs, DB drivers and other implementation libraries + +**What is the merit? -** When having flexible infrastructure that allows adding more API calls and DB queries promptly, a developer can code a feature faster by focusing on the domain folder. In other words, less time is spent on technical activities and more on activities with added value. This is a ubiquitous trait that is at the heart of most software architectures like DDD, hexagonal, clean-architecture and others. On top of this, when the domain layer is not aware of any edge protocol, it can serve any client and not only HTTP calls + +**Why not MVC or clean architecture? -** The 3-tier pattern strikes a great balance between achieving the separation goal while still keeping the structure simple. It also lacks abstractions - each tier represents real-world physical tier where every request will visit. On the other hand, MVC is a simplistic pattern where the letters VC represent a few lines of a code only and the letter M means anything else. Clean architecture is architecture with high level of abstractions that can achieve even greater separation but the price tag is unproportionally higher due to the increased complexity \ No newline at end of file diff --git a/sections/projectstructre/createlayers.polish.md b/sections/projectstructre/createlayers.polish.md index 6c068cd8e..a9d30263c 100644 --- a/sections/projectstructre/createlayers.polish.md +++ b/sections/projectstructre/createlayers.polish.md @@ -4,10 +4,10 @@ ### Rozdziel kod komponentu na warstwy: sieć, usługi i DAL -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/structurebycomponents.PNG "Separate component code into layers") +![alt text](../../assets/images/structurebycomponents.PNG "Separate component code into layers")

### 1 minuta wyjaśniania: Minusem mieszanie warstw -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/keepexpressinweb.gif "The downside of mixing layers") +![alt text](../../assets/images/keepexpressinweb.gif "The downside of mixing layers") diff --git a/sections/projectstructre/createlayers.russian.md b/sections/projectstructre/createlayers.russian.md index 00d5e69ba..b7c2865b0 100644 --- a/sections/projectstructre/createlayers.russian.md +++ b/sections/projectstructre/createlayers.russian.md @@ -4,10 +4,10 @@ ### Разделить код компонента на слои: веб, сервисы и DAL -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/structurebycomponents.PNG "Separate component code into layers") +![alt text](../../assets/images/structurebycomponents.PNG "Separate component code into layers")

### 1 минутное объяснение: обратная сторона смешения слоев -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/keepexpressinweb.gif "The downside of mixing layers") +![alt text](../../assets/images/keepexpressinweb.gif "The downside of mixing layers") diff --git a/sections/projectstructre/separateexpress.basque.md b/sections/projectstructre/separateexpress.basque.md index ed404e847..a47b8e6fb 100644 --- a/sections/projectstructre/separateexpress.basque.md +++ b/sections/projectstructre/separateexpress.basque.md @@ -2,9 +2,9 @@

-### Azalpen paragrafoa +### Azalpena -Azken Express sorgailuak mantentzea merezi duen sekulako jardunbide bikain bat du. Izan ere, APIaren deklarazioa sarearekin erlazionatutako ezarpenetatik (portua, protokoloa, etab.) banandua dago. Horrek APIa prozesua martxan den bitartean egiaztatzea ahalbidetzen du, sare deirik egin gabe eta horrek dakartzan onura guztiekin: egiaztatze azkarren exekuzioa eta estalduraren metrikak eskuratzea. API bera sare baldintza malgu eta ezberdinetan inplementatzea ere ahalbidetzen du. Gehigarria: arduren bereizte hobea eta kode garbiagoa +Azken Express sorgailuak mantentzea merezi duen sekulako praktika bikaina du. Izan ere, APIaren deklarazioa sarearekin erlazionatutako ezarpenetatik (portua, protokoloa, etab.) banandua dago. Horrek ahalbidetzen du APIa egiaztatzea prozesua martxan den bitartean, sare deirik egin gabe eta horrek dakartzan onura guztiekin: egiaztatze azkarren exekuzioa eta estalduraren metrikak eskuratzea. API bera sare baldintza malgu eta ezberdinetan inplementatzea ere ahalbidetzen du. Gehigarria: arduren bereizte hobea eta kode garbiagoa

@@ -53,7 +53,7 @@ const server = http.createServer(app); -### Kode adibidea: zure APIa prozesua martxan den bitartean probatu supertest (frogentzako pakete ospetsua) erabiliz +### Kode adibidea: zure APIa prozesua martxan den bitartean probatu supertest (probentzako pakete ospetsua) erabiliz
Javascript diff --git a/sections/projectstructre/separateexpress.md b/sections/projectstructre/separateexpress.french.md similarity index 56% rename from sections/projectstructre/separateexpress.md rename to sections/projectstructre/separateexpress.french.md index e35c67d24..dea000f63 100644 --- a/sections/projectstructre/separateexpress.md +++ b/sections/projectstructre/separateexpress.french.md @@ -1,100 +1,100 @@ -# Separate Express 'app' and 'server' - -

- -### One Paragraph Explainer - -The latest Express generator comes with a great practice that is worth to keep - the API declaration is separated from the network related configuration (port, protocol, etc). This allows testing the API in-process, without performing network calls, with all the benefits that it brings to the table: fast testing execution and getting coverage metrics of the code. It also allows deploying the same API under flexible and different network conditions. Bonus: better separation of concerns and cleaner code - -

- -### Code example: API declaration, should reside in app.js/app.ts - -```javascript -const app = express(); -app.use(bodyParser.json()); -app.use('/api/events', events.API); -app.use('/api/forms', forms); -``` - -### Code example: Server network declaration, should reside in /bin/www - -
-Javascript - -```javascript -const app = require('../app'); -const http = require('http'); - -// Get port from environment and store in Express. -const port = normalizePort(process.env.PORT || '3000'); -app.set('port', port); - -// Create HTTP server. -const server = http.createServer(app); -``` -
- -
-Typescript - -```typescript -import app from '../app'; -import http from 'http'; - -// Get port from environment and store in Express. -const port = normalizePort(process.env.PORT || '3000'); -app.set('port', port); - -// Create HTTP server. -const server = http.createServer(app); -``` -
- -### Example: test your API in-process using supertest (popular testing package) - -
-Javascript - -```javascript -const request = require('supertest'); -const app = express(); - -app.get('/user', (req, res) => { - res.status(200).json({ name: 'tobi' }); -}); - -request(app) - .get('/user') - .expect('Content-Type', /json/) - .expect('Content-Length', '15') - .expect(200) - .end((err, res) => { - if (err) throw err; - }); -``` -
- - -
-Typescript - -```typescript -import * as request from "supertest"; -const app = express(); - -app.get('/user', (req: Request, res: Response) => { - res.status(200).json({ name: 'tobi' }); -}); - -request(app) - .get('/user') - .expect('Content-Type', /json/) - .expect('Content-Length', '15') - .expect(200) - .end((err: Error) => { - if (err) throw err; - }); - -``` -
+# Séparez Express 'app' et 'server' + +

+ +### Un paragraphe d'explication + +Le dernier générateur Express est livré avec une excellente pratique qui vaut la peine d'être conservée - la déclaration de l'API est séparée de la configuration liée au réseau (port, protocole, etc.). Cela permet de tester l'API en cours de traitement, sans effectuer d'appels réseau, avec tous les avantages qu'elle apporte : exécution rapide des tests et obtention des mesures de couverture du code. Il permet également de déployer la même API dans des conditions de réseau flexibles et différentes. Bonus : une meilleure séparation des préoccupations et un code plus propre. + +

+ +### Exemple de code : la déclaration de l'API doit résider dans app.js/app.ts + +```javascript +const app = express(); +app.use(bodyParser.json()); +app.use('/api/events', events.API); +app.use('/api/forms', forms); +``` + +### Exemple de code : la déclaration du réseau du serveur doit résider dans /bin/www + +
+Javascript + +```javascript +const app = require('../app'); +const http = require('http'); + +// Obtenir le port de l'environnement et le stockez dans Express. +const port = normalizePort(process.env.PORT || '3000'); +app.set('port', port); + +// Créer un serveur HTTP. +const server = http.createServer(app); +``` +
+ +
+Typescript + +```typescript +import app from '../app'; +import http from 'http'; + +// Obtenir le port de l'environnement et le stockez dans Express. +const port = normalizePort(process.env.PORT || '3000'); +app.set('port', port); + +// Créer un serveur HTTP. +const server = http.createServer(app); +``` +
+ +### Exemple : testez votre API en cours de traitement à l'aide de supertest (package de test populaire) + +
+Javascript + +```javascript +const request = require('supertest'); +const app = express(); + +app.get('/user', (req, res) => { + res.status(200).json({ name: 'tobi' }); +}); + +request(app) + .get('/user') + .expect('Content-Type', /json/) + .expect('Content-Length', '15') + .expect(200) + .end((err, res) => { + if (err) throw err; + }); +``` +
+ + +
+Typescript + +```typescript +import * as request from "supertest"; +const app = express(); + +app.get('/user', (req: Request, res: Response) => { + res.status(200).json({ name: 'tobi' }); +}); + +request(app) + .get('/user') + .expect('Content-Type', /json/) + .expect('Content-Length', '15') + .expect(200) + .end((err: Error) => { + if (err) throw err; + }); + +``` +
\ No newline at end of file diff --git a/sections/projectstructre/thincomponents.chinese.md b/sections/projectstructre/thincomponents.chinese.md index 6fc193ed3..5b036ddb4 100644 --- a/sections/projectstructre/thincomponents.chinese.md +++ b/sections/projectstructre/thincomponents.chinese.md @@ -18,9 +18,9 @@

### 推荐: 通过自包含的组件来构造解决方案 -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/structurebycomponents.PNG "Structuring solution by components") +![alt text](../../assets/images/structurebycomponents.PNG "Structuring solution by components")

### 避免: 通过技术角色对文件进行分组 -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/structurebyroles.PNG "Structuring solution by technical roles") +![alt text](../../assets/images/structurebyroles.PNG "Structuring solution by technical roles") diff --git a/sections/projectstructre/thincomponents.french.md b/sections/projectstructre/thincomponents.french.md new file mode 100644 index 000000000..91c5e05c0 --- /dev/null +++ b/sections/projectstructre/thincomponents.french.md @@ -0,0 +1,27 @@ +# Organisez votre projet en composants + +

+ +### Un paragraphe d'explication + +Pour les applications de taille moyenne et supérieure, les monolithes sont vraiment mauvais - avoir un gros logiciel avec de nombreuses dépendances est difficile à appréhender et mène souvent à du code spaghetti. Même les architectes intelligents - ceux qui sont suffisamment qualifiés pour apprivoiser la bête et la « modulariser » - consacrent un temps considérable à sa conception, et chaque changement nécessite d'évaluer soigneusement l'impact sur d'autres objets dépendants. La solution ultime est de développer de petits logiciels : divisez la pile entière en composants autonomes qui ne partagent pas de fichiers avec d'autres, chacun constituant très peu de fichiers (par exemple API, service, accès aux données, test, etc.) de sorte qu'il soit très facile à raisonner à ce sujet. Certains peuvent appeler cette architecture de « microservices » - il est important de comprendre que les microservices ne sont pas une spécification que vous devez suivre, mais plutôt un ensemble de principes. Vous pouvez adopter tous les principes dans une architecture de microservices ou en adopter seulement quelques-uns. Les deux sont bons tant que la complexité du logiciel est faible. Le moins que vous puissiez faire est de créer des frontières de base entre les composants, d'assigner un dossier à la racine de votre projet pour chaque composant métier et de le rendre autonome - les autres composants ne sont autorisés à utiliser ses fonctionnalités que via son interface publique ou son API. C'est la base pour garder vos composants simples, éviter l'enfer des dépendances et ouvrir à l'avenir la voie à des véritables microservices une fois que votre application se développera. + +

+ +### Citation de blog : « La mise à l'échelle nécessite la mise à l'échelle de l'application entière » + + Extrait du blog de MartinFowler.com + + > Les applications monolithiques peuvent réussir, mais de plus en plus de personnes ressentent des frustrations à leur égard, d'autant plus que davantage d'applications sont déployées dans le cloud. Les cycles de changement sont liés les uns aux autres - une modification apportée à une petite partie de l'application nécessite la reconstruction et le déploiement du monolithe entier. Au fil du temps, il est souvent difficile de conserver une bonne structure modulaire, ce qui rend plus difficile la conservation des modifications qui ne devraient affecter qu'un module au sein de ce module. La mise à l'échelle nécessite la mise à l'échelle de l'application entière plutôt que les parties concernées, cela nécessitent donc plus de ressources. + +

+ +### Bon : Organisez votre solution avec des composants autonomes + +![alt text](../../assets/images/structurebycomponents.PNG "Solution d'organisation par composants") + +

+ +### Mauvais : Regroupez vos fichiers selon leur rôle technique + +![alt text](../../assets/images/structurebyroles.PNG "Solution d'organisation par rôles techniques") diff --git a/sections/projectstructre/thincomponents.japanese.md b/sections/projectstructre/thincomponents.japanese.md index 7d5535b6e..e586d6884 100644 --- a/sections/projectstructre/thincomponents.japanese.md +++ b/sections/projectstructre/thincomponents.japanese.md @@ -18,10 +18,10 @@ For medium sized apps and above, monoliths are really bad - one big software wit ### Good: Structure your solution by self-contained components -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/structurebycomponents.PNG "Structuring solution by components") +![alt text](../../assets/images/structurebycomponents.PNG "Structuring solution by components")

### Bad: Group your files by technical role -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/structurebyroles.PNG "Structuring solution by technical roles") +![alt text](../../assets/images/structurebyroles.PNG "Structuring solution by technical roles") diff --git a/sections/projectstructre/thincomponents.md b/sections/projectstructre/thincomponents.md index 7d5535b6e..e586d6884 100644 --- a/sections/projectstructre/thincomponents.md +++ b/sections/projectstructre/thincomponents.md @@ -18,10 +18,10 @@ For medium sized apps and above, monoliths are really bad - one big software wit ### Good: Structure your solution by self-contained components -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/structurebycomponents.PNG "Structuring solution by components") +![alt text](../../assets/images/structurebycomponents.PNG "Structuring solution by components")

### Bad: Group your files by technical role -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/structurebyroles.PNG "Structuring solution by technical roles") +![alt text](../../assets/images/structurebyroles.PNG "Structuring solution by technical roles") diff --git a/sections/projectstructre/thincomponents.russian.md b/sections/projectstructre/thincomponents.russian.md index 394f3dbe6..6f3c6a1be 100644 --- a/sections/projectstructre/thincomponents.russian.md +++ b/sections/projectstructre/thincomponents.russian.md @@ -18,10 +18,10 @@ ### Хорошо: структурируйте свое решение по отдельным компонентам -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/structurebycomponents.PNG "Structuring solution by components") +![alt text](../../assets/images/structurebycomponents.PNG "Structuring solution by components")

### Плохо: сгруппируйте файлы по техническим ролям -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/structurebyroles.PNG "Structuring solution by technical roles") +![alt text](../../assets/images/structurebyroles.PNG "Structuring solution by technical roles") diff --git a/sections/projectstructre/typescript-considerations.md b/sections/projectstructre/typescript-considerations.md new file mode 100644 index 000000000..fcf881111 --- /dev/null +++ b/sections/projectstructre/typescript-considerations.md @@ -0,0 +1,23 @@ +# Use TypeScript sparingly and thoughtfully + +

+ +### One Paragraph Explainer + +TypeScript has won the community's hearts and is almost a standard for modern JavaScript apps. Compared to plain JS, it brings much better coding ergonomics, facilitates editor code completions, even for historical libraries that were written with JavaScript and was proven to [prevent specific type of bugs](https://earlbarr.com/publications/typestudy.pdf). With that, if you look carefully under the hype, TypeScript actually brings two **mutually-exclusive** offerings to the table: type-safety and advanced design constructs like abstract classes, interfaces, namespaces and more. Many teams chose TypeScript for better type safety yet _unintentionally_, without any proper planning, use it for other purposes, such as OOP. These teams change their design style unintentionally due to the ['law of the instruments'](https://en.wikipedia.org/wiki/Law_of_the_instrument) — a cognitive bias that involves using the tooling in hand whether they are the right choice for the mission or not. In other words, if an 'abstract class' exists in the toolbox — developers will use it. If teams consciously opted for the coding techniques mentioned above — that's fair and legit. For others, positively consider coding with classic JavaScript, plain functions and objects, which are simply decorated with primitive types. The latter option is likely to result in lower complexity + +

+ +### Research Quote: "15% less bugs" + +From the research [To Type or Not to Type](https://earlbarr.com/publications/typestudy.pdf) + +> "our central finding is that both static type systems find an important percentage of public bugs: both Flow 0.30 and TypeScript 2.0 successfully detect 15%!" + +

+ +### Blog Quote: "TypeScript will always miss 80% of bugs" + +From the post [The TypeScript tax](https://medium.com/javascript-scene/the-typescript-tax-132ff4cb175b) + +> "Some will argue that TypeScript provides realtime bug feedback, so you can catch the bugs earlier, but so do type inference, lint, and testing... You may argue that these other measures have a cost, but because TypeScript will always miss 80% of bugs, you can’t safely skip them either way, so their cost applies to both sides of the ROI math, and is already factored in" diff --git a/sections/projectstructre/wraputilities.basque.md b/sections/projectstructre/wraputilities.basque.md index 7a2250731..18efeeb0f 100644 --- a/sections/projectstructre/wraputilities.basque.md +++ b/sections/projectstructre/wraputilities.basque.md @@ -1,11 +1,10 @@ -# Antolatu baliabide komunak npm paketetan +# Kokatu baliabide komunak npm paketetan

-### Azalpen paragrafoa - -Hazten hasi eta zerbitzari ezberdinetan antzeko baliabideak erabiltzen dituzten gero eta osagai ezberdin gehiago dituzun heinean, menpekotasunak kudeatzen hasi beharko zenuke. Nola gorde zenezake zure baliabidearen iturburu kodearen kopia bat eta beste osagaiei hura erabiltzen eta inplementatzen utzi? Bada, npm izeneko tresna bat badago horretarako... Hasi baliabide paketeetan zure kodea jartzen, etorkizunean kodearen ordezkapena errazteko eta argitaratu zure kode propioa npm pakete pribatu gisa. Horrela, zure kodeak beste kode hori inportatu ahal izango du, debaldeko menpekotasun kudeaketa tresnari esker. Posible da zure erabilera pribaturako npm paketeak argitaratzea,haiek publikoki partekatu gabe, [modulu pribatuak](https://docs.npmjs.com/private-modules/intro), [erregistro pribatua](https://npme.npmjs.com/docs/tutorials/npm-enterprise-with-nexus.html) edo [npm pakete lokalak](https://medium.com/@arnaudrinquin/build-modular-application-with-npm-local-modules-dfc5ff047bcc) erabiliz +### Azalpena +Hazten hasi eta zerbitzari ezberdinetan antzeko baliabideak erabiltzen dituzten gero eta osagai ezberdin gehiago dituzun heinean, menpekotasunak kudeatzen hasi beharko zenuke. Nola gorde zenezakeen zure baliabidearen iturburu kodearen kopia bat eta beste osagaiei hura erabiltzen eta inplementatzen utzi? Bada, npm izeneko tresna bat badago horretarako... Hasi baliabide paketeetan zure kodea jartzen, etorkizunean kodearen ordezkapena errazteko, eta argitaratu zure kode propioa npm pakete pribatu gisa. Horrela, zure kodeak beste kode hori inportatu ahal izango du, debaldeko menpekotasun kudeaketa tresnari esker. Posible da zure erabilera pribaturako npm paketeak argitaratzea, haiek publikoki partekatu gabe, [modulu pribatuak](https://docs.npmjs.com/private-modules/intro), [erregistro pribatua](https://npme.npmjs.com/docs/tutorials/npm-enterprise-with-nexus.html) edo [npm pakete lokalak](https://medium.com/@arnaudrinquin/build-modular-application-with-npm-local-modules-dfc5ff047bcc) erabiliz

@@ -13,4 +12,4 @@ Hazten hasi eta zerbitzari ezberdinetan antzeko baliabideak erabiltzen dituzten ### Partekatu zure baliabide propioak ingurune eta osagaietan -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/Privatenpm.png "Antolatu proiektua osagaietan") +![alt text](../../assets/images/Privatenpm.png "Antolatu proiektua osagaietan") diff --git a/sections/projectstructre/wraputilities.brazilian-portuguese.md b/sections/projectstructre/wraputilities.brazilian-portuguese.md index c054b4d04..13d54d763 100644 --- a/sections/projectstructre/wraputilities.brazilian-portuguese.md +++ b/sections/projectstructre/wraputilities.brazilian-portuguese.md @@ -10,4 +10,4 @@ Quando você começa a crescer e tem componentes diferentes em servidores difere ### Compartilhando seus próprios utilitários comuns em ambientes e componentes -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/Privatenpm.png "Solução de estruturação por componentes") +![alt text](../../assets/images/Privatenpm.png "Solução de estruturação por componentes") diff --git a/sections/projectstructre/wraputilities.chinese.md b/sections/projectstructre/wraputilities.chinese.md index 15511bf97..aa9e1a96b 100644 --- a/sections/projectstructre/wraputilities.chinese.md +++ b/sections/projectstructre/wraputilities.chinese.md @@ -11,4 +11,4 @@ ### 在环境和组件中共享你自己的公用实用工具 -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/Privatenpm.png "构建解决方案的组件") +![alt text](../../assets/images/Privatenpm.png "构建解决方案的组件") diff --git a/sections/projectstructre/wraputilities.french.md b/sections/projectstructre/wraputilities.french.md new file mode 100644 index 000000000..523c5fc52 --- /dev/null +++ b/sections/projectstructre/wraputilities.french.md @@ -0,0 +1,13 @@ +# Externalisez les utilitaires communs en paquets NPM + +

+ +### Un paragraphe d'explication + +Une fois que vous commencez à vous développer et que vous avez différents composants sur différents serveurs qui consomment des utilitaires similaires, vous devez commencer à gérer les dépendances - comment pouvez-vous conserver une copie de votre code utilitaire et laisser plusieurs composants consommateurs l'utiliser et le déployer ? Eh bien, il y a un outil pour ça, ça s'appelle npm ... Commencez par emballer des paquets d'utilitaires tiers avec votre propre code pour le rendre facilement remplaçable à l'avenir et publiez votre propre code en tant que package npm privé. Désormais, toute votre base de code peut importer ce code et bénéficier d'un outil de gestion des dépendances gratuit. Il est possible de publier des packages npm pour votre propre usage privé sans le partager publiquement à l'aide de [modules privés](https://docs.npmjs.com/private-modules/intro), [registre privé](https://npme.npmjs.com/docs/tutorials/npm-enterprise-with-nexus.html) ou de [paquets npm locaux](https://medium.com/@arnaudrinquin/build-modular-application-with-npm-local-modules-dfc5ff047bcc). + +

+ +### Partage de vos propres utilitaires communs entre les environnements et les composants + +![alt text](../../assets/images/Privatenpm.png "Solution d'organisation par composants") diff --git a/sections/projectstructre/wraputilities.japanese.md b/sections/projectstructre/wraputilities.japanese.md index b9a703d05..52060026e 100644 --- a/sections/projectstructre/wraputilities.japanese.md +++ b/sections/projectstructre/wraputilities.japanese.md @@ -10,4 +10,4 @@ ### 環境やコンポーネント横断で独自の共通ユーティリティを共有する -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/Privatenpm.png "コンポーネントでソリューションを構築する") +![alt text](../../assets/images/Privatenpm.png "コンポーネントでソリューションを構築する") diff --git a/sections/projectstructre/wraputilities.korean.md b/sections/projectstructre/wraputilities.korean.md index 9265ea317..8bfaf69a8 100644 --- a/sections/projectstructre/wraputilities.korean.md +++ b/sections/projectstructre/wraputilities.korean.md @@ -10,4 +10,4 @@ ### 당신만의 공유 유틸리티들을 환경과 컴포넌츠에 공유하기 -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/Privatenpm.png "Structuring solution by components") +![alt text](../../assets/images/Privatenpm.png "Structuring solution by components") diff --git a/sections/projectstructre/wraputilities.md b/sections/projectstructre/wraputilities.md index ed3639007..4d9e3da62 100644 --- a/sections/projectstructre/wraputilities.md +++ b/sections/projectstructre/wraputilities.md @@ -10,4 +10,4 @@ Once you start growing and have different components on different servers which ### Sharing your own common utilities across environments and components -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/Privatenpm.png "Structuring solution by components") +![alt text](../../assets/images/Privatenpm.png "Structuring solution by components") diff --git a/sections/projectstructre/wraputilities.polish.md b/sections/projectstructre/wraputilities.polish.md index e823509de..bbd4432a1 100644 --- a/sections/projectstructre/wraputilities.polish.md +++ b/sections/projectstructre/wraputilities.polish.md @@ -10,4 +10,4 @@ Kiedy zaczniesz się rozwijać i będziesz mieć różne komponenty na różnych ### Udostępnianie własnych wspólnych narzędzi w różnych środowiskach i komponentach -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/Privatenpm.png "Structuring solution by components") +![alt text](../../assets/images/Privatenpm.png "Structuring solution by components") diff --git a/sections/projectstructre/wraputilities.russian.md b/sections/projectstructre/wraputilities.russian.md index 02a1fac70..3520ef383 100644 --- a/sections/projectstructre/wraputilities.russian.md +++ b/sections/projectstructre/wraputilities.russian.md @@ -10,4 +10,4 @@ ### Совместное использование собственных общих утилит в средах и компонентах -![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/Privatenpm.png "Structuring solution by components") +![alt text](../../assets/images/Privatenpm.png "Structuring solution by components") diff --git a/sections/security/avoid_publishing_secrets.basque.md b/sections/security/avoid_publishing_secrets.basque.md new file mode 100644 index 000000000..fab83a08a --- /dev/null +++ b/sections/security/avoid_publishing_secrets.basque.md @@ -0,0 +1,49 @@ +# Saihestu npm erregistroan sekretuak argitaratzea + +### Azalpena + +Arreta eduki behar da npm erregistroetan sekretuak istripuz argitaratzeko arriskua dago eta. `.npmignore` fitxategia erabil daiteke fitxategi eta karpeta zehatz batzuk zerrenda beltzean jartzeko, edota `files` zerrendak `package.json`en zerrenda txuri gisa joka dezake. + +npmek erregistroan benetan argitaratzen duenaren ikuspegia edukitzeko, `--dry-run` gehi daiteke npm publish komandora sortutako paketearen ikuspegi esanguratsua edukitzeko. + +Garrantzitsua da kontutan edukitzea, proiektu batek `.npmignore` eta `.gitignore` fitxategiak erabiltzen baditu, `.npmignore`ren barruan dagoena erregistroan argitaratuko dela (esaterako, `.npmignore` fitxategiak `.gitignore` berridazten du). Baldintza hori nahasgarria izan daiteke eta sekretuak argitaratzeko arriskua ekar dezake. Programatzaileek `.gitignore` fitxategia egunera dezakete, baina `.npmignore` eguneratzea ahaztu, eta horrek fitxategi garrantzitsuak iturburu kontrolean ez argitaratzea ekar dezake, npm paketean egon arren + +### Kode adibidea + +.npmignore fitxategiaren adibidea + +``` +# Probak +test +coverage + +# Eraikitze tresnak +.travis.yml +.jenkins.yml + +# Ingurunea +.env +.config + +``` + +"files" zerrenda package.jsonen erabiltzearen adibidea + +```json +{ + "files" : [ + "dist/moment.js", + "dist/moment.min.js" + ] +} +``` + +### Beste blogari batzuek diotena + +[Liran Tal & Juan Picado at Snyk](https://snyk.io/blog/ten-npm-security-best-practices/) bloga: + +> ... Erabil beharreko beste jarduera egoki bat package.json fitxategiko files ezaugarria da, zerrenda zuri bezala funtzionatzen duena eta sortu eta instalatu beharreko paketean fitxategien multzoa zehazten duena (aintzakotzat ez hartzeko (ignore) fitxategiak zerrenda beltz gisa funtzionatzen duelarik). Filesen ezaugarria eta aintzakotzat ez hartzeko fitxategiak batera erabil daitezke esplizituki zein fitxategi gehitu edo baztertu behar diren zehazteko. Biak erabiltzean, package.jsoneko aurreko filesen ezagugarriak lehentasuna hartzen du aintzakotzat ez hartzeko fitxategiaren parean. + +[npm blog](https://blog.npmjs.org/post/165769683050/publishing-what-you-mean-to-publish)a: + +> ... npm publish exekutatzean, npmek lekuko direktorioko fitxategi guztiak bateratzen ditu. Zer gehitu eta alde batera zer utzi erabakitzen du zure ordez. Erabaki horiek hartzeko zure proiektuko direktorioko hainbat fitxategiren edukiak erabiltzen ditu. Fitxategi horien artean, .gitignore, .npmingnore eta package.jsoneko files zerrenda aurkitzen dira. Gainera, beti gehitzen ditu fitxategi jakin batzuk, eta beste batzuk alde batera utzi. diff --git a/sections/security/avoid_publishing_secrets.brazilian-portuguese.md b/sections/security/avoid_publishing_secrets.brazilian-portuguese.md index dea51020e..23c9fabed 100644 --- a/sections/security/avoid_publishing_secrets.brazilian-portuguese.md +++ b/sections/security/avoid_publishing_secrets.brazilian-portuguese.md @@ -10,15 +10,15 @@ Para obter uma visão do que o npm publish realmente publicará no registro, o s ### Exemplo de Código Exemplo de arquivo .npmignore ``` -#tests +# Tests test coverage -#build tools +# Build tools .travis.yml .jenkins.yml -#environment +# Environment .env .config @@ -26,7 +26,7 @@ coverage Exemplo uso de uma lista de arquivos no package.json -``` +```json { "files" : [ "dist/moment.js", diff --git a/sections/security/avoid_publishing_secrets.french.md b/sections/security/avoid_publishing_secrets.french.md new file mode 100644 index 000000000..ad3d8ee70 --- /dev/null +++ b/sections/security/avoid_publishing_secrets.french.md @@ -0,0 +1,44 @@ +# Éviter de publier les secrets dans le registre npm + +### Un paragraphe d'explication +Des précautions doivent être prises pour éviter de publier accidentellement des secrets dans un registre public npm. Un fichier `.npmignore` peut être utilisé pour ignorer des fichiers ou dossiers spécifiques, ou le tableau `files` du `package.json` peut être utilisé comme une liste blanche. + +Pour savoir ce que npm publish va vraiment publier sur le registre, l'option `--dry-run` peut être ajoutée à la commande npm publish pour obtenir un résultat verbeux du package crée. + +Il est important de noter que si un projet utilise à la fois des fichiers `.npmignore` et `.gitignore`, tout ce qui n'est pas dans `.npmignore` est publié dans le registre (c'est-à-dire que le fichier `.npmignore` écrase `.gitignore`). Cette condition est communément une source de confusion et un problème qui peut mener à la fuite de secrets. Les développeurs ont l'habitude de mettre à jour le fichier `.gitignore`, mais peuvent oublier de faire de même avec `.npmignore`, ce qui peut conduire à ce qu'un potentiel fichier sensible ne soit pas envoyé sur l'outil de gestion des versions, mais soit toujours inclus dans le package npm. + +### Exemple de code +Fichier d'exemple .npmignore +``` +# Tests +test +coverage + +# Build tools +.travis.yml +.jenkins.yml + +# Environment +.env +.config + +``` + +Exemple d'usage du tableau files de package.json + +```json +{ + "files" : [ + "dist/moment.js", + "dist/moment.min.js" + ] +} +``` + +### Ce que disent les autres blogueurs + +Extrait du blog de [Liran Tal & Juan Picado sur Snyk](https://snyk.io/blog/ten-npm-security-best-practices/): +> ... Une autre bonne pratique à adopter est d'utiliser la propriété files du package.json, qui fonctionne comme une liste blanche et spécifie un tableau de fichiers à inclure dans le package qui sera créé et installé (tandis que le fichier .npmignore fonctionne comme une liste noire). La propriété files et le fichier .npmignore peuvent être utilisés ensemble pour déterminer explicitement quels fichiers doivent être inclus, et exclus, du package. Quand les deux sont utilisés, la propriété files du package.json a la priorité sur le fichier .npmignore. + +Extrait du blog de [blog de npm](https://blog.npmjs.org/post/165769683050/publishing-what-you-mean-to-publish) +> ... Quand vous exécutez npm publish, npm met dans le package l'ensemble des fichiers du répertoire courant. Il prend quelques décisions pour vous à propos de ce qu'il faut inclure et de ce qu'il faut ignorer. Pour prendre ces décisions, il utilise le contenu de plusieurs fichiers dans le répertoire de votre projet. Ces fichiers incluent .gitignore, .npmignore, et le tableau files dans package.json. De plus, il inclut toujours certains fichiers et en ignore d'autres. \ No newline at end of file diff --git a/sections/security/avoid_publishing_secrets.japanese.md b/sections/security/avoid_publishing_secrets.japanese.md index 8f3f02141..3011094eb 100644 --- a/sections/security/avoid_publishing_secrets.japanese.md +++ b/sections/security/avoid_publishing_secrets.japanese.md @@ -10,15 +10,15 @@ npm publish が実際にレジストリに何をパブリッシュするのか ### コード例 .npmignore file の例 ``` -#tests +# Tests test coverage -#build tools +# Build tools .travis.yml .jenkins.yml -#environment +# Environment .env .config @@ -26,7 +26,7 @@ coverage package.json 内の files 配列の利用例 -``` +```json { "files" : [ "dist/moment.js", diff --git a/sections/security/avoid_publishing_secrets.md b/sections/security/avoid_publishing_secrets.md index 934325bb5..ca68234af 100644 --- a/sections/security/avoid_publishing_secrets.md +++ b/sections/security/avoid_publishing_secrets.md @@ -10,15 +10,15 @@ It is important to note that if a project is utilising both `.npmignore` and `.g ### Code example Example .npmignore file ``` -#tests +# Tests test coverage -#build tools +# Build tools .travis.yml .jenkins.yml -#environment +# Environment .env .config @@ -26,7 +26,7 @@ coverage Example use of files array in package.json -``` +```json { "files" : [ "dist/moment.js", diff --git a/sections/security/avoid_publishing_secrets.polish.md b/sections/security/avoid_publishing_secrets.polish.md index d4a3f9a28..4b29aa89b 100644 --- a/sections/security/avoid_publishing_secrets.polish.md +++ b/sections/security/avoid_publishing_secrets.polish.md @@ -10,15 +10,15 @@ Ważne jest, aby pamiętać, że jeśli projekt wykorzystuje zarówno pliki `.np ### Przykład kodu Example .npmignore file ``` -#tests +# Tests test coverage -#build tools +# Build tools .travis.yml .jenkins.yml -#environment +# Environment .env .config @@ -26,7 +26,7 @@ coverage Przykład zastosowania tablicy plików w package.json -``` +```json { "files" : [ "dist/moment.js", diff --git a/sections/security/avoid_publishing_secrets.russian.md b/sections/security/avoid_publishing_secrets.russian.md index cee60ef3f..7e8170313 100644 --- a/sections/security/avoid_publishing_secrets.russian.md +++ b/sections/security/avoid_publishing_secrets.russian.md @@ -10,15 +10,15 @@ ### Пример кода Example .npmignore file ``` -#tests +# Tests test coverage -#build tools +# Build tools .travis.yml .jenkins.yml -#environment +# Environment .env .config @@ -26,7 +26,7 @@ coverage Пример использования массива файлов в package.json -``` +```json { "files" : [ "dist/moment.js", diff --git a/sections/security/avoideval.basque.md b/sections/security/avoideval.basque.md new file mode 100644 index 000000000..9de3032ef --- /dev/null +++ b/sections/security/avoideval.basque.md @@ -0,0 +1,23 @@ +# Saihestu JavaScript eval adierazpenak + +### Azalpena + +`eval()`, `setTimeout()`, `setInterval()`, eta `new Function()` funtzio globalak dira, Node.jsen maiz erabiltzen direnak, eta JavaScript expresio bat, adierazpen bat edo adierazpen segida bat jasotzen dituen kate parametroak onartzen dituztenak. Funtzio horiek erabiltzeak segurtasun arazoak sortzen ditu. Izan ere, fidagarria ez den erabiltzaileren bat sartzen bada zerbitzarian kodea exekutatu eta zerbitzaria arriskuan jarri ahal izango du, erabiltzaile kodearen ebaluazioa gainditzeak ahalmena ematen baitie erasotzaileei nahi dituzten ekintzak burutzeko. Gomendagarria da kodea garbitzea, funtzio horiek bukaerako funtzioari pasatu eta exekutatuak izatea ekiditeko. + +### Kode adibidea + +```javascript +// erasotzailea sartzeko gai izan den kode maltzurraren adibidea +const erabiltzaileSarrera = + "require('child_process').spawn('rm', ['-rf', '/'])"; + +// exekutatutako kode maltzurra +eval(erabiltzaileSarrera); +``` + +### Beste bloglari batzuk diotena + +[Liran Tal](https://leanpub.com/nodejssecurity)-en Essential Node.js Security liburua: + +> Berharbada, segurtasunaren ikuspuntutik, eval() funtzioa gaizkien ikusita dagoen JavaScripten ataletako bat da. JavaScript kateak testu moduan aztertzen ditu eta JavaScript kodea balitz bezala exekutatzen ditu. +> Horrekin batera, fidagarria ez den erabiltzaileren bat sartzen bada kodearen egiaztapena gaindituz, hondamendirako bide arriskutsua da, zerbitzariaren funtzionamendua larriki kaltetu dezakeena. diff --git a/sections/security/avoideval.french.md b/sections/security/avoideval.french.md new file mode 100644 index 000000000..3a1775e74 --- /dev/null +++ b/sections/security/avoideval.french.md @@ -0,0 +1,20 @@ +# Éviter les déclarations d'évaluation de JS + +### Un paragraphe d'explication + +`eval()`, `setTimeout()`, `setInterval()`, et `new Function()` sont des fonctions globales, souvent utilisées dans Node.js, qui acceptent comme paramètre une châine de caractères représentant une expression Javascript, une déclaration ou une suite de déclarations. Le problème de sécurité que pose ces fonctionnalités est la possibilité que les entrées d'un utilisateur non fiable se retrouvent dans le code exécuté, ce qui pourrait compromettre le serveur, l'évaluation du code permettant essentiellement à un attaquant d'effectuer toutes les actions possibles. Il est suggéré de refactoriser le code pour ne pas se fier à ces fonctions où les entrées de l'utilisateur pourraient y être passées et exécutées. + +### Exemple de code + +```javascript +// exemple d'un code malicieux qui permettait à un attaquant d'entrer +const userInput = "require('child_process').spawn('rm', ['-rf', '/'])"; + +// code malicieux exécuté +eval(userInput); +``` + +### Ce que disent les autres blogueurs + +Extrait du livre « Essential Node.js Security » de [Liran Tal](https://leanpub.com/nodejssecurity): +> La fonction eval() est peut-être l'une des plus mal vues dans JavaScript du point de vue de la sécurité. Elle analyse une chaîne de caractère JavaScript comme du texte, et l'exécute comme si c'était du code JavaScript. En mélangeant cela avec des entrées d'utilisateurs non fiables qui pourraient trouver un moyen d'accéder à la fonction eval(), on obtient la recette d'un désastre qui peut finir par compromettre le serveur. diff --git a/sections/security/childprocesses.basque.md b/sections/security/childprocesses.basque.md new file mode 100644 index 000000000..244fd40fa --- /dev/null +++ b/sections/security/childprocesses.basque.md @@ -0,0 +1,29 @@ +# Kontuz ibili bigarren mailako prozesuekin lan egitean + +### Azalpena + +Bigarren mailako prozesuak oso erabilgarriak izan badaitezke ere, kontuz erabili behar da haiekin. Izan ere, erabiltzaileen sarrera desinfektatu egin behar da, edo, bestela, guztiz baztertu beharra dago. Mugagabeak dira sistemako logika egikaritzen duten desinfektatu gabeko sarreren arriskuak: norbaitek kodea urrunetik egikaritzea suertatu daiteke, sistemaren datu sentikorrak agerian jartzea gerta daiteke, eta datuak galtzerainoko arazoak gerta daitezke ere. Itxura hau izan dezake prestaketen egiaztapen zerrendak: + +- eragotzi erabiltzailearen sarrera kasu guztietan, bestela balioztatu eta saneatu +- guraso eta seme-alaben prozesuen pribilegioak mugatu erabiltzaile/talde identitateak erabiliz +- exekutatu zure prozesua ingurune isolatu baten barruan, nahi ez dituzun bigarren mailako ondorioak ekiditeko beste prestaketek huts egiten badute ere + +### Kode adibidea: desinfektatu gabeko bigarren mailako prozesuen exekuzioen arriskuak + +```javascript +const { exec } = require('child_process'); + +... + +// adibide gisa, bi argudio hartzen dituen scripta hartu, bietako bat garbitu gabeko erabiltzaile sarrera delarik +exec('"/path/to/test file/someScript.sh" --someOption ' + input); + +// -> imaginatu zer gertatuko litzatekeen erabiltzaileak '&& rm -rf --no-preserve-root /' bezalako zerbait idatziz gero +// espero gabeko sorpresa hartuko zenuke +``` + +### Baliabide osagarriak + +Node.js bigarren mailako prozesuaren [dokumentazioa](https://nodejs.org/dist/latest-v8.x/docs/api/child_process.html#child_process_child_process_exec_command_options_callback): + +> Ez inoiz pasatu erabiltzaile sarrerarik funtzio honetara higienizatu gabe. Shell metakarakereak duen edozein sarrera erabil daiteke komando arbitrarioen exekuzioa abiarazteko. diff --git a/sections/security/childprocesses.french.md b/sections/security/childprocesses.french.md new file mode 100644 index 000000000..7a34fdab0 --- /dev/null +++ b/sections/security/childprocesses.french.md @@ -0,0 +1,31 @@ +# Soyez prudent lorsque vous travaillez avec des processus enfants + +### Un paragraphe d'explication + +Aussi importants que soient les processus enfants, ils doivent être utilisés avec prudence. Les entrées des utilisateurs qui y sont passées doivent être assainies (NdT *sanitize*), voire évitées. +Les dangers d'une entrée non assainie exécutant une logique au niveau du système sont illimités, allant de l'exécution de code à distance à l'exposition de données système sensibles et aussi de perte de données. +Une liste de contrôle des préparatifs pourrait ressembler à ceci : + +- éviter les entrées des utilisateurs dans tous les cas, autrement les valider et les assainir +- limiter les privilèges du parent et des processus enfants en utilisant les identités de groupe et d'utilisateur +- exécuter votre processus dans un environnement isolé pour prévenir des effets secondaires indésirables si les autres préparations échouent + +### Exemple de code : Les dangers de l'exécution de processus enfants non assainis + +```javascript +const { exec } = require('child_process'); + +... + +// comme exemple, prenons un script qui prend deux arguments, l'un d'entre eux est une entrée utilisateur non assainie +exec('"/path/to/test file/someScript.sh" --someOption ' + input); + +// -> imaginez ce qu'il se passerait si un utilisateur entrait simplement quelque chose comme '&& rm -rf --no-preserve-root /' +// vous auriez une surprise indésirable +``` + +### Ressources supplémentaires + +Extrait de la [documentation](https://nodejs.org/dist/latest-v8.x/docs/api/child_process.html#child_process_child_process_exec_command_options_callback) Node.js sur les processus enfants : + +> Ne jamais passer une entrée utilisateur non assainie à cette fonction. Toute entrée comportant des métacaractères du shell peut être utilisée pour déclencher une commande arbitrairement \ No newline at end of file diff --git a/sections/security/commonsecuritybestpractices.basque.md b/sections/security/commonsecuritybestpractices.basque.md new file mode 100644 index 000000000..d5aa6ab7f --- /dev/null +++ b/sections/security/commonsecuritybestpractices.basque.md @@ -0,0 +1,128 @@ +[✔]: ../../assets/images/checkbox-small-blue.png + +# Node.jsren ohiko segurtasun praktika onak + +Ohiko segurtasun praktiken atalak esparru eta konbentzio askotan estandarizatuta dauden praktika onak biltzen ditu. Adibidez, aplikazio bat exekutatzea SSL / TLS-rekin konfigurazio guztietan erabili beharko litzatekeen praktika eta konbentzio arrunta da, horrela segurtasun abantaila handiak lortuko lirateke eta. + +## ![✔] Erabili SSL / TLS bezeroen zerbitzariaren konexioa enkriptatzeko + +**TL; DR:** [doako SSL / TLS ziurtagirien](https://letsencrypt.org/) eta haien konfigurazio errazaren garaian, ez duzu zertan pisatu zerbitzari segurua erabiltzearen abantailak eta desabantailak, argi eta garbi gailentzen baitira segurtasuna, teknologia modernoaren laguntza eta konfiantza bezalako abantailak -gutxieneko gainkarga minimoa bezalako desabantailak edukita ere- HTTP hutsaren aldean. + +**Bestela:** erasotzaileek erdi-erdiko erasoak egin ditzakete, zure erabiltzaileen portaera zelatatu eta are ekintza maltzurragoak egin ditzakete konexioa enkriptatu gabe dagoenean. + +🔗 [**Informazio gehiago: Node.js zerbitzari segurua egikaritzea**](./secureserver.basque.md) + +

+ +## ![✔] Balio sekretuak eta aztarnak modu seguruan alderatzea + +**TL; DR:** balio sekretuak edo aztarnak alderatzean HMAC laburpenak balira bezala, [`crypto.timingSafeEqual(a, b)`](https://nodejs.org/dist/latest-v9.x/docs/api/crypto.html#crypto_crypto_timingsafeequal_a_b) funtzioa erabili beharko zenuke, Node.js v6.6.0 geroztik Nodek eskaintzen duena. Metodo horrek emandako bi objektu alderatzen ditu eta datuok alderatzen jarraitzen du bat ez badatoz ere. Datuak berdinak diren alderatzeko metodo lehenetsiak berez bueltatuko lirateke berriro, karakterrak bat etorriko ez balira, eta horrela eragiketaren iraupen luzeak erasoak ahalbidetuko lituzke + +**Bestela:** datuak berdinak diren alderatzeko metodo lehenetsiak erabiltzen badituzu, informazio kritikoa agerian jar dezakezu, zenbatekoa den bi objektu alderatzeko behar den denbora. + +

+ +## ![✔] Ausazko kateak sortzea Node.js erabiliz + +**TL; DR:** tokenetarako (giltzak) eta segurtasunaren menpekoak diren beste kasu batzuetarako sasi ausazko kateak sortzen dituen funtzio pertsonalizatua erabiltzea ez da, agian, uste bezain ausazkoa izango, eta, ondorioz, zure aplikazioa eraso kriptografikoen aurrean zaurgarria izan daditeke. Ausazko kate seguruak sortu behar dituzunean, erabili [`crypto.randomBytes(size, [callback])`](https://nodejs.org/api/crypto.html#crypto_crypto_randombytes_size_callback) funtzioa sistemak eskaintzen duen entropia baliatuz. + +**Bestela:** sasi ausazko kateak sortzen direnean kriptografikoki seguruak diren metodorik gabe, erasotzaileek sortutako emaitzak aurreikusi eta erreproduzi ditzakete, zure aplikazioa segurtasunik gabe geldituz. + +

+ +Jarraian, OWASP proiektuko hainbat gomendio garrantzitsu zerrendatu ditugu + +## ![✔] OWASP A2: hautsitako autentifikazioa + +- Eskatu MFA / 2FA zerbitzu eta kontu garrantzitsuetarako +- Biratu pasahitzak eta atzitzeko gakoak maiz, SSH giltzak barne +- Aplikatu pasahitz politika sendoak, bai operazioetarako, bai aplikazioko erabiltzaileen kudeaketarako ([🔗 OWASP pasahitz gomendioa](https://www.owasp.org/index.php/Authentication_Cheat_Sheet#Implement_Proper_Password_Strength_Controls.22)) +- Ez bidali edo zabaldu zure aplikazioa lehenespenezko kredentzialekin, batez ere administratzaile erabiltzaileentzat edo menpeko dituzun kanpoko zerbitzuentzat +- Erabili OAuth, OpenID eta horiek bezalako autentifikazio metodo estandarrak, eta **saihestu** oinarrizko autentifikazioa +- Mugatu autentifikazio saiakera kopurua: debekatu _X_ saio saiakera baino gehiago (pasahitza berreskuratzea barne, etab.) _Y_ aldian +- Saioa hastean huts eginez gero, ez utzi erabiltzaileari jakiten erabiltzaile izenaren egiaztatzeak edo pasahitzaren egiaztatzeak huts egin zuen; autentifikazio errore arrunta itzuli besterik ez egin +- Aztertu ez ote den komeni erabiltzea erabiltzaileen kudeaketarako sistema zentralizaturen bat langile bakoitzeko hainbat kontu kudeatu beharra ekiditeko (adibidez, GitHub, AWS, Jenkins, etab.) eta erabiltzaileen kudeaketarako sistema ezagun eta zailduren baten onurez baliatzeko. + +## ![✔] OWASP A5: sarbide kontrol hautsia + +- Errespetatu [pribilegio txikienaren printzipioa](https://en.wikipedia.org/wiki/Principle_of_least_privilege): DevOpseko osagai eta pertsona bakoitzak soilik izan behar du aukera beharrezko informazioa eta baliabideak eskuratzeko +- **Inoiz** ez lan egin kontsola / root (pribilegio osoa) kontuarekin kontu kudeaketan izan ezik +- Exekutatu instantzia / edukiontzi guztiak rol / zerbitzu kontu baten izenean +- Esleitu baimenak taldeei eta ez erabiltzaileei. Horrek baimenen kudeaketa errazagoa eta gardenagoa izatea ahalbidetu beharko luke kasu gehienetan + +## ![✔] OWASP A6: segurtasun okerreko konfigurazioa + +- Barne sarea da bide bakarra ekoizpen inguruneko barne osagaietara iristeko; erabili SSH edo beste modu batzuk erabili, baina _inoiz_ agerian jarri gabe barne zerbitzuak +- Mugatu barne sareko sarbidea: berariaz zehaztu zein baliabide sar daitekeen beste baliabide batzuetara (adibidez, sare politika edo azpisareak) +- Cookieak erabiltzen badituzu, konfiguratu modu "seguruan", bidalketak SSL bidez bakarrik egiteko +- Cookieak erabiltzen badituzu, konfiguratu "gune bererako" soilik; beraz domeinu bereko eskaerek soilik izendatutako cookieak itzuliko dituzte +- Cookieak erabiltzen badituzu, aukeratu "HttpOnly" konfigurazioa, bezeroaren JavaScript kodea sartzea galarazten duena +- Babestu VPC bakoitza sarbide arau zorrotz eta murriztaileekin +- Lehenetsi mehatxuak STRIDE edo DREAD bezalako segurtasun mehatxu eredu estandarrak erabiliz +- Babestu DDoS erasoen aurka HTTP (S) eta TCP karga orekatzaileak erabiliz +- Erakunde espezializatuek aldizka sartzeko probak egin + +## ![✔] OWASP A3: bereziki babestutako datuen esposizioa + +- Onartu SSL / TLS konexioak soilik, eta ezarri Strict-Transport-Security goiburuak erabiliz +- Bereizi sarea segmentutan (hau da, azpisareak) eta ziurtatu nodo bakoitzak sarbide baimenak dituela beharrezko gutxieneko sarerako +- Multzokatu Interneteko sarbiderik behar ez duten zerbitzu / instantzia guztiak eta berariaz baztertu irteerako edozein konexio (azpisare pribatua, adibidez) +- Gorde sekretu guztiak AWS KMS, HashiCorp Vault edo Google Cloud KMS bezalako segurtasun karpetak dituzten produktuetan +- Blokeatu izaera sentikorreko metadatuak metadatuak erabiliz +- Enkriptatu pasoko datuak ingurune fisiko batetik irteten direnean +- Ez sartu sekretuak egunkarietako adierazpenetan +- Saihestu frontendean pasahitz arruntak erakustea; hartu beharrezko neurriak backendean; eta ez gorde inoiz informazio sentikorrik testu soilean + + +## ![✔] OWASP A9: segurtasun ahulezia ezagunak dituzten osagaien erabilera + +- Eskaneatu dockeren irudiak ahulezia ezagunak aurkitzeko (Dockeren eta beste hornitzaile batzuen eskaneatze zerbitzuak erabiliz) +- Gaitu instantzia automatikoen (makina) adabakiak eta bertsio berritzea segurtasun adabakirik ez duten sistema eragileen bertsio zaharrak exekutatzea ekiditeko +- Eman erabiltzaileari 'id', 'sarbidea' eta 'eguneratu'ren giltzak(tokenak), sarbide giltzak (tokenak) iraupen laburra izan dezan eta giltzarekin (tokenarekin) egunera dadin +- Erregistratu eta ikuskatu APIaren dei guztiak hodei eta kudeaketa zerbitzuetara (adibidez, nork ezabatu zuen S3 ontzia?) AWS CloudTrail bezalako zerbitzuak erabiliz +- Exekutatu zure hodei hornitzailearen segurtasun egiaztatzailea (adibidez, AWS segurtasun fidagarritasun aholkularia) + + +## ![✔] OWASP A10: erregistro eta kontrol eznahikoak + +- Ohartarazi ikuskaritzako gertaera aipagarri edo susmagarriez: erabiltzaileen saioa hastea, erabiltzaile berriak sortzea, baimenen aldaketa, etab +- Ohartarazi saioa hastean hutsegiteen kopuru irregularra dela (edo ahaztutako pasahitza bezalako ekintzak) +- Sartu eguneratzeari hasiera eman dion denbora eta erabiltzaile izena DB erregistro bakoitzean + +## ![✔] OWASP A7: Cross-Site-Scripting (XSS) + +- Erabili diseinuaren bidez XSS-i automatikoki ihes egiten dioten txantiloien motorrak edo esparruak, hala nola EJS, Pug, React edo Angular. Ezagutu XSS babes mekanismo bakoitzaren mugak eta kudeatu estaltzen ez diren erabilera kasuak +- HTML irteerako testuinguruaren arabera fidagarriak ez diren HTTP eskaera datuak sahiestean (gorputza, atributua, JavaScript, CSS edo URLa) konpondu egingo dira islatu eta gordetako XSS ahuleziak +- Testuinguruaren araberako kodeketa aplikatzeak DOM XSSren aurka egiten du arakatzailearen dokumentua aldatzean bezeroaren aldetik +- Gaitu Edukien Segurtasun Politika (CSP) XSSren aurkako kontrola arintzeko defentsa sakon gisa + +## ![✔] Babestu pertsonalki identifikatu daitekeen informazioa (PII datuak) + +- Pertsonalki identifikatzeko informazioa (PII) pertsona zehatz bat identifikatzeko erabil daitekeen edozein datu da +- Babestu aplikazioetan identifikatu daitekeen informazioa, enkriptatuz +- Jarraitu tokian tokiko datuen pribatutasun legeak. Erreferentzia legeak: + - Europar Batasuna: GDPR - https://ec.europa.eu/info/law/law-topic/data-protection_en + - India: https://meity.gov.in/writereaddata/files/Personal_Data_Protection_Bill,2018.pdf + - Singapur: https://www.pdpc.gov.sg/Overview-of-PDPA/The-Legislation/Personal-Data-Protection-Act + +## ![✔] Izan security.txt fitxategia [PRODUKZIOA] + +**TL; DR:** izan ```security.txt``` izeneko testu fitxategia direktorio ```/.well-known``` azpian (/.well-known/security.txt) edo zure webgunearen edo ekoizpenean dagoen zure web aplikazioaren erro direktorioan (/security.txt). Segurtasun ikertzaileek atzemandako ahultasunen xehetasunak izan behar ditu ```security.txt``` fitxategiak, eta txostenak bidali behar zaizkion pertsona edo talde arduradunaren harremanetarako datuak ere jaso beharko ditu (posta elektronikoko IDa edo / eta telefono zenbakiak) . + +**Bestela:** baliteke ahulezien berri ez izatea. Galduko duzu ahuleziei garaiz eragiteko aukera. + +🔗 [**security.txt**](https://securitytxt.org/) +


+ +## ![✔] Izan SECURITY.md fitxategia [ITURRI IREKIA] + +**TL; DR:** zure proiektuaren segurtasun ahulezien berri modu arduratsuan eman nahi badiozu jendeari jarraibideak zehazte aldera, SECURITY.md fitxategia gehi dezakezu zure biltegiko erroan, dokumentuetan edo .github karpetan. SECURITY.md fitxategiak informazio egokia eduki behar du segurtasun ikertzaileek proiektuaren ahuleziak atzeman eta txostenak bidali behar zaizkion pertsona / talde arduradunaren harremanetarako datuak (posta elektronikoko IDa edo / eta telefono zenbakiak) jaso ahal ditzaten + +**Bestela:** baliteke ahulezien berri ez izatea. Ahulezien gainean garaiz jarduteko aukera galduko duzu. + +🔗 [**Informazio gehiago: SECURITY.md**](https://help.github.com/en/github/managing-security-vulnerabilities/adding-a-security-policy-to-your-repository) + +


+ + +


diff --git a/sections/security/commonsecuritybestpractices.brazilian-portuguese.md b/sections/security/commonsecuritybestpractices.brazilian-portuguese.md index 764e34812..79d129c58 100644 --- a/sections/security/commonsecuritybestpractices.brazilian-portuguese.md +++ b/sections/security/commonsecuritybestpractices.brazilian-portuguese.md @@ -10,7 +10,7 @@ A seção de boas práticas comuns de segurança contém as práticas recomendad **Caso contrário:** invasores podem executar ataques man-in-the-middle, espionar o comportamento de seus usuários e executar ações ainda mais maliciosas quando a conexão não é criptografada. -🔗 [**Leia Mais: Executando um servidor Node.js seguro**](/sections/security/secureserver.brazilian-portuguese.md) +🔗 [**Leia Mais: Executando um servidor Node.js seguro**](./secureserver.brazilian-portuguese.md)

diff --git a/sections/security/commonsecuritybestpractices.french.md b/sections/security/commonsecuritybestpractices.french.md new file mode 100644 index 000000000..c9bcac371 --- /dev/null +++ b/sections/security/commonsecuritybestpractices.french.md @@ -0,0 +1,127 @@ +[✔]: ../../assets/images/checkbox-small-blue.png + +# Meilleures pratiques de sécurité communes avec Node.js + +La section des directives de sécurité communes contient les meilleures pratiques qui sont normalisées dans de nombreux frameworks et conventions. L'utilisation d'une application avec SSL/TLS, par exemple, devrait être une directive et une convention commune suivie dans chaque configuration pour obtenir des grands avantages en matière de sécurité. + +## ![✔] Utilisez SSL/TLS pour crypter la connexion client-serveur + +**TL;PL :** À l'heure des [certificats SSL/TLS gratuits](https://letsencrypt.org/) et de la facilité de leur configuration, vous n'avez plus à peser les avantages et les inconvénients de l'utilisation d'un serveur sécurisé car les avantages tels que la sécurité, le support de la technologie moderne et de la confiance l'emportent clairement sur les inconvénients tels que la surcharge minimale par rapport au HTTP pur. + +**Autrement :** Les attaquants peuvent effectuer des attaques de type "attaque de l'homme du milieu", espionner le comportement de vos utilisateurs et effectuer des actions encore plus malveillantes lorsque la connexion n'est pas cryptée. + +🔗 [**Plus d'infos : exécution d'un serveur Node.js sécurisé**](./secureserver.french.md) + +

+ +## ![✔] Comparez les valeurs secrètes et les hachages en toute sécurité + +**TL;PL :** Lorsque vous comparez des valeurs secrètes ou des hachages comme les digests HMAC, vous devez utiliser la fonction [`crypto.timingSafeEqual(a, b)`](https://nodejs.org/dist/latest-v9.x/docs/api/crypto.html#crypto_crypto_timingsafeequal_a_b) que Node fournit dès la version 6.6.0 de Node.js. Cette méthode compare deux objets donnés et continue de comparer même si les données ne correspondent pas. Les méthodes de comparaison d'égalité par défaut s'arrêteraient simplement après une discordance de caractères, permettant de chronométrer les attaques basées sur la longueur de l'opération. + +**Autrement :** En utilisant les opérateurs de comparaison d'égalité par défaut, vous pourriez exposer des informations critiques basées sur le temps nécessaire pour comparer deux objets. + +

+ +## ![✔] Génération de chaînes aléatoires à l'aide de Node.js + +**TL;PL :** L'utilisation d'une fonction personnalisée générant des chaînes pseudo-aléatoires pour les jetons et autres cas d'utilisation sensibles à la sécurité pourrait en fait ne pas être aussi aléatoire que vous le pensez, rendant votre application vulnérable aux attaques cryptographiques. Lorsque vous devez générer des chaînes aléatoires sécurisées, utilisez la fonction [`crypto.randomBytes(size, [callback])`](https://nodejs.org/api/crypto.html#crypto_crypto_randombytes_size_callback) en utilisant l'entropie disponible fournie par le système. + +**Autrement :** Lors de la génération de chaînes pseudo-aléatoires sans recourir à des méthodes cryptographiques sûres, les pirates peuvent prévoir et reproduire les résultats générés, ce qui rend votre application peu sûre. + +

+ +Nous avons énuméré ci-dessous quelques conseils importants tirés du projet OWASP. + +## ![✔] OWASP A2 : Authentification frauduleuse + +- Exigez MFA/2FA pour les services et comptes importants +- Changez fréquemment les mots de passe et les clés d'accès, y compris les clés SSH +- Appliquez des politiques strictes en matière de mots de passe, tant pour l'exploitation que pour la gestion des utilisateurs dans l'application ([🔗 OWASP recommandation sur le mot de passe](https://www.owasp.org/index.php/Authentication_Cheat_Sheet#Implement_Proper_Password_Strength_Controls.22)) +- N'envoyez ou ne déployez pas votre application avec des identifiants par défaut, en particulier pour les utilisateurs de l'administration ou les services externes dont vous dépendez +- Utilisez uniquement des méthodes d'authentification standard comme OAuth, OpenID, etc, **évitez** l'authentification de base +- Limitez le taux d'authentification : interdisez plus de _X_ tentatives de connexion (y compris la récupération du mot de passe, etc.) pendant une période _Y_. +- En cas d'échec de la connexion, n'indiquez pas à l'utilisateur si la vérification du nom d'utilisateur ou du mot de passe a échoué, mais renvoyez simplement une erreur d'authentification ordinaire. +- Envisagez d'utiliser un système de gestion des utilisateurs centralisé pour éviter de gérer plusieurs comptes par employé (par exemple GitHub, AWS, Jenkins, etc.) et pour bénéficier d'un système de gestion des utilisateurs éprouvé + +## ![✔] OWASP A5 : Contrôle d'accès défectueux + +- Respectez le [principe de moindre privilège](https://fr.wikipedia.org/wiki/Principe_de_moindre_privil%C3%A8ge)  -  chaque composant et chaque personne du DevOps ne doit avoir accès qu'aux informations et ressources nécessaires +- **Ne travaillez jamais** avec le compte console/root (privilège total) sauf pour la gestion de compte +- Exécutez toutes les instances/conteneurs sous le nom d'un compte de rôle/service +- Attribuez des autorisations à des groupes et non à des utilisateurs. Cela devrait rendre la gestion des permissions plus facile et plus transparente dans la plupart des cas + +## ![✔] OWASP A6 : Mauvaise configuration de la sécurité + +- L'accès à l'environnement interne de production se fait uniquement par le réseau interne, en utilisant SSH ou d'autres moyens, mais _n'exposez jamais_ les services internes +- Restreignez l'accès au réseau interne - définissez explicitement quelle ressource peut accéder à quelles autres ressources (par exemple, la politique du réseau ou des sous-réseaux) +- Si vous utilisez des cookies, configurez-les en mode « sécurisés » afin qu'ils soient envoyés uniquement via SSL +- Si vous utilisez des cookies, configurez-les uniquement pour un « même site » afin que seules les requêtes provenant d'un même domaine puissent récupérer les cookies indiqués. +- Si vous utilisez des cookies, préférez une configuration « HttpOnly » qui empêche le code JavaScript côté client d'accéder aux cookies +- Protégez chaque VPC par des règles d'accès strictes et restrictives +- Priorisez les menaces en utilisant n'importe quel modèle standard de menace de sécurité comme STRIDE ou DREAD +- Protégez-vous contre les attaques DDoS à l'aide d'équilibreurs de charge HTTP(S) et TCP +- Effectuez des tests de pénétration périodiques par des agences spécialisées + +## ![✔] OWASP A3 : Exposition des données sensibles + +- N'acceptez que les connexions SSL/TLS, appliquez Strict-Transport-Security en utilisant les entêtes +- Séparez le réseau en segments (c'est-à-dire sous-réseaux) et assurez-vous que chaque nœud dispose uniquement des autorisations d'accès nécessaires au réseau +- Regroupez tous les services/instances qui n'ont pas besoin d'accès à internet et interdisez explicitement toute connexion sortante (un sous-réseau privé) +- Stockez tous les secrets dans un coffre-fort, des produits comme AWS KMS, HashiCorp Vault ou Google Cloud KMS +- Verrouillez les métadonnées d'instance sensibles à l'aide de métadonnées +- Cryptez les données en transit lorsqu'elles quittent une frontière physique +- N'incluez pas de secrets dans les instructions de journal +- Évitez d'afficher des mots de passe en clair dans le frontend, prenez les mesures nécessaires dans le backend et ne stockez jamais d'informations sensibles en clair + +## ![✔] OWASP A9 : Utilisation de composants avec des vulnérabilités de sécurité connues + +- Analysez les images des dockers à la recherche de vulnérabilités connues (en utilisant les services d'analyse de Docker et d'autres fournisseurs) +- Activez les correctifs et les mises à jour automatiques des instances (machines) pour éviter d'utiliser des versions de systèmes d'exploitation anciennes qui ne disposent pas de correctifs de sécurité +- Fournissez à l'utilisateur les jetons « id », « access » et « refresh » afin que le jeton d'accès soit de courte durée et renouvelé avec le jeton « refresh » +- Enregistrez et auditerz chaque appel d'API vers les services de gestion et de cloud (par exemple, qui a supprimé le compartiment S3 ?) en utilisant des services comme AWS CloudTrail +- Exécutez le contrôle de sécurité de votre fournisseur de services en ligne (par exemple, le conseiller en sécurité de AWS) + + +## ![✔] OWASP A10 : Journalisation et surveillance insuffisantes + +- Alertez sur les événements d'audit significatifs ou suspects tels que la connexion d'un utilisateur, la création d'un nouvel utilisateur, le changement d'autorisation, etc. +- Alertez sur le nombre irrégulier d'échecs de connexion (ou actions équivalentes comme l'oubli du mot de passe) +- Indiquez l'heure et le nom de l'utilisateur qui a initié la mise à jour dans chaque enregistrement de la base de données + +## ![✔] OWASP A7 : Cross-Site-Scripting (XSS) + +- Utilisez des moteurs ou des frameworks de template qui échappent automatiquement le XSS par leur conception, comme EJS, Pug, React ou Angular. Apprenez les limites de chaque mécanisme de protection XSS et traiter de manière appropriée les cas d'utilisation qui ne sont pas couverts +- Échappez les données de requête HTTP non fiables en fonction du contexte dans la sortie HTML (corps, attribut, JavaScript, CSS ou URL) résoudra les vulnérabilités XSS reflétées et stockées +- L'application d'un encodage contextuel lors de la modification du document du navigateur côté client agit contre DOM XSS +- Permettez une politique de sécurité des contenus (CSP) comme défense en profondeur pour atténuer le contrôle contre les XSS + +## ![✔] Protégez les informations personnelles identifiables (données PII) + +- Les informations personnelles identifiables (PII : Personally identifiable information) sont toutes les données qui peuvent être utilisées pour identifier une personne spécifique +- Protégez les informations personnelles identifiables dans les applications en les cryptant +- Respectez les lois du pays en matière de protection des données. Lois de référence : + - Union européenne : RGPD - https://ec.europa.eu/info/law/law-topic/data-protection_fr + - Inde : https://meity.gov.in/writereaddata/files/Personal_Data_Protection_Bill,2018.pdf + - Singapour : https://www.pdpc.gov.sg/Overview-of-PDPA/The-Legislation/Personal-Data-Protection-Act + +## ![✔] Avoir un fichier security.txt [PRODUCTION] + +**TL;PL :** Ayez un fichier texte appelé ```security.txt``` sous le répertoire ```/.well-known``` (/.well-known/security.txt) ou dans le répertoire racine (/security.txt) de votre site web ou de votre application web en production. Le fichier ```security.txt``` doit contenir les détails permettant aux chercheurs en sécurité de signaler des vulnérabilités, ainsi que les coordonnées de la personne/du groupe responsable (adresse électronique et/ou numéros de téléphone) à qui les rapports doivent être envoyés. + +**Autrement :** Il se peut que vous ne soyez pas informé des vulnérabilités. Vous manquerez l'occasion d'agir à temps sur les vulnérabilités. + +🔗 [**Plus d'infos : security.txt**](https://securitytxt.org/) +


+ +## ![✔] Avoir un fichier SECURITY.md [OPEN SOURCE] + +**TL;PL :** Pour donner aux gens des instructions pour signaler de manière responsable les vulnérabilités de sécurité dans votre projet, vous pouvez ajouter un fichier SECURITY.md file à la racine de votre dépôt, dans le dossier docs ou .github. Le fichier SECURITY.md doit contenir les détails permettant aux chercheurs en sécurité de signaler les vulnérabilités, ainsi que les coordonnées de la personne/du groupe responsable (adresse électronique et/ou numéros de téléphone) à qui les rapports doivent être envoyés. + +**Autrement :** Il se peut que vous ne soyez pas informé des vulnérabilités. Vous manquerez l'occasion d'agir à temps sur les vulnérabilités. + +🔗 [**Plus d'infos : SECURITY.md**](https://help.github.com/en/github/managing-security-vulnerabilities/adding-a-security-policy-to-your-repository) + +


+ + +


diff --git a/sections/security/commonsecuritybestpractices.japanese.md b/sections/security/commonsecuritybestpractices.japanese.md index faa4c3a15..1aa5549a1 100644 --- a/sections/security/commonsecuritybestpractices.japanese.md +++ b/sections/security/commonsecuritybestpractices.japanese.md @@ -10,7 +10,7 @@ **さもないと:** 接続が暗号化されていない場合には、攻撃者は中間者攻撃を行い、ユーザーの行動を監視し、さらに悪質なアクションを行ってくる可能性があります。 -🔗 [**さらに読む: セキュアな Node.js サーバーを実行する**](/sections/security/secureserver.japanese.md) +🔗 [**さらに読む: セキュアな Node.js サーバーを実行する**](./secureserver.japanese.md)

diff --git a/sections/security/commonsecuritybestpractices.md b/sections/security/commonsecuritybestpractices.md index 1ba97c5fb..86a906f27 100644 --- a/sections/security/commonsecuritybestpractices.md +++ b/sections/security/commonsecuritybestpractices.md @@ -10,7 +10,7 @@ The common security guidelines section contains best practices that are standard **Otherwise:** Attackers could perform man-in-the-middle attacks, spy on your users' behaviour and perform even more malicious actions when the connection is unencrypted -🔗 [**Read More: Running a secure Node.js server**](/sections/security/secureserver.md) +🔗 [**Read More: Running a secure Node.js server**](./secureserver.md)

@@ -102,7 +102,7 @@ Going on, below we've listed some important bits of advice from the OWASP projec - Follow the data privacy laws of the land. Reference laws: - European Union: GDPR - https://ec.europa.eu/info/law/law-topic/data-protection_en - India: https://meity.gov.in/writereaddata/files/Personal_Data_Protection_Bill,2018.pdf - - Singapore: https://www.pdpc.gov.sg/Legislation-and-Guidelines/Personal-Data-Protection-Act-Overview + - Singapore: https://www.pdpc.gov.sg/Overview-of-PDPA/The-Legislation/Personal-Data-Protection-Act ## ![✔] Have a security.txt File [PRODUCTION] diff --git a/sections/security/commonsecuritybestpractices.polish.md b/sections/security/commonsecuritybestpractices.polish.md index 5bc707f7b..1638ec8ae 100644 --- a/sections/security/commonsecuritybestpractices.polish.md +++ b/sections/security/commonsecuritybestpractices.polish.md @@ -10,7 +10,7 @@ Sekcja wspólnych wskazówek bezpieczeństwa zawiera najlepsze praktyki, które **W przeciwnym razie:** Atakujący mogą przeprowadzać ataki typu man-in-the-middle, szpiegować zachowanie użytkowników i wykonywać jeszcze bardziej złośliwe działania, gdy połączenie nie jest szyfrowane -🔗 [**Czytaj więcej: Running a secure Node.js server**](/sections/security/secureserver.md) +🔗 [**Czytaj więcej: Running a secure Node.js server**](./secureserver.md)

diff --git a/sections/security/commonsecuritybestpractices.russian.md b/sections/security/commonsecuritybestpractices.russian.md index a69db38fa..c5bd479de 100644 --- a/sections/security/commonsecuritybestpractices.russian.md +++ b/sections/security/commonsecuritybestpractices.russian.md @@ -10,7 +10,7 @@ **Иначе:** Злоумышленники могут выполнять атаки "человек посередине", следить за поведением ваших пользователей и совершать еще более злонамеренные действия, когда соединение не зашифровано. -🔗 [**Read More: Запуск безопасного Node.js сервера**](/sections/security/secureserver.russian.md) +🔗 [**Read More: Запуск безопасного Node.js сервера**](./secureserver.russian.md)

diff --git a/sections/security/dependencysecurity.basque.md b/sections/security/dependencysecurity.basque.md new file mode 100644 index 000000000..beb8d0825 --- /dev/null +++ b/sections/security/dependencysecurity.basque.md @@ -0,0 +1,54 @@ +# Etengabe eta automatikoki ikuskatu mendekotasun ba ote dagoen zaurgarritik + +### Azalpena + +Node.js aplikazio gehienak inork egindako npm edo Yarn modulu ugarietan oinarritzen dira, pakete erregistro ezagunak biak, garatzeko erraztasuna eta azkartasuna dituzte eta. Hala ere, abantaila horren alde txarra da ahulezia ezezagunak dituela zure aplikazioan sartuz gero haren segurtasunari arriskuak eragin ahal dizkiona, hau da, OWASP web aplikazioen segurtasun arrisku larrien zerrendan duten lekuagatik ezagunak direnak. + +Node.js aplikazioetan tresna ugari erabil daitezke hirugarrenen paketeetan ahulak diren aplikazioak identifikatzen laguntzeko, zure proiektuan sartzeko arriskua arintze aldera . Horiek aldizka CLI tresnetatik erabil daitezke edo zure aplikazioaren eraikuntza prozesuaren barruan sartu. + +### Edukien taula + +- [NPM audit](#npm-audit) +- [Snyk](#snyk) +- [Greenkeeper](#greenkeeper) +- [Baliabide osagarriak](#baliabide-osagarriak) + +### NPM Audit + +`npm audit` NPM @ 6-rekin batera sartutako cli tresna berria da. + +Npm auditoretza exekutatzeak segurtasun ahultasunen txostena sortuko du kaltetutako paketearen izenarekin, zaurgarritasunaren larritasunarekin eta deskribapenarekin, bidearekin eta bestelako informazioarekin, eta, gainera, ahultasunak konpontzeko adabakiak aplikatzeko aginduak emango ditu, eskuragarri egonez gero. + +![npm audit adibidea](../../assets/images/npm-audit.png) + +🔗 [Irakurri: NPM bloga](https://docs.npmjs.com/getting-started/running-a-security-audit) + +### Snyk + +Snykek funtzio aberatsa duen CLI bat eskaintzen du, baita GitHub integrazioa ere. Horrekin Snyk urrunago doa eta, ahultasunak jakinarazteaz gain, ahuleziak konpontzen dituen erauzte eskaera berriak ere sortzen ditu automatikoki, adabakiak ahulezia ezagunetarako kaleratzen baitira. + +Snyken webgune aberatsak mendekotasunak ad-hoc ebaluatzeko aukera ere ematen du GitHub biltegiarekin edo npm moduluaren URLarekin hornituta. Ahuleziak dituzten npm paketeak ere bila ditzakezu zuzenean. + +Synk GitHub integrazioaren irteeraren adibide bat, erauzte eskaera automatikoki sortuz: +![snyk GitHub adibidea](../../assets/images/snyk.png) + +🔗 [ Irakurri hemen: Snyk webgunea](https://snyk.io/) + +🔗 [Irakurri: Synk onlineko tresna npm paketeak eta GitHub moduluak egiaztatzeko](https://snyk.io/test) + +### Greenkeeper + +Greenkeeper denbora errealeko menpekotasunen eguneratzeak eskaintzen dituen zerbitzua da, aplikazioak seguruago mantentzen dituena, eguneratutako eta adabakitako menpekotasun bertsioak erabiliz beti. + +Greenkeeperrek biltegi baten `package.json` fitxategian zehaztutako npm menpekotasunak ikusten ditu eta automatikoki laneko adar bat sortzen du menpekotasunen eguneratze bakoitzarekin. Biltegirako CI suite exekutatuko da aplikazioan eguneratutako menpekotasun bertsiorako aldaketa aldakorrak agerian uzteko. IEk huts egiten badu menpekotasunaren eguneratzea dela eta, gai argia eta zehatza sortzen da enkantean jarri nahi den biltegian, uneko eta eguneratutako paketeen bertsioak azalduz, informazioarekin eta eguneratutako bertsioaren konpromiso historiarekin batera. + +Greenkeeper GitHub integrazioaren irteeraren adibide bat erauzte eskaera automatikoki sortuz: + +![synk github adibidea](../../assets/images/greenkeeper.png) +🔗 [Irakurri: Greenkeeper webgunea](https://greenkeeper.io/) + +### Baliabide osagarriak + +🔗 [Rising Stack bloga: Node.jsren menpekotasun arriskuak](https://blog.risingstack.com/controlling-node-js-security-risk-npm-dependencies/) + +🔗 [NodeSource Bloga: npmen segurtasuna hobetzea](https://nodesource.com/blog/how-to-reduce-risk-and-improve-security-around-npm) diff --git a/sections/security/dependencysecurity.brazilian-portuguese.md b/sections/security/dependencysecurity.brazilian-portuguese.md index 012a7ea11..54b0ebc63 100644 --- a/sections/security/dependencysecurity.brazilian-portuguese.md +++ b/sections/security/dependencysecurity.brazilian-portuguese.md @@ -18,7 +18,7 @@ Há várias ferramentas disponíveis para ajudar a identificar pacotes de tercei A execução de `npm audit` produzirá um relatório de vulnerabilidades de segurança com o nome do pacote afetado, gravidade da vulnerabilidade e descrição, caminho e outras informações e, se disponíveis, comandos para aplicar correções para resolver vulnerabilidades. -![exemplos do npm audit](/assets/images/npm-audit.png) +![exemplos do npm audit](../../assets/images/npm-audit.png) 🔗 [Leia em: NPM blog](https://docs.npmjs.com/getting-started/running-a-security-audit) @@ -29,7 +29,7 @@ O Snyk oferece uma CLI rica em recursos, bem como integração com o GitHub. O S O site do Snyk, rico em recursos, também permite uma avaliação ad-hoc das dependências, quando fornecido com um repositório do GitHub ou url do módulo npm. Você também pode procurar por pacotes npm que possuem vulnerabilidades diretamente. Um exemplo da saída da integração do Synk GitHub, solicitação de pull criada automaticamente: -![exemplo do synk GitHub](/assets/images/snyk.png) +![exemplo do synk GitHub](../../assets/images/snyk.png) 🔗 [Leia em: Snyk website](https://snyk.io/) @@ -43,7 +43,7 @@ O Greenkeeper observa as dependências npm especificadas no arquivo `package.jso Um exemplo da saída da solicitação do Greenkeeper GitHub automaticamente criado pull request: -![exemplo do synk github](/assets/images/greenkeeper.png) +![exemplo do synk github](../../assets/images/greenkeeper.png) 🔗 [Leia em: site do Greenkeeper](https://greenkeeper.io/) ### Recursos Adicionais diff --git a/sections/security/dependencysecurity.french.md b/sections/security/dependencysecurity.french.md new file mode 100644 index 000000000..b625e55cc --- /dev/null +++ b/sections/security/dependencysecurity.french.md @@ -0,0 +1,54 @@ +# Inspectez constamment et automatiquement les dépendances vulnérables + +### Un paragraphe d'explication + +La majorité des applications Node.js pour des raisons de facilité et de rapidité de développement reposent largement sur un grand nombre de modules tiers de npm ou de Yarn, deux registres de paquets populaires. Cependant, l'inconvénient de cet avantage est le risque d'inclure des vulnérabilités inconnues dans votre application, risque reconnu par son classement dans la liste des principaux risques de sécurité des applications web critiques de l'OWASP. + +Il existe un certain nombre d'outils disponibles pour aider à identifier les paquets tiers dans les applications Node.js qui ont été identifiés comme vulnérables par la communauté afin d'atténuer le risque de les introduire dans votre projet. Ceux-ci peuvent être utilisés périodiquement à partir des outils CLI ou inclus dans le cadre du processus de construction de votre application. + +### Table des matières + +- [NPM audit](#npm-audit) +- [Snyk](#snyk) +- [Greenkeeper](#greenkeeper) +- [Ressources complémentaires](#ressources-complémentaires) + +### NPM Audit + +`npm audit` est un nouvel outil cli introduit avec NPM@6. + +L'exécution de `npm audit` produira un rapport des vulnérabilités de sécurité avec le nom du paquet affecté, la gravité et la description de la vulnérabilité, le chemin et d'autres informations, et si disponibles, des commandes pour appliquer des correctifs pour résoudre les vulnérabilités. + +![exemple npm audit](../../assets/images/npm-audit.png) + +🔗 [A lire : NPM blog](https://docs.npmjs.com/getting-started/running-a-security-audit) + +### Snyk + +Snyk propose une CLI riche en fonctionnalités, ainsi qu'une intégration dans GitHub. Snyk va plus loin dans cette démarche et en plus de notifier les vulnérabilités, il crée automatiquement de nouvelles pull requests corrigeant les vulnérabilités au fur et à mesure que des correctifs sont publiés pour des vulnérabilités connues. + +Le site web riche en fonctionnalités de Snyk permet également une évaluation adéquate des dépendances lorsqu'il est associé avec un dépôt GitHub ou une URL de module npm. Vous pouvez également rechercher directement les paquets npm qui présentent des vulnérabilités. + +Un exemple d'affichage de l'intégration de Snyk avec GitHub qui crée automatiquement un pull request : +![exemple GitHub avec snyk](../../assets/images/snyk.png) + +🔗 [A lire : Site web de Snyk](https://snyk.io/) + +🔗 [A lire : Outil en ligne Synk pour vérifier les paquets npm et les modules GitHub](https://snyk.io/test) + +### Greenkeeper + +Greenkeeper est un service qui propose des mises à jour de dépendances en temps réel, ce qui permet de garder une application plus sûre en utilisant toujours les versions de dépendances les plus récentes et les plus corrigées. + +Greenkeeper surveille les dépendances npm spécifiées dans le fichier `package.json` d'un dépôt et crée automatiquement une branche de travail avec chaque mise à jour de dépendance. La suite CI du dépôt est ensuite exécutée pour révéler les changements de rupture de la version de dépendance mise à jour dans l'application. Si le CI échoue en raison de la mise à jour des dépendances, une issue claire et concise est créée dans le dépôt pour être traitée, décrivant les versions actuelles et mises à jour du paquet, ainsi que les informations et l'historique des commits de la version mise à jour. + +Un exemple d'affichage de l'intégration de Greenkeeper avec GitHub qui crée automatiquement un pull request : + +![exemple Github avec Greenkeeper](../../assets/images/greenkeeper.png) +🔗 [A lire : Site web de Greenkeeper](https://greenkeeper.io/) + +### Ressources complémentaires + +🔗 [Blog de Rising Stack : Risques de dépendance de Node.js](https://blog.risingstack.com/controlling-node-js-security-risk-npm-dependencies/) + +🔗 [Blog de NodeSource : Améliorez la sécurité de npm](https://nodesource.com/blog/how-to-reduce-risk-and-improve-security-around-npm) diff --git a/sections/security/dependencysecurity.japanese.md b/sections/security/dependencysecurity.japanese.md index 5cfe18adf..bd03ac3ea 100644 --- a/sections/security/dependencysecurity.japanese.md +++ b/sections/security/dependencysecurity.japanese.md @@ -18,7 +18,7 @@ Node.js アプリケーションの大部分は、開発の容易化とスピー `npm audit` を実行すると、影響を受けるパッケージ名、脆弱性の深刻度と概要、パス、そしてその他の情報を含むセキュリティ脆弱性のレポートが作成され、さらに、利用可能な場合には脆弱性を解決するためのパッチを適用するためのコマンドが表示されます。 -![npm audit の例](/assets/images/npm-audit.png) +![npm audit の例](../../assets/images/npm-audit.png) 🔗 [NPM blog で読む](https://docs.npmjs.com/getting-started/running-a-security-audit) @@ -29,7 +29,7 @@ Snyk は機能豊富な CLI と GitHub インテグレーションを提供し Snyk の機能豊富なウェブサイトでは、GitHub リポジトリや npm モジュールの URL を与えると、依存性のアドホックな評価を実行することもできます。また、脆弱性がある npm パッケージを直接検索することもできます。 Synk Github インテグレーションが自動的にプルリクエストを作成した際の出力結果例: -![synk GitHub example](/assets/images/snyk.png) +![synk GitHub example](../../assets/images/snyk.png) 🔗 [Snyk website で読む](https://snyk.io/) @@ -43,7 +43,7 @@ Greenkeeper は、リポジトリの `package.json` ファイルで指定され Greenkeeper GitHub インテグレーションが自動的にプルリクエストを作成した際の出力結果例: -![synk github example](/assets/images/greenkeeper.png) +![synk github example](../../assets/images/greenkeeper.png) 🔗 [Greenkeeper website で読む](https://greenkeeper.io/) ### 追加資料 diff --git a/sections/security/dependencysecurity.md b/sections/security/dependencysecurity.md index 1108409c8..11478f1c3 100644 --- a/sections/security/dependencysecurity.md +++ b/sections/security/dependencysecurity.md @@ -19,7 +19,7 @@ There is a number of tools available to help identify third-party packages in No Running `npm audit` will produce a report of security vulnerabilities with the affected package name, vulnerability severity and description, path, and other information, and, if available, commands to apply patches to resolve vulnerabilities. -![npm audit example](/assets/images/npm-audit.png) +![npm audit example](../../assets/images/npm-audit.png) 🔗 [Read on: NPM blog](https://docs.npmjs.com/getting-started/running-a-security-audit) @@ -30,7 +30,7 @@ Snyk offers a feature-rich CLI, as well as GitHub integration. Snyk goes further Snyk's feature rich website also allows for ad-hoc assessment of dependencies when provided with a GitHub repository or npm module url. You can also search for npm packages which have vulnerabilities directly. An example of the output of the Snyk GitHub integration automatically created pull request: -![snyk GitHub example](/assets/images/snyk.png) +![snyk GitHub example](../../assets/images/snyk.png) 🔗 [Read on: Snyk website](https://snyk.io/) @@ -44,7 +44,7 @@ Greenkeeper watches the npm dependencies specified in a repository's `package.js An example of the output of the Greenkeeper GitHub integration automatically created pull request: -![synk github example](/assets/images/greenkeeper.png) +![synk github example](../../assets/images/greenkeeper.png) 🔗 [Read on: Greenkeeper website](https://greenkeeper.io/) ### Additional resources diff --git a/sections/security/dependencysecurity.polish.md b/sections/security/dependencysecurity.polish.md index c2ae63357..47afc29dc 100644 --- a/sections/security/dependencysecurity.polish.md +++ b/sections/security/dependencysecurity.polish.md @@ -18,7 +18,7 @@ Dostępnych jest wiele narzędzi pomagających w identyfikacji pakietów stron t Uruchomienie `npm audit` wygeneruje raport o słabych punktach bezpieczeństwa wraz z nazwą pakietu, istotnością i opisem podatności, ścieżką i innymi informacjami oraz, jeśli są dostępne, polecenia zastosowania łat w celu usunięcia luk. -![npm audit example](/assets/images/npm-audit.png) +![npm audit example](../../assets/images/npm-audit.png) 🔗 [Czytaj: NPM blog](https://docs.npmjs.com/getting-started/running-a-security-audit) @@ -29,7 +29,7 @@ Snyk oferuje bogaty w funkcje interfejs CLI, a także integrację z GitHub. Snyk Bogata w funkcje strona internetowa Snyka pozwala również na ocenę ad-hoc zależności, jeśli jest dostarczana z repozytorium GitHub lub adresem URL modułu npm. Możesz także wyszukiwać pakiety npm, które mają luki bezpośrednio. Przykład danych wyjściowych integracji Synk GitHub automatycznie utworzony pull request: -![synk GitHub example](/assets/images/snyk.png) +![synk GitHub example](../../assets/images/snyk.png) 🔗 [Czytaj: Snyk website](https://snyk.io/) @@ -43,7 +43,7 @@ Greenkeeper śledzi zależności npm określone w pliku `package.json` repozytor Przykład danych wyjściowych integracji Greenkeeper GitHub tworzący automatycznie pull request: -![synk github example](/assets/images/greenkeeper.png) +![synk github example](../../assets/images/greenkeeper.png) 🔗 [Czytaj: Greenkeeper website](https://greenkeeper.io/) ### Dodatkowe źródła diff --git a/sections/security/dependencysecurity.russian.md b/sections/security/dependencysecurity.russian.md index adf4aee5d..0ebe882e7 100644 --- a/sections/security/dependencysecurity.russian.md +++ b/sections/security/dependencysecurity.russian.md @@ -19,7 +19,7 @@ Запуск `npm audit` выдаст отчет об уязвимостях безопасности с указанием имени уязвимого пакета, серьезности и описания уязвимости, пути и другой информации, а также, если доступно, команд для применения исправлений для устранения уязвимостей. -![npm audit example](/assets/images/npm-audit.png) +![npm audit example](../../assets/images/npm-audit.png) 🔗 [Читайте еще: NPM blog](https://docs.npmjs.com/getting-started/running-a-security-audit) @@ -30,7 +30,7 @@ Snyk предлагает многофункциональный интерфе Многофункциональный веб-сайт Snyk также позволяет проводить специальную оценку зависимостей, когда предоставляется GitHub-репозиторий или URL-адрес модуля npm. Вы также можете искать пакеты npm, которые имеют уязвимости напрямую. Пример вывода интеграции Synk GitHub с автоматически созданным пул-запросом: -![synk GitHub example](/assets/images/snyk.png) +![synk GitHub example](../../assets/images/snyk.png) 🔗 [Читайте еще: Snyk website](https://snyk.io/) @@ -44,7 +44,7 @@ Greenkeeper следит за зависимостями npm, указанным Пример вывода интеграции Greenkeeper GitHub с автоматически созданным запросом на извлечение: -![synk github example](/assets/images/greenkeeper.png) +![synk github example](../../assets/images/greenkeeper.png) 🔗 [Читайте еще: Greenkeeper website](https://greenkeeper.io/) ### Дополнительные ресурсы diff --git a/sections/security/escape-output.basque.md b/sections/security/escape-output.basque.md new file mode 100644 index 000000000..c99a7848e --- /dev/null +++ b/sections/security/escape-output.basque.md @@ -0,0 +1,66 @@ +# Ihes irteera + +### Azalpena + +HTML eta beste web lengoaia batzuek kode egikarigarriarekin nahasten dute edukia. HTML paragrafo bakar batek datuen irudikapen bisuala izan dezake JavaScript egikaritzeko argibideekin batera. HTMLa kargatzean edo APItik datuak itzultzean, gure ustez eduki hutsa denak JavaScript kodea har lezake, nabigatzaileak interpretatu eta egikaritzeko modukoa. Hori gertatzen da, adibidez, erasotzaile batek datu base batean txertatutako edukia kargatzen dugunean, adibidez `
`. Hori arindu daiteke arakatzaileari aginduz konfiantzazko datuen zatiak edukitzat soilik tratatzeko eta inoiz ez interpretatzeko. Teknika horri ihes egitea deritzo. Npm liburutegi eta HTML txantiloi motor askok ihes egiteko baliabideak eskaintzen dituzte (adibidez: [escape-html](https://github.com/component/escape-html), [node-esapi](https://github.com/ESAPI/node-esapi))). HTML edukiak ez ezik CSSk eta JavaScriptek ere ihes egin beharko lukete + + + +### Kode adibidea: ez jarri fidagarritasunik gabeko daturik zure HTMLan + +```html + zuzenean scriptean + + HTML komentario baten barruan + +
ezaugarri izen batean + + tag izen batean + + CSSan zuzenean + +``` + +### Kode adibidea: datu base batean txerta daitekeen eduki kaltegarria + +```html +
+ Komentario bat + +
+ +``` + +

+ +### Blog aipua: "Pertsonaiak interpretatuak izatea nahi ez dugunean" + +[benramsey.com](https://benramsey.com/articles/escape-output/) bloga: +> Datuak modu askotara irten daitezke zure aplikaziotik: web nabigatzaile bati bidalitako HTML moduan, SQL datu basera bidalita, XML RSS irakurgailura bidalita, WML haririk gabeko gailu batera bidalita, etab. Aukerak mugagabeak dira. Horietako bakoitzak bere karaktere bereziak ditu, multzoka jasotzen dituena, eta jasotako gainerako testu arruntaren aldean desberdin interpretatzen dena. Batzuetan, karaktere berezi horiek bidali nahi ditugu interpretatuak izan ahal izateko (HTML nabigatzaile batera bidalitako HTML etiketak, adibidez); beste batzuetan (erabiltzaileek edo beste iturri batzuek egindako sarreren kasuan), ez dugu nahi karaktere horiek interpretatuak izan daitezen, eta, beraz, ihes egin behar diegu. + +> Ihes egiteari kodetzea ere esaten zaio batzuetan: ihes egitea edo kodetzea, laburbilduz,, datuak egikaritu edo interpretatuko ez diren moduan irudikatzeko prozesua da, alegia. Adibidez, HTMLk honako testu hau letra lodiz idatziko du web nabigatzaile batean ``etiketek esanahi berezia dutelako: +> ```html +> Testu hau letra lodiz idatzita dago. +> ``` +> +> Baina, demagun etiketak nabigatzailean kargatu nahi ditudala eta haien interpretazioa ekidin nahi dudala. Orduan, HTMLan esanahi berezia duten parentesi angeluarretatik ihes egin behar dut. Hona hemen ihes egindako HTMLa: +> +> ```html +> <strong>Testu hau letra lodiz idatzita dago.</strong>` +> ``` + +

+ +### Blog aipua: "OWASPek segurtasunera bideratutako kodeketa liburutegia erabiltzea gomendatzen du" + +OWASP [XSS (Cross Site Scripting) Prebentzio tranpa orria](https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet) bloga: +> "Kodetzaile horiek idaztea ez da oso zaila, baina tranpa ugari daude ezkutuan. Adibidez, Javascripten bezalako lasterbide batzuk" erabiltzeko tentazioa izan dezakezu. Hala ere, balio horiek arriskutsuak dira, eta nabigatzailean habiaratutako analizatzaileek oker interpreta ditzakete. Baliteke zuri ahaztea ihes egitea ihes pertsonaiarengandik, erasotzaileek erabil dezaketeena neutralizatzeko zure segurtasun ahaleginak. **OWASPek gomendatzen du segurtasunera bideratutako kodeketa liburutegiak erabiltzea, arauak behar bezala ezartzen direla ziurtatzeko**." + +

+ +### Blog aipua: "Ihes sintaxia erabili behar duzu HTML zatian" + +OWASP [XSS (Cross Site Scripting) Prebentzio tranpa orria](https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet) bloga: +> "Baina HTML entitate kodeketak ez du ondo funtzionatzen ` direto em um script dentro de um comentário HTML @@ -22,7 +22,7 @@ HTML e outras linguagens da Web combinam conteúdo com código executável - um ### Exemplo de código - Conteúdo mal-intencionado que pode ser injetado em um banco de dados -```javascript +```html
A pseudo comment to the a post
`. This can be mitigated by instructing the browser to treat any chunk of untrusted data as content only and never interpret it - this technique is called escaping. Many npm libraries and HTML templating engines provide escaping capabilities (example: [escape-html](https://github.com/component/escape-html), [node-esapi](https://github.com/ESAPI/node-esapi)). Not only HTML content should be escaped but also CSS and JavaScript + + +### Code example - Don't put untrusted data into your HTML + +```html + directly in a script + + inside an HTML comment + +
in an attribute name + + in a tag name + + directly in CSS + +``` + +### Code example - Malicious content that might be injected into a DB + +```html +
+ A pseudo comment to the a post + +
+ +``` + +

+ +### Blog Quote: "When we don’t want the characters to be interpreted" + +From the Blog [benramsey.com](https://benramsey.com/articles/escape-output/) +> Data may leave your application in the form of HTML sent to a Web browser, SQL sent to a database, XML sent to an RSS reader, WML sent to a wireless device, etc. The possibilities are limitless. Each of these has its own set of special characters that are interpreted differently than the rest of the plain text received. Sometimes we want to send these special characters so that they are interpreted (HTML tags sent to a Web browser, for example), while other times (in the case of input from users or some other source), we don’t want the characters to be interpreted, so we need to escape them. +> +> Escaping is also sometimes referred to as encoding. In short, it is the process of representing data in a way that it will not be executed or interpreted. For example, HTML will render the following text in a Web browser as bold-faced text because the `` tags have special meaning: +> +> ```html +> This is bold text. +> ``` +> +> But, suppose I want to render the tags in the browser and avoid their interpretation. Then, I need to escape the angle brackets, which have special meaning in HTML. The following illustrates the escaped HTML: +> +> ```html +> <strong>This is bold text.</strong> +> ``` + +

+ +### Blog Quote: "OWASP recommends using a security-focused encoding library" + +From the blog OWASP [XSS (Cross Site Scripting) Prevention Cheat Sheet](https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet) +> "Writing these encoders is not tremendously difficult, but there are quite a few hidden pitfalls. For example, you might be tempted to use some of the escaping shortcuts like \" in JavaScript. However, these values are dangerous and may be misinterpreted by the nested parsers in the browser. You might also forget to escape the escape character, which attackers can use to neutralize your attempts to be safe. **OWASP recommends using a security-focused encoding library to make sure these rules are properly implemented**." + + +

+ +### Blog Quote: "You MUST use the escape syntax for the part of the HTML" + +From the blog OWASP [XSS (Cross Site Scripting) Prevention Cheat Sheet](https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet) +> "But HTML entity encoding doesn't work if you're putting untrusted data inside a ` directly in a script inside an HTML comment @@ -22,7 +22,7 @@ HTML and other web languages mix content with executable code - a single HTML pa ### Code example - Malicious content that might be injected into a DB -```javascript +```html
A pseudo comment to the a post directly in a script inside an HTML comment @@ -21,7 +21,7 @@ HTML i inne języki internetowe mieszają zawartość z kodem wykonywalnym - poj ### Przykład kodu - złośliwe treści, które mogą zostać wstrzyknięte do bazy danych -```javascript +```html
A pseudo comment to the a post directly in a script inside an HTML comment @@ -22,7 +22,7 @@ HTML и другие веб-языки смешивают контент с ис ### Пример кода - вредоносный контент, который может быть введен в БД -```javascript +```html
A pseudo comment to the a post