├── .all-contributorsrc ├── .github └── stale.yml ├── .gitignore ├── .operations ├── .common-answers.md ├── .env.example ├── .markdownlint.json ├── CONTRIBUTING.md ├── gen-html.js ├── operations-manual.md ├── out │ └── .gitignore ├── package.json ├── res │ ├── github.css │ ├── highlight.pack.js │ ├── normalize.css │ ├── skeleton.css │ └── template.html ├── writing-guidelines.basque.md ├── writing-guidelines.chinese.md ├── writing-guidelines.indonesia.md ├── writing-guidelines.japanese.md ├── writing-guidelines.md ├── writing-guidelines.polish.md └── writing-guidelines.russian.md ├── .travis.yml ├── LICENSE ├── README.basque.md ├── README.brazilian-portuguese.md ├── README.chinese.md ├── README.japanese.md ├── README.korean.md ├── README.md ├── README.polish.md ├── README.russian.md ├── assets ├── flags │ ├── BR.jpg │ ├── BR.png │ ├── CN.png │ ├── ES.png │ ├── EU.png │ ├── FR.png │ ├── HE.png │ ├── JA.png │ ├── KR.png │ ├── PL.png │ ├── RU.png │ └── TR.png └── images │ ├── 6-parts-in-test.jpg │ ├── Kubernetes-graceful-shutdown-flowchart.png │ ├── Privatenpm.png │ ├── Sketch (8).png │ ├── anchore-report.png │ ├── apm1.png │ ├── apm2.png │ ├── apm3.png │ ├── app-dynamics-dashboard.png │ ├── banner-1.png │ ├── banner-2.jpg │ ├── banner-3.jpg │ ├── banner-4.jpg │ ├── checkbox-sm.png │ ├── checkbox-small-blue.png │ ├── checkbox-small.PNG │ ├── checkmark-green-small.png │ ├── checkmark-green.png │ ├── checkmark-green_small.png │ ├── circleci.png │ ├── codeanalysis-climate-complex-methods.PNG │ ├── codeanalysis-climate-history.PNG │ ├── codeanalysis-sonarqube-dashboard.PNG │ ├── concat-benchmark.png │ ├── createmaintenanceendpoint1.png │ ├── docker_layers_schema.png │ ├── error-handling-flow.png │ ├── eslint-plugin-security.png │ ├── event-loop.png │ ├── greenkeeper.png │ ├── integration-test-roi.PNG │ ├── jenkins_dashboard.png │ ├── keepexpressinweb.gif │ ├── kibana-graph-1024x550.jpg │ ├── kibana-raw-1024x637.png │ ├── linkedin.png │ ├── logging-overview.png │ ├── members │ ├── bruno.png │ ├── ido.png │ ├── keith.png │ ├── kevyn.png │ ├── kyle.png │ ├── refael.png │ ├── sagir.png │ └── yoni.png │ ├── monitoring1.png │ ├── monitoring2.jpg │ ├── monitoring3.png │ ├── npm-audit.png │ ├── placeholdet.txt │ ├── sampleMeanDiag.png │ ├── setnodeenv1.png │ ├── smartlogging1.png │ ├── smartlogging2.jpg │ ├── snyk.png │ ├── structurebycomponents.PNG │ ├── structurebyroles.PNG │ ├── swaggerDoc.png │ ├── swaggerMarkup.png │ ├── test-report-like-requirements.jpeg │ ├── testingpyramid.png │ ├── twitter-s.png │ ├── twitter.png │ ├── uptimerobot.jpg │ ├── utilizecpucores1.png │ ├── viconblue.PNG │ ├── www.png │ └── ydnlu.png └── sections ├── codestylepractices ├── eslint_prettier.basque.md ├── eslint_prettier.brazilian-portuguese.md ├── eslint_prettier.chinese.md ├── eslint_prettier.japanese.md ├── eslint_prettier.korean.md ├── eslint_prettier.md ├── eslint_prettier.polish.md └── eslint_prettier.russian.md ├── docker ├── avoid-build-time-secrets.chinese.md ├── avoid-build-time-secrets.japanese.md ├── avoid-build-time-secrets.md ├── bootstrap-using-node.chinese.md ├── bootstrap-using-node.japanese.md ├── bootstrap-using-node.md ├── clean-cache.japanese.md ├── clean-cache.md ├── docker-ignore.japanese.md ├── docker-ignore.md ├── generic-tips.japanese.md ├── generic-tips.md ├── graceful-shutdown.japanese.md ├── graceful-shutdown.md ├── image-tags.japanese.md ├── image-tags.md ├── install-for-production.japanese.md ├── install-for-production.md ├── lint-dockerfile.japanese.md ├── lint-dockerfile.md ├── memory-limit.japanese.md ├── memory-limit.md ├── multi_stage_builds.japanese.md ├── multi_stage_builds.md ├── restart-and-replicate-processes.japanese.md ├── restart-and-replicate-processes.md ├── scan-images.japanese.md ├── scan-images.md ├── smaller_base_images.japanese.md ├── smaller_base_images.md ├── use-cache-for-shorter-build-time.japanese.md └── use-cache-for-shorter-build-time.md ├── drafts ├── readme-general-toc-1.md ├── readme-general-toc-2.md ├── readme-general-toc-3.md └── readme-general-toc-4.md ├── errorhandling ├── apmproducts.basque.md ├── apmproducts.brazilian-portuguese.md ├── apmproducts.chinese.md ├── apmproducts.japanese.md ├── apmproducts.korean.md ├── apmproducts.md ├── apmproducts.polish.md ├── apmproducts.russian.md ├── asyncerrorhandling.basque.md ├── asyncerrorhandling.brazilian-portuguese.md ├── asyncerrorhandling.chinese.md ├── asyncerrorhandling.japanese.md ├── asyncerrorhandling.korean.md ├── asyncerrorhandling.md ├── asyncerrorhandling.polish.md ├── asyncerrorhandling.russian.md ├── catchunhandledpromiserejection.basque.md ├── catchunhandledpromiserejection.brazilian-portuguese.md ├── catchunhandledpromiserejection.chinese.md ├── catchunhandledpromiserejection.japanese.md ├── catchunhandledpromiserejection.korean.md ├── catchunhandledpromiserejection.md ├── catchunhandledpromiserejection.polish.md ├── catchunhandledpromiserejection.russian.md ├── centralizedhandling.basque.md ├── centralizedhandling.brazilian-portuguese.md ├── centralizedhandling.chinese.md ├── centralizedhandling.japanese.md ├── centralizedhandling.korean.md ├── centralizedhandling.md ├── centralizedhandling.polish.md ├── centralizedhandling.russian.md ├── documentingusingswagger.basque.md ├── documentingusingswagger.brazilian-portuguese.md ├── documentingusingswagger.chinese.md ├── documentingusingswagger.japanese.md ├── documentingusingswagger.korean.md ├── documentingusingswagger.md ├── documentingusingswagger.polish.md ├── documentingusingswagger.russian.md ├── failfast.basque.md ├── failfast.brazilian-portuguese.md ├── failfast.chinese.md ├── failfast.japanese.md ├── failfast.korean.md ├── failfast.md ├── failfast.polish.md ├── failfast.russian.md ├── monitoring.chinese.md ├── monitoring.japanese.md ├── monitoring.md ├── monitoring.russian.md ├── operationalvsprogrammererror.basque.md ├── operationalvsprogrammererror.brazilian-portuguese.md ├── operationalvsprogrammererror.chinese.md ├── operationalvsprogrammererror.japanese.md ├── operationalvsprogrammererror.korean.md ├── operationalvsprogrammererror.md ├── operationalvsprogrammererror.polish.md ├── operationalvsprogrammererror.russian.md ├── returningpromises.basque.md ├── returningpromises.md ├── returningpromises.russian.md ├── shuttingtheprocess.basque.md ├── shuttingtheprocess.brazilian-portuguese.md ├── shuttingtheprocess.chinese.md ├── shuttingtheprocess.japanese.md ├── shuttingtheprocess.korean.md ├── shuttingtheprocess.md ├── shuttingtheprocess.polish.md ├── shuttingtheprocess.russian.md ├── testingerrorflows.basque.md ├── testingerrorflows.brazilian-portuguese.md ├── testingerrorflows.chinese.md ├── testingerrorflows.japanese.md ├── testingerrorflows.korean.md ├── testingerrorflows.md ├── testingerrorflows.polish.md ├── testingerrorflows.russian.md ├── usematurelogger.basque.md ├── usematurelogger.brazilian-portuguese.md ├── usematurelogger.chinese.md ├── usematurelogger.japanese.md ├── usematurelogger.korean.md ├── usematurelogger.md ├── usematurelogger.polish.md ├── usematurelogger.russian.md ├── useonlythebuiltinerror.basque.md ├── useonlythebuiltinerror.brazilian-portuguese.md ├── useonlythebuiltinerror.chinese.md ├── useonlythebuiltinerror.japanese.md ├── useonlythebuiltinerror.korean.md ├── useonlythebuiltinerror.md ├── useonlythebuiltinerror.polish.md └── useonlythebuiltinerror.russian.md ├── examples └── dockerfile │ ├── .dockerignore │ ├── .npmrc │ ├── Dockerfile │ ├── package.json │ └── src │ └── app.ts ├── performance ├── block-loop.japanese.md ├── block-loop.md ├── block-loop.polish.md ├── block-loop.russian.md ├── nativeoverutil.brazilian-portuguese.md ├── nativeoverutil.japanese.md ├── nativeoverutil.md ├── nativeoverutil.polish.md └── nativeoverutil.russian.md ├── production ├── LTSrelease.brazilian-portuguese.md ├── LTSrelease.japanese.md ├── LTSrelease.korean.md ├── LTSrelease.md ├── LTSrelease.polish.md ├── LTSrelease.russian.md ├── apmproducts.brazilian-portuguese.md ├── apmproducts.chinese.md ├── apmproducts.japanese.md ├── apmproducts.korean.md ├── apmproducts.md ├── apmproducts.polish.md ├── apmproducts.russian.md ├── assigntransactionid.brazilian-portuguese.md ├── assigntransactionid.chinese.md ├── assigntransactionid.japanese.md ├── assigntransactionid.korean.md ├── assigntransactionid.md ├── assigntransactionid.polish.md ├── assigntransactionid.russian.md ├── bestateless.brazilian-portuguese.md ├── bestateless.chinese.md ├── bestateless.japanese.md ├── bestateless.korean.md ├── bestateless.md ├── bestateless.polish.md ├── bestateless.russian.md ├── createmaintenanceendpoint.brazilian-portuguese.md ├── createmaintenanceendpoint.chinese.md ├── createmaintenanceendpoint.japanese.md ├── createmaintenanceendpoint.korean.md ├── createmaintenanceendpoint.md ├── createmaintenanceendpoint.polish.md ├── createmaintenanceendpoint.russian.md ├── delegatetoproxy.brazilian-portuguese.md ├── delegatetoproxy.chinese.md ├── delegatetoproxy.japanese.md ├── delegatetoproxy.korean.md ├── delegatetoproxy.md ├── delegatetoproxy.polish.md ├── delegatetoproxy.russian.md ├── detectvulnerabilities.brazilian-portuguese.md ├── detectvulnerabilities.chinese.md ├── detectvulnerabilities.japanese.md ├── detectvulnerabilities.korean.md ├── detectvulnerabilities.md ├── detectvulnerabilities.polish.md ├── detectvulnerabilities.russian.md ├── frontendout.brazilian-portuguese.md ├── frontendout.chinese.md ├── frontendout.japanese.md ├── frontendout.korean.md ├── frontendout.md ├── frontendout.polish.md ├── frontendout.russian.md ├── guardprocess.brazilian-portuguese.md ├── guardprocess.chinese.md ├── guardprocess.japanese.md ├── guardprocess.korean.md ├── guardprocess.md ├── guardprocess.polish.md ├── guardprocess.russian.md ├── installpackageswithnpmci.japanese.md ├── installpackageswithnpmci.md ├── lockdependencies.brazilian-portuguese.md ├── lockdependencies.chinese.md ├── lockdependencies.japanese.md ├── lockdependencies.korean.md ├── lockdependencies.md ├── lockdependencies.polish.md ├── lockdependencies.russian.md ├── logrouting.brazilian-portuguese.md ├── logrouting.japanese.md ├── logrouting.md ├── logrouting.polish.md ├── logrouting.russian.md ├── measurememory.brazilian-portuguese.md ├── measurememory.chinese.md ├── measurememory.japanese.md ├── measurememory.korean.md ├── measurememory.md ├── measurememory.polish.md ├── measurememory.russian.md ├── monitoring.brazilian-portuguese.md ├── monitoring.chinese.md ├── monitoring.japanese.md ├── monitoring.korean.md ├── monitoring.md ├── monitoring.polish.md ├── monitoring.russian.md ├── productioncode.brazilian-portuguese.md ├── productioncode.chinese.md ├── productioncode.japanese.md ├── productioncode.korean.md ├── productioncode.md ├── productioncode.polish.md ├── productioncode.russian.md ├── setnodeenv.brazilian-portuguese.md ├── setnodeenv.chinese.md ├── setnodeenv.japanese.md ├── setnodeenv.korean.md ├── setnodeenv.md ├── setnodeenv.polish.md ├── setnodeenv.russian.md ├── smartlogging.brazilian-portuguese.md ├── smartlogging.chinese.md ├── smartlogging.japanese.md ├── smartlogging.korean.md ├── smartlogging.md ├── smartlogging.polish.md ├── smartlogging.russian.md ├── utilizecpu.brazilian-portuguese.md ├── utilizecpu.chinese.md ├── utilizecpu.japanese.md ├── utilizecpu.korean.md ├── utilizecpu.md ├── utilizecpu.polish.md └── utilizecpu.russian.md ├── projectstructre ├── breakintcomponents.basque.md ├── breakintcomponents.brazilian-portuguese.md ├── breakintcomponents.chinese.md ├── breakintcomponents.japanese.md ├── breakintcomponents.korean.md ├── breakintcomponents.md ├── breakintcomponents.polish.md ├── breakintcomponents.russian.md ├── configguide.basque.md ├── configguide.brazilian-portuguese.md ├── configguide.chinese.md ├── configguide.japanese.md ├── configguide.korean.md ├── configguide.md ├── configguide.polish.md ├── configguide.russian.md ├── createlayers.basque.md ├── createlayers.brazilian-portuguese.md ├── createlayers.chinese.md ├── createlayers.japanese.md ├── createlayers.korean.md ├── createlayers.md ├── createlayers.polish.md ├── createlayers.russian.md ├── separateexpress.basque.md ├── separateexpress.brazilian-portuguese.md ├── separateexpress.chinese.md ├── separateexpress.japanese.md ├── separateexpress.korean.md ├── separateexpress.md ├── separateexpress.polish.md ├── separateexpress.russian.md ├── thincomponents.chinese.md ├── thincomponents.japanese.md ├── thincomponents.md ├── thincomponents.russian.md ├── wraputilities.basque.md ├── wraputilities.brazilian-portuguese.md ├── wraputilities.chinese.md ├── wraputilities.japanese.md ├── wraputilities.korean.md ├── wraputilities.md ├── wraputilities.polish.md └── wraputilities.russian.md ├── security ├── avoid_publishing_secrets.brazilian-portuguese.md ├── avoid_publishing_secrets.japanese.md ├── avoid_publishing_secrets.md ├── avoid_publishing_secrets.polish.md ├── avoid_publishing_secrets.russian.md ├── avoideval.brazilian-portuguese.md ├── avoideval.chinese.md ├── avoideval.japanese.md ├── avoideval.md ├── avoideval.polish.md ├── avoideval.russian.md ├── bcryptpasswords.brazilian-portuguese.md ├── bcryptpasswords.chinese.md ├── bcryptpasswords.japanese.md ├── bcryptpasswords.polish.md ├── bcryptpasswords.russian.md ├── childprocesses.brazilian-portuguese.md ├── childprocesses.chinese.md ├── childprocesses.japanese.md ├── childprocesses.md ├── childprocesses.polish.md ├── childprocesses.russian.md ├── commonsecuritybestpractices.brazilian-portuguese.md ├── commonsecuritybestpractices.japanese.md ├── commonsecuritybestpractices.md ├── commonsecuritybestpractices.polish.md ├── commonsecuritybestpractices.russian.md ├── dependencysecurity.brazilian-portuguese.md ├── dependencysecurity.japanese.md ├── dependencysecurity.md ├── dependencysecurity.polish.md ├── dependencysecurity.russian.md ├── escape-output.brazilian-portuguese.md ├── escape-output.japanese.md ├── escape-output.md ├── escape-output.polish.md ├── escape-output.russian.md ├── expirejwt.brazilian-portuguese.md ├── expirejwt.chinese.md ├── expirejwt.japanese.md ├── expirejwt.md ├── expirejwt.polish.md ├── expirejwt.russian.md ├── hideerrors.brazilian-portuguese.md ├── hideerrors.chinese.md ├── hideerrors.japanese.md ├── hideerrors.md ├── hideerrors.polish.md ├── hideerrors.russian.md ├── limitrequests.brazilian-portuguese.md ├── limitrequests.chinese.md ├── limitrequests.japanese.md ├── limitrequests.md ├── limitrequests.polish.md ├── limitrequests.russian.md ├── lintrules.brazilian-portuguese.md ├── lintrules.japanese.md ├── lintrules.md ├── lintrules.polish.md ├── lintrules.russian.md ├── login-rate-limit.brazilian-portuguese.md ├── login-rate-limit.japanese.md ├── login-rate-limit.md ├── login-rate-limit.polish.md ├── login-rate-limit.russian.md ├── non-root-user.brazilian-portuguese.md ├── non-root-user.japanese.md ├── non-root-user.md ├── non-root-user.polish.md ├── non-root-user.russian.md ├── ormodmusage.brazilian-portuguese.md ├── ormodmusage.japanese.md ├── ormodmusage.md ├── ormodmusage.polish.md ├── ormodmusage.russian.md ├── regex.brazilian-portuguese.md ├── regex.japanese.md ├── regex.md ├── regex.polish.md ├── regex.russian.md ├── requestpayloadsizelimit.brazilian-portuguese.md ├── requestpayloadsizelimit.japanese.md ├── requestpayloadsizelimit.md ├── requestpayloadsizelimit.polish.md ├── requestpayloadsizelimit.russian.md ├── safemoduleloading.brazilian-portuguese.md ├── safemoduleloading.chinese.md ├── safemoduleloading.japanese.md ├── safemoduleloading.md ├── safemoduleloading.polish.md ├── safemoduleloading.russian.md ├── saferedirects.brazilian-portuguese.md ├── saferedirects.chinese.md ├── saferedirects.japanese.md ├── saferedirects.md ├── saferedirects.polish.md ├── saferedirects.russian.md ├── sandbox.brazilian-portuguese.md ├── sandbox.chinese.md ├── sandbox.japanese.md ├── sandbox.md ├── sandbox.polish.md ├── sandbox.russian.md ├── secretmanagement.brazilian-portuguese.md ├── secretmanagement.japanese.md ├── secretmanagement.md ├── secretmanagement.polish.md ├── secretmanagement.russian.md ├── secureheaders.brazilian-portuguese.md ├── secureheaders.japanese.md ├── secureheaders.md ├── secureheaders.polish.md ├── secureheaders.russian.md ├── secureserver.brazilian-portuguese.md ├── secureserver.chinese.md ├── secureserver.japanese.md ├── secureserver.md ├── secureserver.russian.md ├── sessions.brazilian-portuguese.md ├── sessions.japanese.md ├── sessions.md ├── sessions.polish.md ├── sessions.russian.md ├── userpasswords.md ├── validation.brazilian-portuguese.md ├── validation.japanese.md ├── validation.md ├── validation.polish.md └── validation.russian.md ├── template.basque.md ├── template.md └── testingandquality ├── 3-parts-in-name.basque.md ├── 3-parts-in-name.brazilian-portuguese.md ├── 3-parts-in-name.japanese.md ├── 3-parts-in-name.md ├── 3-parts-in-name.polish.md ├── 3-parts-in-name.russian.md ├── aaa.basque.md ├── aaa.japanese.md ├── aaa.md ├── aaa.polish.md ├── aaa.russian.md ├── avoid-global-test-fixture.basque.md ├── avoid-global-test-fixture.brazilian-portuguese.md ├── avoid-global-test-fixture.japanese.md ├── avoid-global-test-fixture.md ├── avoid-global-test-fixture.polish.md ├── avoid-global-test-fixture.russian.md ├── bumpversion.japanese.md ├── bumpversion.md ├── citools.basque.md ├── citools.brazilian-portuguese.md ├── citools.chinese.md ├── citools.japanese.md ├── citools.korean.md ├── citools.md ├── citools.polish.md ├── citools.russian.md ├── refactoring.basque.md ├── refactoring.brazilian-portuguese.md ├── refactoring.japanese.md ├── refactoring.md ├── refactoring.polish.md ├── refactoring.russian.md ├── test-middlewares.basque.md ├── test-middlewares.japanese.md └── test-middlewares.md /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Number of days of inactivity before an issue becomes stale 2 | daysUntilStale: 90 3 | # Number of days of inactivity before a stale issue is closed 4 | daysUntilClose: 10 5 | # Issues with these labels will never be considered stale 6 | exemptLabels: 7 | - security 8 | # Label to use when marking an issue as stale 9 | staleLabel: stale 10 | # Comment to post when marking an issue as stale. Set to `false` to disable 11 | markComment: > 12 | Hello there! 👋 13 | 14 | This issue has gone silent. Eerily silent. ⏳ 15 | 16 | We currently close issues after 100 days of inactivity. It has been 90 days 17 | since the last update here. 18 | 19 | If needed, you can keep it open by replying here. 20 | 21 | Thanks for being a part of the Node.js Best Practices community! 💚 22 | # Comment to post when closing a stale issue. Set to `false` to disable 23 | closeComment: false 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | .idea 3 | .vscode 4 | .idea/**/* 5 | .vscode/**/* 6 | .nyc_output 7 | mochawesome-report 8 | .DS_Store 9 | npm-debug.log.* 10 | node_modules 11 | node_modules/**/* 12 | .eslintcache 13 | cert 14 | logs/* 15 | desktop.ini 16 | package-lock.json 17 | .history 18 | .env -------------------------------------------------------------------------------- /.operations/.common-answers.md: -------------------------------------------------------------------------------- 1 | **Welcoming new translators** 2 | 3 | @name - Welcome aboard, it's great to have you here 🎆 4 | 5 | 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 6 | 7 | Let's go for this? Few basic guideliness: 8 | 9 | - 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 10 | 11 | - 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) 12 | 13 | - 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 14 | 15 | 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) 16 | 17 | 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 18 | -------------------------------------------------------------------------------- /.operations/.env.example: -------------------------------------------------------------------------------- 1 | GITHUB_TOKEN=REPLACEME -------------------------------------------------------------------------------- /.operations/.markdownlint.json: -------------------------------------------------------------------------------- 1 | { 2 | "default": true, 3 | "MD033": false, 4 | "MD001": false, 5 | "MD013": false, 6 | "MD039": false 7 | } -------------------------------------------------------------------------------- /.operations/out/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /.operations/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nodebestpractices", 3 | "version": "1.0.0", 4 | "description": "[✔]: assets/images/checkbox-small-blue.png", 5 | "main": "gen-html.js", 6 | "scripts": { 7 | "build": "cd .. && node .operations/gen-html.js", 8 | "test": "echo \"Error: no test specified\" && exit 1", 9 | "lint": "./node_modules/.bin/markdownlint ../README.md" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "git+https://github.com/goldbergyoni/nodebestpractices.git" 14 | }, 15 | "author": "", 16 | "license": "ISC", 17 | "bugs": { 18 | "url": "https://github.com/goldbergyoni/nodebestpractices/issues" 19 | }, 20 | "homepage": "https://github.com/goldbergyoni/nodebestpractices#readme", 21 | "dependencies": { 22 | "cheerio": "^1.0.0-rc.2", 23 | "github-api": "^3.0.0", 24 | "graceful-fs": "^4.1.15", 25 | "imagemin": "^6.0.0", 26 | "imagemin-jpegtran": "^6.0.0", 27 | "imagemin-pngquant": "^6.0.0", 28 | "markdownlint-cli": "^0.18.0", 29 | "showdown": "^1.9.0" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /.operations/res/github.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | github.com style (c) Vasily Polovnyov 4 | 5 | */ 6 | 7 | .hljs { 8 | display: block; 9 | overflow-x: auto; 10 | padding: 0.5em; 11 | color: #333; 12 | background: #f8f8f8; 13 | } 14 | 15 | .hljs-comment, 16 | .hljs-quote { 17 | color: #998; 18 | font-style: italic; 19 | } 20 | 21 | .hljs-keyword, 22 | .hljs-selector-tag, 23 | .hljs-subst { 24 | color: #333; 25 | font-weight: bold; 26 | } 27 | 28 | .hljs-number, 29 | .hljs-literal, 30 | .hljs-variable, 31 | .hljs-template-variable, 32 | .hljs-tag .hljs-attr { 33 | color: #008080; 34 | } 35 | 36 | .hljs-string, 37 | .hljs-doctag { 38 | color: #d14; 39 | } 40 | 41 | .hljs-title, 42 | .hljs-section, 43 | .hljs-selector-id { 44 | color: #900; 45 | font-weight: bold; 46 | } 47 | 48 | .hljs-subst { 49 | font-weight: normal; 50 | } 51 | 52 | .hljs-type, 53 | .hljs-class .hljs-title { 54 | color: #458; 55 | font-weight: bold; 56 | } 57 | 58 | .hljs-tag, 59 | .hljs-name, 60 | .hljs-attribute { 61 | color: #000080; 62 | font-weight: normal; 63 | } 64 | 65 | .hljs-regexp, 66 | .hljs-link { 67 | color: #009926; 68 | } 69 | 70 | .hljs-symbol, 71 | .hljs-bullet { 72 | color: #990073; 73 | } 74 | 75 | .hljs-built_in, 76 | .hljs-builtin-name { 77 | color: #0086b3; 78 | } 79 | 80 | .hljs-meta { 81 | color: #999; 82 | font-weight: bold; 83 | } 84 | 85 | .hljs-deletion { 86 | background: #fdd; 87 | } 88 | 89 | .hljs-addition { 90 | background: #dfd; 91 | } 92 | 93 | .hljs-emphasis { 94 | font-style: italic; 95 | } 96 | 97 | .hljs-strong { 98 | font-weight: bold; 99 | } 100 | -------------------------------------------------------------------------------- /.operations/res/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Node Best Practices 9 | 10 | 27 | 28 | 29 | 30 | 31 |
32 |
33 |
34 |
35 | 36 | 37 | 38 | 39 | 40 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /.operations/writing-guidelines.chinese.md: -------------------------------------------------------------------------------- 1 | # 我们的内容写作声明 2 | 如何提高访问者的阅读和学习体验 3 | 4 | ## 1. 越简单越好 5 | 6 |
7 | 我们的使命, 我们管理内容是为了使阅读和吸收知识更容易。因此, 我们专注于将复杂和无趣的话题转化为一个简化的清单, 用缩短和不那么精确的细节来交易超载信息, 避免 ‘易燃’ 和有争议的话题, 摆脱主观想法, 赞成普遍接受做法 8 | 9 |
10 | 11 | ## 2. 以证据为基础并且可靠 12 | 13 |
14 | 我们的读者应该有很大的信心, 他们浏览的内容是可靠的。我们通过包括引用、数据和本主题可用的其他资源等证据来实现这一点。实际上, 努力包括可靠来源的引用, 显示基准, 相关的设计模式或任何科学措施, 以证明您的主张 15 | 16 | 17 | ## 3. MECE (Mutually Exclusive and Collectively Exhaustive) 18 | 除了大量编辑和可靠的内容, 通过它略读也应该提供全面覆盖的主题。不应排除重要的子主题 19 | 20 | ## 4. 一致的格式 21 | 内容是使用固定模板显示的。任何将来的内容都必须符合同一模板。如果希望添加新项目符号, 请从现有项目符号复制项目符号格式, 并将其扩展以满足您的需要。有关其他信息, 请查看[模版](https://github.com/goldbergyoni/nodebestpractices/blob/master/sections/template.md) 22 | 23 | ## 5. 关于Node.js 24 | 每个建议都应直接与Node.js相关, 而不是一般软件开发。当我们建议在Node.js中实现通用模式/规则时, 内容应该集中在Node的实现上。例如, 当我们建议将所有请求的输入为了安全原因进行处理时, 应使用Node行话 - '使用中间件来处理请求输入' 25 | 26 | ## 6. 仅限主要的vendor 27 | 有时, 包括可以解决某些挑战和问题 (如 npm 软件包、开源工具甚至商业产品) 的供应商名称是很有用的。为了避免极长的列表或推荐信誉不好和不稳定的项目, 我们提出了以下规则: 28 | 29 | - 只有排名前3的vendor应该被推荐 – 对于一个给定的相关关键词,如果某个vendor出现在搜索引擎结果中排名前3(谷歌或GitHub通过人气排序),那么它可以包含在我们的推荐里 30 | - 如果它是一个npm包,它必须平均一天下载至少750次 31 | - 如果它是一个开源项目,它必须在过去的6个月里至少更新一次 32 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 8 3 | script: 4 | - cd .operations 5 | - npm i 6 | - export PR=https://api.github.com/repos/$TRAVIS_REPO_SLUG/pulls/$TRAVIS_PULL_REQUEST 7 | - export BRANCH=$(if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then echo $TRAVIS_BRANCH; else echo `curl -s $PR | jq -r .head.ref`; fi) 8 | - echo "TRAVIS_BRANCH=$TRAVIS_BRANCH, PR=$PR, BRANCH=$BRANCH" 9 | - npm run lint 10 | - npm run build -------------------------------------------------------------------------------- /assets/flags/BR.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/flags/BR.jpg -------------------------------------------------------------------------------- /assets/flags/BR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/flags/BR.png -------------------------------------------------------------------------------- /assets/flags/CN.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/flags/CN.png -------------------------------------------------------------------------------- /assets/flags/ES.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/flags/ES.png -------------------------------------------------------------------------------- /assets/flags/EU.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/flags/EU.png -------------------------------------------------------------------------------- /assets/flags/FR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/flags/FR.png -------------------------------------------------------------------------------- /assets/flags/HE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/flags/HE.png -------------------------------------------------------------------------------- /assets/flags/JA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/flags/JA.png -------------------------------------------------------------------------------- /assets/flags/KR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/flags/KR.png -------------------------------------------------------------------------------- /assets/flags/PL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/flags/PL.png -------------------------------------------------------------------------------- /assets/flags/RU.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/flags/RU.png -------------------------------------------------------------------------------- /assets/flags/TR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/flags/TR.png -------------------------------------------------------------------------------- /assets/images/6-parts-in-test.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/6-parts-in-test.jpg -------------------------------------------------------------------------------- /assets/images/Kubernetes-graceful-shutdown-flowchart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/Kubernetes-graceful-shutdown-flowchart.png -------------------------------------------------------------------------------- /assets/images/Privatenpm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/Privatenpm.png -------------------------------------------------------------------------------- /assets/images/Sketch (8).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/Sketch (8).png -------------------------------------------------------------------------------- /assets/images/anchore-report.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/anchore-report.png -------------------------------------------------------------------------------- /assets/images/apm1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/apm1.png -------------------------------------------------------------------------------- /assets/images/apm2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/apm2.png -------------------------------------------------------------------------------- /assets/images/apm3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/apm3.png -------------------------------------------------------------------------------- /assets/images/app-dynamics-dashboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/app-dynamics-dashboard.png -------------------------------------------------------------------------------- /assets/images/banner-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/banner-1.png -------------------------------------------------------------------------------- /assets/images/banner-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/banner-2.jpg -------------------------------------------------------------------------------- /assets/images/banner-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/banner-3.jpg -------------------------------------------------------------------------------- /assets/images/banner-4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/banner-4.jpg -------------------------------------------------------------------------------- /assets/images/checkbox-sm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/checkbox-sm.png -------------------------------------------------------------------------------- /assets/images/checkbox-small-blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/checkbox-small-blue.png -------------------------------------------------------------------------------- /assets/images/checkbox-small.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/checkbox-small.PNG -------------------------------------------------------------------------------- /assets/images/checkmark-green-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/checkmark-green-small.png -------------------------------------------------------------------------------- /assets/images/checkmark-green.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/checkmark-green.png -------------------------------------------------------------------------------- /assets/images/checkmark-green_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/checkmark-green_small.png -------------------------------------------------------------------------------- /assets/images/circleci.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/circleci.png -------------------------------------------------------------------------------- /assets/images/codeanalysis-climate-complex-methods.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/codeanalysis-climate-complex-methods.PNG -------------------------------------------------------------------------------- /assets/images/codeanalysis-climate-history.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/codeanalysis-climate-history.PNG -------------------------------------------------------------------------------- /assets/images/codeanalysis-sonarqube-dashboard.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/codeanalysis-sonarqube-dashboard.PNG -------------------------------------------------------------------------------- /assets/images/concat-benchmark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/concat-benchmark.png -------------------------------------------------------------------------------- /assets/images/createmaintenanceendpoint1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/createmaintenanceendpoint1.png -------------------------------------------------------------------------------- /assets/images/docker_layers_schema.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/docker_layers_schema.png -------------------------------------------------------------------------------- /assets/images/error-handling-flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/error-handling-flow.png -------------------------------------------------------------------------------- /assets/images/eslint-plugin-security.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/eslint-plugin-security.png -------------------------------------------------------------------------------- /assets/images/event-loop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/event-loop.png -------------------------------------------------------------------------------- /assets/images/greenkeeper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/greenkeeper.png -------------------------------------------------------------------------------- /assets/images/integration-test-roi.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/integration-test-roi.PNG -------------------------------------------------------------------------------- /assets/images/jenkins_dashboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/jenkins_dashboard.png -------------------------------------------------------------------------------- /assets/images/keepexpressinweb.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/keepexpressinweb.gif -------------------------------------------------------------------------------- /assets/images/kibana-graph-1024x550.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/kibana-graph-1024x550.jpg -------------------------------------------------------------------------------- /assets/images/kibana-raw-1024x637.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/kibana-raw-1024x637.png -------------------------------------------------------------------------------- /assets/images/linkedin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/linkedin.png -------------------------------------------------------------------------------- /assets/images/logging-overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/logging-overview.png -------------------------------------------------------------------------------- /assets/images/members/bruno.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/members/bruno.png -------------------------------------------------------------------------------- /assets/images/members/ido.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/members/ido.png -------------------------------------------------------------------------------- /assets/images/members/keith.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/members/keith.png -------------------------------------------------------------------------------- /assets/images/members/kevyn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/members/kevyn.png -------------------------------------------------------------------------------- /assets/images/members/kyle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/members/kyle.png -------------------------------------------------------------------------------- /assets/images/members/refael.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/members/refael.png -------------------------------------------------------------------------------- /assets/images/members/sagir.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/members/sagir.png -------------------------------------------------------------------------------- /assets/images/members/yoni.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/members/yoni.png -------------------------------------------------------------------------------- /assets/images/monitoring1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/monitoring1.png -------------------------------------------------------------------------------- /assets/images/monitoring2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/monitoring2.jpg -------------------------------------------------------------------------------- /assets/images/monitoring3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/monitoring3.png -------------------------------------------------------------------------------- /assets/images/npm-audit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/npm-audit.png -------------------------------------------------------------------------------- /assets/images/placeholdet.txt: -------------------------------------------------------------------------------- 1 | lorem ipsum 2 | -------------------------------------------------------------------------------- /assets/images/sampleMeanDiag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/sampleMeanDiag.png -------------------------------------------------------------------------------- /assets/images/setnodeenv1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/setnodeenv1.png -------------------------------------------------------------------------------- /assets/images/smartlogging1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/smartlogging1.png -------------------------------------------------------------------------------- /assets/images/smartlogging2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/smartlogging2.jpg -------------------------------------------------------------------------------- /assets/images/snyk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/snyk.png -------------------------------------------------------------------------------- /assets/images/structurebycomponents.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/structurebycomponents.PNG -------------------------------------------------------------------------------- /assets/images/structurebyroles.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/structurebyroles.PNG -------------------------------------------------------------------------------- /assets/images/swaggerDoc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/swaggerDoc.png -------------------------------------------------------------------------------- /assets/images/swaggerMarkup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/swaggerMarkup.png -------------------------------------------------------------------------------- /assets/images/test-report-like-requirements.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/test-report-like-requirements.jpeg -------------------------------------------------------------------------------- /assets/images/testingpyramid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/testingpyramid.png -------------------------------------------------------------------------------- /assets/images/twitter-s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/twitter-s.png -------------------------------------------------------------------------------- /assets/images/twitter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/twitter.png -------------------------------------------------------------------------------- /assets/images/uptimerobot.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/uptimerobot.jpg -------------------------------------------------------------------------------- /assets/images/utilizecpucores1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/utilizecpucores1.png -------------------------------------------------------------------------------- /assets/images/viconblue.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/viconblue.PNG -------------------------------------------------------------------------------- /assets/images/www.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/www.png -------------------------------------------------------------------------------- /assets/images/ydnlu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/assets/images/ydnlu.png -------------------------------------------------------------------------------- /sections/codestylepractices/eslint_prettier.basque.md: -------------------------------------------------------------------------------- 1 | # Erabili ESLint eta Prettier 2 | 3 | ### ESLint eta Prettier alderatzen 4 | 5 | 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. 6 | 7 | 8 | ```javascript 9 | foo( 10 | argudioBenetanLuzea(), 11 | aiAmaParametroPiloPiloa(), 12 | hauGarbituBeharkoNuke(), 13 | benetanOraindikBesteBat(), 14 | txantxetanZabiltzaEzta() 15 | ); 16 | ``` 17 | 18 | ```javascript 19 | foo( 20 | argudioBenetanLuzea(), 21 | aiAmaParametroPiloPiloa(), 22 | hauGarbituBeharkoNuke(), 23 | benetanOraindikBesteBat(), 24 | txantxetanZabiltzaEzta() 25 | ); 26 | ``` 27 | 28 | Iturria: [https://github.com/prettier/prettier-eslint/issues/101](https://github.com/prettier/prettier-eslint/issues/101) 29 | 30 | ### ESLint eta Prettier integratzen 31 | 32 | 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 33 | -------------------------------------------------------------------------------- /sections/codestylepractices/eslint_prettier.brazilian-portuguese.md: -------------------------------------------------------------------------------- 1 | # Use ESLint e Prettier 2 | 3 | 4 | ### Comparando ESLint com Prettier 5 | 6 | Se você formatar este código usando o ESLint, ele apenas dará um aviso de que ele é muito grande (dependendo da sua configuração `max-len`). O Prettier irá formatá-lo automaticamente para você. 7 | 8 | ```javascript 9 | foo(reallyLongArg(), omgSoManyParameters(), IShouldRefactorThis(), isThereSeriouslyAnotherOne(), noWayYouGottaBeKiddingMe()); 10 | ``` 11 | 12 | ```javascript 13 | foo( 14 | reallyLongArg(), 15 | omgSoManyParameters(), 16 | IShouldRefactorThis(), 17 | isThereSeriouslyAnotherOne(), 18 | noWayYouGottaBeKiddingMe() 19 | ); 20 | ``` 21 | 22 | Fonte: [https://github.com/prettier/prettier-eslint/issues/101](https://github.com/prettier/prettier-eslint/issues/101) 23 | 24 | ### Integrando ESLint e Prettier 25 | 26 | ESLint e Prettier se sobrepõem no recurso de formatação de código, mas podem ser facilmente combinados usando outros pacotes como [prettier-eslint](https://github.com/prettier/prettier-eslint), [eslint-plugin-prettier](https://github.com/prettier/eslint-plugin-prettier), e [eslint-config-prettier](https://github.com/prettier/eslint-config-prettier). Para mais informações sobre as diferenças entre eles, clique [aqui](https://stackoverflow.com/questions/44690308/whats-the-difference-between-prettier-eslint-eslint-plugin-prettier-and-eslint). 27 | -------------------------------------------------------------------------------- /sections/codestylepractices/eslint_prettier.chinese.md: -------------------------------------------------------------------------------- 1 | # 使用 ESLint 和 Prettier 2 | 3 | 4 | ### 比较 ESLint 和 Prettier 5 | 6 | 如果你使用ESLint格式化代码,它只是给你一个警告,比如这一行太宽(取决于你的`最大长度`设置)。Prettier会自动为你格式化。 7 | 8 | ```javascript 9 | foo(reallyLongArg(), omgSoManyParameters(), IShouldRefactorThis(), isThereSeriouslyAnotherOne(), noWayYouGottaBeKiddingMe()); 10 | ``` 11 | 12 | ```javascript 13 | foo( 14 | reallyLongArg(), 15 | omgSoManyParameters(), 16 | IShouldRefactorThis(), 17 | isThereSeriouslyAnotherOne(), 18 | noWayYouGottaBeKiddingMe() 19 | ); 20 | ``` 21 | 22 | Source: [https://github.com/prettier/prettier-eslint/issues/101](https://github.com/prettier/prettier-eslint/issues/101) 23 | 24 | ### 整合 ESLint 和 Prettier 25 | 26 | ESLint和Prettier在代码格式化功能上有重叠, 但它可以很容易通过其他的包来解决,比如 [prettier-eslint](https://github.com/prettier/prettier-eslint), [eslint-plugin-prettier](https://github.com/prettier/eslint-plugin-prettier), 和 [eslint-config-prettier](https://github.com/prettier/eslint-config-prettier)。有关他们的差异的更多信息,您可以查看链接 [这里](https://stackoverflow.com/questions/44690308/whats-the-difference-between-prettier-eslint-eslint-plugin-prettier-and-eslint). 27 | -------------------------------------------------------------------------------- /sections/codestylepractices/eslint_prettier.japanese.md: -------------------------------------------------------------------------------- 1 | # ESLint と Prettier を使う 2 | 3 | 4 | ### ESLint と Prettier の比較 5 | 6 | 以下のコードを ESLint でフォーマットすると、幅が広すぎるという警告が表示されます( `max-len` の設定によります) 。Prettier はそれを自動的にフォーマットしてくれます。 7 | 8 | ```javascript 9 | foo(reallyLongArg(), omgSoManyParameters(), IShouldRefactorThis(), isThereSeriouslyAnotherOne(), noWayYouGottaBeKiddingMe()); 10 | ``` 11 | 12 | ```javascript 13 | foo( 14 | reallyLongArg(), 15 | omgSoManyParameters(), 16 | IShouldRefactorThis(), 17 | isThereSeriouslyAnotherOne(), 18 | noWayYouGottaBeKiddingMe() 19 | ); 20 | ``` 21 | 22 | ソース: [https://github.com/prettier/prettier-eslint/issues/101](https://github.com/prettier/prettier-eslint/issues/101) 23 | 24 | ### ESLint と Prettier の統合 25 | 26 | ESLint と Prettier はコードフォーマット機能で重複していますが、[prettier-eslint](https://github.com/prettier/prettier-eslint) や [eslint-plugin-prettier](https://github.com/prettier/eslint-plugin-prettier)、[eslint-config-prettier](https://github.com/prettier/eslint-config-prettier) のような他のパッケージを使うことで簡単に組み合わせることができます。それぞれの違いについての詳細は、リンク先の[こちら](https://stackoverflow.com/questions/44690308/whats-the-difference-between-prettier-eslint-eslint-plugin-prettier-and-eslint)をご覧ください。 27 | -------------------------------------------------------------------------------- /sections/codestylepractices/eslint_prettier.korean.md: -------------------------------------------------------------------------------- 1 | # ESLint와 Prettier 사용하기 2 | 3 | ### ESLint와 Prettier 비교하기 4 | 5 | 만약 당신이 ESLint를 사용해서 이 코드를 포맷한다면, 당신에게 너무 넓다는 경고만 줄 것이다 (당신의 `mas-len` 설정에 의존해). Prettier는 자동적으로 당신을 위해 그것을 포맷할 것이다. 6 | 7 | ```javascript 8 | foo(reallyLongArg(), omgSoManyParameters(), IShouldRefactorThis(), isThereSeriouslyAnotherOne(), noWayYouGottaBeKiddingMe()); 9 | ``` 10 | 11 | ```javascript 12 | foo( 13 | reallyLongArg(), 14 | omgSoManyParameters(), 15 | IShouldRefactorThis(), 16 | isThereSeriouslyAnotherOne(), 17 | noWayYouGottaBeKiddingMe() 18 | ); 19 | ``` 20 | 21 | 출처: [https://github.com/prettier/prettier-eslint/issues/101](https://github.com/prettier/prettier-eslint/issues/101) 22 | 23 | ### ESLint와 Prettier 통합시키기 24 | 25 | ESLint와 Prettier는 코드 포맷팅 기능에서 겹치지만 [prettier-eslint](https://github.com/prettier/prettier-eslint), [eslint-plugin-prettier](https://github.com/prettier/eslint-plugin-prettier), 그리고 [eslint-config-prettier](https://github.com/prettier/eslint-config-prettier)와 같은 다른 패키지들을 사용해 쉽게 결합시킬 수 있다. 그들의 차이점에 대해 더 많은 내용을 보려면, 당신은 [here](https://stackoverflow.com/questions/44690308/whats-the-difference-between-prettier-eslint-eslint-plugin-prettier-and-eslint) 링크를 볼 수 있다. 26 | -------------------------------------------------------------------------------- /sections/codestylepractices/eslint_prettier.md: -------------------------------------------------------------------------------- 1 | # Using ESLint and Prettier 2 | 3 | 4 | ### Comparing ESLint and Prettier 5 | 6 | If you format this code using ESLint, it will just give you a warning that it's too wide (depends on your `max-len` setting). Prettier will automatically format it for you. 7 | 8 | ```javascript 9 | foo(reallyLongArg(), omgSoManyParameters(), IShouldRefactorThis(), isThereSeriouslyAnotherOne(), noWayYouGottaBeKiddingMe()); 10 | ``` 11 | 12 | ```javascript 13 | foo( 14 | reallyLongArg(), 15 | omgSoManyParameters(), 16 | IShouldRefactorThis(), 17 | isThereSeriouslyAnotherOne(), 18 | noWayYouGottaBeKiddingMe() 19 | ); 20 | ``` 21 | 22 | Source: [https://github.com/prettier/prettier-eslint/issues/101](https://github.com/prettier/prettier-eslint/issues/101) 23 | 24 | ### Integrating ESLint and Prettier 25 | 26 | ESLint and Prettier overlap in the code formatting feature but can be easily combined by using other packages like [prettier-eslint](https://github.com/prettier/prettier-eslint), [eslint-plugin-prettier](https://github.com/prettier/eslint-plugin-prettier), and [eslint-config-prettier](https://github.com/prettier/eslint-config-prettier). For more information about their differences, you can view the link [here](https://stackoverflow.com/questions/44690308/whats-the-difference-between-prettier-eslint-eslint-plugin-prettier-and-eslint). 27 | -------------------------------------------------------------------------------- /sections/codestylepractices/eslint_prettier.polish.md: -------------------------------------------------------------------------------- 1 | # Używanie ESLint oraz Prettier 2 | 3 | 4 | ### Porównanie ESLint i Prettier 5 | 6 | Jeśli sformatujesz ten kod za pomocą ESLint, wyświetli ostrzeżenie, że jest on zbyt szeroki (zależy od twojego ustawienia „max-len”). Prettier automatycznie go sformatuje. 7 | 8 | ```javascript 9 | foo(reallyLongArg(), omgSoManyParameters(), IShouldRefactorThis(), isThereSeriouslyAnotherOne(), noWayYouGottaBeKiddingMe()); 10 | ``` 11 | 12 | ```javascript 13 | foo( 14 | reallyLongArg(), 15 | omgSoManyParameters(), 16 | IShouldRefactorThis(), 17 | isThereSeriouslyAnotherOne(), 18 | noWayYouGottaBeKiddingMe() 19 | ); 20 | ``` 21 | 22 | Źródło: [https://github.com/prettier/prettier-eslint/issues/101](https://github.com/prettier/prettier-eslint/issues/101) 23 | 24 | ### Integracja ESLint i Prettier 25 | 26 | ESLint i Prettier nakładają się na siebie w funkcji formatowania kodu, ale można je łatwo łączyć za pomocą innych pakietów, takich jak [prettier-eslint](https://github.com/prettier/prettier-eslint), [eslint-plugin-prettier](https://github.com/prettier/eslint-plugin-prettier), i [eslint-config-prettier](https://github.com/prettier/eslint-config-prettier). Aby uzyskać więcej informacji o ich różnicach, możesz zobaczyć link [tutaj](https://stackoverflow.com/questions/44690308/whats-the-difference-between-prettier-eslint-eslint-plugin-prettier-and-eslint). 27 | -------------------------------------------------------------------------------- /sections/codestylepractices/eslint_prettier.russian.md: -------------------------------------------------------------------------------- 1 | # Использование ESLint и Prettier 2 | 3 | 4 | ### Сравнение ESLint и Prettier 5 | 6 | Если вы отформатируете код ниже с помощью ESLint, он просто выдаст вам предупреждение, что он слишком широкий (зависит от настроек `max-len`). Prettier же автоматически отформатирует его для вас. 7 | 8 | ```javascript 9 | foo(reallyLongArg(), omgSoManyParameters(), IShouldRefactorThis(), isThereSeriouslyAnotherOne(), noWayYouGottaBeKiddingMe()); 10 | ``` 11 | 12 | ```javascript 13 | foo( 14 | reallyLongArg(), 15 | omgSoManyParameters(), 16 | IShouldRefactorThis(), 17 | isThereSeriouslyAnotherOne(), 18 | noWayYouGottaBeKiddingMe() 19 | ); 20 | ``` 21 | 22 | Source: [https://github.com/prettier/prettier-eslint/issues/101](https://github.com/prettier/prettier-eslint/issues/101) 23 | 24 | ### Интеграция ESLint и Prettier 25 | 26 | ESLint и Prettier перекрываются в функции форматирования кода, но могут быть легко объединены с помощью других пакетов, таких как [prettier-eslint](https://github.com/prettier/prettier-eslint), [eslint-plugin-prettier](https://github.com/prettier/eslint-plugin-prettier), и [eslint-config-prettier](https://github.com/prettier/eslint-config-prettier). Для получения дополнительной информации об их различиях вы можете просмотреть ссылку [здесь](https://stackoverflow.com/questions/44690308/whats-the-difference-between-prettier-eslint-eslint-plugin-prettier-and-eslint). 27 | -------------------------------------------------------------------------------- /sections/docker/clean-cache.japanese.md: -------------------------------------------------------------------------------- 1 | # NODE_MODULE キャッシュをクリーンアップする 2 | 3 |

