In this article, I’m going to cover the following new features of CRA 3:
- Jest 24
- Support of hook rules
- Linting of TypeScript files
browserslist
configuration for production and development environmentsbaseUrl
injsconfig.json
/tsconfig.json
For a complete list of all the features (and some breaking changes), check out the changelog for this release.
Jest 24
CRA now bundles the latest major version of Jest (specifically, version 24.7.1, at the time of this writing).
In comparison to the previous version, Jest 24 includes changes like:
- Built-in support for transpiling TypeScript files
- Improved error reporting
- A
test.todo
function to print todos separately in the test summary - Renamed
setupTestFrameworkScriptFile
tosetupFilesAfterEnv
, turning it into an array
For more information, you can check out this blog post or the changelog.
If you haven’t use Jest, it is a unit testing framework that runs in a Node.js environment instead of a browser.
When executing npm test
, CRA will use Jest to run tests with the following naming conventions:
- Files with a
.js
suffix in__tests__
folders - Files with a
.test.js
suffix - Files with a
.spec.js
suffix
By default, Jest will only run the tests related to files changed since the last commit and it will launch in watch mode (every time you save a file, it will re-run the tests).
To avoid running tests in watch mode, CRA 3 removed the --no-watch
flag in favor of Jest’s flag --watchAll=false
. However, this flag is not necessary if you, or your CI server, set the CI
environment variable.
You can know more about running tests on this page.
Hooks rules
Hooks were introduced in React 16.8. They are functions that allow you to use React features only available for classes (like state handling) in functional components.
There are two rules for using hooks:
- Use hooks at the top level of your functional component, never inside loops, conditions, or nested functions
- Only call hooks from functional components, don’t call hooks from regular JavaScript functions
CRA 3 integrates an ESLint plugin, eslint-plugin-react-hooks, that enforces these two rules and other conventions (for example, that hooks must begin with use
followed by an uppercase character).
The build will fail if you break one of the rules.
For example, if you modify the file src/App.js
in the following way:
import React, { useState } from 'react'; // ... function App() { if(1 !== 0) { const [count, setCount] = useState(0); } return ( /* ... */ ); } // ...
Since the hook useState
is being used inside a conditional block, the build will fail with the following message:
Failed to compile.
./src/App.js Line 7: React Hook "useState" is called conditionally. React Hooks must be called in the exact same order in every component render react-hooks/rules-of-hooks
In this README file (and in particular, the index.js file), you can know more about the ESLint configuration used by CRA.
And on this page, you can learn how to set up your editor to display the lint output.
TypeScript linting
CRA 3 also added linting rules for TypeScript projects via typescript-eslint.
Remember that you can create a TypeScript project with either:
npx create-react-app my-typescript-app --typescript
Or:
yarn create react-app my-typescript-app --typescript
Here you can see the ESLint configuration for TypeScript in CRA 3.0, and in this page, you can find instructions to enable TypeScript support in the ESLint extension of Visual Studio Code.
Browserslist configuration
Browserslist allows you to configure a set of browser versions to change the build output in order to produce compatible code and support the specified browser versions.
You can specify separate lists for production and development. For example, if you add the following configuration to the package.json
file:
"browserslist": { "production": [ "cover 99.5%" ], "development": [ "last 2 chrome versions" ] }
The production build will target browsers that cover 99.5% of global usage, while the development build will target only the last two versions of Chrome.
Browserslist uses Can I Use for these queries, but you can use https://browserl.ist to see the results of these queries (here and here) and test your own.
This way, you can install @babel/polyfill as a dependency of your project and import it at the top of the src/index.js
or src/index.tsx
files and Browserslist will include polyfills when necessary (polyfills are not automatically added). In this page, you can find more information about the supported language features.
Also, if you want CRA 3 to handle a reset CSS, it will use PostCSS Normalize by default, which in turn, will use the Browserslist configuration to adapt its output. You just need to add @import-normalize;
anywhere in your CSS file(s). See this page for more information.
Browserslist’s default configuration targets a broad range of browsers in production, but following the instructions in this README file, you’ll be able to define your own custom queries.
Setting a base URL
Setting the NODE_PATH
environment variable to a colon-delimited (semicolons on Windows) list of absolute paths, allows Node.js to search for modules in those paths to avoid things like:
const myModule = require('../../../../../../myModule');
CRA 3 removes the need for setting NODE_PATH
in a .env
file (this variable is still considered, but is deprecated and will be removed in a future release).
So now you have to use baseUrl
in either a jsconfig.json
or tsconfig.json
file (the latter for TypeScript projects) at the root of your project:
{ "compilerOptions": { "baseUrl": "src" }, }
This way, instead of having something like:
import Menu from 'src/components/Menu';
You can just have:
import Menu from 'components/Menu';
Not a big improvement, but in CRA 3.0, the only acceptable values for baseUrl
are src
and node_modules
(the default value).
In this page, you can find more information about this feature.
Conclusion
There’s no doubt CRA keeps improving with every new release. Thanks to the work of almost 50 committers, this time, it has brought a set of useful additions, improvements, and updates to internal and underlying tools.
If you have created a React application with CRA 2 and you have not ejected it, upgrading to CRA 3 is as easy as running one the following commands:
npm install --save --save-exact [email protected] # Or yarn add --exact [email protected]
If you have ejected your application, there’s no easy process to upgrade, so consider if it’s worth revert the project up to the point before ejection, upgrade, and optionally, eject again.
Happy coding!