A perfect React application on the cutting edge of technology Introduction Every developer can search on the web and find something related to web application based on and see some examples of implementations. some concepts like: React Server-Side Rendering Using React Router Using CSS Modules Using PostCSS Webpack configuration Express Configuration for separating Development and Production environment Powerful tools for big scale application deployment Application scaling Progressive Web Application … They are too many and very complicated that sometimes, a crowd of numbers of these technologies causes not to implement them correctly.Sometimes we see websites of large companies like , or , and this question arises to us . Pinterest Instagram Facebook How they act and how they use all techniques without any conflict with a large number of developers In this article, I wanna show you, straightforward vision or example to a good platform, complete and able to transform to a large scale. I explain it step by step. In the end, you have a complete repository that you can build a good application which contains trend techniques and technologies. Surely, your exportation will look like good examples in this field but this doesn’t mean you can not make it better than it is now. react If you are bored to read all the article, and you want to see the results now, see and use . TL;DR! : this repository I wish, if you have ideas or vision to make it better, it on Github and it. Andrew and I fully welcome this. Fork PR What we wanna build If you seek for React App on the internet, you can find many implementations that they have , and many other things. but many of them were written based on Development targets, not Production mode. SSR React Helmet In this article, I wanna implement an awesome Development area that you can do your jobs as fast as you can and also, you can Have a Production area with the efficient standards technologies. Tools and Technologies in this article React React Router 4 React Helmet CSS Modules PostCSS Webpack 3 Babel Express PM2 Basic requirement In fact, you should install , I Prefer the long-term support version (LTS) if you don’t have it, so, download and install it from . Node Node Official Website Now What? The next step is making a folder the application that we wanna create it. With folding the project files you can regulate your application and make it scalable. The best practices for folding are so different, in this article I used mine that is like best of best, but you can use your folding style. Now, I name my project folder and then based on your OS, open your command prompt area or terminal. I assume you open it. then go the folder by using your terminal and then input below command: react-example react-example npm init This command alongside running ask you some questions. answer them but do not concern about it. this question and answers are for making the file and you can easily edit it. package.json Now input these commands in your terminal: npm install --save react@16.3.2 react-dom@16.3.2 Actually, with the above command, you installed two important of this article. A folder is made beside the file that name is which these dependencies and others are kept there. Don’t care about them now. Those numbers are the version of the packages for this article. use these versions because they are compatible with each other and maybe when you are reading this article the earlier versions released. dependencies package.json node_modules Seriously Now next step, type below command: npm install --save-dev babel-loader@7.0.0 babel-core@6.24.1 webpack@3.11.0 These are dependencies for Development area, the install them but separate them from dependencies. for clearness, you can open and see the file. --save-dev --save package.json Now, it is time to install , the question is babel What is it? With a straightforward explanation, you’re going to code very very awesome based on cutting-edge technologies, But this doesn’t mean when you export your project and prepare it for deployment, all of the browsers are awesome like you. Maybe users use ancient browsers, So, you should take care of them.Babel allows you to be like a hero, but at the end, when will build your project, it exports codes that all kind of browsers understands them, both young and old of them, So, now paste below command in your terminal: Webpack npm install --save-dev babel-preset-es2015@6.24.1 babel-preset-react@6.24.1 babel-preset-env@1.5.1 babel-preset-stage-0@6.24.1 These are 's plug-ins and dependencies, don’t not attention to them now, but later, when you need something, definitely, you will seek and find these kinds of plug-ins. for using these plug-ins you must create a file with a name and write inside it these codes: babel .babelrc {"presets": ["env","es2015","react","stage-0"]} All lines of the above codes have their own meaning. for example means, let us use syntax and after building the project you will get just codes. or cause to the project system understand syntax and after build you just see . I don’t explain much more, you can search about these presets and plug-ins or ask about them in the comment. es2015 ES6 ES5.1 react JSX createElement Webpack configuration Until now, All files and configs are basic and we put all of them on the root of the project folder, but now we settle configs inside some folders to regulate project. This kind of folding cause the project will be regular and flexible to change and will be scalable. Just like I said, we have two kind of environment, the Development and the Production, do for this target make a folder and name that . inside of it make file and name it and write its content as below: webpack webpack.development.config.js const path = require('path');const ExtractTextPlugin = require('extract-text-webpack-plugin'); const distDir = path.join(__dirname, '../dist');const srcDir = path.join(__dirname, '../src'); module.exports = [{name: 'client',target: 'web',entry: `${srcDir}/client.jsx`,output: {path: path.join(__dirname, 'dist'),filename: 'client.js',publicPath: '/dist/',},resolve: {extensions: ['.js', '.jsx']},devtool: 'source-map',module: {rules: [{test: /\.(js|jsx)$/,exclude: /(node_modules[\\\/])/,use: [{loader: 'babel-loader',}]},{test: /\.pcss$/,use: ExtractTextPlugin.extract({fallback: 'style-loader',use: [{loader: 'css-loader',options: {modules: true,importLoaders: 1,localIdentName: '[local]',sourceMap: true,}},{loader: 'postcss-loader',options: {config: {path: `${__dirname}/../postcss/postcss.config.js`,}}}]})},],},plugins: [new ExtractTextPlugin({filename: 'styles.css',allChunks: true})]},{name: 'server',target: 'node',entry: `${srcDir}/server.jsx`,output: {path: path.join(__dirname, 'dist'),filename: 'server.js',libraryTarget: 'commonjs2',publicPath: '/dist/',},resolve: {extensions: ['.js', '.jsx']},module: {rules: [{test: /\.(js|jsx)$/,exclude: /(node_modules[\\\/])/,use: [{loader: 'babel-loader',}]},{test: /\.pcss$/,use: [{loader: 'isomorphic-style-loader',},{loader: 'css-loader',options: {modules: true,importLoaders: 1,localIdentName: '[local]',sourceMap: false}},{loader: 'postcss-loader',options: {config: {path: `${__dirname}/../postcss/postcss.config.js`,}}}]}],},}]; As you see, in this file we distinguish and and set some configs for each of sides. somethings are similar and somethings are not. This article is too long now and for more explanation ask your question about configs in comments. client server PostCSS configuration Good, it is essential to be said that this is so different from its friends, like . You must also install its plug-ins in addition to the installation. With plug-ins, it will become stronger. And, If anywhere you feel or see some jobs exist that cannot leverage it, you can search and find a plug-in to settle the problem. I chose some enough plug-ins, So let’s install them: Preprocessor SCSS PostCSS npm install --save-dev autoprefixer@8.3.0 css-loader@0.28.4 css-mqpacker@6.0.2 isomorphic-style-loader@4.0.0 postcss@6.0.21 postcss-apply@0.10.0 postcss-cssnext@3.1.0 postcss-custom-properties@7.0.0 postcss-extend@1.0.5 postcss-loader@2.1.4 postcss-nested@3.0.0 postcss-nested-ancestors@2.0.0 postcss-partial-import@4.1.0 postcss-scss@1.0.5 style-loader@0.21.0 extract-text-webpack-plugin@3.0.2 In the root of the project folder, make another folder and name it , and make a file inside it as and put below configuration in it. maybe you ask If you search a little about its benefits, undoubtedly you believe this awesome preprocessor. One of its benefits is that vanish your need to . Just with a little config, you can change the support level of browsers: postcss postcss.config.js Why you don’t use SCSS or Less. autoprefixer mixins module.exports = {ident: 'postcss',syntax: 'postcss-scss',map: {'inline': true,},plugins: {'postcss-partial-import': {'prefix': '_','extension': '.pcss','glob': false,'path': ['./../src/styles']},'postcss-nested-ancestors': {},'postcss-apply': {},'postcss-custom-properties': {},'postcss-nested': {},'postcss-cssnext': {'features': {'nesting': false},'warnForDuplicates': false},'postcss-extend': {},'css-mqpacker': {'sort': true},'autoprefixer': {'browsers': ['last 15 versions']},}}; Now The App It is so obvious that our application has several pages and should something exists that manage the route of these pages, and here I introduce my dear friend, the , Pay attention please, I wanna use the 4th version, so install it with special below command: React Router npm install --save react-router-dom@4.2.2 And then make a folder in the root of project folder and name it then make a file and name it as and put below command in it: src client.jsx import React from 'react';import {hydrate} from 'react-dom';import {BrowserRouter} from 'react-router-dom';import App from './app/App'; hydrate((<BrowserRouter><App/></BrowserRouter>), document.getElementById('root')); Then make a another file alongside above file and name it as and paste below codes inside it: server.jsx import React from 'react';import ReactDOMServer from 'react-dom/server';import {StaticRouter} from 'react-router-dom';import {Helmet} from "react-helmet";import Template from './app/template';import App from './app/App'; export default function serverRenderer({clientStats, serverStats}) {return (req, res, next) => {const context = {};const markup = ReactDOMServer.renderToString(<StaticRouter location={req.url} context={context}><App/></StaticRouter>);const helmet = Helmet.renderStatic(); res.status(200).send(Template({markup: markup,helmet: helmet,}));};}; And now make two folders alongside and files, and name them as and . First is for our main application files and second for its style files. client.jsx server.jsx app styles CSS Application files Inside of folder make a file and name it as and put the main template in it that wanna inject its markups. app template.jsx HTML React export default ({ markup, helmet }) => {return `<!DOCTYPE html><html ${helmet.htmlAttributes.toString()}><head>${helmet.title.toString()}${helmet.meta.toString()}${helmet.link.toString()}</head><body ${helmet.bodyAttributes.toString()}><div id="root">${markup}</div><script src="/dist/client.js" async></script></body></html>`;}; Then make a file and it is the main file of this project, The main file that contain every part of our React Application. I put some simple codes inside it, but you can folding and make larger application: App.jsx import React, {Component} from 'react'; export default class App extends Component {constructor(props) {super(props);} render() {return (<div><h1>Hello World!</h1></div>);}} A little ahead, I’ll return and add some more codes, but now it has enough code to be understood, After watching our simple inside browser come back and make it more complete. Hello World! Just add a simple thing, , it’s awesome and has much good efficient. In fact, this awesome component fill tag dynamically and put many options for managing pages. For installing use below command inside your terminal: React-Helmet SEO head React-Helmet npm install --save react-helmet@5.2.0 Just install it now. When we comeback to for completion you will aware of its benefits. App.jsx Styles Files Inside folder make a file and name it . And alongside it make a folder and name it , then inside partials folder make a partial file and name it as and put below codes inside every file: styles styles.pcss partials _partial.pcss // styles.pcss@import "partials/partial"; .component {@extend %box;color: #2f95ff;} .text {display: flex;@extend %box;} .test {display: flex;} .active {color: red;} And // partials/_partial.pcss%box {box-shadow: 0 0 10px 1px #ff6fc3;} Development Server Configuration The server of our Development area is . In fact, we use some that when we change something inside every file of the project, for example, files, the build system will be aware and rebuild all files again and again automatically. express.js middleware PostCSS First should install dependencies packages: npm i --save-dev express@4.15.3 webpack-dev-middleware@2.0.6 webpack-hot-middleware@2.22.1 webpack-hot-server-middleware@0.5.0 Then inside of root make a folder and name it , and put Development configuration in it, for this please make a file and name it as and write this file like below: express development.js const express = require('express');const app = express();const webpack = require('webpack');const config = require('./../webpack/webpack.development.config.js');const compiler = webpack(config);const webpackDevMiddleware = require('webpack-dev-middleware');const webpackHotMiddleware = require('webpack-hot-middleware');const webpackHotServerMiddleware = require('webpack-hot-server-middleware'); app.use(webpackDevMiddleware(compiler, {serverSideRender: true,publicPath: "/dist/",}));app.use(webpackHotMiddleware(compiler.compilers.find(compiler => compiler.name === 'client')));app.use(webpackHotServerMiddleware(compiler)); const PORT = process.env.PORT || 3000; app.listen(PORT, error => {if (error) { return console.error(error); } else { console.log(`Development Express server running at );}}); http://localhost:${PORT}` Let’s See What We build It’s time to test and see what we build until now, for this action it is needed to run below command inside your terminal: node ./express/development.js If you are working on Windows OS, maybe you see error, don’t worry and visit . I wrote what you should do there, If it has no error you should see below inside your terminal area: NODE_ENV this address log Development Express server running at http://localhost:3000 If you see above inside your terminal, you reached halfway of our road. Now open in your browser, and enjoy your Masterpiece. log http://localhost:3000 React Router Configuration Everything is amazing till now, we bind many items alongside each other truly and All of them work as well as a Swiss watch. I insist, if you have any issue please leave a comment and I definitely will answer. If you remember, we just installed and didn’t import it to application, now time to return to , now edit this file with the following code: React Router App.jsx import React, {Component} from 'react';import Helmet from "react-helmet";import {Switch, Route} from 'react-router-dom';import {Link, NavLink} from 'react-router-dom';import styles from '../styles/styles.pcss'; class Menu extends Component {render() {return (<div><ul><li><NavLink exact to={'/'} activeClassName={styles.active}>Homepage</NavLink></li><li><NavLink activeClassName={styles.active} to={'/about'}>About</NavLink></li><li><NavLink activeClassName={styles.active} to={'/contact'}>Contact</NavLink></li></ul></div>);}} class Homepage extends Component { render() {return (<div className={styles.component}><Helmet title="Welcome to our Homepage"/><Menu/><h1>Homepage</h1></div>);}} class About extends Component {render() {return (<div><Helmet title="About us"/><Menu/><h1>About</h1></div>);}} class Contact extends Component {render() {return (<div><Helmet title="Contact us"/><Menu/><h1>Contact</h1></div>);}} export default class App extends Component { render() {return (<div><HelmethtmlAttributes={{lang: "en", amp: undefined}} // amp takes no valuetitleTemplate="%s | React App"titleAttributes={{itemprop: "name", lang: "en"}}meta={[{name: "description", content: "Server side rendering example"},{name: "viewport", content: "width=device-width, initial-scale=1"},]}link={[{rel: "stylesheet", href: "/dist/styles.css"}]}/><Switch><Route exact path='/' component={Homepage}/><Route path='/about' component={About}/><Route path='/contact' component={Contact}/></Switch></div>);}} Sounds good, let me explain this new content, we have three components, , and That they play the role of our three pages. Homepage About Contact After these three pages, we make a component for showing menu in each component or actually each page. Menu , we are not supposed to use class names like the past. We are going to use , so, we should add the styles root file like a object: Here is a point CSS-Modules JavaScript import styles from '../styles/styles.pcss'; And use it in a class name like a object: JavaScript <div className={styles.container}><div className={styles['container-top']}example</div></div> I think it is so obvious, in the files leave any class names or name spacing methodologies, like , and inside use that name like a child of object instead of direct name.This kind of using cause when you prepare the deployment version hence Production version, the class names will be transformed to hash names and you can make them small to characters. Definitely, your built file will be very small and compact. PostCSS BEM JSX styles 5 CSS The other thing that I like it, is , that you can see in the above codes obviously. In each component exists separately, In the root component, it exists too for general head settings. These settings are very straightforward so I refuse to explain it here. React Helmet React Helmet Now, let’s see what we build again, so run Development command again: node ./express/development.js It’s like a miracle, yeah, you build a skeleton of a web application based on that has many awesome technologies. when you click on each menu item the related page renders from the server and it is dynamic on your browser, but is it done? React.js Both yes and no, : Because we built an awesome Development area, : Because we don’t know how to prepare it for Production area and deployment. YES NO Preparing for deployment on Production environment So far, we’ve done everything for Development, but now we settle different configuration for Production so we should consider these three goals: Bundling and compressing all files in our application and vanishing s and s and transpiling them to debugger console.log ES5.1 Extracting in a separate file and compressing and omitting all comments styles.css Building file that in fact, it is stuff pieces of on the server actions, which needs them. stat.json webpack express Going to Production configuration with following commands: npm install --save-dev clean-webpack-plugin@0.1.19 stats-webpack-plugin@0.6.0 optimize-css-assets-webpack-plugin@3.2.0 Now create another file in folder that its name is . its content is: webpack webpack.production.config.js const path = require('path');const webpack = require('webpack');const ExtractTextPlugin = require('extract-text-webpack-plugin');const StatsPlugin = require('stats-webpack-plugin');const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');const CleanWebpackPlugin = require('clean-webpack-plugin'); const distDir = path.join(__dirname, '../dist');const srcDir = path.join(__dirname, '../src'); module.exports = [{name: 'client',target: 'web',entry: `${srcDir}/client.jsx`,output: {path: distDir,filename: 'client.js',publicPath: distDir,},resolve: {extensions: ['.js', '.jsx']},module: {rules: [{test: /\.(js|jsx)$/,exclude: /(node_modules[\\\/])/,use: [{loader: 'babel-loader',}]},{test: /\.pcss$/,use: ExtractTextPlugin.extract({fallback: 'style-loader',use: [{loader: 'css-loader',options: {modules: true,importLoaders: 1,localIdentName: '[hash:base64:10]',sourceMap: false,}},{loader: 'postcss-loader',options: {config: {path: `${__dirname}/../postcss/postcss.config.js`,}}}]})}],},plugins: [new ExtractTextPlugin({filename: 'styles.css',allChunks: true}),new webpack.DefinePlugin({'process.env': {NODE_ENV: '"production"'}}),new CleanWebpackPlugin(distDir),new webpack.optimize.UglifyJsPlugin({compress: {warnings: false,screw_ie8: true,drop_console: true,drop_debugger: true}}),new webpack.optimize.OccurrenceOrderPlugin(),]},{name: 'server',target: 'node',entry: `${srcDir}/server.jsx`,output: {path: distDir,filename: 'server.js',libraryTarget: 'commonjs2',publicPath: distDir,},resolve: {extensions: ['.js', '.jsx']},module: {rules: [{test: /\.(js|jsx)$/,exclude: /(node_modules[\\\/])/,use: [{loader: 'babel-loader',}]},{test: /\.pcss$/,use: [{loader: 'isomorphic-style-loader',},{loader: 'css-loader',options: {modules: true,importLoaders: 1,localIdentName: '[hash:base64:10]',sourceMap: false}},{loader: 'postcss-loader',options: {config: {path: `${__dirname}/../postcss/postcss.config.js`,}}}]}],},plugins: [new OptimizeCssAssetsPlugin({cssProcessorOptions: {discardComments: {removeAll: true}}}),new StatsPlugin('stats.json', {chunkModules: true,modules: true,chunks: true,exclude: [/node_modules[\\\/]react/],}),]}]; And create another file in folder and name it and fill it by using below codes: express production.js const express = require('express');const path = require('path');const app = express();const ClientStatsPath = path.join(__dirname, './../dist/stats.json');const ServerRendererPath = path.join(__dirname, './../dist/server.js');const ServerRenderer = require(ServerRendererPath).default;const Stats = require(ClientStatsPath); app.use('/dist', express.static(path.join(__dirname, '../dist')));app.use(ServerRenderer(Stats)); const PORT = process.env.PORT || 3000; app.listen(PORT, error => {if (error) { return console.error(error); } else { console.log(`Production Express server running at );}}); http://localhost:${PORT}` So now, with below commands, we can build some files that they are needed for the Production environment: NODE_ENV=production webpack -p --config ./webpack/webpack.production.config.js --progress --profile --colors You can see some files are generated inside a new folder that name is . you can see the semi-production environment that all visitors will see by using the following command: dist NODE_ENV=production node ./express/production.js If on your browser you had installed the and extensions, you can see the logo, especially you can see the turns to color and it is not color yet_._ Google Chrome React Developer Tools Wappalyzer React React Developer Tools blue red means it is on production build and means it is under construction of development build. Blue red Congratulations! this article is so simple but a little complex, when you are here, it means you are perfect. It takes some time to find all the things out. But at last, you will make your custom project with many add on other things like , , or testing like and many other things. eslint Redux Redux-Saga Jest Running on Real Server When all the above stuff is prepared, you should tell your specialist that install on the Production server, because a large scale application with a crowd of visitors never run with above command. the should install with this command: DevOps pm2 React pm2 npm install pm2 -g And at last for running should use this command: NODE_ENV=production pm2 start ./express/production.js You can use on your own PC for a test, it is no different between and commands in your browser but the specialist knows about their difference like load balance, managing caching and etc. If you like to know more about you can read . pm2 pm2 node DevOps pm2 its Docs Conclusion For easy development, I put some commands in the section of the file. you can access them in the or see below codes: scripts package.json GitHub Repository "scripts": {"test": "echo \"Error: no test specified\" && exit 1","dev": "NODE_ENV=development node ./express/development.js","build": "NODE_ENV=production webpack -p --config ./webpack/webpack.production.config.js --progress --profile --colors","prod": "NODE_ENV=production webpack -p --config ./webpack/webpack.production.config.js --progress --profile --colors && node ./express/production.js","pm2": "NODE_ENV=production pm2 start ./express/production.js"} And the last point, it is right that I used in all of this article, for example you can use for running development, but the is so slow, when each changing is happen in files, system will build your new development files about to seconds! later, and it is annoying for development. Then you can see your changes with browser . It’s so boring.For this issue, I suggest you use . You can start to develop with command, it is unbelievable, it longs about milliseconds to build new development files. npm npm run dev npm 27 30 Hard Reload yarn yarn dev 500 Hope this article helps you to build your **React.js** application