Git Product home page Git Product logo

tangerine-monorepo's Introduction

๐ŸŠ Tangerine monorepo

A "fast" TypeScript-based Node.js monorepo setup powered by esbuild.
Feel free to use it as a template/boilerplate for your own monorepos.

Features

This monorepo is a boilerplate for TypeScript-based Node.js projects, powered by esbuild.

  • Uses TypeScript to write code, tests, and scripts.
  • Uses esbuild to compile your TypeScript codebase, tests, and scripts.
  • Uses tsc CLI to type-check the codebase without emitting the compiled files (since they're handled by esbuild). No need to keep TypeScript's Project References up-to-date.
  • Uses esbuild-runner to run scripts on the fly.
  • Uses Yarn workspaces to make it easy to work within the monorepo.
  • Uses Ultra runner to run scripts from the project root.
  • Uses a shareable ESLint config and Jest config to provide an extensible linting and testing setup.
  • Uses esbuild + nodemon to reload the server in development mode (even when workspace dependencies are changed).

Workspaces structure

Tangerine monorepo includes five workspaces:

  • packages/is-even: The simplest workspace โ€” it doesn't depend on any other worskpace. It's a Node.js module that exposes an isEven function that tells if the input number is even. It includes a CLI script that invokes the function from your terminal, and a test file, both written in TypeScript. The CLI script runs using esbuild-runner, which uses esbuild to compile it on the fly.
  • package/is-odd: Depends on packages/is-even. It's a Node.js module that exposes an isOdd function that tells if the input number is odd (by invoking isEven and checking if it's false). It includes a CLI script and a test file.
  • package/server: Depends on both packages/is-odd and packages/is-even. It's a Node.js Express server that exposes two routes that invoke isEven and isOdd. It uses nodemon to reload the server in development mode.
  • packages/jest-config: Shared Jest config that uses esbuild to compile your tests and your codebase.
  • packages/eslint-config: Shared ESLint config.

All the workspaces use esbuild to compile the TypeScript codebase. Be it for building, testing, or running CLI scripts, the compilation is instantaneous compared to the native TypeScript compiler (you can quickly test the difference by temporarily swapping esbuild with tsc).

The tsc CLI is used only to type-check the codebase (without emitting the compiled files โ€” since they're handled by esbuild). I expect people usually use the IDE integration to type-check the code anyway and explicitly invoke the tsc CLI only in specific use cases (such as pre-commit hooks).

Each workspace's package.json is pointing the main and types entry to src/index.ts. Which might look strange at first, given that it's uncompiled code... see "You might not need TypeScript project references" on the Turborepo blog for an explanation. This pattern has been working fine for my use cases so far (especially while using esbuild). Still, you might want to update these entries to suit your needs (e.g., when shipping packages to npm).

.
โ””โ”€โ”€ <project-root>/
    โ””โ”€โ”€ packages/
        โ”œโ”€โ”€ eslint-config/ # eslint-config shared across the workspaces
        โ”œโ”€โ”€ is-even/ # simple Node.js module example (with no dependencies)
        โ”œโ”€โ”€ is-odd/ # simple Node.js module example (depends on is-even)
        โ”œโ”€โ”€ jest-config/ # jest-config shared across the workspaces
        โ””โ”€โ”€ server/ # simple Node.js server example (depends on is-even and is-odd)

FAQs

Why are you using Yarn Classic instead of Yarn 2+?

Mainly because every time I use Yarn 2+ I encounter tiny issues requiring additional fixes or setup (e.g., Editor SDKs).
If you prefer Yarn 2+, switching to it is as easy as running yarn set version berry ๐Ÿ‘ (at that point you can even stop using ultra-runner and use yarn workspaces foreach instead).

Why esbuild? Why not swc?

I love swc, but I feel esbuild is still more "mature". I've also noticed that in some cases swc doesn't respect TypeScript's compilerOptions's paths.

Why are you pointing the package.json's main and types entry to uncompiled code?

See "You might not need TypeScript project references" on the Turborepo blog. This pattern has been working fine for my use cases so far (especially while using esbuild). Still, you might want to update these entries to suit your needs.

tangerine-monorepo's People

Contributors

mmazzarolo avatar browniefed avatar

Watchers

James Cloos avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.