JavaScript
es6
ESModules
HALDay 10

ECMAScript 6 modules

この記事はHAL Advent Calendar 2017 の10日目の記事です。

担当はJavaScriptにステ振りしたHAL Osakaの4年生です。
JavaScriptのフレームワークはもう何でもいいのでデータモデリングとCSSをどうにかするのがマイブームです。

なぜモジュールを知るのか

いったい何回それをコピペするのか。

Don’t Repeat Yourself

Andy Hunt氏とDave Thomas氏が「The Pragmatic Programmer: From Journeyman to Master」で最初に言及したソフトウェア開発原則です。

ベストプラクティスはソースの繰り返し部分全てを抽象化するというものです。
無理しすぎると不要な抽象化も発生するので気負いすぎないことは大事だと思っています。

嫌でもその同じ関数、クラスあちこちで使っていてたら勉強することになるでしょう。
import - JavaScript - MDN - Mozilla
export - JavaScript - MDN - Mozilla

他にもモジュールの実装と仕様がありますが、ここでは一切触れません。

どのようにモジュールを活用するのか

ずばり、ソースをファイルで切り分けてしまうことです。
validationであればvalidates.jsvalidates/email.jsのように切り分けてソースを移行してしまいましょう。
重複していたソースはなくなり今後も重複することはないので、そのvalidation処理のテストコード書き始めるのがベストだと思います。

一体なぜこの記事を書いたのか

一番言及したかったのはexport defaultについて。

export - JavaScript - MDN - Mozilla

export default expression;
export default function () {  } // class, function* も使用可
export default function name1() {  } // class, function* も使用可

実はexport default {}という記述はどこにもないんですよ。
然しながらエラーは発生しないです動きます。

アクセル博士(プロフィール)発言から

Note that default-exporting objects is usually an anti-pattern (if you want to export the properties). You lose some ES6 module benefits (tree-shaking and faster access to imports).

[意訳]
プロパティをexportする時にexport defaultでオブジェクトをexportすることは一般的にアンチパターン。
より早いimportへのアクセスとツリーシェイキングというES6 Moduleの利点を損なう。

つまり静的解析ができないということです。

どうするのか

ファクトリ関数を作る

url.js
function url() {
  return Object.assign(
    {},
    {
      apis: {
        root: 'http://localhost:8080/api/talks',
        stories: 'http://localhost:8080/api/stories',
        conversations: 'http://localhost:8080/conversations',
      },
    }
  );
}

export default url();
import {url} from 'url';

fetch(url.apis.root)
  .then(function(response) {
    return response.json()
  }).then(function(json) {
    console.log('parsed json', json)
  }).catch(function(ex) {
    console.log('parsing failed', ex)
  })

parcelにも言及したい

📦parcel面白いですよね。とても楽そう。
でも色々な要件があると思うのでwebpack使う現実的に戻されるのがオチ。