1. hareku

    No comment

    hareku
Changes in body
Source | HTML | Preview
@@ -1,133 +1,135 @@
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)で用いられるモジュールパターン。このモジュールは`require('name')`形式で読み込める。
+commonjsはサーバー側(Node.js)で用いられるモジュールパターン。
+このモジュールは`require('name')`形式で読み込める。
+
+
自分のコードが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`ではサンプルコードと同じ結果になる。
しかし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}`);
};
```