🦁

「なぜここでJavaScriptを読み込むのか」 をなんとなく理解できているレベルから、言語化できるレベルに上げる。

2022/11/19に公開

はじめに

こんにちは。フロントエンジニアやっているkeiziii_sanです。
フロントエンジニアとして働き始めて2ヶ月ほど経ったのですが、JavaScriptについて改めて学び直そうと思いたち最近技術書をスキマ時間で少しづつですが読み漁っています。
そんな中で「こういう知識ってJavaScriptを勉強した頃に知っておいた方が良かったな」ということがいくつかありました。今からでもタイムマシンに乗って伝えたいけど、そんなことは無理なので、過去の自分に向けて記事に残しておこうかなと思います。

もし、これからJavaScriptを学ぼうと思っている。もしくはJavaScirptを学び始めたという方がいれば参考になる記事になる思いますので是非目を通して頂ければと思います。

今回はJavaScriptの読み込みができる方法っていくつかありますが、なぜなんだろう?何が違うんだろう?何にどう影響するんだろう?がきっかけで
「なぜここでスクリプトを読み込むのか」 をなんとなく理解できているレベルから、しっかり言語化できる知識に持っていくためにブラウザレンダリングとJavaScriptエンジンについて調べてみました。

JavaScriptはどこに書くのか?

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>study JavaScript!!</title>
    <!-- headタグ内に記述 -->
    <script src="./main.js"></script>
</head>
<body>
    
    <!-- Body配コンテンツの中に記述 -->
    <script src="./main.js"></script>



    <!-- Body配下閉じタグの直前に記述 -->
    <script src="./main.js"></script>
</body>
</html>


JavaScriptを記述するには3つの場所に記述ができます。
①headタグ内に記述
②body配下閉じタグの直前に記述
③body配コンテンツの中に記述

これらの違いについてブラウザレンダリングの仕組みとともに考えていきたいと思います。

ブラウザレンダリングの仕組み

ブラウザレンダリングを知る前にウェブブラウザを構成するコンポーネントには以下のものがあります。

  • ブラウザエンジン(ブラウザの UI を管理する)
  • レンダリングエンジン(HTML と CSS を解析し、画面に描画する)
  • javascriptエンジン
  • ネットワーキング(通信周りの機能を提供する)
  • データストレージ(Cookie 等の各種ストレージ機能を提供する)

今回はレンダリングエンジンとJavaScriptエンジンについて書いていきます。

レンダリングエンジンの処理の流れ

レンダリングエンジンとは簡単に説明するとHTMLファイルやCSSフファイルに記述された言語を解釈・計算し画面表示させるプログラムです。このプログラムには5つの処理を順次に行っていき画面の描画をおこなっていきます。

  • Parse(パース)
    役割:DOM Tree、Style Rules生成
    Documentを最上位として子要素にbody、divなどのノードが配置。JavaScriptで記述できるDocument(Dom API)というのはここで生成されたDomツリーのことをさす。
    JavaScriptでDom操作をしたい場合はパース以降に行う。

  • Style
    役割:Render Tree生成
    使うスレッド:Main Thread
    DOM Tree、Style RulesをもとにどのスタイルがどのNodeに適用されるかを決めてくれる。NodeとStyleをマッチングさせるイメージ。

  • Layout
    役割:Layout Tree生成
    使うスレッド:Main Thread
    要素の位置と大きさの計算を行う。

  • Paint
    役割:Paint Records生成
    使うスレッド:Main Thread
    要素の重なりや、色を決めてくれる。
  • Composite
    役割:レイヤーの合成とラスタライズ
    使うスレッド:Compositor Thread(ここでMain Threadは解放される)
    Paint Recordsを元に各レイヤーのピクセル単位で色を当て込んでいく。

JavaScriptエンジンの処理の流れ

JavaScriptの処理はレンダリングエンジンの処理でHTMLファイルを読み込んでいく過程で、<script></script>タグを見つけ次第JavaScriptエンジンが起動しJavaScriptの処理が始まります。またMain Threadを使って処理を行うため、javaScriptの処理が始まるとHTMLのパースは中断してしまいます。
JavaScript起動と同時にWeb APIも読み込まれDomAPIなども使えるようになります。
※setInterval, setTimeoutってWebAPIだったんだって驚きでした。

Web APIs
console
setInterval, setTimeout
Promise
Fetch
XMLHttpRequest
DOM
Mouse Event

レンダリングとJavaScriptの処理を踏まえてJavaScriptの読み込みを考えていきたいと思います。
①headタグ内に記述
head内のjsファイルの読み込みでは、Domツリーの生成はされてはいません。またheadでJavaScriptを読み込むことでHTMLのパースを中断させてしまう為、画面の描画を中断させてしまうのでここにJavaScriptを読み込むのは良くないと思われます。
ではここに記述するのはどんな時なのでしょうか。
JavaScriptには関数を呼び出す前に関数の定義をしないといけないというルールがあります。その為、HTMLのどこかで読み込みたい関数があればheadに関数定義をした方がいいのです。

②body配下閉じタグの直前に記述
JavaScriptの読み込みや実行などでパースが中断されてしまいます。スクリプトが大きくなればなるほどはページの描画が遅くなるため、それらを考えてスクリプトの記述はbody配下閉じタグの直前にするのがベターだとわかります。

③body配コンテンツの中に記述
ここへの記述については一般的ではないので省略しようと思います。

まとめ

JavaScriptエンジンについて初めて学びましたが、すごく興味深い内容でした。そして、まだまだ掘り下げれそうですね。デバッグのこととかもっと調べてみたいと思いました。
あとCSSの読み込みって同時に処理していると思っていたのですが、いくつかの処理に分かれて処理されており、レンダリングにも影響していることも分かりました。CSSのどんなStyleを当てるとページの描写にどう影響するのかを今後意識できるかなと思いました。
もし、解釈や説明が間違っている部分あればご指摘ください。

参考

独習JavaScript 新版
改訂新版JavaScript本格入門 ~モダンスタイルによる基礎から現場での応用まで
フロントエンジニアなら知っておきたいブラウザレンダリングの仕組みをわかりやすく解説!
JavaScriptがブラウザでどのように動くのか

Discussion