DEV Community

Cover image for Bringing Angular Components to Astro Islands 🏝
Brandon Roberts
Brandon Roberts

Posted on • Updated on

Bringing Angular Components to Astro Islands 🏝

Astro is a relatively new web framework that has a focus on helping you build faster websites. It also has a very interesting extension point in that you can bring your own UI framework of choice, including React, Svelte, Vue, and more. I even rewrote my Angular blog to use Astro in its alpha release days. This post is about bringing things full circle and using Angular components inside an Astro project.


TL;DR
GitHub repo: https://github.com/brandonroberts/angular-astro-islands
Sample website: https://angular-analog-astro-islands.netlify.app/
Partnership Opportunities: https://analogjs.org/docs/sponsoring


I initially wanted to use Angular components in Astro but couldn't do to multiple constraints. Many things have changed since then. Angular v14 includes standalone components that no longer need NgModules. Astro has continued to be developed, switched from Snowpack to Vite for its underlying build tool, and been released as 1.0. In the meantime, I've been working on a Analog, a meta-framework for building Angular applications and websites powered by Vite.

Astro provides integrations to allow additional UI frameworks to render their components inside Astro projects. With these pieces together, we can now take Angular components, render them in Astro, and hydrate them on the client.

Let's dive in!

Creating a New Astro Project

First, create a new Astro project:

With npm:

npm init astro
Enter fullscreen mode Exit fullscreen mode

With yarn:

yarn create astro
Enter fullscreen mode Exit fullscreen mode

Follow the prompts, along with choosing Just the basics to start. Next, is adding the @analogjs/astro-angular integration.

Adding the Angular Integration

The @analogjs/astro-angular integration adds support for using Angular components in an Astro project. The integration provides the Vite Plugin for Angular to compile and transform Angular components, renders Angular components on the server, and hydrates the components as needed on the client.

Use the astro add command to install the integration:

astro add @analogjs/astro-angular
Enter fullscreen mode Exit fullscreen mode

This command:

  • Installs the @analogjs/astro-angular package.
  • Adds the @analogjs/astro-angular integration to the astro.config.mjs file.
  • Installs the necessary Angular dependencies to render Angular components on the server hydrate them on the client, and common Angular dependencies, such as @angular/common and @angular/forms.

After installation, the astro.config.mjs looks like this:

import { defineConfig } from 'astro/config';

import analogjsAngular from "@analogjs/astro-angular";

// https://astro.build/config
export default defineConfig({
  integrations: [analogjsAngular()]
});
Enter fullscreen mode Exit fullscreen mode

Setting up the TypeScript config

The Angular integration needs a tsconfig.app.json at the root of the project for compilation.

Create a tsconfig.app.json in the root of the project.

{
  "extends": "./tsconfig.json",
  "compileOnSave": false,
  "compilerOptions": {
    "baseUrl": "./",
    "outDir": "./dist/out-tsc",
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "noImplicitOverride": true,
    "noPropertyAccessFromIndexSignature": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "sourceMap": true,
    "declaration": false,
    "downlevelIteration": true,
    "experimentalDecorators": true,
    "moduleResolution": "node",
    "importHelpers": true,
    "noEmit": false,
    "target": "es2020",
    "module": "es2020",
    "lib": ["es2020", "dom"]
  },
  "angularCompilerOptions": {
    "enableI18nLegacyMessageIdFormat": false,
    "strictInjectionParameters": true,
    "strictInputAccessModifiers": true,
    "strictTemplates": true
  },
  "files": [],
  "include": ["src/**/*.ts"]
}
Enter fullscreen mode Exit fullscreen mode

You can tweak the compiler settings as needed.

Adding an Angular Component

The Angular integration only supports rendering standalone components. With that caveat out of the way, defining an Angular component using standalone features is relatively straightforward.

Define a component in the components folder. The example below uses src/components/hello.component.ts.

import { NgIf } from '@angular/common';
import { Component } from '@angular/core';

@Component({
  selector: 'app-hello',
  standalone: true,
  imports: [NgIf],
  template: `
    <p>Hello from Angular!!</p>

    <button (click)="toggle()">Toggle</button>

    <p *ngIf="show">Toggled</p>
  `,
})
export class HelloComponent {
  show = true;

