1. hareku

    Posted

    hareku
Changes in title
+TypeScript - tsconfigのmoduleとtargetには何を設定すればいいか
Changes in tags
Changes in body
Source | HTML | Preview
@@ -0,0 +1,133 @@
+TypeScriptの設定ファイルを雰囲気でコピらないための記事
+
+## TL;DR
+- `module`はどのモジュールパターンで出力するかを指定する
+ - Node.jsでの利用想定なら`commonjs`
+ - ブラウザ側での利用なら`umd`
+- `target`はどの動作環境向けにトランスパイルするかを指定する
+ - 利用環境が想定できないなら`es3`や`es5`
+ - 下位互換性のあるコードへの変換をBabelで行うなら`esnext`
+
+## module とは
+
+JavaScriptにはいくつかのモジュールパターン(CommonJSやAMD、ECMAScriptなど)がある。TypeScriptをJavaScriptに変換する際、どのモジュールパターンにするかを`module`に指定する必要がある。
+
+`module`には`'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015', 'esnext'`などを指定できる。デフォルトは`target === "es3" or "es5" ? "commonjs" : "es6"`、つまりtargetがes3かes5ならcommonjsとなる。
+
+### サンプルコード
+今回は実際にアウトプットされるコードを見ながら解説する。
+用いるTypeScriptのサンプルコードは以下。
+
+```index.ts
+export default (name: string) => {
+ console.log(`Hello ${name}`)
+}
+```
+
+### `module: commonjs`
+
+commonjsはサーバー側(Node.js)で用いられるモジュールパターン。
+自分のコードがNode.jsからしか利用されない、という想定の場合はcommonjsにする。
+
+`yarn run tsc index.ts --module commonjs`
+
+```output.js
+"use strict";
+exports.__esModule = true;
+exports["default"] = (function (name) {
+ console.log("Hello " + name);
+});
+```
+
+余談だが、後述するアウトプットの中にも`exports.__esModule = true;`のような記述が頻出する。これはモジュールがES Modules(`import`, `export`)形式に対応していることを伝えるためである。読み込み側はTypeScriptの`esModuleInterop`をtrueにすれば、上のようなcommonjs形式のライブラリも`import`で読み込める。
+
+詳しくは「[TypeScriptの`--esModuleInterop`は一体何をやっているのか - stone's throw](http://osamtimizer.hatenablog.com/entry/2018/06/28/122502)」が参考になる。
+
+### `module: amd`
+
+amdはブラウザ側で利用でき、さらに非同期で読み込めるモジュールパターン。
+amdについては[AMD & RequireJS - Qiita](https://qiita.com/nanocloudx/items/70f1316debf05b93ac82)が参考になる。
+
+`yarn run tsc index.ts --module amd`
+
+```output.js
+define(["require", "exports"], function (require, exports) {
+ "use strict";
+ exports.__esModule = true;
+ exports["default"] = (function (name) {
+ console.log("Hello " + name);
+ });
+});
+```
+
+### `module: umd`
+
+umdは、commonjsとamdの両方に対応したモジュールパターン。コードサイズはamdとそれほど変わらないため、基本的にブラウザ向けに配布する場合もumdにする。(例として、[Vue.jsはscriptをumdで配布している](https://jp.vuejs.org/v2/guide/installation.html)。)
+
+`yarn run tsc index.ts --module umd`
+
+```output.js
+(function (factory) {
+ if (typeof module === "object" && typeof module.exports === "object") {
+ var v = factory(require, exports);
+ if (v !== undefined) module.exports = v;
+ }
+ else if (typeof define === "function" && define.amd) {
+ define(["require", "exports"], factory);
+ }
+})(function (require, exports) {
+ "use strict";
+ exports.__esModule = true;
+ exports["default"] = (function (name) {
+ console.log("Hello " + name);
+ });
+});
+```
+
+### `module: es6`
+`yarn run tsc index.ts --module es6`
+
+ライブラリがES Modules形式でしか利用されない場合、`es6`もしくは`esnext`を指定する。
+しかし前述したcommonjsのライブラリも`esModuleInterop`によってES Modules形式で読み込むことができる。そのため無理にこの`es6`などに設定してcommonjsを切り捨てる必要は無い。
+
+```output.js
+export default (function (name) {
+ console.log("Hello " + name);
+});
+```
+
+## Target
+
+`target`はどの動作環境に向けてトランスパイルするかを指定する。
+
+`target`には、`'es3', 'es5', 'es6', 'es2015', 'es2016', 'es2017', 'es2018', 'es2019', 'es2020', 'esnext'`などを指定できる。(デフォルトは`es3`)
+
+### `target: es3`
+
+サンプルコードにある``Hello ${name}``は、ES6から使える[テンプレートリテラル](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/template_strings)である。ES3やES5では使えないため、ここでは`"Hello " + name`に変換されている。
+
+`yarn run tsc index.ts --target es3`
+
+```output.js
+"use strict";
+exports.__esModule = true;
+exports.default = (function (name) {
+ console.log("Hello " + name);
+});
+```
+
+### `target: es6`
+
+サンプルコードとまったく同じ結果になる。
+
+しかしブラウザではまだES6は動作しないため、前述した`es3`や`es5`で出力しなければいけない。
+このような下位互換性のあるコードに変換する役割はTypeScriptでも担えるが、Babelを用いて行うケースも多い。そういった場合はTypeScriptは`es6`または`esnext`として出力し、Babel側で任意の環境に向けたコードにトランスパイルするのが一般的だ。
+
+
+`yarn run tsc index.ts --target es6`
+
+```output.js
+export default (name) => {
+ console.log(`Hello ${name}`);
+};
+```