How do I use Git to configure JavaScript and TypeScript projects as Monorepo

As the development process progresses, the number of files in the project increases and it becomes more and more difficult to manage these files in a single project. You may find that front-end and back-end projects use some shared modules, and you also need to manage different versions of these modules.

Monorepo is a project structure that enables you to do all the complex operations mentioned above in one place.

I failed in trying to configure Monorepo using Lerna. Using Yalc and Yarn Workspace is also cumbersome when moving projects out of Monorepo.

Finally, I found a way to achieve the same effect with git submodules. Git does an excellent job of resolving code conflicts, and its branch management capabilities can also be used to control versions. With Git or Gitlab, you can have unlimited private repositories for free. In addition, in TypeScript or JavaScript projects that use Webpack, you can configure the alias to bring in a readable path to the module.

In this article, I’ll show you how to build a Monorepo project by setting dependencies and submodules, and how to set module aliases, and then I’ll talk about some of the drawbacks of this approach THAT I’ve encountered in the process.

Browse git-monorepo-project to see the final setup of the project

1. Configure dependencies

Each dependency is a Git module.

Each dependency has its own git repository, which can be a complete project with package.json or JavaScript files like bundled/transpile, Or it can be a project that contains only simple JavaScript or Typescript files.

Create a dependency repository

You can create a common or private repository, make sure contributors have access to it, and then push code to that repository.

Rely on warehouse version management

We often need different versions of dependencies, a process also known as versioning. Versioning allows us to change a particular version without affecting projects that use other version dependencies.

We can use branching to accomplish versioning configuration. For example, the main branch is used for the latest version of the code, the [email protected] branch is used for the 0.0.1 branch, and so on.

2. Build projects

In the figure above, module 1 is a submodule of the front-end project.

The main idea for setting up the Monorepo project with Git is to add the dependencies created in Step 1 as submodules.

In the project structure, each submodule is a local directory. Therefore, we can introduce these submodules into the code as well as local directories or do other things. As a Git repository, any committed changes will also be copied and committed to the associated project after being pushed.

The project structure

A good way to manage projects is to place all dependencies in the SRC/Packages directory, as shown in the example directory tree:

Project - root / ├ ─ ─. Gitsubmodules ├ ─ ─ package. The json ├ ─ ─ tsconfig. Json ├ ─ ─ webpack. Config. Js └ ─ ─ SRC / ├ ─ ─ index. The ts ├ ─ ─ │ ├─ ├─ ├─ class exercises, ├─ class exercises, class exercises, class exercises, class exercises, class exercises, class exercises, class exercises, class exercises, class exercises, class exercises, class exercises, class exercises, class exercises └── garbage. └ ─ ─...Copy the code

Add the dependent

After creating the dependency in Step 1, you can add it as a submodule using the git submodule add command, and then store it in the SRC/Packages directory, for example:

$ git submodule add https://github.com/username/module-name.git src/packages/module-name
Copy the code

If you want to add a specific version of the dependency repository, use the B identifier when adding submodules, as follows:

B $git submodule add - [email protected] https://github.com/username/module-name.git SRC/packages/module - nameCopy the code

Now you can introduce the newly added dependencies as local directories, for example: Import Module1 from “.. / packages/module1 “;

Operate from another client

After monorepo is configured, we can easily install the project and its dependencies on another computer. This is useful when you have multiple workstations or have teammates.

Installing the project from another machine requires the following steps:

  1. Add the -recursive flag with the Clone command. This command downloads the current project and all submodules. Example: $git clone -recursive github.com/username/ma…
  2. If necessary, run the NPM install or YARN command to install the Node module.

After completing the above two steps, the project is ready to launch!

3. Configure the module alias

Following the above steps to configure monorepo presents a problem: the import path is long and unreadable. When, for example, from the SRC/pages/dashboard/profile/ProfileMenu TSX file into “packages/modules1”, introducing path is “.. /.. /.. / packages/module1 “.

Fortunately, we can shorten the import path by setting module aliases: Note: if you are using Webpack to translate TypeScript files, you will need to set project aliases for both JavaScript and TypeScript.

Set the module alias for the JavaScript project

You can configure the module alias by modifying the resolve. Alias configuration item in the webpack.config.js file in your JavaScript project that uses Webpack. For React applications created using CRA, you can override the Webpack configuration using the react-app-rewired command.

The sample Webpack configuration is as follows:

// webpack.config.js
module.exports = {
    …,
    resolve: {
        alias: {
            // import Module1 from “module1”
            "module1": "path/to/src/packages/module1",
            // this config allow importing any modules
            // under src/packages directory
            // i.e import Module1 from “packages/module1”
            "packages": "path/to/src/packages",
            ...
        }
    }
}
Copy the code

See webpack.config.js for more examples

Configure module aliases for TypeScript projects

You can configure aliases for TypeScript projects using the compileroptions. paths configuration item in the tsconfig.json file, as shown in the following example:

{" compilerOptions ": {... , "baseUrl": "./ SRC ", "paths": {// import Module1 from "Module1" "Module1 ":" Packages/Module1 ", "Module1 /*": "packages/module1/*", // This config allow importing any modules // under SRC /packages directory // i.e import Module1 from "packages/ Module1"  "packages": "packages", "packages/*": "packages/*", ... }}}Copy the code

Make sure the “baseUrl” configuration item exists, which helps the compiler resolve dependent paths. See tsconfig.extends. Json for more information.