4 | 5 | ### 一段落説明 6 | 7 | Node パッケージマネージャである npm や Yarn は、同じライブラリを必要とする将来のプロジェクトがリモートリポジトリから取得する必要が無いように、インストールされたパッケージをローカルにキャッシュします。これはパッケージを複製し、より多くのストレージを消費しますが、一般的に同じパッケージをインストールし続けるローカルの開発環境においては効果的です。Docker コンテナでは、依存関係をインストールするのは一度だけなので、このストレージの増加には意味がありません。一行のコードを利用してこのキャッシュを削除することで、イメージから数十 MB を削ることができます。そうする間、non-zero code で中断し、CI のビルドに失敗しないようにしてください - これは --force フラグを含めることで回避できます。 8 | 9 | *マルチステージビルドを利用している場合は、最後のステージで新しいパッケージをインストールしない限り、このプラクティスは関係が無いことに注意してください* 10 | 11 |

12 | 13 | ### コード例 - キャシュをクリーンアップする 14 | 15 |
16 | Dockerfile 17 | 18 | ``` 19 | FROM node:12-slim AS build 20 | WORKDIR /usr/src/app 21 | COPY package.json package-lock.json ./ 22 | RUN npm ci --production && npm cache clean --force 23 | 24 | # 残りの部分がここに記述されます 25 | ``` 26 | 27 |
28 | -------------------------------------------------------------------------------- /sections/docker/clean-cache.md: -------------------------------------------------------------------------------- 1 | # Clean NODE_MODULE cache 2 | 3 |

4 | 5 | ### One Paragraph Explainer 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. 8 | 9 | *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* 10 | 11 |

12 | 13 | ### Code Example – Clean cache 14 | 15 |
16 | Dockerfile 17 | 18 | ``` 19 | FROM node:12-slim AS build 20 | WORKDIR /usr/src/app 21 | COPY package.json package-lock.json ./ 22 | RUN npm ci --production && npm cache clean --force 23 | 24 | # The rest comes here 25 | ``` 26 | 27 |
28 | -------------------------------------------------------------------------------- /sections/docker/docker-ignore.japanese.md: -------------------------------------------------------------------------------- 1 | # .dockerignore を使用してシークレット情報の漏洩を防ぐ 2 | 3 |

4 | 5 | ### 一段落説明 6 | 7 | Docker ビルドコマンドは、仮想ネットワークを介してローカルファイルをビルドコンテキスト環境にコピーします。注意してください - 開発と CI のフォルダには、.npmrc、.aws、.envファイルなどの機密ファイルが含まれています。その結果、Docker イメージは秘密を保持し、危険な領域(Docker リポジトリやパートナーのサーバーなど)で公開される可能性があります。より良い世界では、Dockerfile は何がコピーされるのかを明確にすべきです。その上で、不要なフォルダや潜在的な秘密をフィルタリングする最後のセーフティネットとしての役割を果たす .dockerignore ファイルを含めてください。そうすることで、ビルド速度も向上します。- 本番では使わない一般的な開発フォルダ (例えば .git 、テスト結果、IDE の設定など) を省くことで、キャッシュをより有効に活用し、より良いパフォーマンスを得ることができます。 8 | 9 |

10 | 11 | ### コード例 – Node.js のための良いデフォルトの .dockerignore 12 | 13 |
14 | .dockerignore 15 | 16 | ``` 17 | **/node_modules/ 18 | **/.git 19 | **/README.md 20 | **/LICENSE 21 | **/.vscode 22 | **/npm-debug.log 23 | **/coverage 24 | **/.env 25 | **/.editorconfig 26 | **/.aws 27 | **/dist 28 | ``` 29 | 30 |
31 | 32 |

33 | 34 | ### アンチパターン コード例 – 全てのファイルの再帰的コピー 35 | 36 |
37 | Dockerfile 38 | 39 | ``` 40 | FROM node:12-slim AS build 41 | WORKDIR /usr/src/app 42 | # 次の行はすべてをコピーします 43 | COPY . . 44 | 45 | # 残りはここに来ます 46 | 47 | ``` 48 | 49 |
50 | -------------------------------------------------------------------------------- /sections/docker/docker-ignore.md: -------------------------------------------------------------------------------- 1 | # Use .dockerignore to prevent leaking secrets 2 | 3 |

4 | 5 | ### One Paragraph Explainer 6 | 7 | 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 8 | 9 |

10 | 11 | ### Code Example – A good default .dockerignore for Node.js 12 | 13 |
14 | .dockerignore 15 | 16 | ``` 17 | **/node_modules/ 18 | **/.git 19 | **/README.md 20 | **/LICENSE 21 | **/.vscode 22 | **/npm-debug.log 23 | **/coverage 24 | **/.env 25 | **/.editorconfig 26 | **/.aws 27 | **/dist 28 | ``` 29 | 30 |
31 | 32 |

33 | 34 | ### Code Example Anti-Pattern – Recursive copy of all files 35 | 36 |
37 | Dockerfile 38 | 39 | ``` 40 | FROM node:12-slim AS build 41 | WORKDIR /usr/src/app 42 | # The next line copies everything 43 | COPY . . 44 | 45 | # The rest comes here 46 | 47 | ``` 48 | 49 |
50 | -------------------------------------------------------------------------------- /sections/docker/generic-tips.japanese.md: -------------------------------------------------------------------------------- 1 | [✔]: ../../assets/images/checkbox-small-blue.png 2 | 3 | # 一般的な Docker のベストプラクティス 4 | 5 | この Docker ガイドラインのセクションでは、すべてのプログラミング言語の間で共通して通用するベストプラクティスを紹介しており、Node.js に限ったものではありません。 6 | 7 | ## ![✔] COPY コマンドを ADD コマンドよりも優先する 8 | 9 | **TL;DR:** ADD はリモートのサイトからバイナリをダウンロードするといった高度なフェッチ機能をサポートしていますが、COPY はローカルファイルをコピーするためより安全です。 10 | 11 | ## ![✔] ベース OS をアップデートすることを避ける 12 | 13 | **TL;DR:** ビルド中にローカルのバイナリをアップデートする(例:apt-get update)と、実行のたびに一貫性のないイメージが作成され、高度な権限が要求されます。代わりに、頻繁に更新されるベースイメージを利用してください。 14 | 15 | ## ![✔] ラベルを利用してイメージを分類する 16 | 17 | **TL;DR:** 各イメージにメタデータを提供することで、Ops の専任者がイメージを適切に扱うことの助けになるかもしれません。例えば、管理者名やビルド日時、その他の情報を含めることで、誰かがイメージについて推測する必要がある際に有用となる場合があります。 18 | 19 | ## ![✔] 権限の無いコンテナを利用する 20 | 21 | **TL;DR:** 権限を持つコンテナは、ホストマシンの root ユーザと同じ権限と機能を持っています。このような権限が必要になることは滅多に無く、経験則として、公式の Node イメージ内で作成された「node」ユーザを使用するべきです。 22 | 23 | ## ![✔] 最終的な結果を検査し、検証する 24 | 25 | **TL;DR:** シークレットの漏洩や、不要なファイルなど、ビルドプロセスでの副作用を見落としがちなことがあります。[Dive](https://github.com/wagoodman/dive) のようなツールを利用することで、作成されたイメージを検査し、そのような問題を用意に特定することができます。 26 | 27 | ## ![✔] 完全性チェックを行う 28 | 29 | **TL;DR:** ベースイメージや最終イメージをプルする際に、ネットワークがミスリードされて悪意のあるイメージをダウンロードするようにリダイレクトされる可能性があります。コンテンツに署名して検証しない限り、標準の Docker プロトコルではこれを防ぐことはできません。[Docker Notary](https://docs.docker.com/notary/getting_started/) はこれ防ぐためのツールの一つです。 30 | -------------------------------------------------------------------------------- /sections/docker/image-tags.japanese.md: -------------------------------------------------------------------------------- 1 | # イメージタグ vs ダイジェストを理解し、`:latest` タグは注意深く利用する 2 | 3 | ### 一段落説明 4 | 5 | 本番環境で、セキュリティと安定性を重視するのであれば、「利便性」はベストな決定要因ではないかもしれません。`:latest` タグは Docker のデフォルトタグです。これが意味することは、明示的なタグを追加し忘れた開発者は誤って新しいバージョンのイメージを `latest` としてプッシュしてしまうかもしれないということです。`latest` タグが最新の本番環境のイメージとして利用されている場合には、意図しない結果を招く可能性があります。 6 | 7 | ### コード例: 8 | 9 | ```bash 10 | $ docker build -t company/image_name:0.1 . 11 | # :latest イメージはアップデートされない 12 | $ docker build -t company/image_name 13 | # :latest イメージはアップデートされる 14 | $ docker build -t company/image_name:0.2 . 15 | # :latest イメージはアップデートされない 16 | $ docker build -t company/image_name:latest . 17 | # :latest イメージはアップデートされる 18 | ``` 19 | 20 | ### 他のブロガーが言っていること 21 | 22 | [Vladislav Supalov](https://vsupalov.com/docker-latest-tag/) のブログより: 23 | > 一部の人は、:latest タグは直近でプッシュされたバージョンのイメージを指していると思っています。しかし、そうではありません。 24 | 25 | [Docker success center](https://success.docker.com/article/images-tagging-vs-digests) 26 | 27 |
28 | -------------------------------------------------------------------------------- /sections/docker/image-tags.md: -------------------------------------------------------------------------------- 1 | # Understand image tags vs digests and use the `:latest` tag with caution 2 | 3 | ### One Paragraph Explainer 4 | 5 | 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. 6 | 7 | ### Code example: 8 | 9 | ```bash 10 | $ docker build -t company/image_name:0.1 . 11 | # :latest image is not updated 12 | $ docker build -t company/image_name 13 | # :latest image is updated 14 | $ docker build -t company/image_name:0.2 . 15 | # :latest image is not updated 16 | $ docker build -t company/image_name:latest . 17 | # :latest image is updated 18 | ``` 19 | 20 | ### What Other Bloggers Say 21 | From the blog by [Vladislav Supalov](https://vsupalov.com/docker-latest-tag/): 22 | > Some people expect that :latest always points to the most-recently-pushed version of an image. That’s not true. 23 | 24 | From the [Docker success center](https://success.docker.com/article/images-tagging-vs-digests) 25 | > 26 | 27 |
28 | -------------------------------------------------------------------------------- /sections/docker/lint-dockerfile.japanese.md: -------------------------------------------------------------------------------- 1 | # Dockerfile を lint する 2 | 3 | ### 一段落説明 4 | 5 | コアアプリケーションのコードをベストプラクティスに従わせ、問題になる前にイシューやバグを取り除くために 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 です。 6 | 7 | 8 |
9 | 10 | ### コード例: hadolint を使用して Dockerfile を検査する 11 | 12 | ```bash 13 | hadolint production.Dockerfile 14 | hadolint --ignore DL3003 --ignore DL3006 # 特定のルールを除外する 15 | hadolint --trusted-registry my-company.com:500 # 信頼されていない FROM イメージを利用している場合に警告を出す 16 | ``` 17 | 18 | ### 他のブロガーが言っていること 19 | 20 | [Josh Reichardt](https://thepracticalsysadmin.com/lint-your-dockerfiles-with-hadolint/) のブログより: 21 | > もしまだ Dockerfile を linting する習慣を取り入れていないのであれば、いますぐ取り入れるべきです。コードの linting はソフトウェア開発における一般的な慣習であり、問題となる前にイシューやバグを特定し、排除するのに役立ちます。コードを linting することの主な利点の1つは、問題が発生する前に、厄介な些細なバグを特定し排除する手助けをしてくれることです。 22 | 23 | [Jamie Phillips](https://www.phillipsj.net/posts/hadolint-linting-your-dockerfile/) のブログより: 24 | > Linter は、開発チームがプログラム的なエラーやスタイルエラーを検出しやすくするために、開発現場では一般的に利用されています。Hadolint は Haskell で Dockerfile のために実装された linter です。このツールは、Docker によって示されたベストプラクティスに照らし合わせて検証し、チェックするべき Dockerfile をパースするために、きちんとしたアプローチを取ります。これはすべての主要なプラットフォームをサポートしており、このチュートリアルではコンテナを利用してサンプル Dockerfile 上で linting を行います。 25 |
26 | -------------------------------------------------------------------------------- /sections/docker/restart-and-replicate-processes.japanese.md: -------------------------------------------------------------------------------- 1 | # プロセスを再起動と複製をDocker オーケストレーターに任せる 2 | 3 |

4 | 5 | ### 一段落説明 6 | 7 | Kubernetes のような Docker ランタイムオーケストレータは、コンテナの健全性と配置の決定を行うのが非常に得意です。コンテナの数を最大化し、ゾーン間でバランスをとり、多くのクラスタ要因を考慮しながら、これらの決定を行います。言葉がなくても、彼らは失敗したプロセス(つまりコンテナ)を特定し、適切な場所で再起動します。にもかかわらず、CPU 利用率のためにノードプロセスを複製したり、障害時にプロセスを再起動したりするために、カスタムコードやツールを使いたくなる人もいるかもしれません(例えば、クラスタモジュール、PM2)。これらのローカルツールは、クラスタレベルで利用可能な視点やデータを持っていません。例えば、インスタンスリソースが3つのコンテナをホストでき、2つのリージョンやゾーンが与えられている場合、Kubernetes はゾーン間でコンテナを分散させるように注意します。このようにして、ゾーンやリージョナルの障害が発生してもアプリは生き続けます。逆にローカルツールを使ってプロセスを再起動する場合、Docker オーケストレータはエラーに気づかず、コンテナを新しいインスタンスやゾーンに再配置するような思慮深い決定を下すことができません。 8 | 9 |

10 | 11 | ### コード例 – 中間ツールを使わずに直接 Node.js を呼び出す 12 | 13 |
14 | 15 | Dockerfile 16 | 17 | ``` 18 | 19 | FROM node:12-slim 20 | 21 | # ビルドロジックはこちら 22 | 23 | CMD ["node", "index.js"] 24 | ``` 25 | 26 |
27 | 28 |

29 | 30 | ### アンチパターン コード例 – プロセスマネージャを使用する 31 |
32 | 33 | Dockerfile 34 | 35 | ``` 36 | FROM node:12-slim 37 | 38 | # ビルドロジックはこちら 39 | 40 | CMD ["pm2-runtime", "indes.js"] 41 | ``` 42 | 43 |
44 | -------------------------------------------------------------------------------- /sections/docker/scan-images.japanese.md: -------------------------------------------------------------------------------- 1 | # プロダクションの前にイメージ全体をスキャンする 2 | 3 |

4 | 5 | ### One Paragraph Explainer 6 | 7 | 脆弱性のためにコードをスキャンすることは価値のある行動ですが、すべての潜在的な脅威をカバーできるものではありません。なぜでしょうか? 理由は、脆弱性は OS レベルにも存在し、アプリケーションは Shell や Tarball、OpenSSL といったバイナリを実行する可能性があるためです。また、脆弱な依存関係がコードスキャンの後に注入される(サプライチェイン攻撃など)可能性があります - そのため、プロダクションの直前に最終的なイメージをスキャンする、といったことが順当です。このアイデアは E2E テストに似ています - 様々な要素を独立にテストした後に、組み合わせられた完成物を最終的にチェックするといったことは価値があります。主に 3 つのスキャナファミリーがあります: 脆弱性 DB をキャッシュしたローカル/CI バイナリ、クラウド上のスキャナサービス、そして docker ビルド中にスキャンするニッチなツールです。1 つめのグループは最も人気で、通常もっとも速いものです - [Trivvy](https://github.com/aquasecurity/trivy) や [Anchore](https://github.com/anchore/anchore)、そして [Snyk](https://support.snyk.io/hc/en-us/articles/360003946897-Container-security-overview) といったツールは一度見てみる価値があります。ほとんどの CI ベンダーはこういったスキャナを組み合わせて利用するためのローカルプラグインを提供しています。注意しておくべきこととして、これらのスキャナは多くの領域をカバーしているため、すべてのスキャンで何かしらの結果が表示されるといったことがあります - 圧倒されてしまうことを避けるため、高い閾値を設定することを検討してください。 8 | 9 |

10 | 11 | ### コード例 – Trivvy を用いたスキャン 12 | 13 |
14 | 15 | Bash 16 | 17 | ``` 18 | sudo apt-get install rpm 19 | $ wget https://github.com/aquasecurity/trivy/releases/download/{TRIVY_VERSION}/trivy_{TRIVY_VERSION}_Linux-64bit.deb 20 | $ sudo dpkg -i trivy_{TRIVY_VERSION}_Linux-64bit.deb 21 | trivy image [YOUR_IMAGE_NAME] 22 | ``` 23 | 24 |
25 | 26 |

