この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
どうも!大阪オフィスの西村祐二です。
本番環境、STG環境など複数環境で開発することは多いかと思います。
作業する環境を間違えないためにUIのテーマを環境ごとに変更したいということがあり、今回はAngular Materialのテーマを環境ごとに変更してみたいと思います。
やってみる
環境
Angular CLI: 8.3.23
Node: 12.13.0
OS: darwin x64
Angular: 8.2.14
... animations, common, compiler, compiler-cli, core, forms
... language-service, platform-browser, platform-browser-dynamic
... router
Package Version
-----------------------------------------------------------
@angular-devkit/architect 0.803.23
@angular-devkit/build-angular 0.803.23
@angular-devkit/build-optimizer 0.803.23
@angular-devkit/build-webpack 0.803.23
@angular-devkit/core 8.3.23
@angular-devkit/schematics 8.3.23
@angular/cdk 8.2.3
@angular/cli 8.3.23
@angular/material 8.2.3
@ngtools/webpack 8.3.23
@schematics/angular 8.3.23
@schematics/update 0.803.23
rxjs 6.4.0
typescript 3.5.3
webpack 4.39.2
セットアップ
Angular CLIを使ってアプリケーションの雛形を作成します。
$ ng new demo-theme --style=scss --routing
$ cd demo-theme
Angular Materialをインストールします。
$ ng add @angular/material
? Choose a prebuilt theme name, or "custom" for a custom theme: Indigo/Pink [ Preview: https://material.angular.io?
theme=indigo-pink ]
? Set up HammerJS for gesture recognition? Yes
? Set up browser animations for Angular Material? Yes
Angular Materialのコンポーネントを作成します。
サイドナビを作成
$ ng generate @angular/material:nav nav
ダッシュボードを作成
$ ng generate @angular/material:dashboard dashboard
コンポーネントを組み合わせて画面を作ります。
src/app.component.html
<app-nav>
<app-dashboard></app-dashboard>
</app-nav>
src/app/nav/nav.component.html
<mat-sidenav-container class="sidenav-container">
<mat-sidenav #drawer class="sidenav" fixedInViewport
[attr.role]="(isHandset$ | async) ? 'dialog' : 'navigation'"
[mode]="(isHandset$ | async) ? 'over' : 'side'"
[opened]="(isHandset$ | async) === false">
<mat-toolbar>Menu</mat-toolbar>
<mat-nav-list>
<a mat-list-item href="#">Link 1</a>
<a mat-list-item href="#">Link 2</a>
<a mat-list-item href="#">Link 3</a>
</mat-nav-list>
</mat-sidenav>
<mat-sidenav-content>
<mat-toolbar color="primary">
<button
type="button"
aria-label="Toggle sidenav"
mat-icon-button
(click)="drawer.toggle()"
*ngIf="isHandset$ | async">
<mat-icon aria-label="Side nav toggle icon">menu</mat-icon>
</button>
<span>demo-theme</span>
</mat-toolbar>
<!-- Add Content Here -->
<ng-content></ng-content>
</mat-sidenav-content>
</mat-sidenav-container>
ローカル実行した画面を確認します。下記画面が出力されればOKです。
$ ng serve
設定
angular.json
にstylePreprocessorOptions
を設定することで、ビルドする前にSCSSのインポートするファイルを差し替えることができます。
このオプションを利用して、Angular Materialのテーマの差し替えを実現します。
参考サイトはこちらです。
angular.json
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"demo-theme": {
"projectType": "application",
"schematics": {
"@schematics/angular:component": {
"style": "scss"
}
},
"root": "",
"sourceRoot": "src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/demo-theme",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.app.json",
"aot": false,
"stylePreprocessorOptions": {
"includePaths": ["src/theme/local/"]
},
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"src/styles.scss"
],
"scripts": []
},
"configurations": {
"production": {
"stylePreprocessorOptions": {
"includePaths": ["src/theme/prod/"]
},
"fileReplacements": [{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"extractCss": true,
"namedChunks": false,
"aot": true,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"budgets": [{
"type": "initial",
"maximumWarning": "2mb",
"maximumError": "5mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "6kb",
"maximumError": "10kb"
}
]
}
}
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "demo-theme:build"
},
"configurations": {
"production": {
"browserTarget": "demo-theme:build:production"
}
}
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "demo-theme:build"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "src/test.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.spec.json",
"karmaConfig": "karma.conf.js",
"stylePreprocessorOptions": {
"includePaths": ["src/theme/local/"]
},
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"src/styles.scss"
],
"scripts": []
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"stylePreprocessorOptions": {
"includePaths": ["src/theme/local/"]
},
"options": {
"tsConfig": [
"tsconfig.app.json",
"tsconfig.spec.json",
"e2e/tsconfig.json"
],
"exclude": [
"**/node_modules/**"
]
}
},
"e2e": {
"builder": "@angular-devkit/build-angular:protractor",
"stylePreprocessorOptions": {
"includePaths": ["src/theme/local/"]
},
"options": {
"protractorConfig": "e2e/protractor.conf.js",
"devServerTarget": "demo-theme:serve"
},
"configurations": {
"production": {
"devServerTarget": "demo-theme:serve:production"
}
}
}
}
}
},
"defaultProject": "demo-theme"
}
ここではテーマのファイルをインポートする設定を追加します。
この設定はtheme.scss
ファイルをインポートする設定を意味します。ビルド時に上記で設定したincludePaths
の部分が置き換わるのでファイル名のみ設定します。
src/styles.scss
/* You can add global styles to this file, and also import other style files */
html,
body {
height: 100%;
}
body {
margin: 0;
font-family: Roboto, "Helvetica Neue", sans-serif;
}
@import 'theme';
本番環境用のテーマファイルを作成します。オレンジ系のテーマを設定しています。
src/theme/prod/theme.scss
// テーマ操作関数をライブラリからインポート
@import '~@angular/material/theming';
// Angular Material の共通スタイルをインクルード
@include mat-core();
// 色定義: オプションは hue カラーパレットで色コード指定, 参照: https://material.io/design/color/ and https://material.io/tools/color/
$prod-app-primary: mat-palette($mat-deep-orange);
$prod-app-accent: mat-palette($mat-pink, 500, 900, A100);
$prod-app-warn: mat-palette($mat-blue-grey);
// テーマとして色定義をまとめる
$prod-app-theme: mat-light-theme($prod-app-primary, $prod-app-accent, $prod-app-warn);
// カスタムテーマを適用
@include angular-material-theme($prod-app-theme);
ローカル実行時に適用するテーマを設定しています。既存のindigo-pink
を設定しています。
src/theme/local/theme.scss
@import '@angular/material/prebuilt-themes/indigo-pink.css';
フォルダ構成は下記のようになっています。
動作確認
local実行したときの画面とprod用にビルドしたときの画面を確認してみます。
local実行した際の画面は以前と変わらずの青いヘッダーの画面が表示されます。
$ ng serve
prod用にビルドして画面を確認してみます。
$ ng serve --prod
すると、下記のようにオレンジ系のヘッダーになってテーマが変更されて表示されます。やりましたね。
さいごに
Angular Materialのテーマを環境ごとに変更する方法を紹介しました。
今回の方法を使えば、Angular Material以外でも利用できるのではないでしょうか。
最初はenvironments
を使えば簡単にできるだろうと思っていましたが、思いのほかうまくいかずハマってしまいました。
誰かの参考になれば幸いです。