This is an alpha, sneak peek of Monorepo Maestros. For this iteration, I'm getting all of my thoughts down. In the future, we'll have better information architecture, graphics, and other awesomeness. Your feedback is welcome!

Just-In-Time Package

Using Just-in-Time Packages is a great way to reduce the configuration complexity of your repository. Using a Just-In-Time Package allows you to directly consume TypeScript into applications without having to pre-compile them. Instead, the applications themselves will compile the TypeScript packages when they build for production.

While this approach is much simpler to set up, it does come with one drawback when using Turborepo: Because your package does not have build outputs, you won't be able to cache the build step for your package. This is a simple tradeoff of simplicity vs. build times. If you're interested in improving your build times, take a look at the Internal Packages page to add a cacheable build step.

Let's take a look at what this looks like by building a UI components package with React and Typescript.

Create a workspace

We first need to lay the foundation for our workspace. We can do so in a few quick steps.

Make sure our package manager sees the workspace

Establish a workspace by following the workspace instructions for your package manager.

Add our tsconfig.json

We'll be making a TypeScript package so we need to have a tsconfig.json. If you've read the Typescript reference already, this will look familiar:

packages/ui/tsconfig.json
{
"$schema": "https://json.schemastore.org/tsconfig",
"extends": "@repo/tsconfig/react-library.json",
"compilerOptions": {
"tsBuildInfoFile": "node_modules/.cache/tsbuildinfo.json",
"outDir": "dist"
},
"include": ["."],
"exclude": ["dist", "node_modules"]
}
packages/ui/tsconfig.json
{
"$schema": "https://json.schemastore.org/tsconfig",
"extends": "@repo/tsconfig/react-library.json",
"compilerOptions": {
"tsBuildInfoFile": "node_modules/.cache/tsbuildinfo.json",
"outDir": "dist"
},
"include": ["."],
"exclude": ["dist", "node_modules"]
}

Create an entrypoint to your code

Now, we'll create an entrypoint to our code so that other applications and packages can import it.

The "exports" field make the code available for compilation while the "typesVersions" field makes the type definitions available.

packages/ui/package.json
{
"name": "@repo/ui",
"version": "0.1.0",
"private": true,
"exports": {
".": "./src/index.tsx"
},
"typesVersions": {
"*": {
"*": ["./src/index.tsx"]
}
},
"dependencies": {},
"devDependencies": {}
}
packages/ui/package.json
{
"name": "@repo/ui",
"version": "0.1.0",
"private": true,
"exports": {
".": "./src/index.tsx"
},
"typesVersions": {
"*": {
"*": ["./src/index.tsx"]
}
},
"dependencies": {},
"devDependencies": {}
}

That's it! We don't need to worry about compiling this code because we're going to have the consuming applications compile them in the next step.

Tell your applications to compile TypeScript packages

If you see an error that says,

Module parse failed: Unexpected token (5:9)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file.
Module parse failed: Unexpected token (5:9)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file.

This means that your TypeScript dependencies didn't get transpiled.

Modern frameworks use powerful compilers and bundlers that can automatically transpile TypeScript source code - even if that code is outside the application's context!

Let's take a look at how a few of the ones do this.

Vite

Vite handles TypeScript packages out of the box! No configuration required!

Next.js

For Next.js to transpile your external TypeScript code, you'll need to add a transpilePackages to your next.config.js:

next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
transpilePackages: ['@repo/ui'],
};

module.exports = nextConfig;
next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
transpilePackages: ['@repo/ui'],
};

module.exports = nextConfig;

For more, visit the documentation.

Vue

Vue can transpile your packages on-the-fly by adding transpileDependencies to your vue.config.js:

vue.config.js
module.exports = {
transpileDependencies: ['@repo/ui'],
};
vue.config.js
module.exports = {
transpileDependencies: ['@repo/ui'],
};

For more, visit the documentation.