#Shared components for multiple Astro websites in monorepo setup
1 messages · Page 1 of 1 (latest)
Hi @ionic sedge. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:
To set up a monorepo for multiple Astro websites that share components, you can use workspaces and import aliases. Here's how you can approach this:
Setting up a monorepo with shared components
Astro supports workspaces within your project, which allows you to develop components alongside multiple Astro sites.
1. Structure your monorepo
Create a directory structure like this:
my-monorepo/
├── package.json
├── packages/
│ └── shared-components/
│ ├── index.js
│ ├── package.json
│ └── components/
│ └── ... your shared components
├── site-one/
│ └── ... Astro project files
└── site-two/
└── ... Astro project files
2. Configure workspaces
In your root package.json, define your workspaces:
{
"name": "my-monorepo",
"workspaces": ["site-*", "packages/*"]
}
3. Set up the shared components package
In your packages/shared-components/package.json:
{
"name": "@myorg/shared-components",
"version": "1.0.0",
"main": "index.js"
}
4. Configure import aliases in each Astro site
For each Astro site, set up import aliases in the tsconfig.json:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"$lib/components/*": ["../packages/shared-components/components/*"]
}
}
}
This allows you to import shared components using the $lib/components/* path as requested Import aliases.
5. Add dependencies to each Astro site
In each Astro site's package.json, add the shared components as a dependency:
{
"dependencies": {
"@myorg/shared-components": "workspace:*"
}
}
6. Configure Vite in Astro
When working with Astro in a monorepo, you might need to add the shared dependencies to the vite.ssr.noExternal configuration to ensure they're properly bundled:
// astro.config.mjs
import { defineConfig } from 'astro/config';
export default defineConfig({
vite: {
ssr: {
noExternal: ['@myorg/shared-components']
}
}
});
This helps avoid issues with dependencies in a monorepo setup as mentioned in the troubleshooting guide.
7. Using shared components
Now you can import and use your shared components in any Astro site:
---
import SharedComponent from '$lib/components/SharedComponent.astro';
---
<SharedComponent />
This approach allows you to maintain a single source of truth for your components while using them across multiple Astro websites in your monorepo.
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
@ionic sedge Kapa.ai is still learning and improving, please let me know how I did by reacting below.
@round night In shared components I want to import src/data/consts.ts that is unique for each site (i.e. my-sites/site-a/src/data/consts.ts). How to do that?
Let me check the knowledge base for you again. One moment! :books:
I understand you want to import site-specific constants from each site into your shared components. This is a common need in monorepo setups with Astro. Here's how you can achieve this:
Importing site-specific constants in shared components
You can use import aliases and a pattern that allows your shared components to access site-specific data. Here are a few approaches:
1. Using import aliases with a consistent path
In each site's tsconfig.json, set up an alias that points to its own data directory:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"$lib/components/*": ["../packages/shared-components/components/*"],
"@site-data/*": ["./src/data/*"]
}
}
}
Now in your shared components, you can import using this alias:
---
import { someConstant } from '@site-data/consts';
---
This works because each site has its own alias configuration pointing to its own data directory Import aliases.
2. Using environment variables
Another approach is to use environment variables to determine which site's constants to load:
In your shared component:
---
// This dynamically imports the correct constants based on the site
const { default: siteConstants } = await import(`../../${import.meta.env.SITE_ID}/src/data/consts.ts`);
---
Then in each site's .env file:
SITE_ID=site-a
3. Using middleware for site-specific context
You can also use Astro's middleware to inject site-specific data into Astro.locals:
// In each site's src/middleware.ts
export function onRequest(context, next) {
// Import site-specific constants
import('./data/consts.js').then(module => {
// Add to locals so components can access it
context.locals.siteConstants = module.default;
});
return next();
}
Then in your shared components:
---
const { siteConstants } = Astro.locals;
---
This leverages Astro's middleware capabilities to make site-specific data available to all components Basic Usage.
Choose the approach that best fits your project structure and requirements. The import alias method is generally the cleanest and most maintainable for most projects.