Angular5 で Bootstrap4 ( beta ) を使ってみよう #serverless #adventcalendar

2017.12.19

Angular で Bootstrap を使う機会があったので手順を記録します。Angular は 2017年11月11日にバージョン5.0.0がでましたBootstrapは 2017年12月19日時点で v4.0.0-beta.2 が利用できます

利用ツール バージョン
Angular 5.1.1
Bootstrap 4.0.0-beta.2
angular-cli 1.6.1

Angular5 の導入

最新版の angular-cli を使ってプロジェクトを作ることで Angular5 が利用できます。

npm install -g @angular/cli@latest
ng new angular-bootstrap
cd angular-bootstrap
ng version

Angular CLI: 1.6.1
Node: 8.5.0
OS: darwin x64
Angular: 5.1.1
... animations, common, compiler, compiler-cli, core, forms
... http, language-service, platform-browser
... platform-browser-dynamic, router

@angular/cli: 1.6.1
@angular-devkit/build-optimizer: 0.0.36
@angular-devkit/core: 0.0.22
@angular-devkit/schematics: 0.0.42
@ngtools/json-schema: 1.1.0
@ngtools/webpack: 1.9.1
@schematics/angular: 0.1.11
@schematics/schematics: 0.0.11
typescript: 2.4.2
webpack: 3.10.0

Bootstrap4 の導入

Angular で Bootstrap を使う方法はいくつかありますが、今回は npm を使ってインストールした場合の導入方法を説明します。まずは npm でインストールしましょう。また、Bootstrap4 を使うにあたり必要になるスクリプトも一緒に導入します。

npm install --save bootstrap@4.0.0-beta.2
npm install --save jquery popper.js

Angular では、グローバルに読み込むCSSやスクリプトを .angular-cli.json で指定できます。Bootstrap公式サイトの導入を見ながら、必要なCSS、JSのパスを指定することで読み込ませます。

.angular-cli.json

{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "project": {
    "name": "angular-bootstrap"
  },
  "apps": [
    {
      "root": "src",
      "outDir": "dist",
      "assets": [
        "assets",
        "favicon.ico"
      ],
      "index": "index.html",
      "main": "main.ts",
      "polyfills": "polyfills.ts",
      "test": "test.ts",
      "tsconfig": "tsconfig.app.json",
      "testTsconfig": "tsconfig.spec.json",
      "prefix": "app",
      "styles": [
        "styles.css",
        "../node_modules/bootstrap/dist/css/bootstrap.min.css"
      ],
      "scripts": [
        "../node_modules/jquery/dist/jquery.slim.min.js",
        "../node_modules/popper.js/dist/umd/popper.min.js",
        "../node_modules/bootstrap/dist/js/bootstrap.min.js"
      ],
      "environmentSource": "environments/environment.ts",
      "environments": {
        "dev": "environments/environment.ts",
        "prod": "environments/environment.prod.ts"
      }
    }
  ],
  "e2e": {
    "protractor": {
      "config": "./protractor.conf.js"
    }
  },
  "lint": [
    {
      "project": "src/tsconfig.app.json",
      "exclude": "**/node_modules/**"
    },
    {
      "project": "src/tsconfig.spec.json",
      "exclude": "**/node_modules/**"
    },
    {
      "project": "e2e/tsconfig.e2e.json",
      "exclude": "**/node_modules/**"
    }
  ],
  "test": {
    "karma": {
      "config": "./karma.conf.js"
    }
  },
  "defaults": {
    "styleExt": "css",
    "component": {}
  }
}

これだけで使える状態になります。コンポーネントを作って Bootstrap の class を指定してみましょう。

ng g component card-ui

card-ui.component.html

<div class="card" style="width: 20rem;">
  <img class="card-img-top" src="/assets/img_318_180.svg" alt="Card image cap">
  <div class="card-body">
    <h4 class="card-title">Card title</h4>
    <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
    <a href="#" class="btn btn-primary">Go somewhere</a>
  </div>
</div>

app.component.html

<!--The content below is only a placeholder and can be replaced.-->
<app-card-ui></app-card-ui>
ng serve

その後、http://localhost:4200 にアクセスします。

blowser.png

Bootstrap4 の Card UI が表示されていることがわかります。新しく作成したコンポーネントにも、Bootstrap のCSSが効いていることがわかりました。ただ、気になるエラーが出ていますね。

http://localhost:4200/bootstrap.min.js.map
Failed to load resource: the server responded with a status of 404 (Not Found)

