├── .travis.yml ├── .gitignore ├── img ├── js.png ├── npm.png ├── pm2.png ├── chai.png ├── eslint.png ├── flow.png ├── jest.png ├── mocha.png ├── react.png ├── redux.png ├── yarn.png ├── webpack.png ├── flow-padded.png ├── jest-padded.png ├── js-padded.png ├── pm2-padded.png ├── yarn-padded.png ├── eslint-padded.png ├── pm2-padded-90.png ├── react-padded.png ├── react-router.png ├── redux-padded.png ├── bootstrap-padded.png ├── eslint-padded-90.png ├── flow-padded-90.png ├── jest-padded-90.png ├── react-padded-90.png ├── redux-padded-90.png ├── webpack-padded.png ├── yarn-padded-90.png ├── webpack-padded-90.png ├── bootstrap-padded-90.png ├── react-router-padded.png └── react-router-padded-90.png ├── package.json ├── .github └── ISSUE_TEMPLATE ├── mdlint.js ├── LICENSE.md ├── CHANGELOG.md ├── Definitions.md ├── how-to-translate.md ├── yarn.lock ├── README.md └── tutorial ├── 09-travis-coveralls-heroku.md ├── 07-socket-io.md ├── 01-node-yarn-package-json.md ├── 01-node-yarn-package-json_ru.md ├── 03-express-nodemon-pm2.md ├── 03-express-nodemon-pm2_ru.md ├── 04-webpack-react-hmr.md ├── 04-webpack-react-hmr_ru.md ├── 08-bootstrap-jss.md ├── 02-babel-es6-eslint-flow-jest-husky.md ├── 06-react-router-ssr-helmet.md ├── 06-react-router-ssr-helmet_ru.md └── 05-redux-immutable-fetch.md /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: node 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | npm-debug.log 3 | node_modules 4 | 5 | -------------------------------------------------------------------------------- /img/js.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usulpro/js-stack-from-scratch/HEAD/img/js.png -------------------------------------------------------------------------------- /img/npm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usulpro/js-stack-from-scratch/HEAD/img/npm.png -------------------------------------------------------------------------------- /img/pm2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usulpro/js-stack-from-scratch/HEAD/img/pm2.png -------------------------------------------------------------------------------- /img/chai.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usulpro/js-stack-from-scratch/HEAD/img/chai.png -------------------------------------------------------------------------------- /img/eslint.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usulpro/js-stack-from-scratch/HEAD/img/eslint.png -------------------------------------------------------------------------------- /img/flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usulpro/js-stack-from-scratch/HEAD/img/flow.png -------------------------------------------------------------------------------- /img/jest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usulpro/js-stack-from-scratch/HEAD/img/jest.png -------------------------------------------------------------------------------- /img/mocha.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usulpro/js-stack-from-scratch/HEAD/img/mocha.png -------------------------------------------------------------------------------- /img/react.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usulpro/js-stack-from-scratch/HEAD/img/react.png -------------------------------------------------------------------------------- /img/redux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usulpro/js-stack-from-scratch/HEAD/img/redux.png -------------------------------------------------------------------------------- /img/yarn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usulpro/js-stack-from-scratch/HEAD/img/yarn.png -------------------------------------------------------------------------------- /img/webpack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usulpro/js-stack-from-scratch/HEAD/img/webpack.png -------------------------------------------------------------------------------- /img/flow-padded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usulpro/js-stack-from-scratch/HEAD/img/flow-padded.png -------------------------------------------------------------------------------- /img/jest-padded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usulpro/js-stack-from-scratch/HEAD/img/jest-padded.png -------------------------------------------------------------------------------- /img/js-padded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usulpro/js-stack-from-scratch/HEAD/img/js-padded.png -------------------------------------------------------------------------------- /img/pm2-padded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usulpro/js-stack-from-scratch/HEAD/img/pm2-padded.png -------------------------------------------------------------------------------- /img/yarn-padded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usulpro/js-stack-from-scratch/HEAD/img/yarn-padded.png -------------------------------------------------------------------------------- /img/eslint-padded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usulpro/js-stack-from-scratch/HEAD/img/eslint-padded.png -------------------------------------------------------------------------------- /img/pm2-padded-90.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usulpro/js-stack-from-scratch/HEAD/img/pm2-padded-90.png -------------------------------------------------------------------------------- /img/react-padded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usulpro/js-stack-from-scratch/HEAD/img/react-padded.png -------------------------------------------------------------------------------- /img/react-router.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usulpro/js-stack-from-scratch/HEAD/img/react-router.png -------------------------------------------------------------------------------- /img/redux-padded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usulpro/js-stack-from-scratch/HEAD/img/redux-padded.png -------------------------------------------------------------------------------- /img/bootstrap-padded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usulpro/js-stack-from-scratch/HEAD/img/bootstrap-padded.png -------------------------------------------------------------------------------- /img/eslint-padded-90.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usulpro/js-stack-from-scratch/HEAD/img/eslint-padded-90.png -------------------------------------------------------------------------------- /img/flow-padded-90.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usulpro/js-stack-from-scratch/HEAD/img/flow-padded-90.png -------------------------------------------------------------------------------- /img/jest-padded-90.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usulpro/js-stack-from-scratch/HEAD/img/jest-padded-90.png -------------------------------------------------------------------------------- /img/react-padded-90.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usulpro/js-stack-from-scratch/HEAD/img/react-padded-90.png -------------------------------------------------------------------------------- /img/redux-padded-90.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usulpro/js-stack-from-scratch/HEAD/img/redux-padded-90.png -------------------------------------------------------------------------------- /img/webpack-padded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usulpro/js-stack-from-scratch/HEAD/img/webpack-padded.png -------------------------------------------------------------------------------- /img/yarn-padded-90.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usulpro/js-stack-from-scratch/HEAD/img/yarn-padded-90.png -------------------------------------------------------------------------------- /img/webpack-padded-90.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usulpro/js-stack-from-scratch/HEAD/img/webpack-padded-90.png -------------------------------------------------------------------------------- /img/bootstrap-padded-90.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usulpro/js-stack-from-scratch/HEAD/img/bootstrap-padded-90.png -------------------------------------------------------------------------------- /img/react-router-padded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usulpro/js-stack-from-scratch/HEAD/img/react-router-padded.png -------------------------------------------------------------------------------- /img/react-router-padded-90.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usulpro/js-stack-from-scratch/HEAD/img/react-router-padded-90.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "js-stack-from-scratch", 3 | "version": "2.4.5", 4 | "description": "JavaScript Stack from Scratch - Step-by-step tutorial to build a modern JavaScript stack", 5 | "scripts": { 6 | "test": "node mdlint.js" 7 | }, 8 | "devDependencies": { 9 | "glob": "^7.1.1", 10 | "markdownlint": "^0.4.0" 11 | }, 12 | "repository": "verekia/js-stack-from-scratch", 13 | "author": "Jonathan Verrecchia - @verekia", 14 | "license": "MIT" 15 | } 16 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE: -------------------------------------------------------------------------------- 1 | ### Type of issue: (feature suggestion, bug?) 2 | 3 | ### Chapter: 4 | 5 | ### If it's a bug: 6 | 7 | Please try using the code provided instead of your own to see if that solves the issue. If it does, compare the content of relevant files to see if anything is missing in your version. Every chapter is automatically tested, so issues are likely coming from missing an instruction in the tutorial or a typo. Feel free to open an issue if there is a problem with instructions though. 8 | -------------------------------------------------------------------------------- /mdlint.js: -------------------------------------------------------------------------------- 1 | const glob = require('glob') 2 | const markdownlint = require('markdownlint') 3 | 4 | const config = { 5 | 'default': true, 6 | 'line_length': false, 7 | 'no-emphasis-as-header': false, 8 | } 9 | 10 | const files = glob.sync('**/*.md', { ignore: '**/node_modules/**' }) 11 | 12 | markdownlint({ files, config }, (err, result) => { 13 | if (!err) { 14 | const resultString = result.toString() 15 | console.log('== Linting Markdown Files...') 16 | if (resultString) { 17 | console.log(resultString) 18 | process.exit(1) 19 | } else { 20 | console.log('== OK!') 21 | } 22 | } 23 | }) 24 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # MIT License 2 | 3 | Copyright (c) 2017 Jonathan Verrecchia 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | ## v2.4.5 4 | 5 | - Add `babel-plugin-flow-react-proptypes`. 6 | - Add `eslint-plugin-compat`. 7 | - Add JSS `composes` example. 8 | 9 | ## v2.4.4 10 | 11 | - Update Immutable to remove the `import * as Immutable from 'immutable'` syntax. 12 | - Declare Flow types outside of function params for React components. 13 | - Improve Webpack `publicPath`. 14 | 15 | ## V2, up to v2.4.3 16 | 17 | - Gulp is gone, replaced by NPM (Yarn) scripts. 18 | - Express has been added, with template strings for static HTML. Gzip compression enabled. 19 | - Support for development environment with Nodemon and production environment with PM2. 20 | - Minification or sourcemaps depending on the environment via Webpack. 21 | - Add Webpack Dev Server, with Hot Module Replacement and `react-hot-loader`. 22 | - Add an asynchronous call example with `redux-thunk`. 23 | - Linting / type checking / testing is not launched at every file change anymore, but triggered by Git Hooks via Husky. 24 | - Some chapters have been combined to make it easier to maintain the tutorial. 25 | - Replace Chai and Mocha by Jest. 26 | - Add React-Router, Server-Side rendering, `react-helmet`. 27 | - Rename all "dog" things and replaced it by "hello" things. It's a Hello World app after all. 28 | - Add Twitter Bootstrap, JSS, and `react-jss` for styling. 29 | - Add a Websocket example with Socket.IO. 30 | - Add optional Heroku, Travis, and Coveralls integrations. 31 | -------------------------------------------------------------------------------- /Definitions.md: -------------------------------------------------------------------------------- 1 | Термины и определения 2 | 3 | package - пакет 4 | https://ru.wikipedia.org/wiki/Package_(Java) 5 | 6 | class - класс 7 | 8 | Type Checking - Типизация 9 | 10 | OOP - объектно-ориентированное программирование 11 | 12 | JavaScript 13 | 14 | template strings - Шаблонные строки 15 | https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/template_strings 16 | 17 | arrow functions - стрелочные функции 18 | https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Functions/Arrow_functions 19 | 20 | CommonJS 21 | 22 | Gulp - сборщик проектов 23 | https://habrahabr.ru/post/208890/ 24 | 25 | Task Runner - менеджер задач. 26 | (диспетчер запуска задач) 27 | 28 | Node - сервер Node 29 | 30 | plain JavaScript object - простой JavaScript объект 31 | 32 | Babel 33 | 34 | синтаксический сахар - syntactic sugar 35 | 36 | lint - статический анализ, контроль качества кода 37 | https://ru.wikipedia.org/wiki/Lint 38 | 39 | linter - статический анализатор кода. 40 | 41 | Gulpfile 42 | 43 | linting errors 44 | 45 | bundle - сборка 46 | 47 | polyfill 48 | https://remysharp.com/2010/10/08/what-is-a-polyfill 49 | 50 | TRANSPILING - транспилияция (трансляция) 51 | https://www.stevefenton.co.uk/2012/11/compiling-vs-transpiling/ 52 | 53 | tutorial - руководство 54 | 55 | entry point file - файл, указывающий на начальную точку сборки 56 | 57 | back-end - серверная часть 58 | 59 | trailing commas - завершающая запятая (/пробел) 60 | http://www.multitran.ru/c/m.exe?t=6766895_1_2&s1=trailing%20space 61 | 62 | repo/repository - репозиторий 63 | 64 | commit - фиксировать гл. 65 | commit - коммит сущ. 66 | 67 | reducer functions - reducer-функции 68 | -------------------------------------------------------------------------------- /how-to-translate.md: -------------------------------------------------------------------------------- 1 | # How to translate this tutorial 2 | 3 | Thank you for your interest in translating my tutorial! Here are a few recommendations to get started. 4 | 5 | This tutorial is in constant evolution to provide the best learning experience to readers. Both the code and `README.md` files will change over time. It is great if you do a one-shot translation that won't evolve, but it would be even better if you could try to keep up with the original English version as it changes! 6 | 7 | Here is what I think is a good workflow: 8 | 9 | - Check if there is already an [ongoing translation](https://github.com/verekia/js-stack-from-scratch/issues/147) for your language. If that's the case, get in touch with the folks who opened it and consider collaborating. All maintainers will be mentioned on the English repo, so team work is encouraged! You can open issues on their translation fork project to offer your help on certain chapters for instance. 10 | 11 | - Join the [Translations Gitter room](https://gitter.im/js-stack-from-scratch/Translations) if you're feeling chatty. 12 | 13 | - Fork the main [English repository](https://github.com/verekia/js-stack-from-scratch). 14 | 15 | - Post in [this issue](https://github.com/verekia/js-stack-from-scratch/issues/147) the language and URL of your forked repo. 16 | 17 | - Translate the `README.md` files. 18 | 19 | - Add a note somewhere explaining on the main `README.md` that this is a translation, with a link to the English repository. If you don't plan to make the translation evolve over time, you can maybe add a little note saying to refer to the English one for an up-to-date version of the tutorial. I'll leave that up to your preference. 20 | 21 | - Submit a Pull Request to the English repo to add a link to your forked repository under the Translations section of the main `README.md`. It could look like this: 22 | 23 | ```md 24 | ## Translations 25 | 26 | - [Language](http://github.com/yourprofile/your-fork) by [You](http://yourwebsite.com) 27 | or 28 | - [Language](http://github.com/yourprofile/your-fork) by [@You](http://twitter.com/yourprofile) 29 | or 30 | - [Language](http://github.com/yourprofile/your-fork) by [@You](http://github.com/yourprofile) 31 | ``` 32 | 33 | Since I want to reward you for your good work as much as possible, you can put any link you like on your name (to your personal website, Twitter profile, or Github profile for instance). 34 | 35 | - After your original one-shot translation, if you want to update your repo with the latest change from the main English repo, [sync your fork](https://help.github.com/articles/syncing-a-fork/) with my repo. To make it easy to see what changed since your initial translation, you can use Github's feature to [compare commits](https://help.github.com/articles/comparing-commits-across-time/#comparing-commits). Set the **base** to the last commit from the English repo you used to translate, and compare it to **master**, like so: 36 | 37 | 38 | https://github.com/verekia/js-stack-from-scratch/compare/c65dfa65d02c21063d94f0955de90947ba5273ad...master 39 | 40 | 41 | That should give you a easy-to-read diff to see exactly what changed in `README.md` files since your translation! 42 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | argparse@^1.0.7: 6 | version "1.0.9" 7 | resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86" 8 | dependencies: 9 | sprintf-js "~1.0.2" 10 | 11 | balanced-match@^0.4.1: 12 | version "0.4.2" 13 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838" 14 | 15 | brace-expansion@^1.0.0: 16 | version "1.1.6" 17 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.6.tgz#7197d7eaa9b87e648390ea61fc66c84427420df9" 18 | dependencies: 19 | balanced-match "^0.4.1" 20 | concat-map "0.0.1" 21 | 22 | concat-map@0.0.1: 23 | version "0.0.1" 24 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 25 | 26 | entities@~1.1.1: 27 | version "1.1.1" 28 | resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0" 29 | 30 | fs.realpath@^1.0.0: 31 | version "1.0.0" 32 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 33 | 34 | glob@^7.1.1: 35 | version "7.1.1" 36 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" 37 | dependencies: 38 | fs.realpath "^1.0.0" 39 | inflight "^1.0.4" 40 | inherits "2" 41 | minimatch "^3.0.2" 42 | once "^1.3.0" 43 | path-is-absolute "^1.0.0" 44 | 45 | inflight@^1.0.4: 46 | version "1.0.6" 47 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 48 | dependencies: 49 | once "^1.3.0" 50 | wrappy "1" 51 | 52 | inherits@2: 53 | version "2.0.3" 54 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" 55 | 56 | linkify-it@^2.0.0: 57 | version "2.0.3" 58 | resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-2.0.3.tgz#d94a4648f9b1c179d64fa97291268bdb6ce9434f" 59 | dependencies: 60 | uc.micro "^1.0.1" 61 | 62 | markdown-it@^8.3.0: 63 | version "8.3.1" 64 | resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-8.3.1.tgz#2f4b622948ccdc193d66f3ca2d43125ac4ac7323" 65 | dependencies: 66 | argparse "^1.0.7" 67 | entities "~1.1.1" 68 | linkify-it "^2.0.0" 69 | mdurl "^1.0.1" 70 | uc.micro "^1.0.3" 71 | 72 | markdownlint@^0.4.0: 73 | version "0.4.0" 74 | resolved "https://registry.yarnpkg.com/markdownlint/-/markdownlint-0.4.0.tgz#5be8a342c4ab4d5c6cfe8702db30c63bbed01589" 75 | dependencies: 76 | markdown-it "^8.3.0" 77 | 78 | mdurl@^1.0.1: 79 | version "1.0.1" 80 | resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" 81 | 82 | minimatch@^3.0.2: 83 | version "3.0.3" 84 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.3.tgz#2a4e4090b96b2db06a9d7df01055a62a77c9b774" 85 | dependencies: 86 | brace-expansion "^1.0.0" 87 | 88 | once@^1.3.0: 89 | version "1.4.0" 90 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 91 | dependencies: 92 | wrappy "1" 93 | 94 | path-is-absolute@^1.0.0: 95 | version "1.0.1" 96 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 97 | 98 | sprintf-js@~1.0.2: 99 | version "1.0.3" 100 | resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" 101 | 102 | uc.micro@^1.0.1, uc.micro@^1.0.3: 103 | version "1.0.3" 104 | resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.3.tgz#7ed50d5e0f9a9fb0a573379259f2a77458d50192" 105 | 106 | wrappy@1: 107 | version "1.0.2" 108 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 109 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JavaScript Stack from Scratch 2 | 3 | [](https://travis-ci.org/verekia/js-stack-from-scratch) [](https://gitter.im/js-stack-from-scratch/Lobby) 4 | 5 | [](https://facebook.github.io/react/) 6 | [](http://redux.js.org/) 7 | [](https://github.com/ReactTraining/react-router) 8 | [](https://flowtype.org/) 9 | [](http://eslint.org/) 10 | [](https://facebook.github.io/jest/) 11 | [](https://yarnpkg.com/) 12 | [](https://webpack.github.io/) 13 | [](http://getbootstrap.com/) 14 | 15 | >Это русскоязычная версия руководства Джонатана Верекии ([@verekia](https://twitter.com/verekia)). Оригинальное руководство расположено [здесь](https://github.com/verekia/js-stack-from-scratch). **Начата [работа](https://github.com/UsulPro/js-stack-from-scratch/issues/8) по переводу второй части**. Первая версия находится [тут](https://github.com/UsulPro/js-stack-from-scratch-v1-rus) 16 | 17 | Добро пожаловать в мое современное руководство по стеку технологий JavaScript: **Стек технологий JavaScript с нуля**. 18 | 19 | > 🎉 **Это вторая версия руководства. По сравнению с предыдущм релизом 2016г произведены значительные изменения. См. [Change Log](/CHANGELOG.md)!** 20 | 21 | 22 | Это практико-ориентированное пособие по применению JavaScript технологий. Вам потребуются общие знания по программированию и основы JavaScript. Это пособие **нацелено на интеграцию необходимых инструментов** и предоставляет **максимально простые примеры** для каждого инструмента. Вы можете рассматривать данный документ, как *возможность создать свой собственный шаблонный проект с нуля*. Поскольку целью этого руководства является сборка различных инструментов, я не буду вдаваться в детали по каждому из них. Если вы хотите получить по ним более глубокие знания, изучайте их документацию или другие руководства. 23 | 24 | Конечно, вам не нужны все эти технологии, если вы делаете простую веб страницу с парой JS функций (комбинации Browserify / Webpack + Babel + jQuery достаточно, чтобы написать ES6 код в нескольких файлах), но если вы собираетесь создать масштабируемое веб приложение, и вам нужно все правильно настроить, то это руководство вам отлично подходит. 25 | 26 | В большой части технологий, описываемых здесь, используется React. Если вы только начинаете использовать React и просто хотите изучить его, то [create-react-app](https://github.com/facebookincubator/create-react-app) поможет вам и кратко ознакомит с инфраструктурой React на основе предустановленной конфигурации. Я бы, например, порекомендовал такой подход для тех, кому нужно влиться в команду, использующую React, и на чем-то потренироваться, чтобы подтянуть свои знания. В этом руководстве мы не будем пользоваться предустановленными конфигурациями, поскольку я хочу, чтобы вы полностью понимали все, что происходит "под капотом". 27 | 28 | В каждой части руководства имеются примеры кода, и вы можете запускать их через `yarn && yarn start`. Однако я рекомендую писать все с нуля самостоятельно, следуя **пошаговым инструкциям**. 29 | 30 | Итоговый код данного руководства доступен в отдельном репозитории: [JS-Stack-Boilerplate repository](https://github.com/verekia/js-stack-boilerplate). Он работает под Linux, macOS, и Windows. 31 | 32 | ## Содержание 33 | 34 | [01 - Node, Yarn, `package.json`](/tutorial/01-node-yarn-package-json_ru.md) 35 | 36 | [02 - Babel, ES6, ESLint, Flow, Jest, Husky](/tutorial/02-babel-es6-eslint-flow-jest-husky.md)  37 | 38 | [03 - Express, Nodemon, PM2](/tutorial/03-express-nodemon-pm2_ru.md) 39 | 40 | [04 - Webpack, React, HMR](/tutorial/04-webpack-react-hmr.md) 41 | 42 | [05 - Redux, Immutable, Fetch](/tutorial/05-redux-immutable-fetch_ru.md) 43 | 44 | [06 - React Router, Server-Side Rendering, Helmet](/tutorial/06-react-router-ssr-helmet_ru.md) 45 | 46 | [07 - Socket.IO](/tutorial/07-socket-io.md)  47 | 48 | [08 - Bootstrap, JSS](/tutorial/08-bootstrap-jss.md)  49 | 50 | [09 - Travis, Coveralls, Heroku](/tutorial/09-travis-coveralls-heroku.md)  51 | 52 | ## Далее планируется 53 | 54 | Настройка вашего редактора (Atom и другие), MongoDB, Прогрессивное веб приложение (Progressive Web App). 55 | 56 | ## Переводы на другие языки 57 | 58 | Если вы хотите добавить перевод на другой язык, пожалуйста читайте [рекомендации по переводу](/how-to-translate.md) чтобы начать! 59 | 60 | ### Версия 2 61 | 62 | - [Русский _в процессе превода_](https://github.com/UsulPro/js-stack-from-scratch) by [React Theming](https://github.com/sm-react/react-theming) 63 | 64 | ### Версия 1 65 | 66 | - [中文](https://github.com/pd4d10/js-stack-from-scratch) by [@pd4d10](http://github.com/pd4d10) 67 | - [Italiano](https://github.com/fbertone/js-stack-from-scratch) by [Fabrizio Bertone](https://github.com/fbertone) 68 | - [日本語](https://github.com/takahashim/js-stack-from-scratch) by [@takahashim](https://github.com/takahashim) 69 | - [Русский](https://github.com/UsulPro/js-stack-from-scratch-v1-rus) by [React Theming](https://github.com/sm-react/react-theming) 70 | - [ไทย](https://github.com/MicroBenz/js-stack-from-scratch) by [MicroBenz](https://github.com/MicroBenz) 71 | 72 | ## Сведения 73 | 74 | Создано [@verekia](https://twitter.com/verekia) – [verekia.com](http://verekia.com/). 75 | 76 | Переведено [@usulpro](https://github.com/UsulPro) - [react-theming](https://github.com/sm-react/react-theming) 77 | 78 | Лицензия: MIT 79 | -------------------------------------------------------------------------------- /tutorial/09-travis-coveralls-heroku.md: -------------------------------------------------------------------------------- 1 | # 09 - Travis, Coveralls, and Heroku 2 | 3 | Code for this chapter available in the `master` branch of the [JS-Stack-Boilerplate repository](https://github.com/verekia/js-stack-boilerplate). 4 | 5 | In this chapter, I integrate our app with third-party services. These services offer free and paid plans. It is a bit controversial to use such services in a tutorial that relies exclusively on community-driven and free open source tools, which is why I maintain 2 different branches of the [JS-Stack-Boilerplate repository](https://github.com/verekia/js-stack-boilerplate), `master` and `master-no-services`. 6 | 7 | ## Travis 8 | 9 | > 💡 **[Travis CI](https://travis-ci.org/)** is a popular continuous integration platform, free for open source projects. 10 | 11 | If your project is hosted publicly on Github, integrating Travis is very simple. First, authenticate with your Github account on Travis, and add your repository. 12 | 13 | - Then, create a `.travis.yml` file containing: 14 | 15 | ```yaml 16 | language: node_js 17 | node_js: node 18 | script: yarn test && yarn prod:build 19 | ``` 20 | 21 | Travis will detect automatically that you use Yarn because you have a `yarn.lock` file. Every time you push code to your Github repository, it will run `yarn test && yarn prod:build`. If nothing goes wrong, you should get a green build. 22 | 23 | ## Coveralls 24 | 25 | > 💡 **[Coveralls](https://coveralls.io)** is a service that gives you a history and statistics of your test coverage. 26 | 27 | If your project is open-source on Github and compatible with Coveralls' supported Continuous Integration services, the only thing you need to do is to pipe the coverage file generated by Jest to the `coveralls` binary. 28 | 29 | - Run `yarn add --dev coveralls` 30 | 31 | - Edit your `.travis.yml`'s `script` instruction like so: 32 | 33 | ```yaml 34 | script: yarn test && yarn prod:build && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js 35 | ``` 36 | 37 | Now, every time Travis will build, it will automatically submit your Jest test coverage data to Coveralls. 38 | 39 | ## Badges 40 | 41 | Is everything green on Travis and Coveralls? Great, show it off to the world with shiny badges! 42 | 43 | You can use the code provided by Travis or Coveralls directly, or use [shields.io](http://shields.io/) to homogenize or customize your badges. Let's use shields.io here. 44 | 45 | - Create or edit your `README.md` like so: 46 | 47 | ```md 48 | [](https://travis-ci.org/GITHUB-USERNAME/GITHUB-REPO) 49 | [](https://coveralls.io/github/GITHUB-USERNAME/GITHUB-REPO?branch=master) 50 | ``` 51 | 52 | Of course, replace `GITHUB-USERNAME/GITHUB-REPO` by your actual Github username and repository name. 53 | 54 | ## Heroku 55 | 56 | > 💡 **[Heroku](https://www.heroku.com/)** is a [PaaS](https://en.wikipedia.org/wiki/Platform_as_a_service) to deploy to. It takes care of infrastructure details, so you can focus on developing your app without worrying about what happens behind the scenes. 57 | 58 | This tutorial is not sponsored in any way by Heroku, but Heroku being one hell of a platform, I am going to show you how to deploy your app to it. Yep, that's the kind of free love you get when you build a great product. 59 | 60 | **Note**: I might add an AWS section in this chapter later, but one thing at a time. 61 | 62 | ### Web setup 63 | 64 | - If that's not the done yet, install the [Heroku CLI](https://devcenter.heroku.com/articles/getting-started-with-nodejs) and log in. 65 | 66 | - Go to your [Heroku Dashboard](https://dashboard.heroku.com/) and create 2 apps, one called `your-project` and one called `your-project-staging` for instance. 67 | 68 | We are going to let Heroku take care of transpiling our ES6/Flow code with Babel, and generate client bundles with Webpack. But since these are `devDependencies`, Yarn won't install them in a production environment like Heroku. Let's change this behavior with the `NPM_CONFIG_PRODUCTION` env variable. 69 | 70 | - In both apps, under Settings > Config Variables, add `NPM_CONFIG_PRODUCTION` set to `false`. 71 | 72 | - Create a Pipeline, and grant Heroku access to your Github. 73 | 74 | - Add both apps to the pipeline, make the staging one auto-deploy on changes in `master`, and enable Review Apps. 75 | 76 | Alright, let's prepare our project for a deployment to Heroku. 77 | 78 | ### Running in production mode locally 79 | 80 | - Create a `.env` file containing: 81 | 82 | ```.env 83 | NODE_ENV='production' 84 | PORT='8000' 85 | ``` 86 | 87 | That's in this file that you should put your local-only variables and secret variables. Don't commit it to a public repository if your project is private. 88 | 89 | - Add `/.env` to your `.gitignore` 90 | 91 | - Create a `Procfile` file containing: 92 | 93 | ```Procfile 94 | web: node lib/server 95 | ``` 96 | 97 | That's where we specify the entry point of our server. 98 | 99 | We are not going to use PM2 anymore, we'll use `heroku local` instead to run in production mode locally. 100 | 101 | - Run `yarn remove pm2` 102 | 103 | - Edit your `prod:start` script in `package.json`: 104 | 105 | ```json 106 | "prod:start": "heroku local", 107 | ``` 108 | 109 | - Remove `prod:stop` from `package.json`. We don't need it anymore since `heroku local` is a hanging process that we can kill with Ctrl+C, unlike `pm2 start`. 110 | 111 | 🏁 Run `yarn prod:build` and `yarn prod:start`. It should start your server and show you the logs. 112 | 113 | ### Deploying to production 114 | 115 | - Add the following line to your `scripts` in `package.json`: 116 | 117 | ```json 118 | "heroku-postbuild": "yarn prod:build", 119 | ``` 120 | 121 | `heroku-postbuild` is a task that will be run every time you deploy an app to Heroku. 122 | 123 | You will also probably want to specify a specific version of Node or Yarn for Heroku to use. 124 | 125 | - Add this to your `package.json`: 126 | 127 | ```json 128 | "engines": { 129 | "node": "7.x", 130 | "yarn": "0.20.3" 131 | }, 132 | ``` 133 | 134 | - Create an `app.json` file containing: 135 | 136 | ```json 137 | { 138 | "env": { 139 | "NPM_CONFIG_PRODUCTION": "false" 140 | } 141 | } 142 | ``` 143 | 144 | This is for your Review Apps to use. 145 | 146 | You should now be all set to use Heroku Pipeline deployments. 147 | 148 | 🏁 Create a new git branch, make changes and open a Github Pull Request to instantiate a Review App. Check your changes on the Review App URL, and if everything looks good, merge your Pull Request with `master` on Github. A few minutes later, your staging app should have been automatically deployed. Check your changes on the staging app URL, and if everything still looks good, promote staging to production. 149 | 150 | You are done! Congratulations if you finished this entire tutorial starting from scratch. 151 | 152 | You deserve this emoji medal: 🏅 153 | 154 | Back to the [previous section](08-bootstrap-jss.md#readme) or the [table of contents](https://github.com/verekia/js-stack-from-scratch#table-of-contents). 155 | -------------------------------------------------------------------------------- /tutorial/07-socket-io.md: -------------------------------------------------------------------------------- 1 | # 07 - Socket.IO 2 | 3 | Code for this chapter available [here](https://github.com/verekia/js-stack-walkthrough/tree/master/07-socket-io). 4 | 5 | > 💡 **[Socket.IO](https://github.com/socketio/socket.io)** is a library to easily deal with Websockets. It provides a convenient API and fallback for browsers that don't support Websockets. 6 | 7 | In this chapter, we are going to set up a basic message exchange between the client and the server. In order to not add more pages and components – which would be unrelated to the core feature we're interested in here – we are going to make this exchange happen in the browser console. No UI stuff in this chapter. 8 | 9 | - Run `yarn add socket.io socket.io-client` 10 | 11 | ## Server-side 12 | 13 | - Edit your `src/server/index.js` like so: 14 | 15 | ```js 16 | // @flow 17 | 18 | import compression from 'compression' 19 | import express from 'express' 20 | import { Server } from 'http' 21 | import socketIO from 'socket.io' 22 | 23 | import routing from './routing' 24 | import { WEB_PORT, STATIC_PATH } from '../shared/config' 25 | import { isProd } from '../shared/util' 26 | import setUpSocket from './socket' 27 | 28 | const app = express() 29 | // flow-disable-next-line 30 | const http = Server(app) 31 | const io = socketIO(http) 32 | setUpSocket(io) 33 | 34 | app.use(compression()) 35 | app.use(STATIC_PATH, express.static('dist')) 36 | app.use(STATIC_PATH, express.static('public')) 37 | 38 | routing(app) 39 | 40 | http.listen(WEB_PORT, () => { 41 | // eslint-disable-next-line no-console 42 | console.log(`Server running on port ${WEB_PORT} ${isProd ? '(production)' : 43 | '(development).\nKeep "yarn dev:wds" running in an other terminal'}.`) 44 | }) 45 | ``` 46 | 47 | Note that in order for Socket.IO to work, you need to use `Server` from `http` to `listen` to incoming requests, and not the Express `app`. Fortunately, that doesn't change much of the code. All the Websocket details are externalized in a different file, called with `setUpSocket`. 48 | 49 | - Add the following constants to `src/shared/config.js`: 50 | 51 | ```js 52 | export const IO_CONNECT = 'connect' 53 | export const IO_DISCONNECT = 'disconnect' 54 | export const IO_CLIENT_HELLO = 'IO_CLIENT_HELLO' 55 | export const IO_CLIENT_JOIN_ROOM = 'IO_CLIENT_JOIN_ROOM' 56 | export const IO_SERVER_HELLO = 'IO_SERVER_HELLO' 57 | ``` 58 | 59 | These are the *type of messages* your client and your server will exchange. I suggest prefixing them with either `IO_CLIENT` or `IO_SERVER` to make it clearer *who* is sending the message. Otherwise, things can get pretty confusing when you have a lot of message types. 60 | 61 | As you can see, we have a `IO_CLIENT_JOIN_ROOM`, because for the sake of demonstration, we are going to make clients join a room (like a chatroom). Rooms are useful to broadcast messages to specific groups of users. 62 | 63 | - Create a `src/server/socket.js` file containing: 64 | 65 | ```js 66 | // @flow 67 | 68 | import { 69 | IO_CONNECT, 70 | IO_DISCONNECT, 71 | IO_CLIENT_JOIN_ROOM, 72 | IO_CLIENT_HELLO, 73 | IO_SERVER_HELLO, 74 | } from '../shared/config' 75 | 76 | /* eslint-disable no-console */ 77 | const setUpSocket = (io: Object) => { 78 | io.on(IO_CONNECT, (socket) => { 79 | console.log('[socket.io] A client connected.') 80 | 81 | socket.on(IO_CLIENT_JOIN_ROOM, (room) => { 82 | socket.join(room) 83 | console.log(`[socket.io] A client joined room ${room}.`) 84 | 85 | io.emit(IO_SERVER_HELLO, 'Hello everyone!') 86 | io.to(room).emit(IO_SERVER_HELLO, `Hello clients of room ${room}!`) 87 | socket.emit(IO_SERVER_HELLO, 'Hello you!') 88 | }) 89 | 90 | socket.on(IO_CLIENT_HELLO, (clientMessage) => { 91 | console.log(`[socket.io] Client: ${clientMessage}`) 92 | }) 93 | 94 | socket.on(IO_DISCONNECT, () => { 95 | console.log('[socket.io] A client disconnected.') 96 | }) 97 | }) 98 | } 99 | /* eslint-enable no-console */ 100 | 101 | export default setUpSocket 102 | ``` 103 | 104 | Okay, so in this file, we implement *how our server should react when clients connect and send messages to it*: 105 | 106 | - When the client connects, we log it in the server console, and get access to the `socket` object, which we can use to communicate back with that client. 107 | - When a client sends `IO_CLIENT_JOIN_ROOM`, we make it join the `room` it wants. Once it has joined a room, we send 3 demo messages: 1 message to every user, 1 message to users in that room, 1 message to that client only. 108 | - When the client sends `IO_CLIENT_HELLO`, we log its message in the server console. 109 | - When the client disconnects, we log it as well. 110 | 111 | ## Client-side 112 | 113 | The client-side of things is going to look very similar. 114 | 115 | - Edit `src/client/index.jsx` like so: 116 | 117 | ```js 118 | // [...] 119 | import setUpSocket from './socket' 120 | 121 | // [at the very end of the file] 122 | setUpSocket(store) 123 | ``` 124 | 125 | As you can see, we pass the Redux store to `setUpSocket`. This way whenever a Websocket message coming from the server should alter the client's Redux state, we can `dispatch` actions. We are not going to `dispatch` anything in this example though. 126 | 127 | - Create a `src/client/socket.js` file containing: 128 | 129 | ```js 130 | // @flow 131 | 132 | import socketIOClient from 'socket.io-client' 133 | 134 | import { 135 | IO_CONNECT, 136 | IO_DISCONNECT, 137 | IO_CLIENT_HELLO, 138 | IO_CLIENT_JOIN_ROOM, 139 | IO_SERVER_HELLO, 140 | } from '../shared/config' 141 | 142 | const socket = socketIOClient(window.location.host) 143 | 144 | /* eslint-disable no-console */ 145 | // eslint-disable-next-line no-unused-vars 146 | const setUpSocket = (store: Object) => { 147 | socket.on(IO_CONNECT, () => { 148 | console.log('[socket.io] Connected.') 149 | socket.emit(IO_CLIENT_JOIN_ROOM, 'hello-1234') 150 | socket.emit(IO_CLIENT_HELLO, 'Hello!') 151 | }) 152 | 153 | socket.on(IO_SERVER_HELLO, (serverMessage) => { 154 | console.log(`[socket.io] Server: ${serverMessage}`) 155 | }) 156 | 157 | socket.on(IO_DISCONNECT, () => { 158 | console.log('[socket.io] Disconnected.') 159 | }) 160 | } 161 | /* eslint-enable no-console */ 162 | 163 | export default setUpSocket 164 | ``` 165 | 166 | What happens here should not be surprising if you understood well what we did on the server: 167 | 168 | - As soon as the client is connected, we log it in the browser console and join the room `hello-1234` with a `IO_CLIENT_JOIN_ROOM` message. 169 | - We then send `Hello!` with a `IO_CLIENT_HELLO` message. 170 | - If the server sends us a `IO_SERVER_HELLO` message, we log it in the browser console. 171 | - We also log any disconnection. 172 | 173 | 🏁 Run `yarn start` and `yarn dev:wds`, open `http://localhost:8000`. Then, open your browser console, and also look at the terminal of your Express server. You should see the Websocket communication between your client and server. 174 | 175 | Next section: [08 - Bootstrap, JSS](08-bootstrap-jss.md#readme) 176 | 177 | Back to the [previous section](06-react-router-ssr-helmet.md#readme) or the [table of contents](https://github.com/verekia/js-stack-from-scratch#table-of-contents). 178 | -------------------------------------------------------------------------------- /tutorial/01-node-yarn-package-json.md: -------------------------------------------------------------------------------- 1 | # 01 - Node, Yarn, and `package.json` 2 | 3 | Code for this chapter available [here](https://github.com/verekia/js-stack-walkthrough/tree/master/01-node-yarn-package-json). 4 | 5 | In this section we will set up Node, Yarn, a basic `package.json` file, and try a package. 6 | 7 | ## Node 8 | 9 | > 💡 **[Node.js](https://nodejs.org/)** is a JavaScript runtime environment. It is mostly used for Back-End development, but also for general scripting. In the context of Front-End development, it can be used to perform a whole bunch of tasks like linting, testing, and assembling files. 10 | 11 | We will use Node for basically everything in this tutorial, so you're going to need it. Head to the [download page](https://nodejs.org/en/download/current/) for **macOS** or **Windows** binaries, or the [package manager installations page](https://nodejs.org/en/download/package-manager/) for Linux distributions. 12 | 13 | For instance, on **Ubuntu / Debian**, you would run the following commands to install Node: 14 | 15 | ```sh 16 | curl -sL https://deb.nodesource.com/setup_7.x | sudo -E bash - 17 | sudo apt-get install -y nodejs 18 | ``` 19 | 20 | You want any version of Node > 6.5.0. 21 | 22 | ## Node Version Management Tools 23 | 24 | If you need the flexibility to use multiple versions of Node, check out [NVM](https://github.com/creationix/nvm) or [tj/n](https://github.com/tj/n). 25 | 26 | ## NPM 27 | 28 | NPM is the default package manager for Node. It is automatically installed alongside with Node. Package managers are used to install and manage packages (modules of code that you or someone else wrote). We are going to use a lot of packages in this tutorial, but we'll use Yarn, another package manager. 29 | 30 | ## Yarn 31 | 32 | > 💡 **[Yarn](https://yarnpkg.com/)** is a Node.js package manager which is much faster than NPM, has offline support, and fetches dependencies [more predictably](https://yarnpkg.com/en/docs/yarn-lock). 33 | 34 | Since it [came out](https://code.facebook.com/posts/1840075619545360) in October 2016, it received a very quick adoption and may soon become the package manager of choice of the JavaScript community. If you want to stick to NPM you can simply replace all `yarn add` and `yarn add --dev` commands of this tutorial by `npm install --save` and `npm install --save-dev`. 35 | 36 | Install Yarn by following the [instructions](https://yarnpkg.com/en/docs/install) for your OS. I would recommend using the **Installation Script** from the *Alternatives* tab if you are on macOS or Unix, to [avoid](https://github.com/yarnpkg/yarn/issues/1505) relying on other package managers: 37 | 38 | ```sh 39 | curl -o- -L https://yarnpkg.com/install.sh | bash 40 | ``` 41 | 42 | ## `package.json` 43 | 44 | > 💡 **[package.json](https://yarnpkg.com/en/docs/package-json)** is the file used to describe and configure your JavaScript project. It contains general information (your project name, version, contributors, license, etc), configuration options for tools you use, and even a section to run *tasks*. 45 | 46 | - Create a new folder to work in, and `cd` in it. 47 | - Run `yarn init` and answer the questions (`yarn init -y` to skip all questions), to generate a `package.json` file automatically. 48 | 49 | Here is the basic `package.json` I'll use in this tutorial: 50 | 51 | ```json 52 | { 53 | "name": "your-project", 54 | "version": "1.0.0", 55 | "license": "MIT" 56 | } 57 | ``` 58 | 59 | ## Hello World 60 | 61 | - Create an `index.js` file containing `console.log('Hello world')` 62 | 63 | 🏁 Run `node .` in this folder (`index.js` is the default file Node looks for in a folder). It should print "Hello world". 64 | 65 | **Note**: See that 🏁 racing flag emoji? I will use it every time you reach a **checkpoint**. We are sometimes going to make a lot of changes in a row, and your code may not work until you reach the next checkpoint. 66 | 67 | ## `start` script 68 | 69 | Running `node .` to execute our program is a bit too low-level. We are going to use an NPM/Yarn script to trigger the execution of that code instead. That will give us a nice abstraction to be able to always use `yarn start`, even when our program gets more complicated. 70 | 71 | - In `package.json`, add a `scripts` object like so: 72 | 73 | ```json 74 | { 75 | "name": "your-project", 76 | "version": "1.0.0", 77 | "license": "MIT", 78 | "scripts": { 79 | "start": "node ." 80 | } 81 | } 82 | ``` 83 | 84 | `start` is the name we give to the *task* that will run our program. We are going to create a lot of different tasks in this `scripts` object throughout this tutorial. `start` is typically the name given to the default task of an application. Some other standard task names are `stop` and `test`. 85 | 86 | `package.json` must be a valid JSON file, which means that you cannot have trailing commas. So be careful when editing manually your `package.json` file. 87 | 88 | 🏁 Run `yarn start`. It should print `Hello world`. 89 | 90 | ## Git and `.gitignore` 91 | 92 | - Initialize a Git repository with `git init` 93 | 94 | - Create a `.gitignore` file and add the following to it: 95 | 96 | ```gitignore 97 | .DS_Store 98 | /*.log 99 | ``` 100 | 101 | `.DS_Store` files are auto-generated macOS files that you should never have in your repository. 102 | 103 | `npm-debug.log` and `yarn-error.log` are files that are created when your package manager encounters an error, we don't want them versioned in our repository. 104 | 105 | ## Installing and using a package 106 | 107 | In this section we will install and use a package. A "package" is simply a piece of code that someone else wrote, and that you can use in your own code. It can be anything. Here, we're going to try a package that helps you manipulate colors for instance. 108 | 109 | - Install the community-made package called `color` by running `yarn add color` 110 | 111 | Open `package.json` to see how Yarn automatically added `color` in `dependencies`. 112 | 113 | A `node_modules` folder has been created to store the package. 114 | 115 | - Add `node_modules/` to your `.gitignore` 116 | 117 | You will also notice that a `yarn.lock` file got generated by Yarn. You should commit this file to your repository, as it will ensure that everyone in your team uses the same version of your packages. If you're sticking to NPM instead of Yarn, the equivalent of this file is the *shrinkwrap*. 118 | 119 | - Write the following to your `index.js` file: 120 | 121 | ```js 122 | const color = require('color') 123 | 124 | const redHexa = color({ r: 255, g: 0, b: 0 }).hex() 125 | 126 | console.log(redHexa) 127 | ``` 128 | 129 | 🏁 Run `yarn start`. It should print `#FF0000`. 130 | 131 | Congratulations, you installed and used a package! 132 | 133 | `color` is just used in this section to teach you how to use a simple package. We won't need it anymore, so you can uninstall it: 134 | 135 | - Run `yarn remove color` 136 | 137 | ## Two kinds of dependencies 138 | 139 | There are two kinds of package dependencies, `"dependencies"` and `"devDependencies"`: 140 | 141 | **Dependencies** are libraries you need for your application to function (React, Redux, Lodash, jQuery, etc). You install them with `yarn add [package]`. 142 | 143 | **Dev Dependencies** are libraries used during development or to build your application (Webpack, SASS, linters, testing frameworks, etc). You install those with `yarn add --dev [package]`. 144 | 145 | Next section: [02 - Babel, ES6, ESLint, Flow, Jest, Husky](02-babel-es6-eslint-flow-jest-husky.md#readme) 146 | 147 | Back to the [table of contents](https://github.com/verekia/js-stack-from-scratch#table-of-contents). 148 | -------------------------------------------------------------------------------- /tutorial/01-node-yarn-package-json_ru.md: -------------------------------------------------------------------------------- 1 | # 01 - Node, Yarn, и `package.json` 2 | 3 | Код для этой главы доступен [здесь](https://github.com/verekia/js-stack-walkthrough/tree/master/01-node-yarn-package-json). 4 | 5 | В этой части мы настроим Node, Yarn, простой файл `package.json` и протестируем пакет. 6 | 7 | ## Node 8 | 9 | > 💡 **[Node.js](https://nodejs.org/)** - среда исполнения JavaScript, в основном используется для Back-End разработки, но также и для общих целей. В контексте Front-End разработки может применяться для выполнения целого ряда задач, таких как линтинг (linting), тестирование и сборка файлов. 10 | 11 | Мы будем использовать Node буквально везде в этом руководстве, так что вам нужно будет ее установить. Зайдите на [страницу загрузки](https://nodejs.org/en/download/current/) для **macOS** или **Windows** дистрибутивов, или на [страницу установки пакетного менеджера](https://nodejs.org/en/download/package-manager/) для linux. 12 | 13 | Например для **Ubuntu / Debian** выполните следующие команды, чтобы установить Node: 14 | 15 | ```sh 16 | curl -sL https://deb.nodesource.com/setup_7.x | sudo -E bash - 17 | sudo apt-get install -y nodejs 18 | ``` 19 | 20 | Вам подойдет любая версия Node > 6.5.0. 21 | 22 | ## Средства управления версиями Node. 23 | 24 | Если вам нужна гибкость в использовании различных версий Node, рассмотрите [NVM](https://github.com/creationix/nvm) или [tj/n](https://github.com/tj/n). 25 | 26 | ## NPM 27 | 28 | NPM - менеджер пакетов Node по умолчанию. Он автоматически устанавливается вместе с Node. Менеджеры пакетов используются для установки и управления пакетами (модулями кода, которые написали вы или кто-то другой). Мы будем использовать много пакетов в этом руководстве, но мы установим Yarn - другой пакетный менеджер. 29 | 30 | ## Yarn 31 | 32 | > 💡 **[Yarn](https://yarnpkg.com/)** - менеджер пакетов Node.js гораздо более быстрый чем NPM, поддерживает offline режим и с [более предсказуемой](https://yarnpkg.com/en/docs/yarn-lock) загрузкой пакетов. 33 | 34 | С момента [выхода](https://code.facebook.com/posts/1840075619545360) в Октябре 2016 он очень быстро получил признание, и, возможно, скоро станет основным менеджером пакетов для JavaScript сообщества. Если вы хотите остаться с NPM, вы можете просто заменить в этом руководстве все команды `yarn add` и `yarn add --dev` на `npm install --save` and `npm install --save-dev`. 35 | 36 | Установите Yarn, следую [инструкциям](https://yarnpkg.com/en/docs/install) для вашей ОС. Если вы на macOS или Unix, я бы рекомендовал использовать **установочный Script** из вкладки *Alternatives*, чтобы [избежать](https://github.com/yarnpkg/yarn/issues/1505) взаимодействий с другими пакетными менеджерами: 37 | 38 | ```sh 39 | curl -o- -L https://yarnpkg.com/install.sh | bash 40 | ``` 41 | 42 | ## `package.json` 43 | 44 | > 💡 **[package.json](https://yarnpkg.com/en/docs/package-json)** - файл, используемый для описания и конфигурирования вашего JavaScript проекта. Он содержит основную информацию (имя проекта, версия, контрибьюторы, лиценция и т.д.), конфигурационные настройки для инструментов, которые вы используете и даже раздел для запуска *задач*. 45 | 46 | - Создайте новую папку для работы и `cd` в нее. 47 | - Запустите `yarn init` и ответьте на вопросы (`yarn init -y` - пропустить все вопросы), чтобы создать файл `package.json` автоматически. 48 | 49 | Вот простой `package.json` который я буду использовать в этом руководстве: 50 | 51 | ```json 52 | { 53 | "name": "your-project", 54 | "version": "1.0.0", 55 | "license": "MIT" 56 | } 57 | ``` 58 | 59 | ## Hello World 60 | 61 | - Создайте файл `index.js` содержащий `console.log('Hello world')` 62 | 63 | 🏁 Запустите `node .` в этой папке (`index.js` - файл по умолчанию, который Node ищет в папке). Должно выйти "Hello world". 64 | 65 | **Примечание**: Видите этот значек - 🏁 - гоночный флаг? Я буду его использовать каждый раз при достижении **чекпоинта**. Иногда мы будем делать много изменения подряд, и ваш код не будет работать до тех пор, пока вы не достигнете следующего чекпоинта. 66 | 67 | ## `start` script 68 | 69 | Использование `node .` для запуска программ - несколько низкоуровневый подход. Вместо этого, мы будем использовать NPM/Yarn скрипты для запуска выполнения этого кода. Это даст нам отличный уровень абстракции, позволяющий всегда использовать `yarn start`, даже когда наша программа станет более сложной. 70 | 71 | - В `package.json`, добавьте такой объект `scripts`: 72 | 73 | ```json 74 | { 75 | "name": "your-project", 76 | "version": "1.0.0", 77 | "license": "MIT", 78 | "scripts": { 79 | "start": "node ." 80 | } 81 | } 82 | ``` 83 | 84 | `start` - имя, которое мы дали *задаче*, которая будет запускать нашу программу. Мы создадим много различных задач в этом объекте `scripts` в ходе данного руководства. `start` - это имя по умолчанию одной из типичных задач приложения. Другие стандартные названия задач - это `stop` это `test`. 85 | 86 | `package.json` должен быть валидным JSON файлом, что означает, что вы не можете использовать конечные запятые (trailing commas). Поэтому будьте аккуратны вручную редактируя файл `package.json`. 87 | 88 | 🏁 Запустите `yarn start`. Должно выйти `Hello world`. 89 | 90 | ## Git и `.gitignore` 91 | 92 | - Инициализируйте репозиторий Git с помощью `git init` 93 | 94 | - Создайте файл `.gitignore` и добавьте в него следующее: 95 | 96 | ```gitignore 97 | .DS_Store 98 | /*.log 99 | ``` 100 | 101 | `.DS_Store` - автогенерируемые macOS файлы, которые никогда не должны быть в вашем репозитории. 102 | 103 | `npm-debug.log` и `yarn-error.log` - файлы, генерируемые пакетным менеджером при ошибках. Мы не хотим хранить их в репозитории. 104 | 105 | ## Установка и использование пакетов 106 | 107 | В этой части мы установим и воспользуемся пакетом. "Пакет" - это просто кусок кода, который написал кто-то другой и который вы можете использовать в своем собственном коде. Это может быть что угодно. Сейчас, например, мы попробуем пакет, который помогает манипулировать цветами. 108 | 109 | - Установим созданный сообществом пакет, который называется `color`, запустив `yarn add color`. 110 | 111 | Откройте `package.json` чтобы увидеть как Yarn автоматически добавил `color` в `dependencies`. 112 | 113 | Папка `node_modules` была создана для хранения пакетов. 114 | 115 | - Добавьте `node_modules/` в `.gitignore` 116 | 117 | Вы также заметите файл `yarn.lock`, сгенерированный Yarn. Вам нужно добавить коммит с этим файлом в репозиторий, поскольку это даст уверенность, что все в вашей команде используют одни и теже версии пакетов. Если вы предпочитаете NPM а не Yarn, эквивалентом этому файлу будет *shrinkwrap*. 118 | 119 | - Напишите следующее в файл `index.js`: 120 | 121 | ```js 122 | const color = require('color') 123 | 124 | const redHexa = color({ r: 255, g: 0, b: 0 }).hex() 125 | 126 | console.log(redHexa) 127 | ``` 128 | 129 | 🏁 Запустите `yarn start`. Должно выйти `#FF0000`. 130 | 131 | Поздравляем! Вы установили и использовали пакет. 132 | 133 | Мы использовали `color` в этом разделе, чтобы продемонстрировать вам как использовать простой пакет. Он больше нам не потребуется, поэтому можно его удалить: 134 | 135 | - Запустите `yarn remove color` 136 | 137 | ## Два вида зависимостей 138 | 139 | Пакеты могут быть двух видов зависимостей `"dependencies"` и `"devDependencies"` 140 | 141 | **Dependencies** - библиотеки, нужные чтобы ваше приложение функционировало (React, Redux, Lodash, jQuery, etc). Вы устанавливаете их с помощью `yarn add [package]`. 142 | 143 | **Dev Dependencies** - библиотеки, используемые во время разработки или для сборки вашего приложения (Webpack, SASS, linters, testing frameworks, etc). Устанавливайте их с помощью `yarn add --dev [package]`. 144 | 145 | Следующий раздел: [02 - Babel, ES6, ESLint, Flow, Jest, Husky](02-babel-es6-eslint-flow-jest-husky.md#readme) 146 | 147 | Назад в [содержание](https://github.com/verekia/js-stack-from-scratch#table-of-contents). 148 | -------------------------------------------------------------------------------- /tutorial/03-express-nodemon-pm2.md: -------------------------------------------------------------------------------- 1 | # 03 - Express, Nodemon, and PM2 2 | 3 | Code for this chapter available [here](https://github.com/verekia/js-stack-walkthrough/tree/master/03-express-nodemon-pm2). 4 | 5 | In this section we are going to create the server that will render our web app. We will also set up a development mode and a production mode for this server. 6 | 7 | ## Express 8 | 9 | > 💡 **[Express](http://expressjs.com/)** is by far the most popular web application framework for Node. It provides a very simple and minimal API, and its features can be extended with *middleware*. 10 | 11 | Let's set up a minimal Express server to serve an HTML page with some CSS. 12 | 13 | - Delete everything inside `src` 14 | 15 | Create the following files and folders: 16 | 17 | - Create a `public/css/style.css` file containing: 18 | 19 | ```css 20 | body { 21 | width: 960px; 22 | margin: auto; 23 | font-family: sans-serif; 24 | } 25 | 26 | h1 { 27 | color: limegreen; 28 | } 29 | ``` 30 | 31 | - Create an empty `src/client/` folder. 32 | 33 | - Create an empty `src/shared/` folder. 34 | 35 | This folder is where we put *isomorphic / universal* JavaScript code – files that are used by both the client and the server. A great use case of shared code is *routes*, as you will see later in this tutorial when we'll make an asynchronous call. Here we simply have some configuration constants as an example for now. 36 | 37 | - Create a `src/shared/config.js` file, containing: 38 | 39 | ```js 40 | // @flow 41 | 42 | export const WEB_PORT = process.env.PORT || 8000 43 | export const STATIC_PATH = '/static' 44 | export const APP_NAME = 'Hello App' 45 | ``` 46 | 47 | If the Node process used to run your app has a `process.env.PORT` environment variable set (that's the case when you deploy to Heroku for instance), it will use this for the port. If there is none, we default to `8000`. 48 | 49 | - Create a `src/shared/util.js` file containing: 50 | 51 | ```js 52 | // @flow 53 | 54 | // eslint-disable-next-line import/prefer-default-export 55 | export const isProd = process.env.NODE_ENV === 'production' 56 | ``` 57 | 58 | That's a simple util to test if we are running in production mode or not. The `// eslint-disable-next-line import/prefer-default-export` comment is because we only have one named export here. You can remove it as you add other exports in this file. 59 | 60 | - Run `yarn add express compression` 61 | 62 | `compression` is an Express middleware to activate Gzip compression on the server. 63 | 64 | - Create a `src/server/index.js` file containing: 65 | 66 | ```js 67 | // @flow 68 | 69 | import compression from 'compression' 70 | import express from 'express' 71 | 72 | import { APP_NAME, STATIC_PATH, WEB_PORT } from '../shared/config' 73 | import { isProd } from '../shared/util' 74 | import renderApp from './render-app' 75 | 76 | const app = express() 77 | 78 | app.use(compression()) 79 | app.use(STATIC_PATH, express.static('dist')) 80 | app.use(STATIC_PATH, express.static('public')) 81 | 82 | app.get('/', (req, res) => { 83 | res.send(renderApp(APP_NAME)) 84 | }) 85 | 86 | app.listen(WEB_PORT, () => { 87 | // eslint-disable-next-line no-console 88 | console.log(`Server running on port ${WEB_PORT} ${isProd ? '(production)' : '(development)'}.`) 89 | }) 90 | ``` 91 | 92 | Nothing fancy here, it's almost Express' Hello World tutorial with a few additional imports. We're using 2 different static file directories here. `dist` for generated files, `public` for declarative ones. 93 | 94 | - Create a `src/server/render-app.js` file containing: 95 | 96 | ```js 97 | // @flow 98 | 99 | import { STATIC_PATH } from '../shared/config' 100 | 101 | const renderApp = (title: string) => 102 | ` 103 | 104 |
105 |156 | 157 |
158 |Open your browser console.
165 |Hover me.
441 |Resize the window.
442 | 443 |