Webpackその他

メモ記事とはいえなかなか書いてる時間がとれず一月以上の間が空いてしまった。FastAPIによるバックエンド実装からTypescriptとSASSによるフロントエンド実装の勉強に入った所、WebAssemblyとその有力言語のRustに興味が写ってしまい、そのあたりを勉強しながらフロントエンドに組み込む技術を調査していたら、Webpackという技術に突き当たった。

WebAssemblyとRustに関しては別の機会に書くとして、今回はWebpack。いままで何度か単語程度に見かけはしたが、なんとなくお腹一杯感でスルーしていたが、必要に応じて調べてみると目からウロコ的な技術だった。

従来の静的コンテンツ(ブラウザ側で処理をする所謂フロントエンド)は、HTMLベースでスタールシート(CSS)やJavascriptを必要に応じて読み込む形式だったが、Webpack化することで、大まかには一つのJavascriptにまとめられる。

例えば下記のようなindex.htmlでは

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <!-- 省略 -->
  <style type="text/css">
    @import "/static/css/bootstrap-custom.css";
  </style>
  <script type="module">
    import { Alert, Button, Carousel, Collapse, Dropdown, Modal, Offcanvas, Popover, ScrollSpy, Tab, Toast, Tooltip } from "/static/js/bootstrap.esm.js"
  </script>
</head>
<body class="base">
  <script type="module">
    import {init} from "/static/js/app.js"
    window.addEventListener("load", init());
  </script>
</body>
</html>

6行目〜でbootstrapのカスタムスタイルシート(これは別途SASSでコンパイルしている)を読み込んで、その下9行目〜でbootstrap用のスクリプトをモジュールとして読み込んでいる。Bodyタグを読み込んだあとで14行目〜でシングルページアプリケーション用スクリプトapp.jsを読み込んでページロード完了後にinitを実行(window.addEventListener)。app.jsもTypescriptのソースから別途コンパイルしておりアプリケーションの規模によっては多くのモジュールに分かれてロードされる。

こういった構成のものが、Webpack化することで下記のように出来る

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <!-- 省略 -->
    <script src="/static/dist/main.js"></script>
</head>
<body class="base">
</body>
</html>

6行目のmain.js を読み込むだけとなる。main.jsはWebpackによってコンパイルされたjavascriptで読み込むべきリソースが全てパック化された生成物となる。ソースファイルは一般にindex.jsとされ、下記のような内容となる

import '../scss/bootstrap-custom.scss';
import 'bootstrap/dist/js/bootstrap.esm.js';

import {init, build} from '../ts/app';

init();

window.addEventListener("load", () => {
  build();
});

一行目でbootstrapのカスタムスタイルシートを読み込むが、ここではscssのソースファイルを直接インポートして、WebpackのプラグインでSassコンパイラを起動する。生成したスタイルシートをインポートすると呼び出し側のHTMLのHEADタグ内にSTYLEタグを生成して直接コーディングするため、CSSファイルは生成されない。

2行目はbootstrap用のスクリプトをインポート。4行目でシングルページアプリケーションスクリプトを読み込むが、これもTypescriptのソースを直接していして内部でコンパイラを起動している。また、従来構成と違って読み込んだ時点ではBODYタグが生成されていないため、DOM関連の初期化があると失敗する。DOM関連の初期化はloadイベントをトリガとして始めるよう工夫が必要。

とりあえず、Webpackを導入するとこうなるというだけのメモで、Webpackの具体的な設定などはまた別の機会に。

BootstrapとかCSSの事からSASSにたどり着くまで

djangoを通じてWEBアプリの勉強中。ポータルサイトのdjangoアプリで一通り遊び尽くしたところで、今度はフロント側の見た目やスクリプトに手を付け始めた。

今まではサイトの情報をそのままコピペするようにサイトを作ってきたので、その辺のメカニズムについて勉強を始めた所。今までHTMLとかCSSは必要に応じて編集してきたが、知識は初期のHTML3?あたりで止っているので、そのあたりも昨今のHTML5まで追いつけたら良いなぁ位には考えている。