27 | 28 | ### レポート例 – Docker スキャン結果 (Anchore) 29 | 30 | ![Report examples](/assets/images/anchore-report.png "Docker scan report") 31 | -------------------------------------------------------------------------------- /sections/docker/smaller_base_images.japanese.md: -------------------------------------------------------------------------------- 1 | # 小さな Docker ベースイメージを優先する 2 | 3 | サイズの大きな Docker イメージは脆弱性にさらされる可能性を高め、リソースの消費量を増加させます。多くの場合、ビルド時に必要なパッケージは実行時にインストールする必要はありません。 4 | 大きイメージを扱う場合において、イメージをプルして保存することは、規模が大きくなるにつれてコストが高くなるでしょう。設計上、ミニマルイメージには、ネイティブモジュールの構築に必要な共通して利用されるライブラリや、デバッグに便利なパッケージ(例:curl)がプリインストールされていない場合があります。 5 | Alpine Linux のイメージを利用することで、使用されるリソースと、フル機能を備えたシステムに存在する攻撃の因子の総数の観点において、その度合を抑えることができます。Node.js v14.4.0 Docker イメージは ~345MB であるのに対し、Alpine バージョンのイメージは ~39MB と、10倍近く小さくなっています。 6 | Debian をベースとした Slim 版も良い選択肢です。わずかサイズ 38MB であり、Node.js を実行するために必要な最小限のパッケージを含んでいます。 7 | 8 | ### ブログ引用: "If you want to shrink your Docker images, have your services start faster and be more secure then try Alpine out."(Docker イメージを縮小させ、サービスの起動を高速化し、より安全性を高めたい場合は、Alpine を試してください) 9 | 10 | [Nick Janetakis のブログ](https://nickjanetakis.com/blog/the-3-biggest-wins-when-using-alpine-as-a-base-docker-image)より 11 | 12 | > Docker が、公式の Docker イメージのベースとなるイメージとして Alpine を多用していることは、もう周知の事実です。[...] 13 | > 新しいサーバーに新しい Docker イメージをプルする際は、Alpine を利用することで最初のプルが速くなると予想されます。ネットワークが遅ければ遅いほど、その差は歴然となります。[...] サイズがより小さくなることのもうひとつの利点は、攻撃される領域が小さくなることです。システム上のパッケージやライブラリの数が少ない場合、問題が発生する可能性は低くなります。 14 | -------------------------------------------------------------------------------- /sections/docker/smaller_base_images.md: -------------------------------------------------------------------------------- 1 | # Prefer smaller Docker base images 2 | 3 | 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. 4 | 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. 5 | 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. 6 | 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. 7 | 8 | ### Blog Quote: "If you want to shrink your Docker images, have your services start faster and be more secure then try Alpine out." 9 | 10 | From [Nick Janetakis' blog](https://nickjanetakis.com/blog/the-3-biggest-wins-when-using-alpine-as-a-base-docker-image) 11 | 12 | > 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. [...] 13 | 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. 14 | -------------------------------------------------------------------------------- /sections/errorhandling/apmproducts.chinese.md: -------------------------------------------------------------------------------- 1 | # 使用 APM 产品发现错误和宕机时间 2 | 3 | 4 | ### 一段解释 5 | 6 | 异常 != 错误。传统的错误处理假定存在异常,但应用程序错误可能以代码路径慢,API停机,缺少计算资源等形式出现。因为APM产品允许使用最小的设置来先前一步地检测各种各样 "深埋" 的问题,这是运用它们方便的地方。APM产品的常见功能包括: 当HTTP API返回错误时报警, 在API响应时间低于某个阈值时能被检测, 觉察到‘code smells’,监视服务器资源,包含IT度量的操作型智能仪表板以及其他许多有用的功能。大多数供应商提供免费方案。 7 | 8 | ### 关于 APM 的维基百科 9 | 10 | 在信息技术和系统管理领域, 应用程序性能管理(APM)是对软件应用程序的性能和可用性的监视和管理。APM努力检测和诊断复杂的应用程序性能问题, 以维护预期的服务级别。APM是"将IT度量标准转换为业务含义" 11 | 12 | ### 了解 APM 市场 13 | 14 | APM 产品由3个主要部分构成: 15 | 16 | 1. 网站或API监控 – 通过HTTP请求不断监视正常运行时间和性能的外部服务。可以在几分钟内安装。以下是少数选定的竞争者: [Pingdom](https://www.pingdom.com/), [Uptime Robot](https://uptimerobot.com/), 和[New Relic](https://newrelic.com/application-monitoring); 17 | 18 | 2. 代码检测 – 这类产品需要在应用程序中嵌入代理, 以实现如检测运行缓慢的代码、异常统计、性能监视等功能。以下是少数选定的竞争者: New Relic, App Dynamics; 19 | 20 | 3. 操作型智能仪表板 – 这些产品系列侧重于为ops团队提供度量和管理内容, 帮助他们轻松地保持应用程序性能维持在最佳状态。这通常涉及聚合多个信息源 (应用程序日志、DB日志、服务器日志等) 和前期仪表板设计工作。以下是少数选定的竞争者: [Datadog](https://www.datadoghq.com/), [Splunk](https://www.splunk.com/), [Zabbix](https://www.zabbix.com/); 21 | 22 | 23 | ### 示例: UpTimeRobot.Com – 网站监控仪表板 24 | ![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/uptimerobot.jpg "Website monitoring dashboard") 25 | 26 | ### 示例: AppDynamics.Com – 与代码检测结合的端到端监视 27 | ![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/app-dynamics-dashboard.png "end to end monitoring combined with code instrumentation") 28 | -------------------------------------------------------------------------------- /sections/errorhandling/documentingusingswagger.chinese.md: -------------------------------------------------------------------------------- 1 | # 使用Swagger对API错误文档化 2 | 3 | 4 | ### 一段解释 5 | 6 | REST API使用HTTP代码返回结果, API用户不仅绝对需要了解API schema, 而且还要注意潜在错误 – 调用方可能会捕获错误并巧妙地处理它。例如, 您的api文档可能提前指出, 当客户名称已经存在时, HTTP状态409将返回 (假设api注册新用户), 因此调用方可以相应地呈现给定情况下的最佳UX。Swagger是一个标准, 它定义了 API 文档的schema, 提供了一个生态系统的工具, 允许在线轻松创建文档, 请参阅下面的打印屏幕。 7 | 8 | ### 博客引用: "您必须告诉您的调用者什么错误可能发生" 9 | 摘自博客 Joyent, 对于关键字 “Node.JS logging” , 排名第一 10 | 11 | > 我们已经讨论了如何处理错误, 但是在编写新函数时, 如何将错误传递给调用您的函数的代码? 12 | ...如果你不知道会发生什么错误或者不知道他们的意思, 那么你的程序就不可能是正确的, 除非是偶然的。所以, 如果你正在写一个新的函数, 你必须告诉你的调用者什么错误可以发生, 它们的意思是什么… 13 | 14 | 15 | ### 有用的工具: Swagger 在线文档创建工具 16 | ![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/swaggerDoc.png "API error handling") -------------------------------------------------------------------------------- /sections/errorhandling/failfast.chinese.md: -------------------------------------------------------------------------------- 1 | # 快速报错,使用专用库验证参数 2 | 3 | 4 | ### 一段解释 5 | 6 | 我们都知道如何检查参数和快速报错对于避免隐藏的错误很重要(见下面的反模式代码示例)。如果没有,请阅读显式编程和防御性编程。在现实中,由于对其编码是件恼人的事情(比如考虑验证分层的JSON对象,它包含像email和日期这样的字段),我们倾向于避免做这样的事情 – 像Joi这样的库和验证器轻而易举的处理这个乏味的任务。 7 | 8 | ### 维基百科: 防御性编程 9 | 10 | 防御性编程是一种改进软件和源代码的方法, 在以下方面: 一般质量 – 减少软件 bug 和问题的数量。使源代码可理解 – 源代码应该是可读的和可理解的, 以便在代码审核中得到批准。尽管会有意外输入或用户操作, 但使软件的行为具有可预知的方式。 11 | 12 | 13 | 14 | ### 代码示例: 使用‘Joi’验证复杂的JSON输入 15 | 16 | ```javascript 17 | var memberSchema = Joi.object().keys({ 18 | password: Joi.string().regex(/^[a-zA-Z0-9]{3,30}$/), 19 | birthyear: Joi.number().integer().min(1900).max(2013), 20 | email: Joi.string().email() 21 | }); 22 | 23 | function addNewMember(newMember) 24 | { 25 | //assertions come first 26 | Joi.assert(newMember, memberSchema); //throws if validation fails 27 | //other logic here 28 | } 29 | 30 | ``` 31 | 32 | ### 反模式: 没有验证会产生令人讨厌的错误 33 | 34 | ```javascript 35 | //假如折扣为正,重定向用户去打印他的折扣优惠劵 36 | function redirectToPrintDiscount(httpResponse, member, discount) 37 | { 38 | if(discount != 0) 39 | httpResponse.redirect(`/discountPrintView/${member.id}`); 40 | } 41 | 42 | redirectToPrintDiscount(httpResponse, someMember); 43 | //忘记传递参数discount, 为什么用户被重定向到折扣页面? 44 | 45 | ``` 46 | 47 | ### 博客引用: "您应该立即抛出这些错误" 48 | 摘自博客: Joyent 49 | 50 | > 一个退化情况是有人调用一个异步函数但没有传递一个回调方法。你应该立即抛出这些错误, 因为程序有了错误, 最好的调试它的时机包括,获得至少一个stack trace, 和理想情况下,核心文件里错误的点。为此, 我们建议在函数开始时验证所有参数的类型。 -------------------------------------------------------------------------------- /sections/errorhandling/monitoring.chinese.md: -------------------------------------------------------------------------------- 1 | # 监控 2 | 3 | 4 | ### 一段解释 5 | 6 | > 在最基本的层面上,监控意味着您可以很*容易地识别出在生产环境中发生了什么不好的事情,例如,通过电子邮件或Slack通知。挑战在于选择合适的工具集来满足您的需求而不会破坏您的防护。我建议,从确定核心的指标集开始,这些指标必须被监控以确保一个健康的状态 – CPU,服务器的RAM,node进程RAM(小于1.4GB),在最后一分钟的错误量,进程重新启动的数量,平均响应时间。然后浏览一些你可能喜欢的高级功能并添加到你的愿望清单中。一些豪华的监控功能的例子:数据库分析,跨服务的测量(即测量业务交易),前端整合,暴露原始数据给自定义的BI clients,Slack通知及其他。 7 | 8 | 实现高级功能需要冗长的设置或购买商业产品如datadog,NewRelic和相似产品。不幸的是,即使是基本的实现也不像在公园散步那么简单,因为一些度量指标是硬件相关的(CPU),而其他的则在node进程内(内部错误),因此所有直接了当的工具都需要一些额外的设置。例如,云供应商监控解决方案(如AWS CloudWatch,谷歌Stackdriver)将立即告诉你关于硬件度量,但对内部应用程序的行为却无可奉告。在另一端,基于日志的解决方案如Elasticsearch默认情况下缺少hardware view。解决方案是用缺少的指标来增加您的选择,例如,一个流行的选择是将应用程序日志发送到Elastic stack,并配置一些额外的代理(如Beat)来共享与硬件相关的信息以获得完整的画面。 9 | 10 | ### 博客引用: "我们对于promise有一个问题" 11 | 摘自博客 pouchdb.com, 对于关键字“node promises”,排名11 12 | 13 | > … 我们建议您为所有服务监视这些信号: 14 | 错误率:因为错误是面向用户的,并且会立即影响您的客户。 15 | 响应时间:因为延迟直接影响您的客户和业务。 16 | 吞吐量:流量有助于您了解错误率增加和延迟的上下文。 17 | 饱和度:它告诉您的服务负载多少。如果CPU使用率是90%,你的系统能处理更多的流量吗? 18 | … 19 | -------------------------------------------------------------------------------- /sections/errorhandling/shuttingtheprocess.chinese.md: -------------------------------------------------------------------------------- 1 | # 特殊情况产生时,优雅地退出服务 2 | 3 | 4 | ### 一段解释 5 | 6 | 在您的代码的某个地方,当一个错误抛出的时候,错误处理对象负责决定如何进行时 – 如果错误是可信的(即操作型错误,在最佳实践#3了解进一步的解释),写入日志文件可能是足够的。如果错误不熟悉,事情就变得棘手了 – 这意味着某些组件可能处于故障状态,所有将来的请求都可能失败。例如,假设一个单例(singleton)的,有状态的令牌发行者服务抛出异常并失去它的状态 — 从现在起,它可能会出现意外行为并导致所有请求失败。在这种情况下,杀进程,使用“重启”的工具(像Forever,PM2,等等)重新开始。 7 | 8 | 9 | 10 | ### 代码实例: 决定是否退出 11 | 12 | ```javascript 13 | //收到未捕获的异常时,决定是否要崩溃 14 | //如果开发人员标记已知的操作型错误使用:error.isOperational=true, 查看最佳实践 #3 15 | process.on('uncaughtException', function(error) { 16 | errorManagement.handler.handleError(error); 17 | if(!errorManagement.handler.isTrustedError(error)) 18 | process.exit(1) 19 | }); 20 | 21 | 22 | //封装错误处理相关逻辑在集中的错误处理中 23 | function errorHandler(){ 24 | this.handleError = function (error) { 25 | return logger.logError(err).then(sendMailToAdminIfCritical).then(saveInOpsQueueIfCritical).then(determineIfOperationalError); 26 | } 27 | 28 | this.isTrustedError = function(error) 29 | { 30 | return error.isOperational; 31 | } 32 | 33 | ``` 34 | 35 | 36 | ### 博客引用: "最好的方式是立即崩溃" 37 | 摘自 博客:Joyent 38 | 39 | > …从程序型错误中恢复过来的最好方法是立即崩溃。你应该使用一个重启助手来运行您的程序,它会在崩溃的情况下自动启动程序。当使用重启助手,崩溃是面对临时性的程序型错误时,恢复可靠的服务的最快的方法… 40 | 41 | 42 | ### 博客引用: "错误处理有三种流派" 43 | 摘自 博客:JS Recipes 44 | 45 | > …错误处理主要有三种流派: 46 | 1. 让应用崩溃,并重启。 47 | 2. 处理所有的错误,从不崩溃。 48 | 3. 介于两者之间。 49 | 50 | 51 | ### 博客引用: "不伴随着创建一些易碎的状态,是没有保险的方式退出" 52 | 摘自 Node.JS 官方文档 53 | 54 | > …就throw工作在JavaScript的本质而言,几乎没有任何方法可以安全地“在您丢下的地方捡起”,而不会泄漏引用,或者创建其他类型的未定义的易碎性状态。对抛出的错误作出响应的最安全的方法是关闭进程。当然,在一个普通的Web服务器中,可能有很多连接打开了,因为其他人触发了一个错误,所以突然关闭这些连接是不合理的。更好的方法是将错误响应发送给触发错误的请求,同时让其他人在正常时间内完成,并停止侦听该工作者的新请求。 -------------------------------------------------------------------------------- /sections/errorhandling/testingerrorflows.brazilian-portuguese.md: -------------------------------------------------------------------------------- 1 | # Fluxos de testes de erros usando seu framework favorito 2 | 3 | ### Explicação em um Parágrafo 4 | 5 | Testar caminhos "felizes" não é melhor do que testar falhas. Uma boa cobertura de código de teste exige testar caminhos excepcionais. Caso contrário, não há confiança de que as exceções sejam realmente tratadas corretamente. Cada estrutura de testes unitários, como o [Mocha](https://mochajs.org/) e [Chai](http://chaijs.com/), suporta testes de exceção (exemplos de código abaixo). Se você achar tedioso testar todas as funções internas e exceções, você pode resolver testando apenas erros HTTP da API REST. 6 | 7 | ### Exemplo de código: garantindo que a exceção correta seja lançada usando Mocha & Chai 8 | 9 | ```javascript 10 | describe("Bate-papo do Facebook", () => { 11 | it("Notifica em nova mensagem de bate-papo", () => { 12 | var chatService = new chatService(); 13 | chatService.participants = getDisconnectedParticipants(); 14 | expect(chatService.sendMessage.bind({ message: "Oi" })).to.throw(ConnectionError); 15 | }); 16 | }); 17 | 18 | ``` 19 | 20 | ### Exemplo de código: garantindo que a API retorne o código de erro HTTP correto 21 | 22 | ```javascript 23 | it("Cria um novo grupo no Facebook", function (done) { 24 | var invalidGroupInfo = {}; 25 | httpRequest({ 26 | method: 'POST', 27 | uri: "facebook.com/api/groups", 28 | resolveWithFullResponse: true, 29 | body: invalidGroupInfo, 30 | json: true 31 | }).then((response) => { 32 | // se fôssemos executar o código neste bloco, nenhum erro foi lançado na operação acima 33 | }).catch(function (response) { 34 | expect(400).to.equal(response.statusCode); 35 | done(); 36 | }); 37 | }); 38 | ``` 39 | -------------------------------------------------------------------------------- /sections/errorhandling/testingerrorflows.chinese.md: -------------------------------------------------------------------------------- 1 | # 使用您喜欢的测试框架测试错误流 2 | 3 | 4 | ### 一段解释 5 | 6 | 测试‘正确’路径并不比测试失败更好。良好的测试代码覆盖率要求测试异常路径。否则,异常确实被处理正确是不可信的。每个单元测试框架,如[Mocha](https://mochajs.org/) & [Chai](http://chaijs.com/),都支持异常测试(请看下面的代码示例)。如果您觉得测试每个内部函数和异常都很乏味,那么您可以只测试REST API HTTP错误。 7 | 8 | 9 | 10 | ### 代码示例: 使用 Mocha & Chai 确保正确的异常被抛出 11 | 12 | ```javascript 13 | describe("Facebook chat", () => { 14 | it("Notifies on new chat message", () => { 15 | var chatService = new chatService(); 16 | chatService.participants = getDisconnectedParticipants(); 17 | expect(chatService.sendMessage.bind({message: "Hi"})).to.throw(ConnectionError); 18 | }); 19 | }); 20 | 21 | ``` 22 | 23 | ### 代码示例: 确保 API 返回正确的 HTTP 错误码 24 | 25 | ```javascript 26 | it("Creates new Facebook group", function (done) { 27 | var invalidGroupInfo = {}; 28 | httpRequest({method: 'POST', uri: "facebook.com/api/groups", resolveWithFullResponse: true, body: invalidGroupInfo, json: true 29 | }).then((response) => { 30 | //oh no if we reached here than no exception was thrown 31 | }).catch(function (response) { 32 | expect(400).to.equal(response.statusCode); 33 | done(); 34 | }); 35 | }); 36 | 37 | ``` -------------------------------------------------------------------------------- /sections/errorhandling/testingerrorflows.korean.md: -------------------------------------------------------------------------------- 1 | # Test error flows using your favorite test framework 2 | 3 | ### One Paragraph Explainer 4 | 5 | Testing ‘happy’ paths is no better than testing failures. Good testing code coverage demands to test exceptional paths. Otherwise, there is no trust that exceptions are indeed handled correctly. Every unit testing framework, like [Mocha](https://mochajs.org/) & [Chai](http://chaijs.com/), supports exception testing (code examples below). If you find it tedious to test every inner function and exception you may settle with testing only REST API HTTP errors. 6 | 7 | ### Code example: ensuring the right exception is thrown using Mocha & Chai 8 | 9 | ```javascript 10 | describe("Facebook chat", () => { 11 | it("Notifies on new chat message", () => { 12 | var chatService = new chatService(); 13 | chatService.participants = getDisconnectedParticipants(); 14 | expect(chatService.sendMessage.bind({ message: "Hi" })).to.throw(ConnectionError); 15 | }); 16 | }); 17 | 18 | ``` 19 | 20 | ### Code example: ensuring API returns the right HTTP error code 21 | 22 | ```javascript 23 | it("Creates new Facebook group", function (done) { 24 | var invalidGroupInfo = {}; 25 | httpRequest({ 26 | method: 'POST', 27 | uri: "facebook.com/api/groups", 28 | resolveWithFullResponse: true, 29 | body: invalidGroupInfo, 30 | json: true 31 | }).then((response) => { 32 | // if we were to execute the code in this block, no error was thrown in the operation above 33 | }).catch(function (response) { 34 | expect(400).to.equal(response.statusCode); 35 | done(); 36 | }); 37 | }); 38 | ``` 39 | -------------------------------------------------------------------------------- /sections/errorhandling/usematurelogger.chinese.md: -------------------------------------------------------------------------------- 1 | # 使用成熟的logger提高错误可见性 2 | 3 | ### 一段解释 4 | 5 | 我们都特别喜欢(loovve)console.log,但显而易见地,对于严肃的项目, 有信誉和持久的Logger是必需的,比如[Winston][winston] (非常流行) or [Pino][pino](专注于性能的新库)。一套实践和工具将有助于更快速地解释错误 – (1)使用不同的级别(debug, info, error)频繁地log;(2)在记录日志时, 以 JSON 对象的方式提供上下文信息, 请参见下面的示例;(3)使用日志查询API(在大多数logger中内置)或日志查看程序软件监视和筛选日志;(4)使用操作智能工具(如 Splunk)为操作团队公开和管理日志语句。 6 | 7 | [winston]: https://www.npmjs.com/package/winston 8 | [bunyan]: https://www.npmjs.com/package/bunyan 9 | [pino]: https://www.npmjs.com/package/pino 10 | 11 | ### 代码示例 – 使用Winston Logger 12 | 13 | ```javascript 14 | //您的集中式logger对象 15 | var logger = new winston.Logger({ 16 | level: 'info', 17 | transports: [ 18 | new (winston.transports.Console)(), 19 | new (winston.transports.File)({ filename: 'somefile.log' }) 20 | ] 21 | }); 22 | 23 | //在某个地方使用logger的自定义代码 24 | logger.log('info', 'Test Log Message with some parameter %s', 'some parameter', { anything: 'This is metadata' }); 25 | 26 | ``` 27 | 28 | ### 代码示例 – 查询日志文件夹 (搜索条目) 29 | 30 | ```javascript 31 | var options = { 32 | from: new Date - 24 * 60 * 60 * 1000, 33 | until: new Date, 34 | limit: 10, 35 | start: 0, 36 | order: 'desc', 37 | fields: ['message'] 38 | }; 39 | 40 | 41 | // 查找在今天和昨天之间记录的项目 42 | winston.query(options, function (err, results) { 43 | //对于结果的回调处理 44 | }); 45 | 46 | ``` 47 | 48 | ### 博客引用: "Logger要求" 49 | 摘自博客 Strong Loop 50 | 51 | > 让我们确定一些要求 (对于logger): 52 | 1. 为每条日志添加时间戳。这条很好自我解释-你应该能够告知每个日志条目发生在什么时候。 53 | 2. 日志格式应易于被人类和机器理解。 54 | 3. 允许多个可配置的目标流。例如, 您可能正在将trace log写入到一个文件中, 但遇到错误时, 请写入同一文件, 然后写入到错误日志文件,并同时发送电子邮件… 55 | -------------------------------------------------------------------------------- /sections/errorhandling/usematurelogger.japanese.md: -------------------------------------------------------------------------------- 1 | # エラーの可視性を高めるために成熟したロガーを使用する 2 | 3 | ### 一段落説明 4 | 5 | 私たちはみな console.log を愛用していますが、明らかに [Winston][winston](非常に人気)や [Pino][pino](パフォーマンスにフォーカスした新参者)のような、評価が高く永続的なロガーが真面目なプロジェクトにおいて必須となります。一連のプラクティスやツール群は、より素早くエラーについての考察を行うことに役立ちます ー(1)ログレベルを使い分ける(debug、info、error)、(2)ロギングする際は、JSON オブジェクトとしてコンテキスト情報を提供する(下記の例を参照)、(3)(多くのロガーに組み込まれている)ログクエリ API やログビューアソフトウェアを使用して、ログの確認やフィルタリングを行う、(4)Splunk のような運用ツールを使用して、運用チームのためにログステートメントを公開し、まとめる 6 | 7 | [winston]: https://www.npmjs.com/package/winston 8 | [pino]: https://www.npmjs.com/package/pino 9 | 10 | ### コード例 – Winston 実践 11 | 12 | ```javascript 13 | // 集中化されたロガーオブジェクト 14 | const logger = new winston.Logger({ 15 | level: 'info', 16 | transports: [ 17 | new (winston.transports.Console)() 18 | ] 19 | }); 20 | 21 | // ロガーを使用したカスタムコード 22 | logger.log('info', 'Test Log Message with some parameter %s', 'some parameter', { anything: 'This is metadata' }); 23 | ``` 24 | 25 | ### コード例 – ログフォルダをクエリする(エントリを検索する) 26 | 27 | ```javascript 28 | const options = { 29 | from: Date.now() - 24 * 60 * 60 * 1000, 30 | until: new Date(), 31 | limit: 10, 32 | start: 0, 33 | order: 'desc', 34 | fields: ['message'] 35 | }; 36 | 37 | // 1日前から今にかけてのログを見つける 38 | winston.query(options, (err, results) => { 39 | // results を受け取ってコールバックを実行する 40 | }); 41 | ``` 42 | 43 | ### ブログ引用: "Logger Requirements"(ロガーの要件) 44 | 45 | ブログ Strong Loop より 46 | 47 | > (ロガーのための)いくつかの要件を確認してみましょう: 48 | 1. 各ログ行にタイムスタンプをつけましょう。これは非常に自明です ー 各ログエントリがいつ発生したのかをはっきりさせることができるはずです。 49 | 2. ロギングフォーマットは、機械だけでなく人間にとっても容易に解釈できるものであるべきです。 50 | 3. 複数の設定可能な送信先ストリームを許可しましょう。例えば、あるファイルにトレースログを書き込み、一方でエラーが発生した際は同様のファイルに書き込むと同時にエラーファイルにも書き込み、そして e メールを送信するかもしれません。 51 | -------------------------------------------------------------------------------- /sections/examples/dockerfile/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .git 3 | README.md 4 | LICENSE 5 | .vscode 6 | .idea 7 | npm-debug.log 8 | coverage 9 | .env 10 | .editorconfig 11 | .aws 12 | dist 13 | .npmrc 14 | -------------------------------------------------------------------------------- /sections/examples/dockerfile/.npmrc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gngsn/nodebestpractices/9ad86392da606ba6cfbc280c4bfc064afa8105b6/sections/examples/dockerfile/.npmrc -------------------------------------------------------------------------------- /sections/examples/dockerfile/Dockerfile: -------------------------------------------------------------------------------- 1 | # This is a multistage Dockerfile. 2 | # In the first stage we install system build dependencies, copy project files and build them 3 | # In the second stage, we start fresh and only copy necessary files. We also purge node_modules devDependencies. 4 | 5 | #### Build stage #### 6 | FROM node:14.8.0-alpine AS build 7 | 8 | # Install system build dependencies (if needed) at the top ✅ See bullet point #8.8 about caching 9 | RUN apk add --update --no-cache bash make gcc g++ lcms2-dev libpng-dev autoconf automake 10 | 11 | # Only copy node dependency information and install all dependencies first 12 | COPY --chown=node:node package.json package-lock.json ./ 13 | 14 | # Install packages using the lockfiles as source of truth ✅ See bullet point #8.5 about npm ci 15 | RUN npm ci 16 | 17 | # Copy source code (and all other relevant files) 18 | COPY --chown=node:node src ./src 19 | 20 | # Build code 21 | RUN npm run build 22 | 23 | #### Run-time stage #### 24 | # ✅ See bullet point #8.10 about smaller docker base images 25 | FROM node:14.8.0-alpine as app 26 | 27 | # Set non-root user and expose port 3000 28 | USER node 29 | EXPOSE 3000 30 | 31 | WORKDIR /home/node/app 32 | 33 | # Copy dependency information and build output from previous stage 34 | COPY --chown=node:node --from=build package.json package-lock.json ./ 35 | COPY --chown=node:node --from=build node_modules ./node_modules 36 | COPY --chown=node:node --from=build dist ./dist 37 | 38 | # Clean dev dependencies ✅ See bullet point #8.5 39 | RUN npm prune --production && npm cache clean --force 40 | 41 | # ✅ See bullet point #8.2 about avoiding npm start 42 | CMD [ "node", "dist/app.js" ] 43 | -------------------------------------------------------------------------------- /sections/examples/dockerfile/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-app-with-docker", 3 | "version": "1.0.0", 4 | "description": "An example node app that uses docker to be built", 5 | "main": "src/app.ts", 6 | "scripts": { 7 | "start": "node dist/app.js", 8 | "build": "tsc --outDir dist -m commonjs -t ES2020 src/app.ts", 9 | "test": "echo \"Error: no test specified\" && exit 1" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "git+https://github.com/goldbergyoni/nodebestpractices.git" 14 | }, 15 | "author": "", 16 | "license": "ISC", 17 | "bugs": { 18 | "url": "https://github.com/goldbergyoni/nodebestpractices/issues" 19 | }, 20 | "homepage": "https://github.com/goldbergyoni/nodebestpractices#readme", 21 | "dependencies": { 22 | "express": "^4.17.1" 23 | }, 24 | "devDependencies": { 25 | "@types/express": "^4.17.7", 26 | "typescript": "^3.9.7" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /sections/examples/dockerfile/src/app.ts: -------------------------------------------------------------------------------- 1 | import * as express from 'express'; 2 | const app = express(); 3 | 4 | app.get('/', (req, res) => { 5 | res.send('Hello World!') 6 | }) 7 | 8 | app.listen(3000, () => { 9 | console.log('Navigate to http://localhost:3000'); 10 | }); 11 | -------------------------------------------------------------------------------- /sections/production/LTSrelease.brazilian-portuguese.md: -------------------------------------------------------------------------------- 1 | # Use uma versão LTS do Node.js em produção 2 | 3 | ### Explicação em um Parágrafo 4 | 5 | Verifique se você está usando uma versão LTS (Long Term Support) do Node.js em produção para receber correções de bugs críticos, atualizações de segurança e melhorias de desempenho. 6 | 7 | As versões LTS do Node.js são suportadas por pelo menos 18 meses e são indicadas por números de versão pares (por exemplo, 4, 6, 8). Eles são melhores para produção, já que a linha de lançamento LTS é focada em estabilidade e segurança, enquanto a linha de lançamento 'Atual' tem uma vida útil mais curta e atualizações mais frequentes no código. As alterações nas versões LTS estão limitadas a correções de bugs para estabilidade, atualizações de segurança, possíveis atualizações npm, atualizações de documentação e certos aprimoramentos de desempenho que podem ser demonstrados para não interromper aplicações. existentes. 8 | 9 |

10 | 11 | ### Leia em 12 | 13 | 🔗 [Definições de lançamento do Node.js](https://nodejs.org/en/about/releases/) 14 | 15 | 🔗 [Agenda de lançamento do Node.js](https://github.com/nodejs/Release) 16 | 17 | 🔗 [Etapas Essenciais: Suporte de Longo Prazo para o Node.js por Rod Vagg](https://medium.com/@nodesource/essential-steps-long-term-support-for-node-js-8ecf7514dbd) 18 | > ...o cronograma de lançamentos incrementais dentro de cada um deles será impulsionado pela disponibilidade de correções de bugs, correções de segurança e outras pequenas, mas importantes, alterações. O foco será na estabilidade, mas a estabilidade também inclui a minimização do número de bugs conhecidos e a manutenção das preocupações de segurança à medida que elas surgem. 19 | 20 |

21 | -------------------------------------------------------------------------------- /sections/production/LTSrelease.japanese.md: -------------------------------------------------------------------------------- 1 | # Node.js の LTS リリースをプロダクションで使用する 2 | 3 | ### 一段落説明 4 | 5 | 重要なバグ修正、セキュリティアップデート、パフォーマンスの改善を受けるために、本番環境で Node.js の LTS(Long Term Support) バージョンを使用していることを確認してください。 6 | 7 | Node.js の LTS バージョンは少なくとも18ヶ月間サポートされており、偶数のバージョン番号(例えば4, 6, 8)で示されています。LTS のリリースラインは安定性とセキュリティに焦点を当てているので、運用には最適ですが、「Current」 のリリースラインは寿命が短く、コードの更新がより頻繁に行われます。LTS のバージョンへの変更は、安定性のためのバグ修正、セキュリティ更新、可能な npm の更新、ドキュメントの更新、既存のアプリケーションを壊さないことが証明できる特定のパフォーマンスの改善に限定されます。 8 | 9 |

10 | 11 | ### 続きを読む 12 | 13 | 🔗 [Node.js のリリース定義](https://nodejs.org/en/about/releases/) 14 | 15 | 🔗 [Node.js リリーススケジュール](https://github.com/nodejs/Release) 16 | 17 | 🔗 [Essential Steps: 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) 18 | > ...これらの中での増分リリースのスケジュールは、バグ修正、セキュリティ修正、その他の小さいが重要な変更の有無によって決定されます。安定性に重点が置かれますが、安定性には既知のバグの数を最小限に抑え、セキュリティ上の懸念事項が発生した場合には、それを常に把握しておくことも含まれます。 19 | 20 |

21 | -------------------------------------------------------------------------------- /sections/production/LTSrelease.korean.md: -------------------------------------------------------------------------------- 1 | # Use an LTS release of Node.js in production 2 | 3 | ### One Paragraph Explainer 4 | 5 | Ensure you are using an LTS(Long Term Support) version of Node.js in production to receive critical bug fixes, security updates and performance improvements. 6 | 7 | LTS versions of Node.js are supported for at least 18 months and are indicated by even version numbers (e.g. 4, 6, 8). They're best for production since the LTS release line is focussed on stability and security, whereas the 'Current' release line has a shorter lifespan and more frequent updates to the code. Changes to LTS versions are limited to bug fixes for stability, security updates, possible npm updates, documentation updates and certain performance improvements that can be demonstrated to not break existing applications. 8 | 9 |

10 | 11 | ### Read on 12 | 13 | 🔗 [Node.js release definitions](https://nodejs.org/en/about/releases/) 14 | 15 | 🔗 [Node.js release schedule](https://github.com/nodejs/Release) 16 | 17 | 🔗 [Essential Steps: Long Term Support for Node.js by Rod Vagg](https://medium.com/@nodesource/essential-steps-long-term-support-for-node-js-8ecf7514dbd) 18 | > ...the schedule of incremental releases within each of these will be driven by the availability of bug fixes, security fixes, and other small but important changes. The focus will be on stability, but stability also includes minimizing the number of known bugs and staying on top of security concerns as they arise. 19 | 20 |

21 | -------------------------------------------------------------------------------- /sections/production/LTSrelease.md: -------------------------------------------------------------------------------- 1 | # Use an LTS release of Node.js in production 2 | 3 | ### One Paragraph Explainer 4 | 5 | Ensure you are using an LTS(Long Term Support) version of Node.js in production to receive critical bug fixes, security updates and performance improvements. 6 | 7 | LTS versions of Node.js are supported for at least 18 months and are indicated by even version numbers (e.g. 4, 6, 8). They're best for production since the LTS release line is focussed on stability and security, whereas the 'Current' release line has a shorter lifespan and more frequent updates to the code. Changes to LTS versions are limited to bug fixes for stability, security updates, possible npm updates, documentation updates and certain performance improvements that can be demonstrated to not break existing applications. 8 | 9 |

10 | 11 | ### Read on 12 | 13 | 🔗 [Node.js release definitions](https://nodejs.org/en/about/releases/) 14 | 15 | 🔗 [Node.js release schedule](https://github.com/nodejs/Release) 16 | 17 | 🔗 [Essential Steps: Long Term Support for Node.js by Rod Vagg](https://medium.com/@nodesource/essential-steps-long-term-support-for-node-js-8ecf7514dbd) 18 | > ...the schedule of incremental releases within each of these will be driven by the availability of bug fixes, security fixes, and other small but important changes. The focus will be on stability, but stability also includes minimizing the number of known bugs and staying on top of security concerns as they arise. 19 | 20 |

21 | -------------------------------------------------------------------------------- /sections/production/LTSrelease.polish.md: -------------------------------------------------------------------------------- 1 | # Użyj wersji LTS Node.js w produkcji 2 | 3 | ### Wyjaśnienie jednym akapitem 4 | 5 | Upewnij się, że korzystasz z wersji LTS (Long Term Support) Node.js w produkcji, aby otrzymywać krytyczne poprawki błędów, aktualizacje zabezpieczeń i ulepszenia wydajności. 6 | 7 | Wersje Lode Node.js są obsługiwane przez co najmniej 18 miesięcy i są oznaczone parzystymi numerami wersji (np. 4, 6, 8). Najlepiej nadają się do produkcji, ponieważ linia wydania LTS koncentruje się na stabilności i bezpieczeństwie, podczas gdy linia wydania „Bieżąca” ma krótszą żywotność i częstsze aktualizacje kodu. Zmiany w wersjach LTS ograniczają się do poprawek błędów dotyczących stabilności, aktualizacji bezpieczeństwa, możliwych aktualizacji npm, aktualizacji dokumentacji i pewnych ulepszeń wydajności, które można wykazać, aby nie powodować awarii istniejących aplikacji. 8 | 9 |

10 | 11 | ### Czytaj 12 | 13 | 🔗 [Node.js release definitions](https://nodejs.org/en/about/releases/) 14 | 15 | 🔗 [Node.js release schedule](https://github.com/nodejs/Release) 16 | 17 | 🔗 [Essential Steps: Long Term Support for Node.js by Rod Vagg](https://medium.com/@nodesource/essential-steps-long-term-support-for-node-js-8ecf7514dbd) 18 | > ...the schedule of incremental releases within each of these will be driven by the availability of bug fixes, security fixes, and other small but important changes. The focus will be on stability, but stability also includes minimizing the number of known bugs and staying on top of security concerns as they arise. 19 | 20 |

21 | -------------------------------------------------------------------------------- /sections/production/LTSrelease.russian.md: -------------------------------------------------------------------------------- 1 | # Используйте LTS-релиз Node.js в производстве 2 | 3 | ### Объяснение в один абзац 4 | 5 | Убедитесь, что вы используете LTS (Long Term Support) версию Node.js в работе, чтобы получать критические исправления ошибок, обновления безопасности и улучшения производительности. 6 | 7 | LTS-версии Node.js поддерживаются в течение не менее 18 месяцев и обозначаются четными номерами версий (например, 4, 6, 8). Они лучше всего подходят для производства, поскольку линия выпуска LTS ориентирована на стабильность и безопасность, тогда как линия выпуска "текущий" имеет более короткий срок службы и более частые обновления кода. Изменения в версиях LTS ограничены исправлениями ошибок для стабильности, обновлениями безопасности, возможными обновлениями npm, обновлениями документации и некоторыми улучшениями производительности, которые можно продемонстрировать, чтобы не сломать существующие приложения. 8 | 9 |

10 | 11 | ### Читать еще 12 | 13 | 🔗 [Node.js release definitions](https://nodejs.org/en/about/releases/) 14 | 15 | 🔗 [Node.js release schedule](https://github.com/nodejs/Release) 16 | 17 | 🔗 [Essential Steps: Long Term Support for Node.js by Rod Vagg](https://medium.com/@nodesource/essential-steps-long-term-support-for-node-js-8ecf7514dbd) 18 | > ... график дополнительных выпусков в каждом из них будет зависеть от наличия исправлений ошибок, исправлений безопасности и других небольших, но важных изменений. Основное внимание будет уделяться стабильности, но стабильность также включает в себя минимизацию количества известных ошибок и устранение проблем безопасности по мере их возникновения. 19 | 20 |

21 | -------------------------------------------------------------------------------- /sections/production/apmproducts.brazilian-portuguese.md: -------------------------------------------------------------------------------- 1 | # Descubra erros e tempo de inatividade usando produtos APM 2 | 3 |

4 | 5 | ### Explicação em um Parágrafo 6 | 7 | O APM (monitoramento de desempenho de aplicação) refere-se a uma família de produtos que visa monitorar o desempenho da aplicação de ponta a ponta, também da perspectiva do cliente. Enquanto as soluções de monitoramento tradicionais se concentram em exceções e métricas técnicas autônomas (por exemplo, rastreamento de erros, pontos de extremidade de servidor lentos etc.), no mundo real nossa aplicação sem exceções de código pode criar usuários decepcionados, por exemplo, se algum serviço de middleware for executado muito lentamente. Os produtos APM medem a experiência do usuário de ponta a ponta, por exemplo, dado um sistema que engloba a UI frontend e vários serviços distribuídos - alguns produtos APM podem dizer quão rápido dura uma transação que abrange vários níveis. Pode dizer se a experiência do usuário é sólida e apontar para o problema. Essa oferta atrativa vem com um preço relativamente alto, portanto, é recomendada para produtos complexos e em larga escala que exigem ir além do monitoramento direto. 8 | 9 |

10 | 11 | ### Exemplo de APM - um produto comercial que visualiza o desempenho de aplicações de serviço cruzado 12 | 13 | ![Exemplo de APM](/assets/images/apm1.png "Exemplo de APM") 14 | 15 |

16 | 17 | ### Exemplo de APM - um produto comercial que enfatiza a pontuação da experiência do usuário 18 | 19 | ![Exemplo de APM](/assets/images/apm2.png "Exemplo de APM") 20 | 21 |

22 | 23 | ### Exemplo de APM - um produto comercial que destaca caminhos de código lento 24 | 25 | ![Exemplo de APM](/assets/images/apm3.png "Exemplo de APM") 26 | -------------------------------------------------------------------------------- /sections/production/apmproducts.chinese.md: -------------------------------------------------------------------------------- 1 | # 使用APM产品确保用户体验 2 | 3 |

4 | 5 | 6 | ### 一段解释 7 | 8 | APM(应用程序性能监视)指的是一个产品系列, 目的是从端到端,也从客户的角度监控应用程序的性能。虽然传统的监控解决方案侧重于异常和独立的技术指标 (例如错误跟踪、检测慢速服务器节点等), 在现实世界中, 我们的应用程序可能会在没有任何代码异常的情况下让用户使用起来感到失望, 例如, 如果某些中间件服务执行得非常慢。APM 产品从端到端检测用户体验, 例如, 给定一个包含前端 UI 和多个分布式服务的系统 – 一些 APM 产品可以告诉您, 一个跨过多个层的事务的速度有多快。它可以判断用户体验是否可靠, 并指出问题所在。这种诱人的产品通常有一个相对较高的价格标签, 因此, 对于需要超越一般的监测的,大规模的和复杂的产品, 它们是值得推荐的。 9 | 10 |

11 | 12 | 13 | ### APM 示例 – 一种可视化显示跨服务应用性能的商业产品 14 | ![APM example](/assets/images/apm1.png "APM example") 15 | 16 |

17 | 18 | ### APM 示例 – 一种强调用户体验评分的商业产品 19 | 20 | ![APM example](/assets/images/apm2.png "APM example") 21 | 22 |

23 | 24 | ### APM 示例 – 一种突出显示慢速代码路径的商业产品 25 | 26 | ![APM example](/assets/images/apm3.png "APM example") 27 | -------------------------------------------------------------------------------- /sections/production/apmproducts.japanese.md: -------------------------------------------------------------------------------- 1 | # APM 製品の確かなユーザー体験 2 | 3 |

4 | 5 | ### 一段落説明 6 | 7 | APM(アプリケーション・パフォーマンス・モニタリング)とは、エンド・ツー・エンド、また顧客の視点からアプリケーションのパフォーマンスを監視することを目的とした製品群のことです。従来のモニタリングソリューションでは、例外やスタンドアローンの技術的なメトリクス(エラー追跡、遅いサーバーエンドポイントなど)に焦点を当てていましたが、現実の世界では、例えば、あるミドルウェアサービスが実際に遅い動作をしていた場合など、コードの例外がなくても、私たちのアプリがユーザーを失望させる可能性があります。APM 製品は、例えばフロントエンドの UI と複数の分散サービスを含むシステムを想定して、エンド・ツー・エンドまでのユーザーエクスペリエンスを測定します。 – APM 製品の中には、複数の階層にまたがるトランザクションがどのくらいの速さで最後まで実行されるかを伝えることができるものがあります。ユーザー体験がしっかりしているかどうかが分かり、問題点を指摘してくれます。この魅力的な製品は比較的高い価格帯で提供されているため、単純なモニタリングの域を超えた大規模で複雑なプロダクトにお勧めです。 8 | 9 |

10 | 11 | ### APM の例 – サービス間のアプリパフォーマンスを可視化する商用製品 12 | 13 | ![APM の例](/assets/images/apm1.png "APM の例") 14 | 15 |

16 | 17 | ### APM の例 – ユーザーエクスペリエンススコアを重視した市販品 18 | 19 | ![APM の例](/assets/images/apm2.png "APM の例") 20 | 21 |

22 | 23 | ### APM の例 – 遅いコードパスをハイライトする商用製品 24 | 25 | ![APM の例](/assets/images/apm3.png "APM の例") 26 | -------------------------------------------------------------------------------- /sections/production/apmproducts.korean.md: -------------------------------------------------------------------------------- 1 | # Sure user experience with APM products 2 | 3 |

4 | 5 | ### One Paragraph Explainer 6 | 7 | APM (application performance monitoring) refers to a family of products that aims to monitor application performance from end to end, also from the customer perspective. While traditional monitoring solutions focus on Exceptions and standalone technical metrics (e.g. error tracking, slow server endpoints, etc), in the real world our app might create disappointed users without any code exceptions, for example, if some middleware service performed real slow. APM products measure the user experience from end to end, for example, given a system that encompasses frontend UI and multiple distributed services – some APM products can tell how fast a transaction that spans multiple tiers last. It can tell whether the user experience is solid and point to the problem. This attractive offering comes with a relatively high price tag hence it’s recommended for large-scale and complex products that require going beyond straightforward monitoring. 8 | 9 |

10 | 11 | ### APM example – a commercial product that visualizes cross-service app performance 12 | 13 | ![APM example](/assets/images/apm1.png "APM example") 14 | 15 |

16 | 17 | ### APM example – a commercial product that emphasizes the user experience score 18 | 19 | ![APM example](/assets/images/apm2.png "APM example") 20 | 21 |

22 | 23 | ### APM example – a commercial product that highlights slow code paths 24 | 25 | ![APM example](/assets/images/apm3.png "APM example") 26 | -------------------------------------------------------------------------------- /sections/production/apmproducts.md: -------------------------------------------------------------------------------- 1 | # Sure user experience with APM products 2 | 3 |

4 | 5 | ### One Paragraph Explainer 6 | 7 | APM (application performance monitoring) refers to a family of products that aims to monitor application performance from end to end, also from the customer perspective. While traditional monitoring solutions focus on Exceptions and standalone technical metrics (e.g. error tracking, slow server endpoints, etc), in the real world our app might create disappointed users without any code exceptions, for example, if some middleware service performed real slow. APM products measure the user experience from end to end, for example, given a system that encompasses frontend UI and multiple distributed services – some APM products can tell how fast a transaction that spans multiple tiers last. It can tell whether the user experience is solid and point to the problem. This attractive offering comes with a relatively high price tag hence it’s recommended for large-scale and complex products that require going beyond straightforward monitoring. 8 | 9 |

10 | 11 | ### APM example – a commercial product that visualizes cross-service app performance 12 | 13 | ![APM example](/assets/images/apm1.png "APM example") 14 | 15 |

16 | 17 | ### APM example – a commercial product that emphasizes the user experience score 18 | 19 | ![APM example](/assets/images/apm2.png "APM example") 20 | 21 |

22 | 23 | ### APM example – a commercial product that highlights slow code paths 24 | 25 | ![APM example](/assets/images/apm3.png "APM example") 26 | -------------------------------------------------------------------------------- /sections/production/apmproducts.polish.md: -------------------------------------------------------------------------------- 1 | # Zapewnij użytkownikom wygodę korzystania z produktów APM 2 | 3 |

4 | 5 | ### Wyjaśnienie jednym akapitem 6 | 7 | APM (application performance monitoring) odnosi się do rodziny produktów, która ma na celu monitorowanie wydajności aplikacji od początku do końca, również z perspektywy klienta. Podczas gdy tradycyjne rozwiązania monitorujące koncentrują się na wyjątkach i niezależnych pomiarach technicznych (np. śledzeniu błędów, powolnych punktach końcowych serwera itp.), w prawdziwym świecie nasza aplikacja może tworzyć rozczarowanych użytkowników bez żadnych wyjątków kodu, na przykład, jeśli niektóre usługi oprogramowania pośredniego działają naprawdę wolno. Produkty APM mierzą wrażenia użytkownika end-to-end, na przykład, biorąc pod uwagę system, który obejmuje interfejs użytkownika frontend i wiele usług rozproszonych - niektóre produkty APM mogą powiedzieć, jak szybko trwa transakcja obejmująca wiele poziomów. Może stwierdzić, czy wrażenia użytkownika są solidne i wskazać problem. Ta atrakcyjna oferta ma stosunkowo wysoką cenę, dlatego jest zalecana do dużych i złożonych produktów, które wymagają wykraczania poza proste monitorowanie. 8 | 9 |

10 | 11 | ### APM przykład - produkt komercyjny, który wizualizuje wydajność aplikacji między usługami 12 | 13 | ![APM example](/assets/images/apm1.png "APM example") 14 | 15 |

16 | 17 | ### APM przykład - produkt komercyjny, który podkreśla ocenę doświadczenia użytkownika 18 | 19 | ![APM example](/assets/images/apm2.png "APM example") 20 | 21 |

22 | 23 | ### APM przykład - produkt komercyjny, który wyróżnia wolne ścieżki kodu 24 | 25 | ![APM example](/assets/images/apm3.png "APM example") 26 | -------------------------------------------------------------------------------- /sections/production/assigntransactionid.chinese.md: -------------------------------------------------------------------------------- 1 | # 在每一个log语句指定‘TransactionId’ 2 | 3 |

4 | 5 | 6 | ### 一段解释 7 | 8 | 一个典型的日志是来自所有组件和请求的条目的仓库。当检测到一些可疑行或错误时,为了与其他属于同一特定流程的行(如用户“约翰”试图购买某物)相匹配,就会变得难以应付。特别在微服务环境下,当一个请求/交易可能跨越多个计算机,这变得更加重要和具有挑战性。解决这个问题,可以通过指定一个唯一的事务标识符给从相同的请求过来的所有条目,这样当检测到一行,可以复制这个id,并搜索包含这个transaction id的每一行。但是,在node中实现这个不是那么直截了当的,这是由于它的单线程被用来服务所有的请求 – 考虑使用一个库,它可以在请求层对数据进行分组 – 在下一张幻灯片查看示例代码。当调用其它微服务,使用HTTP头“x-transaction-id”传递transaction id去保持相同的上下文。 9 | 10 |

11 | 12 | 13 | ### 代码示例: 典型的nginx配置 14 | 15 | ```javascript 16 | //当接收到一个新的要求,开始一个新的隔离的上下文和设置一个事务transaction id。下面的例子是使用NPM库continuation-local-storage去隔离请求 17 | 18 | const { createNamespace } = require('continuation-local-storage'); 19 | var session = createNamespace('my session'); 20 | 21 | router.get('/:id', (req, res, next) => { 22 | session.set('transactionId', 'some unique GUID'); 23 | someService.getById(req.params.id); 24 | logger.info('Starting now to get something by Id'); 25 | }); 26 | 27 | //现在, 任何其他服务或组件都可以访问上下文、每个请求、数据 28 | class someService { 29 | getById(id) { 30 | logger.info(“Starting now to get something by Id”); 31 | //其它逻辑 32 | } 33 | } 34 | 35 | //Logger现在可以将事务 id 追加到每个条目, 以便同一请求中的项将具有相同的值 36 | class logger{ 37 | info (message) 38 | {console.log(`${message} ${session.get('transactionId')}`);} 39 | } 40 | ``` 41 | -------------------------------------------------------------------------------- /sections/production/assigntransactionid.japanese.md: -------------------------------------------------------------------------------- 1 | # 各ログ文に 'TransactionId' を割り当てる 2 | 3 |

4 | 5 | ### 一段落説明 6 | 7 | 典型的なログは、すべてのコンポーネントとリクエストからのエントリーの倉庫です。不審なラインやエラーが検出されると、同じ特定のフローに属する他のラインをマッチさせるのが面倒になります(例えば、ユーザの ”John” が何かを買おうとしたなど)。これは、リクエスト/トランザクションが複数のコンピュータにまたがる可能性がある場合、マイクロサービスの環境ではさらに重要で困難になります。これに対処するには、同じリクエストからのすべてのエントリに一意のトランザクション識別子の値を割り当てることで、1つの行を検出するときに、 ID をコピーして、類似のトランザクション ID を持つすべての行を検索できるようにします。しかし、1つのスレッドがすべてのリクエストを処理するために使用されるので、これを実現するためには Node では簡単ではありません - リクエストレベルでデータをグループ化できるライブラリを使用することを考えてください – 次のスライドのコード例を参照してください。他のマイクロサービスを呼び出す際には、同じコンテキストを保つために、”x-transaction-id” のような HTTP ヘッダを使ってトランザクション ID を渡してください。 8 | 9 |

10 | 11 | ### コード例: 典型的な Express の設定 12 | 13 | ```javascript 14 | // 新しいリクエストを受信したときに、新しい独立したコンテキストを開始し、トランザクション ID を設定します。次の例は、npm ライブラリ continuation-local-storage を使用してリクエストを分離しています。 15 | 16 | const { createNamespace } = require('continuation-local-storage'); 17 | const session = createNamespace('my session'); 18 | 19 | router.get('/:id', (req, res, next) => { 20 | session.set('transactionId', 'some unique GUID'); 21 | someService.getById(req.params.id); 22 | logger.info('Starting now to get something by id'); 23 | }); 24 | 25 | // これで、他のサービスやコンポーネントは、コンテクスト、リクエストごと、データごとにアクセスできるようになりました。 26 | class someService { 27 | getById(id) { 28 | logger.info('Starting to get something by id'); 29 | // other logic comes here 30 | } 31 | } 32 | 33 | // ロガーは、同じリクエストからのエントリが同じ値を持つように、各エントリにトランザクション ID を追加することができるようになりました。 34 | class logger { 35 | info (message) { 36 | console.log(`${message} ${session.get('transactionId')}`); 37 | } 38 | } 39 | ``` 40 | -------------------------------------------------------------------------------- /sections/production/bestateless.chinese.md: -------------------------------------------------------------------------------- 1 | # 保存无状态,几乎每天停掉服务器 2 | 3 |

4 | 5 | 6 | ### 一段解释 7 | 8 | 你曾经有没有遇到一类严重的线上问题,比如一个服务器丢失了一些配置或数据?这可能是由于对于不属于部署部分的本地资源的一些不必要的依赖。许多成功的产品对待服务器就像凤凰鸟–它周期性地死亡和重生不带来任何损伤。换句话说,服务器只是一个硬件,执行你的代码一段时间后,可以更换。 9 | 这个方法: 10 | - 允许动态添加和删除服务器,无任何负面影响; 11 | - 简化了维护,因为它使我们不必费精力对每个服务器状态进行评估。 12 | 13 |

14 | 15 | 16 | ### 代码示例: 反模式 17 | 18 | ```javascript 19 | //典型错误1: 保存上传文件在本地服务器上 20 | var multer = require('multer') // 处理multipart上传的express中间件 21 | var upload = multer({ dest: 'uploads/' }) 22 | 23 | app.post('/photos/upload', upload.array('photos', 12), function (req, res, next) {}) 24 | 25 | //典型错误2: 在本地文件或者内存中,保存授权会话(密码) 26 | var FileStore = require('session-file-store')(session); 27 | app.use(session({ 28 | store: new FileStore(options), 29 | secret: 'keyboard cat' 30 | })); 31 | 32 | //典型错误3: 在全局对象中保存信息 33 | Global.someCacheLike.result = {somedata} 34 | ``` 35 | 36 |

37 | 38 | ### 其他博客作者说什么 39 | 摘自博客 [Martin Fowler](https://martinfowler.com/bliki/PhoenixServer.html): 40 | > ...某天,我有了启动一个对操作的认证服务的幻想。认证评估将由我和一位同事出现在企业数据中心,并通过一个棒球棒,一个电锯和一把水枪设置关键生产服务器。评估将基于操作团队需要多长时间才能重新运行所有应用程序。这可能是一个愚蠢的幻想,但有一个真正的智慧在这里。而你应该放弃棒球棒,去定期的几乎烧毁你的服务器,这是一个好的做法。服务器应该像凤凰,经常从灰烬中升起... 41 | 42 |

43 | -------------------------------------------------------------------------------- /sections/production/bestateless.japanese.md: -------------------------------------------------------------------------------- 1 | # ステートレスのままで、ほぼ毎日サーバーを停止させる 2 | 3 |

4 | 5 | ### 一段落説明 6 | 7 | 1台のサーバーに設定やデータの一部が欠落しているという深刻な運用上の問題に遭遇したことはありませんか? これはおそらく、デプロイメントの一部ではないローカルアセットへの不必要な依存が原因であると思われます。多くの成功しているプロダクトが不死鳥のようにサーバーを扱います – それは何のダメージも受けずに死んで定期的に生まれ変わります。言い換えれば、サーバーとは、コードをしばらくの間実行して、その後に入れ替わるハードウェアの一部に過ぎません。 8 | このアプローチは、 9 | 10 | - サーバを動的に追加したり削除したりすることで、副作用のないスケーリングを可能にします。 11 | - 各サーバの状態を評価することから解放されるので、メンテナンスが簡単になります。 12 | 13 |

14 | 15 | ### コード例: アンチパターン 16 | 17 | ```javascript 18 | // 典型的な間違い 1: アップロードファイルのローカル保存 19 | const multer = require('multer'); // マルチパートアップロード処理用高速ミドルウェア 20 | const upload = multer({ dest: 'uploads/' }); 21 | 22 | app.post('/photos/upload', upload.array('photos', 12), (req, res, next) => {}); 23 | 24 | // 典型的な間違い 2: 認証セッション(パスポート)をローカルファイルまたはメモリに保存する 25 | const FileStore = require('session-file-store')(session); 26 | app.use(session({ 27 | store: new FileStore(options), 28 | secret: 'keyboard cat' 29 | })); 30 | 31 | // 典型的な間違い 3: グローバルオブジェクトの情報を格納 32 | Global.someCacheLike.result = { somedata }; 33 | ``` 34 | 35 |

36 | 37 | ### 他のブロガーが言っていること 38 | 39 | ブログ [Martin Fowler](https://martinfowler.com/bliki/PhoenixServer.html) より: 40 | > ...ある日、私は運用のための認証サービスを始めたいという妄想を抱いた。認定審査は、同僚と私が会社のデータセンターに出向き、野球のバット、チェーンソー、水鉄砲を持って、重要な本番用サーバーを見て回るというものでした。評価は、運用チームがすべてのアプリケーションを再稼働させるまでにどれくらいの時間がかかるかに基づいて行われます。くだらない妄想かもしれませんが、ここには名言のヒントがあります。野球のバットは見送るべきですが、定期的にサーバーを仮想的に焼き尽くすのは良いアイデアです。サーバーは不死鳥のように灰の中から定期的に立ち上がるべきです... 41 | 42 |

43 | -------------------------------------------------------------------------------- /sections/production/createmaintenanceendpoint.chinese.md: -------------------------------------------------------------------------------- 1 | # 创建维护端点 2 | 3 |

4 | 5 | 6 | ### 一段解释 7 | 8 | 维护端点是一个简单的安全的HTTP API, 它是应用程序代码的一部分, 它的用途是让ops/生产团队用来监视和公开维护功能。例如, 它可以返回进程的head dump (内存快照), 报告是否存在内存泄漏, 甚至允许直接执行 REPL 命令。在常规的 devops 工具 (监视产品、日志等) 无法收集特定类型的信息或您选择不购买/安装此类工具时, 需要使用此端点。黄金法则是使用专业的和外部的工具来监控和维护生产环境, 它们通常更加健壮和准确的。这就意味着, 一般的工具可能无法提取特定于node或应用程序的信息 – 例如, 如果您希望在 GC 完成一个周期时生成内存快照 – 很少有 npm 库会很乐意为您执行这个, 但流行的监控工具很可能会错过这个功能。 9 | 10 |

11 | 12 | 13 | ### 代码示例: 使用代码生产head dump 14 | 15 | ```javascript 16 | var heapdump = require('heapdump'); 17 | 18 | router.get('/ops/headump', (req, res, next) => { 19 | logger.info(`About to generate headump`); 20 | heapdump.writeSnapshot(function (err, filename) { 21 | console.log('headump file is ready to be sent to the caller', filename); 22 | fs.readFile(filename, "utf-8", function (err, data) { 23 | res.end(data); 24 | }); 25 | }); 26 | }); 27 | ``` 28 | 29 |

30 | 31 | ### 推荐资源 32 | 33 | [Getting your Node.js app production ready (Slides)](http://naugtur.pl/pres3/node2prod) 34 | 35 | ▶ [Getting your Node.js app production ready (Video)](https://www.youtube.com/watch?v=lUsNne-_VIk) 36 | 37 | ![Getting your Node.js app production ready](/assets/images/createmaintenanceendpoint1.png "Getting your Node.js app production ready") 38 | -------------------------------------------------------------------------------- /sections/production/createmaintenanceendpoint.japanese.md: -------------------------------------------------------------------------------- 1 | # メンテナンスエンドポイントの作成 2 | 3 |

4 | 5 | ### 一段落説明 6 | 7 | メンテナンスエンドポイントは、アプリのコードの一部であり、その目的は、ops/プロダクションチームがメンテナンス機能を監視し、公開するために使用する高度に安全な HTTP API です。 例えば、プロセスのヒープダンプ(メモリスナップショット)を返したり、メモリリークがあるかどうかを報告したり、REPL コマンドを直接実行したりすることができます。このエンドポイントは、従来の DevOps ツール(監視製品、ログなど)では特定の情報を収集できない場合や、そのようなツールを購入/インストールしないことを選択した場合に必要となります。黄金律は、生産の監視と維持のために専門的な外部ツールを使用することですが、これらは通常、より堅牢で正確です。とはいえ、一般的なツールでは、Node やアプリに固有の情報を抽出できない場合もあるでしょう。– 例えば、GC がサイクルを完了した瞬間にメモリスナップショットを生成したい場合は、以下のようになります – いくつかの npm ライブラリは喜んでこの機能を実行してくれますが、一般的なモニタリングツールはこの機能を見逃してしまう可能性があります。DDOS 攻撃の標的になる可能性があるため、このエンドポイントを非公開にし、管理者のみがアクセスできるようにしておくことが重要です。 8 | 9 |

10 | 11 | ### コード例: コードによるヒープダンプの生成 12 | 13 | ```javascript 14 | const heapdump = require('heapdump'); 15 | 16 | // リクエストが許可されているかどうかを確認する 17 | function isAuthorized(req) { 18 | // ... 19 | } 20 | 21 | router.get('/ops/heapdump', (req, res, next) => { 22 | if (!isAuthorized(req)) { 23 | return res.status(403).send('You are not authorized!'); 24 | } 25 | 26 | logger.info('About to generate heapdump'); 27 | 28 | heapdump.writeSnapshot((err, filename) => { 29 | console.log('heapdump file is ready to be sent to the caller', filename); 30 | fs.readFile(filename, 'utf-8', (err, data) => { 31 | res.end(data); 32 | }); 33 | }); 34 | }); 35 | ``` 36 | 37 |

38 | 39 | ### 推奨リソース 40 | 41 | [Node.js アプリの制作準備 (スライド)](http://naugtur.pl/pres3/node2prod) 42 | 43 | ▶ [Node.js アプリの制作準備 (ビデオ)](https://www.youtube.com/watch?v=lUsNne-_VIk) 44 | 45 | ![Node.js アプリの制作準備](/assets/images/createmaintenanceendpoint1.png "Node.js アプリの制作準備") 46 | -------------------------------------------------------------------------------- /sections/production/detectvulnerabilities.brazilian-portuguese.md: -------------------------------------------------------------------------------- 1 | # Utilize ferramentas que detectam vulnerabilidades automaticamente 2 | 3 |

4 | 5 | ### Explicação em um Parágrafo 6 | 7 | As aplicações modernas de Node possuem dezenas e algumas vezes centenas de dependências. Se alguma das dependências que você usa tiver uma vulnerabilidade de segurança conhecida, seu aplicativo também estará vulnerável. 8 | As ferramentas a seguir verificam automaticamente vulnerabilidades de segurança conhecidas em suas dependências: 9 | 10 | - [npm audit](https://docs.npmjs.com/cli/audit) - npm audit 11 | - [snyk](https://snyk.io/) - Encontre e corrija continuamente vulnerabilidades em suas dependências 12 | 13 |

14 | 15 | ### O que Outros Blogueiros dizem 16 | 17 | Do blog [StrongLoop](https://strongloop.com/strongblog/best-practices-for-express-in-production-part-one-security/): 18 | 19 | > ...Usá-lo para gerenciar as dependências da sua aplicação é poderoso e conveniente. Mas os pacotes que você usa podem conter vulnerabilidades críticas de segurança que também podem afetar sua aplicação. A segurança da sua aplicação é tão forte quanto o "elo mais fraco" em suas dependências. Felizmente, existem duas ferramentas úteis que você pode usar para garantir os pacotes de terceiros que você usa: nsp e requireSafe. Estas duas ferramentas fazem basicamente a mesma coisa, então usar ambos pode ser um exagero, mas “melhor prevenir do que remediar” são palavras para se viver quando se trata de segurança ... 20 | -------------------------------------------------------------------------------- /sections/production/detectvulnerabilities.chinese.md: -------------------------------------------------------------------------------- 1 | # 使用工具自动检测有漏洞的依赖项 2 | 3 |

4 | 5 | ### 一段解释 6 | 7 | 现代node应用有数十个, 有时是数以百计的依赖。如果您使用的任何依赖项存在已知的安全漏洞, 您的应用也很容易受到攻击。 8 | 下列工具自动检查依赖项中的已知安全漏洞: 9 | [npm audit](https://docs.npmjs.com/cli/audit) - Node 安全工程 10 | [snyk](https://snyk.io/) - 持续查找和修复依赖中的漏洞 11 | 12 |

13 | 14 | ### 其他博主说什么 15 | 摘自博客 [StrongLoop](https://strongloop.com/strongblog/best-practices-for-express-in-production-part-one-security/) : 16 | 17 | > ...被用来管理您应用的依赖是强大且方便的。但是, 您使用的依赖包可能存在严重的安全漏洞, 也会影响您的应用。您的应用的安全性仅仅与您的依赖组件中的 "最薄弱的一环" 一样严重。幸运的是, 您可以使用两种有用的工具来确保您使用的第三方库: ** 和 requireSafe。这两种工具在很大程度上都是一样的, 所以使用两种方法都可能过于夸张, 但 "安全比抱歉" 更安全... 18 | -------------------------------------------------------------------------------- /sections/production/detectvulnerabilities.japanese.md: -------------------------------------------------------------------------------- 1 | # 脆弱な依存関係を自動的に検出するツールを使用する 2 | 3 |

4 | 5 | ### 一段落説明 6 | 7 | 最近の Node アプリケーションは、数十、時には数百の依存関係を持っています。使用している依存関係のいずれかに既知のセキュリティ脆弱性がある場合、あなたのアプリも同様に脆弱です。 8 | 以下のツールは、依存関係にある既知のセキュリティ脆弱性を自動的にチェックします。: 9 | 10 | - [npm audit](https://docs.npmjs.com/cli/audit) - npm 監査 11 | - [snyk](https://snyk.io/) - 依存関係にある脆弱性を継続的に発見し、修正する 12 | 13 |

14 | 15 | ### 他のブロガーが言っていること 16 | 17 | ブログ [StrongLoop](https://strongloop.com/strongblog/best-practices-for-express-in-production-part-one-security/) より: 18 | 19 | > ...アプリケーションの依存関係を管理するために使用することは、強力で便利です。しかし、使用しているパッケージには重要なセキュリティ上の脆弱性が含まれている可能性があり、アプリケーションにも影響を与える可能性があります。アプリのセキュリティは、依存関係の「最も弱いリンク」と同じくらい強力です。幸いなことに、使用するサードパーティ製パッケージのセキュリティを確保するために使用できる 2 つの便利なツールがあります: nsp と requireSafe です。この2つのツールは大体同じことをするので、両方を使うのはやりすぎかもしれませんが、セキュリティに関しては「後悔するよりも安全な方がいい」という言葉が生きてくるでしょう。... 20 | -------------------------------------------------------------------------------- /sections/production/detectvulnerabilities.korean.md: -------------------------------------------------------------------------------- 1 | # Use tools that automatically detect vulnerable dependencies 2 | 3 |

4 | 5 | ### One Paragraph Explainer 6 | 7 | Modern Node applications have tens and sometimes hundreds of dependencies. If any of the dependencies 8 | you use has a known security vulnerability your app is vulnerable as well. 9 | The following tools automatically check for known security vulnerabilities in your dependencies: 10 | 11 | - [npm audit](https://docs.npmjs.com/cli/audit) - npm audit 12 | - [snyk](https://snyk.io/) - Continuously find & fix vulnerabilities in your dependencies 13 | 14 |

15 | 16 | ### What Other Bloggers Say 17 | 18 | From the [StrongLoop](https://strongloop.com/strongblog/best-practices-for-express-in-production-part-one-security/) blog: 19 | 20 | > ...Using to manage your application’s dependencies is powerful and convenient. But the packages that you use may contain critical security vulnerabilities that could also affect your application. The security of your app is only as strong as the “weakest link” in your dependencies. Fortunately, there are two helpful tools you can use to ensure the third-party packages you use: nsp and requireSafe. These two tools do largely the same thing, so using both might be overkill, but “better safe than sorry” are words to live by when it comes to security... 21 | -------------------------------------------------------------------------------- /sections/production/detectvulnerabilities.md: -------------------------------------------------------------------------------- 1 | # Use tools that automatically detect vulnerable dependencies 2 | 3 |

4 | 5 | ### One Paragraph Explainer 6 | 7 | Modern Node applications have tens and sometimes hundreds of dependencies. If any of the dependencies 8 | you use has a known security vulnerability your app is vulnerable as well. 9 | The following tools automatically check for known security vulnerabilities in your dependencies: 10 | 11 | - [npm audit](https://docs.npmjs.com/cli/audit) - npm audit 12 | - [snyk](https://snyk.io/) - Continuously find & fix vulnerabilities in your dependencies 13 | 14 |

15 | 16 | ### What Other Bloggers Say 17 | 18 | From the [StrongLoop](https://strongloop.com/strongblog/best-practices-for-express-in-production-part-one-security/) blog: 19 | 20 | > ...Using to manage your application’s dependencies is powerful and convenient. But the packages that you use may contain critical security vulnerabilities that could also affect your application. The security of your app is only as strong as the “weakest link” in your dependencies. Fortunately, there are two helpful tools you can use to ensure the third-party packages you use: nsp and requireSafe. These two tools do largely the same thing, so using both might be overkill, but “better safe than sorry” are words to live by when it comes to security... 21 | -------------------------------------------------------------------------------- /sections/production/detectvulnerabilities.polish.md: -------------------------------------------------------------------------------- 1 | # Użyj narzędzi, które automatycznie wykrywają podatne na zagrożenia zależności 2 | 3 |

4 | 5 | ### Wyjaśnienie jednym akapitem 6 | 7 | Nowoczesne aplikacje Node mają dziesiątki, a czasem setki zależności. Jeśli którakolwiek z zależności, z której korzystasz 8 | ma znaną lukę w zabezpieczeniach, Twoja aplikacja też. 9 | Następujące narzędzia automatycznie sprawdzają znane luki bezpieczeństwa w twoich zależnościach: 10 | 11 | - [npm audit](https://docs.npmjs.com/cli/audit) - npm audit 12 | - [snyk](https://snyk.io/) - Ciągle znajduj i usuwaj luki w swoich zależnościach 13 | 14 |

15 | 16 | ### Co mówią inni blogerzy 17 | 18 | Z bloga [StrongLoop](https://strongloop.com/strongblog/best-practices-for-express-in-production-part-one-security/): 19 | 20 | > ...Using to manage your application’s dependencies is powerful and convenient. But the packages that you use may contain critical security vulnerabilities that could also affect your application. The security of your app is only as strong as the “weakest link” in your dependencies. Fortunately, there are two helpful tools you can use to ensure the third-party packages you use: nsp and requireSafe. These two tools do largely the same thing, so using both might be overkill, but “better safe than sorry” are words to live by when it comes to security... 21 | -------------------------------------------------------------------------------- /sections/production/detectvulnerabilities.russian.md: -------------------------------------------------------------------------------- 1 | # Используйте инструменты, которые автоматически обнаруживают уязвимые зависимости 2 | 3 |

4 | 5 | ### Объяснение в один абзац 6 | 7 | Современные Node-приложения имеют десятки, а иногда и сотни зависимостей. Если какая-либо из них в зависимостях 8 | у вас есть известная уязвимость в безопасности вашего приложения. 9 | Следующие инструменты автоматически проверяют наличие известных уязвимостей в ваших зависимостях: 10 | 11 | - [npm audit](https://docs.npmjs.com/cli/audit) - аудит npm 12 | - [snyk](https://snyk.io/) - постоянно находите и исправляйте уязвимости в ваших зависимостях 13 | 14 |

15 | 16 | ### Что говорят другие блоггеры 17 | 18 | Из блога [StrongLoop] (https://strongloop.com/strongblog/best-practices-for-express-in-production-part-one-security/): 19 | 20 | > ... Использование для управления зависимостями вашего приложения является мощным и удобным. Но используемые вами пакеты могут содержать критические уязвимости безопасности, которые также могут повлиять на ваше приложение. Безопасность вашего приложения так же сильна, как "самая слабая ссылка" в ваших зависимостях. К счастью, есть два полезных инструмента, которые вы можете использовать для обеспечения сторонних пакетов, которые вы используете: nsp и requireSafe. Эти два инструмента в основном делают одно и то же, поэтому использование обоих может оказаться излишним, но "лучше, чем потом сожалеть" - это слова, которые нужно соблюдать, когда речь заходит о безопасности ... 21 | -------------------------------------------------------------------------------- /sections/production/frontendout.chinese.md: -------------------------------------------------------------------------------- 1 | # 在node外处理您的前端资产 2 | 3 |

4 | 5 | 6 | ### 一段解释 7 | 8 | 在一个经典的 web 应用中,后端返回前端资源/图片给浏览器, 在node的世界,一个非常常见的方法是使用 Express 静态中间件, 以数据流的形式把静态文件返回到客户端。但是, node并不是一个典型的 web应用, 因为它使用单个线程,对于同时服务多个文件,未经过任何优化。相反, 考虑使用反向代理、云存储或 CDN (例如Nginx, AWS S3, Azure Blob 存储等), 对于这项任务, 它们做了很多优化,并获得更好的吞吐量。例如, 像 nginx 这样的专业中间件在文件系统和网卡之间的直接挂钩, 并使用多线程方法来减少多个请求之间的干预。 9 | 10 | 您的最佳解决方案可能是以下形式之一: 11 | 1. 反向代理 – 您的静态文件将位于您的node应用的旁边, 只有对静态文件文件夹的请求才会由位于您的node应用前面的代理 (如 nginx) 提供服务。使用这种方法, 您的node应用负责部署静态文件, 而不是为它们提供服务。你的前端的同事会喜欢这种方法, 因为它可以防止 cross-origin-requests 的前端请求。 12 | 2. 云存储 – 您的静态文件将不会是您的node应用内容的一部分, 他们将被上传到服务, 如 AWS S3, Azure BlobStorage, 或其他类似的服务, 这些服务为这个任务而生。使用这种方法, 您的node应用即不负责部署静态文件, 也不为它们服务, 因此, 在node和前端资源之间完全解耦, 这是由不同的团队处理。 13 | 14 |

15 | 16 | 17 | ### 代码示例: 对于静态文件,典型的nginx配置 18 | 19 | ``` 20 | # configure gzip compression 21 | gzip on; 22 | keepalive 64; 23 | 24 | # defining web server 25 | server { 26 | listen 80; 27 | listen 443 ssl; 28 | 29 | # handle static content 30 | location ~ ^/(images/|img/|javascript/|js/|css/|stylesheets/|flash/|media/|static/|robots.txt|humans.txt|favicon.ico) { 31 | root /usr/local/silly_face_society/node/public; 32 | access_log off; 33 | expires max; 34 | } 35 | ``` 36 | 37 |

38 | 39 | ### 其它博主说了什么 40 | 摘自博客 [StrongLoop](https://strongloop.com/strongblog/best-practices-for-express-in-production-part-two-performance-and-reliability/): 41 | 42 | >…开发模式下, 您可以使用 [res.sendFile()](http://expressjs.com/4x/api.html#res.sendFile) 服务静态文件. 但是不要在生产中这样做, 因为这个函数为了每个文件请求,必须从文件系统中读取, 因此它会遇到很大的延迟, 并影响应用程序的整体性能。请注意, res.sendFile() 没有用系统调用 sendFile 实现, 这将使它更高效。相反, 使用serve-static中间件 (或类似的东西), 在express应用中服务文件,这是优化了的。更佳的选择是使用反向代理来服务静态文件; 有关详细信息, 请参阅使用反向代理… 43 | 44 |

45 | -------------------------------------------------------------------------------- /sections/production/guardprocess.chinese.md: -------------------------------------------------------------------------------- 1 | # 保护和重启你的失败进程(用正确的工具) 2 | 3 |

4 | 5 | 6 | ### 一段解释 7 | 8 | 在基本级别,必须保护Node进程并在出现故障时重新启动。简单地说, 对于那些小应用和不使用容器的应用 – 像这样的工具 [PM2](https://www.npmjs.com/package/pm2-docker) 是完美的,因为它们带来简单性,重启能力以及与Node的丰富集成。其他具有强大Linux技能的人可能会使用systemd并将Node作为服务运行。对于使用Docker或任何容器技术的应用程序来说,事情会变得更加有趣,因为集群管理和协调工具(比如[AWS ECS](http://docs.aws.amazon.com/AmazonECS/latest/developerguide/Welcome.html),[Kubernetes](https://kubernetes.io/)等)会完成部署,监视和保持容器健康的功能。拥有所有丰富的集群管理功能(包括容器重启),为什么还要与其他工具(如PM2)混为一谈?这里并没有可靠的答案。将PM2保留在容器(主要是其容器特定版本[pm2-docker](https://www.npmjs.com/package/pm2-docker))中作为第一个守护层是有充分的理由的 - 在主机容器要求正常重启时,重新启动更快,并提供特定于node的功能比如向代码发送信号。其他选择可能会避免不必要的层。总而言之,没有一个解决方案适合所有人,但了解这些选择是最重要的。 9 | 10 |

11 | 12 | 13 | ### 其它博主说了什么 14 | 15 | * 来自[Express 生成最佳实践](https://expressjs.com/en/advanced/best-practice-performance.html): 16 | > ... 在开发中,您只需从命令行使用node.js或类似的东西启动您的应用程序。**但是在生产中这样做是一种灾难。 如果应用程序崩溃,它将掉线**,直到您重新启动它。要确保应用程序在崩溃时重新启动,请使用进程管理器。流程管理器是便于部署的应用程序的“容器”,提供高可用性,并使您能够在运行时管理应用程序。 17 | 18 | * 摘自 the Medium blog post [了解节点集群](https://medium.com/@CodeAndBiscuits/understanding-nodejs-clustering-in-docker-land-64ce2306afef#.cssigr5z3): 19 | > ...了解Docker-Land中的NodeJS集群“Docker容器”是流线型的轻量级虚拟环境,旨在将流程简化为最低限度。管理和协调自己资源的流程不再有价值。**相反,像Kubernetes,Mesos和Cattle这样的管理层已经普及了这些资源应该在整个基础设施范围进行管理的概念**。CPU和内存资源由“调度器”分配,网络资源由堆栈提供的负载均衡器管理。 20 | -------------------------------------------------------------------------------- /sections/production/installpackageswithnpmci.japanese.md: -------------------------------------------------------------------------------- 1 | # 本番環境に npm ci を使ってパッケージをインストールする 2 | 3 |

4 | 5 | ### 一段落説明 6 | 7 | [**依存関係をロックする**](/sections/production/lockdependencies.japanese.md) に従って依存関係をロックしましたが、本番環境で使用されているパッケージのバージョンが正確であることを確認する必要があります。 8 | 9 | パッケージのインストールに `npm ci` を使うと、まさにそれ以上のことができます。 10 | * `package.json` と `package-lock.json` が一致していない (一致しているはずの) 場合や、ロックファイルがない場合は失敗します。 11 | * もし `node_modules` フォルダが存在する場合は、インストールする前に自動的に削除される 12 | * より速くなります! [リリースブログ記事](https://blog.npmjs.org/post/171556855892/introducing-npm-ci-for-faster-more-reliable) によると、2倍近く速くなっています。 13 | 14 | ### これはどんな時に役立つのでしょうか? 15 | CI 環境や QA が、後に本番環境に送るものと全く同じパッケージバージョンでソフトウェアをテストすることが保証されています。 16 | また、何らかの理由で cli コマンドではなく、直接 package.json を編集して手動で package.json を変更した場合、package.json と package-lock.json の間にギャップが生じてエラーが発生します。 17 | 18 | ### npm が言っていること 19 | 20 | [npm ci ドキュメント](https://docs.npmjs.com/cli/ci.html) より 21 | > このコマンドは npm-install と似ていますが、テストプラットフォームや継続的インテグレーション、デプロイメントなどの自動化された環境や、依存関係をクリーンインストールしていることを確認したい状況で使用することを目的としています。 22 | 23 | [ `ci` コマンドのリリースを発表しているブログポスト](https://blog.npmjs.org/post/171556855892/introducing-npm-ci-for-faster-more-reliable) 24 | > このコマンドは、継続的インテグレーション/継続的デプロイメントプロセスのためのビルドのパフォーマンスと信頼性を大幅に改善し、ワークフローで CI/CD を使用している開発者に一貫性のある高速な体験を提供します。 25 | 26 | [npmjs: dependencies と devDepencies](https://docs.npmjs.com/specifying-dependencies-and-devdependencies-in-a-package-json-file) 27 | > "dependencies": 本番環境のアプリケーションに必要なパッケージ 28 | > "devDependencies": ローカルでの開発やテストにのみ必要なパッケージ 29 | 30 |

31 | -------------------------------------------------------------------------------- /sections/production/measurememory.chinese.md: -------------------------------------------------------------------------------- 1 | # 测量和防范内存使用情况 2 | 3 |

4 | 5 | 6 | ### 一段解释 7 | 8 | 在一个完美的开发过程中, Web开发人员不应该处理内存泄漏问题。 实际上,内存问题是一个必须了解的Node已知的问题。首先,内存使用必须不断监视.在开发和小型生产站点上,您可以使用Linux命令或NPM工具和库(如node-inspector和memwatch)来手动测量。 这个人工操作的主要缺点是它们需要一个人进行积极的监控 - 对于正规的生产站点来说,使用鲁棒性监控工具是非常重要的,例如(AWS CloudWatch,DataDog或任何类似的主动系统),当泄漏发生时提醒。 防止泄漏的开发指南也很少:避免将数据存储在全局级别,使用动态大小的流数据,使用let和const限制变量范围。 9 | 10 |

11 | 12 | ### 其他博客说了什么 13 | 14 | * 摘自博客 [Dyntrace](http://apmblog.dynatrace.com/): 15 | > ... ”正如我们所了解到的,在Node.js 中,JavaScript被V8编译为机器码。由此产生的机器码数据结构与原始表达没有多大关系,只能由V8管理. 这意味着我们不能主动分配或释放JavaScript中的内存. V8 使用了一个众所周知的垃圾收集机制来解决这个问题.” 16 | 17 | * 摘自博客 [Dyntrace](http://blog.argteam.com/coding/hardening-node-js-for-production-part-2-using-nginx-to-avoid-node-js-load): 18 | > ... “虽然这个例子导致了明显的结果,但这个过程总是一样的:用一些时间和相当数量的内存分配创建heap dumps,比较dumps,以找出正在增长的内存泄露。” 19 | 20 | * 摘自博客 [Dyntrace](http://blog.argteam.com/coding/hardening-node-js-for-production-part-2-using-nginx-to-avoid-node-js-load): 21 | > ... “故障, 在内存较少的系统上运行时必须限制内存,Node.js会尝试使用大约1.5GB的内存。这是预期的行为,垃圾收集是一个代价很高的操作。 22 | 解决方案是为Node.js进程添加一个额外的参数: 23 | node –max_old_space_size=400 server.js –production ” 24 | “为什么垃圾收集代价很高? V8 JavaScript 使用了 stop-the-world (STW)的垃圾回收机制。 事实上,这意味着程序在进行垃圾回收时停止执行。” -------------------------------------------------------------------------------- /sections/production/measurememory.japanese.md: -------------------------------------------------------------------------------- 1 | # メモリ使用量を測定してガードする 2 | 3 |

4 | 5 | ### 一段落説明 6 | 7 | 完璧な世界では、ウェブ開発者はメモリリークに対処すべきではありません。実際には、メモリの問題は既知の Node の問題であり、気をつけなければなりません。何よりも、メモリ使用量を常に監視する必要があります。開発現場や小規模なプロダクションサイトでは、Linux コマンドや node-inspector や memwatch のような npm ツールやライブラリを使って手動で測定することもあります。このマニュアル活動の最大の欠点は、人間が積極的に監視する必要があることです。– 深刻なプロダクションサイトでは、( AWS CloudWatch、DataDog、または同様のプロアクティブシステム)などの堅牢な監視ツールを使用して、リークが発生した場合に警告を出すことが絶対的に重要です。漏洩を防ぐための開発ガイドラインもいくつかあります: グローバルレベルでのデータの保存を避ける、動的なサイズのデータにはストリームを使用する、let や const を使用して変数のスコープを制限する。 8 | 9 |

10 | 11 | ### 他のブロガーが言っていること 12 | 13 | * ブログ [Dyntrace](http://apmblog.dynatrace.com/) より: 14 | > ... ”すでに学習したように、Node.js JavaScript は V8 でネイティブコードにコンパイルされています。結果として得られるネイティブなデータ構造は、元の表現とはあまり関係がなく、もっぱら V8 によって管理されています。つまり、JavaScript では能動的にメモリを割り当てたり、解放したりすることができません。V8 はこの問題に対処するために、ガベージコレクションと呼ばれるよく知られたメカニズムを使用しています。” 15 | 16 | * ブログ [Dyntrace](http://blog.argteam.com/coding/hardening-node-js-for-production-part-2-using-nginx-to-avoid-node-js-load) より: 17 | > ... “この例では明らかな結果が得られますが、プロセスは常に同じです。: 18 | ある程度の時間をかけてヒープダンプを作成し、その間にかなりの量のメモリ割り当てを行います。 19 | いくつかのダンプを比較して、何が成長しているかを確認します。” 20 | 21 | * ブログ [Dyntrace](http://blog.argteam.com/coding/hardening-node-js-for-production-part-2-using-nginx-to-avoid-node-js-load) より: 22 | > ... “デフォルトでは、Node.js は約1.5 GB のメモリを使用しようとしますが、メモリの少ないシステムで実行する場合は上限を設定する必要があります。ガベージコレクションは非常にコストのかかる操作なので、これは予想される動作です。 23 | これを解決するには、Node.js のプロセスに余分なパラメータを追加する必要がありました。: 24 | node –max_old_space_size=400 server.js –production ” 25 | “なぜガベージコレクションはコストがかかるのでしょうか?V8 JavaScript エンジンは、stop-the-world ガベージコレクタ機構を採用しています。これは実際には、ガベージコレクションの実行中にプログラムの実行を停止することを意味します。” 26 | -------------------------------------------------------------------------------- /sections/production/monitoring.chinese.md: -------------------------------------------------------------------------------- 1 | 2 | # 监控! 3 | 4 |

5 | 6 | ### 一段解释 7 | 8 | 基本来说,当在生产环境中发生意外时,监控意味着你能够很*容易*识别它们。比如,通过电子邮件或Slack获得通知。挑战在于选择既能满足你的需求又不会破坏防护的合适工具集。我建议, 首先定义一组核心的度量标准, 这些指标必须被监视, 以确保健康状态 – CPU, 服务器RAM, Node进程RAM(小于1.4GB),最后一分钟的错误数量,进程重启次数,平均响应时间。然后去看看你可能喜欢的一些高级功能,并添加到你的愿望清单。一些高级监控功能的例子:DB分析,跨服务测量(即测量业务事务),前端集成,将原始数据展示给自定义BI客户端,Slack 通知等等。 9 | 10 | 要实现高级功能需要冗长的设置或购买诸如Datadog,Newrelic之类的商业产品。不幸的是,实现基本功能也并不容易,因为一些测量标准是与硬件相关的(CPU),而其它则在node进程内(内部错误),因此所有简单的工具都需要一些额外的设置。例如,云供应商监控解决方案(例如[AWS CloudWatch](https://aws.amazon.com/cloudwatch/), [Google StackDriver](https://cloud.google.com/stackdriver/))能立即告诉您硬件度量标准,但不涉及内部应用程序行为。另一方面,基于日志的解决方案(如ElasticSearch)默认缺少硬件视图。解决方案是通过缺少的指标来增加您的选择,例如,一个流行的选择是将应用程序日志发送到[Elastic stack](https://www.elastic.co/products)并配置一些额外的代理(例如[Beat](https://www.elastic.co/products))来共享硬件相关信息以获得完整的展现。 11 | 12 |

13 | 14 | ### 监控示例:AWS cloudwatch默认仪表板。很难提取应用内指标 15 | 16 | ![AWS cloudwatch default dashboard. Hard to extract in-app metrics](/assets/images/monitoring1.png) 17 | 18 |

19 | 20 | ### 监控示例:StackDriver默认仪表板。很难提取应用内指标 21 | 22 | ![StackDriver default dashboard. Hard to extract in-app metrics](/assets/images/monitoring2.jpg) 23 | 24 |

25 | 26 | ### 监控示例:Grafana作为可视化原始数据的UI层 27 | 28 | 29 | ![Grafana as the UI layer that visualizes raw data](/assets/images/monitoring3.png) 30 | 31 |

32 | ### 其他博主说了什么 33 | 摘自博客 [Rising Stack](http://mubaloo.com/best-practices-deploying-node-js-applications/): 34 | 35 | > ...我们建议您为所有服务监听这些信号: 36 | > 错误率:因为错误是用户面对的,并立即会影响您的客户。 37 | > 响应时间:因为延迟会直接影响您的客户和业务。 38 | > 吞吐量:流量可帮助您了解增加的错误率和延迟的上下文。 39 | > 饱和度:饱和度告诉你你的服务有多“满”。如果CPU使用率是90%,您的系统可以处理更多的流量吗?... 40 | -------------------------------------------------------------------------------- /sections/production/productioncode.chinese.md: -------------------------------------------------------------------------------- 1 | # 代码生产环境的准备 2 | 3 |

4 | 5 | 6 | ### 一段解释 7 | 8 | 以下是一个开发技巧的列表,它极大地影响了产品的维护和稳定性: 9 | 10 | * 十二因素指南 — 熟悉[12因素](https://12factor.net/)指南 11 | * 无状态 — 在一个特定的web服务器上不保存本地数据(请参阅相关条目 - “Be Stateless”) 12 | * 高速缓存 — 大量使用缓存,但不会因为缓存不匹配而产生错误 13 | * 测试内存 — 测量内存的使用和泄漏,是作为开发流程的一部分,诸如“memwatch”之类的工具可以极大地促进这一任务 14 | * 命名函数 — 将匿名函数(例如,内联callbabk)的使用最小化,因为一个典型的内存分析器为每个方法名提供内存使用情况 15 | * 使用CI工具 — 在发送到生产前使用CI工具检测故障。例如,使用ESLint来检测引用错误和未定义的变量。使用–trace-sync-io来识别用了同步api的代码(而不是异步版本) 16 | * 明确的日志 — 包括在每个日志语句中希望用json格式记录上下文信息,以便于日志聚合工具,如Elastic可以在这些属性上搜索(请参阅相关条目 – “Increase visibility using smart logs”)。此外,还包括标识每个请求的事务id,并允许将描述相同事务的行关联起来(请参阅 — “Include Transaction-ID”) 17 | * 错误管理 — 错误处理是Node.js生产站点的致命弱点 – 许多Node进程由于小错误而崩溃,然而其他Node进程则会在错误的状态下存活,而不是崩溃。设置你的错误处理策略绝对是至关重要的, 在这里阅读我的(错误处理的最佳实践)(http://goldbergyoni.com/checklist-best-practices-of-node-js-error-handling/) -------------------------------------------------------------------------------- /sections/production/productioncode.japanese.md: -------------------------------------------------------------------------------- 1 | # コードを本番に即したものにする 2 | 3 |

4 | 5 | ### 一段落説明 6 | 7 | 以下は、プロダクションのメンテナンスと安定性に大きく影響する開発のヒントのリストです。: 8 | 9 | * 12要素ガイド – [12要素](https://12factor.net/)のガイドに慣れる 10 | * ステートレスであれ – 特定の Web サーバーにデータをローカルに保存しない (別箇条を参照してください – 「ステートレスであれ」) 11 | * キャッシュ – キャッシュを多用しているが、キャッシュの不一致で失敗することはない 12 | * テストメモリ – 開発フローの一部としてメモリ使用量やリークを測定し、「memwatch」などのツールがこのタスクを大幅に促進します。 13 | * 関数に名前をつける – 一般的なメモリプロファイラでは、メソッド名ごとにメモリ使用量が表示されるため、匿名関数(インラインコールバックなど)の使用を最小限に抑えます。 14 | * CI ツールを使用する – CI ツールを使って、本番に送る前に失敗を検出する。例えば、ESLint を使って参照エラーや未定義変数を検出します。同期 API を使用するコードを識別するために -trace-sync-io を使用します (非同期バージョンではなく)。 15 | * 賢くログを取る – Elastic のようなログアグリゲータツールがそれらのプロパティを検索できるように、各ログ文にコンテキスト情報を含めて、できれば JSON 形式で表示してください(別項「スマートログを使った可視性の向上」を参照)。また、各リクエストを識別するトランザクション ID を含め、同じトランザクションを記述する行を関連付けることができます(別項の「トランザクション ID を含める」を参照)。 16 | * エラー管理 – エラー処理は Node.js プロダクションサイトのアキレス腱です。 – 多くのノードプロセスは小さなエラーのためにクラッシュしていますが、他のプロセスはクラッシュせずに障害のある状態で生き残っています。エラー処理戦略を設定することは絶対に重要です。私の [エラー処理のベストプラクティス](http://goldbergyoni.com/checklist-best-practices-of-node-js-error-handling/) を読んでください。 17 | -------------------------------------------------------------------------------- /sections/production/setnodeenv.chinese.md: -------------------------------------------------------------------------------- 1 | # 配置环境变量 NODE_ENV = production 2 | 3 |

4 | 5 | 6 | ### 一段解释 7 | 8 | 进程的环境变量是一组键值对,可用于任何运行程序,通常用于配置。虽然可以使用其他任何变量,但Node鼓励使用一个名为NODE_ENV的变量来标记我们是否正在开发。这一决定允许组件在开发过程中能提供更好的诊断,例如禁用缓存或发出冗长的日志语句。任何现代部署工具 — Chef、Puppet、CloudFormation等 — 在部署时都支持设置环境变量。 9 | 10 |

11 | 12 | 13 | ### 代码实例:配置和读取NODE_ENV环境变量 14 | 15 | ```javascript 16 | //在启动node进程前,在bash中设置环境变量 17 | $ NODE_ENV=development 18 | $ node 19 | 20 | //使用代码读取环境变量 21 | If(process.env.NODE_ENV === “production”) 22 | useCaching = true; 23 | ``` 24 | 25 |

26 | 27 | 28 | ### 其他博主说了什么 29 | 摘自这篇博客[dynatrace](https://www.dynatrace.com/blog/the-drastic-effects-of-omitting-node_env-in-your-express-js-applications/): 30 | > ...在node.js中有一个约定, 它使用名为NODE_ENV的变量来设置当前工作模式。我们看到它实际上是读取NODE_ENV,如果它没有设置,则默认为“development”。我们清楚的看到,通过设置NODE_ENV为production,node.js可以处理请求的数量可以提高大约三分之二,而CPU的使用率会略有下降。 *让我强调一下:设置NODE_ENV为production可以让你的应用程序快3倍!* 31 | 32 | 33 | ![NODE_ENV=production](/assets/images/setnodeenv1.png "NODE_ENV=production") 34 | 35 | 36 |

37 | 38 | -------------------------------------------------------------------------------- /sections/production/setnodeenv.japanese.md: -------------------------------------------------------------------------------- 1 | # NODE_ENV = production を設定する 2 | 3 |

4 | 5 | ### 一段落説明 6 | 7 | プロセス環境変数は、実行中のプログラムで利用できるキーと値のペアのセットで、通常は設定の目的で利用できます。任意の変数を使うことができますが、Node は NODE_ENV と呼ばれる変数を使って、現在本番環境であるかどうかのフラグを立てる慣習を推奨しています。この決定により、コンポーネントは開発中にキャッシングを無効にしたり、冗長なログ文を出力したりするなど、より良い診断を提供することができます。Chef、Puppet、CloudFormation、その他の最新のデプロイツールは、デプロイ時に環境変数を設定することをサポートしています。 8 | 9 |

10 | 11 | ### コード例: 環境変数 NODE_ENV の設定と読み込み 12 | 13 | ```shell script 14 | // ノードプロセスを起動する前に bash で環境変数を設定する 15 | $ NODE_ENV=development 16 | $ node 17 | ``` 18 | 19 | ```javascript 20 | // コードを使って環境変数を読み込む 21 | if (process.env.NODE_ENV === 'production') 22 | useCaching = true; 23 | ``` 24 | 25 |

26 | 27 | ### 他のブロガーが言っていること 28 | 29 | ブログ [dynatrace](https://www.dynatrace.com/blog/the-drastic-effects-of-omitting-node_env-in-your-express-js-applications/) より: 30 | > ...Node.js では、現在のモードを設定するために node_env という変数を使用する慣習があります。実際には NODE_ENV を読み込んで、設定されていない場合は「development」にデフォルトで設定されていることがわかります。NODE_ENV を本番環境に設定することで、Node.js が処理できるリクエスト数が約3分の2に跳ね上がり、CPU の使用率はわずかに低下することが明らかになっています。*これだけは強調しておきます: NODE_ENV を本番環境に設定すると、アプリケーションが3倍速くなります!* 31 | 32 | ![NODE_ENV=production](/assets/images/setnodeenv1.png "NODE_ENV=production") 33 | 34 |

35 | -------------------------------------------------------------------------------- /sections/production/smartlogging.chinese.md: -------------------------------------------------------------------------------- 1 | # 使用智能日志使你的应用程序变得清晰 2 | 3 |

4 | 5 | 6 | ### 一段解释 7 | 8 | 无论如何,您要打印日志,而且需要一些可以在其中跟踪错误和核心指标的接口来展示生产环境信息(例如,每小时发生了多少错误,最慢的API节点是哪一个)为什么不在健壮的日志框架中进行一些适度的尝试呢? 要实现这一目标,需要在三个步骤上做出深思熟虑的决定: 9 | 10 | **1. 智能日志** – 在最基本的情况下,您需要使用像[Winston](https://github.com/winstonjs/winston), [Bunyan](https://github.com/trentm/node-bunyan)这样有信誉的日志库,在每个事务开始和结束时输出有意义的信息。还可以考虑将日志语句格式化为JSON,并提供所有上下文属性(如用户id、操作类型等)。这样运维团队就可以在这些字段上操作。在每个日志行中包含一个唯一的transaction ID,更多的信息查阅条款 “Write transaction-id to log”。最后要考虑的一点还包括一个代理,它记录系统资源,如内存和CPU,比如Elastic Beat。 11 | 12 | **2. 智能聚合** – 一旦您在服务器文件系统中有了全面的信息,就应该定期将这些信息推送到一个可以聚合、处理和可视化数据的系统中。例如,Elastic stack是一种流行的、自由的选择,它提供所有组件去聚合和产生可视化数据。许多商业产品提供了类似的功能,只是它们大大减少了安装时间,不需要主机托管。 13 | 14 | **3. 智能可视化** – 现在的信息是聚合和可搜索的, 一个可以满足仅仅方便地搜索日志的能力, 可以走得更远, 没有编码或花费太多的努力。我们现在可以显示一些重要的操作指标, 如错误率、平均一天CPU使用, 在过去一小时内有多少新用户选择, 以及任何其他有助于管理和改进我们应用程序的指标。 15 | 16 |

17 | 18 | 19 | ### 可视化示例: Kibana(Elastic stack的一部分)促进了对日志内容的高级搜索 20 | ![Kibana facilitates advanced searching on log content](/assets/images/smartlogging1.png "Kibana facilitates advanced searching on log content") 21 | 22 |

23 | 24 | ### 可视化示例: Kibana(Elastic stack的一部分)基于日志来可视化数据 25 | ![Kibana visualizes data based on logs](/assets/images/smartlogging2.jpg "Kibana visualizes data based on logs") 26 | 27 |

28 | 29 | ### 博客应用: Logger的需求 30 | 摘自博客 [Strong Loop](https://strongloop.com/strongblog/compare-node-js-logging-winston-bunyan/): 31 | 32 | > 让我们识别一些需求(对于一个日志记录器来说): 33 | > 1. 每条日志对应一个时间戳。这个很好解释 – 您应该能够判断每个日志条目出现的时间。 34 | > 2. 日志格式应该很容易被人和机器消化理解。 35 | > 3. 允许多个可配置的目标流。例如,您可能在一个文件中写入trace日志,但是当遇到错误时,将其写入相同的文件,然后写入错误日志文件并同时发送电子邮件... 36 |

37 | 38 | 39 | 40 |

41 | -------------------------------------------------------------------------------- /sections/production/utilizecpu.chinese.md: -------------------------------------------------------------------------------- 1 | # 利用所有的CPU内核 2 | 3 |

4 | 5 | 6 | ### 一段解释 7 | 8 | 这应该不会让人感到意外, 在其基本形式上,Node运行在单进程,单线程,单个CPU上。购买了一个强大的包含4个或8个CPU的硬件,只使用一个听起来是不可思议的,对吗?适合中型应用最快的解决方案是使用Node的Cluster模块,它在10行代码中为每个逻辑核心和路由请求产生一个进程,进程之间以round-robin的形式存在。更好的是使用PM2,它通过一个简单的接口和一个很酷的监视UI来给cluster模块裹上糖衣。虽然这个解决方案对传统应用程序很有效,但它可能无法满足需要顶级性能和健壮的devops流的应用。对于那些高级的用例,考虑使用自定义部署脚本复制NODE进程,并使用像nginx 9 | 这样的专门的工具进行负载均衡,或者使用像AWS ECS或Kubernetees这样的容器引擎,这些工具具有部署和复制进程的高级特性。 10 | 11 |

12 | 13 | 14 | ### 比较:使用Node的clustre vs nginx做负载均衡 15 | 16 | ![Balancing using Node’s cluster vs nginx](/assets/images/utilizecpucores1.png "Balancing using Node’s cluster vs nginx") 17 | 18 |

19 | 20 | ### 其他博主说什么 21 | * 摘自[Node.JS documentation](https://nodejs.org/api/cluster.html#cluster_how_it_works): 22 | > ... 理论上第二种方法, Node clusters,应该是性能最佳的。然而, 在实践中, 由于操作系统调度程序的反复无常, 分布往往非常不平衡。观察负载, 所有连接中,超过70%在两个进程中处理, 而总共有八个进程... 23 | 24 | * 摘自博客[StrongLoop](From the blog StrongLoop): 25 | > ...通过Node的cluster模块实现集群化。这使一个主进程能够产生工作进程,并在工作进程间分配进入的连接。然而,与其直接使用这个模块,更好的选择是使用其中的许多工具之一, 它为您自动处理它; 例如,node-pm或cluster-service... 26 | 27 | * 摘自the Medium post[node.js进程负载平衡性能:比较cluster moudlle、iptables和Nginx](https://medium.com/@fermads/node-js-process-load-balancing- iptabls -and- Nginx -6746aaf38272) 28 | > ... Node cluster易于实施和配置,不依赖于其他软件就可以在Node的领域内进行。请记住,你的主进程将会工作几乎和你的工作进程一样多,比较于其他的解决方案,少一点请求率... -------------------------------------------------------------------------------- /sections/projectstructre/breakintcomponents.chinese.md: -------------------------------------------------------------------------------- 1 | # 组件式构建你的解决方案 2 | 3 |

4 | 5 | 6 | ### 一段解释 7 | 8 | 对于中等规模的应用程序及以上,一个代码库是非常糟糕的 - 一个包含很多依赖的大型软件很难理解,往往导致代码混乱。即使是那些擅长解决复杂问题和 "模块化" 的聪明架构师 - 在设计上花费了很大的脑力, 每一个变化都需要仔细评估对其他依赖对象的影响。最终的解决方案是开发小型软件:将整个堆栈划分为独立的组件,这些组件不与其他组件共享文件,每个组件由很少的文件构成(例如API、服务、数据访问、测试等),因此很容易理解它。有些人可能称之为 "microservices" 架构 - 重要的是要理解 microservices 不是一个你必须遵循的规范,而是一套原则。您可以将许多原则引入到成熟的 microservices 体系结构中, 或者只采用少数几个。只要您保持软件的复杂性低, 两者都是好的。最起码应该做的是在组件之间创建一个基本边界, 为每个业务组件在项目根目录中分配一个文件夹, 并使其自包含-其他组件只能通过其公共接口或 API 使用其功能。这是保持您的组件简单的基础,在未来, 一旦您的应用程序增长,避免依赖性地狱,为全面的 microservices 架构铺平了道路. 9 | 10 |

11 | 12 | 13 | ### 博客引用: "伸缩需要对整个应用程序进行伸缩设计" 14 | 摘自博客 MartinFowler.com 15 | 16 | > 单个应用程序可以成功, 但越来越多的人对它们感到失望 - 尤其是随着更多的应用程序被部署到云中。更改周期被捆绑在一起 - 对应用程序的一小部分进行更改, 需要重建和部署整个整体。随着时间的推移, 通常很难保持一个良好的模块化结构, 这使得更改哪怕只会影响该模块中的一个模块变得更加困难。伸缩设计需要扩展整个应用程序, 而不是它的部分,这往往需要更多资源。 17 | 18 |

19 | 20 | ### 博客引用: "那么, 你的应用程序的架构声明了什么?" 21 | 摘自博客 [uncle-bob](https://8thlight.com/blog/uncle-bob/2011/09/30/Screaming-Architecture.html) 22 | 23 | > ...如果你正在寻找一个图书馆的建筑架构, 你可能会看到一个盛大的入口, 一个 check-in-out 的文员, 阅读区, 小会议室, 画廊, 画廊后面容纳了装载所有图书馆书籍的书架。建筑会声明: 图书馆.
24 | 那么, 应用程序的体系架构会声明什么呢? 当您查看顶级目录结构和最高级别包中的源文件时; 他们声明: 医疗保健系统, 或会计系统, 或库存管理系统? 或者他们声明: Rails, 或Spring/Hibernate, 或 ASP?. 25 | 26 | 27 |

28 | 29 | ### 推荐: 通过独立组件构建解决方案 30 | ![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/structurebycomponents.PNG "Structuring solution by components") 31 | 32 | 33 |

34 | 35 | ### 避免: 按技术角色对文件进行分组 36 | ![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/structurebyroles.PNG "Structuring solution by technical roles") 37 | -------------------------------------------------------------------------------- /sections/projectstructre/configguide.chinese.md: -------------------------------------------------------------------------------- 1 | # 使用环境感知,安全,分层的配置 2 | 3 |

4 | 5 | 6 | ### 一段解释 7 | 8 | 当我们处理配置参数时,常常会很慢并且很烦躁:(1)当需要注入100个keys(而不是只在配置文件中提交它们)时,使用进程环境变量设置所有的keys变得非常繁琐,但是当处理只有devops管理权限的文件时,不改变代码行为就不不会变。一个可靠的配置解决方案必须结合配置文件和进程变量覆盖。(2)枚举一个普通JSON的所有keys时,当目录变得非常庞杂的时候,查找修改条目困难。几乎没有配置库允许将配置存储在多个文件中,运行时将所有文件联合起来。分成几个部分的分层JSON文件能够克服这个问题。请参照下面示例。(3)不推荐存储像密码数据这样的敏感信息,但是又没有快速便捷的方法解决这个难题。一些配置库允许文件加密,其他库在Git提交时加密目录,或者不存储这些目录的真实值,在通过环境变量部署期间枚举真实值。(4)一些高级配置场景需要通过命令行(vargs)注入配置值,或者像Redis一样通过集中缓存同步配置信息,所以不同的服务器不会保存不同的数据。 9 | 10 | 一些配置库可以免费提供这些功能的大部分功能,请查看NPM库([nconf](https://www.npmjs.com/package/nconf), [config](https://www.npmjs.com/package/config) 和 [convict](https://www.npmjs.com/package/convict))这些库可以满足这些要求中的许多要求。 11 | 12 |

13 | 14 | ### 代码示例 – 分层配置有助于查找条目和维护庞大的配置文件 15 | 16 | ```javascript 17 | { 18 | // Customer module configs 19 | "Customer": { 20 | "dbConfig": { 21 | "host": "localhost", 22 | "port": 5984, 23 | "dbName": "customers" 24 | }, 25 | "credit": { 26 | "initialLimit": 100, 27 | // Set low for development 28 | "initialDays": 1 29 | } 30 | } 31 | } 32 | ``` 33 | 34 |

