年末ですね。
Table of Contents
今年の汚れ今年のうちに。
ということで、長らく超技術負債となってしまっていたこのブログをなんとかします。
このブログは、Gatsby.jsをGitHub ActionsでビルドしてNetlifyにデプロイして作られているのですが、CSSフレームワークはBootstrap v3.5.1を使って作られていました。
さすがに2019年にサポート対象外となっているフレームワークを使い続けるのはどうかと思っておりましたが、別に動いているしいいかと思い放置していました。
が、しかしさすがに今年の汚れ今年のうちにと思い立ち、思い切って脱Bootstrapを考え、TailwindとかdaisyUIとか、tailwind-bootstrap-grid とか色々試した結果、めんどくさくなってBootstrap v5に移行することにしました。
問題点
BootStrap v3で動いていたこのブログのソースを見てもらえばわかるのですが、Gatsby.jsで動いているブログなのに、Bootstrapは <script> タグを使ってCDNライクに使ってました。(CDN配信ではありません。ここらへんも闇です。)
Gatsby.jsではHTML.jsというファイルを作ることでHTMLファイルのビルド時に任意のタグを埋め込むことができます。
それを悪用して次のようにBootstrapのCSSを <link> タグで、jQueryとBootstrapのJSを <script> タグでそれぞれ配信されたものを使っている形となっておりました。
import React from 'react';
const HTML = ({
htmlAttributes,
headComponents,
bodyAttributes,
preBodyComponents,
body,
postBodyComponents,
}) => (
<html {...htmlAttributes} lang="ja">
<head>
<link
rel="stylesheet"
href="/vendors/css/bootstrap.min.custom.css" // Bootstrap cssを利用
/>
{headComponents}
</head>
<body {...bodyAttributes}>
{preBodyComponents}
<div
key="body"
id="___gatsby"
dangerouslySetInnerHTML={{ __html: body }}
/>
{postBodyComponents}
<script src="/vendors/js/jquery-3.5.1.slim.custom.min.js" defer /> // Bootstrapで利用するjQueryを利用
<script src="/vendors/js/bootstrap.custom.min.js" defer /> // Bootstrap JSを利用
</body>
</html>
);
export default HTML;
これでは下記の問題が発生する形になり大変問題に感じてました。
- npmの管理外になり、パッケージの更新ができない(もはややる気がなかった)
- Bootstrap特有の超でかいCSSをheadでlinkさせてしまっていることでパフォーマンスに悪影響
- deferで読み込むようにしているがBootstrapJS, JQueryも同様に問題
- 上記のパフォーマンス問題を解決するために、CSS, JS, JQueryをゴリゴリに改造(Purge)したものをホスティングし、それを配信し使っていた。(もはや...)
ゴリゴリに改造したCSSとかが正直サンクコストになっており、かつブログのレイアウトを変えたくない気持ちもあったため長らく放置されることになったのです。
余談ですが、サンクコストって最近言葉知りました。
いざ直す旅へ
ということで早速直していきましょう。冒頭でもお話しましたが、やはり最近のトレンド的にTailwindで行きたいですよね!!!!!! (行きたいです〜)
というわけでTailwindを利用する決断をするのですがやってみて次のような悩みが出てきました。
膨大に作ってしまったコンポーネントをUtility classにするのだるい
はい...ぶっちゃけそういった悩みが出ました。困りましたね...。なんとかならないものでしょうか...。
探していたら、daisyUIというBootstrapライクなUtility classがあったので使ってみましたが、自分の環境だとほぼ置き換えなしでできそうなのがボタンくらいでした。
加えてめんどくさいのはこのブログのGridシステムです。ある意味Bootstrapから抜けることのできない一番の理由がGridかもしれません。いや...ちゃんと作り直せばいいだけなんですけどね。
困り果てているとtailwind-bootstrap-gridというまたもや便利そうなものが出てくるじゃあありませんか。しかしこれも導入を断念しました。
理由はこのブログのカスタムCSSを管理しているSASSとの相性が悪いことで、ビルドすると次のようなエラーが出てきてしまうことです。
ModuleBuildError: Module build failed (from ./node_modules/postcss-loader/dist/cjs.js): TypeError: config is not a function
node-sassやめてPostCSSにすれば直りそうですが、年末にCSSをいじりまくるときっと辛いと思うので断念することにしました。
そもそも問題点を考える
そもそもの話ですが、Tailwind化が目的ではなくBootstrap v3をなんとかしたいことが問題でしたので、いっそのことBootstrapを問題ないバージョンまでバージョンアップすればいいと気が付きました。
そうと決まれば、Bootstrap v5からはjQueryを使わなくてよくなっていたのでいっそのことv3 => v5のビックバンリライトを実施することにしました。
やったこと
まず、HTML.jsでの <script> タグでのBootstrap利用をやめました。
Gatsby.jsではgatsby-browser.jsを使って、ブラウザ側で利用したいモジュールを設定できますのでこちらにCSSとJSをimportするようにします。
import './src/styles/global.scss';
import { Dropdown } from 'bootstrap/dist/js/bootstrap'; // 必要なJSモジュールはDropdownなので
// global.scssには @import "~bootstrap/scss/bootstrap.scss"; という形でBootstrapのCSSをimportする
これだけでうまくいくかなーと思いましたが、さすがに甘くありませんでした。ちょっとコードの方も手直しします。
Dropdown menuの変更
Dropdown menuのtoggle buttonの実装方法がちょっとだけ変わってました。 data-toggleとdata-targetがそれぞれdata-bs-toggle、data-bs-targetに変わっただけです。
// before
<button
className="navbar-toggler"
type="button"
data-toggle="collapse"
aria-label="navbar-toggler"
data-target="#navbarSupportedContent"
>
// after
<button
className="navbar-toggler"
type="button"
data-bs-toggle="collapse"
aria-label="navbar-toggler"
data-bs-target="#navbarSupportedContent"
>
Column orderの制限
Columnの順番を制御できるOrderについて今までは無邪気にorder-10とかできたのですが、order-5までの制限となっておりました。なのでこちらも修正します。
// before
<Sidebar />
<div className="col-xl-7 col-lg-6 col-md-12 col-sm-12 order-10 content">
<Content post={html} />
</div>
// after
<Sidebar />
<div className="col-xl-7 col-lg-6 col-md-12 col-sm-12 order-2 content">
<Content post={html} />
</div>
デフォルトでaタグにtext-decoration: underlineがつく
といういらない変更が入っていたので、こちらはglobal.sCSSでnoneを上書きします。
a {
text-decoration: none;
}
デフォルトでscroll-behavior smoothがつく
というおせっかいが入っているのでこちらもglobal.sCSSで無効化します。別にあってもいいかなとも思ったのですが、画像のLazy loadingとの相性が最悪で遷移先のページでうまく画像を読み込んでくれなかったので無効化します。
:root {
scroll-behavior: auto;
}
あとは細かいレイアウト崩れをちょこちょこ直して完成です。
Purgeの野望
さてこれでBootstrap v5化はできました。Tailwindを使おうと思った理由はPurgeだったので、Purgeしてしまいます。
Gatsby.jsではCSSのPurgeにgatsby-plugin-purgeCSSが利用できます。今回はglobal.sCSSにBootstrapのCSSをimportしているのでgatsby-config.jsに次のように設定してあげることで利用してないCSS RuleをPurgeしてくれます。
{
resolve: `gatsby-plugin-purgecss`,
options: {
printRejected: true,
develop: true,
purgeOnly : ['src/styles/global.scss'], // global.scssを指定
},
},
完成
というわけで完成しました。
今あなたが見ているブログがまさにBootstrap v5で動いているブログなわけです。
ちなみに、Purgeの効果あってかわかりませんが、Lighthouseのパフォーマンススコアは次のとおりでした。
みなさまこのブログは なんでTypeScriptでリライトしないのか? という疑問があると思うのですが、それもこのBootstrap問題がちょっと絡んでいるので、この際頑張ってTypeScript化しようかなと思ってます。
最後に
本年もお世話になりました。来年もよろしくおねがいします!!!