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!

Multiple Entrypoint Package

Using the knowledge we gained in the Internal Packages and Just-In-Time Packages, we can easily create packages with multiple entrypoints.

Motivation

There could be several reasons that you'd want to create your package with multiple entrypoints:

Add an entrypoint to an Internal Package

To pick up where we left off at the end of the Internal Packages page, we had a transpiled package that we could share to the rest of our workspaces with one entrypoint.

To give this package another entrypoint, we'll only need to make a few small changes.

Add some source code

Let's add another file to our source code for a couple icons:

packages/ui/src/icons.tsx
export const Circle = (props: SVGAttributes<SVGElement>) => {
return (
<svg {...props} viewBox="0 0 50 50">
<circle cx="25" cy="25" r="20" />
</svg>
);
};

export const Square = (props: SVGAttributes<SVGElement>) => {
return (
<svg {...props} viewBox="0 0 50 50">
<rect x="10" y="10" width="30" height="30" />
</svg>
);
};
packages/ui/src/icons.tsx
export const Circle = (props: SVGAttributes<SVGElement>) => {
return (
<svg {...props} viewBox="0 0 50 50">
<circle cx="25" cy="25" r="20" />
</svg>
);
};

export const Square = (props: SVGAttributes<SVGElement>) => {
return (
<svg {...props} viewBox="0 0 50 50">
<rect x="10" y="10" width="30" height="30" />
</svg>
);
};

Add the tsup entrypoint

Next, we'll need to make tsup aware of the new entry to your package.

packages/ui/tsup.config.js
export default defineConfig((options) => ({
entry: [
"src/index.tsx",
"src/icons.tsx"
]
...
}));
packages/ui/tsup.config.js
export default defineConfig((options) => ({
entry: [
"src/index.tsx",
"src/icons.tsx"
]
...
}));

Note: We're using JavaScript here but will still get great autocomplete. 😄

Add a new entry to exports

Last, we'll add the entrypoint to our package.json.

packages/ui/package.json
{
"name": "@repo/ui",
"version": "0.1.0",
"private": true,
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js"
},
"./icons": {
"types": "./dist/icons.d.ts",
"import": "./dist/icons.js"
}
},
...
}
packages/ui/package.json
{
"name": "@repo/ui",
"version": "0.1.0",
"private": true,
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js"
},
"./icons": {
"types": "./dist/icons.d.ts",
"import": "./dist/icons.js"
}
},
...
}

You'll now be able to import from the entrypoint using:

apps/web/src/index.tsx
import { Circle } from '@repo/ui/icons';
apps/web/src/index.tsx
import { Circle } from '@repo/ui/icons';

Adding an entrypoint to a Just-In-Time Package

To pick up where we left off at the end of the Just-In-Time Package page, we can add another entrypoint in two quick steps.

Add some source code

Let's add another file to our source code for a couple icons:

packages/ui/src/icons.tsx
export const Circle = (props: SVGAttributes<SVGElement>) => {
return (
<svg {...props} viewBox="0 0 50 50">
<circle cx="25" cy="25" r="20" />
</svg>
);
};

export const Square = (props: SVGAttributes<SVGElement>) => {
return (
<svg {...props} viewBox="0 0 50 50">
<rect x="10" y="10" width="30" height="30" />
</svg>
);
};
packages/ui/src/icons.tsx
export const Circle = (props: SVGAttributes<SVGElement>) => {
return (
<svg {...props} viewBox="0 0 50 50">
<circle cx="25" cy="25" r="20" />
</svg>
);
};

export const Square = (props: SVGAttributes<SVGElement>) => {
return (
<svg {...props} viewBox="0 0 50 50">
<rect x="10" y="10" width="30" height="30" />
</svg>
);
};

Add a new entry to exports

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

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

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

You'll now be able to import from the entrypoint using:

apps/web/src/index.tsx
import { Circle } from '@repo/ui/icons';
apps/web/src/index.tsx
import { Circle } from '@repo/ui/icons';