manabuyasuda / til

知ったこと考えたこと
4 stars 0 forks source link

2019/08/02 lodash-esのimportを最適化する #15

Open manabuyasuda opened 5 years ago

manabuyasuda commented 5 years ago

必要なモジュールだけをインポートするのが最適解とはいえ、楽をしたいのもの。 Tree Shakingでいい感じに最適化してくれないかなとテストをした。

すべて_.map();と同等の処理をしている。

import ファイルサイズ
import _ from 'lodash-es'; 96KB
import { map } from 'lodash-es'; 16KB
import * as _ from 'lodash-es'; 25KB

意外なことに、import * as _ from_にモジュールをすべて含めるパターンが{ map }のように個別にインポートするパターンとそれほど大差がない。

_.cloneDeep();_.omit();を追加して再テストした。

import ファイルサイズ
import _ from 'lodash-es'; 96KB
import { map, cloneDeep, omit } from 'lodash-es'; 23KB
import * as _ from 'lodash-es'; 32KB

一括 / 個別 *100%で計算すると、_.map()だけの場合は156%大きかったのが、3つになると139%になっていた。 実数だと1つだけの場合と3つの場合で共に9KBしか変わらない。 合計6つにしても10KB(64と74)しか変わらない。

一括でインポートする場合もTree Shakingの対象になっていて、10KB増えているのは_プロパティにlodashをインポートする処理なのではないか。

import * as _ from 'lodash-es';を使うのが、パフォーマンスを含めた最適解かもしれない。

気になったのはモジュールを6つ使って64KBって、フルサイズの96KBとそんなに変わらないのでは…。

lodashをフルで入れた場合で80KBだった。 もうlodashでいいのではという気もしてきた。 debounceとthrottleくらいしか使ってない場合はlodash-es、値を色々フォーマットする場合はlodashを使うのがよさそう。

manabuyasuda commented 5 years ago

検証環境は以下の通り。

  "devDependencies": {
    "@babel/preset-env": "^7.4.5",
    "babel-loader": "^8.0.6",
    "core-js": "^3.1.4",
    "dotenv": "^8.0.0",
    "eslint": "^6.0.1",
    "eslint-config-airbnb-base": "^13.1.0",
    "eslint-config-prettier": "^6.0.0",
    "eslint-loader": "^2.1.2",
    "eslint-plugin-import": "^2.18.0",
    "eslint-plugin-prettier": "^3.1.0",
    "eslint-plugin-vue": "^5.2.3",
    "gulp": "^4.0.2",
    "webpack": "^4.35.0",
    "webpack-stream": "^5.2.1"
  },
  "dependencies": {
    "lodash": "^4.17.15",
    "lodash-es": "^4.17.11",
  },
{
  "presets": [
    [
      "@babel/preset-env",
      {
        "modules": false,
        "useBuiltIns": "usage",
        "corejs": 3
      }
    ]
  ]
}
manabuyasuda commented 4 years ago

import * as _ from 'lodash-es';にすると、developmentモード以外で以下のエラーになった。 再現条件は未検証だが、避けたほうが無難かもしれない。

Dn(...).reject is not a function