35 | -------------------------------------------------------------------------------- /sections/projectstructre/configguide.japanese.md: -------------------------------------------------------------------------------- 1 | # 環境を意識したセキュアで階層的な設定を使用する 2 | 3 |

4 | 5 | ### 一段落説明 6 | 7 | 設定データを扱う場合、多くのことはただ単に迷惑であったり、遅くしたりするだけです。 8 | 9 | 1. 100個のキーを注入する必要がある場合(設定ファイルでコミットするだけではなく)、プロセス環境変数を使ってすべてのキーを設定するのは面倒になります。しかし、ファイルのみで作業する場合は、devops 管理者はコードを変更しないと挙動を変更することができません。信頼性の高い設定に関する解決策は、両方の設定ファイルとプロセス変数からのオーバーライドを組み合わせる必要があります。 10 | 11 | 2. フラットな JSON ですべてのキーを指定する場合、リストが大きくなったときにエントリを見つけて修正するのはイライラします。セクションにグループ化された階層的な JSON ファイルは、この問題を克服することができます + いくつかの設定ライブラリでは、複数のファイルに設定を保存し、実行時にすべてを結合するように注意を払うことができます。以下の例を見てください。 12 | 13 | 3. DB パスワードのような機密情報を保存することは明らかに推奨されていませんが、この課題に対する迅速で便利なソリューションは存在しません。設定ライブラリによっては、ファイルの暗号化を許可しているものもあれば、Git コミット時にそれらのエントリを暗号化しているものもありますし、単にそれらのエントリの実値を保存せず、デプロイ時に環境変数で実際の値を指定しているだけのものもあります。 14 | 15 | 4. いくつかの高度な設定シナリオでは、コマンドライン ( vargs ) から設定値を注入したり、Redis のような集中化されたキャッシュを介して設定情報を同期させたりして、複数のサーバが同じ設定データを使用するように要求しています。 16 | 17 | 5. アプリケーションは、起動時に必要な環境変数が存在しない場合には、可能な限り迅速に失敗し、即座にフィードバックを提供しなければなりません。これは、設定を検証するために [convict](https://www.npmjs.com/package/convict) を使用することで実現できます。 18 | 19 | 設定ライブラリの中には、これらの機能のほとんどを無料で提供できるものもありますので、[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) のような、これらの要件を多く満たしている npm ライブラリを見てみてください。 20 | 21 |

22 | 23 | ### コード例 – 階層化された設定は、エントリの検索や巨大な設定ファイルの管理に役立ちます 24 | 25 | ```json5 26 | { 27 | // Customer module configs 28 | "Customer": { 29 | "dbConfig": { 30 | "host": "localhost", 31 | "port": 5984, 32 | "dbName": "customers" 33 | }, 34 | "credit": { 35 | "initialLimit": 100, 36 | // Set low for development 37 | "initialDays": 1 38 | } 39 | } 40 | } 41 | ``` 42 | 43 |

44 | -------------------------------------------------------------------------------- /sections/projectstructre/createlayers.basque.md: -------------------------------------------------------------------------------- 1 | # Antolatu zure aplikazioa geruzatan, mantendu Express bere esparruaren barruan 2 | 3 |

4 | 5 | ### Osagaien kodea geruzatan banandu: web, zerbitzuak, eta Datuen Sarbide Geruza (DSG) (Ingelesez Data Access Layer, DAL) 6 | 7 | ![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/structurebycomponents.PNG "Osagaien kodea geruzatan banandu") 8 | 9 |

10 | 11 | ### Minutu bateko azalpena: geruzak nahastearen eragozpena 12 | 13 | ![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/keepexpressinweb.gif "Geruzak nahastearen eragozpena") 14 | -------------------------------------------------------------------------------- /sections/projectstructre/createlayers.brazilian-portuguese.md: -------------------------------------------------------------------------------- 1 | # Coloque seus Componentes em Camadas, mantenha o Express dentro de seus limites 2 | 3 |

4 | 5 | ### Separe o código do componente em camadas: web, serviços e DAL 6 | 7 | ![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/structurebycomponents.PNG "Separe o código do componente em camadas") 8 | 9 |

10 | 11 | ### Explicação em 1 minuto: A desvantagem de misturar camadas 12 | 13 | ![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/keepexpressinweb.gif "A desvantagem de misturar camadas") 14 | -------------------------------------------------------------------------------- /sections/projectstructre/createlayers.chinese.md: -------------------------------------------------------------------------------- 1 | # 应用程序分层,保持Express在其边界内 2 | 3 |

4 | 5 | ### 将组件代码分成web, services, DAL层 6 | ![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/structurebycomponents.PNG "Separate component code into layers") 7 | 8 |

9 | 10 | ### 1分钟说明:混合层的缺点 11 | ![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/keepexpressinweb.gif "The downside of mixing layers") 12 | -------------------------------------------------------------------------------- /sections/projectstructre/createlayers.japanese.md: -------------------------------------------------------------------------------- 1 | # アプリケーションを階層化し、 Express を境界内に収める 2 | 3 |

4 | 5 | ### コンポーネントコードをウェブ、サービス、DAL のレイヤーに分ける 6 | 7 | ![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/structurebycomponents.PNG "コンポーネントコードを階層化する") 8 | 9 |

10 | 11 | ### 1分解説: レイヤーを混ぜることのデメリット 12 | 13 | ![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/keepexpressinweb.gif "レイヤーを混ぜることのデメリット") 14 | -------------------------------------------------------------------------------- /sections/projectstructre/createlayers.korean.md: -------------------------------------------------------------------------------- 1 | # 컴포넌트를 계층화(layer)하고, Express를 그 경계 안에 둬라 2 | 3 |

4 | 5 | ### 컴포넌트 코드를 웹, 서비스, 데이터 접근 언어(DAL) 계층으로 나누어라 6 | 7 | ![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/structurebycomponents.PNG "Separate component code into layers") 8 | 9 |

10 | 11 | ### 1분 설명: 계층을 섞으면 불리한 점 12 | 13 | ![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/keepexpressinweb.gif "The downside of mixing layers") 14 | -------------------------------------------------------------------------------- /sections/projectstructre/createlayers.md: -------------------------------------------------------------------------------- 1 | # Layer your app, keep Express within its boundaries 2 | 3 |

4 | 5 | ### Separate component code into layers: web, services, and Data Access Layer (DAL) 6 | 7 | ![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/structurebycomponents.PNG "Separate component code into layers") 8 | 9 |

10 | 11 | ### 1 min explainer: The downside of mixing layers 12 | 13 | ![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/keepexpressinweb.gif "The downside of mixing layers") 14 | -------------------------------------------------------------------------------- /sections/projectstructre/createlayers.polish.md: -------------------------------------------------------------------------------- 1 | # Nakładaj warstwę na aplikację i trzymaj Express w jej granicach 2 | 3 |

4 | 5 | ### Rozdziel kod komponentu na warstwy: sieć, usługi i DAL 6 | 7 | ![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/structurebycomponents.PNG "Separate component code into layers") 8 | 9 |

10 | 11 | ### 1 minuta wyjaśniania: Minusem mieszanie warstw 12 | 13 | ![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/keepexpressinweb.gif "The downside of mixing layers") 14 | -------------------------------------------------------------------------------- /sections/projectstructre/createlayers.russian.md: -------------------------------------------------------------------------------- 1 | # Выделяйте ваши компоненты в отдельный слой, держите Express в его границах 2 | 3 |

4 | 5 | ### Разделить код компонента на слои: веб, сервисы и DAL 6 | 7 | ![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/structurebycomponents.PNG "Separate component code into layers") 8 | 9 |

10 | 11 | ### 1 минутное объяснение: обратная сторона смешения слоев 12 | 13 | ![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/keepexpressinweb.gif "The downside of mixing layers") 14 | -------------------------------------------------------------------------------- /sections/projectstructre/separateexpress.chinese.md: -------------------------------------------------------------------------------- 1 | # Express的 '应用' 和 '服务' 分离 2 | 3 |

4 | 5 | 6 | ### 一段解释 7 | 8 | 最新的Express生成器有一个值得保留的伟大实践--API声明与网络相关配置(端口、协议等)是分开的。这样就可以在不执行网络调用的情况下对API进行在线测试,它所带来的好处是:快速执行测试操作和获取代码覆盖率。它还允许在灵活多样的网络条件下部署相同的API。额外好处:更好的关注点分离和更清晰的代码结构。 9 | 10 |

11 | 12 | ### 代码示例:API声明应该在 app.js 文件里面 13 | 14 | ```javascript 15 | var app = express(); 16 | app.use(bodyParser.json()); 17 | app.use("/api/events", events.API); 18 | app.use("/api/forms", forms); 19 | 20 | ``` 21 | 22 |

23 | 24 | ### 代码示例: 服务器网络声明,应该在 /bin/www 文件里面 25 | 26 | ```javascript 27 | var app = require('../app'); 28 | var http = require('http'); 29 | 30 | /** 31 | * Get port from environment and store in Express. 32 | */ 33 | 34 | var port = normalizePort(process.env.PORT || '3000'); 35 | app.set('port', port); 36 | 37 | /** 38 | * Create HTTP server. 39 | */ 40 | 41 | var server = http.createServer(app); 42 | 43 | ``` 44 | 45 | 46 | ### 示例代码: 使用超快的流行的测试包在线测试你的代码 47 | 48 | ```javascript 49 | const app = express(); 50 | 51 | app.get('/user', function(req, res) { 52 | res.status(200).json({ name: 'tobi' }); 53 | }); 54 | 55 | request(app) 56 | .get('/user') 57 | .expect('Content-Type', /json/) 58 | .expect('Content-Length', '15') 59 | .expect(200) 60 | .end(function(err, res) { 61 | if (err) throw err; 62 | }); 63 | ```` 64 | -------------------------------------------------------------------------------- /sections/projectstructre/thincomponents.chinese.md: -------------------------------------------------------------------------------- 1 | # 用组件来构造你的解决方案 2 | 3 |

4 | 5 | 6 | ### 一段解释 7 | 8 | 对于中型应用以上来说,按部就班的写在一起真是太糟糕了-当一个有很多依赖的大型的软件会导致我们理解起来非常困难并且导致我们的代码杂乱不堪。甚至像那些能够熟练地驯服野兽的聪明的设计师一样,他们在设计上花费大量的精力用来"模块化"代码,每一次改动都需要仔细的评估对于其他依赖对象的影响。构建小型项目的最终方法是:将整体的项目分享一个个不与其他组件共享文件的独立组件,每个组件由很少的文件组成(例如API、服务、数据访问、测试等),所以这是比较容易理解的。一些被称为"microservices"的架构,去理解"microservices"不是你必须遵守的规范而是一套原则是非常重要的。你可以将许多原则应用到一个成熟的微服务体系结构中,或者只采用少数几个原则。只要你把软件的复杂性保持在低水平,两者都是好的。您至少应该做的是在组件之间创建一个基本的边界,在项目根中为每个业务组件分配一个文件夹,并让它自己做到其他组件只允许通过它的公共接口或API来实现它的功能。这是让你的组件保持简单的基础,避免依赖关系,在你的应用程序成长后,为将来成熟的微服务铺平道路。 9 | 10 |

11 | 12 | 13 | ### 引用博客: "扩展需要整个应用的扩展" 14 | 摘自博客 MartinFowler.com 15 | 16 | > 单片应用程序可以成功,但是越来越多的人对它们感到失望——特别是当越来越多的应用程序被部署到云上时。变更周期是绑定在一起的——对应用程序的一小部分进行了更改,需要重新构建和部署整个庞然大物。随着时间的推移,保持良好的模块结构通常很难,这使得更改只会影响自己内部的模块变得更加困难。扩展需要扩展整个应用程序,而不是需要更大的资源的部分。 17 | 18 |

19 | 20 | ### 推荐: 通过自包含的组件来构造解决方案 21 | ![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/structurebycomponents.PNG "Structuring solution by components") 22 | 23 |

24 | 25 | ### 避免: 通过技术角色对文件进行分组 26 | ![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/structurebyroles.PNG "Structuring solution by technical roles") 27 | -------------------------------------------------------------------------------- /sections/projectstructre/wraputilities.basque.md: -------------------------------------------------------------------------------- 1 | # Antolatu baliabide komunak npm paketetan 2 | 3 |

4 | 5 | ### Azalpen paragrafoa 6 | 7 | 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 8 | 9 | 10 |

11 | 12 | 13 | 14 | ### Partekatu zure baliabide propioak ingurune eta osagaietan 15 | 16 | ![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/Privatenpm.png "Antolatu proiektua osagaietan") 17 | -------------------------------------------------------------------------------- /sections/projectstructre/wraputilities.brazilian-portuguese.md: -------------------------------------------------------------------------------- 1 | # Envolva os utilitários comuns como pacotes npm 2 | 3 |

4 | 5 | ### Explicação em um Parágrafo 6 | 7 | Quando você começa a crescer e tem componentes diferentes em servidores diferentes que consomem utilitários semelhantes, você deve começar a gerenciar as dependências - como você pode manter uma cópia do código do utilitário e permitir que vários componentes do consumidor a usem e implantem? Bem, existe uma ferramenta para isso, ele é chamado npm ... Comece por encapsular pacotes de utilitários de terceiros com seu próprio código para torná-los facilmente substituíveis no futuro e publicar seu próprio código como pacote npm privado. Agora, toda a sua base de código pode importar esse código e se beneficiar da ferramenta gratuita de gerenciamento de dependências. É possível publicar pacotes npm para seu uso privado sem compartilhá-lo publicamente usando [módulos privados](https://docs.npmjs.com/private-modules/intro), [registros privados](https://npme.npmjs.com/docs/tutorials/npm-enterprise-with-nexus.html) ou [pacotes npm locais](https://medium.com/@arnaudrinquin/build-modular-application-with-npm-local-modules-dfc5ff047bcc) 8 | 9 |

10 | 11 | ### Compartilhando seus próprios utilitários comuns em ambientes e componentes 12 | 13 | ![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/Privatenpm.png "Solução de estruturação por componentes") 14 | -------------------------------------------------------------------------------- /sections/projectstructre/wraputilities.chinese.md: -------------------------------------------------------------------------------- 1 | # 将公用实用工具封装成 npm 包 2 | 3 |

4 | 5 | 6 | ### 一段解释 7 | 一旦你开始在不同的服务器上增加不同的组件并使用不同的服务器,这些服务器会消耗类似的工具,那么你应该开始管理依赖关系 - 你如何保留实用工具代码的一个副本,并让多个使用组件者使用和部署? 好吧,有一个这样的框架,它被称为npm ...首先用自己的代码包装第三方实用工具包,以便将来可以轻松替换,并发布自己的代码作为私人npm包。 现在,您所有的代码库都可以导入该代码并受益于免费的依赖管理框架。 您可以发布npm包供您自己的私人使用,而无需公开分享 [私人模块](https://docs.npmjs.com/private-modules/intro), [私人注册表](https://npme.npmjs.com/docs/tutorials/npm-enterprise-with-nexus.html) or [本地 npm 包](https://medium.com/@arnaudrinquin/build-modular-application-with-npm-local-modules-dfc5ff047bcc) 8 | 9 | 10 |

11 | 12 | 13 | ### 在环境和组件中共享你自己的公用实用工具 14 | ![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/Privatenpm.png "构建解决方案的组件") 15 | -------------------------------------------------------------------------------- /sections/projectstructre/wraputilities.japanese.md: -------------------------------------------------------------------------------- 1 | # 一般的なユーティリティを npm パッケージとしてラップする 2 | 3 |

4 | 5 | ### 一段落説明 6 | 7 | 成長を始めて、似たようなユーティリティを使用する異なるサーバ上の異なるコンポーネントを持つようになったら、依存関係の管理を始めなければなりません。- ユーティリティコードのコピーを1つにして、複数のコンシューマコンポーネントに使用させてデプロイするにはどうすれば良いでしょう? そのためのツールとして、npm と呼ばれるものがあります。サードパーティのユーティリティパッケージを独自のコードでラップして、将来的に簡単に置き換えられるようにし、独自のコードをプライベートな npm パッケージとして公開することから始めましょう。そうすることで、あなたのすべてのコードベースは、コードをインポートすることができ、無料の依存関係管理ツールの恩恵を受けることができます。[private modules](https://docs.npmjs.com/private-modules/intro) や [private registry](https://npme.npmjs.com/docs/tutorials/npm-enterprise-with-nexus.html)、[local npm packages](https://medium.com/@arnaudrinquin/build-modular-application-with-npm-local-modules-dfc5ff047bcc) を使うことで、自分だけのプライベートな利用だけのために npm パッケージを公開することができます。 8 | 9 |

10 | 11 | ### 環境やコンポーネント横断で独自の共通ユーティリティを共有する 12 | 13 | ![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/Privatenpm.png "コンポーネントでソリューションを構築する") 14 | -------------------------------------------------------------------------------- /sections/projectstructre/wraputilities.korean.md: -------------------------------------------------------------------------------- 1 | # 공유 유틸리티들은 NPM 패키지로 감싸라 (wrap) 2 | 3 |

4 | 5 | ### 한문단 설명 6 | 7 | 자라나기 시작하면서 비슷한 유틸리티들을 소비하는 다른 서버의 다른 컴포넌트들이 생겨나면 의존성을 관리하기 시작해야 한다 - 유틸리티 코드 한 부를 어떻게 소비자 컴포넌트 여럿이서 같이 쓰고 배치할 수 있게 하는가? 자, 여기 쓸만한 도구가 여기 있다...npm이라 불리는. 먼저 제삼자 유틸리티 패키지를 자신만의 코드로 감싸 미래에 대체하기 쉽게 하고 그 코드를 private npm 패키지로 publish해라. 이제 당신의 모든 코드 기반은 그 코드를 수입하여 무료 의존성 관리 도구의 혜택을 볼 수 있다. [private 모듈](https://docs.npmjs.com/private-modules/intro)이나 [private 레지스트리](https://npme.npmjs.com/docs/tutorials/npm-enterprise-with-nexus.html), 혹은 [로컬 npm 패키지](https://medium.com/@arnaudrinquin/build-modular-application-with-npm-local-modules-dfc5ff047bcc)를 사용하면 npm 패키지를 공개적으로 공유하지 않고도 자용으로 쓸 수 있게 출판할 수 있다. 8 | 9 |

10 | 11 | ### 당신만의 공유 유틸리티들을 환경과 컴포넌츠에 공유하기 12 | 13 | ![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/Privatenpm.png "Structuring solution by components") 14 | -------------------------------------------------------------------------------- /sections/projectstructre/wraputilities.md: -------------------------------------------------------------------------------- 1 | # Wrap common utilities as npm packages 2 | 3 |

4 | 5 | ### One Paragraph Explainer 6 | 7 | Once you start growing and have different components on different servers which consumes similar utilities, you should start managing the dependencies - how can you keep 1 copy of your utility code and let multiple consumer components use and deploy it? well, there is a tool for that, it's called npm... Start by wrapping 3rd party utility packages with your own code to make it easily replaceable in the future and publish your own code as private npm package. Now, all your code base can import that code and benefit free dependency management tool. It's possible to publish npm packages for your own private use without sharing it publicly using [private modules](https://docs.npmjs.com/private-modules/intro), [private registry](https://npme.npmjs.com/docs/tutorials/npm-enterprise-with-nexus.html) or [local npm packages](https://medium.com/@arnaudrinquin/build-modular-application-with-npm-local-modules-dfc5ff047bcc) 8 | 9 |

10 | 11 | ### Sharing your own common utilities across environments and components 12 | 13 | ![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/Privatenpm.png "Structuring solution by components") 14 | -------------------------------------------------------------------------------- /sections/projectstructre/wraputilities.polish.md: -------------------------------------------------------------------------------- 1 | # Zawiń typowe narzędzia jako pakiety npm 2 | 3 |

4 | 5 | ### Wyjaśnienie jednym akapitem 6 | 7 | Kiedy zaczniesz się rozwijać i będziesz mieć różne komponenty na różnych serwerach, które zużywają podobne narzędzia, powinieneś zacząć zarządzać zależnościami - w jaki sposób możesz zachować 1 kopię kodu narzędzia i pozwolić, aby wiele komponentów konsumenckich używało go i wdrażało? Cóż, istnieje narzędzie do tego, nazywa się npm... Zacznij od zawinięcia pakietów narzędziowych stron trzecich własnym kodem, aby w przyszłości można go łatwo było wymienić i opublikować własny kod jako prywatny pakiet npm. Teraz cała baza kodu może zaimportować ten kod i bezpłatne narzędzie do zarządzania zależnościami. Możliwe jest publikowanie pakietów NPM na własny użytek bez publicznego udostępniania go za pomocą [prywatnych modułów](https://docs.npmjs.com/private-modules/intro), [prywatnego rejestru](https://npme.npmjs.com/docs/tutorials/npm-enterprise-with-nexus.html) lub [lokalnych pakietów npm](https://medium.com/@arnaudrinquin/build-modular-application-with-npm-local-modules-dfc5ff047bcc) 8 | 9 |

10 | 11 | ### Udostępnianie własnych wspólnych narzędzi w różnych środowiskach i komponentach 12 | 13 | ![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/Privatenpm.png "Structuring solution by components") 14 | -------------------------------------------------------------------------------- /sections/projectstructre/wraputilities.russian.md: -------------------------------------------------------------------------------- 1 | # Оборачивайте общие утилиты в пакеты npm 2 | 3 |

4 | 5 | ### Объяснение в один абзац 6 | 7 | Как только вы начнете расти и иметь разные компоненты на разных серверах, которые используют одинаковые утилиты, вы должны начать управлять зависимостями - как вы можете сохранить 1 копию своего кода утилиты и позволить нескольким потребительским компонентам использовать и развертывать ее? ну, есть инструмент для этого, он называется npm ... Начните с упаковки сторонних пакетов утилит с вашим собственным кодом, чтобы в будущем его можно было легко заменить, и опубликуйте свой собственный код как частный пакет npm. Теперь вся ваша кодовая база может импортировать этот код и использовать бесплатный инструмент управления зависимостями. Можно публиковать пакеты npm для личного использования, не публикуя их публично, используя [private modules](https://docs.npmjs.com/private-modules/intro), [private registry](https://npme.npmjs.com/docs/tutorials/npm-enterprise-with-nexus.html) или [local npm packages](https://medium.com/@arnaudrinquin/build-modular-application-with-npm-local-modules-dfc5ff047bcc) 8 | 9 |

