24
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

webpack4のTree Shakingを基本的なimport/exportで試してみる

Last updated at Posted at 2018-11-30

今まで大して意識をせずにimportexportを行ってきましたが、TypeScriptについていろいろ調べていたところ、このようなものを見つけ。。

export default considered harmful

え、そんな危険なの?と。なんとなく、import書くの楽だし使っていたのですが、ビビりました。まぁ読んでみるとそこまで害悪でもなかったのですが、調べているとアンチパターンについて言及があったりなど、何も考えずに使っていると無駄にbundleされたファイルが大きくなってしまうようなので、ここらでTree-Shakingをテストすることにします。

テスト環境

めっちゃありがたい先駆者の記事がありましたので、そのソースコードをフォークしました。ありがたや。

今回のソースコードはこちらになります。

環境は以下のような感じ。

package.json
  "devDependencies": {
    "babel-core": "^6.26.3",
    "babel-loader": "^7.1.4",
    "babel-plugin-transform-imports": "^1.5.0",
    "babel-preset-env": "^1.6.1",
    "webpack": "^4.14.0",
    "webpack-cli": "^3.0.2"
  }

webpackは4系で試しています。3系でも試したところ、結構結果変わったので、注意してください。

テストしたもの

かなりバリエーションに富んだ、import & export & default を試しました。以下の「単体export」はexport func, export func2のようにexportだけを使ったもの、「単体でimport」はimport { func }、「全体でimport」はimport * as hogehoge.funcを実行といった感じです。詳しくは、ソースコード見てください。

  • 「単体export」を「単体でimport」: solo.js
  • 「単体export」を「全体でimport」: all.js
  • 「単体exportをそのまま全体でexportしたファイル」を「全体でimport」: all2.js
  • 「単体exportを全体でimportし、それを単体exportしたファイル」を「単体でimport」: all3.js
  • 「export default した object を default as で受けたものを export したファイル」を「単体でimport」: all4.js
  • 「object を export default」を「普通にimport」: object.js
  • 「object を export default」を「default as で import」: object2.js
  • 「アンチパターン検証記事で試されていたもの」を「普通にimport」: object3.js

基本的に、各ファイルには「A」と「B」の2つの関数が入っています。index.jsでは、importしたもののうち「A」が付くものだけを実行しています。

// all.js
export const allA = () => console.log('allA');

export const allB = () => console.log('allB');

// index.js
import * as all from './all';

all.allA();

つまり、上記の例では、console.log('allA');のみ見つかれば「Tree Shakingが効いている」、console.log('allB');も見つかると「Tree Shakingが効いていない」と判断できます。

実行結果

yarn buildでビルドできます。実行したときの結果は以下の通り。

bundle.png

dist/bundle.js
// 上の方は省略
  var r = function () {
      return console.log("soloA")
    },
    l = function () {
      return console.log("all3A")
    },
    u = function () {
      return console.log("all3B")
    },
    c = function () {
      return console.log("all4A")
    },
    f = function () {
      return console.log("objectA")
    },
    i = function () {
      return console.log("object2A")
    };
  r(), console.log("allA"), console.log("all2A"), r(), t.all3A(), c(), f(), i(), console.log("foo")
}]);

お、all3.js以外はTree Shakingが効いていることがわかりました。

テストからわかったこと1:オブジェクトでexportしてもTree Shakingは効く

アンチパターン検証記事によれば、export default objectではTree Shakingが効かないとありましたが、webpack4では効くようです。(※webpack3では、効かないですが!詳細は後述。)

テストからわかったこと2:全体指定でexportしてもTree Shakingは効く

個人的に気になっていたこととして、「import * as all from './all';として、その一部分しか使用しなかった場合に、Tree Shakingが効くのか否か」があります。

結果としては、Tree Shaking は効いていました。こうなってくると、多量にexportが存在するファイルでは、*でimportしてそこから呼び出した方が気持ちよくなりますね。

テストからわかったこと3:ワンクッションおいてexportしたい場合はexport { default as name }を使う

今回の実験の目的として、これがありました。ReactとReduxのファイル構成パターンであるre-ducksなどで構成が深くなる場合、どうしてもindex.jsにexportを集約させたほうが楽になります。そうした、1クッションおく場合の実装はどのようなimport/exportが最適なのかを知りたかったのですが、それがわかりました。

以下の通りにやると、しっかりTree Shakingが効くことがわかりました。

// all4.js
export { default as all4 } from './forAll4';

// forAll4.js
const all4A = () => console.log('all4A');

const all4B = () => console.log('all4B');

export default { all4A, all4B };

ちなみに、構文的にexport * as all4 from './forAll3などのようなことはできないみたいなので、これを実現したい場合は上記のようにexport defaultを使う必要があります。

webpack 3系で試すと全然違った

かなり違いました。3系では、アンチパターン検証記事が正しく、オブジェクトの場合は全くTree Shakingが効きません。object.js、object2.js、object3.jsが全滅でした。また同様に、all3.jsとall4.jsでもTree Shakingは効いていませんでした。

3系でも効くのは、solo.jsとall.js、all2.jsのみでした。つまり、単体でimport/exportするか、直接import * as allなどのようにimportする場合は、Tree Shakingが効くということです。

自分で確認したい方は、webpack3用にブランチを切ったので、そちらをクローンし、ビルドしてください。その結果をここでminifyすると、何がTree Shakingされるかが確認できます。

結論

圧縮率も違うみたいだし、webpack3からwebpack4に移行しましょう!!

24
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
24
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?