Angular Materialのテーマを環境ごとに変えてみる
どうも!大阪オフィスの西村祐二です。
本番環境、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
コンポーネントを組み合わせて画面を作ります。
<app-nav> <app-dashboard></app-dashboard> </app-nav>
<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のテーマの差し替えを実現します。
参考サイトはこちらです。
{ "$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
の部分が置き換わるのでファイル名のみ設定します。
/* 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';
本番環境用のテーマファイルを作成します。オレンジ系のテーマを設定しています。
// テーマ操作関数をライブラリからインポート @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
を設定しています。
@import '@angular/material/prebuilt-themes/indigo-pink.css';
フォルダ構成は下記のようになっています。
動作確認
local実行したときの画面とprod用にビルドしたときの画面を確認してみます。
local実行した際の画面は以前と変わらずの青いヘッダーの画面が表示されます。
$ ng serve
prod用にビルドして画面を確認してみます。
$ ng serve --prod
すると、下記のようにオレンジ系のヘッダーになってテーマが変更されて表示されます。やりましたね。
さいごに
Angular Materialのテーマを環境ごとに変更する方法を紹介しました。
今回の方法を使えば、Angular Material以外でも利用できるのではないでしょうか。
最初はenvironments
を使えば簡単にできるだろうと思っていましたが、思いのほかうまくいかずハマってしまいました。
誰かの参考になれば幸いです。