Skip to content

Instantly share code, notes, and snippets.

@GautamSatish
Last active June 29, 2023 07:08
Show Gist options
  • Save GautamSatish/daba61a267d142ada6132264cd9fa4c6 to your computer and use it in GitHub Desktop.
Save GautamSatish/daba61a267d142ada6132264cd9fa4c6 to your computer and use it in GitHub Desktop.
Step by step instructions to set up Webpack, Babel, ESLint, Jest and Flow for your React project.
{
"presets": ["env", "react", "flow"]
}
1) Install Node.js and download the source files from the Github repository. If you are using a text editor like Atom, add the project into your editor.
https://github.com/GautamSatish/react_setup_demo
The project contains only 2 folders, dist which contains the HTML file index.html and the src folder which contains the JavaScript code from the Multiplication tables example we covered in Week 2.
2) Create a package.json file using the Node.js package manager (NPM) module.
# npm init
Fill in only basic details and leave everything else empty for now. We will update this file as we proceed.
3) Install react and react-dom. Use the --save option to add them in your package.json "dependencies".
# npm install --save react react-dom
4) Install webpack and webpack-cli as development dependencies.
# npm install --save-dev webpack webpack-cli
5) Install all the babel modules as development dependencies.
core: Babel compiler core.
loader: Webpack plugin for Babel
preset-env: For ES6 compilation.
preset-react : For JSX and Flow compilation.
# npm install --save-dev babel-core babel-loader babel-preset-env babel-preset-react
If you are using Atom, you may install the "Language Babel" package. With this package, the editor can recognize JSX and ES6 code and provide smart editing options such as JSX tag closing, html element completion suggestions etc.
6) Create a Babel configuration file .babelrc with the content from the same named file in this gist. This is telling Babel to use the ENV and REACT presets while compiling our project.
7) Create a Webpack config file webpack.config.js file with the content from the same named file in this gist.
This will set entry point as ./src/index.js, output file as ./dist/bundle.js.
It will use the babel-loader for all JS and JSX files excluding node_modules.
It will resolve filenames with JS and JSX extenstions and set mode as development.
8) Add the webpack command to your package.json scripts. Alternatively, you can run it directly from node_modules.
"dist": "webpack"
#npm run dist
OR
# ./node_modules/.bin/webpack
This should produce a bundle.js file in the dist folder. You can now open index.html in the browser and the multiplication app should be available to you.
9) Currently we are opening the index.html file directly from the file system using file://<path_to_your_project>/dist/index.html. It is not being server from a web server. Not all features and tools work with this mode. The webpack development server solves this problem by providing a hosting of our files.
To set up the development server, install the module.
# npm install --save-dev webpack-dev-server
10) Add a devServer parameter to your webpack.config.js file.
This will host the contents of the dist folder for us at port 9000.
devServer: {
contentBase: path.join(__dirname, 'dist'),
compress: true,
port: 9000
}
11) Add the dev-server command to package.json.
"dev": "webpack-dev-server"
# npm run dev
Now the app should be available at http://localhost:9000/
12) Use Hot Module Replacement to speed up the development process. With HMR, for every code change, re-running webpack is not required. Webpack watches was changes and automatically re-creates the bundle.
Add the following plugins into webpack.config.js.
Apart from the HMR plugin, we add NamedModules in-order to see which module has changed.
plugins: [
new webpack.NamedModulesPlugin(),
new webpack.HotModuleReplacementPlugin(),
]
Enable HMR in the devServer as well.
devServer: {
contentBase: path.join(__dirname, 'dist'),
compress: true,
port: 9000,
hot: true // This enables HMR
}
Now run "npm run dev". Try changing any source file, your dev command will replace the module in the bundle. You can see the updates on your browser.
13) Set up ESLint for the project by installing the eslint module and the webpack loader.
# npm install --save-dev eslint eslint-loader
# eslint --init
For now, we will use a popular style. Pick AirBnB, Yes for React and JSON for the config format.Once the init is complete you should have a .eslintrc.json file in your project root.
If you are on Windows, add the following to the .eslintrc.json file:
"rules": {
"linebreak-style": ["error", "windows"]
}
Add the command into your package.json file to run lint through the JS and JSX file in src directory.
"lint": "eslint --ext .jsx --ext .js src"
# npm run lint
If you get errors of the nature "Couldn't find plugin...", run the following.
# npm install --save-dev eslint-config-airbnb eslint-plugin-import eslint-plugin-jsx-a11y eslint-plugin-react
Once setup correctly, "npm run lint" should list you all the lint errors in your src folder. Some of these can be fixed with a --fix command.
# npm run lint -- --fix
You can fix the other errors manually by referring to the rule documentation.
If you are using Atom, you may install the "Linter Eslint" package. With this package, the editor can highlight your errors.
14) If you wish to run ESList with webpack, you can add a corresponding loader rules in webpack.config.js
{
test: /\.jsx$/,
exclude: /node_modules/,
use: {
loader: 'eslint-loader',
}
}
This will run ESLint when you run "npm run dev".
15) Setup Jest by installing the dependencies.
# npm install --save-dev jest jest-cli
Add the command to your package.json file. You can skip the --watchAll option if you do not want to keep a watch.
"test": "jest --watchAll"
# npm run test
This should report no tests
16) Add the file Tile.test.js into your src directory and install the following dependency.
# npm install --save-dev react-test-renderer
Now "npm run test" should start running the test cases. You can alter the tile and cause the snapshot test to fail.
You may add Jest to your webpack by adding the appropriate loaders.
17) Set up Flow by installing the dependency and the corresponding Babel preset.
# npm install --save-dev babel-preset-flow flow-bin
Add the command to your package.json file.
"flow": "flow"
Initialize Flow by running the init command.
# npm run flow -- init
This command will create a .flowconfig file in your project root.
Add the line "// @flow" and run flow to catch issues.
# npm run flow
You can now fix these issues.
18) Now you have a basic build and test setup ready.
This is a set of commands that can be run at the start of the training session if internet speed is low.
npm config set proxy http://web-proxy.cup.hp.com:8080
npm config set https-proxy http://web-proxy.cup.hp.com:8080
git clone git@github.com:GautamSatish/react_setup_demo.git
cd react_setup_demo
npm init
npm install --save react react-dom
npm install --save-dev webpack webpack-cli babel-core babel-loader babel-preset-env babel-preset-react webpack-dev-server eslint eslint-loader jest jest-cli react-test-renderer babel-preset-flow flow-bin
import React from 'react';
import renderer from 'react-test-renderer';
import Tile from './Tile';
function sum(a, b) {
return a + b;
}
test('adds 1 + 2 to equal 3', () => {
expect(sum(3, 1)).toBe(4);
});
test('Tile Snapshot Test', () => {
const component = renderer.create(<Tile number={1} multiplier={3} />);
const tree = component.toJSON();
expect(tree).toMatchSnapshot();
});
const path = require('path');
const webpack = require('webpack');
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
},
},
{
test: /\.jsx$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
},
}
]
},
resolve: {
extensions: ['.js', '.jsx'],
},
mode: 'development'
};
@iliyan-trifonov
Copy link

