Boaty: Setting up your development environment
Note: this is part 2 of a series of posts, aimed at building a React Native app from the ground up. If you haven’t already done so, it’s worth starting from the beginning of the series.
In part 1, we set up our local machine to compile and run a React Native app, and scaffolded a new app Boaty.
Now that we have an app to work with, it’s worth spending some time setting up your development environment. This will speed up the development process and ensure that the app is produced with clean code and optimised assets.
In this post we’ll be covering the setup of:
- TypeScript, to add static typing and autocomplete (IntelliSense) to your JavaScript code
- TSLint, to ensure that the code is written without any syntax errors or bad practices
- Prettier, to automatically format the code to a standard coding style
- ImageMin, for optimising image assets
- Husky, for automatically checking / formatting code and optimising assets when a git commit occurs
Editor
Before we start configuring the environment, you’ll want to choose your editor. Select one that supports TypeScript, TSLint syntax highlighting and prettier code formatting - I recommend VSCode but you may have another editor which you prefer.
The instructions in the rest of this post assume that you are using VSCode as your editor.
TypeScript
TypeScript is a typed superset of JavaScript. It allows you to write JavaScript code with static types.
There are many benefits to this approach:
- catch bugs sooner (at compile-time, rather than when your code is run)
- provide hints to your editor, allowing for autocompletion of code as you type
Note: You may see blog posts and guides elsewhere that use
react-native-typescript-transform
- this is no longer necessary as of v0.57 of React Native.
As of v0.57, React Native supports TypeScript natively, but we still need to add TypeScript support to our editor:
- Install the TypeScript compiler locally, and the typings for React and React Native:
npm install -D [email protected] @types/react @types/react-native
Note: we are specifically installing TypeScript v3.0.3 since at the time of writing, the react-native typings don’t fully support the latest TypeScript version.
- Create a new file
tsconfig.json
in the root of the project, and add the following contents:
{
"compilerOptions": {
// Target latest version of ECMAScript.
"target": "esnext",
// Search under node_modules for non-relative imports.
"moduleResolution": "node",
// Don't emit; allow Babel to transform files.
"noEmit": true,
// Enable strictest settings like strictNullChecks & noImplicitAny.
"strict": true,
// Disallow features that require cross-file information for emit.
"isolatedModules": true,
// Import non-ES modules as default imports.
"esModuleInterop": true,
// Allow `import React from 'react'` style imports
"allowSyntheticDefaultImports": true,
// Ensure JSX is compiled using React.createElement
"jsx": "react",
// Include the latest version of ECMAScript
"lib": ["esnext"]
},
"include": [
"src"
]
}
- Create a new folder
src
in your project. - Move the file
App.js
to thesrc/
folder, and rename it toApp.tsx
. - Remove the line at the top of this file which reads
@flow
- Change the line which reads
type Props = {};
tointerface Props {};
- Open the file
index.js
and change the import on line 4 to readimport App from './src/App';
- Delete the file
.flowconfig
(this is used for a competing type system Flow, which we won’t be using).
If you are using VSCode, tell it to use the workspace-local version of TypeScript that we’ve just installed:
- Open your workspace settings file (
.vscode/settings.json
) - Add the following entry to it:
"typescript.tsdk": "./node_modules/typescript/lib"
- Open your
App.tsx
file in VSCode. In the statusbar at the bottom of the screen, the TypeScript version number will be reported. Click on it, and ensure that the ‘Use Workspace Version’ option is checked (see here for more details).
To check that the compiler is working correctly, open a terminal in the project root and run the following command:
node_modules/.bin/tsc
If all is well, you should see no errors reported.
Now, in the terminal, run:
npm start
In a separate terminal start the app:
react-native run-ios
The app should load in the iOS simulator as normal.
TSLint
As TypeScript is a statically typed language, it is very good at catching errors in your code. There are some issues however that TypeScript itself cannot catch, such as ensuring your code conforms to best practices regarding readability and maintainability.
This is the gap that TSLint attempts to fill. TSLint is a linting tool for TypeScript - it analyses your code as you type for common readability and maintainability issues, and suggests areas for improvement.
To install and configure TSLint:
- Install the VSCode extension
- Install tslint and the tslint-react rules locally by running the command:
npm install -D tslint tslint-react
- Create a new file
tslint.json
in the project root and add the following contents:
{
"extends": ["tslint:recommended", "tslint-react"],
"rules": {
"quotemark": [true, "single", "jsx-double"],
"object-literal-sort-keys": false
}
}
If you open the App.tsx file you should now see a few errors appear in the editor. These errors are reported by TSLint, and although they are not syntax errors (i.e. your code will still run), they indicate that the code can be cleaned up. We need to make three changes:
- Remove the
interface Props
line. Empty interfaces are not needed and add unnecessary noise to the code. - Remove the
<Props>
code afterComponent
(since we are no longer using the Props interface). - Add the
public
keyword beforerender()
.
You may not agree with the default rules that tslint ships with - if not, you can override each rule by adding a new item to the rules
object in tslint.json
. For more information on each rule, check out the documentation.
Prettier
The next tool that we’ll be setting up is Prettier, a formatting tool which automatically rewrites your code to meet a specific coding style.
To install and configure Prettier:
- Install the VSCode extension
- Install prettier locally by running the command:
npm install -D prettier
- Create a new file
.prettierrc
in the root of your project and add the following contents:
{
"singleQuote": true,
"trailingComma": "es5"
}
- Configure VSCode to automatically format your code when you save:
- Open the file
.vscode/settings.json
- Add the following entries:
"editor.formatOnSave": true
"javascript.format.enable": false
- Open the file
To check that prettier is set up correctly, open up your App.tsx
file. Remove the semicolon from the end of line 8 and press save: prettier should kick in and automatically add the semicolon back in.
Conflicts with tslint
Now that we have prettier formatting our code automatically, we need to make TSLint aware of prettier, otherwise changes made by prettier may conflict with the TSLint rules. It would also be nice if any prettier warnings were surfaced as TSLint errors, so we can see them in our editor.
We can achieve this by installing two new packages:
npm install -D tslint-config-prettier # Makes TSLint accept any rules that prettier enforces
npm install -D tslint-plugin-prettier # Show prettier warnings as TSLint errors in the editor
Now that these packages are installed, make TSLint aware of them by changing the tslint.json
configuration to the following:
{
"extends": [
"tslint:recommended",
"tslint-react",
"tslint-config-prettier",
"tslint-plugin-prettier"
],
"rules": {
"prettier": true,
"quotemark": [true, "single", "jsx-double"],
"object-literal-sort-keys": false
}
}
These changes will ensure that prettier and TSLint play together nicely.
Husky
Husky is a useful tool that allows you to run an action prior to code being committed to version control. If the action fails, the commit is aborted. It can be used to prevent ‘bad’ commits.
We are going to use husky to perform two actions before code is committed:
- format the code with prettier, and lint the code using TSLint, aborting if there are any errors
- optimise any image assets that have been added to the filesystem
Husky itself is just a tool to run an action when a commit happens. We need to write these actions ourselves in the codebase.
A naive solution could be to run the actions above on every file in the codebase, on every commit. This is wildly inefficient however - files that have not changed do not need to be checked. We therefore need a way of running actions only on files that have been added or changed.
Fortunately, another tool exists to help us with this, lint-staged
. This allows us to run a set of commands against files that are in the git staging area, i.e. files that are about to be committed.
By combining husky and lint-staged, we can run a series of actions on the files that have changed when a commit occurs.
Finally, we also need a module to perform the image optimisation - imagemin-lint-staged
is the module we’ll be using.
Putting this altogether, install these packages:
npm install -D husky lint-staged imagemin-lint-staged
Create two new files in the root of the project:
.huskyrc
, with the following contents:
{
"hooks": {
"pre-commit": "lint-staged"
}
}
.lintstagedrc
, with the following contents:
{
"linters": {
"*.{ts,tsx}": ["prettier --write", "tslint --fix", "git add"],
"*.{png,jpeg,jpg,gif,svg}": ["imagemin-lint-staged", "git add"]
}
}
Now, whenever you make a new commit, the husky pre-commit
hook will be run. This in turn will run lint-staged
, which will:
- run any
.ts
or.tsx
files through prettier, and lint them with TSLint. If there are no errors, they will be re-added to the staging area. - run any image files through imagemin, adding the newly optimised image to the staging area.
If all was well, the commit will now contain code which is formatted correctly, with images that are nicely minified.
Summary
We’ve set up our editor to make React Native development much smoother with the following tools:
- TypeScript, to add static typing and autocomplete to our code
- TSLint, to highlight issues with code readability and maintenance
- Prettier, to automatically format our code in a standard way on save
- Husky and Lint-staged, to automatically format our code and optimise our assets before a commit
The code for this section can be found on the accompanying GitHub repo, make sure to check out the changes to the code from part 1.
Next Steps
You should now have a fully loaded development environment, which serves as an excellent foundation for implementing a React Native app. In part 3, we’ll build the app.
If you’d like to learn more about building an app with TypeScript and/or React Native, I run in-person or remote workshops which walk through the fundamentals of building apps with these cutting-edge tools. If you are interested in learning more, let me know and I’d be happy to chat further!