どうやらソースマップを読み込もうとして失敗しているようです。npm経由で取得した Bootstrap の Javascript は、(おそらくデバッグのための)ソースマップへのリンクが記載されいてます。npm モジュールとして require('bootstrap') のような形で使う場合は問題になりませんが、今回のようにピンポイントで Javascript のパスだけ指定しているような場合は関連する asset へのパスを見失うことがあります。解決策として、 .angular-cli.json にソースマップの場所を教えてやればOKです。jquery, popper.js も同様でしたので同じようにソースマップを追加しました。

.angular-cli.json

...前略...
{
  ...
  "apps": [
    {
      "root": "src",
      "outDir": "dist",
      "assets": [
        "assets",
        "favicon.ico",
        { "glob": "jquery.slim.min.js.map", "input": "../node_modules/jquery/dist/", "output": "./" },
        { "glob": "popper.min.js.map", "input": "../node_modules/popper.js/dist/umd/", "output": "./" },
        { "glob": "bootstrap.min.js.map", "input": "../node_modules/bootstrap/dist/js/", "output": "./" }
      ],
      ...
    }
  ]
}
...後略...

これで、デバッグコンソールでみたときにエラーはでなくなりました。ただしこの方法は、おそらく本番環境用ビルド ng build --prod でビルドした場合も asset ファイルとして成果物に含まれることになると思います。やや成果物を肥大化させてしまうことになります。

Bootstrap4 の Card UI を試す

このタイプのUI、とくにECサイトや、最近ではニュースサイトでも見かけますね。Bootstrap で手軽に実装できるようになったのは嬉しいポイントです。いくつか試してみます。

Card groups

<div class="container-fluid">
  <div class="card-group">
    <div class="card">
      <img class="card-img-top" src="/assets/019Yamasha1218_TP_V.jpg" alt="Card image cap">
      <div class="card-body">
        <h4 class="card-title">蓼科山山頂から望む厳冬期八ヶ岳連峰</h4>
        <p class="card-text">山頂はとても寒いです。2500メートルを超える高さを誇り、頂上からの長めは絶景です。</p>
        <p class="card-text">
          <small class="text-muted">Last updated 3 mins ago</small>
        </p>
      </div>
    </div>
    <div class="card">
      <img class="card-img-top" src="/assets/gunma-IMG_6125_TP_V.jpg" alt="Card image cap">
      <div class="card-body">
        <h4 class="card-title">毛無峠から破風岳のルート</h4>
        <p class="card-text">近辺での硫黄採掘が始まり、精錬時に発生する亜硫酸ガスによって裸山になってしまいました。鉱山跡は観光スポットにもなっています。</p>
        <p class="card-text">
          <small class="text-muted">Last updated 5 days ago</small>
        </p>
      </div>
    </div>
    <div class="card">
      <img class="card-img-top" src="/assets/1711163AMEMAN005_TP_V.jpg" alt="Card image cap">
      <div class="card-body">
        <h4 class="card-title">八幡平の紅葉渓谷</h4>
        <p class="card-text">岩手県の紅葉名所。松川温泉もあり特に秋は絶好の観光スポットです。</p>
        <p class="card-text">
          <small class="text-muted">Last updated 10 days ago</small>
        </p>
      </div>
    </div>
  </div>
</div>

card-group.png

Image overlays

<div class="card bg-dark text-white">
  <img class="card-img" src="/assets/gunma-IMG_6125_TP_V.jpg" alt="Card image">
  <div class="card-img-overlay">
    <h4 class="card-title">毛無峠から破風岳のルート</h4>
    <p class="card-text">近辺での硫黄採掘が始まり、精錬時に発生する亜硫酸ガスによって裸山になってしまいました。鉱山跡は観光スポットにもなっています。</p>
  </div>
</div>

image_overlays.png

Header and footer

<div class="card text-center">
  <div class="card-header">
    ピザ&ワインからのお知らせ
  </div>
  <div class="card-body">
    <h4 class="card-title">白ワインのセットご注文で5%OFF!</h4>
    <img class="card-img" src="/assets/tachiaraiIMGL4852_TP_V.jpg" alt="Card image">
    <p class="card-text">週末のパーティにいかがですか?</p>
    <a href="#" class="btn btn-primary">購入ページへ行く</a>
  </div>
  <div class="card-footer text-muted">
    2 days ago
  </div>
</div>

header_footer.png

まとめ

Angular で Bootstrap を利用する一例を紹介しました。Angular の考え方としてコンポーネント指向がベースとなっており、コンポーネントを組み合わせて画面を構成していくことになると思います。Bootstrap のように、全コンポーネントでCSSを利用したいといったシーンで、 .angular-cli.json への設定を追加することがわかれば、いろいろと応用できますね。Bootstrap は新しく追加された Card UI を始め、コンポーネントの見た目を手早く整えてくれるのでSPAを作る際などはかなり重宝することになるでしょう。Bootstrap を利用する際の参考になれば幸いです。

参考