Setting up ESLint & Prettier with Webpack in VSCode

In our third part of the series, we will set up the configuration for ESLint and Prettier within VSCode.

We will install our own ESLint and Prettier without going through neither webpack nor babel. Follow the quick set-up guide if you still want to set up the project like it is in GitHub. Visit previous articles for a more in-depth explanation of what’s happening behind the scenes here.

Versions being used:

  • response 18
  • babel 7
  • webpack 5
  • typescript 4
  • eslint 8
  • beautiful 2

To start the project quickly, run the following command:

One. Build package.json file

npm init -y
enter fullscreen mode

exit fullscreen mode

b. Install React, Babel, Webpack, TypeScript and other required packages

npm install --save-dev --save-exact react react-dom @babel/core @babel/preset-env @babel/preset-react babel-loader webpack webpack-cli webpack-dev-server html-webpack-plugin style-loader css-loader file-loader typescript @types/react @types/react-dom @babel/preset-typescript
enter fullscreen mode

exit fullscreen mode

C. Create babel configuration file .babelrc and paste the following code:

{
  "presets": [
    "@babel/preset-env",
    [
      "@babel/preset-react",
      {
        "runtime": "automatic"
      }
    ],
    "@babel/preset-typescript"
  ]
}
enter fullscreen mode

exit fullscreen mode

D. Create TypeScript configuration file tsconfig.json and paste the following code:

{
  "compilerOptions": {
    // Emit Configuration
    "noEmit": true,

    // Type Checking Configuration
    "allowUnreachableCode": false,
    "allowUnusedLabels": false,
    "exactOptionalPropertyTypes": true,
    "noFallthroughCasesInSwitch": true,
    "noImplicitThis": true,
    "noPropertyAccessFromIndexSignature": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noImplicitOverride": true,
    "noImplicitAny": true,
    "noImplicitReturns": true,
    // Strict Rules - v4.8
    "alwaysStrict": true,
    "strictBindCallApply": true,
    "strictFunctionTypes": true,
    "strictNullChecks": true,
    "strictPropertyInitialization": true,
    "useUnknownInCatchVariables": true,

    // Modules Configuration
    "baseUrl": "./",
    "module": "ES2022",
    "moduleResolution": "node",

    // Language and Environment Configuration
    "target": "ES2022",
    "jsx": "react-jsx",

    // JavaScript Support Configuration
    "allowJs": true,
    "checkJs": true,

    // Interop Constraints Configuration
    "esModuleInterop": true,
    "isolatedModules": true
  },
  "include": ["src/**/**/*"],
  "exclude": ["node_modules"]
}
enter fullscreen mode

exit fullscreen mode

I. create webpack.config.js file and paste the following code:

const HtmlWebpackPlugin = require("html-webpack-plugin");
const path = require("path");

module.exports = {
  entry: "./src/index.tsx",
  mode: "development",
  output: {
    filename: "bundle.[fullhash].js",
    path: path.resolve(__dirname, "dist"),
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: "./src/index.html",
    }),
  ],
  resolve: {
    modules: [__dirname, "src", "node_modules"],
    extensions: ["*", ".js", ".jsx", ".tsx", ".ts"],
  },
  module: {
    rules: [
      {
        test: /\.(js|ts)x?$/,
        exclude: /node_modules/,
        use: ["babel-loader"]
      },
      {
        test: /\.css$/,
        exclude: /node_modules/,
        use: ["style-loader", "css-loader"]
      },
      {
        test: /\.(png|svg|jpg|gif)$/,
        exclude: /node_modules/,
        use: ["file-loader"]
      }, 
    ],
  },
};
enter fullscreen mode

exit fullscreen mode

F. Create a folder named “src” with the following files:

const App = () => (
  <div>
    <h1>Hello, World!</h1>
  </div>
);

export default App;
enter fullscreen mode

exit fullscreen mode

import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import App from './App';