  toggle() {
    this.show = !this.show;
  }
}
Enter fullscreen mode Exit fullscreen mode

This is a pretty simple Angular component that toggles some text to show change detection working properly.

Next, add the Angular component to the Astro component template. In the generated Astro project, add the HelloComponent to the src/pages/index.astro page.

---
import Layout from '../layouts/Layout.astro';
import Card from '../components/Card.astro';
import { HelloComponent } from '../components/hello.component.ts';
---

<Layout title="Welcome to Astro.">
    <main>
        <h1>Welcome to <span class="text-gradient">Astro</span></h1>

        <!-- Angular Component -->
        <HelloComponent />

        <!-- HTML 😉 -->

        </main>
</Layout>
Enter fullscreen mode Exit fullscreen mode

This only renders the HTML from the Angular component. To hydrate the component on the client, use one of Astro's client directives:

<HelloComponent client:visible />
Enter fullscreen mode Exit fullscreen mode

Find more information about Client Directives in the Astro documentation.

Developing the Website

To view the running website, start the dev server using the Astro CLI:

yarn astro dev
Enter fullscreen mode Exit fullscreen mode

Visit the website at http://localhost:3000, including the new Angular component 😎.

Astro + Angular

Now its your turn to make some tweaks and play around 😀.

To build for deployment:

yarn astro build
Enter fullscreen mode Exit fullscreen mode

Summary

This integration opens the door for web developers to build faster websites using Astro with Angular components. The Analog project and Astro Integration is actively being developed, so if you'd like to contribute, join us on GitHub and Discord.

Learn More

  • Visit the Analog Docs
  • Follow the Analog project on Twitter
  • Join me at ViteConf to learn more about "Vite, Meta-frameworks, and Angular".

So what do you think? Leave a ❤️ on the post, and leave a comment and let me know your thoughts.

Top comments (8)

Collapse
 
arturgawlik profile image
arturgawlik • Edited

Great work! Are there any plans to support Angular components events (@Output) in Astro?

Collapse
 
brandontroberts profile image
Brandon Roberts

Thanks! Astro does not support component events on the client-side, so @Output is not supported.

docs.astro.build/en/core-concepts/...

Collapse
 
riscie profile image
riscie

This looks very promising! The combination of having a fast, statically built website with the possibility of implementing dynamic UI where needed is very compelling to me.
For this reason, astro was interesting to me before I knew that people were working on an angular integration.

And this post makes it even more interesting to me, because I am primarily an angular guy :P

I hope astro finds wide adaption. Even if it's only within the angular community. Because I feel like other communities already have decent solutions for fast, SSR websites within their frameworks ecosystem.

Having worked with angular universal and also scully.io in the past. I think we still have some ground to make up in this area.

Great work @brandontroberts!

Collapse
 
olierxleben profile image
Oliver Erxleben • Edited

The tsconfig.app.json was not recognised and I added it to the normal tsconfig.json.

The toggle button did not triggered change detection on my local following. Any idea why this may happen?

my editor was hinting me to not use the .ts file extension during import. But this is obviously necessary in an astro file.

Collapse
 
intellix profile image
Dominic Watson

Looks really cool, especially in a time when SSR is so painfully large. After following your basic example, I noticed my common bundle is 313kb yet yours is only 95kb... how were you able to achieve a "production" build? I don't see it in the help etc

Collapse
 
sakar_dhana profile image
Sakar

Hi this relay amazing! Is it possible to bring all the Angular feature into Astro. Like Angular reactive forms, Angular service injecting, Angular material components, etc.

Collapse
 
serg profile image
Sergio Wilson

@brandontroberts great post.
anyway to force the Astro / Analog integration to client side only globally i.e
analogjsangular({ ssr: false})

Collapse
 
brandontroberts profile image
Brandon Roberts

Thanks Sergio.

This isn't possible, because the client-side control is handled by Astro and not the Analog integration. Astro is no client-side JavaScript by default, so you have to opt into it when using the components on the page.