大規模なWebの開発をする際に気をつけること
今回は、大規模なWebを開発するのに気をつけたいことをLTイベントでお話したのでそこらへんの知見をnoteでも共有したいと思ったので記事にします。(最近noteがスライド貼れるようになったので使いたかった)
現在、女性向け動画メディアのフロントエンドを担当しているのですが、その時にどんな構成でWebを作っていくか色々考えた結果大規模なWebの開発で気をつけたいことがちょくちょくあったので、2つ共有したいと思います。
技術としては流行りのReact(v16)を採用しました。
Reactのレンダリング方法
Reactを使ってWebを開発する際に、よくreact-routerを使ってSPAとしてWebを動かしていくのがあると思います。サーバーからは
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
</head>
<body>
<div id="app"></div>
<script src="bundle.js"></script>
</body>
</html>
のようなHTMLが200 OKで返ってきてbundle.jsが読み込まれ、Reactが画面のレンダリングを行います。
その後、react-routerなどでSPAとしてページの遷移をしていきます。
この時のメリット・デメリットを考えてみます。よく言われてるものとして
メリット
- 高速なページ遷移が実現可能
- 通常のWebではできないようなUXを生める
デメリット
- SEOの面で不利になる(Googleのクローラーはみてくれるって見かけた覚えもありますが一応)
- 初回のロードが遅い(JavaScriptを読み込んでから実行して初めてページがレンダリングされるため)
などがあります。ここでサーバーサイドレンダリングで実装した場合のメリット・デメリットも確認しておきます。
メリット
- 初回のロードが早い
デメリット
- ページ遷移のたびにロードしないといけない
- SPAで出来たようなUXを実現するのは難しい
ここである偉い人は気づきました。
あれ。これ両方のいいとこ取ればよくね。
この両方のいいところをとったような構成がIsomorphicです。(話は簡略化してます)
Isomorphicは、サーバーでReactのコンポーネントをimportしてきて、react-domのrenderToStringと言うメソッドを使いサーバーから文字列としてHTMLを返します。これによりサーバーサイドレンダリングを実現します。ブラウザがこのHTMLを取得してからはSPAとして機能するので、先ほどの2つのメリットを得ることができました!
肥大化するbundle.js
isomorphicを実現できたのでめでたしめでたしではなく、今回はもう一つ、bundle.jsの肥大化についても少し共有したいと思います。
肥大化するbundle.jsを解決するにはwebpackのcode splittingというページをみてみると良いです。
今回はdynamic importsについての話なのでこちらをみると分かります。
dynamic importsは現在、stage-3の機能なんですがReactを使っているプロジェクトは多分トランスパイラーもはいっていると思うので、そこで対処してもらえるといいと思います。
実際にどこまでファイルサイズを抑えれるのかを試してみます。
import moment from "moment"
const getDate = () => {
return moment().format("YYYY/MM/DD")
}
export default getDate
こんな感じの重めなファイルを用意します。
これを普通にimportするのと、dynamic importした時にベースのbundle.jsはどこまで差がでるでしょうか。
普通にimportします。
import heavy from "./heavy"
const main = () => {
console.log("Today is...")
console.log(heavy())
}
main()
このファイルをbundle化した場合のファイルサイズは619KBになりました。
dynamic importしたコードです。
const getDate = () => import(/* webpackChunkName: "heavy" */"./heavy")
const main = async () => {
console.log("Today is...")
const m = await getDate()
console.log(m.default())
}
main()
これをbundle化すると7.9KBになりました!
78.4分の1になりました!
dynamic importのコードはkonojunya/dynamic-import-sampleにあげているのでみていただければと思います。