10 | 11 | ### Совместное использование собственных общих утилит в средах и компонентах 12 | 13 | ![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/Privatenpm.png "Structuring solution by components") 14 | -------------------------------------------------------------------------------- /sections/security/avoideval.brazilian-portuguese.md: -------------------------------------------------------------------------------- 1 | # Evite instruções eval do JavaScript 2 | 3 | ### Explicação em um Parágrafo 4 | 5 | `eval()`, `setTimeout()`, `setInterval()`, e `new Function()` são funções globais, geralmente usadas no Node.js, que aceitam um parâmetro de string que representa uma expressão, instrução ou sequência de instruções JavaScript. A preocupação de segurança de usar essas funções é a possibilidade de que uma entrada de usuário não confiável possa entrar na execução do código, levando ao comprometimento do servidor, já que avaliar o código do usuário essencialmente permite que um invasor execute qualquer ação possível. Sugere-se refatorar código para não depender do uso dessas funções em que a entrada do usuário pode ser passada para a função e executada. 6 | 7 | ### Exemplo de Código 8 | 9 | ```javascript 10 | // exemplo de código malicioso que um invasor conseguiu inserir 11 | userInput = "require('child_process').spawn('rm', ['-rf', '/'])"; 12 | 13 | // código malicioso executado 14 | eval(userInput); 15 | ``` 16 | 17 | ### O que Outros Blogueiros Dizem 18 | 19 | Do livro Essential Node.js Security por [Liran Tal](https://leanpub.com/nodejssecurity): 20 | > A função eval() é talvez a mais desaprovada dentro do JavaScript em uma perspectiva de segurança. Ela analisa uma string JavaScript como texto e a executa como se fosse um código JavaScript. 21 | Misturar isso com entradas não confiáveis ​​do usuário que podem encontrar o caminho para eval() é uma receita para o desastre que 22 | pode acabar comprometendo o servidor. 23 | -------------------------------------------------------------------------------- /sections/security/avoideval.chinese.md: -------------------------------------------------------------------------------- 1 | # 避免JS eval语法 2 | 3 | ### 一段解释 4 | 5 | `eval()`,`setTimeout()`和`setInterval()`是全局方法,经常在Node.js中被使用,它接收一个字符串参数,代表一个JavaScript表达式,语句,或者语句序列。使用这些函数的安全问题是, 不受信任的用户输入可能会发现进入代码执行的方式,从而导致危害服务器,因为评估用户代码实质上允许攻击者执行任何他可以的操作。对于这些用户输入可以传递给函数并执行的方法,建议重构代码,而不依赖于它们的使用。 6 | 7 | ### 代码示例 8 | 9 | ```javascript 10 | // 攻击者可能输入的恶意代码示例 11 | const userInput = "require('child_process').spawn('rm', ['-rf', '/'])"; 12 | 13 | // 恶意代码被执行 14 | eval(userInput); 15 | ``` 16 | 17 | ### 其他博客作者的说法 18 | 19 | 摘自[Liran Tal](https://leanpub.com/nodejssecurity)的书籍Essential Node.js Security: 20 | > 从安全的角度出发,在JavaScript语法中,eval()可能是最让人不悦的函数。 21 | 它将javascript字符串解析为文本,并将其作为javascript代码执行。 22 | 和不受信任的用户输入掺和在一起,可能会发现使用eval()是一个导致灾难的方式,最终服务器遭受破坏。 23 | -------------------------------------------------------------------------------- /sections/security/avoideval.japanese.md: -------------------------------------------------------------------------------- 1 | # JavaScript の eval 構文を避ける 2 | 3 | ### 一段落説明 4 | 5 | `eval()`、`setTimeout()`、`setInterval()`、そして `new Function()` は Node.js でしばしば利用される、JavaScript の式、文そして連続した文を表す文字列パラメータを受け取るグローバル関数です。これらの関数を利用することをセキュリティ的な懸念は、ユーザーのコードを評価することは本質的には攻撃者にあらゆるアクションを実行することを許すことなので、信頼されていないユーザーの入力がコード実行の中に入り込み、サーバーを危険にさらす可能性があるということです。ユーザーの入力が渡されて実行されるような関数の利用に依存しないようにコードをリファクタすることが推奨されています。 6 | 7 | ### コード例 8 | 9 | ```javascript 10 | // 攻撃者が入力できる悪意のあるコードの例 11 | const userInput = "require('child_process').spawn('rm', ['-rf', '/'])"; 12 | 13 | // 悪意のあるコードが実行される 14 | eval(userInput); 15 | ``` 16 | 17 | ### 他のブロガーが言っていること 18 | 19 | [Liran Tal](https://leanpub.com/nodejssecurity) による書籍 Essential Node.js Security より: 20 | > セキュリティの観点から見ると、eval() 関数はおそらく JavaScript の中でもっとも忌み嫌われている部分でしょう。 21 | > それは JavaScript の文字列をテキストにパースし、まるで JavaScript コードのように実行します。 22 | > これを、eval() へ渡されることが分かっているかもしれない信頼されていないユーザー入力と混ぜることは、サーバーを危険にさらすことになる、崩壊へのレシピといえるでしょう。 23 | -------------------------------------------------------------------------------- /sections/security/avoideval.md: -------------------------------------------------------------------------------- 1 | # Avoid JS eval statements 2 | 3 | ### One Paragraph Explainer 4 | 5 | `eval()`, `setTimeout()`, `setInterval()`, and `new Function()` are global functions, often used in Node.js, which accept a string parameter representing a JavaScript expression, statement, or sequence of statements. The security concern of using these functions is the possibility that untrusted user input might find its way into code execution leading to server compromise, as evaluating user code essentially allows an attacker to perform any actions that you can. It is suggested to refactor code to not rely on the usage of these functions where user input could be passed to the function and executed. 6 | 7 | ### Code example 8 | 9 | ```javascript 10 | // example of malicious code which an attacker was able to input 11 | const userInput = "require('child_process').spawn('rm', ['-rf', '/'])"; 12 | 13 | // malicious code executed 14 | eval(userInput); 15 | ``` 16 | 17 | ### What other bloggers say 18 | 19 | From the Essential Node.js Security book by [Liran Tal](https://leanpub.com/nodejssecurity): 20 | > The eval() function is perhaps of the most frowned upon JavaScript pieces from a security 21 | perspective. It parses a JavaScript string as text, and executes it as if it were a JavaScript code. 22 | Mixing that with untrusted user input that might find it’s way to eval() is a recipe for disaster that 23 | can end up with server compromise. 24 | -------------------------------------------------------------------------------- /sections/security/avoideval.polish.md: -------------------------------------------------------------------------------- 1 | # Unikaj JS eval statements 2 | 3 | ### Wyjaśnienie jednym akapitem 4 | 5 | `eval()`, `setTimeout()`, `setInterval()`, i `new Function()` są funkcjami globalnymi, często używanymi w Node.js, które akceptują parametr ciągu znaków reprezentujący wyrażenie JavaScript, instrukcję lub sekwencję instrukcji. Problemem związanym z bezpieczeństwem korzystania z tych funkcji jest możliwość, że niezaufane dane wejściowe użytkownika mogą znaleźć drogę do wykonania kodu prowadzącego do naruszenia bezpieczeństwa serwera, ponieważ ocena kodu użytkownika zasadniczo pozwala atakującemu na wykonanie dowolnych działań. Sugeruje się, aby kod refaktoryzować, aby nie polegał na użyciu tych funkcji, w których dane wejściowe użytkownika mogą być przekazywane do funkcji i wykonywane. 6 | 7 | ### Przykład kodu 8 | 9 | ```javascript 10 | // example of malicious code which an attacker was able to input 11 | const userInput = "require('child_process').spawn('rm', ['-rf', '/'])"; 12 | 13 | // malicious code executed 14 | eval(userInput); 15 | ``` 16 | 17 | ### Co mówią inni blogerzy 18 | 19 | Z książki Essential Node.js Security od [Liran Tal](https://leanpub.com/nodejssecurity): 20 | > The eval() function is perhaps of the most frowned upon JavaScript pieces from a security 21 | perspective. It parses a JavaScript string as text, and executes it as if it were a JavaScript code. 22 | Mixing that with untrusted user input that might find it’s way to eval() is a recipe for disaster that 23 | can end up with server compromise. 24 | -------------------------------------------------------------------------------- /sections/security/avoideval.russian.md: -------------------------------------------------------------------------------- 1 | # Избегайте JavaScript eval утверждений 2 | 3 | ### Объяснение в один абзац 4 | 5 | `eval()`, `setTimeout()`, `setInterval()` и `new Function()` являются глобальными функциями, часто используемыми в Node.js, которые принимают строковый параметр, представляющий выражение, инструкцию или последовательность JavaScript инструкций. Забота о безопасности при использовании этих функций - это вероятность того, что ненадежный пользовательский ввод может найти свое место в выполнении кода, что приведет к компрометации сервера, поскольку оценка пользовательского кода, по сути, позволяет злоумышленнику выполнять любые действия, которые вы можете. Рекомендуется реорганизовать код, чтобы не полагаться на использование этих функций, когда пользовательский ввод может быть передан в функцию и выполнен. 6 | 7 | ### Пример кода 8 | 9 | ```javascript 10 | // example of malicious code which an attacker was able to input 11 | const userInput = "require('child_process').spawn('rm', ['-rf', '/'])"; 12 | 13 | // malicious code executed 14 | eval(userInput); 15 | ``` 16 | 17 | ### Что говорят другие блогеры 18 | 19 | Из книги Essential Node.js Security [Liran Tal](https://leanpub.com/nodejssecurity): 20 | > Функция eval(), пожалуй, самая неодобрительная с точки зрения безопасности с точки зрения JavaScript. Он анализирует строку JavaScript как текст и выполняет ее, как если бы это был код JavaScript. 21 | Сочетание этого с ненадежным пользовательским вводом, который может найти путь к eval(), - это рецепт катастрофы, которая может привести к компрометации сервера 22 | -------------------------------------------------------------------------------- /sections/security/bcryptpasswords.chinese.md: -------------------------------------------------------------------------------- 1 | # 对于密码,避免使用Node.js的Crypto库,使用Bcrypt 2 | 3 | ### 一段解释 4 | 5 | 当存储用户密码的时候,建议使用[bcrypt npm module](https://www.npmjs.com/package/bcrypt)提供的自适应哈希算法bcrypt,而不是使用Node.js的crypto模块。由于`Math.random()`的可预测性,它也不应该作为密码或者令牌生成的一部分。 6 | 7 | 相较于JavaScript实现,`bcrypt`或者类似的模块应该被使用。当使用`bcrypt`时,可以指定相应数量的回合数(rounds),以提供安全的哈希。这将设置work factor或者用于数据处理的回合次数,而更多的哈希回合次数导致更安全的哈希值(尽管这是CPU耗时的代价)。哈希回合(hashing rounds)的引入意味着蛮力因子会显著降低, 因此密码破解会减慢, 从而增加产生一次尝试所需的时间。 8 | 9 | ### 代码示例 10 | 11 | ```javascript 12 | // 使用10个哈希回合异步生成安全密码 13 | bcrypt.hash('myPassword', 10, function(err, hash) { 14 | // 在用户记录中存储安全哈希 15 | }); 16 | 17 | // 将提供的密码输入与已保存的哈希进行比较 18 | bcrypt.compare('somePassword', hash, function(err, match) { 19 | if(match) { 20 | // 密码匹配 21 | } else { 22 | // 密码不匹配 23 | } 24 | }); 25 | ``` 26 | 27 | ### 其他博客作者的说法 28 | 29 | 摘自博客[Max McCarty](https://dzone.com/articles/nodejs-and-password-storage-with-bcrypt): 30 | > ... 它不只是使用正确的哈希算法。我已经广泛讨论了正确的工具,包括必要的成分"时间",如何作为密码哈希算法的一部分, 以及它对于试图通过蛮力破解密码的攻击者,意味着什么。 31 | -------------------------------------------------------------------------------- /sections/security/bcryptpasswords.japanese.md: -------------------------------------------------------------------------------- 1 | # パスワードの処理に Node.js の crypto ライブラリではなく Bcrypt を利用する 2 | 3 | ### 一段落説明 4 | 5 | ユーザーのパスワードを保存する際には、ネイティブの Node.js crypto モジュールを使用するのではなく、[bcrypt npm モジュール](https://www.npmjs.com/package/bcrypt)が提供するbcrypt のような、適応性のあるハッシュアルゴリズムを使用することをおすすめします。`Math.random()` は予測可能性があるため、パスワードやトークン生成の一部としては決して使用しないでください。 6 | 7 | JavaScript の実装ではなく、`bcrypt` モジュールなどを使用しなければなりません。`bcrypt` を使う場合、安全なハッシュを提供するために 'ラウンド数' を指定することができます。これはワークファクターもしくはデータが処理される回数を指定し、ハッシュのラウンド数が増えるほど、より安全なハッシュが算出されます(ただし、CPU 計算時間のコストがかかります)。ハッシュラウンドの導入は、1回試行するために必要な時間を増加させることでパスワードクラッカーが減速されるため、ブルートフォース要因が大幅に削減されることを意味します。 8 | 9 | ### コード例 10 | 11 | ```javascript 12 | try { 13 | // 10回のハッシュラウンドを設定して、非同期にセキュアなパスワードを生成する 14 | const hash = await bcrypt.hash('myPassword', 10); 15 | // セキュアなハッシュをユーザレコードに保存する 16 | 17 | // 与えられたパスワード入力を保存されたハッシュと比較する 18 | const match = await bcrypt.compare('somePassword', hash); 19 | if (match) { 20 | // パスワードが合致した場合 21 | } else { 22 | // パスワードが合致しなかった場合 23 | } 24 | } catch { 25 | logger.error('could not hash password.') 26 | } 27 | ``` 28 | 29 | ### 他のブロガーが言っていること 30 | 31 | [Max McCarty](https://dzone.com/articles/nodejs-and-password-storage-with-bcrypt) のブログより: 32 | > ... 正しいハッシュアルゴリズムを使うだけではありません。正しいツールがパスワードハッシュアルゴリズムの一部として 「時間」という必要不可欠な要素を含んでいることと、それがブルートフォースでパスワードを解読しようとしている攻撃者にとって何を意味するのかについて、広範囲にわたって話してきました。 33 | -------------------------------------------------------------------------------- /sections/security/childprocesses.chinese.md: -------------------------------------------------------------------------------- 1 | # 处理子进程时要谨慎 2 | 3 | ### 一段解释 4 | 5 | 尽管子进程非常棒, 但使用它们应该谨慎。如果无法避免传递用户输入,就必须经过脱敏处理。 6 | 未经脱敏处理的输入执行系统级逻辑的危险是无限的, 从远程代码执行到暴露敏感的系统数据, 甚至数据丢失。准备工作的检查清单可能是这样的 7 | 8 | - 避免在每一种情况下的用户输入, 否则验证和脱敏处理 9 | - 使用user/group标识限制父进程和子进程的权限 10 | - 在隔离环境中运行进程, 以防止在其他准备工作失败时产生不必要的副作用 11 | 12 | ### 代码示例: 未脱敏处理子进程的危害 13 | 14 | ```javascript 15 | const { exec } = require('child_process'); 16 | 17 | ... 18 | 19 | // 例如, 以一个脚本为例, 它采用两个参数, 其中一个参数是未经脱敏处理的用户输入 20 | exec('"/path/to/test file/someScript.sh" --someOption ' + input); 21 | 22 | // -> 想象一下, 如果用户只是输入'&& rm -rf --no-preserve-root /'类似的东西, 会发生什么 23 | // 你会得到一个不想要的结果 24 | ``` 25 | 26 | ### 额外资源 27 | 28 | 摘自Node.js child process [documentation](https://nodejs.org/dist/latest-v8.x/docs/api/child_process.html#child_process_child_process_exec_command_options_callback): 29 | 30 | > 切勿将未经脱敏处理的用户输入传递给此函数。任何包含shell元字符(metacharacters)的输入都可用于触发任意命令的执行。 31 | -------------------------------------------------------------------------------- /sections/security/childprocesses.japanese.md: -------------------------------------------------------------------------------- 1 | # 子プロセスで処理を行う場合は注意する 2 | 3 | ### 一段落説明 4 | 5 | 子プロセスは素晴らしいものですが、注意して使用する必要があります。ユーザー入力の受け渡しは、利用しないのでなければ、サニタイズされていなければなりません。サニタイズされていない入力がシステムレベルのロジックを実行する危険性は無限にあり、リモートコードの実行からセンシティブなシステムデータの漏洩、そしてデータ損失にまで及びます。準備のためのチェックリストは以下のようになります。 6 | 7 | - すべての場合でユーザー入力を避け、そうでない場合は検証とサニタイズを行う 8 | - ユーザー/グループアイデンティを利用して、親プロセスと子プロセスの権限を制限する 9 | - 上記が機能しなかった場合の望まない副作用を防ぐために、プロセスを隔離された環境で実行する 10 | 11 | ### コード例: サニタイズされていない子プロセス実行の危険性 12 | 13 | ```javascript 14 | const { exec } = require('child_process'); 15 | 16 | ... 17 | 18 | // 例として、2つのうち1つがサニタイズされていないユーザー入力であるスクリプトを考えてみましょう 19 | exec('"/path/to/test file/someScript.sh" --someOption ' + input); 20 | 21 | // -> ユーザー入力が '&& rm -rf --no-preserve-root /' だった場合に、何が起こるか想像してみてください 22 | // 望まない結果に驚くことでしょう 23 | ``` 24 | 25 | ### その他のリソース 26 | 27 | Node.js child process の[ドキュメント](https://nodejs.org/dist/latest-v8.x/docs/api/child_process.html#child_process_child_process_exec_command_options_callback) より: 28 | 29 | > サニタイズされていないユーザー入力をこの関数に決して渡さないでください。シェルのメタ文字を含んでいるどんな入力も、任意のコマンド実行を引き起こすために利用される可能性があります。 30 | -------------------------------------------------------------------------------- /sections/security/childprocesses.md: -------------------------------------------------------------------------------- 1 | # Be cautious when working with child processes 2 | 3 | ### One Paragraph Explainer 4 | 5 | As great as child processes are, they should be used with caution. Passing in user input must be sanitized, if not avoided at all. 6 | The dangers of unsanitized input executing system-level logic are unlimited, reaching from remote code execution to the exposure of 7 | sensitive system data and even data loss. A check list of preparations could look like this 8 | 9 | - avoid user input in every case, otherwise validate and sanitize it 10 | - limit the privileges of the parent and child processes using user/group identities 11 | - run your process inside of an isolated environment to prevent unwanted side-effects if the other preparations fail 12 | 13 | ### Code example: Dangers of unsanitized child process executions 14 | 15 | ```javascript 16 | const { exec } = require('child_process'); 17 | 18 | ... 19 | 20 | // as an example, take a script that takes two arguments, one of them is unsanitized user input 21 | exec('"/path/to/test file/someScript.sh" --someOption ' + input); 22 | 23 | // -> imagine what could happen if the user simply enters something like '&& rm -rf --no-preserve-root /' 24 | // you'd be in for an unwanted surprise 25 | ``` 26 | 27 | ### Additional resources 28 | 29 | From the Node.js child process [documentation](https://nodejs.org/dist/latest-v8.x/docs/api/child_process.html#child_process_child_process_exec_command_options_callback): 30 | 31 | > Never pass unsanitized user input to this function. Any input containing shell metacharacters may be used to trigger arbitrary command execution. 32 | -------------------------------------------------------------------------------- /sections/security/childprocesses.polish.md: -------------------------------------------------------------------------------- 1 | # Zachowaj ostrożność podczas pracy z procesami potomnymi 2 | 3 | ### Wyjaśnienie jednym akapitem 4 | 5 | Niezależnie od tego, jak wielkie są procesy potomne, należy ich używać ostrożnie. Przekazywanie danych wejściowych przez użytkownika musi być sanitized, jeśli w ogóle nie można go uniknąć. 6 | Niebezpieczeństwa związane z niezaangażowanym wejściem wykonującym logikę na poziomie systemu są nieograniczone, od zdalnego wykonania kodu po ujawnienie 7 | wrażliwych danych systemowych, a nawet utraty danych. Lista kontrolna przygotowań może wyglądać następująco 8 | 9 | - w każdym przypadku unikaj wprowadzania danych przez użytkownika, w przeciwnym razie waliduj i sanitize 10 | - ograniczenie uprawnień procesów nadrzędnych i podrzędnych przy użyciu tożsamości użytkowników / grup 11 | - uruchom proces w izolowanym środowisku, aby zapobiec niepożądanym skutkom ubocznym, jeśli inne przygotowania zawiodą 12 | 13 | ### Przykład kodu: Dangers of unsanitized child process executions 14 | 15 | ```javascript 16 | const { exec } = require('child_process'); 17 | 18 | ... 19 | 20 | // as an example, take a script that takes two arguments, one of them is unsanitized user input 21 | exec('"/path/to/test file/someScript.sh" --someOption ' + input); 22 | 23 | // -> imagine what could happen if the user simply enters something like '&& rm -rf --no-preserve-root /' 24 | // you'd be in for an unwanted surprise 25 | ``` 26 | 27 | ### Dodatkowe zasoby 28 | 29 | Z Node.js child process [documentation](https://nodejs.org/dist/latest-v8.x/docs/api/child_process.html#child_process_child_process_exec_command_options_callback): 30 | 31 | > Never pass unsanitized user input to this function. Any input containing shell metacharacters may be used to trigger arbitrary command execution. 32 | -------------------------------------------------------------------------------- /sections/security/expirejwt.brazilian-portuguese.md: -------------------------------------------------------------------------------- 1 | # Tenha suporte à lista negra de JWTs 2 | 3 | ### Explicação em um Parágrafo 4 | 5 | Por padrão, os JWTs (JSON Web Tokens) são completamente sem estado, portanto, quando um token válido é assinado por um emissor, o token pode ser verificado como autêntico pela aplicação. O problema que isso causa é a preocupação de segurança em que um token vazado ainda pode ser usado e não pode ser revogado, devido à assinatura permanecer válida, desde que a assinatura fornecida pelos problemas corresponda ao esperado pelo aplicativo. 6 | Devido a isso, ao usar a autenticação do JWT, uma aplicação deve gerenciar uma lista negra de tokens expirados ou revogados para reter a segurança do usuário, no caso de um token precisar ser revogado. 7 | 8 | ### exemplo `express-jwt-blacklist` 9 | 10 | Um exemplo de uso do `express-jwt-blacklist` em um projeto Node.js usando o `express-jwt` 11 | 12 | ```javascript 13 | var jwt = require('express-jwt'); 14 | var blacklist = require('express-jwt-blacklist'); 15 | 16 | app.use(jwt({ 17 | secret: 'my-secret', 18 | isRevoked: blacklist.isRevoked 19 | })); 20 | 21 | app.get('/logout', function (req, res) { 22 | blacklist.revoke(req.user) 23 | res.sendStatus(200); 24 | }); 25 | ``` 26 | 27 | ### O que Outros Blogueiros Dizem 28 | 29 | Do blog de [Marc Busqué](http://waiting-for-dev.github.io/blog/2017/01/25/jwt_secure_usage/): 30 | > ...adicione uma camada de revogação sobre o JWT, mesmo que isso implique na perda de sua natureza sem estado. 31 | -------------------------------------------------------------------------------- /sections/security/expirejwt.chinese.md: -------------------------------------------------------------------------------- 1 | # 支持黑名单的JWTs 2 | 3 | ### 一段解释 4 | 5 | 按照设计, JWTs(JSON Web Tokens)是完全无状态的, 因此, 一旦有效令牌由颁发者签署, 应用程序就可以验证该令牌是否真实。这导致了安全的问题, 这里,泄漏的令牌仍可使用且无法撤销, 因为只要问题令牌提供的签名与应用程序所期望的相匹配, 签名就仍然有效。 6 | 因此, 在使用JWT身份验证时, 应用程序应管理过期或已吊销令牌的黑名单, 以便在需要吊销令牌的情况下保留用户的安全性。 7 | 8 | ### `express-jwt-blacklist` 示例 9 | 10 | 在Node.js项目中,使用`express-jwt`,并运行`express-jwt-blacklist`的例子 11 | 12 | ```javascript 13 | const jwt = require('express-jwt'); 14 | const blacklist = require('express-jwt-blacklist'); 15 | 16 | app.use(jwt({ 17 | secret: 'my-secret', 18 | isRevoked: blacklist.isRevoked 19 | })); 20 | 21 | app.get('/logout', function (req, res) { 22 | blacklist.revoke(req.user) 23 | res.sendStatus(200); 24 | }); 25 | ``` 26 | 27 | ### 其他博客作者说什么 28 | 29 | 摘自博客[Marc Busqué](http://waiting-for-dev.github.io/blog/2017/01/25/jwt_secure_usage/): 30 | > ...在JWT之上添加一个吊销层(revocation layer), 即使它意味着失去其无状态性质。 31 | -------------------------------------------------------------------------------- /sections/security/expirejwt.japanese.md: -------------------------------------------------------------------------------- 1 | # JWT の ブラックリスト化をサポートする 2 | 3 | ### 一段落説明 4 | 5 | 設計上、JWTs (JSON Web Tokens) は完全にステートレスであるため、一度有効なトークンが発行者によって署名されると、恐らくそのトークンはアプリケーションによって本物であると判断されるでしょう。このことが引き起こす問題として、発行者によって施された署名がアプリケーションの要求と一致する限り署名は有効であると判断されるため、漏洩したトークンが使用され、そのトークンを無効にすることができないというセキュリティ上の懸念があります。 6 | そのため、JWT 認証を利用する場合は、トークンが無効化される必要があるケースにおいてユーザーのセキュリティを維持するために、アプリケーションは期限切れや無効なトークンのブラックリストを管理する必要があります。 7 | 8 | ### `express-jwt-blacklist` の例 9 | 10 | `express-jwt` を利用した Node.js プロジェクトで、`express-jwt-blacklist` を実行する例です。ここで、`express-jwt-blacklist` のデフォルトストア設定である(インメモリ)キャッシュを利用せず、複数の Node.js プロセスをまたいでトークンを無効化できるように、Redis のような外部のストアを利用することが重要であることに注意してください。 11 | 12 | ```javascript 13 | const jwt = require('express-jwt'); 14 | const blacklist = require('express-jwt-blacklist'); 15 | 16 | blacklist.configure({ 17 | tokenId: 'jti', 18 | strict: true, 19 | store: { 20 | type: 'memcached', 21 | host: '127.0.0.1', 22 | port: 11211, 23 | keyPrefix: 'mywebapp:', 24 | options: { 25 | timeout: 1000 26 | } 27 | } 28 | }); 29 | 30 | app.use(jwt({ 31 | secret: 'my-secret', 32 | isRevoked: blacklist.isRevoked 33 | })); 34 | 35 | app.get('/logout', (req, res) => { 36 | blacklist.revoke(req.user) 37 | res.sendStatus(200); 38 | }); 39 | ``` 40 | 41 | ### 他のブロガーが言っていること 42 | 43 | [Marc Busqué](http://waiting-for-dev.github.io/blog/2017/01/25/jwt_secure_usage/) のブログより: 44 | > ...たとえそれがステートレス性を損なったとしても、JTW 上に無効化レイヤを追加してください。 45 | -------------------------------------------------------------------------------- /sections/security/hideerrors.brazilian-portuguese.md: -------------------------------------------------------------------------------- 1 | # Oculte detalhes de erros dos usuários 2 | 3 | ### Explicação em um Parágrafo 4 | 5 | A exposição dos detalhes de erros da aplicação ao cliente em produção deve ser evitada devido ao risco de expor detalhes confidenciais do aplicativo, como caminhos de arquivo do servidor, módulos de terceiros em uso e outros fluxos de trabalho internos da aplicação que poderiam ser explorados por um invasor. 6 | O Express vem com um manipulador de erros embutido, que cuida de quaisquer erros que possam ser encontrados na aplicação. Essa função de middleware padrão de tratamento de erros é adicionada no final do stack de funções do middleware. 7 | Se você passar um erro para `next()` e você não o manipular em um manipulador de erro personalizado, ele será tratado pelo manipulador de erros Express; o erro será gravado no cliente com o rastreamento de stack. Esse comportamento será verdadeiro quando `NODE_ENV` for definido como `development`, no entanto, quando `NODE_ENV` for definido como `production`, o rastreio de pilha não será gravado, apenas o código de resposta HTTP. 8 | 9 | ### Exemplo de código: Manipulador de erros do express 10 | 11 | ``` javascript 12 | // manipulador de erros em produção 13 | // nenhum rastreamento de stack vazou para o usuário 14 | app.use(function(err, req, res, next) { 15 | res.status(err.status || 500); 16 | res.render('error', { 17 | message: err.message, 18 | error: {} 19 | }); 20 | }); 21 | ``` 22 | 23 | ### Recursos Adicionais 24 | 25 | 🔗 [Documentação de manipulação de erros do Express.js](https://expressjs.com/en/guide/error-handling.html) 26 | -------------------------------------------------------------------------------- /sections/security/hideerrors.chinese.md: -------------------------------------------------------------------------------- 1 | # 在客户端隐藏错误详情 2 | 3 | ### 一段解释 4 | 5 | 在生产环境中,应该避免在客户端暴露应用程序的错误详情,因为这会带来暴露程序敏感信息的风险,比如:服务器文件路径、使用的第三方模块以及其他可能被攻击者利用的内部工作流程信息等。Express拥有内置的错误处理机制,以此来处理好在程序中可能会出现的任何错误。默认的错误处理中间件方法被添加到了中间件堆栈的最后面。如果你传了一个错误给`next()`,又没有通过自定义的错误处理机制来处理它,这个错误会被Express内置的错误处理机制处理;这个错误会被写到客户端的堆栈跟踪信息里。当`NODE_ENV`被设置为`development`的时候,才会把详细的错误信息写到客户端,但是当`NODE_ENV`被设置为`production`的时候,不会把详细的堆栈跟踪信息写入到客户端,只会返回HTTP的响应码。 6 | 7 | ### 代码示例:Express错误处理 8 | 9 | ``` javascript 10 | // 生产环境错误处理 11 | // 不把堆栈跟踪信息展示给用户看 12 | app.use(function(err, req, res, next) { 13 | res.status(err.status || 500); 14 | res.render('error', { 15 | message: err.message, 16 | error: {} 17 | }); 18 | }); 19 | ``` 20 | 21 | ### 其他资源 22 | 23 | 🔗 [Express.js 错误处理相关文档](https://expressjs.com/en/guide/error-handling.html) -------------------------------------------------------------------------------- /sections/security/hideerrors.japanese.md: -------------------------------------------------------------------------------- 1 | # エラーの詳細をクライアントから隠す 2 | 3 | ### 一段落説明 4 | 5 | サーバファイルのパス、使用中のサードパーティモジュール、その他攻撃者に悪用される可能性のあるアプリケーションの内部ワークフローなど、機密性の高いアプリケーションの詳細情報が漏洩するリスクがあるため、本番環境においてクライアントにアプリケーションエラーの詳細を晒すべきではありません。 6 | Express には、アプリ内で発生する恐れのあるエラーを処理するエラーハンドラが組み込まれています。このデフォルトのエラー処理ミドルウェア関数は、ミドルウェア関数スタックの最後に追加されます。 7 | エラーを `next()` に渡し、カスタムエラーハンドラで処理しない場合は、組み込みの Express エラーハンドラで処理されます。エラーはスタックトレースと共にクライアントに書き込まれます。この動作は `NODE_ENV` が `development` に設定されている場合に有効ですが、`NODE_ENV` が `production` に設定されている場合は、スタックトレースは書き込まれず、HTTP レスポンスコードのみが書き込まれます。 8 | 9 | ### コード例: Express エラーハンドラ 10 | 11 | ```javascript 12 | // 本番のエラーハンドラ 13 | // スタックトレースがユーザーに漏洩しない 14 | app.use((err, req, res, next) => { 15 | res.status(err.status || 500); 16 | res.render('error', { 17 | message: err.message, 18 | error: {} 19 | }); 20 | }); 21 | ``` 22 | 23 | ### その他のリソース 24 | 25 | 🔗 [Express.js エラーハンドリングドキュメント](https://expressjs.com/en/guide/error-handling.html) 26 | -------------------------------------------------------------------------------- /sections/security/hideerrors.md: -------------------------------------------------------------------------------- 1 | # Hide error details from client 2 | 3 | ### One Paragraph Explainer 4 | 5 | Exposing application error details to the client in production should be avoided due to the risk of exposing 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. 6 | Express comes with a built-in error handler, which takes care of any errors that might be encountered in the app. This default error-handling middleware function is added at the end of the middleware function stack. 7 | If you pass an error to `next()` and you do not handle it in a custom error handler, it will be handled by the built-in Express error handler; the error will be written to the client with the stack trace. This behaviour will be true when `NODE_ENV` is set to `development`, however when `NODE_ENV` is set to `production`, the stack trace is not written, only the HTTP response code. 8 | 9 | ### Code example: Express error handler 10 | 11 | ```javascript 12 | // production error handler 13 | // no stacktraces leaked to user 14 | app.use((err, req, res, next) => { 15 | res.status(err.status || 500); 16 | res.render('error', { 17 | message: err.message, 18 | error: {} 19 | }); 20 | }); 21 | ``` 22 | 23 | ### Additional resources 24 | 25 | 🔗 [Express.js error handling documentation](https://expressjs.com/en/guide/error-handling.html) 26 | -------------------------------------------------------------------------------- /sections/security/hideerrors.polish.md: -------------------------------------------------------------------------------- 1 | # Ukryj szczegóły błędu przed klientem 2 | 3 | ### Wyjaśnienie jednym akapitem 4 | 5 | Należy unikać ujawniania klientowi szczegółów błędu aplikacji podczas produkcji ze względu na ryzyko ujawnienia wrażliwych szczegółów aplikacji, takich jak ścieżki plików serwera, używane moduły innych firm i inne wewnętrzne przepływy pracy aplikacji, które mogą zostać wykorzystane przez atakującego. 6 | Express jest wyposażony we wbudowany moduł obsługi błędów, który zajmuje się wszelkimi błędami, które mogą wystąpić w aplikacji. Ta domyślna funkcja oprogramowania pośredniego obsługująca błędy jest dodawana na końcu stosu funkcji oprogramowania pośredniego. 7 | Jeśli przekażesz błąd do `next ()` i nie obsłużysz go w niestandardowej procedurze obsługi błędów, zostanie on obsłużony przez wbudowaną procedurę obsługi błędów Express; błąd zostanie zapisany w kliencie ze śledzeniem stosu. To zachowanie będzie prawdziwe, gdy `NODE_ENV` jest ustawione na `development`, jednak gdy `NODE_ENV` jest ustawione na `production`, ślad stosu nie jest zapisywany, tylko kod odpowiedzi HTTP. 8 | 9 | ### Przykład kodu: Express error handler 10 | 11 | ```javascript 12 | // production error handler 13 | // no stacktraces leaked to user 14 | app.use((err, req, res, next) => { 15 | res.status(err.status || 500); 16 | res.render('error', { 17 | message: err.message, 18 | error: {} 19 | }); 20 | }); 21 | ``` 22 | 23 | ### Dodatkowe źródła 24 | 25 | 🔗 [Express.js error handling documentation](https://expressjs.com/en/guide/error-handling.html) 26 | -------------------------------------------------------------------------------- /sections/security/hideerrors.russian.md: -------------------------------------------------------------------------------- 1 | # Скрывайте детали ошибок от клиентов 2 | 3 | ### Объяснение в один абзац 4 | 5 | Следует избегать предоставления подробных сведений об ошибках в сообщениях клиенту в производственном процессе, поскольку существует риск раскрытия таких важных сведений приложения, как пути к файлам сервера, используемые сторонние модули и другие внутренние рабочие процессы приложения, которые могут быть использованы злоумышленником. 6 | Express поставляется со встроенным обработчиком ошибок, который заботится о любых ошибках, которые могут возникнуть в приложении. Эта промежуточная функция обработки ошибок по умолчанию добавляется в конец стека функций промежуточного программного обеспечения. 7 | Если вы передаете ошибку в `next()` и не обрабатываете ее в пользовательском обработчике ошибок, она будет обработана встроенным обработчиком ошибок Express; ошибка будет записана клиенту с трассировкой стека. Это поведение будет истинным, если для `NODE_ENV` установлено значение `development`, однако, если для `NODE_ENV` установлено значение `production`, трассировка стека не записывается, только код ответа HTTP. 8 | 9 | ### Пример кода: экспресс-обработчик ошибок 10 | 11 | ```javascript 12 | // production error handler 13 | // no stacktraces leaked to user 14 | app.use((err, req, res, next) => { 15 | res.status(err.status || 500); 16 | res.render('error', { 17 | message: err.message, 18 | error: {} 19 | }); 20 | }); 21 | ``` 22 | 23 | ### Дополнительные ресурсы 24 | 25 | 🔗 [Express.js error handling documentation](https://expressjs.com/en/guide/error-handling.html) 26 | -------------------------------------------------------------------------------- /sections/security/limitrequests.chinese.md: -------------------------------------------------------------------------------- 1 | # 通过平衡器或者中间件限制并发请求 2 | 3 | ### 一段解释 4 | 5 | 你的Node.js应用程序应该实现限流,以此来保护它不会因为同一时间太多请求而崩溃。限流就是一个任务,需要一个专门为此设计的服务来辅助才能达到最佳的执行效果,比如nginx,但是通过应用程序中间件也可以实现,比如[express-rate-limiter](https://www.npmjs.com/package/express-rate-limit)。 6 | 7 | ### 代码示例:Express对某些路由使用限流中间件 8 | 9 | 使用[express-rate-limiter](https://www.npmjs.com/package/express-rate-limit)模块 10 | 11 | ``` javascript 12 | const RateLimit = require('express-rate-limit'); 13 | // 如果请求需要经过代理,确保客户端IP能够传给req.ip这一点非常重要 14 | app.enable('trust proxy'); 15 | 16 | const apiLimiter = new RateLimit({ 17 | windowMs: 15*60*1000, // 15分钟 18 | max: 100, 19 | }); 20 | 21 | // 仅应用于以/user/开头的请求 22 | app.use('/user/', apiLimiter); 23 | ``` 24 | 25 | ### 其他博主的看法 26 | 27 | 摘自 [NGINX 博客](https://www.nginx.com/blog/rate-limiting-nginx/): 28 | 29 | > 限流可以是出于安全考虑,比如用于降低暴力破解密码攻击的风险。可以通过限制输入请求速率在某个基于真实用户的特定值来防止DDOS攻击,这对分析(通过日志)特定的URLs也有一定的帮助。但通常情况下,限流是用来保护上游应用程序不会因为同一时间太多请求而崩溃。 -------------------------------------------------------------------------------- /sections/security/lintrules.japanese.md: -------------------------------------------------------------------------------- 1 | # linter のセキュリティルールを受け入れる 2 | 3 | ### 一段落説明 4 | 5 | [eslint-plugin-security](https://github.com/nodesecurity/eslint-plugin-security) や [tslint-config-security](https://www.npmjs.com/package/tslint-config-security) といった ESLint や TSLint 用のセキュリティプラグインは、安全でない正規表現や安全でない `eval()` の使用、そしてアプリケーション内のファイルシステムにアクセスする際にリテラルでないファイル名を使用するといった、多くの既知の脆弱性に基づいたコードセキュリティチェックを提供しています。[pre-git](https://github.com/bahmutov/pre-git) のような Git hooks の利用することで、リモートに配布される前に、シークレットがコードに含まれていないかチェックするなど、ソースコントロール上にさらなるルールを強制することができます。 6 | 7 | ### `eslint-plugin-security` の例 8 | 9 | `eslint-plugin-security` によって検出される安全でないプラクティスの例: 10 | 11 | `detect-pseudoRandomBytes` 12 | 13 | ```javascript 14 | const insecure = crypto.pseudoRandomBytes(5); 15 | ``` 16 | 17 | `detect-non-literal-fs-filename` 18 | 19 | ```javascript 20 | const path = req.body.userinput; 21 | fs.readFile(path); 22 | ``` 23 | 24 | `detect-eval-with-expression` 25 | 26 | ```javascript 27 | const userinput = req.body.userinput; 28 | eval(userinput); 29 | ``` 30 | 31 | `detect-non-literal-regexp` 32 | 33 | ```javascript 34 | const unsafe = new RegExp('/(x+x+)+y/)'); 35 | ``` 36 | 37 | 上記の安全でないコード例を含んだ Node.js プロジェクトにおける `eslint-plugin-security` の実行例: 38 | 39 | ![nsp check example](/assets/images/eslint-plugin-security.png) 40 | 41 | ### 他のブロガーが言っていること 42 | 43 | [Adam Baldwin](https://www.safaribooksonline.com/blog/2014/03/28/using-eslint-plugins-node-js-app-security/) のブログより: 44 | > Linting は、空白やセミコロン、eval 文などの細かいルールを強制するだけのツールではありません。ESLint は、コード内の様々な潜在的に危険なパターン(正規表現、入力値の検証など)を取り除くための強力なフレームワークを提供します。それはセキュリティを意識する JavaScript デベロッパーにとって検討に値する強力なツールを提供してくれると思います。 45 | -------------------------------------------------------------------------------- /sections/security/regex.japanese.md: -------------------------------------------------------------------------------- 1 | # 悪意のある RegEx がシングルスレッド実行をオーバーロードすることを防止する 2 | 3 | ### 一段落説明 4 | 5 | 正規表現の使用に内在するリスクは、テキストを解析して、与えられたパターンにマッチするかどうか確認するために必要な計算リソースです。シングルスレッドのイベントループが支配している Node.js プラットフォームでは、正規表現パターンを解決するような CPU 依存のオペレーションをアプリケーションを応答不能にしてしまいます。 6 | 可能な場合は RegEx の使用を避けるか、[validator.js](https://github.com/chriso/validator.js) のような専用ライブラリに処理を任せるか、あるいは [safe-regex](https://github.com/substack/safe-regex) を利用して RegEx パターンが安全かどうかチェックしてください。 7 | 8 | [OWASP examples](https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS) における、脆弱な RegEx パターンの例: 9 | * (a|aa)+ 10 | * ([a-zA-Z]+)* 11 | 12 |

13 | 14 | ### コード例 – Express フレームワークを利用して SSL/TLS を有効にする 15 | 16 | ```javascript 17 | const saferegex = require('safe-regex'); 18 | const emailRegex = /^([a-zA-Z0-9])(([\-.]|[_]+)?([a-zA-Z0-9]+))*(@){1}[a-z0-9]+[.]{1}(([a-z]{2,3})|([a-z]{2,3}[.]{1}[a-z]{2,3}))$/; 19 | 20 | // emailRegex が ReDoS 攻撃に対して脆弱であるため、false を出力するべき 21 | console.log(saferegex(emailRegex)); 22 | 23 | // 正規表現パターンを利用する代わりに、バリデータを使用してください: 24 | const validator = require('validator'); 25 | console.log(validator.isEmail('liran.tal@gmail.com')); 26 | ``` 27 | 28 |

