Build a React App Using TypeScript, Yarn Workspaces, Webpack, and Babel

Tony Bui
JavaScript in Plain English
4 min readSep 24, 2021

--

Large scale React App. Source SitePoint

Context

Why do we need to use Yarn workspaces?

Imagine you are working in the React app codebase with 3 other developers. You start very small with a few routes, containers and components. Everything is very peaceful. But suddenly, the business is making good money and want to invest more money in the product, they hire more people to speed up the development process.

Now, the challenges come in place. We want to have multiple teams work on each React route, different routes will have a different dependencies, we have another team working on a different product, a shared component library needs to be implemented — it’s not peaceful anymore. Every day, you need to work your *** off to figure out how to re-structure your codebase. So why not structure a project in such a way from the beginning so that it’s easy to scale? Okay, let do it!

Folder structure:

Folder structure for React App

In this example, I split project by route, we have the route /home , /about so the folder will be app , app-home , app-about .

With this structure, you can see we have multiple independent projects under src folder which can be split in the different repository in the future and treat them as a dependency. That’s why under app-home you see I have a file named package.json which declares dependencies for that folder.

And now, Yarn Workspaces come to play a role here. You don’t want to see the node_modules in every folder, do you? Yarn Workspaces will resolve all the dependencies across the whole project and then create only one node_modules folder in the root level of the project.

Using alias to import

I always find using alias is very helpful when import something and refactor my code. Never bother to deal with the dot dot hell ../../../../

But it will be more helpful when you split one project to another repository and push it to NPM. Now it becomes a dependency, so you need to update your import statement everywhere. With alias, you don’t really need to do anything, or just simply resolve what package name you want to match again that alias. To be more clear, I will give you an example:

//app-home/index.ts
// It works fine in both way//But with this way, you need to update the path if you split the component-library to become a node_modules dependency.
import { Button } from '../component-library/src/Button'
// Minor changes in the config to map the alias again the package.
import { Button } from 'component-library/src/Button'

Creating React App using Typescript, Babel, Webpack, and Yarn Workspaces:

There are a lot of articles about how to set up React with TypeScript, Babel and Webpack so I will go through it very quickly.

Package.json

Copy this file package.json to the root level, it contains all the dev dependencies it needs for compiling the project.

  • Private: need to be true to use Yarn Workspaces
  • Workspaces: where to let Yarn know where the workspaces come from.
  • Dependencies: it is empty because in the root level, we don’t need any dependency for our app, each workspace will have a set of dependency for its own.
  • DevDependencies: all the DevDependencies will stay here because we are using it to compile our code.

Create folder directory and workspace

In each workspace, we need to have a file `package.json` to declare its dependencies. For example in src/app-home/package.json

Note that, I declare component-library, app-home is a dependency of app-home because we want to bypass the es-lint rule when we using alias.

tsconfig.json

If we want auto import from VS Code we need to add the path to tsconfig.json:

babel.config.json

We also need to add the path resolver to the babel config as well. In here, we are using the babel-plugin-module-resolver to resolve the alias.

webpack.config.js

In babel-loader , I add rootMode: upward to let the workspace under src to use the same babel config with the root project. You may don’t need it in your project.

How to add a new dependency for a project:

Inside package.json in every project, the field ‘name’ will tell you the name of the workspace you are working on, but basically, it will match with the folder name.

For adding a new dependency for a specific workspace, we use this command:

yarn workspace <workspace-name> add <packages>

E.g.: I want to add faker to app-home, the command will be: yarn workspace app-home add faker

How to add a dependency to the root level:

There are some dependencies that will be used all across our projects like webpack, jest… It will make sense if we add it to the root level.

yarn -W add <packages>

See my example project at Github repo

More content at plainenglish.io

--

--