Analog

Astro

On this page

@analogjs/astro-angular

Astro 是一个现代 Web 框架,专为构建快速、内容为中心的网站而设计,兼容所有主流前端框架。虽然它主要是一个静态站点生成 (SSG) 工具,但它也可以集成称为 "islands" 的动态组件,这些组件支持部分 hydration。

此包允许在 Astro 中将 Angular 组件作为 islands 渲染。

设置

使用 Astro CLI

使用 astro add 命令安装集成

使用 npm:

npx astro add @analogjs/astro-angular

使用 pnpm:

pnpm astro add @analogjs/astro-angular

使用 yarn:

yarn astro add @analogjs/astro-angular

此命令将:

  • 安装 @analogjs/astro-angular 包。
  • @analogjs/astro-angular 集成添加到 astro.config.mjs 文件中。
  • 安装在服务端和客户端渲染 Angular 组件所需的依赖项,以及常见的 Angular 依赖项,例如 @angular/common

设置 TypeScript 配置

该集成需要在项目根目录下有一个 tsconfig.app.json 用于编译。

在项目根目录下创建一个 tsconfig.app.json

{
  "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"],
    "skipLibCheck": true
  },
  "angularCompilerOptions": {
    "enableI18nLegacyMessageIdFormat": false,
    "strictInjectionParameters": true,
    "strictInputAccessModifiers": true,
    "strictTemplates": true,
    "allowJs": false
  },
  "files": [],
  "include": ["src/**/*.ts", "src/**/*.tsx"]
}

前往 定义组件 以设置要在 Astro 组件中使用的 Angular 组件。

手动安装

也可以手动安装该集成

安装 Astro 集成

yarn add @analogjs/astro-angular

安装必要的 Angular 依赖项

npm install @angular/build @angular/{animations,common,compiler-cli,compiler,core,language-service,forms,platform-browser,platform-server} rxjs tslib --save

添加集成

将集成添加到 astro.config.mjs

export default defineConfig({
  integrations: [angular()],
});

前往 定义组件

配置

配置 Vite Angular 插件

提供一个选项对象来配置驱动此插件的 @analogjs/vite-plugin-angular

export default defineConfig({
  integrations: [
    angular({
      vite: {
        inlineStylesExtension: 'scss|sass|less',
      },
    }),
  ],
});

过滤文件转换

为了在与其他插件(如 Starlight)集成时获得更好的兼容性,请将 Angular 组件放在特定文件夹中,并使用 transformFilter 回调函数仅转换这些文件。

export default defineConfig({
  integrations: [
    angular({
      vite: {
        transformFilter: (_code, id) => {
          return id.includes('src/components'); // <- only transform Angular TypeScript files
        },
      },
    }),
  ],
});

为 SSR 兼容性转换包

为确保 Angular 库在 Astro 的 SSR 过程中被转换,请将它们添加到 Vite 配置中的 ssr.noExternal 数组中。

export default defineConfig({
  integrations: [angular()],
  vite: {
    ssr: {
      // transform these packages during SSR. Globs supported
      noExternal: ['@rx-angular/**'],
    },
  },
});

定义组件

Astro Angular 集成 支持渲染 standalone components:

@Component({
  selector: 'app-hello',
  template: `
    <p>Hello from Angular!!</p>

    @if (show()) {
      <p>{{ helpText() }}</p>
    }

    <button (click)="toggle()">Toggle</button>
  `,
})
export class HelloComponent {
  helpText = input('help');

  show = signal(false);

  toggle() {
    this.show.update((show) => !show);
  }
}

将 Angular 组件添加到 Astro 组件模板中。这仅渲染 Angular 组件的 HTML。

---
const helpText = "Helping binding";
---

<HelloComponent />
<HelloComponent helpText="Helping" />
<HelloComponent helpText={helpText} />

要在客户端 hydrate 组件,请使用 Astro client directives 之一:

---
---

<HelloComponent client:visible />

在 Astro 文档中查找有关 Client Directives 的更多信息。

监听组件 Output

Angular 组件发出的 Output 会作为 HTML 事件转发给 Astro island。 要启用此功能,请向每个 Angular 组件添加一个 client directive 和唯一的 [data-analog-id] 属性:

---
---

<HelloComponent client:visible data-analog-id="hello-component-1" />

然后,使用 addOutputListener 函数在 Astro 组件中监听该事件:

---
---

<HelloComponent client:visible data-analog-id="hello-component-1" />

<script>
  addOutputListener('hello-component-1', 'outputName', (event) => {
    console.log(event.detail);
  });
</script>

添加组件 Providers

可以向组件添加额外的 providers 以用于静态渲染和客户端 hydration。

它们分别是 renderProvidersclientProviders。这些 providers 被定义为组件类上的静态数组,并在组件渲染和在客户端 hydrate 时注册。

interface Todo {
  id: number;
  title: string;
  completed: boolean;
}

@Component({
  selector: 'app-todos',
  template: `
    <h2>Todos</h2>

    <ul>
      @for (todo of todos(); track todo.id) {
        <li>
          {{ todo.title }}
        </li>
      }
    </ul>
  `,
})
export class TodosComponent implements OnInit {
  static clientProviders = [provideHttpClient()];
  static renderProviders = [TodosComponent.clientProviders];

  http = inject(HttpClient);
  todos = signal<Todo[]>([]);

  ngOnInit() {
    this.http
      .get<Todo[]>('https://jsonplaceholder.typicode.com/todos')
      .subscribe((todos) => this.todos.set(todos));
  }
}

在 MDX 页面中使用组件

要在 MDX 页面中使用组件,必须按照 @astrojs/mdx 的 Astro 集成指南安装和配置 MDX 支持。你的 astro.config.mjs 现在应该包含 @astrojs/mdx 集成。

export default defineConfig({
  integrations: [mdx(), angular()],
});

src/pages 目录中创建一个 .mdx 文件,并在 frontmatter 下方添加 Angular 组件导入。

---
layout: '../../layouts/BlogPost.astro'
title: 'Using Angular in MDX'
description: 'Lorem ipsum dolor sit amet'
pubDate: 'Sep 22 2022'
---

<HelloComponent />
<HelloComponent helpText="Helping" />

要在客户端 hydrate 组件,请使用 Astro client directives 之一:

---
layout: '../../layouts/BlogPost.astro'
title: 'Using Angular in MDX'
description: 'Lorem ipsum dolor sit amet'
pubDate: 'Sep 22 2022'
---

<HelloComponent client:load />
<HelloComponent client:visible helpText="Helping" />

重要提示:在 .mdx 文件中,组件导入必须以 .ts 后缀结尾。否则,组件的动态导入将失败,组件将不会被 hydrate。

当前限制

  • 仅支持 v14.2+ 版本的 standalone Angular 组件
  • 不支持向 island 组件进行内容投影 (Content projection)