BootstrapでレスポンシブルなWEBサイトを・・・と分かったような分かってないような事を書いてみたが、使っていくと結構便利で、あんまり考えなくても一応ちゃんとしたサイトが作ることが出来る(本サイトのポータルもdjango+Bootstrap)。しかし、いろんなサイトの情報をつまみ食いしながらゴチャゴチャやってきたら、非常にごちゃごちゃのHTMLソースが出来上がってしまった。

例えば、下記カード型サイドメニューの一部だが、クラスタグのカタマリのようになってしまう。

    <div class="container-fluid">
      <div class="row justify-content-md-center">
        <div class="col-md-2 px-1">
          <!-- 右側サイドバー -->
          <div class="card px-0 mx-0 my-2">
            <div class="card-body">
              <h4 class="card-title btn rounded-pill btn-outline-dark">Side Menu</h4>
                <ul class="list-group list-group-flush">
                   <li class="list-group-item">
   ・・・・・・

そもそも、HTMLとCSSに分かれたのって、文書と見た目の装飾を分けるのが目的で、HTMLの新しくなるにつれて、ボールドとかイタリックとか文字サイズの直接変更みたいなのは削除されてきたように思うのだが、昨日今日勉強し始めた素人的な感想だが、一応昔からHTMLには接してきてその進化も遠巻きに見てきたので、HTMLはあくまでも文書とその構造を定義するもので、見た目や表現はCSSの仕事という認識。

Bootstrapは確かに便利でいろんなパーツが揃っているが、こうもクラスタグで文書の見た目についての情報をベタベタ貼付けていると、何か本末転倒のような気がするのもあるかなーと思う。

確かに汎用性があるのは良いのだが、もっとCSSの方でスッキリ纏められないものかと、調べてみると、世の中考える人は多いもので、SASSというツールに辿りついた。これはCSSのプリプロセッサのようなもので、CSSだけでは手が届かなかった構造化したスタイルシートを定義して、CSSにコンパイルするツール。

これを使えば例えば 「card-bodyクラスのブロックに含まれるh4ヘッダはこのスタイル」と決められる。またdivを使用せずに「cardクラスのブロックに含まれるsectionというブロックはcard-bodyのスタイルを持つ」みたいな感じでdivを多用せずに意味のあるブロックで文書を構成することが出来る。

.cardclass {
  @extend .card, .px-0, .mx-0, .my-2;
  section {
    @extend .card-body;
    h4 {
      @extend .card-title, .btn, .rounded-pill, .btn-outline-dark;
    }
    ul {
      @extend .list-group, .list-group-flush;
      li {
        @extend .list-group-item;
      }
    }
  }
}

と定義出来、上のHTMLも

    <div class="container-fluid">
      <div class="row justify-content-md-center">
        <div class="col-md-2 px-1">
          <!-- 右側サイドバー -->
          <div class="cardclass">
            <section>
              <h4>Side Menu</h4>
                <ul>
                  <li>
   ・・・・・・

のように長々としたクラスタグを書かずにスッキリさせることが出来る。

久々にこの手の勉強を始めて間もないので、こういう考え方で良いのかどうか分からないが、少なくとも文書の構造を定義するHTMLの考え方はこうじゃないかなと、思う所。あとCSSファイルのサイズの肥大化でページの読み込み速度の話もあるかも知れないが、とりあえずは今はそっちは考えないとする。

と、まぁそんな感じで、自サイトを使用して色々試しているが、今日もブラウザキャッシュの罠にハマって半日ほど無駄にしてしまった。。テスト環境と本番環境で同じファイルなのに本番環境のみ一部のクラスタグの部分が反映されないとか・・・これもキャッシュだったとは。とりあえず難しいことは考えずにこまめにキャッシュクリアが大事です。
本番環境にはSassコンパイラ入れてなかったので、いろいろ大変なことになっていた。