JSのモジュールについてのあれこれ

最初に読む
上を読んだ上で読む
ES Modulesについて
こちらの記事を参考にしてまとめたもの。
モジュールって?
機能のまとまりの単位のこと。
JSにはモジュールが実装されてなかったみたい。だから後発的に施策されたり、サードパーティーライブラリが実装されてきた背景がある。

JSのモジュール
JSのモジュールには仕様と、それを使うツールが存在。
仕様
CommonJS
とかESModules
とか。
これらはモジュールをどう実現させるか、どう記述するか、どう動くかをまとめた概念やルール。(実体はない)
ツール
モジュールは仕様だけでは動かない。
仕様に基づいて作成されたツールが必要。
Webpack
とかrollup.js
とか
ここまでのまとめ
仕様+ツール=JSのモジュール
仕様:CommonJS
、ESModules
etc...
ツール:Webpack
、rollup.js
etc...
CommonJS
とESModules
って何が違うんだ...?てかなんで2つあるんだ??どっちがいいとかあるの?

モジュールの歴史
JS/Node | 出来事 |
---|---|
JS | JSは小規模実装だけだったりの理由でモジュール機能がなかった。なのでimport やrequire など外部ファイル(モジュール)の読み込みができなかった。(HTMLファイル内でscriptタグ のsrc属性 で読み込んでいた。) |
Node | === Nodeでモジュール機能誕生 === |
Node | CommonJS(モジュールの仕様)の策定 |
Node | Node.jsが誕生(サーバーサイドでJSが書ける様になった) |
JS | === ブラウザでモジュール機能誕生 === |
JS |
CommonJS をブラウザで使える様にとかで色々なツールが誕生してカオス状態に |
JS | ES2015になって、ESModules 策定 |
JS | WebpackがESModules に対応 |
JS | Babelを使って、ESModules =>CommonJS に変換できる様になった |
JS |
モダンなブラウザではESMoudles を標準で使用可能に(2017年ごろ) |
Node |
Node.jsでもESModulesを標準で使用可能に(2019年ごろ)( |
メモ
ノーバンドルなビルドツール→snowpackやviteがあるが、何が嬉しいのか理解できていないので調査
疑問点
・今後はESModules
がスタンダードに?
・「WebpackがESModules
に対応したり」ってなんだ?CommonJS
とESModules
に対応!とかそんな感じで複数の仕様に対応したりするのか?
・「モダンなブラウザではESMoudles
を標準で使用可能に」ってことはCommonJS
が使われていて、CommonJS
も継続して使えるのか。歴史の古いCommonJS
が標準になっていた?

webpackやbabelについて軽く触れる
babel
ESModules
=>CommonJS
に変換してくれるツール。これによって、古いブラウザでも使用可能に。
-
新しいJS文法(ES6以降)
=>古いJS文法(ES5)
に変換(トンランスパイル)。(polyfill) -
pollyfill
とは代替コードのこと- 最近のbabelは「ES5記法への変換+polyfillの導入」をまとめてやってくれるみたい
-
TypeScript
=>JavaScript
に変換 - import/exportの依存解決まではやってくれないので、webpackなどでバンドルする必要あり
=>要は、ES6以降の新JSをES5の旧JSに変換(トランスパイル)してくれて、新JSの文法に対応していないブラウザを助けてくれるいい奴。
webpack
webpackでビルドすると、node_modules以下の依存関係も含め、1つのJSファイルにまとめる。
-
=>モダンブラウザは標準対応imort
やrequire
などをブラウザでも対応できる様にする - 1つのJSファイルにまとめるので、読み込みの順番などを気にせずに済む
- 複数のJSファイルのみでなく、
node_modules
のモジュールを結合可能- node.jsで使われている仕様が
commonJS
など関係なく解決してくれる
- node.jsで使われている仕様が
- JSだけでなく、CSSや画像もバンドル可能
- 標準の
ES Modules
が使える- 変数の競合やグローバル汚染を防げる(=開発の安全性アップ)
=>要は、複数のJSファイルなどを1つにまとめて、くれる奴import
などのmodule機能をブラウザ対応して

export
やimport
について
ES Modulesによる
named exports
export
パート
// 変数をexport
export const url = "https://zenn.dev/";
// 関数をexport
export function test(a, b) {
return a * b;
}
// 変数に入れた関数をexport
export const calc = (x, y) => {
return x * y;
}
import
する記述
// sub.jsの中からcalc関数(モジュール)をimport
import { calc } from "sub";
calc(3, 2); // => 6
import
するファイルのモジュール全てを参照もできる。
// sub.jsの全てのモジュールをimport
import * as sub from "sub";
sub.calc(3, 2); // => 6
default exports
export
する記述
export default function(a, b) {
return a * b;
}
import
する記述
import Sub from "subFunc";
Sub(3, 10); // => 30
default exports
でも複数のモジュールをexport
できる。
export
する記述
const calc = (a: number,b: number) => {
return a * b;
};
const greeting = (name) => {
return `こんにちは、${name}です。`;
};
export default { calc, greeting }
import
する記述
import Sub2 from "subFunc2";
Sub2.calc(3, 10); // => 30
Sub2.greeting("あきひろ"); // => こんにちは、あきひろです。
まとめ
named exports
は同じファイル内で複数をモジュールとしてexport
できる。
default exports
は1つのみ。でもオブジェクトにしてその中にモジュールを入れてexport
すれば似たことができる。結構この記述方法好き。

default exportについてもうちょい
default export
はnamed export
でもあるらしい
どういうことか?
上記のコードを例もう一度例に出す。
export
する記述
export default function(a, b) {
return a * b;
}
import
する記述
import部分の以下二つは同じ意味。
export default { do stuff }
のdefault
と言う名前でexport
している。
import { default as Sub } from "subFunc";
import Sub from "subFunc";
Sub(3, 10); // => 30
つまり、ここで分かることは
import Sub from "subFunc";
のSub
部分は{ default as Sub }
と同じ意味で、defaultという名前をimport側ではSub
として扱っているということになる。

未読
疑問
import React, { useState } from 'react'
上記みたいなdefault exports
とnamed exports
の組み合わせってどうなっている?(その組み合わせではないかもしれない)=>未調査
エントリーポイントを叩けば、それに内包されているコンポーネントを読み取れるという奴。
これはimportしてexport(橋渡し)のショートハンド?
export {default as AnswersList} from './AnswersList';

Viteについて
Viteは開発時にはモダンブラウザーのES modulesを使って高速に動作します
が、最終的にビルドする際は従来型のバンドラーと同様、すべてのファイルをひとつにまとめてくれる
(具体的には、ビルド時は内部的にrollup.jsを使用しています)