TypeScript project references, paths alias y configuración para monorepos

En proyectos con múltiples paquetes o workspaces, compilar todo desde cero en cada cambio es lento y los alias de rutas importadas con cadenas relativas largas como ../../../componentes/ui son difíciles de mantener. Las project references de TypeScript resuelven el primer problema mediante compilaciones incrementales, y los paths alias del tsconfig resuelven el segundo. Esta guía cubre ambas herramientas y cómo configurar los alias en Vite, webpack y esbuild.

Project references: composite y references

Para que un proyecto TypeScript pueda referenciar a otro, el proyecto referenciado debe tener composite: true en su tsconfig. Esto activa la generación de archivos .d.ts y de un fichero .tsbuildinfo para la compilación incremental:

// packages/utils/tsconfig.json  (proyecto referenciado)
{
  "compilerOptions": {
    "composite": true,
    "declaration": true,
    "declarationMap": true,
    "outDir": "./dist",
    "rootDir": "./src"
  },
  "include": ["src"]
}

// packages/app/tsconfig.json  (proyecto que referencia)
{
  "compilerOptions": {
    "outDir": "./dist",
    "rootDir": "./src"
  },
  "references": [
    { "path": "../utils" }   // ruta al tsconfig del proyecto referenciado
  ],
  "include": ["src"]
}

// Compilar con referencias (incremental, solo lo que cambió):
// tsc --build packages/app

tsconfig raíz con extends

En un monorepo con muchos paquetes es habitual tener un tsconfig base compartido y extenderlo en cada paquete:

// tsconfig.base.json  (raíz del monorepo)
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true
  }
}

// packages/api/tsconfig.json
{
  "extends": "../../tsconfig.base.json",
  "compilerOptions": {
    "composite": true,
    "outDir": "./dist",
    "rootDir": "./src"
  }
}

// tsconfig.json raíz (solo para el IDE, no para compilar)
{
  "files": [],
  "references": [
    { "path": "packages/utils" },
    { "path": "packages/api" },
    { "path": "packages/web" }
  ]
}

paths alias con baseUrl

Los paths alias permiten usar @/componentes/Boton en lugar de ../../componentes/Boton. Se configuran con baseUrl y paths en el tsconfig:

// tsconfig.json
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"],
      "@componentes/*": ["src/componentes/*"],
      "@utils/*": ["src/utils/*"],
      "@tipos": ["src/types/index"]
    }
  }
}

// Ahora en cualquier archivo:
import { Boton } from "@componentes/Boton";
import { formatearFecha } from "@utils/fecha";
import type { Usuario } from "@tipos";

Configurar los alias en Vite

// vite.config.ts
import { defineConfig } from "vite";
import path from "path";

export default defineConfig({
  resolve: {
    alias: {
      "@": path.resolve(__dirname, "./src"),
      "@componentes": path.resolve(__dirname, "./src/componentes"),
      "@utils": path.resolve(__dirname, "./src/utils"),
    },
  },
});

// También puedes usar el plugin vite-tsconfig-paths para leerlos del tsconfig:
// import tsconfigPaths from "vite-tsconfig-paths";
// plugins: [tsconfigPaths()]

Configurar los alias en webpack

// webpack.config.js
const path = require("path");

module.exports = {
  resolve: {
    alias: {
      "@": path.resolve(__dirname, "src"),
      "@componentes": path.resolve(__dirname, "src/componentes"),
    },
    extensions: [".ts", ".tsx", ".js"],
  },
};

Configurar los alias en esbuild / tsconfig-paths

// Para Node.js en runtime (no solo compilación):
// npm install -D tsconfig-paths

// Ejecutar con alias resueltos:
// node -r tsconfig-paths/register dist/index.js

// O en el entry point:
// tsconfig-paths/register debe llamarse antes de los imports

// Con tsx (ejecución directa sin compilar):
// tsx --tsconfig tsconfig.json src/index.ts  (alias resueltos automáticamente)

// Con esbuild:
import { build } from "esbuild";
import { TsconfigPathsPlugin } from "@esbuild-plugins/tsconfig-paths";

await build({
  entryPoints: ["src/index.ts"],
  bundle: true,
  plugins: [TsconfigPathsPlugin({ tsconfig: "./tsconfig.json" })],
});

Las project references y los paths alias son dos mejoras independientes que se complementan bien en monorepos grandes. Las references resuelven el rendimiento de la compilación; los alias resuelven la legibilidad de los imports. Ambas requieren configuración tanto en TypeScript como en la herramienta de build que uses, ya que TypeScript solo las gestiona a nivel de tipos, no en el bundling final.

Imagen: Pexels / Tima Miroshnichenko

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP