Pythonしか触ったことのなかった大学生がReact(Gatsby.js)でWeb開発した話


作ったLP(ランディングページ)

SynQ Remote LP https://www.synq-platform.com/

大学1年の10月から福岡市内のITベンチャーでインターンをしており、そこで自社プロダクトのLP(ランディングページ)開発プロジェクトを任せてもらっています。
今月でインターン開始1年になるので、記念に(?)LP開発までの流れを書いていきたいと思います。

LPを作るまでの自分のスキルについて

インターン開始前は授業でPythonを触ったのみ

インターンを始める前、大学1年前期の講義で「プログラミング演習」という必修科目を取っていました。これは関数を定義するくらいまでのPythonの基礎を学ぶ科目で、昔からパソコンをいじるのが好きだった自分はとても面白い講義だなと思い、これをきっかけにプログラミングを学びつつバイト代わりにもなるインターンを探すことを決意します。

インターン先を見つけ、プロジェクトに配属される

2ヶ月ほど期間を要しましたが、ようやくWantedlyで自分に合ったインターン先を見つけることができました。早速、鉄板加工工場のオートメーション化プロジェクトに配属され、主にPythonベースのDjango(バックエンド)の開発を任せてもらいます。初めの方はわからないことだらけでしたが、3, 4ヶ月経つと一定の成果をあげることができるようになっていきました。

Python以外に手を出してみたくなる

すると、そろそろPython以外の言語にも手を出してみたくなりました。インターン先CTOに相談したところ、ReactでQiitaトップページを模写するという課題をいただきました。2月に合宿免許に行くことになりインターンできない状況にあったので、その期間をReact勉強期間に充てたのち、Qiita模写を1週間くらいで開発しました。(https://github.com/horri1520/qiita-toppage/)

LP開発プロジェクトを任せてもらうことに

Qiita模写を通してフロントエンド楽しい!!!もっといろいろ作りたい!!!となっていた自分を見て、前述のCTOがLP開発プロジェクトを任せてくれることになりました。当時僕はフロントエンドの技術スタックについて全然詳しくなかったので、CTOがGatsbyなるものを提案してくれました。ここから、LP開発についての詳細を書いていきたいと思います。

技術スタックについて

フレームワークはGatsby.js

Reactベースの静的サイトジェネレータ、「Gatsby.js」を採用しています。僕のアイデアではないですが(笑
しかし開発を通して、Gatsbyを使ったことによる恩恵を十分に享受することができました。Gatsby製のサイトはなんと言ってもパフォーマンスに長けています。爆速です。
爆速になるカギは静的サイトホスティングサービス「Netlify」と、サイト内の画像を最適化してくれるGatsby専用プラグインgatsby-imageにあると思っています。

Netlifyとgatsby-image

Netlifyはサーバーレスで静的サイトをビルド・ホスティングできるサービスです。主な特徴は、GitHubへのpushをトリガーにサイトのビルド・デプロイが走ることと、その際行われるサーバーサイドレンダリングです。(後者は諸刃の剣な側面があって、、、詳しくは後述します。)
gatsby-imagelazy-loadやサイズ最適化など、画像を軽量化して扱うための機能がひとまとめになっているプラグインです。詳しいことは割愛しますが、GraphQLのクエリを叩けば軽量化された画像ファイルを生成してくれます。
Netlifyとgatsby-imageを組み合わせるとどういうことが起こるのかについて説明します。まず、GitHub上のコードから静的サイトのビルドが走ります。サイト上の各要素はこの段階で描画(レンダリング)され、1枚のページビューにまとめられます。その際サイト上の画像はぼやけた、モザイクに近いようなものとしていったん生成されます。
そしてそのページにアクセスすると、最初はモザイクに近い画像が表示されますが、ページを読み進めていくにつれ、高解像度の画像の読み込みが走り(lazy-load)順次置き換えられていきます。一連の流れを視覚化すると、このような挙動になります。

レンダリングがすでに行われているというだけでも十分高速なのですが、さらに重たい原因になる画像まで軽量化してくれるところがGatsbyならではの強みです。

技術スタックまとめ

Gatsby.jsで書いたコード
 ↓push
GitHub
 ↓pushをトリガーにビルド&デプロイ
Netlify

実装してみて

とある日、いつものようにビルドを走らせると…

ページがぐっちゃぐちゃになっていた。。。

めっちゃくちゃ萎えました。このスクショ以外にも様々な見た目で崩壊(画像など各要素は表示されるけど位置がはちゃめちゃとか)していましたが、萎えたのでこのスクショしか撮れていないほどです。やはり自分が開発したサイトがバリエーション豊かに崩壊しているのを見るのはへこみますね。しかし、そうも言ってられないので崩壊原因の調査を始めることにしました。

原因調査

いろいろ調べているうちに、同じ現象に悩まされている方々が執筆したいくつかのブログ記事やフォーラムにたどり着きました。おそらく、導入していたMaterial UIのmakeStylesとレスポンシブ対応プラグインのreact-responsiveがサーバーサイドレンダリングに対応していないことが全ての原因であるとのことです。しかし、どのページにも有効な解決策は示されておらず、GitHubのissueに至っては解決していないのに閉じられていました。絶望です。

解決策を求めて

いったん状況を整理するために、コードを書き換えてみたりコメントアウトしてみたりしました。その結果、

  • react-responsiveは完全にアウト。発生条件は定かではないが、動作しない箇所が出てきてしまう。
  • makeStylesはindexページのみの適用だと動作するが、他のページに適用するとそのページのCSSが崩壊してしまう。404ページに至っては、404ページ自体もindexページも共に崩壊してしまった。
  • これらの現象はlocalhostで立てた開発用サーバーでは発生せず、ビルドしてみて初めて異変に気づくのでそもそも気づくのも遅れる上デバッグもしづらい。

という結果が得られました。
もうGatsbyやめようかな…という考えも一瞬頭をよぎりましたが、上述したGatsbyのメリットが大きすぎるため、Gatsbyでも正常に動作するプラグインを探し、それに置き換えることにしました。

公式ドキュメントを読むことの重要性

ユーザーで困っている人々がいるのなら、公式はそれに対しどのような見解を持っているのだろうかと気になり、ここでいったんGatsby公式のドキュメントに立ち返ってみることにしました。すると、GatsbyでのCSSスタイリングをどうするのかについてのページにたどり着き、(https://www.gatsbyjs.com/tutorial/part-two/) styled-componentsが推奨されているということを知りました。(逆にmakeStylesが非推奨とはどこにも書かれていませんでしたが!笑)

このことで、

  • 公式ドキュメントをきっちり読むこと
  • サーバーサイドレンダリング下において、特に画面描画周りのプラグインとは相性があるので事前に対応状況を確認するべきであるということ

この2点の重要性を再認識できました。また、レスポンシブ対応プラグインについては、同様にGatsby公式プラグインライブラリ(https://www.gatsbyjs.com/plugins/) からgatsby-plugin-breakpointsという対応プラグインを見つけ出すことができました。

一連の流れについて振り返ると、発見した時は慌てふためきましたが、今となっては
得られた知見だけでなく問題について調査し、解決に向けて試行錯誤していくプロセスにもとても意義があったと思っています。今後新たな技術に触れる際、何かトラブルが起きてももう怖くなさそうです。

続いて、gatsby-plugin-breakpointsが便利だったので詳しく紹介していきます。

gatsby-plugin-breakpointsの使い方

詳しくはドキュメント(https://www.gatsbyjs.com/plugins/gatsby-plugin-breakpoints/) を参照していただきたいのですが、gatsby-config.js内にbreakPointsを定義すれば各コンポーネントで手軽に使えます。

僕は下のようにbreakPointsを定義しました。


    const breakPoints = {
      smartphone: "(max-width: 420px)",
      mobileWide: "(min-width: 421px)",
      wxga: "(min-width: 1280px)",
      mobile: "(max-width: 1023px)",
      pc: "(min-width: 1024px)",
      portrait: '(orientation: portrait)',
    }

そして、使用したいファイル上で


    import { useBreakpoint } from "gatsby-plugin-breakpoints"

    const Hoge = () => {
        const breakPoints = useBreakpoint()

        return (
            <>
                {breakPoints.pc
                    ?
                        // PC用のコンポーネント
                    :
                        null
                }
                {breakPoints.mobile
                    ?
                        // モバイル用のコンポーネント
                    :
                        null
                }
            </>
        )
    }

のように、閲覧しているデバイスの画面サイズに応じてreturnするコンポーネントを切り替えることができます。
breakPointsの中には、

    { pc: true, mobile: false, wxga: true, ... }

このようにconfigで定義したbreakPointsを満たしているかどうかがboolean値で格納されているので、画面サイズに応じた条件処理を自由度高く書くことができました。

その結果、CSSのメディアクエリと遜色ないレスポンシブ対応ページをJavaScriptだけで実装することができました。JavaScriptだけでの実装にこだわってよかったなと思っています。

Gatsby.jsでのWeb開発まとめ

  • CSS in JSプラグインはstyled-componentsgatsby-plugin-styled-componentsとセットで使う
  • レスポンシブ対応プラグインは専用のgatsby-plugin-breakpointsを使う
  • Gatsbyのサーバーサイドレンダリングに非対応のプラグインはまともに動作しないので注意!事前によく調べるべき

LPの開発を終えて

Gatsby.jsはサーバーサイドレンダリング起因のCSS崩壊や、有効なプラグインを調べてきてカスタマイズ・チューニングが必要なことなど、調整に手のかかるところがあるという欠点もありますが、それ以上に、gatsby-imageによる画像ファイルの最適化だったり、NetlifyやGitHubとの連携だったり、上で紹介しませんでしたがpagesにJSファイルを置けばルーティングまで勝手にやってくれることだったりと、Webサイト開発において優れた点が多いです。今後静的なWebサイトを開発する時も、今回得た知見をもとにGatsbyで開発したいなと思っています。
そして、インターンの今後のプロジェクトですが、LPと並行して、

  • インターン先のHP https://quando.jp
  • インターン先自社プロダクト SynQ Remote
  • 鉄板加工工場オートメーション化プロジェクト Webアプリ開発(Vue.jsとDjango)
  • 同プロジェクト用CNN(画像認識)モデル

なども任せてもらっているので、フロントエンドだけでなくバックエンド・機械学習など、フルスタックエンジニアを目指して様々な分野の技術に触れていきたいです。