import文を使ったファイル読み込み
はじめに
2019-11-21リリース のNode.js 13.2.0からimport, exportに正式対応しました。
これで、import文を使ったコードがトランスパイラなしでWeb, Node.js両環境で動くようになったのでWDKに採用しました。 ざっくりとしたimportの歴史
htmlファイルでscriptタグを並べることによる複数読み込み
Node.jsで、代替手段として用意されたrequireモジュール
管理が楽になるため、Web開発でもrequireを使ったのちにコード結合されるように
ES6でWeb開発でもモジュール管理ができるimport/exportが正式採用
Webでは2017-18年頃の最新ブラウザで採用
Node.jsも拡張子を.mjsにし、実行時フラグ--experimental-modulesを設定することでimport/exportに対応
(2017.9 / Node.js 8.5.0)
Node.js、package.jsonに"type": "module"を設定することで拡張子.jsでも動くように
(2019.4 / Node.js 12.0.0)
実行時フラグ--experimental-modulesをつけなくても使えるように ←イマココ
(2019.11 / Node.js 13.2.0)
ドキュメント
ブラウザ
Node.js
ブラウザ宣言
import文を使うことで、ブラウザでのjavascript読み込みが一つになります。
Before
code: html
<head>
<meta charset="UTF-8">
<link href="stylesheets/screen.css" media="screen, projection" rel="stylesheet" type="text/css" />
<link href="stylesheets/print.css" media="print" rel="stylesheet" type="text/css" />
<link href="stylesheets/ie.css" media="screen, projection" rel="stylesheet" type="text/css" />
<script src="js/state.js"></script>
<script src="js/resource.js"></script>
<script src="js/input.js"></script>
<script src="js/screenHelper.js"></script>
<script src="js/screenModel.js"></script>
<script src="js/screen.js"></script>
<script src="js/main.js"></script>
<title>title</title>
</head>
After
code: html
<head>
<meta charset="UTF-8">
<link href="stylesheets/screen.css" media="screen, projection" rel="stylesheet" type="text/css" />
<script type="module" crossorigin src="js/main.js"></script>
<title>title</title>
</head>
Node.js
package.jsonを配備して"type": "module"を設定する必要があります。
code: package.json
{
"type": "module"
}
使い方①
jsファイルがmain.jsすべて同じ階層にある場合の例
import側
code: main.js
import { preload } from './image.js'
import { defaultState } from './state.js'
import { addListener } from './input.js'
const init = () => {
const state = defaultState;
createCanvas(state, 'screen');
preload(state);
addListener(state);
setInterval(update, 1000/state.system.fps);
}
export側
code: image.js
export const preload = (state) => {
state.resourceLoader = new ResourceLoader(resourceTable);
state.resourceLoader.preload();
}
code: state.js
export const defaultState = createState();
宣言の前にexportをつけるだけ、Functions, Objectsなんでも可能です。
使い方②
code: screenModel.js
...
export default {
getBoardPos,
getBallRadius,
getCellPos
};
export defaultでデフォルトのエクスポートする機能を規定できます。
code: index.js
import { defaultState } from './state.js'
import model from './screenModel.js'
const state = defaultState;
state.view.width = 480;
state.view.height = 640;
console.log(model.getCellPos(defaultState, 4, 4));
import model from './screenModel.js'
とすることで、デフォルトの機能を名前付きでインポートできます
その他
import * as ~といった手段でファイルのexportをまるごとimportできますが、
AirbnbStyleGuideによると非推奨のようです。
code: js
// bad
import * as AirbnbStyleGuide from './AirbnbStyleGuide';
// good
import AirbnbStyleGuide from './AirbnbStyleGuide';
ファイルごとに、デフォルトで与えられるimport手段は1つであるべき、という思想のようです。
嬉しいこと
トランスパイラなし & (Web/Node.js)共通コード縛りで参照がネストするコードが書ける
使うモジュールだけimportすることで名前衝突を避けられる & カプセル化
今までは全ファイルがグローバルに置かれている状態
本当はclassだったり、グローバル環境でもカプセル化する手段は色々あるのだけど、import採用を見越して、あえて最近ファイル直下にコード片を宣言 & global化してました。
今までフロントで書いてたコードをnode.jsで動かす形での単体テストも可能に。