const rootElement = document.querySelector('#root');
if (!rootElement) throw new Error('Failed to find the root element');
const root = createRoot(rootElement);
root.render(
  <StrictMode>
    <App />
  </StrictMode>
);
enter fullscreen mode

exit fullscreen mode

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>React</title>
  </head>
  <body>
    <div id="root"></div>
  </body>
</html>
enter fullscreen mode

exit fullscreen mode

F. Make tscheck, buildAnd start script
In package.json file, add these lines to your script section:

"tscheck": "tsc",
"build": "webpack --config webpack.config.js --mode production",
"start": "webpack serve --open"
enter fullscreen mode

exit fullscreen mode

Now that we have all of the above set-up, the quick set-up should be able to run. If you have questions or want to learn more about what’s going on above, check out my previous article here.

Background Information:

As a developer, it is always good to ask yourself, why do I need to do this? What use cases would I need to implement this? Is the implementation worth the work compared to the alternative? These are the questions we are going to answer.

1. ESLint vs Prettier

First things first, “ESlint vs Prettier” should really always be said: ESLint and Prettier. This is because the jobs between these two devices are meant to accomplish different tasks. ESLint will line up our code while Prettier will simply format our code.

Layer: The way our code is implemented is to follow certain coding practices. Some examples would include ensuring that all console.logs() and unused variables are removed, while more specific rules would be such as not allowing the use of continue statements.

Formatting: We only care about how the code looks, it doesn’t involve catching errors or coding rules. An example would be making sure all lines of code have a length of 100 and then autoformatting the code to follow this rule.

Now that we have a clear definition, ESLint will be used as the linter, while Prettier will take care of our formatting.

2. Why ESLint and Prettier?

Why would we ever need tools like ESLint and Prettier? As an individual developer, these tools would be in the “Nice to Haves” categories and not “100%” necessary. This is because different developers working on a project may follow their own coding rules and styles.

However what happens when we have a team now? Maybe multiple teams of developers all working together and each developer has their own coding rules and styles? This can quickly complicate our projects as each pull request (PR) can have too many “un-needed” style changes and code rules that will then be debated. This makes the PR review a little heavier than necessary and it takes time to really constructively critique the actual needed change. This is where ESLint and Prettier come into play.

ESLint will ensure that each developer is adhering to certain coding requirements that a team agrees on. Prettier will then ensure that each file will have the same “look and feel” throughout the project. These two tools will ensure that there will be better unity among the team(s) and there will be minimum changes in any PR. All of this obviates the need for a coherent, front-end project.

Leave a comment if you have any additional benefits of using ESLint and Prettier!💬

3. Implementation Options

Before we begin our set-up, let me go over three different ways we can use ESLint; It all depends on whether we want babel, webpack, or npm lining up our code. In this article, we won’t let our ESLint depend on any tool other than NPM running our linux.

My personal reason for organizing ESLint this way is for the separation of concerns. I believe the ability to decouple our tools (and code) creates fewer dependencies and thus, less trouble whenever things eventually break from updates, configuration changes, or changes to code. Is.

Since we are going to implement ESLint like NPM, we need to add one more line to our scripting process.

1. Installing ESLint and Prettier

To install ESLint, we need to include the following in our dev dependencies:

npm install --save-dev --save-exact eslint eslint-plugin-react eslint-plugin-react-hooks eslint-config-prettier prettier @typescript-eslint/parser @typescript-eslint/eslint-plugin
enter fullscreen mode

exit fullscreen mode

2. Configuring ESLint

To configure ESLint, we need to create .eslintrc.json file in the root directory of our current project.

Background: Within this file, we can apply various plugins and extensions for ESLint. Some of the basic fields present in configuration files are as follows:

  • env

    • The environment designed to run your scripts.
  • spread out
    • Allows ESLint to use and will override an already existing ESLint configuration.
  • parser

    • Converts the code into an Abstract Syntax Tree (AST).
  • parser option

    • Tells ESLint which version of JavaScript we are targeting.
  • plug-in

    • There are additional rules that can be used to configure your ESLint.
  • Adjustment

    • There is a shared setting that specifies information that must conform to all of its rules.
  • rules

    • Where we can configure our plugins and the various rules offered by ESLint.

