Zenn
Closed9

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

あきひろあきひろ

最初に読む

https://uuuundefined.tokyo/blog/javascript-modules/
https://www.tohuandkonsome.site/entry/2018/07/13/182057
https://ics.media/entry/16511/

上を読んだ上で読む

https://blog.ikeryo1182.com/javascript-modules/
https://qiita.com/teradonburi/items/a0095b8c8dfd876d6b91
https://zenn.dev/naoki_mochizuki/articles/46928ccb420ee733f78f
https://zenn.dev/mizchi/articles/native-esm-age

ES Modulesについて

https://qiita.com/senou/items/a2f7a0f717d8aadabbf7
https://zenn.dev/mizchi/articles/3789a101dae388d98159
https://youtu.be/7hVUV0fwKwg

こちらの記事を参考にしてまとめたもの。

モジュールって?

機能のまとまりの単位のこと。
JSにはモジュールが実装されてなかったみたい。だから後発的に施策されたり、サードパーティーライブラリが実装されてきた背景がある。

あきひろあきひろ

JSのモジュール

JSのモジュールには仕様と、それを使うツールが存在。

仕様

CommonJSとかESModulesとか。
これらはモジュールをどう実現させるか、どう記述するか、どう動くかをまとめた概念やルール。(実体はない)

ツール

モジュールは仕様だけでは動かない。
仕様に基づいて作成されたツールが必要。
Webpackとかrollup.jsとか

ここまでのまとめ

仕様+ツール=JSのモジュール
仕様:CommonJSESModulesetc...
ツール:Webpackrollup.jsetc...

CommonJSESModulesって何が違うんだ...?てかなんで2つあるんだ??どっちがいいとかあるの?

あきひろあきひろ

モジュールの歴史

JS/Node 出来事
JS JSは小規模実装だけだったりの理由でモジュール機能がなかった。なのでimportrequireなど外部ファイル(モジュール)の読み込みができなかった。(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年ごろ)(v12系以降=>Node v13.2.0 でようやく正式にサポート)

メモ

ノーバンドルなビルドツール→snowpackやviteがあるが、何が嬉しいのか理解できていないので調査

疑問点

・今後はESModulesがスタンダードに?
・「WebpackがESModulesに対応したり」ってなんだ?CommonJSESModulesに対応!とかそんな感じで複数の仕様に対応したりするのか?
・「モダンなブラウザでは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ファイルにまとめる

  • imortrequireなどをブラウザでも対応できる様にする=>モダンブラウザは標準対応
  • 1つのJSファイルにまとめるので、読み込みの順番などを気にせずに済む
  • 複数のJSファイルのみでなく、node_modulesのモジュールを結合可能
    • node.jsで使われている仕様がcommonJSなど関係なく解決してくれる
  • JSだけでなく、CSS画像もバンドル可能
  • 標準のES Modulesが使える
    • 変数の競合やグローバル汚染を防げる(=開発の安全性アップ)

=>要は、複数のJSファイルなどを1つにまとめて、importなどのmodule機能をブラウザ対応してくれる奴

あきひろあきひろ

ES Modulesによるexportimportについて

named exports

exportパート

sub.js
// 変数を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する記述

main.js
// sub.jsの中からcalc関数(モジュール)をimport
import { calc } from "sub";
calc(3, 2); // => 6

importするファイルのモジュール全てを参照もできる。

main.js
// sub.jsの全てのモジュールをimport
import * as sub from "sub";
sub.calc(3, 2); // => 6

default exports

exportする記述

subFunc.js
export default function(a, b) {
  return a * b;
}

importする記述

main.js
import Sub from "subFunc";
Sub(3, 10); // => 30

default exportsでも複数のモジュールをexportできる。

exportする記述

subFunc2.js
const calc = (a: number,b: number) => {
  return a * b;
};

const greeting = (name) => {
  return `こんにちは、${name}です。`;
};

export default { calc, greeting }

importする記述

main.js
import Sub2 from "subFunc2";
Sub2.calc(3, 10); // => 30
Sub2.greeting("あきひろ"); // => こんにちは、あきひろです。

まとめ

named exportsは同じファイル内で複数をモジュールとしてexportできる。
default exportsは1つのみ。でもオブジェクトにしてその中にモジュールを入れてexportすれば似たことができる。結構この記述方法好き。

あきひろあきひろ

default exportについてもうちょい

default exportnamed exportでもあるらしい

どういうことか?
上記のコードを例もう一度例に出す。

exportする記述

subFunc.js
export default function(a, b) {
  return a * b;
}

importする記述

import部分の以下二つは同じ意味。
export default { do stuff }defaultと言う名前でexportしている。

main.js
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として扱っているということになる。

あきひろあきひろ

未読

https://www.codegrid.net/articles/2017-es-modules-1/
https://zenn.dev/oukayuka/books/cb48853473000fb7fcde/viewer

疑問

import React, { useState } from 'react'

上記みたいなdefault exportsnamed exportsの組み合わせってどうなっている?(その組み合わせではないかもしれない)=>未調査

エントリーポイントを叩けば、それに内包されているコンポーネントを読み取れるという奴。
これはimportしてexport(橋渡し)のショートハンド?

エントリーポイント
export {default as AnswersList} from './AnswersList';
このスクラップは2023/10/28にクローズされました
ログインするとコメントできます