hero image

Migrate react-scripts v2.x to v3.0.0

On April 22, 2019, Facebook react-scripts v3.0.0 was released. In this article I’ll try to describe a process of migration in general, with some issues and solutions to them, I’ve experienced while doing this migration.

Most notable features of this release are:

  • React Hooks are now fully supported
  • TypeScript linting now integrated into ESLint
  • Absolute imports using jsconfig.json or tsconfig.json
  • Also, bug which made react-scripts test --coverage impossible to run in watch mode, is now fixed

Update react-scripts

In order to update react-scripts to the latest version, according to release notes, you should run the following command inside your project’s directory terminal:


Note: during an update, you may see that react-scripts package depends on a different version of some of your dependencies (ex. eslint , or any other dependency). In that case, you can remove explicitly provided dependencies it clashes with from your package.json file (all except typescript ) and then — re-run installation command above. In case of a typescript, you’ll need to type and save its version inside package.json. This way step-by-step you’ll trust react-scripts to install and maintain dependencies it relies on (and will clean your package.json file as a slight bonus).

Migrate rules from TSLint to ESLint

Next big thing might be moving all of your Typescript linting rules from tslint.json into .eslintrc :

  • if you’re starting from a scratch, create an empty .eslintrc file in the root of your project’s directory and add following basic configuration there:
  • if you already have an existing .eslintrc config, make sure it already extends "react-app" . It is being made to properly show you all of react-script bundled rules during manual linting or inside of your code editor of choice (in my case that’s VSCode).
  • now copy-paste all of your tslint rules from tslint.json -> "rules" section into .eslintrc -> "rules" section.
  • the next step will be running eslint with command below and checking for possible rules syntax errors:

Note: errors will relate to true or false set for rules, which expect 0, 1, 2 or "off", "warn", "error" as a value correspondingly.

  • If you have multiple tslint configs for linting code on different stages (ex. separate dev and separate pre-commit configs), don’t forget doing the same operation for them, but naming files accordingly.

Note: as an alternative, you can skip everything related to rules copy-pasting above and just re-write your rules from scratch using http://ESlint.org/docs/rules documentation and then continue from the next step.

  • fix your npm scripts inside package.json to use eslint instead of tslint .

Note: if needed, you can specify needed config for each separate npm script with --config flag (ex. eslint --config .eslintrc --fix \”src/**/*.{ts,tsx,js}\”).

  • now lint your files and fix all possible errors
  • remove all tslint related files and configs from package.json and re-run your npm install or yarn to clean node_modules folder from stale dependencies.

Absolute imports

Now, react-scripts supports absolute imports based on jsconfig.json / tsconfig.json baseUrl setting. To configure it, create or update your jsconfig.json or tsconfig.json with following lines:

Note: currently the only supported options for baseUrl are node_modules which are set by default, and src .

Starting from this point, you can import your components specifying the relative path to your src folder, instead of writing a long chain of our beloved ../../../ :

A small note on Jest tests file naming

If your tests file names don’t have a .spec or .test suffix, and for instance are called simply as test.tsx (like it was in my case) — they won’t be discovered by a react-scripts test runner. As a result, you’ll need to rename them not to be called as test.tsx but to include this suffix in their name (ex. Button.test.tsx).

Another note on react-scripts test

If in your development process you relied on the react-scripts test --coverage running only once (ex. — CI run, or some pre-commit hook), it’s now running in watch mode by default. So to fix that, you’ll need to add --watchAll=false flag, to make sure it will not run in a watch mode.

Good luck!

TechMagic is a software and web development company from Lviv, Ukraine that builds dedicated teams skilled in JavaScript, Node.js, Angular, React, AWS, Serverless, and Salesforce.
contact person
  • 12 Heath Hill, Chestnut Hill
  • MA 02445, Boston, USA

  • +1 677 456 1265