この記事で学べること
・Angularとは
・JavaScriptフレームワークの比較
・環境構築
・Angularの基本構成
・ログイン画面の実装(Angular+Firebase)
Angularとは
Angularは、Googleが開発しているSPA(Single Page Application)のJavascriptフレームワークです。
最近ではReact, Vue が人気が高いですが、
Angularの一番の特徴は、フルスタックなフレームワークであると言うことです。
React や Vueも同じJavaSqriptフレームワークですが、 React や Vue はライブラリでAngularはフレームワークだと言われることがあります。
その言葉の通り、React, Vueは他のライブラリと併用して開発することが多く、AngularはAngular内のライブラリのみで構成されていることが多いです。
JavaScriptフレームワークの比較
- HTMLとJSの関係について
- Angularは、HTMLとJavaScript(TypeScript)を分割してかきます
- Reactは、JavaScriptの中にHTMLを書きます
- Vueは、HTMLにJavaScriptを書きます
- 各フレームワークの性能について
- Reactが性能面で総合的に有利
- Angularは起動に不利だが、実行性能(フレームレート)は良好
- Vueは大量にコンポーネントを配置するような場面においては不利
性能について、フレームレート、メモリ使用量、ライブラリ容量、ライブラリの起動時間により比較したサイト
Vue・React・Angularのパフォーマンス比較検証
Angularの環境構築
インストール方法(angular-cli)
$ npm install -g @angular/cli
Angular-Cli
をインストールすることにより、ターミナル上で ng
コマンドが使用可能になります。
プロジェクトやコンポーネントのひな形を生成してくれます。
Angular CLIのコマンド
// 新規プロジェクトの作成
$ ng new <project-name>
// コンポーネントの作成
$ ng generate component <my-component>
// ローカルサーバーの起動(cnrl+Cでサーバーの停止ができます)
$ ng serve
詳しくは下記サイトを参考にしてください
<参考サイト>
Angular入門 未経験から1ヶ月でサービス作れるようにする その1. インストール
Angularの基本構成
プロジェクトのフォルダ構成
プロジェクトを作成すると以下のようなフォルダが作成される。
├── src
│ ├── app
│ │ ├── app.component.css
│ │ ├── app.component.html
│ │ ├── app.component.spec.ts
│ │ ├── app.component.ts
│ │ └── app.module.ts
│ ├── assets
│ ├── browserslist
│ ├── environments
│ │ ├── environment.prod.ts
│ │ └── environment.ts
│ ├── favicon.ico
│ ├── index.html
│ ├── karma.conf.js
│ ├── main.ts
│ ├── polyfills.ts
│ ├── styles.css
│ ├── test.ts
│ ├── tsconfig.app.json
│ ├── tsconfig.spec.json
│ └── tslint.json
├── e2e
│ ├── protractor.conf.js
│ ├── src
│ │ ├── app.e2e-spec.ts
│ │ └── app.po.ts
│ └── tsconfig.e2e.json
├── node_modules
│ ├── ...
├── README.md
├── angular.json
├── package.json
├── tsconfig.json
├── tslint.json
└── yarn.lock
ディレクトリ名 | 役割 |
---|---|
src | ソースコードを置くディレクトリ |
e2e | e2e(end to end) テスト(実際にブラウザを動かしてページのテストを行うもの)のコードを置くディレクトリ |
node_modules | nodeのモジュールが置かれるディレクトリ。基本的には触らない |
srcディレクトリ内のフォルダ構成
src ディレクトリの内部のディレクトリは以下の構成になっています。
ディレクトリ名 | 役割 |
---|---|
app | アプリケーションのソースコードを置くディレクトリ |
assets | 画像などの静的ファイルを置くディレクトリ |
environments | 開発環境と本番環境などの環境ごとに変動させたい値を格納するファイルを置くディレクトリ |
基本的にappフォルダに各コンポーネントごとにフォルダ分けし、ソースを格納していく形となります。
よく使うソース
ファイル名 | 役割 |
---|---|
app.component.ts | 作成されたプロジェクトの起点となるファイル。最初はこのファイルが動く |
app-routing.module.ts | ページ遷移のルーティングを行うファイル |
package.json | nodeのパッケージを管理するファイル。バージョン、ngコマンドの設定が記載 |
angular.json | Angularの設定ファイル。が記載 |
コンポーネントの設定
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
@Component
という記述は、おまじないのようなものと思っておきましょう。コンポーネントのTypescriptにつけるおまじないです。
中で指定されている3つの要素は、それぞれ下記を示しています。
要素 | 役割 |
---|---|
selector | このコンポーネントがHTMLから参照されるときのタグ名 (今回の場合、 <app-root></app-root> となる) |
templateUrl | このファイルのHTMLファイルのパス |
styleUrls | このファイルのCSSファイルのパス(配列なので、複数指定可能。共通のCSSを利用したいときなどに複数にすることがあるが、基本的には一つだと考えましょう) |
この宣言により、 app.component.ts
, app.component.html
, app.component.css
の3つのファイルが連携できるということになります。
ルーティングの設定方法
app-routing.module.tsは以下のような構成になっています。
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { SignUpComponent } from './sign-up/sign-up.component';
import { PortalComponent } from './portal/portal.component';
import { HomeComponent } from './home/home.component';
const routes: Routes = [
{ path: 'signup', component: SignUpComponent },
{ path: 'portal', component: PortalComponent },
{ path: 'portal/:id', component: HomeComponent },
{ path: '', redirectTo: '/portal', pathMatch: 'prefix' },
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
解説
解説と言いつつ、 @NgModule
以下の行は、とりあえずおまじないと思って無視しましょう。
重要なのは、 const routes: Routes
です。
ここで、ルーティングの定義を行っています。
{ path: 'portal', component: PortalComponent },
まず、これは、http://localhost:4200/portal
の URL(サーバにあげればホスト名は変わります)を 先程作成した PortalComponent
にマッピングする、という意味です。
{ path: 'products/:id', component: ProductDetailComponent },
次に、この行ですが、これは、 http://localhost:4200/portal/xxx
を HomeComponent
にマッピングするという意味です。
上記の :id
は、コンポーネントからパラメータとして取得できるので、その内容によってコンポーネントの状態を変更させたい場合に利用します。
portal の id
をURLから取得することで、最終的には API を叩いてその id
の portal
の情報を取得して表示する、というコンポーネントにしたいと思っています。
{ path: '', redirectTo: '/products', pathMatch: 'prefix' },
最後にこの行ですが、上で説明した2つのURL以外のURLが指定されると、自動的に /portal
にリダイレクトさせるという意味です。
ルーティングを有効な状態にする
app-routing.module.ts
はプロジェクト上に存在しているだけでどこからも参照されていないため、ルーティングの設定が完了していません。
Angularでは大きくmodule単位で管理されており、利用したい機能のModuleをimportすることでアプリケーション側で利用できるようになります。
app.module.ts
に以下の記述を追記してapp-routing.module
を参照するように設定してください。
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';// 追加
import { AppComponent } from './app.component';
import { SignUpComponent } from './sign-up/sign-up.component';
import { PortalComponent } from './portal/portal.component';
import { HomeComponent } from './home/home.component';
@NgModule({
declarations: [
AppComponent,
SignUpComponent,
PortalComponent,
HomeComponent
],
imports: [
BrowserModule,
AppRoutingModule // 追加
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
参考サイト
Angular入門 未経験から1ヶ月でサービス作れるようにする その2. ディレクトリ構造とコンポーネントの基礎
Firebaseとは
Firebase とは Google が提供しているモバイルおよび Web アプリケーションのBaaS(バックエンドサービス)です。
Firebaseの機能としては、認証(Authentication)、データベース(Database)、ストレージ(Storage)、ホスティング(Hosting)、Functionsなど便利な機能がたくさんあります。
では、今までの基礎を踏まえて以下のような順序でログイン画面の実装に入っていきます。
・プロジェクトの作成
・firebaseセットアップ
・firebaseインストール
・ログイン画面/ホーム画面の作成
プロジェクトの作成
まずAngularプロジェクトを作成したいディレクトリにて、以下のコマンドを実行します。
今回はプロジェクト名をlogin-sampleとします。(AngularCliがインストールされている前提で行います)
作成プロジェクトに階層を移動し、起動を確認てみましょう
// Angularプロジェクトの作成
ng new login-app
// ローカルサーバーの起動(cnrl+Cでサーバーの停止ができます)
$ ng serve
ローカルサーバーを起動してこの画面がでたら、プロジェクトの作成完了です。
Firebaseのセットアップ
https://firebase.google.com
から始めてみましょう。
右上の Go to console をクリックします。
(Googleアカウントでログインします。ない人は作りましょう)
アプリの作成
Firestoreのプロジェクト内にアプリを作成します。
歯車のアイコンをクリックし、「プロジェクトを設定」を開きます。
▼下の方になる「マイアプリ」のところのwebのボタンをクリックします。
下記のように設定し、「次へ」ボタンを押下。(その他の項目は特別設定することがないため、ボタンを押下で進んでしまって良い)
アプリの登録が完了したら、表示が変化します。構成のラジオボタンをクリックします。
すると、アプリケーション側で利用するFirebaseの設定情報が表示されるので、コピーしておきます。(environment.ts設定時に使用します)
Angularアプリケーションとfirebaseを連携させる
Angularで利用するFirebaseの公式Angularライブラリをインストールします。その際にプロジェクトを選択する際は、先程作成したtodo-demo-app-angularを選択します。
// Firebase CLIをインストール
npm install -g firebase-tools
// Angularで利用するFirebaseの公式Angularライブラリ
yarn add firebase
ng add @angular/fire@next
// angularfire2のインストール
npm install firebase angularfire2 --save
// firebaseの起動
firebase login
ng add @angular/fire@next
実行時にfirebaseを利用するプロジェクトを指定する必要があるため、
今回作成したlogin-appを指定してください。
つまづいた場合は下記サイトを参考にしてみてください。
FireBaseの設定/インストールについてまとめられているサイトFirebaseの始め方
各設定ファイルの修正
app.module.ts
にfirebaseで使うライブラリのインポートを記載します。
import { AngularFireModule } from 'angularfire2';// 追加
import { AngularFireAuthModule } from 'angularfire2/auth';// 追加
import { environment } from '../environments/environment';
@NgModule({
declarations: [
AppComponent,
SignUpComponent,
LoginComponent,
HomeComponent,
],
imports: [
BrowserModule,
AppRoutingModule,
AngularFireModule.initializeApp(environment.firebase),// 追加
AngularFireAuthModule,// 追加
],
先程コピーしたFirebaseの設定情報を参考にアプリケーションに追加します。
これで、アプリケーションからFirebaseに対して操作することができます。
設定情報はenvironment.ts
とenvironment.prod.ts
の両方に追記しておいてください。
export const environment = {
production: false,
firebase: {
apiKey: "XXXXXXXXXX",
authDomain: "XXXXX",
databaseURL: "XXXXX",
projectId: "XXXXXX",
storageBucket: "XXXXX",
messagingSenderId: "XXXX",
appId: "XXX",
measurementId: "XXX",
},
};
FirebaseHostingにデプロイ
動作確認も兼ねてFirebase Hostingにデプロイしてみましょう。
方法はとても簡単でfirebase deploy
するだけです。設定などはインストール時に自動的に設定されています。
デプロイが完了したら表示されたURLにアクセスしてみましょう。
ローカルサーバー起動時と同じ画面が表示できていれば完了です。
アプリケーションの実装
Angular Materialを導入
UI部分の実装工数をへらすために、Angular公式が提供するUIフレームワークのAngular Materialをインストールします。
インストールの際に対話形式でいくつか質問されます。
custom theme:基本となるカラーテーマを選択します。今回はIndigo/Pinkとしておきます。
他きかれることは基本的にYesで問題ないです。
ng add @angular/material
Angular Materialはいろんなところで利用するためモジュール化しておきます。
Angular Materialの見た目を使いたいときは、MatIconModuleのようなモジュールをimportする必要があります。
importすることで、対象のモジュールにぶら下がるComponentの中でAngular Materialの見た目がつかえるようになります。
機能ごとにモジュールを分割していくと都度Angular Materialをimportする必要がでてきて面倒なので、まとめてimportするためのmaterial.moduleを作っておきます。
ng g module material
使いたいAngular Materialのmoduleをimportしておき、exportsに列挙していきます。
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { MatIconModule } from '@angular/material/icon';
import { MatButtonModule } from '@angular/material/button';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatToolbarModule } from '@angular/material/toolbar';
import { DragDropModule } from '@angular/cdk/drag-drop';
@NgModule({
declarations: [],
imports: [CommonModule],
exports: [
MatToolbarModule,
MatIconModule,
MatButtonModule,
MatFormFieldModule,
MatInputModule,
DragDropModule,
],
})
export class MaterialModule {}
作成したMaterialモジュールをAppModuleにimportしてAppModuleに紐づくcomponetでAngular Materialを利用できるようにしておきます。
他に追加しているのはAngularMatelialで使用したいモジュールになります。
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { MaterialModule } from 'src/app/material/material.module';// 追加
import { FormsModule } from '@angular/forms';// 追加
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';// 追加
import { MatTabsModule } from '@angular/material/tabs';// 追加
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { AngularFireModule } from 'angularfire2';
import { AngularFireAuthModule } from 'angularfire2/auth';
import { environment } from 'src/environments/environment';
import { SignUpComponent } from './sign-up/sign-up.component';
import { LoginComponent } from './login/login.component';
import { HomeComponent } from './home/home.component';
@NgModule({
declarations: [
AppComponent,
SignUpComponent,
LoginComponent,
HomeComponent,
imports: [
BrowserModule,
FormsModule,// 追加
AppRoutingModule,
AngularFireModule.initializeApp(environment.firebase),
AngularFireAuthModule,
MaterialModule,// 追加
BrowserAnimationsModule,
MatTabsModule,// 追加
],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule {}
ここで記載しているSignUpComponent,LoginComponent,HomeComponent
は画面で使用するコンポーネントです。
次はこのコンポーネントにどういう役割を持たせ、構成していくのか説明して行きます。
今回はSignUpComponent,LoginComponent,HomeComponent
の三つのコンポーネントを使用してログイン+home画面の実装をして行きます。
役割は以下です
コンポーネント名 | 役割 |
---|---|
LoginComponent | ログイン画面を生成するコンポーネント |
SignUpComponent | Signup機能を実装するコンポーネント。 ログインコンポーネントの子要素 |
HomeComponent | ログイン後に遷移するhome画面 |
まずコンポーネントを生成します。
// ログインコンポーネントの生成
ng g component login
// サインアップコンポーネントの生成
ng g component signup
// ホームコンポーネントの生成
ng g component home
はじめに表示する画面としてログインコンポーネントが表示されるよう、ルーティングと大元となるコンポーネントのapp.component.html
の修正をします
<router-outlet></router-outlet>
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { SignUpComponent } from './sign-up/sign-up.component';
import { LoginComponent } from './login/login.component';
import { HomeComponent } from './home/home.component';
const routes: Routes = [
{ path: 'home', component: HomeComponent },
{ path: 'signup', component: SignUpComponent },
{ path: 'login', component: LoginComponent },
{ path: '', redirectTo: 'login', pathMatch: 'full'},
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
app-routing.module.ts
のpath設定でpath指定がなかったとき、また各コンポーネントがpathに入力されたときは、そのコンポーネントが表示させるよう設定します
ログイン画面の作成
ログインコンポーネントでは以下の処理を実装して行きます
・email,passを使用したログイン機能
・タイトルバーの実装
・signupボタンが押下された場合、signupコンポーネントにフォームを出しわけ機能
今回はAngularマテリアルのライブラリを利用して画面を作成して行きます
<mat-toolbar>
<label>{{title}}</label>
<span class="spacer"></span>
</mat-toolbar>
<div class="login">
<mat-tab-group mat-align-tabs="center">
<mat-tab label="Login">
<form
#loginForm="ngForm"
(ngSubmit)="login(loginForm)"
class="login-form"
>
<mat-form-field class="email-width">
<mat-label>Email</mat-label>
<input
type="email"
ngModel
name="email"
matInput
placeholder="半角英数字4文字"
/>
</mat-form-field>
<mat-form-field class="pass-width">
<mat-label>Pass</mat-label>
<textarea
type="password"
ngModel
name="password"
matInput
placeholder="半角英数字6字以上"
></textarea>
</mat-form-field>
<button mat-raised-button type="submit" color="primary">Login</button>
</form>
</mat-tab>
<mat-tab label="Signup">
<app-sign-up [title]="title"></app-sign-up>
</mat-tab>
</mat-tab-group>
</div>
使用しているAngularMaterialの機能は以下です
angular material | 役割 |
---|---|
mat-toolbar | ツールバー表示 |
mat-tab-group | タブに応じた画面表示ができる。ログインコンポーネントとsignupコンポーネントの出しわけを行う |
mat-form-field | フォームのデザインを整える |
今回詳しくは説明しませんが、気になりましたら公式ページから調べてみてください
https://material.angular.io/
import { Component, OnInit } from '@angular/core';
import { AuthService } from '../service/auth.service';
import { NgForm } from '@angular/forms';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
title = 'Login';
constructor(private authService: AuthService) { }
ngOnInit() {
}
login(loginForm: NgForm): void {
this.authService.login(loginForm.value.email, loginForm.value.password);
}
}
login.componet.ts
で行う処理は画面側からのemail,passwordの受け渡しと、titleの文字の設定です。
ここまででローカルサーバーを起動すると、以下のような画面になるはずです。
(loginメソッドのauthServiceのloginメソッドを呼び出す処理をコメントアウトして起動)
login.component.css
に以下ように追記します。
.login {
position: relative;
height: 50%;
width: 405px;
margin: auto;
margin-top: 5%;
padding: 60px 60px;
background: no-repeat center center #BCFBFF;
background-size: cover;
box-shadow: 0px 30px 60px -5px #000;
border-radius: 4px;
text-align: center;
}
.login-form {
min-width: 150px;
max-width: 500px;
width: 100%;
margin: auto;
padding-top: 10%;
}
.sigunup-label {
color: rgba(255, 255, 255, 0.2);
}
h2 {
padding-left: 12px;
font-size: 22px;
text-transform: uppercase;
padding-bottom: 5px;
letter-spacing: 2px;
display: inline-block;
font-weight: 100;
}
h2:first-child {
padding-left: 0px;
}
.email-width {
width: 100%;
}
.pass-width {
width: 100%;
}
.signup-form {
background: no-repeat center center #E1FF4A;
}
cssについては詳しく説明しません。
cssを適用した状態で起動すると、以下のような画面になります。
次にauth.service.ts
の実装をして行きます。
login、signupの処理を実装します。
まずauth.serviceを生成し、実装して行きます。
ng g service service/auth
import { Injectable } from "@angular/core";
import { AngularFireAuth } from "angularfire2/auth";
import { Router } from "@angular/router";
@Injectable({
providedIn: 'root',
})
export class AuthService {
user$ = this.afAuth.user;
constructor(private router: Router, private afAuth: AngularFireAuth) {}
signUp(email: string, password: string) {
this.afAuth.auth
.createUserWithEmailAndPassword(email, password)
.then( auth => auth.user.sendEmailVerification()) // メールアドレス確認
.then(() => alert('メールアドレス確認メールを送信しました。'))
.catch((error) => {
console.log("Something is wrong:", error.message);
});
}
login(email: string, password: string): void {
this.afAuth.auth
.signInWithEmailAndPassword(email, password)
.catch((error) => {
console.log("Something is wrong:", error.message);
});
this.router.navigate(["/home"]);
}
}
今回はFirebase Authenticationを利用してlogin,signup処理を実装します。
Firebase Authenticationとは
Firebase Authenticationは、Firebaseが提供するマルチプラットフォームログイン機能です。
自分で実装するとかなり面倒なユーザー管理機能ですが、Firebase Authenticationはその機能を無料で利用することができ、かつユーザーIDのデバイス間共有も容易にしてくれる優れものです。
今回はその中のメール&パスワード認証機能を利用します。
AngularFireAuthのメソッドであるcreateUserWithEmailAndPassword()と、その返り値にあるfirebase.Userが持つメソッドsendEmailVerification()を使って、アカウント作成用のメソッドを作成します。
ここで使用したAngularFireAuthのメソッドをまとめておきます。
メソッド名 | 機能 | 戻り値 |
---|---|---|
createUserWithEmailAndPassword(email, password) | メールアドレスとパスワードでアカウントを作成する | firebase.auth.UserCredential |
sendEmailVerification(actionCodeSettings) | メールアドレス有効化メールを送信する | void |
signInWithEmailAndPassword(email, password) | メールアドレスとパスワードでログインする | firebase.auth.UserCredential |
サインアップ画面の作成
サインアップコンポーネントの実装をします。
サインアップコンポーネントはログインコンポーネントと処理内容として変わりがないので、説明を省略します。
<form #signupForm="ngForm" (ngSubmit)="signup(signupForm)" class="signup-form">
<mat-form-field class="email-width">
<mat-label>Email</mat-label>
<input
type="email"
ngModel
name="email"
matInput
placeholder="半角英数字4字"
/>
</mat-form-field>
<mat-form-field class="pass-width">
<mat-label>Pass</mat-label>
<input
type="password"
ngModel
name="password"
matInput
placeholder="半角英数字6字以上"
/>
</mat-form-field>
<button mat-raised-button type="submit" color="primary">Signup</button>
</form>
import { Component, OnInit } from '@angular/core';
import { AuthService } from '../service/auth.service';
@Component({
selector: 'app-sign-up',
templateUrl: './sign-up.component.html',
styleUrls: ['./sign-up.component.css']
})
export class SignUpComponent implements OnInit {
constructor(private authService: AuthService) { }
ngOnInit(): void {
}
signup(signupForm): void {
this.authService.signUp(signupForm.value.email, signupForm.value.password);
}
}
.signup-form {
min-width: 150px;
max-width: 500px;
width: 100%;
margin: auto;
padding-top: 10%;
}
.login-label {
border-bottom: 2px solid #1161ed;
}
.sigunup-label {
color: rgba(255, 255, 255, 0.2);
}
h2 {
padding-left: 12px;
font-size: 22px;
text-transform: uppercase;
padding-bottom: 5px;
letter-spacing: 2px;
display: inline-block;
font-weight: 100;
}
h2:first-child {
padding-left: 0px;
}
.email-width {
width: 100%;
}
.pass-width {
width: 100%;
}
.passcheck-width {
width: 100%;
}
ホームコンポーネントの実装は今回想定していないため、ページ内の処理は特別記載しません。
これでローカルサーバを起動すると画像のような画面が表示されていれば完成です。
今回説明したのはAngularの基礎の一部です。
もし興味が湧きましたら、さらに調べAngularの知見を増やしてみてください!
Angularの基礎がまとまっている記事は以下です。
今日から始めるAngular
Angular+Firebase Authenticationで認証機能を導入する