green grass field under white clouds during daytime

JavaScript jsファイル読み込み import export まとめ

今回は、JavaScriptのファイル読込指定と、インポート・エクスポート方法についてのメモです。
純粋なJavaScriptだけを考えての内容になっています。

普段からお世話になっているMDNを、今回は特に参考にしています。(いつもありがとうございます)

・MDN 開発者向けのウェブ技術 -> JavaScript -> JavaScript リファレンス -> 文と宣言 ->import

https://developer.mozilla.org/ja/docs/Web/HTML/How_to/Add_JavaScript_to_your_web_page

・MDN 開発者向けのウェブ技術 -> HTML -> リファレンス -> 要素 -> <script>
https://developer.mozilla.org/ja/docs/Web/HTML/Reference/Elements/script


jsファイル 読み込み指定

まず、HTMLで読み込む方法です。scriptタグの表記についてです。

scriptタグは、幾つか属性が存在します。(以下を参照ください)
https://developer.mozilla.org/ja/docs/Web/HTML/Reference/Elements/script

・デフォルト(src属性以外指定なし)

<script src="path/to/my/script.js"></script>

処理の流れイメージ

  1. HTML解析一時停止して、JavaScriptをダウンロードする
  2. ダウンロード完了後、即座にスクリプト実行
  3. スクリプト終了後、HTML解析再開

読み込みパス以外を一切を指定しないパターンです。

意図的に同期が必要な場合、HTMLの描画前にどうしても処理したい場合には、こちらの指定になると思いますが、
特殊なライブラリなどでない限り、あまり行わない指定だと思います。

<script src="a.js"></script> 
<script src="b.js"></script> <!-- a.js のダウンロード・実行等が完全に処理されてから実施。 -->
<script src="c.js"></script> <!-- b.js のダウンロード・実行等が完全に処理されてから実施。 -->

jsファイルサイズが小さければそこまで影響出ないかもしれませんが、
それでもパーサーブロッキング(スクリプトの解析を優先して、HTML解析を一時停止)
が発生することになりますので、
念の為注意が必要です。

・async

<script async src="path/to/my/script.js"></script>

処理の流れイメージ

  1. HTML解析を行いながら、非同期でJavaScriptをダウンロードする
  2. ダウンロード完了後、即座にスクリプト実行(HTML解析一時停止)
  3. スクリプト実行終了後、HTML解析再開

非同期のためHTML解析を阻害しません。早く読み込み終わったものから実行を行うため、処理順は不確定となります。
そのため、依存関係が存在し、実行順が定められている場合指定できません。
疎結合な処理や機能を読み込む場合に利用します。

個人的にはあまりasyncも利用機会がなく、Google Analyticsなど本当に独立性が高いものに指定しています。

<script src="jquery.js"></script> 
<script src="use-jquery-utils.js"></script> <!-- jQuery使用箇所が、jQuery読込前に実行されエラーになる可能性あり。 -->
<script src="use-jquery-app.js"></script> <!-- jQuery使用箇所が、jQuery読込前に実行されエラーになる可能性あり。 -->

・defer

<script defer src="path/to/my/script.js"></script> 

処理の流れイメージ

  1. HTML解析を行いながら、非同期でJavaScriptをダウンロードする
  2. ダウンロード完了後、即座にスクリプト実行せずHTML解析が完了するまで実行待機
  3. HTML解析終了後、スクリプト実行

遅延指定です。DOMが完全に解析された後、DOMContentLoadedイベントが発火する直前に実行します。
実行順を保証したい時やDOMの操作を行う処理の場合こちらを指定し
ます。

<script defer src="a.js"></script> <!-- DOMが完全に処理されてから実施。 -->
<script defer src="b.js"></script> <!-- a.js のダウンロード・実行等が完全に処理されてから実施。 -->
<script defer src="c.js"></script> <!-- b.js のダウンロード・実行等が完全に処理されてから実施。 -->

・type

スクリプトタグの内容の種類を指定します。用途に応じてこちら(<script type>)を指定します。
jsonの内容を埋め込みたい場合などにも、以下のような指定をします。

<script type="application/json" id="config">
{
  "apiUrl": "/api"
}
</script>

未指定

こちらは、type=”text/javascript”と同義となります。

type=”module”

