📐

AngularのメタフレームワークAnalogを試す

2022/12/10に公開

はじめに

今回は、AnalogというAngularのメタフレームワークを試してみたので紹介します。

Analogとは

Analogは、Angularのフルスタックメタフレームワークです。
https://analogjs.org/

GDEで、NgrxのメンテナーもしているBrandon氏が主に開発しているOSSで、現在は次の機能が提供されています。

  • Vite-powered
    • AnalogはビルドツールとしてViteを使用しており、テストもVitestを使っているようです。
  • File-based routing and API routes
    • Next.jsやNuxt.jsのpagesフォルダのようにディレクトリ構成でルーティングが決定する実装になっています。
  • Hybrid SSR/SSG support (upcoming features)
    • SSRやSSGについてはViteの機能を上手く使おうとしているようで開発予定となっています。
    • 2023/4/3追記:AnalogがSSGとSSRをサポートしてました
      • SSGの方はViteのprerenderを上手く使っているようです。
      • SSRの方はAngularUniversalのrenderApplication関数を上手く使っているようです。

試してみる

アプリケーションを作成する

最初に、次のコマンドでプロジェクトを作成します。

npm create analog@latest

次に、プロジェクト名を聞かれるので、任意の名前に設定します。

Project name: analog-sample

その後、テンプレートを聞かれるので、「Analog」を選択します。

Select a template: › Analog

最後に、Angularのバージョンを聞かれるので、「angular-v15」を選択します。

Select a variant: › angular-v15

アプリケーションが作成されたら、package.jsonを参照すると分かるとおり、普段のAngularアプリケーションのように、npmコマンドを実行できます。

npm run start

初期化時に生成されるtsconfig.jsonのtargetがES2022になっており、ES2022のクラスの静的メソッド、static-class-featuresの辺りがSafariでエラーになっていたので、es2018にします。tsconfig.jsonを設定する

tsconfig.json
  "compilerOptions": {
  ...
-   "target": "ES2022",
+   "target": "es2018",
  },
  ...

また、自分が試した時は、vitestがtypescriptに上手く認識されていなかったので、"vitest"を追加して回避しました。

tsconfig.spec.json
  "compilerOptions": {
-   "types": ["node", "vitest/globals"]
+   "types": ["node", "vitest/globals", "vitest"]
  },

加えて、AnalogはStandalone Componentを前提としているため、angular-cliを使う場合は、angular.jsonに次の記述を追加するとng g cで作成するコンポーネントがデフォルトでStandaloneとなり、作成しやすいです。

angular.json
...
        "test": {
          "builder": "@nrwl/vite:test",
          "options": {
            "config": "vite.config.ts"
          }
        }
      },
+      "schematics": {
+       "@schematics/angular:component": {
+         "standalone": true
+       }
+     }
...

ディレクトリ構成とルーティング

src/
├─ app/
│  ├─ routes/
│  │  ├─ index.ts
├─ assets/
├─ server/
│  ├─ routes/
│  │  ├─ v1/
│  │  │  ├─ hello.ts

アプリケーション初期化時には、このようなディレクトリ構成になっており、app/routesがNext.jsやNuxt.jsのpagesに相当するものとなっており、フロントエンド側のルーティングが設定されます。Angularアプリケーションでよく使われる次のようなルーティング設定を記述しなくても動くようになっています。

app-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { TopComponent } from './pages/top/top.component';

const routes: Routes = [{ path: '', component: TopComponent }];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule],
})
export class AppRoutingModule {}

また、server/routes/v1にサーバー側のAPIを記述することができます。

hello.ts
import { defineEventHandler } from 'h3';

export default defineEventHandler(() => ({ message: 'Hello World' }));

記述方法はViteを使っているため、Nuxt.jsと似ています。
https://nuxt.com/docs/guide/directory-structure/server#server-routes

そして、フロントエンド側からは、次のように呼び出すことができます。

api.service.ts
import { inject, Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable({
  providedIn: 'root'
})
export class ApiService {
  private http = inject(HttpClient);

  getHello() {
    return this.http.get<{ message: string }>('/api/v1/hello');
  }
}

ルーティングの定義方法

Defining Routesにある通り、現状は、5種類のルーティングの定義方法がありました。

  • Index Routes
    • src/app/routes/(home).tsのように(home)とすることで、トップのルート/で表示するコンポーネントを指定できます。
  • Static Routes
    • src/app/routes/static.tsとすることでファイル名そのままのルート/staticで表示するコンポーネントを指定できます。
  • Dynamic Routes
    • src/app/routes/dynamic.[pageId].tsとすることでファイル名そのままのルート/dynamic/:pageIdで表示するコンポーネントを指定できます。
  • Nested Routes
    • ディレクトリ構造を次のようにすることで/products/以下を<router-outlet></router-outlet>する/products/配下のルートコンポーネントであるproducts.ts/productsで表示する(products-list).ts/products/:productIdで表示する[productId].ts、のようにコンポーネントを指定できます。
routes/
│   └── products/
│      ├──[productId].ts
│      └──(products-list).ts
└── products.ts
  • Catch-all routes
    • src/app/routes/[...page-not-found].tsとすることで、404ページのようなアプリケーション内でパスの指定がないルートに対して表示するコンポーネントを指定できます。

ルーティングに関してはサンプルアプリケーションを作成したので、興味があれば見てみてください。
komura-c-analog-sample.netlify.app/
github.com/komura-c/analog-sample
また、Analogのリポジトリにも実装サンプルがあります。https://github.com/analogjs/analog/tree/main/apps

おわりに

AngularのメタフレームワークAnalogを試してみました。現状試した感想は、Viteを使っているのでビルドが早いという所とルーティングの体験が簡単なのが良いなと感じました。今後が楽しみです。
また、開発者のBrandon氏は、Building Angular Applications with Viteという動画も公開しているので、見てみると理解が深まるかもしれません。

明日は、@masayasvielさんです。

Voicyテックブログ

Discussion