29 | 30 | ### 書籍引用: "A vulnerable Regular Expression is known as one which applies repetition"(脆弱な正規表現は、繰り返しを適用するものとして知られています) 31 | 32 | Liran Tal による書籍 [Essential Node.js Security](https://leanpub.com/nodejssecurity) より: 33 | > しばしば、プログラマーはユーザーから受け取った値入力が期待する条件に合致しているか検証するために RegEx を使用します。脆弱性のある正規表現は、繰り返されているキャプチャグループに対して繰り返しを適用するものとして知られており、マッチする文字列が、有効なマッチパターンのサフィックスとキャプチャグループにマッチしない文字で構成されています。 34 | -------------------------------------------------------------------------------- /sections/security/safemoduleloading.brazilian-portuguese.md: -------------------------------------------------------------------------------- 1 | # Evite o carregamento de módulos usando uma variável 2 | 3 | ### Explicação em um Parágrafo 4 | 5 | Evite requerir/importar outro arquivo com um caminho que tenha sido fornecido como parâmetro devido à preocupação de que ele possa ter se originado da entrada do usuário. Esta regra pode ser estendida para acessar arquivos em geral (por exemplo, `fs.readFile ()`) ou outros recursos sensíveis com variáveis ​​dinâmicas provenientes da entrada do usuário. 6 | 7 | ### Exemplo de código 8 | 9 | ```javascript 10 | // inseguro, pois a variável helperPath pode ter sido modificada pela entrada do usuário 11 | const uploadHelpers = require(helperPath); 12 | 13 | // seguro 14 | const uploadHelpers = require('./helpers/upload'); 15 | ``` 16 | -------------------------------------------------------------------------------- /sections/security/safemoduleloading.chinese.md: -------------------------------------------------------------------------------- 1 | # 避免使用变量加载模块 2 | 3 | ### 一段解释 4 | 5 | 避免使用被指定为参数的路径变量导入(requiring/importing)另一个文件, 因为该变量可能源自用户输入。此规则可以扩展到一般情况下的访问文件(例如,`fs.readFile()`),或者包含源自用户输入的动态变量的其他敏感资源。 6 | 7 | ### 代码示例 8 | 9 | ```javascript 10 | // 不安全, 因为helperPath变量可能通过用户输入而改变 11 | const uploadHelpers = require(helperPath); 12 | 13 | // 安全 14 | const uploadHelpers = require('./helpers/upload'); 15 | ``` 16 | -------------------------------------------------------------------------------- /sections/security/safemoduleloading.japanese.md: -------------------------------------------------------------------------------- 1 | # 変数を利用してモジュールを読み込むことを避ける 2 | 3 | ### 一段落説明 4 | 5 | ユーザー入力が起因となって問題が生じる恐れがあるため、パラメータとして与えられたパスを用いて他のファイルを require/import しないようにしてください。この原則は、ユーザー入力に基づいた動的な変数を用いた、一般的なファイルアクセス(`fs.readFile()` など)やその他のセンシティブなリソースアクセスにも拡張することができます。 6 | 7 | ### コード例 8 | 9 | ```javascript 10 | // セキュアでない例(変数 helperPath がユーザー入力によって変更される可能性がある) 11 | const badWayToRequireUploadHelpers = require(helperPath); 12 | 13 | // セキュアな例 14 | const uploadHelpers = require("./helpers/upload"); 15 | ``` 16 | -------------------------------------------------------------------------------- /sections/security/safemoduleloading.md: -------------------------------------------------------------------------------- 1 | # Avoid module loading using a variable 2 | 3 | ### One Paragraph Explainer 4 | 5 | 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 resources with dynamic variables originating from user input. 6 | 7 | ### Code example 8 | 9 | ```javascript 10 | // insecure, as helperPath variable may have been modified by user input 11 | const badWayToRequireUploadHelpers = require(helperPath); 12 | 13 | // secure 14 | const uploadHelpers = require('./helpers/upload'); 15 | ``` 16 | -------------------------------------------------------------------------------- /sections/security/safemoduleloading.polish.md: -------------------------------------------------------------------------------- 1 | # Unikaj ładowania modułu za pomocą zmiennej 2 | 3 | ### Wyjaśnienie jednym akapitem 4 | 5 | Unikaj wymagania / importowania innego pliku ze ścieżką podaną jako parametr ze względu na obawy, że mógł on pochodzić z danych wejściowych użytkownika. Regułę tę można rozszerzyć w celu uzyskania ogólnego dostępu do plików (tj. `Fs.readFile()`) lub innych wrażliwych zasobów ze zmiennymi dynamicznymi pochodzącymi z danych wprowadzanych przez użytkownika. 6 | 7 | ### Przykład kodu 8 | 9 | ```javascript 10 | // insecure, as helperPath variable may have been modified by user input 11 | const badWayToRequireUploadHelpers = require(helperPath); 12 | 13 | // secure 14 | const uploadHelpers = require('./helpers/upload'); 15 | ``` 16 | -------------------------------------------------------------------------------- /sections/security/safemoduleloading.russian.md: -------------------------------------------------------------------------------- 1 | # Избегайте загрузки модулей с использованием переменных 2 | 3 | ### Объяснение в один абзац 4 | 5 | Избегайте вызова/импорта другого файла с путем, указанным в качестве параметра, из-за опасений, что он мог возникнуть из-за ввода пользователя. Это правило может быть расширено для доступа к файлам вообще (то есть `fs.readFile()`) или другим чувствительным ресурсам с динамическими переменными, происходящими из пользовательского ввода. 6 | 7 | ### Пример кода 8 | 9 | ```javascript 10 | // insecure, as helperPath variable may have been modified by user input 11 | const badWayToRequireUploadHelpers = require(helperPath); 12 | 13 | // secure 14 | const uploadHelpers = require('./helpers/upload'); 15 | ``` 16 | -------------------------------------------------------------------------------- /sections/security/saferedirects.chinese.md: -------------------------------------------------------------------------------- 1 | # 避免不安全的重定向 2 | 3 | ### 一段解释 4 | 5 | 当我们在 Node.js 或者 Express 中实现重定向时,在服务器端进行输入校验非常重要。当攻击者发现你没有校验用户提供的外部输入时,他们会在论坛、社交媒体以和其他公共场合发布他们精心制作的链接来诱使用户点击,以此达到漏洞利用的目的。 6 | 7 | 案例: express 使用用户输入的不安全的重定向 8 | 9 | ```javascript 10 | const express = require('express'); 11 | const app = express(); 12 | 13 | app.get('/login', (req, res, next) => { 14 | 15 | if (req.session.isAuthenticated()) { 16 | res.redirect(req.query.url); 17 | } 18 | 19 | }); 20 | ``` 21 | 22 | 建议的避免不安全重定向的方案是,避免依赖用户输入的内容来进行重定向。如果一定要使用用户输入的内容,可以通过使用白名单重定向的方式来避免暴露漏洞。 23 | 24 | 案例:使用白名单实现安全的重定向 25 | 26 | ```javascript 27 | const whitelist = { 28 | 'https://google.com': 1 29 | }; 30 | 31 | function getValidRedirect(url) { 32 | // 检查url是否以/开头 33 | if (url.match(/^\/(?!\/)/)) { 34 | // 前置我们的域名来确保(安全) 35 | return 'https://example.com' + url; 36 | } 37 | 38 | // 否则对照白名单列表 39 | return whitelist[url] ? url : '/'; 40 | } 41 | 42 | app.get('/login', (req, res, next) => { 43 | 44 | if (req.session.isAuthenticated()) { 45 | res.redirect(getValidRedirect(req.query.url)); 46 | } 47 | 48 | }); 49 | ``` 50 | 51 | ### 其他博主的看法 52 | 53 | 来自博客[NodeSwat](https://blog.nodeswat.com/unvalidated-redirects-b0a2885720db): 54 | 55 | > 幸运的是,缓解此漏洞的方法非常简单-不要使用未经验证的用户输入作为重定向的基础。 56 | 57 | 来自博客[Hailstone](https://blog.hailstone.io/how-to-prevent-unsafe-redirects-in-node-js/): 58 | 59 | > 但是,如果服务器端的重定向逻辑没有对url参数的数据进行校验的话,则你的用户可能最终访问的地址跟你的地址看起来几乎完全一致(examp1e.com),但这最终满足了犯罪黑客们的需求。 60 | -------------------------------------------------------------------------------- /sections/security/saferedirects.japanese.md: -------------------------------------------------------------------------------- 1 | # 安全でないリダイレクトを防ぐ 2 | 3 | ### 一段落説明 4 | 5 | Node.js、そして Express でリダイレクトを実装する際は、サーバーサイドで入力検証を行うことが重要です。 6 | もし攻撃者が、外部のユーザーから与えられた入力を検証していないことを発見した場合、特別に作成されたリンクをフォーラムやソーシャルメディア、その他のパブリックな場所に投稿してユーザーにクリックさせることで、この脆弱性を悪用する恐れがあります。 7 | 8 | 例: ユーザー入力を利用した、安全でない express リダイレクト 9 | ```javascript 10 | const express = require('express'); 11 | const app = express(); 12 | 13 | app.get('/login', (req, res, next) => { 14 | 15 | if (req.session.isAuthenticated()) { 16 | res.redirect(req.query.url); 17 | } 18 | 19 | }); 20 | ``` 21 | 22 | 安全でないリダイレクトを避けるために推奨される改善方法は、ユーザー入力を信頼しないということです。ユーザー入力を利用する必要がある場合には、脆弱性を晒すことを避けるために、安全なリダイレクトホワイトリストを利用することができます。 23 | 24 | 例: 安全なリダイレクトホワイトリスト 25 | ```javascript 26 | const whitelist = { 27 | 'https://google.com': 1 28 | }; 29 | 30 | function getValidRedirect(url) { 31 | // url がシングルスラッシュで始めっているかチェックする 32 | if (url.match(/^\/(?!\/)/)) { 33 | // 正しくドメインを付加する 34 | return 'https://example.com' + url; 35 | } 36 | // または、ホワイトリストでチェックする 37 | return whitelist[url] ? url : '/'; 38 | } 39 | 40 | app.get('/login', (req, res, next) => { 41 | 42 | if (req.session.isAuthenticated()) { 43 | res.redirect(getValidRedirect(req.query.url)); 44 | } 45 | 46 | }); 47 | ``` 48 | 49 | 50 | ### 他のブロガーが言っていること 51 | 52 | [NodeSwat](https://blog.nodeswat.com/unvalidated-redirects-b0a2885720db) のブログより: 53 | > 幸いなことに、この脆弱性に対する緩和策は非常にシンプルです - 検証されていないユーザー入力を、リダイレクトのための基準として扱わないことです。 54 | 55 | [Hailstone](https://blog.hailstone.io/how-to-prevent-unsafe-redirects-in-node-js/) のブログより: 56 | > しかし、もしサーバーサイドのリダイレクトロジックが url パラメータを入力するデータを検証しない場合、ユーザーはまるであなたのサイトのように見える(examp1e.com)にたどり着き、犯罪者ハッカーの要求を満たす結果となりかねません。 57 | 58 | 59 | -------------------------------------------------------------------------------- /sections/security/sandbox.chinese.md: -------------------------------------------------------------------------------- 1 | # 在沙箱中运行不安全的代码 2 | 3 | ### 一段解释 4 | 5 | 根据经验, 应该只运行自己的javascript文件。撇开理论不谈, 现实世界中的场景需要执行在运行时动态传递的javascript文件。例如, 考虑一个动态框架(如 webpack), 该框架接受自定义加载器(custom loaders), 并在构建时动态执行这些加载器。在存在一些恶意插件的情况下, 我们希望最大限度地减少损害, 甚至可能让工作流成功终止 - 这需要在一个沙箱环境中运行插件, 该环境在资源、宕机和我们共享的信息方面是完全隔离的。三个主要选项可以帮助实现这种隔离: 6 | 7 | - 一个专门的子进程 - 这提供了一个快速的信息隔离, 但要求制约子进程, 限制其执行时间, 并从错误中恢复 8 | - 一个基于云的无服务框架满足所有沙盒要求,但动态部署和调用Faas方法不是本部分的内容 9 | - 一些npm库,比如[sandbox](https://www.npmjs.com/package/sandbox)和[vm2](https://www.npmjs.com/package/vm2)允许通过一行代码执行隔离代码。尽管后一种选择在简单中获胜, 但它提供了有限的保护。 10 | 11 | ### 代码示例 - 使用Sandbox库运行隔离代码 12 | 13 | ```javascript 14 | const Sandbox = require("sandbox"); 15 | const s = new Sandbox(); 16 | 17 | s.run( "lol)hai", function( output ) { 18 | console.log(output); 19 | //output='Syntax error' 20 | }); 21 | 22 | // Example 4 - Restricted code 23 | s.run( "process.platform", function( output ) { 24 | console.log(output); 25 | //output=Null 26 | }) 27 | 28 | // Example 5 - Infinite loop 29 | s.run( "while (true) {}", function( output ) { 30 | console.log(output); 31 | //output='Timeout' 32 | }) 33 | ``` 34 | -------------------------------------------------------------------------------- /sections/security/sandbox.japanese.md: -------------------------------------------------------------------------------- 1 | # サンドボックス内で安全でないコードを実行する 2 | 3 | ### 一段落説明 4 | 5 | 経験則として、すべての人は自分自身が管理する JavaScript ファイルのみを実行するべきです。セオリーはさておき、現実世界では実行時に動的に渡される JavaScript ファイルを実行する必要があります。例えば、webpack のような、ビルド時にカスタムローダーを動的に実行する動的なフレームワークを考えてみましょう。悪意のあるプラグインが存在する場合、被害を最小限に抑え、フローを正常に終了させたいと願うでしょう - これを実現するには、そういったプラグインを、リソース、クラッシュ、共有する情報の観点において、完全に隔離されたサンドボックス環境で実行する必要があります。この隔離を実現するには、以下の3つの主要なオプションがあります。 6 | 7 | - 専用の子プロセス - これは迅速な情報の隔離を提供しますが、子プロセスを管理し、実行時間を制限し、そしてエラーから復帰させる必要があります 8 | - クラウドのサーバーレス環境は、サンドボックスの要件をすべて満たしていますが、デプロイと FaaS 機能の動的な呼び出しは簡単ではありません 9 | - [sandbox](https://www.npmjs.com/package/sandbox) や [vm2](https://www.npmjs.com/package/vm2) といったいくつかの npm ライブラリは、たった1行で隔離されたコード実行を可能にします。このオプションはシンプルさにおいては優位ですが、保護範囲が限られています。 10 | 11 | ### コード例 - 独立した状態でコードを実行するために sandbox ライブラリを使用する 12 | 13 | ```javascript 14 | const Sandbox = require('sandbox'); 15 | const s = new Sandbox(); 16 | 17 | s.run('lol)hai', (output) => { 18 | console.log(output); 19 | //output='Syntax error' 20 | }); 21 | 22 | // 例 4 - 制限されたコード 23 | s.run('process.platform', (output) => { 24 | console.log(output); 25 | //output=Null 26 | }); 27 | 28 | // 例 5 - 無限ループ 29 | s.run('while (true) {}', (output) => { 30 | console.log(output); 31 | //output='Timeout' 32 | }); 33 | ``` 34 | -------------------------------------------------------------------------------- /sections/security/secretmanagement.japanese.md: -------------------------------------------------------------------------------- 1 | # 設定ファイルからシークレットを抽出する、もしくはパッケージを利用して暗号化する 2 | 3 | ### 一段落説明 4 | 5 | Node.js アプリケーションにキーやシークレットを渡すための最も一般的で安全な方法は、実行環境における環境変数にそれらの値を格納することです。環境変数に設定することで、それらの値にグローバルオブジェクトである `process.env` オブジェクトからアクセスできるようになります。 6 | アプリケーションが全ての設定をコードから正しく抽出できているかどうかのリトマステストとしては、クレデンシャルを晒すことなくコードをいつでもオープンソースにすることができるかどうか、というものがあります。 7 | 8 | シークレットをソースコントロールの中に格納しなければならない稀な状況の場合においては、[cryptr](https://www.npmjs.com/package/cryptr) のようなパッケージを使用することで、平文ではなく暗号化された形で保存することができます。 9 | 10 | [git-secrets](https://github.com/awslabs/git-secrets) のように、git commit においてコミットやコミットメッセージを監査して、誤ってシークレットを追加されていないかをチェックするツールが多く存在します。 11 | 12 | ### コード例 13 | 14 | 環境変数に格納された API キーにアクセスする: 15 | 16 | ```javascript 17 | const azure = require('azure'); 18 | 19 | const apiKey = process.env.AZURE_STORAGE_KEY; 20 | const blobService = azure.createBlobService(apiKey); 21 | ``` 22 | 23 | `cryptr` を死傷して暗号化されたシークレットを保存する: 24 | 25 | ```javascript 26 | const Cryptr = require('cryptr'); 27 | const cryptr = new Cryptr(process.env.SECRET); 28 | 29 | let accessToken = cryptr.decrypt('e74d7c0de21e72aaffc8f2eef2bdb7c1'); 30 | 31 | console.log(accessToken); // ソースコントロールに保存されていない、復号化された文字列を出力します 32 | ``` 33 | 34 | ### 他のブロガーが言っていること 35 | 36 | > 環境変数は、コードを変更することなくデプロイごとに簡単に変更できる。設定ファイルとは異なり、誤ってリポジトリにチェックインされる可能性はほとんどない。また、独自形式の設定ファイルや Java System Properties など他の設定の仕組みとは異なり、環境変数は言語や OS に依存しない標準である。[The 12 factor app より](https://12factor.net/ja/config) 37 | -------------------------------------------------------------------------------- /sections/security/secureserver.brazilian-portuguese.md: -------------------------------------------------------------------------------- 1 | # Usando HTTPS para criptografar a conexão cliente-servidor 2 | 3 |

4 | 5 | 6 | ### Explicação em um Parágrafo 7 | 8 | Usar serviços como [Let'sEncrypt](https://letsencrypt.org/), uma autoridade certificadora que fornece certificados SSL/TLS __gratuitos__, pode ajudar a criptografar a comunicação de suas aplicações. Frameworks Node.js como [Express](http://expressjs.com/) (baseado no módulo central `https`) suportam SSL/TLS, o qual pode ser implementado em poucas linhas de código. 9 | 10 | Você também pode configurar SSL/TLS em um proxy reverso, como [NGINX](http://nginx.org/en/docs/http/configuring_https_servers.html) ou HAProxy. 11 | 12 |

13 | 14 | ### Exemplo de código - Ativando SSL/TLS usando o framework Express 15 | 16 | ```javascript 17 | const express = require('express'); 18 | const https = require('https'); 19 | const app = express(); 20 | const options = { 21 | // O caminho deve ser alterado de acordo com sua configuração 22 | cert: fs.readFileSync('./sslcert/fullchain.pem'), 23 | key: fs.readFileSync('./sslcert/privkey.pem') 24 | }; 25 | https.createServer(options, app).listen(443); 26 | ``` 27 | 28 |

29 | -------------------------------------------------------------------------------- /sections/security/secureserver.chinese.md: -------------------------------------------------------------------------------- 1 | # 使用https加密客户端-服务器连接 2 | 3 |

4 | 5 | 6 | ### 一段解释 7 | 8 | 使用服务,比如[Let'sEncrypt](https://letsencrypt.org/)证书颁发机构提供 __free__ ssl/tls证书,您可以轻松地获得证书, 以确保您的应用程序安全。Node.js框架,比如[Express](http://expressjs.com/)(基于核心`https`模块) 轻松支持基于ssl/tls的服务,此外, 配置可以通过几行额外的代码完成。 9 | 10 | 您还可以在指向应用程序的反向代理上配置ssl/tls,例如使用[nginx](http://nginx.org/en/docs/http/configuring_https_servers.html)或者HAProxy. 11 | 12 |

13 | 14 | ### 代码示例 – 使用express框架启用SSL/TLS 15 | 16 | ```javascript 17 | const express = require('express'); 18 | const https = require('https'); 19 | const app = express(); 20 | const options = { 21 | // 路径应根据您的设置进行相应的更改 22 | cert: fs.readFileSync('./sslcert/fullchain.pem'), 23 | key: fs.readFileSync('./sslcert/privkey.pem') 24 | }; 25 | https.createServer(options, app).listen(443); 26 | ``` 27 | 28 |

29 | -------------------------------------------------------------------------------- /sections/security/secureserver.japanese.md: -------------------------------------------------------------------------------- 1 | # クライアント/サーバー間の通信を暗号化するために SSL/TLS を使用する 2 | 3 |

4 | 5 | 6 | ### 一段落説明 7 | 8 | [Let'sEncrypt](https://letsencrypt.org/) のような、無料で証明書を発行してくれるサービスを利用することで、アプリケーションの通信を暗号化することができます。[Express](http://expressjs.com/) のような Node.js フレームワーク(`https`コアモジュールをベースにしている)は SSL/TLS をサポートしており、数行のコードで実装することができます。 9 | 10 | また、[NGINX](http://nginx.org/en/docs/http/configuring_https_servers.html) や HAProxy のようなリバースプロキシを用いて SSL/TLS 化することもできます。 11 | 12 |

13 | 14 | ### コード例 – Express を使用して SSL/TLS を有効化する 15 | 16 | ```javascript 17 | const express = require('express'); 18 | const https = require('https'); 19 | const app = express(); 20 | const options = { 21 | // ファイルのパスは環境によって異なります 22 | cert: fs.readFileSync('./sslcert/fullchain.pem'), 23 | key: fs.readFileSync('./sslcert/privkey.pem') 24 | }; 25 | https.createServer(options, app).listen(443); 26 | ``` 27 | 28 |

29 | -------------------------------------------------------------------------------- /sections/security/secureserver.md: -------------------------------------------------------------------------------- 1 | # Using HTTPS to encrypt the client-server connection 2 | 3 |

4 | 5 | 6 | ### One Paragraph Explainer 7 | 8 | Using services such as [Let'sEncrypt](https://letsencrypt.org/), a certificate authority which provides __free__ SSL/TLS certificates, can help encrypt the communication of your applications. Node.js frameworks like [Express](http://expressjs.com/) (based on the core `https` module) support SSL/TLS, which can be implemented in a few lines of code. 9 | 10 | You can also configure SSL/TLS on a reverse proxy, such as [NGINX](http://nginx.org/en/docs/http/configuring_https_servers.html) or HAProxy. 11 | 12 |

13 | 14 | ### Code Example – Enabling SSL/TLS using the Express framework 15 | 16 | ```javascript 17 | const express = require('express'); 18 | const https = require('https'); 19 | const app = express(); 20 | const options = { 21 | // The path should be changed accordingly to your setup 22 | cert: fs.readFileSync('./sslcert/fullchain.pem'), 23 | key: fs.readFileSync('./sslcert/privkey.pem') 24 | }; 25 | https.createServer(options, app).listen(443); 26 | ``` 27 | 28 |

29 | -------------------------------------------------------------------------------- /sections/security/secureserver.russian.md: -------------------------------------------------------------------------------- 1 | # Используйте HTTPS для шифрования соединения клиент-сервер 2 | 3 |

4 | 5 | 6 | ### Объяснение в один абзац 7 | 8 | Использование таких служб, как [Let'sEncrypt](https://letsencrypt.org/), центр сертификации, который предоставляет __free__ сертификаты SSL/TLS, может помочь зашифровать связь ваших приложений. Среды Node.js, такие как [Express](http://expressjs.com/) (основанные на модуле `https`), поддерживают SSL/TLS, который может быть реализован в несколько строк кода. 9 | 10 | Вы также можете настроить SSL/TLS на обратном прокси, например [NGINX] (http://nginx.org/en/docs/http/configuring_https_servers.html) или HAProxy. 11 | 12 |

13 | 14 | ### Пример кода - Включение SSL/TLS с использованием платформы Express 15 | 16 | ```javascript 17 | const express = require('express'); 18 | const https = require('https'); 19 | const app = express(); 20 | const options = { 21 | // The path should be changed accordingly to your setup 22 | cert: fs.readFileSync('./sslcert/fullchain.pem'), 23 | key: fs.readFileSync('./sslcert/privkey.pem') 24 | }; 25 | https.createServer(options, app).listen(443); 26 | ``` 27 | 28 |

29 | -------------------------------------------------------------------------------- /sections/security/sessions.japanese.md: -------------------------------------------------------------------------------- 1 | # セッションミドルウェアの設定を変更する 2 | 3 |

4 | 5 | 6 | ### 一段落説明 7 | 8 | 多くの有名なセッションミドルウェアは、そのまま利用できるような、ベストプラクティス/セキュア Cookie 設定を適用していません。これらの設定をデフォルト値から調整することによって、セッションハイジャックやセッション識別のような攻撃の脅威を減らし、ユーザーとアプリケーションの両方により安全な保護を提供します。 9 | 10 | デフォルト値のままになっている最も一般的な設定は、セッション名 `name` です - `express-session` では、`connect.sid` に値します。攻撃者はこの情報を利用して背後にある Web アプリケーションフレームワークや、モジュール固有の脆弱性を特定する可能性があります。この値を他の値に変更することで、どんなセッション機構が利用されているかの特定を難しくします。 11 | 12 | また `express-session` では、`cookie.secure` オプションがデフォルトで false に指定されています。この値を true に変更することで、Cookie の送信を https のみに制限し、中間者攻撃からの保護を提供します。 13 | 14 |

15 | 16 | 17 | ### コード例: 安全な Cookie の設定を行う 18 | 19 | ```javascript 20 | // express セッションミドルウェアを使用する 21 | app.use(session({ 22 | secret: 'youruniquesecret', // cookie に格納されるセッション ID に署名するために利用されるシークレット文字列 23 | name: 'youruniquename', // デフォルトの connect.sid を取り除くために、ユニークな名前をセットする 24 | cookie: { 25 | httpOnly: true, // クライアントの cookie 読み取りを制限することで、XSS 攻撃のリスクを最小化する 26 | secure: true, // https でのみ cookie を送信する 27 | maxAge: 60000*60*24 // cookie の有効期限を ms で指定する 28 | } 29 | })); 30 | ``` 31 | 32 |

33 | 34 | ### 他のブロガーが言っていること 35 | 36 | [NodeSource blog](http://nodesource.com/blog/nine-security-tips-to-keep-express-from-getting-pwned/) より: 37 | > ...Express にはデフォルトの cookie 設定がありますが、これはあまり安全ではありません。この設定は、アプリケーションとユーザーの両方にとってのセキュリティを強化するために、手動で厳しくすることができます。 38 | 39 |

40 | -------------------------------------------------------------------------------- /sections/template.basque.md: -------------------------------------------------------------------------------- 1 | # Izenburua hemen 2 | 3 |

4 | 5 | ### Azalpen paragrafo bat 6 | 7 | Testua 8 | 9 |

10 | 11 | ### Kode Adibidea: azalpena 12 | 13 | ```javascript 14 | kodea hemen 15 | ``` 16 | 17 |

18 | 19 | ### Kode Adibidea: beste azalpen bat 20 | 21 | ```javascript 22 | kodea hemen 23 | ``` 24 | 25 |

26 | 27 | ### Blogeko aipua: "Izenburua" 28 | 29 | Blogean, pouchdb.comek “Node Promesak hitz gakoarentzat 11.posizioa du 30 | 31 | > …testua hemen 32 | 33 |

34 | 35 | ### Adibidea: CodeClimaterekin funtzio konplexuen analisia (iragarkia) 36 | 37 | ![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/codeanalysis-climate-complex-methods.PNG "Funtzio konplexuen analisia") 38 | 39 | ### Adibidea: CodeClimaterekin kode analisi joerak eta historia (iragarkia) 40 | 41 | ![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/codeanalysis-climate-history.PNG "Kode analisiaren historia") 42 | 43 | ### Adibidea: SonarQuberekin kode analisiaren laburpena eta joerak (iragarkia) 44 | 45 | ![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/codeanalysis-sonarqube-dashboard.PNG "Kode analisiaren historia") 46 | 47 |

48 | -------------------------------------------------------------------------------- /sections/template.md: -------------------------------------------------------------------------------- 1 | # Title here 2 | 3 |

4 | 5 | ### One Paragraph Explainer 6 | 7 | Text 8 | 9 |

10 | 11 | ### Code Example – explanation 12 | 13 | ```javascript 14 | code here 15 | ``` 16 | 17 |

18 | 19 | ### Code Example – another 20 | 21 | ```javascript 22 | code here 23 | ``` 24 | 25 |

26 | 27 | ### Blog Quote: "Title" 28 | 29 | From the blog, pouchdb.com ranked 11 for the keywords “Node Promises” 30 | 31 | > …text here 32 | 33 |

34 | 35 | ### Example: Complex methods analysis with CodeClimate (commercial) 36 | 37 | ![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/codeanalysis-climate-complex-methods.PNG "Complex methods analysis") 38 | 39 | ### Example: Code analysis trends and history with CodeClimate (commercial) 40 | 41 | ![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/codeanalysis-climate-history.PNG "Code analysis history") 42 | 43 | ### Example: Code analysis summary and trends with SonarQube (commercial) 44 | 45 | ![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/codeanalysis-sonarqube-dashboard.PNG "Code analysis history") 46 | 47 | 48 |

49 | -------------------------------------------------------------------------------- /sections/testingandquality/bumpversion.japanese.md: -------------------------------------------------------------------------------- 1 | # Title here 2 | 3 | ### One Paragraph Explainer 4 | 5 | Text 6 | 7 | ### Code Example – explanation 8 | 9 | ```javascript 10 | code here 11 | ``` 12 | 13 | ### Code Example – another 14 | 15 | ```javascript 16 | code here 17 | ``` 18 | 19 | ### Blog Quote: "Title" 20 | 21 | From the blog, pouchdb.com ranked 11 for the keywords “Node Promises” 22 | 23 | > …text here 24 | 25 | ### Image title 26 | 27 | ![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/swaggerDoc.png "API error handling") 28 | -------------------------------------------------------------------------------- /sections/testingandquality/bumpversion.md: -------------------------------------------------------------------------------- 1 | # Title here 2 | 3 | ### One Paragraph Explainer 4 | 5 | Text 6 | 7 | ### Code Example – explanation 8 | 9 | ```javascript 10 | code here 11 | ``` 12 | 13 | ### Code Example – another 14 | 15 | ```javascript 16 | code here 17 | ``` 18 | 19 | ### Blog Quote: "Title" 20 | 21 | From the blog, pouchdb.com ranked 11 for the keywords “Node Promises” 22 | 23 | > …text here 24 | 25 | ### Image title 26 | 27 | ![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/swaggerDoc.png "API error handling") 28 | -------------------------------------------------------------------------------- /sections/testingandquality/citools.chinese.md: -------------------------------------------------------------------------------- 1 | # 仔细挑选您的 CI 平台 2 | 3 |

4 | 5 | 6 | ### 一段解释 7 | 8 | 曾经,CI世界就是易于扩展的[Jenkins](https://jenkins.io/) vs 简单方便的SaaS方案。游戏正在改变,比如SaaS提供者[CircleCI](https://circleci.com/)和[Travis](https://travis-ci.org/)提供了强大的解决方案,包含最小化设置时间的Docker容器,而Jenkins也尝试在简单易用性上做文字而提高竞争性。虽然您可以在云上设置丰富的CI解决方案, 如果它需要控制更多的细节Jenkins仍然是选择的平台。最终的选择归结为CI过程自定义的范围: 免安装,方便设置的云供应商允许运行自定义shell命令、自定义的docker image、调整工作流、运行matrix build和其他丰富的功能。但是, 如果使用像Java这样的正式编程语言来控制基础结构或编程CI逻辑 - Jenkins可能仍然是首选。否则, 考虑选择简单方便和设置自由的云选项。 9 | 10 |

11 | 12 | 13 | ### 代码示例 – 典型的云CI配置,一个yml文件就够了 14 | ```javascript 15 | version: 2 16 | jobs: 17 | build: 18 | docker: 19 | - image: circleci/node:4.8.2 20 | - image: mongo:3.4.4 21 | steps: 22 | - checkout 23 | - run: 24 | name: Install npm wee 25 | command: npm install 26 | test: 27 | docker: 28 | - image: circleci/node:4.8.2 29 | - image: mongo:3.4.4 30 | steps: 31 | - checkout 32 | - run: 33 | name: Test 34 | command: npm test 35 | - run: 36 | name: Generate code coverage 37 | command: './node_modules/.bin/nyc report --reporter=text-lcov' 38 | - store_artifacts: 39 | path: coverage 40 | prefix: coverage 41 | 42 | ``` 43 | 44 | 45 | 46 | ### Circle CI - 几乎零设置的云CI 47 | ![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/circleci.png "API error handling") 48 | 49 | ### Jenkins - 完善和强大的CI 50 | ![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/jenkins_dashboard.png "API error handling") 51 | 52 | 53 |

54 | -------------------------------------------------------------------------------- /sections/testingandquality/refactoring.japanese.md: -------------------------------------------------------------------------------- 1 | # リファクタリング 2 | 3 |

4 | 5 | ### 一段落説明 6 | 7 | リファクタリングは反復開発フローにおいて重要なプロセスです。重複したコード、長いメソッド、長いパラメータリストといった「コードの臭い」(悪いコーディングプラクティス)を取り除くことで、コードが改善し、保守性が向上します。静的解析ツールを使用することは、そういったコードの臭いを発見しリファクタリングを中心としたプロセスを構築するのに役立ちます。こういったツールを CI に導入することで、品質チェックプロセスを自動化することができます。CI が Sonar や Code Climate といったツールと統合されている場合、コードの臭いを検出した際にビルドを失敗させ、作者に問題の対処方法を知らせます。これらの静的解析ツールは、ESLint のような lint ツールを補うものです。多くの linting ツールは、単一ファイルにおけるインデントやセミコロンの付け忘れ(長い関数のようなコードの臭いを見つけるものもありますが)といったコードスタイルにフォーカスしますが、静的解析ツールは単一のファイルおよび複数のファイルにおいてコードの臭いを発見する(重複したコード、複雑性解析など)ことにフォーカスしています。 8 | 9 |

10 | 11 | 12 | ### Martin Fowler - ThoughtWorks 社のチーフサイエンティスト 13 | 14 | 書籍 "Refactoring - Improving the Design of Existing Code" より 15 | 16 | > リファクタリングは、既存のコードベースの設計を改善するための、制御された技術です。 17 | 18 |

19 | 20 | ### Evan Burchard - Web 開発コンサルタント、作家 21 | 22 | 書籍 "Refactoring JavaScript: Turning Bad Code into Good Code" より 23 | 24 | > どのようなフレームワークや「JS にコンパイル可能な」言語、ライブラリを使用しようとも、JavaScript の根本的な質が低ければ、バグやパフォーマンスの懸念は常に問題になります。 25 | 26 |

27 | 28 | ### 例: CodeClimate を使用した複雑なメソッドの解析(商用) 29 | 30 | ![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/codeanalysis-climate-complex-methods.PNG "複雑なメソッドの解析") 31 | 32 | ### 例: CodeClimate を使用したコード解析結果の傾向と履歴(商用) 33 | 34 | ![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/codeanalysis-climate-history.PNG "コード解析の履歴") 35 | 36 | ### 例: コード解析結果のサマリーと傾向(商用) 37 | 38 | ![alt text](https://github.com/goldbergyoni/nodebestpractices/blob/master/assets/images/codeanalysis-sonarqube-dashboard.PNG "コード解析結果のサマリーと傾向") 39 | 40 | 41 |

42 | -------------------------------------------------------------------------------- /sections/testingandquality/test-middlewares.basque.md: -------------------------------------------------------------------------------- 1 | # Probatu zure middlewareak eurak bakarrik 2 | 3 |

4 | 5 | ### Azalpen paragrafoa 6 | 7 | Askok middlewarearen probak alde batera uzten dituzte sistemaren zati txiki bat adierazten dutelako eta zuzeneko Express zerbitzaria edukitzea behar dutelako. Bi arrazoi horiek okerrak dira: middlewareak txikiak dira, baina eskaera guztiei edo gehienei eragiten diete, eta erraz probatu daitezke {req,res} JS objektuak berreskuratzen dituzten funtzio huts gisa. Middleware funtzioak probatzeko, norberak funtzioa deitu behar du eta {req,res} objektuekin dagoen elkarrekintza espiatu (spy) ([erabili Sinon adibide gisa](https://www.npmjs.com/package/sinon)), funtzioak ekintza zuzena egin duela ziurtatzeko. [node-mock-http](https://www.npmjs.com/package/node-mocks-http) liburutegia oraindik ere urrutiago doa eta {req,res} objektuak faktorizatzen ditu beraien jokaera espiatuz. Adibidez, res objektuan zehaztutako http estatus bat espero den balioarekin bat datorren baiezta dezake (ikusi beheko adibidea) 8 | 9 | 10 |

11 | 12 | ### Kode adibidea: probatu zure middlewarea bera bakarrik 13 | 14 | ```javascript 15 | //probatu nahi dugun middlewarea 16 | const probapeanDagoenUnitatea = require("./middleware"); 17 | const httpMocks = require("node-mocks-http"); 18 | //Jest sintaxisa, Mochako describe() eta it()en baliokidea 19 | test("Autentikazio goiburu gabeko eskaera, 403 http estatus bat bueltatu beharko luke", () => { 20 | const request = httpMocks.createRequest({ 21 | method: "GET", 22 | url: "/user/42", 23 | headers: { 24 | authentication: "" 25 | } 26 | }); 27 | const erantzuna = httpMocks.createResponse(); 28 | probapeanDagoenUnitatea(request, response); 29 | expect(erantzuna.statusCode).toBe(403); 30 | }); 31 | ``` 32 | -------------------------------------------------------------------------------- /sections/testingandquality/test-middlewares.japanese.md: -------------------------------------------------------------------------------- 1 | # ミドルウェアを分離してテストする 2 | 3 |

4 | 5 | ### 一段落説明 6 | 7 | ミドルウェアはシステムのごく一部であり、Express を起動させる必要があるため、多くの人はミドルウェアのテストを避けます。しかし、どちらの理由も間違っています ー ミドルウェアは小さいですが、すべて、あるいはほとんどのリクエストに影響を及ぼすものであり、`{req, res}` という JS オブジェクトを取得する純粋な関数として簡単にテストできます。ミドルウェア関数をテストするためには、その関数を呼び出して、関数が正しく動作していることを確認するために、{req, res} オブジェクトとのやり取りを([例えば Sinon を使用して](https://www.npmjs.com/package/sinon))スパイするべきです。[node-mock-http](https://www.npmjs.com/package/node-mocks-http) というライブラリは、これをさらに発展させ、{req, res} オブジェクトの動作をスパイしながら、そのオブジェクトに要素付けします。例えば、res オブジェクトに設定された http ステータスが期待値と一致しているかどうかを判定することができます(下記の例を参照してください)。 8 | 9 |

10 | 11 | ### コード例: ミドルウェアを分離してテストする 12 | 13 | ```javascript 14 | // テストしたいミドルウェア 15 | const unitUnderTest = require("./middleware"); 16 | const httpMocks = require("node-mocks-http"); 17 | // Jest シンタックス、Mocha における describe() と it() と同様 18 | test("A request without authentication header, should return http status 403", () => { 19 | const request = httpMocks.createRequest({ 20 | method: "GET", 21 | url: "/user/42", 22 | headers: { 23 | authentication: "" 24 | } 25 | }); 26 | const response = httpMocks.createResponse(); 27 | unitUnderTest(request, response); 28 | expect(response.statusCode).toBe(403); 29 | }); 30 | ``` 31 | -------------------------------------------------------------------------------- /sections/testingandquality/test-middlewares.md: -------------------------------------------------------------------------------- 1 | # Test your middlewares in isolation 2 | 3 |

4 | 5 | ### One Paragraph Explainer 6 | 7 | Many avoid Middleware testing because they represent a small portion of the system and require a live Express server. Both reasons are wrong — Middlewares are small but affect all or most of the requests and can be tested easily as pure functions that get `{req,res}` JS objects. To test a middleware function one should just invoke it and spy ([using Sinon for example](https://www.npmjs.com/package/sinon)) on the interaction with the {req,res} objects to ensure the function performed the right action. The library [node-mock-http](https://www.npmjs.com/package/node-mocks-http) takes it even further and factors the {req,res} objects along with spying on their behavior. For example, it can assert whether the http status that was set on the res object matches the expectation (See example below) 8 | 9 |

10 | 11 | ### Code example: Testing middleware in isolation 12 | 13 | ```javascript 14 | //the middleware we want to test 15 | const unitUnderTest = require("./middleware"); 16 | const httpMocks = require("node-mocks-http"); 17 | //Jest syntax, equivalent to describe() & it() in Mocha 18 | test("A request without authentication header, should return http status 403", () => { 19 | const request = httpMocks.createRequest({ 20 | method: "GET", 21 | url: "/user/42", 22 | headers: { 23 | authentication: "" 24 | } 25 | }); 26 | const response = httpMocks.createResponse(); 27 | unitUnderTest(request, response); 28 | expect(response.statusCode).toBe(403); 29 | }); 30 | ``` 31 | --------------------------------------------------------------------------------