<script type="module" src="script.js"></script>

個人的には最も利用します。

  • import/export が使える(依存関係を自動解決)
  • defer と処理の流れが同じ(HTML解析と並行してJSダウンロードされ、HTML解析終了後に実行される)
  • モジュールごとにスコープが分離される

こちらを指定してjsを読み込むと、別のjsに定義されたfunctionのimport利用を行えるようになります。
全てのjs読み込みscriptタグを設置する必要がなくなります。

a1.js

function sample1() {
    console.log("This is sample1 function");
}

export { sample1 };

b1.js

import { sample1 } from './a1.js';

sample1();
<html>
<head>
<!-- 以下のようにtype="module"を付与するとb1.js内でa1.jsの処理をimport利用できる -->
<!-- type="module"がないと、Uncaught SyntaxError: Cannot use import statement outside a moduleが発生する。 -->
<script type="module" src="js/b1.js"></script>
</head>
</html>

詳しい背景も以下で解説されています。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Modules

まとめ

  • 絶対にHTML描画前に実行したい → deferasync も付けない通常の <script>
  • 順序不要でとにかく並列実行したい → async付与
  • 複数のJavaScriptの実行順を保証しつつ、HTML解析を止めたくないdefer付与
  • import/exportを利用したモジュール管理を行いたいtype="module"付与

インポート・エクスポート構文

CommonJS と ES modulesについて

JavaScriptの基礎知識として、CommonJSとES modulesについて触れておきます。

過去に、サーバーサイドなどWebブラウザ外のモジュール仕様としてCommonJSが作成されました。
その後、Webブラウザも含めたJavaScriptの標準規格として、ES Modulesが作成されましたので、
元々CommonJS基準で実装されていたものもES Modulesに移行しているようです。

CommonJS表記例

/* インポート */
var myModule = require('MyModule.js');

/* エクスポート */
module.exports = function myFunction() {...}

ES Modules表記例

/* インポート */
import { myModule } from "MyModule.js"

/* エクスポート */
export function myModule() {...}

以下に、ES modulesについての詳細が記載されています。
インポートとエクスポートについてもこちらの規約より確認することができます。

https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Modules

エクスポート方法

エクスポートしたい変数やfunctionの前に、export キーワードを付与します。
個々に付与したり、まとめて指定したりできます。

a.js

// 個々にexport指定を行う。(名前付きエクスポート)
export const aaa = "text";
export function bbb(num) {
    console.log("This is function bbb in a1.js value=" + num);
};

// まとめてexport指定を行う。(名前付きエクスポート)
const ccc = 99;
function ddd(num) {
    console.log("This is function ddd in a1.js value=" + num);
};

export { ccc, ddd }

インポート方法

b.js


// 名前付きimport
import { aaa, bbb } from "./a1.js"

// エイリアス指定しつつインポート
import { ccc as numberConst, ddd as loggerFunction } from "./a1.js"

// 全てのエクスポートを含んだインポート
import * as a_all from "./a1.js"

// 名前付きインポートした変数・Functionの使用
console.log(aaa);
bbb(5);

// エイリアス指定してインポートした変数・Functionの使用
console.log(numberConst)
loggerFunction(10);

// ワイルドカード・エイリアス指定してインポートした変数・Functionの使用
console.log(a_all.aaa);
a_all.bbb(20);
console.log(a_all.ccc);
a_all.ddd(30);

JavaScript import export sample

以下は、モジュールごとに1つだけ定義できるDefault Exportについてです。

Defaultエクスポート

export default function Header() {
  return "Header";
}

Defaultインポート

// {} を省略できよりシンプル時に利用可能
import Header from "./Header";
// 名称を変更して利用も可能(名前付きimport・exportは不可)
import MyHeader from "./Header"; 

今回の内容は以上となります。

基本的なjsの読み込み方法とインポート・エクスポート方法にすぎませんが、
複数のプログラミング言語を同時に触っている時に、どの記述方法が最適かなど忘れてしまいます。

都内でエンジニアをやっています。 2017年に脱サラ(法人設立)しました。 仕事で調べたことや、気になったことをメモしています。
投稿を作成しました 190

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA


関連投稿

検索語を上に入力し、 Enter キーを押して検索します。キャンセルするには ESC を押してください。

トップに戻る