iliyan-trifonov commented Sep 22, 2021

All of the following changes are needed if you want to use the latest versions of the packages, which require some package names and some configurations to be changed.

On the step in the instructions where we do the first dist compilation, with the latest Babel(v7), I had to make the following changes:

these are my current package.json's dev deps(just before we run npm run dist):

  "devDependencies": {
    "@babel/core": "^7.15.5",
    "@babel/preset-env": "^7.15.6",
    "@babel/preset-flow": "^7.14.5",
    "@babel/preset-react": "^7.14.5",
    "babel-loader": "^8.2.2",
    "webpack": "^5.53.0",
    "webpack-cli": "^4.8.0"
  }

and my current .babelrc contents:

{
    "presets": ["@babel/preset-env", "@babel/preset-react", "@babel/preset-flow"]
}

On the webpack dev server step, I had to replace contentBase with static:

  devServer: {
    static: path.join(__dirname, "dist"),
    compress: true,
    port: 9000,
  },

And then run npm run dev successfully.

In the plugins section, I had to remove the: new NamedModulesPlugin() because of an error, and in the latest versions it's also running by default in dev mode. The HMR and others are also loaded automatically or are set by default so I could've skipped the plugins step. Still, I wanted to change only the code and configuration that produced errors. Settings while unneeded but are still compatible with the latest versions of the packages are OK for me.

For the eslint section I ran npm run lint, got 8 warnings, and fixed them manually by removing unused components and adding PropTypes.
I also added settings to the .eslintrc.json like this:

{
    "env": {
        "browser": true,
        "es2021": true,
        "node": true
    },
    "extends": [
        "eslint:recommended",
        "plugin:react/recommended"
    ],
    "parserOptions": {
        "ecmaFeatures": {
            "jsx": true
        },
        "ecmaVersion": 12,
        "sourceType": "module"
    },
    "plugins": [
        "react"
    ],
    "settings": {
        "react": {
            "version": "detect"
        }
    },
    "rules": {
    }
}

And my new webpack loaders config:

      {
        test: /\.jsx$/,
        exclude: /node_modules/,
        use: [
          {
            loader: "babel-loader",
          },
          {
            loader: "eslint-loader",
          },
        ],
      },

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment