[
  {
    "path": ".github/FUNDING.yml",
    "content": "github: verekia\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE",
    "content": "### Type of issue: (feature suggestion, bug?)\n\n### Chapter:\n\n### If it's a bug:\n\nPlease 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.\n"
  },
  {
    "path": ".gitignore",
    "content": ".DS_Store\nnpm-debug.log\nnode_modules\n\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: node_js\nnode_js: node\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# Change Log\n\n## v2.4.5\n\n- Add `babel-plugin-flow-react-proptypes`.\n- Add `eslint-plugin-compat`.\n- Add JSS `composes` example.\n\n## v2.4.4\n\n- Update Immutable to remove the `import * as Immutable from 'immutable'` syntax.\n- Declare Flow types outside of function params for React components.\n- Improve Webpack `publicPath`.\n\n## V2, up to v2.4.3\n\n- Gulp is gone, replaced by NPM (Yarn) scripts.\n- Express has been added, with template strings for static HTML. Gzip compression enabled.\n- Support for development environment with Nodemon and production environment with PM2.\n- Minification or sourcemaps depending on the environment via Webpack.\n- Add Webpack Dev Server, with Hot Module Replacement and `react-hot-loader`.\n- Add an asynchronous call example with `redux-thunk`.\n- Linting / type checking / testing is not launched at every file change anymore, but triggered by Git Hooks via Husky.\n- Some chapters have been combined to make it easier to maintain the tutorial.\n- Replace Chai and Mocha by Jest.\n- Add React-Router, Server-Side rendering, `react-helmet`.\n- Rename all \"dog\" things and replaced it by \"hello\" things. It's a Hello World app after all.\n- Add Twitter Bootstrap, JSS, and `react-jss` for styling.\n- Add a Websocket example with Socket.IO.\n- Add optional Heroku, Travis, and Coveralls integrations.\n"
  },
  {
    "path": "LICENSE.md",
    "content": "# MIT License\n\nCopyright (c) 2017 Jonathan Verrecchia\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# JavaScript Stack from Scratch\n\n[![Build Status](https://travis-ci.org/verekia/js-stack-from-scratch.svg?branch=master)](https://travis-ci.org/verekia/js-stack-from-scratch)\n[![Release](https://img.shields.io/github/release/verekia/js-stack-from-scratch.svg?style=flat-square)](https://github.com/verekia/js-stack-from-scratch/releases)\n[![Gitter](https://img.shields.io/gitter/room/js-stack-from-scratch/Lobby.svg?style=flat-square)](https://gitter.im/js-stack-from-scratch/)\n\n[![React](/img/react-padded-90.png)](https://facebook.github.io/react/)\n[![Redux](/img/redux-padded-90.png)](http://redux.js.org/)\n[![React Router](/img/react-router-padded-90.png)](https://github.com/ReactTraining/react-router)\n[![Flow](/img/flow-padded-90.png)](https://flowtype.org/)\n[![ESLint](/img/eslint-padded-90.png)](http://eslint.org/)\n[![Jest](/img/jest-padded-90.png)](https://facebook.github.io/jest/)\n[![Yarn](/img/yarn-padded-90.png)](https://yarnpkg.com/)\n[![Webpack](/img/webpack-padded-90.png)](https://webpack.github.io/)\n\nWelcome to my modern JavaScript stack tutorial: **JavaScript Stack from Scratch**.\n\n> 🎉 **This is the V2 of the tutorial, major changes happened since the 2016 release. Check the [Change Log](/CHANGELOG.md)!**\n\nThis is a straight-to-the-point guide to assembling a JavaScript stack. It requires some general programming knowledge, and JavaScript basics. **It focuses on wiring tools together** and giving you the **simplest possible example** for each tool. You can see this tutorial as *a way to write your own boilerplate from scratch*. Since the goal of this tutorial is to assemble various tools, I do not go into details about how these tools work individually. Refer to their documentation or find other tutorials if you want to acquire deeper knowledge in them.\n\nYou don't need to use this entire stack if you build a simple web page with a few JS interactions of course (a combination of Browserify/Webpack + Babel + jQuery is enough to be able to write ES6 code in different files), but if you want to build a web app that scales, and need help setting things up, this tutorial will work great for you.\n\nA big chunk of the stack described in this tutorial uses React. If you are beginning and just want to learn React, [create-react-app](https://github.com/facebookincubator/create-react-app) will get you up and running with a React environment very quickly with a pre-made configuration. I would for instance recommend this approach to someone who arrives in a team that's using React and needs to catch up with a learning playground. In this tutorial you won't use a pre-made configuration, because I want you to understand everything that's happening under the hood.\n\nCode examples are available for each chapter, and you can run them all with `yarn && yarn start`. I recommend writing everything from scratch yourself by following the **step-by-step instructions** though.\n\nFinal code available in the [JS-Stack-Boilerplate repository](https://github.com/verekia/js-stack-boilerplate), and in the [releases](https://github.com/verekia/js-stack-from-scratch/releases). There is a [live demo](https://js-stack.herokuapp.com/) too.\n\nWorks on Linux, macOS, and Windows.\n\n> **Note**: Since the tutorial was last edited in May 2017, a few libraries have slightly changed their APIs. 95% of the tutorial is still perfectly valid, but if you run into something weird, make sure to check out the [open issues](https://github.com/verekia/js-stack-from-scratch/issues?q=is%3Aopen+is%3Aissue+label%3Abug).\n\n## Table of contents\n\n[01 - Node, Yarn, `package.json`](/tutorial/01-node-yarn-package-json.md#readme)\n\n[02 - Babel, ES6, ESLint, Flow, Jest, Husky](/tutorial/02-babel-es6-eslint-flow-jest-husky.md#readme)\n\n[03 - Express, Nodemon, PM2](/tutorial/03-express-nodemon-pm2.md#readme)\n\n[04 - Webpack, React, HMR](/tutorial/04-webpack-react-hmr.md#readme)\n\n[05 - Redux, Immutable, Fetch](/tutorial/05-redux-immutable-fetch.md#readme)\n\n[06 - React Router, Server-Side Rendering, Helmet](/tutorial/06-react-router-ssr-helmet.md#readme)\n\n[07 - Socket.IO](/tutorial/07-socket-io.md#readme)\n\n[08 - Bootstrap, JSS](/tutorial/08-bootstrap-jss.md#readme)\n\n[09 - Travis, Coveralls, Heroku](/tutorial/09-travis-coveralls-heroku.md#readme)\n\n## Coming up next\n\nSetting up your editor (Atom first), MongoDB, Progressive Web App, E2E testing.\n\n## Translations\n\nIf you want to add your translation, please read the [translation recommendations](/how-to-translate.md) to get started!\n\n### V2\n\n- [Bulgarian](https://github.com/mihailgaberov/js-stack-from-scratch) by [mihailgaberov](http://github.com/mihailgaberov)\n- [Chinese (simplified)](https://github.com/yepbug/js-stack-from-scratch/) by [@yepbug](https://github.com/yepbug)\n- [French](https://github.com/naomihauret/js-stack-from-scratch/) by [Naomi Hauret](https://twitter.com/naomihauret)\n- [Italian](https://github.com/fbertone/guida-javascript-moderno) by [Fabrizio Bertone](https://github.com/fbertone) - [fbertone.it](http://fbertone.it)\n- [Polish](https://github.com/mbiesiad/js-stack-from-scratch) by [@mbiesiad](https://github.com/mbiesiad)\n\nCheck out the [ongoing translations](https://github.com/verekia/js-stack-from-scratch/issues/147).\n\n### V1\n\n- [Chinese (simplified)](https://github.com/pd4d10/js-stack-from-scratch) by [@pd4d10](http://github.com/pd4d10)\n- [Italian](https://github.com/fbertone/js-stack-from-scratch) by [Fabrizio Bertone](https://github.com/fbertone)\n- [Japanese](https://github.com/takahashim/js-stack-from-scratch) by [@takahashim](https://github.com/takahashim)\n- [Russian](https://github.com/UsulPro/js-stack-from-scratch) by [React Theming](https://github.com/sm-react/react-theming)\n- [Thai](https://github.com/MicroBenz/js-stack-from-scratch) by [MicroBenz](https://github.com/MicroBenz)\n\n## Credits\n\nCreated by [@verekia](https://twitter.com/verekia) – [verekia.com](http://verekia.com/).\n\nLicense: MIT\n"
  },
  {
    "path": "how-to-translate.md",
    "content": "# How to translate this tutorial\n\nThank you for your interest in translating my tutorial! Here are a few recommendations to get started.\n\nThis 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!\n\nHere is what I think is a good workflow:\n\n- 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.\n\n- Join the [Translations Gitter room](https://gitter.im/js-stack-from-scratch/Translations) if you're feeling chatty.\n\n- Fork the main [English repository](https://github.com/verekia/js-stack-from-scratch).\n\n- Post in [this issue](https://github.com/verekia/js-stack-from-scratch/issues/147) the language and URL of your forked repo.\n\n- Translate the `README.md` files.\n\n- 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.\n\n- 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:\n\n```md\n## Translations\n\n- [Language](http://github.com/yourprofile/your-fork) by [You](http://yourwebsite.com)\nor\n- [Language](http://github.com/yourprofile/your-fork) by [@You](http://twitter.com/yourprofile)\nor\n- [Language](http://github.com/yourprofile/your-fork) by [@You](http://github.com/yourprofile)\n```\n\nSince 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).\n\n- 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:\n\n<!-- markdownlint-disable MD034 -->\nhttps://github.com/verekia/js-stack-from-scratch/compare/c65dfa65d02c21063d94f0955de90947ba5273ad...master\n<!-- markdownlint-enable MD034 -->\n\nThat should give you a easy-to-read diff to see exactly what changed in `README.md` files since your translation!\n"
  },
  {
    "path": "mdlint.js",
    "content": "const glob = require('glob')\nconst markdownlint = require('markdownlint')\n\nconst config = {\n  'default': true,\n  'line_length': false,\n  'no-emphasis-as-header': false,\n}\n\nconst files = glob.sync('**/*.md', { ignore: '**/node_modules/**' })\n\nmarkdownlint({ files, config }, (err, result) => {\n  if (!err) {\n    const resultString = result.toString()\n    console.log('== Linting Markdown Files...')\n    if (resultString) {\n      console.log(resultString)\n      process.exit(1)\n    } else {\n      console.log('== OK!')\n    }\n  }\n})\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"js-stack-from-scratch\",\n  \"version\": \"2.4.5\",\n  \"description\": \"JavaScript Stack from Scratch - Step-by-step tutorial to build a modern JavaScript stack\",\n  \"scripts\": {\n    \"test\": \"node mdlint.js\"\n  },\n  \"devDependencies\": {\n    \"glob\": \"^7.1.1\",\n    \"markdownlint\": \"^0.4.0\"\n  },\n  \"repository\": \"verekia/js-stack-from-scratch\",\n  \"author\": \"Jonathan Verrecchia - @verekia\",\n  \"license\": \"MIT\"\n}\n"
  },
  {
    "path": "tutorial/01-node-yarn-package-json.md",
    "content": "# 01 - Node, Yarn, and `package.json`\n\nCode for this chapter available [here](https://github.com/verekia/js-stack-walkthrough/tree/master/01-node-yarn-package-json).\n\nIn this section we will set up Node, Yarn, a basic `package.json` file, and try a package.\n\n## Node\n\n> 💡 **[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.\n\nWe 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.\n\nFor instance, on **Ubuntu / Debian**, you would run the following commands to install Node:\n\n```sh\ncurl -sL https://deb.nodesource.com/setup_7.x | sudo -E bash -\nsudo apt-get install -y nodejs\n```\n\nYou want any version of Node > 6.5.0.\n\n## Node Version Management Tools\n\nIf 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).\n\n## NPM\n\nNPM 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.\n\n## Yarn\n\n> 💡 **[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).\n\nSince 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`.\n\nInstall 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:\n\n```sh\ncurl -o- -L https://yarnpkg.com/install.sh | bash\n```\n\n## `package.json`\n\n> 💡 **[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*.\n\n- Create a new folder to work in, and `cd` in it.\n- Run `yarn init` and answer the questions (`yarn init -y` to skip all questions), to generate a `package.json` file automatically.\n\nHere is the basic `package.json` I'll use in this tutorial:\n\n```json\n{\n  \"name\": \"your-project\",\n  \"version\": \"1.0.0\",\n  \"license\": \"MIT\"\n}\n```\n\n## Hello World\n\n- Create an `index.js` file containing `console.log('Hello world')`\n\n🏁 Run `node .` in this folder (`index.js` is the default file Node looks for in a folder). It should print \"Hello world\".\n\n**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.\n\n## `start` script\n\nRunning `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.\n\n- In `package.json`, add a `scripts` object like so:\n\n```json\n{\n  \"name\": \"your-project\",\n  \"version\": \"1.0.0\",\n  \"license\": \"MIT\",\n  \"scripts\": {\n    \"start\": \"node .\"\n  }\n}\n```\n\n`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`.\n\n`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.\n\n🏁 Run `yarn start`. It should print `Hello world`.\n\n## Git and `.gitignore`\n\n- Initialize a Git repository with `git init`\n\n- Create a `.gitignore` file and add the following to it:\n\n```gitignore\n.DS_Store\n/*.log\n```\n\n`.DS_Store` files are auto-generated macOS files that you should never have in your repository.\n\n`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.\n\n## Installing and using a package\n\nIn 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.\n\n- Install the community-made package called `color` by running `yarn add color`\n\nOpen `package.json` to see how Yarn automatically added `color` in  `dependencies`.\n\nA `node_modules` folder has been created to store the package.\n\n- Add `node_modules/` to your `.gitignore`\n\nYou 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*.\n\n- Write the following to your `index.js` file:\n\n```js\nconst color = require('color')\n\nconst redHexa = color({ r: 255, g: 0, b: 0 }).hex()\n\nconsole.log(redHexa)\n```\n\n🏁 Run `yarn start`. It should print `#FF0000`.\n\nCongratulations, you installed and used a package!\n\n`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:\n\n- Run `yarn remove color`\n\n## Two kinds of dependencies\n\nThere are two kinds of package dependencies, `\"dependencies\"` and `\"devDependencies\"`:\n\n**Dependencies** are libraries you need for your application to function (React, Redux, Lodash, jQuery, etc). You install them with `yarn add [package]`.\n\n**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]`.\n\nNext section: [02 - Babel, ES6, ESLint, Flow, Jest, Husky](02-babel-es6-eslint-flow-jest-husky.md#readme)\n\nBack to the [table of contents](https://github.com/verekia/js-stack-from-scratch#table-of-contents).\n"
  },
  {
    "path": "tutorial/02-babel-es6-eslint-flow-jest-husky.md",
    "content": "# 02 - Babel, ES6, ESLint, Flow, Jest, and Husky\n\nCode for this chapter available [here](https://github.com/verekia/js-stack-walkthrough/tree/master/02-babel-es6-eslint-flow-jest-husky).\n\nWe're now going to use some ES6 syntax, which is a great improvement over the \"old\" ES5 syntax. All browsers and JS environments understand ES5 well, but not ES6. That's where a tool called Babel comes to the rescue!\n\n## Babel\n\n> 💡 **[Babel](https://babeljs.io/)** is a compiler that transforms ES6 code (and other things like React's JSX syntax) into ES5 code. It is very modular and can be used in tons of different [environments](https://babeljs.io/docs/setup/). It is by far the preferred ES5 compiler of the React community.\n\n- Move your `index.js` into a new `src` folder. This is where you will write your ES6 code. Remove the previous `color`-related code in `index.js`, and replace it with a simple:\n\n```js\nconst str = 'ES6'\nconsole.log(`Hello ${str}`)\n```\n\nWe're using a *template string* here, which is an ES6 feature that lets us inject variables directly inside the string without concatenation using `${}`. Note that template strings are created using **backquotes**.\n\n- Run `yarn add --dev babel-cli` to install the CLI interface for Babel.\n\nBabel CLI comes with [two executables](https://babeljs.io/docs/usage/cli/): `babel`, which compiles ES6 files into new ES5 files, and `babel-node`, which you can use to replace your call to the `node` binary and execute ES6 files directly on the fly. `babel-node` is great for development but it is heavy and not meant for production. In this chapter we are going to use `babel-node` to set up the development environment, and in the next one we'll use `babel` to build ES5 files for production.\n\n- In `package.json`, in your `start` script, replace `node .` with `babel-node src` (`index.js` is the default file Node looks for, which is why we can omit `index.js`).\n\nIf you try to run `yarn start` now, it should print the correct output, but Babel is not actually doing anything. That's because we didn't give it any information about which transformations we want to apply. The only reason it prints the right output is because Node natively understands ES6 without Babel's help. Some browsers or older versions of Node would not be so successful though!\n\n- Run `yarn add --dev babel-preset-env` to install a Babel preset package called `env`, which contains configurations for the most recent ECMAScript features supported by Babel.\n\n- Create a `.babelrc` file at the root of your project, which is a JSON file for your Babel configuration. Write the following to it to make Babel use the `env` preset:\n\n```json\n{\n  \"presets\": [\n    \"env\"\n  ]\n}\n```\n\n🏁 `yarn start` should still work, but it's actually doing something now. We can't really tell if it is though, since we're using `babel-node` to interpret ES6 code on the fly. You'll soon have a proof that your ES6 code is actually transformed when you reach the [ES6 modules syntax](#the-es6-modules-syntax) section of this chapter.\n\n## ES6\n\n> 💡 **[ES6](http://es6-features.org/)**: The most significant improvement of the JavaScript language. There are too many ES6 features to list them here but typical ES6 code uses classes with `class`, `const` and `let`, template strings, and arrow functions (`(text) => { console.log(text) }`).\n\n### Creating an ES6 class\n\n- Create a new file, `src/dog.js`, containing the following ES6 class:\n\n```js\nclass Dog {\n  constructor(name) {\n    this.name = name\n  }\n\n  bark() {\n    return `Wah wah, I am ${this.name}`\n  }\n}\n\nmodule.exports = Dog\n```\n\nIt should not look surprising to you if you've done OOP in the past in any language. It's relatively recent for JavaScript though. The class is exposed to the outside world via the `module.exports` assignment.\n\nIn `src/index.js`, write the following:\n\n```js\nconst Dog = require('./dog')\n\nconst toby = new Dog('Toby')\n\nconsole.log(toby.bark())\n```\n\nAs you can see, unlike the community-made package `color` that we used before, when we require one of our files, we use `./` in the `require()`.\n\n🏁 Run `yarn start` and it should print \"Wah wah, I am Toby\".\n\n### The ES6 modules syntax\n\nHere we simply replace `const Dog = require('./dog')` by `import Dog from './dog'`, which is the newer ES6 modules syntax (as opposed to \"CommonJS\" modules syntax). It is currently not natively supported by NodeJS, so this is your proof that Babel processes those ES6 files correctly.\n\nIn `dog.js`, we also replace `module.exports = Dog` by `export default Dog`\n\n🏁 `yarn start` should still print \"Wah wah, I am Toby\".\n\n## ESLint\n\n> 💡 **[ESLint](http://eslint.org)** is the linter of choice for ES6 code. A linter gives you recommendations about code formatting, which enforces style consistency in your code, and code you share with your team. It's also a great way to learn about JavaScript by making mistakes that ESLint will catch.\n\nESLint works with *rules*, and there are [many of them](http://eslint.org/docs/rules/). Instead of configuring the rules we want for our code ourselves, we will use the config created by Airbnb. This config uses a few plugins, so we need to install those as well.\n\nCheck out Airbnb's most recent [instructions](https://www.npmjs.com/package/eslint-config-airbnb) to install the config package and all its dependencies correctly. As of 2017-02-03, they recommend using the following command in your terminal:\n\n```sh\nnpm info eslint-config-airbnb@latest peerDependencies --json | command sed 's/[\\{\\},]//g ; s/: /@/g' | xargs yarn add --dev eslint-config-airbnb@latest\n```\n\nIt should install everything you need and add `eslint-config-airbnb`, `eslint-plugin-import`, `eslint-plugin-jsx-a11y`, and `eslint-plugin-react` to your `package.json` file automatically.\n\n**Note**: I've replaced `npm install` by `yarn add` in this command. Also, this won't work on Windows, so take a look at the `package.json` file of this repository and just install all the ESLint-related dependencies manually using `yarn add --dev packagename@^#.#.#` with `#.#.#` being the versions given in `package.json` for each package.\n\n- Create an `.eslintrc.json` file at the root of your project, just like we did for Babel, and write the following to it:\n\n```json\n{\n  \"extends\": \"airbnb\"\n}\n```\n\nWe'll create an NPM/Yarn script to run ESLint. Let's install the `eslint` package to be able to use the `eslint` CLI:\n\n- Run `yarn add --dev eslint`\n\nUpdate the `scripts` of your `package.json` to include a new `test` task:\n\n```json\n\"scripts\": {\n  \"start\": \"babel-node src\",\n  \"test\": \"eslint src\"\n},\n```\n\nHere we just tell ESLint that we want it to lint all JavaScript files under the `src` folder.\n\nWe will use this standard `test` task to run a chain of all the commands that validate our code, whether it's linting, type checking, or unit testing.\n\n- Run `yarn test`, and you should see a whole bunch of errors for missing semicolons, and a warning for using `console.log()` in `index.js`. Add `/* eslint-disable no-console */` at the top of our `index.js` file to allow the use of `console` in this file.\n\n**Note**: If you're on Windows, make sure you configure your editor and Git to use Unix LF line endings and not Windows CRLF. If your project is only used in Windows environments, you can add `\"linebreak-style\": [2, \"windows\"]` in ESLint's `rules` array (see the example below) to enforce CRLF instead.\n\n### Semicolons\n\nAlright, this is probably the most heated debate in the JavaScript community, let's talk about it for a minute. JavaScript has this thing called Automatic Semicolon Insertion, which allows you to write your code with or without semicolons. It really comes down to personal preference and there is no right and wrong on this topic. If you like the syntax of Python, Ruby, or Scala, you will probably enjoy omitting semicolons. If you prefer the syntax of Java, C#, or PHP, you will probably prefer using semicolons.\n\nMost people write JavaScript with semicolons, out of habit. That was my case until I tried going semicolon-less after seeing code samples from the Redux documentation. At first it felt a bit weird, simply because I was not used to it. After just one day of writing code this way I could not see myself going back to using semicolons at all. They felt so cumbersome and unnecessary. A semicolon-less code is easier on the eyes in my opinion, and is faster to type.\n\nI recommend reading the [ESLint documentation about semicolons](http://eslint.org/docs/rules/semi). As mentioned in this page, if you're going semicolon-less, there are some rather rare cases where semicolons are required. ESLint can protect you from such cases with the `no-unexpected-multiline` rule. Let's set up ESLint to safely go semicolon-less in `.eslintrc.json`:\n\n```json\n{\n  \"extends\": \"airbnb\",\n  \"rules\": {\n    \"semi\": [2, \"never\"],\n    \"no-unexpected-multiline\": 2\n  }\n}\n```\n\n🏁 Run `yarn test`, and it should now pass successfully. Try adding an unnecessary semicolon somewhere to make sure the rule is set up correctly.\n\nI am aware that some of you will want to keep using semicolons, which will make the code provided in this tutorial inconvenient. If you are using this tutorial just for learning, I'm sure it will remain bearable to learn without semicolons, until going back to using them on your real projects. If you want to use the code provided in this tutorial as a boilerplate though, it will require a bit of rewriting, which should be pretty quick with ESLint set to enforce semicolons to guide you through the process. I apologize if you're in such case.\n\n### Compat\n\n[Compat](https://github.com/amilajack/eslint-plugin-compat) is a neat ESLint plugin that warns you if you use some JavaScript APIs that are not available in the browsers you need to support. It uses [Browserslist](https://github.com/ai/browserslist), which relies on [Can I Use](http://caniuse.com/).\n\n- Run `yarn add --dev eslint-plugin-compat`\n\n- Add the following to your `package.json`, to indicate that we want to support browsers that have more than 1% market share:\n\n```json\n\"browserslist\": [\"> 1%\"],\n```\n\n- Edit your `.eslintrc.json` file like so:\n\n```json\n{\n  \"extends\": \"airbnb\",\n  \"plugins\": [\n    \"compat\"\n  ],\n  \"rules\": {\n    \"semi\": [2, \"never\"],\n    \"no-unexpected-multiline\": 2,\n    \"compat/compat\": 2\n  }\n}\n```\n\nYou can try the plugin by using `navigator.serviceWorker` or `fetch` in your code for instance, which should raise an ESLint warning.\n\n### ESLint in your editor\n\nThis chapter set you up with ESLint in the terminal, which is great for catching errors at build time / before pushing, but you also probably want it integrated to your IDE for immediate feedback. Do NOT use your IDE's native ES6 linting. Configure it so the binary it uses for linting is the one in your `node_modules` folder instead. This way it can use all of your project's config, the Airbnb preset, etc. Otherwise you will just get some generic ES6 linting.\n\n## Flow\n\n> 💡 **[Flow](https://flowtype.org/)**: A static type checker by Facebook. It detects inconsistent types in your code. For instance, it will give you an error if you try to use a string where should be using a number.\n\nRight now, our JavaScript code is valid ES6 code. Flow can analyze plain JavaScript to give us some insights, but in order to use its full power, we need to add type annotations in our code, which will make it non-standard. We need to teach Babel and ESLint what those type annotations are in order for these tools to not freak out when parsing our files.\n\n- Run `yarn add --dev flow-bin babel-preset-flow babel-eslint eslint-plugin-flowtype`\n\n`flow-bin` is the binary to run Flow in our `scripts` tasks, `babel-preset-flow` is the preset for Babel to understand Flow annotations, `babel-eslint` is a package to enable ESLint *to rely on Babel's parser* instead of its own, and `eslint-plugin-flowtype` is an ESLint plugin to lint Flow annotations. Phew.\n\n- Update your `.babelrc` file like so:\n\n```json\n{\n  \"presets\": [\n    \"env\",\n    \"flow\"\n  ]\n}\n```\n\n- And update `.eslintrc.json` as well:\n\n```json\n{\n  \"extends\": [\n    \"airbnb\",\n    \"plugin:flowtype/recommended\"\n  ],\n  \"plugins\": [\n    \"flowtype\",\n    \"compat\"\n  ],\n  \"rules\": {\n    \"semi\": [2, \"never\"],\n    \"no-unexpected-multiline\": 2,\n    \"compat/compat\": 2\n  }\n}\n```\n\n**Note**: The `plugin:flowtype/recommended` contains the instruction for ESLint to use Babel's parser. If you want to be more explicit, feel free to add `\"parser\": \"babel-eslint\"` in `.eslintrc.json`.\n\nI know this is a lot to take in, so take a minute to think about it. I'm still amazed that it is even possible for ESLint to use Babel's parser to understand Flow annotations. These 2 tools are really incredible for being so modular.\n\n- Chain `flow` to your `test` task:\n\n```json\n\"scripts\": {\n  \"start\": \"babel-node src\",\n  \"test\": \"eslint src && flow\"\n},\n```\n\n- Create a `.flowconfig` file at the root of your project containing:\n\n```flowconfig\n[options]\nsuppress_comment= \\\\(.\\\\|\\n\\\\)*\\\\flow-disable-next-line\n```\n\nThis is a little utility that we set up to make Flow ignore any warning detected on the next line. You would use it like this, similarly to `eslint-disable`:\n\n```js\n// flow-disable-next-line\nsomething.flow(doesnt.like).for.instance()\n```\n\nAlright, we should be all set for the configuration part.\n\n- Add Flow annotations to `src/dog.js` like so:\n\n```js\n// @flow\n\nclass Dog {\n  name: string\n\n  constructor(name: string) {\n    this.name = name\n  }\n\n  bark() {\n    return `Wah wah, I am ${this.name}`\n  }\n}\n\nexport default Dog\n```\n\nThe `// @flow` comment tells Flow that we want this file to be type-checked. For the rest, Flow annotations are typically a colon after a function parameter or a function name. Check out the [documentation](https://flowtype.org/docs/quick-reference.html) for more details.\n\n- Add `// @flow` at the top of `index.js` as well.\n\n`yarn test` should now both lint and type-check your code fine.\n\nThere are 2 things that I want you to try:\n\n- In `dog.js`, replace `constructor(name: string)` by `constructor(name: number)`, and run `yarn test`. You should get a **Flow** error telling you that those types are incompatible. That means Flow is set up correctly.\n\n- Now replace `constructor(name: string)` by `constructor(name:string)`, and run `yarn test`. You should get an **ESLint** error telling you that Flow annotations should have a space after the colon. That means the Flow plugin for ESLint is set up correctly.\n\n🏁 If you got the 2 different errors working, you are all set with Flow and ESLint! Remember to put the missing space back in the Flow annotation.\n\n### Flow in your editor\n\nJust like with ESLint, you should spend some time configuring your editor / IDE to give you immediate feedback when Flow detects issues in your code.\n\n## Jest\n\n> 💡 **[Jest](https://facebook.github.io/jest/)**: A JavaScript testing library by Facebook. It is very simple to set up and provides everything you would need from a testing library right out of the box. It can also test React components.\n\n- Run `yarn add --dev jest babel-jest` to install Jest and the package to make it use Babel.\n\n- Add the following to your `.eslintrc.json` at the root of the object to allow the use of Jest's functions without having to import them in every test file:\n\n```json\n\"env\": {\n  \"jest\": true\n}\n```\n\n- Create a `src/dog.test.js` file containing:\n\n```js\nimport Dog from './dog'\n\ntest('Dog.bark', () => {\n  const testDog = new Dog('Test')\n  expect(testDog.bark()).toBe('Wah wah, I am Test')\n})\n```\n\n- Add `jest` to your `test` script:\n\n```json\n\"scripts\": {\n  \"start\": \"babel-node src\",\n  \"test\": \"eslint src && flow && jest --coverage\"\n},\n```\n\nThe `--coverage` flag makes Jest generate coverage data for your tests automatically. This is useful to see which parts of your codebase lack testing. It writes this data into a `coverage` folder.\n\n- Add `/coverage/` to your `.gitignore`\n\n🏁 Run `yarn test`. After linting and type checking, it should run Jest tests and show a coverage table. Everything should be green!\n\n## Git Hooks with Husky\n\n> 💡 **[Git Hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks)**: Scripts that are run when certain actions like a commit or a push occur.\n\nOkay so we now have this neat `test` task that tells us if our code looks good or not. We're going to set up Git Hooks to automatically run this task before every `git commit` and `git push`, which will prevent us from pushing bad code to the repository if it doesn't pass the `test` task.\n\n[Husky](https://github.com/typicode/husky) is a package that makes this very easy to set up Git Hooks.\n\n- Run `yarn add --dev husky`\n\nAll we have to do is to create two new tasks in `scripts`, `precommit` and `prepush`:\n\n```json\n\"scripts\": {\n  \"start\": \"babel-node src\",\n  \"test\": \"eslint src && flow && jest --coverage\",\n  \"precommit\": \"yarn test\",\n  \"prepush\": \"yarn test\"\n},\n```\n\n🏁 If you now try to commit or push your code, it should automatically run the `test` task.\n\nIf it does not work, it is possible that `yarn add --dev husky` did not install the Git Hooks properly. I have never encountered this issue but it happens for some people. If that's your case, run `yarn add --dev husky --force`, and maybe post a note describing your situation in [this issue](https://github.com/typicode/husky/issues/84).\n\n**Note**: If you are pushing right after a commit, you can use `git push --no-verify` to avoid running all the tests again.\n\nNext section: [03 - Express, Nodemon, PM2](03-express-nodemon-pm2.md#readme)\n\nBack to the [previous section](01-node-yarn-package-json.md#readme) or the [table of contents](https://github.com/verekia/js-stack-from-scratch#table-of-contents).\n"
  },
  {
    "path": "tutorial/03-express-nodemon-pm2.md",
    "content": "# 03 - Express, Nodemon, and PM2\n\nCode for this chapter available [here](https://github.com/verekia/js-stack-walkthrough/tree/master/03-express-nodemon-pm2).\n\nIn 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.\n\n## Express\n\n> 💡 **[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*.\n\nLet's set up a minimal Express server to serve an HTML page with some CSS.\n\n- Delete everything inside `src`\n\nCreate the following files and folders:\n\n- Create a `public/css/style.css` file containing:\n\n```css\nbody {\n  width: 960px;\n  margin: auto;\n  font-family: sans-serif;\n}\n\nh1 {\n  color: limegreen;\n}\n```\n\n- Create an empty `src/client/` folder.\n\n- Create an empty `src/shared/` folder.\n\nThis 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.\n\n- Create a `src/shared/config.js` file, containing:\n\n```js\n// @flow\n\nexport const WEB_PORT = process.env.PORT || 8000\nexport const STATIC_PATH = '/static'\nexport const APP_NAME = 'Hello App'\n```\n\nIf 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`.\n\n- Create a `src/shared/util.js` file containing:\n\n```js\n// @flow\n\n// eslint-disable-next-line import/prefer-default-export\nexport const isProd = process.env.NODE_ENV === 'production'\n```\n\nThat'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.\n\n- Run `yarn add express compression`\n\n`compression` is an Express middleware to activate Gzip compression on the server.\n\n- Create a `src/server/index.js` file containing:\n\n```js\n// @flow\n\nimport compression from 'compression'\nimport express from 'express'\n\nimport { APP_NAME, STATIC_PATH, WEB_PORT } from '../shared/config'\nimport { isProd } from '../shared/util'\nimport renderApp from './render-app'\n\nconst app = express()\n\napp.use(compression())\napp.use(STATIC_PATH, express.static('dist'))\napp.use(STATIC_PATH, express.static('public'))\n\napp.get('/', (req, res) => {\n  res.send(renderApp(APP_NAME))\n})\n\napp.listen(WEB_PORT, () => {\n  // eslint-disable-next-line no-console\n  console.log(`Server running on port ${WEB_PORT} ${isProd ? '(production)' : '(development)'}.`)\n})\n```\n\nNothing 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.\n\n- Create a `src/server/render-app.js` file containing:\n\n```js\n// @flow\n\nimport { STATIC_PATH } from '../shared/config'\n\nconst renderApp = (title: string) =>\n`<!doctype html>\n<html>\n  <head>\n    <title>${title}</title>\n    <link rel=\"stylesheet\" href=\"${STATIC_PATH}/css/style.css\">\n  </head>\n  <body>\n    <h1>${title}</h1>\n  </body>\n</html>\n`\n\nexport default renderApp\n```\n\nYou know how you typically have *templating engines* on the back-end? Well these are pretty much obsolete now that JavaScript supports template strings. Here we create a function that takes a `title` as a parameter and injects it in both the `title` and `h1` tags of the page, returning the complete HTML string. We also use a `STATIC_PATH` constant as the base path for all our static assets.\n\n### HTML template strings syntax highlighting in Atom (optional)\n\nIt might be possible to get syntax highlighting working for HTML code inside template strings depending on your editor. In Atom, if you prefix your template string with an `html` tag (or any tag that *ends* with `html`, like `ilovehtml`), it will automatically highlight the content of that string. I sometimes use the `html` tag of the `common-tags` library to take advantage of this:\n\n```js\nimport { html } from `common-tags`\n\nconst template = html`\n<div>Wow, colors!</div>\n`\n```\n\nI did not include this trick in the boilerplate of this tutorial, since it seems to only work in Atom, and it's less than ideal. Some of you Atom users might find it useful though.\n\nAnyway, back to business!\n\n- In `package.json` change your `start` script like so: `\"start\": \"babel-node src/server\",`\n\n🏁 Run `yarn start`, and hit `localhost:8000` in your browser. If everything works as expected you should see a blank page with \"Hello App\" written both on the tab title and as a green heading on the page.\n\n**Note**: Some processes – typically processes that wait for things to happen, like a server for instance – will prevent you from entering commands in your terminal until they're done. To interrupt such processes and get your prompt back, press **Ctrl+C**. You can alternatively open a new terminal tab if you want to keep them running while being able to enter commands. You can also make these processes run in the background but that's out of the scope of this tutorial.\n\n## Nodemon\n\n> 💡 **[Nodemon](https://nodemon.io/)** is a utility to automatically restart your Node server when file changes happen in the directory.\n\nWe are going to use Nodemon whenever we are in **development** mode.\n\n- Run `yarn add --dev nodemon`\n\n- Change your `scripts` like so:\n\n```json\n\"start\": \"yarn dev:start\",\n\"dev:start\": \"nodemon --ignore lib --exec babel-node src/server\",\n```\n\n`start` is now just a pointer to an other task, `dev:start`. That gives us a layer of abstraction to tweak what the default task is.\n\nIn `dev:start`, the `--ignore lib` flag is to *not* restart the server when changes happen in the `lib` directory. You don't have this directory yet, but we're going to generate it in the next section of this chapter, so it will soon make sense. Nodemon typically runs the `node` binary. In our case, since we're using Babel, we can tell Nodemon to use the `babel-node` binary instead. This way it will understand all the ES6/Flow code.\n\n🏁 Run `yarn start` and open `localhost:8000`. Go ahead and change the `APP_NAME` constant in `src/shared/config.js`, which should trigger a restart of your server in the terminal. Refresh the page to see the updated title. Note that this automatic restart of the server is different from *Hot Module Replacement*, which is when components on the page update in real-time. Here we still need a manual refresh, but at least we don't need to kill the process and restart it manually to see changes. Hot Module Replacement will be introduced in the next chapter.\n\n## PM2\n\n> 💡 **[PM2](http://pm2.keymetrics.io/)** is a Process Manager for Node. It keeps your processes alive in production, and offers tons of features to manage them and monitor them.\n\nWe are going to use PM2 whenever we are in **production** mode.\n\n- Run `yarn add --dev pm2`\n\nIn production, you want your server to be as performant as possible. `babel-node` triggers the whole Babel transpilation process for your files at each execution, which is not something you want in production. We need Babel to do all this work beforehand, and have our server serve plain old pre-compiled ES5 files.\n\nOne of the main features of Babel is to take a folder of ES6 code (usually named `src`) and transpile it into a folder of ES5 code (usually named `lib`).\n\nThis `lib` folder being auto-generated, it's a good practice to clean it up before a new build, since it may contain unwanted old files. A neat simple package to delete files with cross platform support is `rimraf`.\n\n- Run `yarn add --dev rimraf`\n\nLet's add the following `prod:build` task to our `scripts`:\n\n```json\n\"prod:build\": \"rimraf lib && babel src -d lib --ignore .test.js\",\n```\n\n- Run `yarn prod:build`, and it should generate a `lib` folder containing the transpiled code, except for files ending in `.test.js` (note that `.test.jsx` files are also ignored by this parameter).\n\n- Add `/lib/` to your `.gitignore`\n\nOne last thing: We are going to pass a `NODE_ENV` environment variable to our PM2 binary. With Unix, you would do this by running `NODE_ENV=production pm2`, but Windows uses a different syntax. We're going to use a small package called `cross-env` to make this syntax work on Windows as well.\n\n- Run `yarn add --dev cross-env`\n\nLet's update our `package.json` like so:\n\n```json\n\"scripts\": {\n  \"start\": \"yarn dev:start\",\n  \"dev:start\": \"nodemon --ignore lib --exec babel-node src/server\",\n  \"prod:build\": \"rimraf lib && babel src -d lib --ignore .test.js\",\n  \"prod:start\": \"cross-env NODE_ENV=production pm2 start lib/server && pm2 logs\",\n  \"prod:stop\": \"pm2 delete server\",\n  \"test\": \"eslint src && flow && jest --coverage\",\n  \"precommit\": \"yarn test\",\n  \"prepush\": \"yarn test\"\n},\n```\n\n🏁 Run `yarn prod:build`, then run `yarn prod:start`. PM2 should show an active process. Go to `http://localhost:8000/` in your browser and you should see your app. Your terminal should show the logs, which should be \"Server running on port 8000 (production).\". Note that with PM2, your processes are run in the background. If you press Ctrl+C, it will kill the `pm2 logs` command, which was the last command our our `prod:start` chain, but the server should still render the page. If you want to stop the server, run `yarn prod:stop`\n\nNow that we have a `prod:build` task, it would be neat to make sure it works fine before pushing code to the repository. Since it is probably unnecessary to run it for every commit, I suggest adding it to the `prepush` task:\n\n```json\n\"prepush\": \"yarn test && yarn prod:build\"\n```\n\n🏁 Run `yarn prepush` or just push your files to trigger the process.\n\n**Note**: We don't have any test here, so Jest will complain a bit. Ignore it for now.\n\nNext section: [04 - Webpack, React, HMR](04-webpack-react-hmr.md#readme)\n\nBack to the [previous section](02-babel-es6-eslint-flow-jest-husky.md#readme) or the [table of contents](https://github.com/verekia/js-stack-from-scratch#table-of-contents).\n"
  },
  {
    "path": "tutorial/04-webpack-react-hmr.md",
    "content": "# 04 - Webpack, React, and Hot Module Replacement\n\nCode for this chapter available [here](https://github.com/verekia/js-stack-walkthrough/tree/master/04-webpack-react-hmr).\n\n## Webpack\n\n> 💡 **[Webpack](https://webpack.js.org/)** is a *module bundler*. It takes a whole bunch of various source files, processes them, and assembles them into one (usually) JavaScript file called a bundle, which is the only file your client will execute.\n\nLet's create some very basic *hello world* and bundle it with Webpack.\n\n- In `src/shared/config.js`, add the following constants:\n\n```js\nexport const WDS_PORT = 7000\n\nexport const APP_CONTAINER_CLASS = 'js-app'\nexport const APP_CONTAINER_SELECTOR = `.${APP_CONTAINER_CLASS}`\n```\n\n- Create an `src/client/index.js` file containing:\n\n```js\nimport 'babel-polyfill'\n\nimport { APP_CONTAINER_SELECTOR } from '../shared/config'\n\ndocument.querySelector(APP_CONTAINER_SELECTOR).innerHTML = '<h1>Hello Webpack!</h1>'\n```\n\nIf you want to use some of the most recent ES features in your client code, like `Promise`s, you need to include the [Babel Polyfill](https://babeljs.io/docs/usage/polyfill/) before anything else in your bundle.\n\n- Run `yarn add babel-polyfill`\n\nIf you run ESLint on this file, it will complain about `document` being undefined.\n\n- Add the following to `env` in your `.eslintrc.json` to allow the use of `window` and `document`:\n\n```json\n\"env\": {\n  \"browser\": true,\n  \"jest\": true\n}\n```\n\nAlright, we now need to bundle this ES6 client app into an ES5 bundle.\n\n- Create a `webpack.config.babel.js` file containing:\n\n```js\n// @flow\n\nimport path from 'path'\n\nimport { WDS_PORT } from './src/shared/config'\nimport { isProd } from './src/shared/util'\n\nexport default {\n  entry: [\n    './src/client',\n  ],\n  output: {\n    filename: 'js/bundle.js',\n    path: path.resolve(__dirname, 'dist'),\n    publicPath: isProd ? '/static/' : `http://localhost:${WDS_PORT}/dist/`,\n  },\n  module: {\n    rules: [\n      { test: /\\.(js|jsx)$/, use: 'babel-loader', exclude: /node_modules/ },\n    ],\n  },\n  devtool: isProd ? false : 'source-map',\n  resolve: {\n    extensions: ['.js', '.jsx'],\n  },\n  devServer: {\n    port: WDS_PORT,\n  },\n}\n```\n\nThis file is used to describe how our bundle should be assembled: `entry` is the starting point of our app, `output.filename` is the name of the bundle to generate, `output.path` and `output.publicPath` describe the destination folder and URL. We put the bundle in a `dist` folder, which will contain things that are generated automatically (unlike the declarative CSS we created earlier which lives in `public`). `module.rules` is where you tell Webpack to apply some treatment to some type of files. Here we say that we want all `.js` and `.jsx` (for React) files except the ones in `node_modules` to go through something called `babel-loader`. We also want these two extensions to be used to `resolve` modules when we `import` them. Finally, we declare a port for Webpack Dev Server.\n\n**Note**: The `.babel.js` extension is a Webpack feature to apply our Babel transformations to this config file.\n\n`babel-loader` is a plugin for Webpack that transpiles your code just like we've been doing since the beginning of this tutorial. The only difference is that this time, the code will end up running in the browser instead of your server.\n\n- Run `yarn add --dev webpack webpack-dev-server babel-core babel-loader`\n\n`babel-core` is a peer-dependency of `babel-loader`, so we installed it as well.\n\n- Add `/dist/` to your `.gitignore`\n\n### Tasks update\n\nIn development mode, we are going to use `webpack-dev-server` to take advantage of Hot Module Reloading (later in this chapter), and in production we'll simply use `webpack` to generate bundles. In both cases, the `--progress` flag is useful to display additional information when Webpack is compiling your files. In production, we'll also pass the `-p` flag to `webpack` to minify our code, and the `NODE_ENV` variable set to `production`.\n\nLet's update our `scripts` to implement all this, and improve some other tasks as well:\n\n```json\n\"scripts\": {\n  \"start\": \"yarn dev:start\",\n  \"dev:start\": \"nodemon -e js,jsx --ignore lib --ignore dist --exec babel-node src/server\",\n  \"dev:wds\": \"webpack-dev-server --progress\",\n  \"prod:build\": \"rimraf lib dist && babel src -d lib --ignore .test.js && cross-env NODE_ENV=production webpack -p --progress\",\n  \"prod:start\": \"cross-env NODE_ENV=production pm2 start lib/server && pm2 logs\",\n  \"prod:stop\": \"pm2 delete server\",\n  \"lint\": \"eslint src webpack.config.babel.js --ext .js,.jsx\",\n  \"test\": \"yarn lint && flow && jest --coverage\",\n  \"precommit\": \"yarn test\",\n  \"prepush\": \"yarn test && yarn prod:build\"\n},\n```\n\nIn `dev:start` we explicitly declare file extensions to monitor, `.js` and `.jsx`, and add `dist` in the ignored directories.\n\nWe created a separate `lint` task and added `webpack.config.babel.js` to the files to lint.\n\n- Next, let's create the container for our app in `src/server/render-app.js`, and include the bundle that will be generated:\n\n```js\n// @flow\n\nimport { APP_CONTAINER_CLASS, STATIC_PATH, WDS_PORT } from '../shared/config'\nimport { isProd } from '../shared/util'\n\nconst renderApp = (title: string) =>\n`<!doctype html>\n<html>\n  <head>\n    <title>${title}</title>\n    <link rel=\"stylesheet\" href=\"${STATIC_PATH}/css/style.css\">\n  </head>\n  <body>\n    <div class=\"${APP_CONTAINER_CLASS}\"></div>\n    <script src=\"${isProd ? STATIC_PATH : `http://localhost:${WDS_PORT}/dist`}/js/bundle.js\"></script>\n  </body>\n</html>\n`\n\nexport default renderApp\n```\n\nDepending on the environment we're in, we'll include either the Webpack Dev Server bundle, or the production bundle. Note that the path to Webpack Dev Server's bundle is *virtual*, `dist/js/bundle.js` is not actually read from your hard drive in development mode. It's also necessary to give Webpack Dev Server a different port than your main web port.\n\n- Finally, in `src/server/index.js`, tweak your `console.log` message like so:\n\n```js\nconsole.log(`Server running on port ${WEB_PORT} ${isProd ? '(production)' :\n  '(development).\\nKeep \"yarn dev:wds\" running in an other terminal'}.`)\n```\n\nThat will give other developers a hint about what to do if they try to just run `yarn start` without Webpack Dev Server.\n\nAlright that was a lot of changes, let's see if everything works as expected:\n\n🏁 Run `yarn start` in a terminal. Open an other terminal tab or window, and run `yarn dev:wds` in it. Once Webpack Dev Server is done generating the bundle and its sourcemaps (which should both be ~600kB files) and both processes hang in your terminals, open `http://localhost:8000/` and you should see \"Hello Webpack!\". Open your Chrome console, and under the Source tab, check which files are included. You should only see `static/css/style.css` under `localhost:8000/`, and have all your ES6 source files under `webpack://./src`. That means sourcemaps are working. In your editor, in `src/client/index.js`, try changing `Hello Webpack!` into any other string. As you save the file, Webpack Dev Server in your terminal should generate a new bundle and the Chrome tab should reload automatically.\n\n- Kill the previous processes in your terminals with Ctrl+C, then run `yarn prod:build`, and then `yarn prod:start`. Open `http://localhost:8000/` and you should still see \"Hello Webpack!\". In the Source tab of the Chrome console, you should this time find `static/js/bundle.js` under `localhost:8000/`, but no `webpack://` sources. Click on `bundle.js` to make sure it is minified. Run `yarn prod:stop`.\n\nGood job, I know this was quite dense. You deserve a break! The next section is easier.\n\n**Note**: I would recommend to have at least 3 terminals open, one for your Express server, one for the Webpack Dev Server, and one for Git, tests, and general commands like installing packages with `yarn`. Ideally, you should split your terminal screen in multiple panes to see them all.\n\n## React\n\n> 💡 **[React](https://facebook.github.io/react/)** is a library for building user interfaces by Facebook. It uses the **[JSX](https://facebook.github.io/react/docs/jsx-in-depth.html)** syntax to represent HTML elements and components while leveraging the power of JavaScript.\n\nIn this section we are going to render some text using React and JSX.\n\nFirst, let's install React and ReactDOM:\n\n- Run `yarn add react react-dom`\n\nRename your `src/client/index.js` file into `src/client/index.jsx` and write some React code in it:\n\n```js\n// @flow\n\nimport 'babel-polyfill'\n\nimport React from 'react'\nimport ReactDOM from 'react-dom'\n\nimport App from './app'\nimport { APP_CONTAINER_SELECTOR } from '../shared/config'\n\nReactDOM.render(<App />, document.querySelector(APP_CONTAINER_SELECTOR))\n```\n\n- Create a `src/client/app.jsx` file containing:\n\n```js\n// @flow\n\nimport React from 'react'\n\nconst App = () => <h1>Hello React!</h1>\n\nexport default App\n```\n\nSince we use the JSX syntax here, we have to tell Babel that it needs to transform it with the `babel-preset-react` preset. And while we're at it, we're also going to add a Babel plugin called `flow-react-proptypes` which automatically generates PropTypes from Flow annotations for your React components.\n\n- Run `yarn add --dev babel-preset-react babel-plugin-flow-react-proptypes` and edit your `.babelrc` file like so:\n\n```json\n{\n  \"presets\": [\n    \"env\",\n    \"flow\",\n    \"react\"\n  ],\n  \"plugins\": [\n    \"flow-react-proptypes\"\n  ]\n}\n```\n\n🏁 Run `yarn start` and `yarn dev:wds` and hit `http://localhost:8000`. You should see \"Hello React!\".\n\nNow try changing the text in `src/client/app.jsx` to something else. Webpack Dev Server should reload the page automatically, which is pretty neat, but we are going to make it even better.\n\n## Hot Module Replacement\n\n> 💡 **[Hot Module Replacement](https://webpack.js.org/concepts/hot-module-replacement/)** (*HMR*) is a powerful Webpack feature to replace a module on the fly without reloading the entire page.\n\nTo make HMR work with React, we are going to need to tweak a few things.\n\n- Run `yarn add react-hot-loader@next`\n\n- Edit your `webpack.config.babel.js` like so:\n\n```js\nimport webpack from 'webpack'\n// [...]\nentry: [\n  'react-hot-loader/patch',\n  './src/client',\n],\n// [...]\ndevServer: {\n  port: WDS_PORT,\n  hot: true,\n  headers: {\n    'Access-Control-Allow-Origin': '*',\n  },\n},\nplugins: [\n  new webpack.optimize.OccurrenceOrderPlugin(),\n  new webpack.HotModuleReplacementPlugin(),\n  new webpack.NamedModulesPlugin(),\n  new webpack.NoEmitOnErrorsPlugin(),\n],\n```\n\nThe `headers` bit is to allow Cross-Origin Resource Sharing which is necessary for HMR.\n\n- Edit your `src/client/index.jsx` file:\n\n```js\n// @flow\n\nimport 'babel-polyfill'\n\nimport React from 'react'\nimport ReactDOM from 'react-dom'\nimport { AppContainer } from 'react-hot-loader'\n\nimport App from './app'\nimport { APP_CONTAINER_SELECTOR } from '../shared/config'\n\nconst rootEl = document.querySelector(APP_CONTAINER_SELECTOR)\n\nconst wrapApp = AppComponent =>\n  <AppContainer>\n    <AppComponent />\n  </AppContainer>\n\nReactDOM.render(wrapApp(App), rootEl)\n\nif (module.hot) {\n  // flow-disable-next-line\n  module.hot.accept('./app', () => {\n    // eslint-disable-next-line global-require\n    const NextApp = require('./app').default\n    ReactDOM.render(wrapApp(NextApp), rootEl)\n  })\n}\n```\n\nWe need to make our `App` a child of `react-hot-loader`'s `AppContainer`, and we need to `require` the next version of our `App` when hot-reloading. To make this  process clean and DRY, we create a little `wrapApp` function that we use in both places it needs to render `App`. Feel free to move the `eslint-disable global-require` to the top of the file to make this more readable.\n\n🏁 Restart your `yarn dev:wds` process if it was still running. Open `localhost:8000`. In the Console tab, you should see some logs about HMR. Go ahead and change something in `src/client/app.jsx` and your changes should be reflected in your browser after a few seconds, without any full-page reload!\n\nNext section: [05 - Redux, Immutable, Fetch](05-redux-immutable-fetch.md#readme)\n\nBack to the [previous section](03-express-nodemon-pm2.md#readme) or the [table of contents](https://github.com/verekia/js-stack-from-scratch#table-of-contents).\n"
  },
  {
    "path": "tutorial/05-redux-immutable-fetch.md",
    "content": "# 05 - Redux, Immutable, and Fetch\n\nCode for this chapter available [here](https://github.com/verekia/js-stack-walkthrough/tree/master/05-redux-immutable-fetch).\n\nIn this chapter we will hook up React and Redux to make a very simple app. The app will consist of a message and a button. The message changes when the user clicks the button.\n\nBefore we start, here is a very quick introduction to ImmutableJS, which is completely unrelated to React and Redux, but will be used in this chapter.\n\n## ImmutableJS\n\n> 💡 **[ImmutableJS](https://facebook.github.io/immutable-js/)** (or just Immutable) is a library by Facebook to manipulate immutable collections, like lists and maps. Any change made on an immutable object returns a new object without mutating the original object.\n\nFor instance, instead of doing:\n\n```js\nconst obj = { a: 1 }\nobj.a = 2 // Mutates `obj`\n```\n\nYou would do:\n\n```js\nconst obj = Immutable.Map({ a: 1 })\nobj.set('a', 2) // Returns a new object without mutating `obj`\n```\n\nThis approach follows the **functional programming** paradigm, which works really well with Redux.\n\nWhen creating immutable collections, a very convenient method is `Immutable.fromJS()`, which takes any regular JS object or array and returns a deeply immutable version of it:\n\n```js\nconst immutablePerson = Immutable.fromJS({\n  name: 'Stan',\n  friends: ['Kyle', 'Cartman', 'Kenny'],\n})\n\nconsole.log(immutablePerson)\n\n/*\n *  Map {\n *    \"name\": \"Stan\",\n *    \"friends\": List [ \"Kyle\", \"Cartman\", \"Kenny\" ]\n *  }\n */\n```\n\n- Run `yarn add immutable@4.0.0-rc.2`\n\n## Redux\n\n> 💡 **[Redux](http://redux.js.org/)** is a library to handle the lifecycle of your application. It creates a *store*, which is the single source of truth of the state of your app at any given time.\n\nLet's start with the easy part, declaring our Redux actions:\n\n- Run `yarn add redux redux-actions`\n\n- Create a `src/client/action/hello.js` file containing:\n\n```js\n// @flow\n\nimport { createAction } from 'redux-actions'\n\nexport const SAY_HELLO = 'SAY_HELLO'\n\nexport const sayHello = createAction(SAY_HELLO)\n```\n\nThis file exposes an *action*, `SAY_HELLO`, and its *action creator*, `sayHello`, which is a function. We use [`redux-actions`](https://github.com/acdlite/redux-actions) to reduce the boilerplate associated with Redux actions. `redux-actions` implement the [Flux Standard Action](https://github.com/acdlite/flux-standard-action) model, which makes *action creators* return objects with the `type` and `payload` attributes.\n\n- Create a `src/client/reducer/hello.js` file containing:\n\n```js\n// @flow\n\nimport Immutable from 'immutable'\nimport type { fromJS as Immut } from 'immutable'\n\nimport { SAY_HELLO } from '../action/hello'\n\nconst initialState = Immutable.fromJS({\n  message: 'Initial reducer message',\n})\n\nconst helloReducer = (state: Immut = initialState, action: { type: string, payload: any }) => {\n  switch (action.type) {\n    case SAY_HELLO:\n      return state.set('message', action.payload)\n    default:\n      return state\n  }\n}\n\nexport default helloReducer\n```\n\nIn this file we initialize the state of our reducer with an Immutable Map containing one property, `message`, set to `Initial reducer message`. The `helloReducer` handles `SAY_HELLO` actions by simply setting the new `message` with the action payload. The Flow annotation for `action` destructures it into a `type` and a `payload`. The `payload` can be of `any` type. It looks funky if you've never seen this before, but it remains pretty understandable. For the type of `state`, we use the `import type` Flow instruction to get the return type of `fromJS`. We rename it to `Immut` for clarity, because `state: fromJS` would be pretty confusing. The `import type` line will get stripped out like any other Flow annotation. Note the usage of `Immutable.fromJS()` and `set()` as seen before.\n\n## React-Redux\n\n> 💡 **[react-redux](https://github.com/reactjs/react-redux)** *connects* a Redux store with React components. With `react-redux`, when the Redux store changes, React components get automatically updated. They can also fire Redux actions.\n\n- Run `yarn add react-redux`\n\nIn this section we are going to create *Components* and *Containers*.\n\n**Components** are *dumb* React components, in a sense that they don't know anything about the Redux state. **Containers** are *smart* components that know about the state and that we are going to *connect* to our dumb components.\n\n- Create a `src/client/component/button.jsx` file containing:\n\n```js\n// @flow\n\nimport React from 'react'\n\ntype Props = {\n  label: string,\n  handleClick: Function,\n}\n\nconst Button = ({ label, handleClick }: Props) =>\n  <button onClick={handleClick}>{label}</button>\n\nexport default Button\n```\n\n**Note**: You can see a case of Flow *type alias* here. We define the `Props` type before annotating our component's destructured `props` with it.\n\n- Create a `src/client/component/message.jsx` file containing:\n\n```js\n// @flow\n\nimport React from 'react'\n\ntype Props = {\n  message: string,\n}\n\nconst Message = ({ message }: Props) =>\n  <p>{message}</p>\n\nexport default Message\n```\n\nThese are examples of *dumb* components. They are logic-less, and just show whatever they are asked to show via React **props**. The main difference between `button.jsx` and `message.jsx` is that `Button` contains a reference to an action dispatcher in its props, where `Message` just contains some data to show.\n\nAgain, *components* don't know anything about Redux **actions** or the **state** of our app, which is why we are going to create smart **containers** that will feed the proper action dispatchers and data to these 2 dumb components.\n\n- Create a `src/client/container/hello-button.js` file containing:\n\n```js\n// @flow\n\nimport { connect } from 'react-redux'\n\nimport { sayHello } from '../action/hello'\nimport Button from '../component/button'\n\nconst mapStateToProps = () => ({\n  label: 'Say hello',\n})\n\nconst mapDispatchToProps = dispatch => ({\n  handleClick: () => { dispatch(sayHello('Hello!')) },\n})\n\nexport default connect(mapStateToProps, mapDispatchToProps)(Button)\n```\n\nThis container hooks up the `Button` component with the `sayHello` action and Redux's `dispatch` method.\n\n- Create a `src/client/container/message.js` file containing:\n\n```js\n// @flow\n\nimport { connect } from 'react-redux'\n\nimport Message from '../component/message'\n\nconst mapStateToProps = state => ({\n  message: state.hello.get('message'),\n})\n\nexport default connect(mapStateToProps)(Message)\n```\n\nThis container hooks up the Redux's app state with the `Message` component. When the state changes, `Message` will now automatically re-render with the proper `message` prop. These connections are done via the `connect` function of `react-redux`.\n\n- Update your `src/client/app.jsx` file like so:\n\n```js\n// @flow\n\nimport React from 'react'\nimport HelloButton from './container/hello-button'\nimport Message from './container/message'\nimport { APP_NAME } from '../shared/config'\n\nconst App = () =>\n  <div>\n    <h1>{APP_NAME}</h1>\n    <Message />\n    <HelloButton />\n  </div>\n\nexport default App\n```\n\nWe still haven't initialized the Redux store and haven't put the 2 containers anywhere in our app yet:\n\n- Edit `src/client/index.jsx` like so:\n\n```js\n// @flow\n\nimport 'babel-polyfill'\n\nimport React from 'react'\nimport ReactDOM from 'react-dom'\nimport { AppContainer } from 'react-hot-loader'\nimport { Provider } from 'react-redux'\nimport { createStore, combineReducers } from 'redux'\n\nimport App from './app'\nimport helloReducer from './reducer/hello'\nimport { APP_CONTAINER_SELECTOR } from '../shared/config'\nimport { isProd } from '../shared/util'\n\nconst store = createStore(combineReducers({ hello: helloReducer }),\n  // eslint-disable-next-line no-underscore-dangle\n  isProd ? undefined : window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__())\n\nconst rootEl = document.querySelector(APP_CONTAINER_SELECTOR)\n\nconst wrapApp = (AppComponent, reduxStore) =>\n  <Provider store={reduxStore}>\n    <AppContainer>\n      <AppComponent />\n    </AppContainer>\n  </Provider>\n\nReactDOM.render(wrapApp(App, store), rootEl)\n\nif (module.hot) {\n  // flow-disable-next-line\n  module.hot.accept('./app', () => {\n    // eslint-disable-next-line global-require\n    const NextApp = require('./app').default\n    ReactDOM.render(wrapApp(NextApp, store), rootEl)\n  })\n}\n```\n\nLet's take a moment to review this. First, we create a *store* with `createStore`. Stores are created by passing reducers to them. Here we only have one reducer, but for the sake of future scalability, we use `combineReducers` to group all of our reducers together. The last weird parameter of `createStore` is something to hook up Redux to browser [Devtools](https://github.com/zalmoxisus/redux-devtools-extension), which are incredibly useful when debugging. Since ESLint will complain about the underscores in `__REDUX_DEVTOOLS_EXTENSION__`, we disable this ESLint rule. Next, we conveniently wrap our entire app inside `react-redux`'s `Provider` component thanks to our `wrapApp` function, and pass our store to it.\n\n🏁 You can now run `yarn start` and `yarn dev:wds` and hit `http://localhost:8000`. You should see \"Initial reducer message\" and a button. When you click the button, the message should change to \"Hello!\". If you installed the Redux Devtools in your browser, you should see the app state change over time as you click on the button.\n\nCongratulations, we finally made an app that does something! Okay it's not a *super* impressive from the outside, but we all know that it is powered by one badass stack under the hood.\n\n## Extending our app with an asynchronous call\n\nWe are now going to add a second button to our app, which will trigger an AJAX call to retrieve a message from the server. For the sake of demonstration, this call will also send some data, the hard-coded number `1234`.\n\n### The server endpoint\n\n- Create a `src/shared/routes.js` file containing:\n\n```js\n// @flow\n\n// eslint-disable-next-line import/prefer-default-export\nexport const helloEndpointRoute = (num: ?number) => `/ajax/hello/${num || ':num'}`\n```\n\nThis function is a little helper to produce the following:\n\n```js\nhelloEndpointRoute()     // -> '/ajax/hello/:num' (for Express)\nhelloEndpointRoute(1234) // -> '/ajax/hello/1234' (for the actual call)\n```\n\nLet's actually create a test real quick to make sure this thing works well.\n\n- Create a `src/shared/routes.test.js` containing:\n\n```js\nimport { helloEndpointRoute } from './routes'\n\ntest('helloEndpointRoute', () => {\n  expect(helloEndpointRoute()).toBe('/ajax/hello/:num')\n  expect(helloEndpointRoute(123)).toBe('/ajax/hello/123')\n})\n```\n\n- Run `yarn test` and it should pass successfully.\n\n- In `src/server/index.js`, add the following:\n\n```js\nimport { helloEndpointRoute } from '../shared/routes'\n\n// [under app.get('/')...]\n\napp.get(helloEndpointRoute(), (req, res) => {\n  res.json({ serverMessage: `Hello from the server! (received ${req.params.num})` })\n})\n```\n\n### New containers\n\n- Create a `src/client/container/hello-async-button.js` file containing:\n\n```js\n// @flow\n\nimport { connect } from 'react-redux'\n\nimport { sayHelloAsync } from '../action/hello'\nimport Button from '../component/button'\n\nconst mapStateToProps = () => ({\n  label: 'Say hello asynchronously and send 1234',\n})\n\nconst mapDispatchToProps = dispatch => ({\n  handleClick: () => { dispatch(sayHelloAsync(1234)) },\n})\n\nexport default connect(mapStateToProps, mapDispatchToProps)(Button)\n```\n\nIn order to demonstrate how you would pass a parameter to your asynchronous call and to keep things simple, I am hard-coding a `1234` value here. This value would typically come from a form field filled by the user.\n\n- Create a `src/client/container/message-async.js` file containing:\n\n```js\n// @flow\n\nimport { connect } from 'react-redux'\n\nimport MessageAsync from '../component/message'\n\nconst mapStateToProps = state => ({\n  message: state.hello.get('messageAsync'),\n})\n\nexport default connect(mapStateToProps)(MessageAsync)\n```\n\nYou can see that in this container, we are referring to a `messageAsync` property, which we're going to add to our reducer soon.\n\nWhat we need now is to create the `sayHelloAsync` action.\n\n### Fetch\n\n> 💡 **[Fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch)** is a standardized JavaScript function to make asynchronous calls inspired by jQuery's AJAX methods.\n\nWe are going to use `fetch` to make calls to the server from the client. `fetch` is not supported by all browsers yet, so we are going to need a polyfill. `isomorphic-fetch` is a polyfill that makes it work cross-browsers and in Node too!\n\n- Run `yarn add isomorphic-fetch`\n\nSince we're using `eslint-plugin-compat`, we need to indicate that we are using a polyfill for `fetch` to not get warnings from using it.\n\n- Add the following to your `.eslintrc.json` file:\n\n```json\n\"settings\": {\n  \"polyfills\": [\"fetch\"]\n},\n```\n\n### 3 asynchronous actions\n\n`sayHelloAsync` is not going to be a regular action. Asynchronous actions are usually split into 3 actions, which trigger 3 different states: a *request* action (or \"loading\"), a *success* action, and a *failure* action.\n\n- Edit `src/client/action/hello.js` like so:\n\n```js\n// @flow\n\nimport 'isomorphic-fetch'\n\nimport { createAction } from 'redux-actions'\nimport { helloEndpointRoute } from '../../shared/routes'\n\nexport const SAY_HELLO = 'SAY_HELLO'\nexport const SAY_HELLO_ASYNC_REQUEST = 'SAY_HELLO_ASYNC_REQUEST'\nexport const SAY_HELLO_ASYNC_SUCCESS = 'SAY_HELLO_ASYNC_SUCCESS'\nexport const SAY_HELLO_ASYNC_FAILURE = 'SAY_HELLO_ASYNC_FAILURE'\n\nexport const sayHello = createAction(SAY_HELLO)\nexport const sayHelloAsyncRequest = createAction(SAY_HELLO_ASYNC_REQUEST)\nexport const sayHelloAsyncSuccess = createAction(SAY_HELLO_ASYNC_SUCCESS)\nexport const sayHelloAsyncFailure = createAction(SAY_HELLO_ASYNC_FAILURE)\n\nexport const sayHelloAsync = (num: number) => (dispatch: Function) => {\n  dispatch(sayHelloAsyncRequest())\n  return fetch(helloEndpointRoute(num), { method: 'GET' })\n    .then((res) => {\n      if (!res.ok) throw Error(res.statusText)\n      return res.json()\n    })\n    .then((data) => {\n      if (!data.serverMessage) throw Error('No message received')\n      dispatch(sayHelloAsyncSuccess(data.serverMessage))\n    })\n    .catch(() => {\n      dispatch(sayHelloAsyncFailure())\n    })\n}\n```\n\nInstead of returning an action, `sayHelloAsync` returns a function which launches the `fetch` call. `fetch` returns a `Promise`, which we use to *dispatch* different actions depending on the current state of our asynchronous call.\n\n### 3 asynchronous action handlers\n\nLet's handle these different actions in `src/client/reducer/hello.js`:\n\n```js\n// @flow\n\nimport Immutable from 'immutable'\nimport type { fromJS as Immut } from 'immutable'\n\nimport {\n  SAY_HELLO,\n  SAY_HELLO_ASYNC_REQUEST,\n  SAY_HELLO_ASYNC_SUCCESS,\n  SAY_HELLO_ASYNC_FAILURE,\n} from '../action/hello'\n\nconst initialState = Immutable.fromJS({\n  message: 'Initial reducer message',\n  messageAsync: 'Initial reducer message for async call',\n})\n\nconst helloReducer = (state: Immut = initialState, action: { type: string, payload: any }) => {\n  switch (action.type) {\n    case SAY_HELLO:\n      return state.set('message', action.payload)\n    case SAY_HELLO_ASYNC_REQUEST:\n      return state.set('messageAsync', 'Loading...')\n    case SAY_HELLO_ASYNC_SUCCESS:\n      return state.set('messageAsync', action.payload)\n    case SAY_HELLO_ASYNC_FAILURE:\n      return state.set('messageAsync', 'No message received, please check your connection')\n    default:\n      return state\n  }\n}\n\nexport default helloReducer\n```\n\nWe added a new field to our store, `messageAsync`, and we update it with different messages depending on the action we receive. During `SAY_HELLO_ASYNC_REQUEST`, we show `Loading...`. `SAY_HELLO_ASYNC_SUCCESS` updates `messageAsync` similarly to how `SAY_HELLO` updates `message`. `SAY_HELLO_ASYNC_FAILURE` gives an error message.\n\n### Redux-thunk\n\nIn `src/client/action/hello.js`, we made `sayHelloAsync`, an action creator that returns a function. This is actually not a feature that is natively supported by Redux. In order to perform these async actions, we need to extend Redux's functionality with the `redux-thunk` *middleware*.\n\n- Run `yarn add redux-thunk`\n\n- Update your `src/client/index.jsx` file like so:\n\n```js\n// @flow\n\nimport 'babel-polyfill'\n\nimport React from 'react'\nimport ReactDOM from 'react-dom'\nimport { AppContainer } from 'react-hot-loader'\nimport { Provider } from 'react-redux'\nimport { createStore, combineReducers, applyMiddleware, compose } from 'redux'\nimport thunkMiddleware from 'redux-thunk'\n\nimport App from './app'\nimport helloReducer from './reducer/hello'\nimport { APP_CONTAINER_SELECTOR } from '../shared/config'\nimport { isProd } from '../shared/util'\n\n// eslint-disable-next-line no-underscore-dangle\nconst composeEnhancers = (isProd ? null : window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__) || compose\n\nconst store = createStore(combineReducers({ hello: helloReducer }),\n  composeEnhancers(applyMiddleware(thunkMiddleware)))\n\nconst rootEl = document.querySelector(APP_CONTAINER_SELECTOR)\n\nconst wrapApp = (AppComponent, reduxStore) =>\n  <Provider store={reduxStore}>\n    <AppContainer>\n      <AppComponent />\n    </AppContainer>\n  </Provider>\n\nReactDOM.render(wrapApp(App, store), rootEl)\n\nif (module.hot) {\n  // flow-disable-next-line\n  module.hot.accept('./app', () => {\n    // eslint-disable-next-line global-require\n    const NextApp = require('./app').default\n    ReactDOM.render(wrapApp(NextApp, store), rootEl)\n  })\n}\n```\n\nHere we pass `redux-thunk` to Redux's `applyMiddleware` function. In order for the Redux Devtools to keep working, we also need to use Redux's `compose` function. Don't worry too much about this part, just remember that we enhance Redux with `redux-thunk`.\n\n- Update `src/client/app.jsx` like so:\n\n```js\n// @flow\n\nimport React from 'react'\nimport HelloButton from './container/hello-button'\nimport HelloAsyncButton from './container/hello-async-button'\nimport Message from './container/message'\nimport MessageAsync from './container/message-async'\nimport { APP_NAME } from '../shared/config'\n\nconst App = () =>\n  <div>\n    <h1>{APP_NAME}</h1>\n    <Message />\n    <HelloButton />\n    <MessageAsync />\n    <HelloAsyncButton />\n  </div>\n\nexport default App\n```\n\n🏁 Run `yarn start` and `yarn dev:wds` and you should now be able to click the \"Say hello asynchronously and send 1234\" button and retrieve a corresponding message from the server! Since you're working locally, the call is instantaneous, but if you open the Redux Devtools, you will notice that each click triggers both `SAY_HELLO_ASYNC_REQUEST` and `SAY_HELLO_ASYNC_SUCCESS`, making the message go through the intermediate `Loading...` state as expected.\n\nYou can congratulate yourself, that was an intense section! Let's wrap it up with some testing.\n\n## Testing\n\nIn this section, we are going to test our actions and reducer. Let's start with the actions.\n\nIn order to isolate the logic that is specific to `action/hello.js` we are going to need to *mock* things that don't concern it, and also mock that AJAX `fetch` request which should not trigger an actual AJAX in our tests.\n\n- Run `yarn add --dev redux-mock-store fetch-mock`\n\n- Create a `src/client/action/hello.test.js` file containing:\n\n```js\nimport fetchMock from 'fetch-mock'\nimport configureMockStore from 'redux-mock-store'\nimport thunkMiddleware from 'redux-thunk'\n\nimport {\n  sayHelloAsync,\n  sayHelloAsyncRequest,\n  sayHelloAsyncSuccess,\n  sayHelloAsyncFailure,\n} from './hello'\n\nimport { helloEndpointRoute } from '../../shared/routes'\n\nconst mockStore = configureMockStore([thunkMiddleware])\n\nafterEach(() => {\n  fetchMock.restore()\n})\n\ntest('sayHelloAsync success', () => {\n  fetchMock.get(helloEndpointRoute(666), { serverMessage: 'Async hello success' })\n  const store = mockStore()\n  return store.dispatch(sayHelloAsync(666))\n    .then(() => {\n      expect(store.getActions()).toEqual([\n        sayHelloAsyncRequest(),\n        sayHelloAsyncSuccess('Async hello success'),\n      ])\n    })\n})\n\ntest('sayHelloAsync 404', () => {\n  fetchMock.get(helloEndpointRoute(666), 404)\n  const store = mockStore()\n  return store.dispatch(sayHelloAsync(666))\n    .then(() => {\n      expect(store.getActions()).toEqual([\n        sayHelloAsyncRequest(),\n        sayHelloAsyncFailure(),\n      ])\n    })\n})\n\ntest('sayHelloAsync data error', () => {\n  fetchMock.get(helloEndpointRoute(666), {})\n  const store = mockStore()\n  return store.dispatch(sayHelloAsync(666))\n    .then(() => {\n      expect(store.getActions()).toEqual([\n        sayHelloAsyncRequest(),\n        sayHelloAsyncFailure(),\n      ])\n    })\n})\n```\n\nAlright, Let's look at what's happening here. First we mock the Redux store using `const mockStore = configureMockStore([thunkMiddleware])`. By doing this we can dispatch actions without them triggering any reducer logic. For each test, we mock `fetch` using `fetchMock.get()` and make it return whatever we want. What we actually test using `expect()` is which series of actions have been dispatched by the store, thanks to the `store.getActions()` function from `redux-mock-store`. After each test we restore the normal behavior of `fetch` with `fetchMock.restore()`.\n\nLet's now test our reducer, which is much easier.\n\n- Create a `src/client/reducer/hello.test.js` file containing:\n\n```js\nimport {\n  sayHello,\n  sayHelloAsyncRequest,\n  sayHelloAsyncSuccess,\n  sayHelloAsyncFailure,\n} from '../action/hello'\n\nimport helloReducer from './hello'\n\nlet helloState\n\nbeforeEach(() => {\n  helloState = helloReducer(undefined, {})\n})\n\ntest('handle default', () => {\n  expect(helloState.get('message')).toBe('Initial reducer message')\n  expect(helloState.get('messageAsync')).toBe('Initial reducer message for async call')\n})\n\ntest('handle SAY_HELLO', () => {\n  helloState = helloReducer(helloState, sayHello('Test'))\n  expect(helloState.get('message')).toBe('Test')\n})\n\ntest('handle SAY_HELLO_ASYNC_REQUEST', () => {\n  helloState = helloReducer(helloState, sayHelloAsyncRequest())\n  expect(helloState.get('messageAsync')).toBe('Loading...')\n})\n\ntest('handle SAY_HELLO_ASYNC_SUCCESS', () => {\n  helloState = helloReducer(helloState, sayHelloAsyncSuccess('Test async'))\n  expect(helloState.get('messageAsync')).toBe('Test async')\n})\n\ntest('handle SAY_HELLO_ASYNC_FAILURE', () => {\n  helloState = helloReducer(helloState, sayHelloAsyncFailure())\n  expect(helloState.get('messageAsync')).toBe('No message received, please check your connection')\n})\n```\n\nBefore each test, we initialize `helloState` with the default result of our reducer (the `default` case of our `switch` statement in the reducer, which returns `initialState`). The tests are then very explicit, we just make sure the reducer updates `message` and `messageAsync` correctly depending on which action it received.\n\n🏁 Run `yarn test`. It should be all green.\n\nNext section: [06 - React Router, Server-Side Rendering, Helmet](06-react-router-ssr-helmet.md#readme)\n\nBack to the [previous section](04-webpack-react-hmr.md#readme) or the [table of contents](https://github.com/verekia/js-stack-from-scratch#table-of-contents).\n"
  },
  {
    "path": "tutorial/06-react-router-ssr-helmet.md",
    "content": "# 06 - React Router, Server-Side Rendering, and Helmet\n\nCode for this chapter available [here](https://github.com/verekia/js-stack-walkthrough/tree/master/06-react-router-ssr-helmet).\n\nIn this chapter we are going to create different pages for our app and make it possible to navigate between them.\n\n## React Router\n\n> 💡 **[React Router](https://reacttraining.com/react-router/)** is a library to navigate between pages in your React app. It can be used on both the client and the server.\n\n- Run `yarn add react-router react-router-dom`\n\nOn the client side, we first need to wrap our app inside a `BrowserRouter` component.\n\n- Update your `src/client/index.jsx` like so:\n\n```js\n// [...]\nimport { BrowserRouter } from 'react-router-dom'\n// [...]\nconst wrapApp = (AppComponent, reduxStore) =>\n  <Provider store={reduxStore}>\n    <BrowserRouter>\n      <AppContainer>\n        <AppComponent />\n      </AppContainer>\n    </BrowserRouter>\n  </Provider>\n```\n\n## Pages\n\nOur app will have 4 pages:\n\n- A Home page.\n- A Hello page showing a button and message for the synchronous action.\n- A Hello Async page showing a button and message for the asynchronous action.\n- A 404 \"Not Found\" page.\n\n- Create a `src/client/component/page/home.jsx` file containing:\n\n```js\n// @flow\n\nimport React from 'react'\n\nconst HomePage = () => <p>Home</p>\n\nexport default HomePage\n```\n\n- Create a `src/client/component/page/hello.jsx` file containing:\n\n```js\n// @flow\n\nimport React from 'react'\n\nimport HelloButton from '../../container/hello-button'\nimport Message from '../../container/message'\n\nconst HelloPage = () =>\n  <div>\n    <Message />\n    <HelloButton />\n  </div>\n\nexport default HelloPage\n\n```\n\n- Create a `src/client/component/page/hello-async.jsx` file containing:\n\n```js\n// @flow\n\nimport React from 'react'\n\nimport HelloAsyncButton from '../../container/hello-async-button'\nimport MessageAsync from '../../container/message-async'\n\nconst HelloAsyncPage = () =>\n  <div>\n    <MessageAsync />\n    <HelloAsyncButton />\n  </div>\n\nexport default HelloAsyncPage\n```\n\n- Create a `src/client/component/page/not-found.jsx` file containing:\n\n```js\n// @flow\n\nimport React from 'react'\n\nconst NotFoundPage = () => <p>Page not found</p>\n\nexport default NotFoundPage\n```\n\n## Navigation\n\nLet's add some routes in the shared config file.\n\n- Edit your `src/shared/routes.js` like so:\n\n```js\n// @flow\n\nexport const HOME_PAGE_ROUTE = '/'\nexport const HELLO_PAGE_ROUTE = '/hello'\nexport const HELLO_ASYNC_PAGE_ROUTE = '/hello-async'\nexport const NOT_FOUND_DEMO_PAGE_ROUTE = '/404'\n\nexport const helloEndpointRoute = (num: ?number) => `/ajax/hello/${num || ':num'}`\n```\n\nThe `/404` route is just going to be used in a navigation link for the sake of demonstrating what happens when you click on a broken link.\n\n- Create a `src/client/component/nav.jsx` file containing:\n\n```js\n// @flow\n\nimport React from 'react'\nimport { NavLink } from 'react-router-dom'\nimport {\n  HOME_PAGE_ROUTE,\n  HELLO_PAGE_ROUTE,\n  HELLO_ASYNC_PAGE_ROUTE,\n  NOT_FOUND_DEMO_PAGE_ROUTE,\n} from '../../shared/routes'\n\nconst Nav = () =>\n  <nav>\n    <ul>\n      {[\n        { route: HOME_PAGE_ROUTE, label: 'Home' },\n        { route: HELLO_PAGE_ROUTE, label: 'Say Hello' },\n        { route: HELLO_ASYNC_PAGE_ROUTE, label: 'Say Hello Asynchronously' },\n        { route: NOT_FOUND_DEMO_PAGE_ROUTE, label: '404 Demo' },\n      ].map(link => (\n        <li key={link.route}>\n          <NavLink to={link.route} activeStyle={{ color: 'limegreen' }} exact>{link.label}</NavLink>\n        </li>\n      ))}\n    </ul>\n  </nav>\n\nexport default Nav\n```\n\nHere we simply create a bunch of `NavLink`s that use the previously declared routes.\n\n- Finally, edit `src/client/app.jsx` like so:\n\n```js\n// @flow\n\nimport React from 'react'\nimport { Switch } from 'react-router'\nimport { Route } from 'react-router-dom'\nimport { APP_NAME } from '../shared/config'\nimport Nav from './component/nav'\nimport HomePage from './component/page/home'\nimport HelloPage from './component/page/hello'\nimport HelloAsyncPage from './component/page/hello-async'\nimport NotFoundPage from './component/page/not-found'\nimport {\n  HOME_PAGE_ROUTE,\n  HELLO_PAGE_ROUTE,\n  HELLO_ASYNC_PAGE_ROUTE,\n} from '../shared/routes'\n\nconst App = () =>\n  <div>\n    <h1>{APP_NAME}</h1>\n    <Nav />\n    <Switch>\n      <Route exact path={HOME_PAGE_ROUTE} render={() => <HomePage />} />\n      <Route path={HELLO_PAGE_ROUTE} render={() => <HelloPage />} />\n      <Route path={HELLO_ASYNC_PAGE_ROUTE} render={() => <HelloAsyncPage />} />\n      <Route component={NotFoundPage} />\n    </Switch>\n  </div>\n\nexport default App\n```\n\n🏁 Run `yarn start` and `yarn dev:wds`. Open `http://localhost:8000`, and click on the links to navigate between our different pages. You should see the URL changing dynamically. Switch between different pages and use the back button of your browser to see that the browsing history is working as expected.\n\nNow, let's say you navigated to `http://localhost:8000/hello` this way. Hit the refresh button. You now get a 404, because our Express server only responds to `/`. As you navigated between pages, you were actually only doing it on the client-side. Let's add server-side rendering to the mix to get the expected behavior.\n\n## Server-Side Rendering\n\n> 💡 **Server-Side Rendering** means rendering your app at the initial load of the page instead of relying on JavaScript to render it in the client's browser.\n\nSSR is essential for SEO and provides a better user experience by showing the app to your users right away.\n\nThe first thing we're going to do here is to migrate most of our client code to the shared / isomorphic / universal part of our codebase, since the server is now going to render our React app too.\n\n### The big migration to `shared`\n\n- Move all the files located under `client` to `shared`, except `src/client/index.jsx`.\n\nWe have to adjust a whole bunch of imports:\n\n- In `src/client/index.jsx`, replace the 3 occurrences of `'./app'` by `'../shared/app'`, and `'./reducer/hello'` by `'../shared/reducer/hello'`\n\n- In `src/shared/app.jsx`, replace `'../shared/routes'` by `'./routes'` and `'../shared/config'` by `'./config'`\n\n- In `src/shared/component/nav.jsx`, replace `'../../shared/routes'` by `'../routes'`\n\n### Server changes\n\n- Create a `src/server/routing.js` file containing:\n\n```js\n// @flow\n\nimport {\n  homePage,\n  helloPage,\n  helloAsyncPage,\n  helloEndpoint,\n} from './controller'\n\nimport {\n  HOME_PAGE_ROUTE,\n  HELLO_PAGE_ROUTE,\n  HELLO_ASYNC_PAGE_ROUTE,\n  helloEndpointRoute,\n} from '../shared/routes'\n\nimport renderApp from './render-app'\n\nexport default (app: Object) => {\n  app.get(HOME_PAGE_ROUTE, (req, res) => {\n    res.send(renderApp(req.url, homePage()))\n  })\n\n  app.get(HELLO_PAGE_ROUTE, (req, res) => {\n    res.send(renderApp(req.url, helloPage()))\n  })\n\n  app.get(HELLO_ASYNC_PAGE_ROUTE, (req, res) => {\n    res.send(renderApp(req.url, helloAsyncPage()))\n  })\n\n  app.get(helloEndpointRoute(), (req, res) => {\n    res.json(helloEndpoint(req.params.num))\n  })\n\n  app.get('/500', () => {\n    throw Error('Fake Internal Server Error')\n  })\n\n  app.get('*', (req, res) => {\n    res.status(404).send(renderApp(req.url))\n  })\n\n  // eslint-disable-next-line no-unused-vars\n  app.use((err, req, res, next) => {\n    // eslint-disable-next-line no-console\n    console.error(err.stack)\n    res.status(500).send('Something went wrong!')\n  })\n}\n```\n\nThis file is where we deal with requests and responses. The calls to business logic are externalized to a different `controller` module.\n\n**Note**: You will find a lot of React Router examples using `*` as the route on the server, leaving the entire routing handling to React Router. Since all requests go through the same function, that makes it inconvenient to implement MVC-style pages. Instead of doing that, we're here explicitly declaring the routes and their dedicated responses, to be able to fetch data from the database and pass it to a given page easily.\n\n- Create a `src/server/controller.js` file containing:\n\n```js\n// @flow\n\nexport const homePage = () => null\n\nexport const helloPage = () => ({\n  hello: { message: 'Server-side preloaded message' },\n})\n\nexport const helloAsyncPage = () => ({\n  hello: { messageAsync: 'Server-side preloaded message for async page' },\n})\n\nexport const helloEndpoint = (num: number) => ({\n  serverMessage: `Hello from the server! (received ${num})`,\n})\n```\n\nHere is our controller. It would typically make business logic and database calls, but in our case we just hard-code some results. Those results are passed back to the `routing` module to be used to initialize our server-side Redux store.\n\n- Create a `src/server/init-store.js` file containing:\n\n```js\n// @flow\n\nimport Immutable from 'immutable'\nimport { createStore, combineReducers, applyMiddleware } from 'redux'\nimport thunkMiddleware from 'redux-thunk'\n\nimport helloReducer from '../shared/reducer/hello'\n\nconst initStore = (plainPartialState: ?Object) => {\n  const preloadedState = plainPartialState ? {} : undefined\n\n  if (plainPartialState && plainPartialState.hello) {\n    // flow-disable-next-line\n    preloadedState.hello = helloReducer(undefined, {})\n      .merge(Immutable.fromJS(plainPartialState.hello))\n  }\n\n  return createStore(combineReducers({ hello: helloReducer }),\n    preloadedState, applyMiddleware(thunkMiddleware))\n}\n\nexport default initStore\n```\n\nThe only thing we do here, besides calling `createStore` and applying middleware, is to merge the plain JS object we received from the `controller` into a default Redux state containing Immutable objects.\n\n- Edit `src/server/index.js` like so:\n\n```js\n// @flow\n\nimport compression from 'compression'\nimport express from 'express'\n\nimport routing from './routing'\nimport { WEB_PORT, STATIC_PATH } from '../shared/config'\nimport { isProd } from '../shared/util'\n\nconst app = express()\n\napp.use(compression())\napp.use(STATIC_PATH, express.static('dist'))\napp.use(STATIC_PATH, express.static('public'))\n\nrouting(app)\n\napp.listen(WEB_PORT, () => {\n  // eslint-disable-next-line no-console\n  console.log(`Server running on port ${WEB_PORT} ${isProd ? '(production)' :\n    '(development).\\nKeep \"yarn dev:wds\" running in an other terminal'}.`)\n})\n```\n\nNothing special here, we just call `routing(app)` instead of implementing routing in this file.\n\n- Rename `src/server/render-app.js` to `src/server/render-app.jsx` and edit it like so:\n\n```js\n// @flow\n\nimport React from 'react'\nimport ReactDOMServer from 'react-dom/server'\nimport { Provider } from 'react-redux'\nimport { StaticRouter } from 'react-router'\n\nimport initStore from './init-store'\nimport App from './../shared/app'\nimport { APP_CONTAINER_CLASS, STATIC_PATH, WDS_PORT } from '../shared/config'\nimport { isProd } from '../shared/util'\n\nconst renderApp = (location: string, plainPartialState: ?Object, routerContext: ?Object = {}) => {\n  const store = initStore(plainPartialState)\n  const appHtml = ReactDOMServer.renderToString(\n    <Provider store={store}>\n      <StaticRouter location={location} context={routerContext}>\n        <App />\n      </StaticRouter>\n    </Provider>)\n\n  return (\n    `<!doctype html>\n    <html>\n      <head>\n        <title>FIX ME</title>\n        <link rel=\"stylesheet\" href=\"${STATIC_PATH}/css/style.css\">\n      </head>\n      <body>\n        <div class=\"${APP_CONTAINER_CLASS}\">${appHtml}</div>\n        <script>\n          window.__PRELOADED_STATE__ = ${JSON.stringify(store.getState())}\n        </script>\n        <script src=\"${isProd ? STATIC_PATH : `http://localhost:${WDS_PORT}/dist`}/js/bundle.js\"></script>\n      </body>\n    </html>`\n  )\n}\n\nexport default renderApp\n```\n\n`ReactDOMServer.renderToString` is where the magic happens. React will evaluate our entire `shared` `App`, and return a plain string of HTML elements. `Provider` works the same as on the client, but on the server, we wrap our app inside `StaticRouter` instead of `BrowserRouter`. In order to pass the Redux store from the server to the client, we pass it to `window.__PRELOADED_STATE__` which is just some arbitrary variable name.\n\n**Note**: Immutable objects implement the `toJSON()` method which means you can use `JSON.stringify` to turn them into plain JSON strings.\n\n- Edit `src/client/index.jsx` to use that preloaded state:\n\n```js\nimport Immutable from 'immutable'\n// [...]\n\n/* eslint-disable no-underscore-dangle */\nconst composeEnhancers = (isProd ? null : window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__) || compose\nconst preloadedState = window.__PRELOADED_STATE__\n/* eslint-enable no-underscore-dangle */\n\nconst store = createStore(combineReducers(\n  { hello: helloReducer }),\n  { hello: Immutable.fromJS(preloadedState.hello) },\n  composeEnhancers(applyMiddleware(thunkMiddleware)))\n```\n\nHere with feed our client-side store with the `preloadedState` that was received from the server.\n\n🏁 You can now run `yarn start` and `yarn dev:wds` and navigate between pages. Refreshing the page on `/hello`, `/hello-async`, and `/404` (or any other URI), should now work correctly. Notice how the `message` and `messageAsync` vary depending on if you navigated to that page from the client or if it comes from server-side rendering.\n\n### React Helmet\n\n> 💡 **[React Helmet](https://github.com/nfl/react-helmet)**: A library to inject content to the `head` of a React app, on both the client and the server.\n\nI purposely made you write `FIX ME` in the title to highlight the fact that even though we are doing server-side rendering, we currently do not fill the `title` tag properly (or any of the tags in `head` that vary depending on the page you're on).\n\n- Run `yarn add react-helmet`\n\n- Edit `src/server/render-app.jsx` like so:\n\n```js\nimport Helmet from 'react-helmet'\n// [...]\nconst renderApp = (/* [...] */) => {\n  // [...]\n  const appHtml = ReactDOMServer.renderToString(/* [...] */)\n  const head = Helmet.rewind()\n\n  return (\n    `<!doctype html>\n    <html>\n      <head>\n        ${head.title}\n        ${head.meta}\n        <link rel=\"stylesheet\" href=\"${STATIC_PATH}/css/style.css\">\n      </head>\n    [...]\n    `\n  )\n}\n```\n\nReact Helmet uses [react-side-effect](https://github.com/gaearon/react-side-effect)'s `rewind` to pull out some data from the rendering of our app, which will soon contain some `<Helmet />` components. Those `<Helmet />` components are where we set the `title` and other `head` details for each page. Note that `Helmet.rewind()` *must* come after `ReactDOMServer.renderToString()`.\n\n- Edit `src/shared/app.jsx` like so:\n\n```js\nimport Helmet from 'react-helmet'\n// [...]\nconst App = () =>\n  <div>\n    <Helmet titleTemplate={`%s | ${APP_NAME}`} defaultTitle={APP_NAME} />\n    <Nav />\n    // [...]\n```\n\n- Edit `src/shared/component/page/home.jsx` like so:\n\n```js\n// @flow\n\nimport React from 'react'\nimport Helmet from 'react-helmet'\n\nimport { APP_NAME } from '../../config'\n\nconst HomePage = () =>\n  <div>\n    <Helmet\n      meta={[\n        { name: 'description', content: 'Hello App is an app to say hello' },\n        { property: 'og:title', content: APP_NAME },\n      ]}\n    />\n    <h1>{APP_NAME}</h1>\n  </div>\n\nexport default HomePage\n\n```\n\n- Edit `src/shared/component/page/hello.jsx` like so:\n\n```js\n// @flow\n\nimport React from 'react'\nimport Helmet from 'react-helmet'\n\nimport HelloButton from '../../container/hello-button'\nimport Message from '../../container/message'\n\nconst title = 'Hello Page'\n\nconst HelloPage = () =>\n  <div>\n    <Helmet\n      title={title}\n      meta={[\n        { name: 'description', content: 'A page to say hello' },\n        { property: 'og:title', content: title },\n      ]}\n    />\n    <h1>{title}</h1>\n    <Message />\n    <HelloButton />\n  </div>\n\nexport default HelloPage\n```\n\n- Edit `src/shared/component/page/hello-async.jsx` like so:\n\n```js\n// @flow\n\nimport React from 'react'\nimport Helmet from 'react-helmet'\n\nimport HelloAsyncButton from '../../container/hello-async-button'\nimport MessageAsync from '../../container/message-async'\n\nconst title = 'Async Hello Page'\n\nconst HelloAsyncPage = () =>\n  <div>\n    <Helmet\n      title={title}\n      meta={[\n        { name: 'description', content: 'A page to say hello asynchronously' },\n        { property: 'og:title', content: title },\n      ]}\n    />\n    <h1>{title}</h1>\n    <MessageAsync />\n    <HelloAsyncButton />\n  </div>\n\nexport default HelloAsyncPage\n\n```\n\n- Edit `src/shared/component/page/not-found.jsx` like so:\n\n```js\n// @flow\n\nimport React from 'react'\nimport Helmet from 'react-helmet'\n\nconst title = 'Page Not Found'\n\nconst NotFoundPage = () =>\n  <div>\n    <Helmet\n      title={title}\n      meta={[\n        { name: 'description', content: 'A page to say hello' },\n        { property: 'og:title', content: title },\n      ]}\n    />\n    <h1>{title}</h1>\n  </div>\n\nexport default NotFoundPage\n```\n\nThe `<Helmet>` component doesn't actually render anything, it just injects content in the `head` of your document and exposes the same data to the server.\n\n🏁 Run `yarn start` and `yarn dev:wds` and navigate between pages. The title on your tab should change when you navigate, and it should also stay the same when you refresh the page. Show the source of the page to see how React Helmet sets the `title` and `meta` tags even for server-side rendering.\n\nNext section: [07 - Socket.IO](07-socket-io.md#readme)\n\nBack to the [previous section](05-redux-immutable-fetch.md#readme) or the [table of contents](https://github.com/verekia/js-stack-from-scratch#table-of-contents).\n"
  },
  {
    "path": "tutorial/07-socket-io.md",
    "content": "# 07 - Socket.IO\n\nCode for this chapter available [here](https://github.com/verekia/js-stack-walkthrough/tree/master/07-socket-io).\n\n> 💡 **[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.\n\nIn 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.\n\n- Run `yarn add socket.io socket.io-client`\n\n## Server-side\n\n- Edit your `src/server/index.js` like so:\n\n```js\n// @flow\n\nimport compression from 'compression'\nimport express from 'express'\nimport { Server } from 'http'\nimport socketIO from 'socket.io'\n\nimport routing from './routing'\nimport { WEB_PORT, STATIC_PATH } from '../shared/config'\nimport { isProd } from '../shared/util'\nimport setUpSocket from './socket'\n\nconst app = express()\n// flow-disable-next-line\nconst http = Server(app)\nconst io = socketIO(http)\nsetUpSocket(io)\n\napp.use(compression())\napp.use(STATIC_PATH, express.static('dist'))\napp.use(STATIC_PATH, express.static('public'))\n\nrouting(app)\n\nhttp.listen(WEB_PORT, () => {\n  // eslint-disable-next-line no-console\n  console.log(`Server running on port ${WEB_PORT} ${isProd ? '(production)' :\n    '(development).\\nKeep \"yarn dev:wds\" running in an other terminal'}.`)\n})\n```\n\nNote 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`.\n\n- Add the following constants to `src/shared/config.js`:\n\n```js\nexport const IO_CONNECT = 'connect'\nexport const IO_DISCONNECT = 'disconnect'\nexport const IO_CLIENT_HELLO = 'IO_CLIENT_HELLO'\nexport const IO_CLIENT_JOIN_ROOM = 'IO_CLIENT_JOIN_ROOM'\nexport const IO_SERVER_HELLO = 'IO_SERVER_HELLO'\n```\n\nThese 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.\n\nAs 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.\n\n- Create a `src/server/socket.js` file containing:\n\n```js\n// @flow\n\nimport {\n  IO_CONNECT,\n  IO_DISCONNECT,\n  IO_CLIENT_JOIN_ROOM,\n  IO_CLIENT_HELLO,\n  IO_SERVER_HELLO,\n} from '../shared/config'\n\n/* eslint-disable no-console */\nconst setUpSocket = (io: Object) => {\n  io.on(IO_CONNECT, (socket) => {\n    console.log('[socket.io] A client connected.')\n\n    socket.on(IO_CLIENT_JOIN_ROOM, (room) => {\n      socket.join(room)\n      console.log(`[socket.io] A client joined room ${room}.`)\n\n      io.emit(IO_SERVER_HELLO, 'Hello everyone!')\n      io.to(room).emit(IO_SERVER_HELLO, `Hello clients of room ${room}!`)\n      socket.emit(IO_SERVER_HELLO, 'Hello you!')\n    })\n\n    socket.on(IO_CLIENT_HELLO, (clientMessage) => {\n      console.log(`[socket.io] Client: ${clientMessage}`)\n    })\n\n    socket.on(IO_DISCONNECT, () => {\n      console.log('[socket.io] A client disconnected.')\n    })\n  })\n}\n/* eslint-enable no-console */\n\nexport default setUpSocket\n```\n\nOkay, so in this file, we implement *how our server should react when clients connect and send messages to it*:\n\n- 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.\n- 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.\n- When the client sends `IO_CLIENT_HELLO`, we log its message in the server console.\n- When the client disconnects, we log it as well.\n\n## Client-side\n\nThe client-side of things is going to look very similar.\n\n- Edit `src/client/index.jsx` like so:\n\n```js\n// [...]\nimport setUpSocket from './socket'\n\n// [at the very end of the file]\nsetUpSocket(store)\n```\n\nAs 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.\n\n- Create a `src/client/socket.js` file containing:\n\n```js\n// @flow\n\nimport socketIOClient from 'socket.io-client'\n\nimport {\n  IO_CONNECT,\n  IO_DISCONNECT,\n  IO_CLIENT_HELLO,\n  IO_CLIENT_JOIN_ROOM,\n  IO_SERVER_HELLO,\n  } from '../shared/config'\n\nconst socket = socketIOClient(window.location.host)\n\n/* eslint-disable no-console */\n// eslint-disable-next-line no-unused-vars\nconst setUpSocket = (store: Object) => {\n  socket.on(IO_CONNECT, () => {\n    console.log('[socket.io] Connected.')\n    socket.emit(IO_CLIENT_JOIN_ROOM, 'hello-1234')\n    socket.emit(IO_CLIENT_HELLO, 'Hello!')\n  })\n\n  socket.on(IO_SERVER_HELLO, (serverMessage) => {\n    console.log(`[socket.io] Server: ${serverMessage}`)\n  })\n\n  socket.on(IO_DISCONNECT, () => {\n    console.log('[socket.io] Disconnected.')\n  })\n}\n/* eslint-enable no-console */\n\nexport default setUpSocket\n```\n\nWhat happens here should not be surprising if you understood well what we did on the server:\n\n- 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.\n- We then send `Hello!` with a `IO_CLIENT_HELLO` message.\n- If the server sends us a `IO_SERVER_HELLO` message, we log it in the browser console.\n- We also log any disconnection.\n\n🏁 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.\n\nNext section: [08 - Bootstrap, JSS](08-bootstrap-jss.md#readme)\n\nBack 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).\n"
  },
  {
    "path": "tutorial/08-bootstrap-jss.md",
    "content": "# 08 - Bootstrap and JSS\n\nCode for this chapter available in the [`master-no-services`](https://github.com/verekia/js-stack-boilerplate/tree/master-no-services) branch of the [JS-Stack-Boilerplate repository](https://github.com/verekia/js-stack-boilerplate).\n\nAlright! It's time to give our ugly app a facelift. We are going to use Twitter Bootstrap to give it some base styles. We'll then add a CSS-in-JS library to add some custom styles.\n\n## Twitter Bootstrap\n\n> 💡 **[Twitter Bootstrap](http://getbootstrap.com/)** is a library of UI components.\n\nThere are 2 options to integrate Bootstrap in a React app. Both have their pros and cons:\n\n- Using the official release, **which uses jQuery and Tether** for the behavior of its components.\n- Using a third-party library that re-implements all of Bootstrap's components in React, like [React-Bootstrap](https://react-bootstrap.github.io/) or [Reactstrap](https://reactstrap.github.io/).\n\nThird-party libraries provide very convenient React components that dramatically reduce the code bloat compared to the official HTML components, and integrate greatly with your React codebase. That being said, I must say that I am quite reluctant to use them, because they will always be *behind* the official releases (sometimes potentially far behind). They also won't work with Bootstrap themes that implement their own JS. That's a pretty tough drawback considering that one major strength of Bootstrap is its huge community of designers who make beautiful themes.\n\nFor this reason, I'm going to make the tradeoff of integrating the official release, alongside with jQuery and Tether. One of the concerns of this approach is the file size of our bundle of course. For your information, the bundle weighs about 200KB (Gzipped) with jQuery, Tether, and Bootstrap's JS included. I think that's reasonable, but if that's too much for you, you should probably consider an other option for Bootstrap, or even not using Bootstrap at all.\n\n### Bootstrap's CSS\n\n- Delete `public/css/style.css`\n\n- Run `yarn add bootstrap@4.0.0-alpha.6`\n\n- Copy `bootstrap.min.css` and `bootstrap.min.css.map` from `node_modules/bootstrap/dist/css` to your `public/css` folder.\n\n- Edit `src/server/render-app.jsx` like so:\n\n```html\n<link rel=\"stylesheet\" href=\"${STATIC_PATH}/css/bootstrap.min.css\">\n```\n\n### Bootstrap's JS with jQuery and Tether\n\nNow that we have Bootstrap's styles loaded on our page, we need the JavaScript behavior for the components.\n\n- Run `yarn add jquery tether`\n\n- Edit `src/client/index.jsx` like so:\n\n```js\nimport $ from 'jquery'\nimport Tether from 'tether'\n\n// [right after all your imports]\n\nwindow.jQuery = $\nwindow.Tether = Tether\nrequire('bootstrap')\n```\n\nThat will load Bootstrap's JavaScript code.\n\n### Bootstrap Components\n\nAlright, it's time for you to copy-paste a whole bunch of files.\n\n- Edit `src/shared/component/page/hello-async.jsx` like so:\n\n```js\n// @flow\n\nimport React from 'react'\nimport Helmet from 'react-helmet'\n\nimport MessageAsync from '../../container/message-async'\nimport HelloAsyncButton from '../../container/hello-async-button'\n\nconst title = 'Async Hello Page'\n\nconst HelloAsyncPage = () =>\n  <div className=\"container mt-4\">\n    <Helmet\n      title={title}\n      meta={[\n        { name: 'description', content: 'A page to say hello asynchronously' },\n        { property: 'og:title', content: title },\n      ]}\n    />\n    <div className=\"row\">\n      <div className=\"col-12\">\n        <h1>{title}</h1>\n        <MessageAsync />\n        <HelloAsyncButton />\n      </div>\n    </div>\n  </div>\n\nexport default HelloAsyncPage\n```\n\n- Edit `src/shared/component/page/hello.jsx` like so:\n\n```js\n// @flow\n\nimport React from 'react'\nimport Helmet from 'react-helmet'\n\nimport Message from '../../container/message'\nimport HelloButton from '../../container/hello-button'\n\nconst title = 'Hello Page'\n\nconst HelloPage = () =>\n  <div className=\"container mt-4\">\n    <Helmet\n      title={title}\n      meta={[\n        { name: 'description', content: 'A page to say hello' },\n        { property: 'og:title', content: title },\n      ]}\n    />\n    <div className=\"row\">\n      <div className=\"col-12\">\n        <h1>{title}</h1>\n        <Message />\n        <HelloButton />\n      </div>\n    </div>\n  </div>\n\nexport default HelloPage\n```\n\n- Edit `src/shared/component/page/home.jsx` like so:\n\n```js\n// @flow\n\nimport React from 'react'\nimport Helmet from 'react-helmet'\n\nimport ModalExample from '../modal-example'\nimport { APP_NAME } from '../../config'\n\nconst HomePage = () =>\n  <div>\n    <Helmet\n      meta={[\n        { name: 'description', content: 'Hello App is an app to say hello' },\n        { property: 'og:title', content: APP_NAME },\n      ]}\n    />\n    <div className=\"jumbotron\">\n      <div className=\"container\">\n        <h1 className=\"display-3 mb-4\">{APP_NAME}</h1>\n      </div>\n    </div>\n    <div className=\"container\">\n      <div className=\"row\">\n        <div className=\"col-md-4 mb-4\">\n          <h3 className=\"mb-3\">Bootstrap</h3>\n          <p>\n            <button type=\"button\" role=\"button\" data-toggle=\"modal\" data-target=\".js-modal-example\" className=\"btn btn-primary\">Open Modal</button>\n          </p>\n        </div>\n        <div className=\"col-md-4 mb-4\">\n          <h3 className=\"mb-3\">JSS (soon)</h3>\n        </div>\n        <div className=\"col-md-4 mb-4\">\n          <h3 className=\"mb-3\">Websockets</h3>\n          <p>Open your browser console.</p>\n        </div>\n      </div>\n    </div>\n    <ModalExample />\n  </div>\n\nexport default HomePage\n```\n\n- Edit `src/shared/component/page/not-found.jsx` like so:\n\n```js\n// @flow\n\nimport React from 'react'\nimport Helmet from 'react-helmet'\nimport { Link } from 'react-router-dom'\nimport { HOME_PAGE_ROUTE } from '../../routes'\n\nconst title = 'Page Not Found!'\n\nconst NotFoundPage = () =>\n  <div className=\"container mt-4\">\n    <Helmet title={title} />\n    <div className=\"row\">\n      <div className=\"col-12\">\n        <h1>{title}</h1>\n        <div><Link to={HOME_PAGE_ROUTE}>Go to the homepage</Link>.</div>\n      </div>\n    </div>\n  </div>\n\nexport default NotFoundPage\n```\n\n- Edit `src/shared/component/button.jsx` like so:\n\n```js\n// [...]\n<button\n  onClick={handleClick}\n  className=\"btn btn-primary\"\n  type=\"button\"\n  role=\"button\"\n>{label}</button>\n// [...]\n```\n\n- Create a `src/shared/component/footer.jsx` file containing:\n\n```js\n// @flow\n\nimport React from 'react'\nimport { APP_NAME } from '../config'\n\nconst Footer = () =>\n  <div className=\"container mt-5\">\n    <hr />\n    <footer>\n      <p>© {APP_NAME} 2017</p>\n    </footer>\n  </div>\n\nexport default Footer\n```\n\n- Create a `src/shared/component/modal-example.jsx` containing:\n\n```js\n// @flow\n\nimport React from 'react'\n\nconst ModalExample = () =>\n  <div className=\"js-modal-example modal fade\">\n    <div className=\"modal-dialog\">\n      <div className=\"modal-content\">\n        <div className=\"modal-header\">\n          <h5 className=\"modal-title\">Modal title</h5>\n          <button type=\"button\" className=\"close\" data-dismiss=\"modal\">×</button>\n        </div>\n        <div className=\"modal-body\">\n          This is a Bootstrap modal. It uses jQuery.\n        </div>\n        <div className=\"modal-footer\">\n          <button type=\"button\" role=\"button\" className=\"btn btn-primary\" data-dismiss=\"modal\">Close</button>\n        </div>\n      </div>\n    </div>\n  </div>\n\nexport default ModalExample\n```\n\n- Edit `src/shared/app.jsx` like so:\n\n```js\nconst App = () =>\n  <div style={{ paddingTop: 54 }}>\n```\n\nThis is an example of a *React inline style*.\n\nThis will translate into: `<div style=\"padding-top:54px;\">` in your DOM. We need this style to push the content under the navigation bar, but that's what's important here. [React inline styles](https://speakerdeck.com/vjeux/react-css-in-js) are a great way to isolate your component's styles from the global CSS namespace, but it comes at a price: You cannot use some native CSS features like `:hover`, Media Queries, animations, or `font-face`. That's [one of the reasons](https://github.com/cssinjs/jss/blob/master/docs/benefits.md#compared-to-inline-styles) we're going to integrate a CSS-in-JS library, JSS, later in this chapter.\n\n- Edit `src/shared/component/nav.jsx` like so:\n\n```js\n// @flow\n\nimport $ from 'jquery'\nimport React from 'react'\nimport { Link, NavLink } from 'react-router-dom'\nimport { APP_NAME } from '../config'\nimport {\n  HOME_PAGE_ROUTE,\n  HELLO_PAGE_ROUTE,\n  HELLO_ASYNC_PAGE_ROUTE,\n  NOT_FOUND_DEMO_PAGE_ROUTE,\n} from '../routes'\n\nconst handleNavLinkClick = () => {\n  $('body').scrollTop(0)\n  $('.js-navbar-collapse').collapse('hide')\n}\n\nconst Nav = () =>\n  <nav className=\"navbar navbar-toggleable-md navbar-inverse fixed-top bg-inverse\">\n    <button className=\"navbar-toggler navbar-toggler-right\" type=\"button\" role=\"button\" data-toggle=\"collapse\" data-target=\".js-navbar-collapse\">\n      <span className=\"navbar-toggler-icon\" />\n    </button>\n    <Link to={HOME_PAGE_ROUTE} className=\"navbar-brand\">{APP_NAME}</Link>\n    <div className=\"js-navbar-collapse collapse navbar-collapse\">\n      <ul className=\"navbar-nav mr-auto\">\n        {[\n          { route: HOME_PAGE_ROUTE, label: 'Home' },\n          { route: HELLO_PAGE_ROUTE, label: 'Say Hello' },\n          { route: HELLO_ASYNC_PAGE_ROUTE, label: 'Say Hello Asynchronously' },\n          { route: NOT_FOUND_DEMO_PAGE_ROUTE, label: '404 Demo' },\n        ].map(link => (\n          <li className=\"nav-item\" key={link.route}>\n            <NavLink to={link.route} className=\"nav-link\" activeStyle={{ color: 'white' }} exact onClick={handleNavLinkClick}>{link.label}</NavLink>\n          </li>\n        ))}\n      </ul>\n    </div>\n  </nav>\n\nexport default Nav\n```\n\nThere is something new here, `handleNavLinkClick`. One issue I encountered using Bootstrap's `navbar` in an SPA is that clicking on a link on mobile does not collapse the menu, and does not scroll back to the top of the page. This is a great opportunity to show you an example of how you would integrate some jQuery / Bootstrap-specific code in your app:\n\n```js\nimport $ from 'jquery'\n// [...]\n\nconst handleNavLinkClick = () => {\n  $('body').scrollTop(0)\n  $('.js-navbar-collapse').collapse('hide')\n}\n\n<NavLink /* [...] */ onClick={handleNavLinkClick}>\n```\n\n**Note**: I've removed accessibility-related attributes (like `aria` attributes) to make the code more readable *in the context of this tutorial*. **You should absolutely put them back**. Refer to Bootstrap's documentation and code samples to see how to use them.\n\n🏁 Your app should now be entirely styled with Bootstrap.\n\n## The current state of CSS\n\nIn 2016, the typical modern JavaScript stack settled. The different libraries and tools this tutorial made you set up are pretty much the *cutting-edge industry standard* (*cough – even though it could become completely outdated in a year from now – cough*). Yes, that's a complex stack to set up, but at least, most front-end devs agree that React-Redux-Webpack is the way to go. Now regarding CSS, I have some pretty bad news. Nothing settled, there is no standard way to go, no standard stack.\n\nSASS, BEM, SMACSS, SUIT, Bass CSS, React Inline Styles, LESS, Styled Components, CSSX, JSS, Radium, Web Components, CSS Modules, OOCSS, Tachyons, Stylus, Atomic CSS, PostCSS, Aphrodite, React Native for Web, and many more that I forget are all different approaches or tools to get the job done. They all do it well, which is the problem, there is no clear winner, it's a big mess.\n\nThe cool React kids tend to favor React inline styles, CSS-in-JS, or CSS Modules approaches though, since they integrate really well with React and solve programmatically many [issues](https://speakerdeck.com/vjeux/react-css-in-js) that regular CSS approaches struggle with.\n\nCSS Modules work well, but they don't leverage the power of JavaScript and its many features over CSS. They just provide encapsulation, which is fine, but React inline styles and CSS-in-JS take styling to an other level in my opinion. My personal suggestion would be to use React inline styles for common styles (that's also what you have to use for React Native), and use a CSS-in-JS library for things like `:hover` and media queries.\n\nThere are [tons of CSS-in-JS libraries](https://github.com/MicheleBertoli/css-in-js). JSS is a full-featured, well-rounded, and [performant](https://github.com/cssinjs/jss/blob/master/docs/performance.md) one.\n\n## JSS\n\n> 💡 **[JSS](http://cssinjs.org/)** is a CSS-in-JS library to write your styles in JavaScript and inject them into your app.\n\nNow that we have some base template with Bootstrap, let's write some custom CSS. I mentioned earlier that React inline styles could not handle `:hover` and media queries, so we'll show a simple example of this on the homepage using JSS. JSS can be used via `react-jss`, a library that is convenient to use with React components.\n\n- Run `yarn add react-jss`\n\nAdd the following to your `.flowconfig` file, as there is currently a Flow [issue](https://github.com/cssinjs/jss/issues/411) with JSS:\n\n```flowconfig\n[ignore]\n.*/node_modules/jss/.*\n```\n\n### Server-side\n\nJSS can render styles on the server for the initial rendering.\n\n- Add the following constants to `src/shared/config.js`:\n\n```js\nexport const JSS_SSR_CLASS = 'jss-ssr'\nexport const JSS_SSR_SELECTOR = `.${JSS_SSR_CLASS}`\n```\n\n- Edit `src/server/render-app.jsx` like so:\n\n```js\nimport { SheetsRegistry, SheetsRegistryProvider } from 'react-jss'\n// [...]\nimport { APP_CONTAINER_CLASS, JSS_SSR_CLASS, STATIC_PATH, WDS_PORT } from '../shared/config'\n// [...]\nconst renderApp = (location: string, plainPartialState: ?Object, routerContext: ?Object = {}) => {\n  const store = initStore(plainPartialState)\n  const sheets = new SheetsRegistry()\n  const appHtml = ReactDOMServer.renderToString(\n    <Provider store={store}>\n      <StaticRouter location={location} context={routerContext}>\n        <SheetsRegistryProvider registry={sheets}>\n          <App />\n        </SheetsRegistryProvider>\n      </StaticRouter>\n    </Provider>)\n  // [...]\n      <link rel=\"stylesheet\" href=\"${STATIC_PATH}/css/bootstrap.min.css\">\n      <style class=\"${JSS_SSR_CLASS}\">${sheets.toString()}</style>\n  // [...]\n```\n\n## Client-side\n\nThe first thing the client should do after rendering the app client-side, is to get rid of the server-generated JSS styles.\n\n- Add the following to `src/client/index.jsx` after the `ReactDOM.render` calls (before `setUpSocket(store)` for instance):\n\n```js\nimport { APP_CONTAINER_SELECTOR, JSS_SSR_SELECTOR } from '../shared/config'\n// [...]\n\nconst jssServerSide = document.querySelector(JSS_SSR_SELECTOR)\n// flow-disable-next-line\njssServerSide.parentNode.removeChild(jssServerSide)\n\nsetUpSocket(store)\n```\n\nEdit `src/shared/component/page/home.jsx` like so:\n\n```js\nimport injectSheet from 'react-jss'\n// [...]\nconst styles = {\n  hoverMe: {\n    '&:hover': {\n      color: 'red',\n    },\n  },\n  '@media (max-width: 800px)': {\n    resizeMe: {\n      color: 'red',\n    },\n  },\n  specialButton: {\n    composes: ['btn', 'btn-primary'],\n    backgroundColor: 'limegreen',\n  },\n}\n\nconst HomePage = ({ classes }: { classes: Object }) =>\n  // [...]\n  <div className=\"col-md-4 mb-4\">\n    <h3 className=\"mb-3\">JSS</h3>\n    <p className={classes.hoverMe}>Hover me.</p>\n    <p className={classes.resizeMe}>Resize the window.</p>\n    <button className={classes.specialButton}>Composition</button>\n  </div>\n  // [...]\n\nexport default injectSheet(styles)(HomePage)\n```\n\nUnlike React inline styles, JSS uses classes. You pass styles to `injectSheet` and the CSS classes end up in the props of your component.\n\n🏁 Run `yarn start` and `yarn dev:wds`. Open the homepage. Show the source of the page (not in the inspector) to see that the JSS styles are present in the DOM at the initial render in the `<style class=\"jss-ssr\">` element (only on the Home page). They should be gone in the inspector, replaced by `<style type=\"text/css\" data-jss data-meta=\"HomePage\">`.\n\n**Note**: In production mode, the `data-meta` is obfuscated. Sweet!\n\nIf you hover over the \"Hover me\" label, it should turn red. If you resize your browser window to be narrower than 800px, the \"Resize your window\" label should turn red. The green button is extending Bootstrap's CSS classes using JSS' `composes` property.\n\nNext section: [09 - Travis, Coveralls, Heroku](09-travis-coveralls-heroku.md#readme)\n\nBack to the [previous section](07-socket-io.md#readme) or the [table of contents](https://github.com/verekia/js-stack-from-scratch#table-of-contents).\n"
  },
  {
    "path": "tutorial/09-travis-coveralls-heroku.md",
    "content": "# 09 - Travis, Coveralls, and Heroku\n\nCode for this chapter available in the `master` branch of the [JS-Stack-Boilerplate repository](https://github.com/verekia/js-stack-boilerplate).\n\nIn 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`.\n\n## Travis\n\n> 💡 **[Travis CI](https://travis-ci.org/)** is a popular continuous integration platform, free for open source projects.\n\nIf your project is hosted publicly on Github, integrating Travis is very simple. First, authenticate with your Github account on Travis, and add your repository.\n\n- Then, create a `.travis.yml` file containing:\n\n```yaml\nlanguage: node_js\nnode_js: node\nscript: yarn test && yarn prod:build\n```\n\nTravis 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.\n\n## Coveralls\n\n> 💡 **[Coveralls](https://coveralls.io)** is a service that gives you a history and statistics of your test coverage.\n\nIf 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.\n\n- Run `yarn add --dev coveralls`\n\n- Edit your `.travis.yml`'s `script` instruction like so:\n\n```yaml\nscript: yarn test && yarn prod:build && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js\n```\n\nNow, every time Travis will build, it will automatically submit your Jest test coverage data to Coveralls.\n\n## Badges\n\nIs everything green on Travis and Coveralls? Great, show it off to the world with shiny badges!\n\nYou 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.\n\n- Create or edit your `README.md` like so:\n\n```md\n[![Build Status](https://img.shields.io/travis/GITHUB-USERNAME/GITHUB-REPO.svg?style=flat-square)](https://travis-ci.org/GITHUB-USERNAME/GITHUB-REPO)\n[![Coverage Status](https://img.shields.io/coveralls/GITHUB-USERNAME/GITHUB-REPO.svg?style=flat-square)](https://coveralls.io/github/GITHUB-USERNAME/GITHUB-REPO?branch=master)\n```\n\nOf course, replace `GITHUB-USERNAME/GITHUB-REPO` by your actual Github username and repository name.\n\n## Heroku\n\n> 💡 **[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.\n\nThis 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.\n\n**Note**: I might add an AWS section in this chapter later, but one thing at a time.\n\n### Web setup\n\n- If that's not done yet, install the [Heroku CLI](https://devcenter.heroku.com/articles/getting-started-with-nodejs) and log in.\n\n- 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.\n\nWe 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.\n\n- In both apps, under Settings > Config Variables, add `NPM_CONFIG_PRODUCTION` set to `false`.\n\n- Create a Pipeline, and grant Heroku access to your Github.\n\n- Add both apps to the pipeline, make the staging one auto-deploy on changes in `master`, and enable Review Apps.\n\nAlright, let's prepare our project for a deployment to Heroku.\n\n### Running in production mode locally\n\n- Create a `.env` file containing:\n\n```.env\nNODE_ENV='production'\nPORT='8000'\n```\n\nThat'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.\n\n- Add `/.env` to your `.gitignore`\n\n- Create a `Procfile` file containing:\n\n```Procfile\nweb: node lib/server\n```\n\nThat's where we specify the entry point of our server.\n\nWe are not going to use PM2 anymore, we'll use `heroku local` instead to run in production mode locally.\n\n- Run `yarn remove pm2`\n\n- Edit your `prod:start` script in `package.json`:\n\n```json\n\"prod:start\": \"heroku local\",\n```\n\n- 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`.\n\n🏁 Run `yarn prod:build` and `yarn prod:start`. It should start your server and show you the logs.\n\n### Deploying to production\n\n- Add the following line to your `scripts` in `package.json`:\n\n```json\n\"heroku-postbuild\": \"yarn prod:build\",\n```\n\n`heroku-postbuild` is a task that will be run every time you deploy an app to Heroku.\n\nYou will also probably want to specify a specific version of Node or Yarn for Heroku to use.\n\n- Add this to your `package.json`:\n\n```json\n\"engines\": {\n  \"node\": \"7.x\",\n  \"yarn\": \"0.20.3\"\n},\n```\n\n- Create an `app.json` file containing:\n\n```json\n{\n  \"env\": {\n    \"NPM_CONFIG_PRODUCTION\": \"false\"\n  }\n}\n```\n\nThis is for your Review Apps to use.\n\nYou should now be all set to use Heroku Pipeline deployments.\n\n🏁 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.\n\nYou are done! Congratulations if you finished this entire tutorial starting from scratch.\n\nYou deserve this emoji medal: 🏅\n\nBack 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).\n"
  }
]