Setting up .eslintrc.json: here is my .eslintrc.json Which I use, if you have any suggestions please leave a comment!

{
  "env": {
    "browser": true,
    "es2022": true,
    "node": true
  },
  "extends": [
    "eslint:recommended",
    "plugin:@typescript-eslint/recommended",
    "plugin:react/recommended",
    "plugin:react-hooks/recommended",
    "prettier"
  ],
  "parser": "@typescript-eslint/parser",
  "parserOptions": {
    "ecmaFeatures": {
      "jsx": true
    },
    "ecmaVersion": "latest",
    "sourceType": "module"
  },
  "plugins": [
    "react",
    "@typescript-eslint"
  ],
  "settings": {
    "react": {
      "version": "999.999.999"
    }
  },
  "rules": {
    "react/jsx-uses-react": "off",
    "react/react-in-jsx-scope": "off"
  }
}
enter fullscreen mode

exit fullscreen mode

Here are some explanations on some of the configurations:

  • env
    • We are going to add support for es6 global variables by setting es2022 to true.
  • spread out
    • Here we use the recommended ESLint and plugin rules. We need to make sure that prettier is placed last in order to override any rules that may cause conflicts between prettier and other packages.
  • parser
    • we are choosing @typescript-eslint/parser Since we have typescript in our project.
  • parser option
    • Since we are using React, we want to turn on jsx. We are going to add support for the latest Ecma syntax by setting ecmaVersion to latest.
  • plug-in
    • We need to modify some rules for these plugins, so we’ve included them here.
  • Adjustment
    • We want to set react version here to avoid react warning of not having specified version. We can keep an exact version of the response but for now we can leave it as the value shown.
  • rules
    • Since we are using JSX transforms, we can disable the specific rules listed.

Finally, for our installation .eslintrc.json We need to create a file similar to .gitignore called .eslintignore, It pretty much works with the main difference of telling ESLint which files we shouldn’t check. We will be adding several files to our current project:

node_modules
dist
package-lock.json
webpack.config.js
enter fullscreen mode

exit fullscreen mode

We do this to help speed up the process of getting our projects down the line. Add or Remove depending on your needs!

3. Configuring Beautiful

Now we can create a .prettierrc.json. This is where we’ll put our code formatting rules that will run and adjust pretty well!

Here are my formatting rules, leave a comment what rules you guys prefer to use!

{
  "semi": true,
  "tabWidth": 2,
  "printWidth": 100,
  "singleQuote": true,
  "trailingComma": "none",
  "jsxBracketSameLine": true
}
enter fullscreen mode

exit fullscreen mode

4. Configuring VSCode

With VSCode IDE, we have the following settings options available to the user to configure:

  • user settings
    • Settings that will be applied globally to any instance of VSCode on your machine.
  • workspace settings
    • Settings set inside your project that will be applied each time your specific project is opened

We will be creating a workspace setting to be able to share our project as we go, and to have a consistent environment across teams. I have the following in my settings. Jason:

{
  "editor.defaultFormatter": "rvest.vs-code-prettier-eslint",
  "editor.formatOnPaste": false, // required
  "editor.formatOnType": false, // required
  "editor.formatOnSave": true, // optional
  "editor.formatOnSaveMode": "file", // required to format on save
  "files.autoSave": "onFocusChange" // optional but recommended
}
enter fullscreen mode

exit fullscreen mode

With these settings, we will now be able to use prettier every time we save.

5. Configuring package.json

Now in the package.json file, we need to add this line to your script section:

"lint": "eslint .",
"lint:fix": "eslint . --fix",
enter fullscreen mode

exit fullscreen mode

This will lint all the code. And will also try to auto-correct any linting errors that come up.

See everything in one go on Github.

If you found this helpful or if you enjoyed reading the article, consider grabbing me a cup of coffee.

Leave a Comment