web-dev-qa-db-ja.com

ライブラリをwebpackで本当にツリーシェイク可能にするにはどうすればよいですか?

複数のreactコンポーネントのライブラリがあり、ライブラリをツリーシェイク可能にして、次のようなコンポーネントをインポートするときに

import { Checkbox } from 'my-react-components'

バンドル全体をインポートしません。

私のindex.jsは次のようになります

export { default as Button } from './components/Button'
export { default as Checkbox } from './components/Checkbox'
export { default as FlexView } from './components/FlexView'
export { default as Radio } from './components/Radio'
export { default as Select } from './components/Select'
export { default as TextInput } from './components/TextInput'
export { default as Toggle } from './components/Toggle'

そして、webpackを使用してバンドルします

module.exports = {
  mode: 'production',
  entry: './src/index.ts',
  output: {
    path: path.resolve('./lib'),
    filename: 'react-components.js',
    libraryTarget: 'commonjs2',
  },

  // loaders and stuff...
  // terser-webpack-plugin...

  externals: {
    // don't include react in the bundle
    react: {
      root: 'React',
      commonjs2: 'react',
      commonjs: 'react',
      AMD: 'react',
    },
  },
  optimization: {
    splitChunks: false,
    sideEffects: false,
  },
}

そしてもちろん私のbabel設定には

['@babel/preset-env', {
  modules: false,
}]

この設定では、コンポーネントを1つだけインポートすると、バンドル全体が含まれます(インポートするときもwebpackを使用しています)。どうすればこれを防ぐことができますか?

17
Pontiacks

package.jsonmoduleプロパティも必要だと思います

{
   ...
   "main": "lib/index.js",
   "module": "lib/index.esm.js",
   ...
}

ライブラリに名前を付けるだけでなく、ライブラリのlibフォルダーからファイルを直接インポートすることで、これを機能させることができました。

私の場合、次のようにReactstrapライブラリからいくつかのコンポーネントをインポートしました。

import Button from 'reactstrap/lib/Button';
import UncontrolledPopover from 'reactstrap/lib/UncontrolledPopover';
import PopoverHeader from 'reactstrap/lib/PopoverHeader';
import PopoverBody from 'reactstrap/lib/PopoverBody';

1
Ehsan Sadeghi

指定したルールに従ってインポートを変換するのに役立つ効果的な babelプラグイン があります。

[
   'transform-imports', // or 'babel-plugin-transform-imports'
   {
     'react-router': {
       transform: 'react-router-dom/${member}',
       preventFullImport: true
     },
     reactstrap: {
       transform: 'reactstrap/lib/${member}',
       preventFullImport: true
     }
   }
]

注:preventFullImportは、そのパスへのインポートがツリーシェイク可能であることを確認する場合に役立ちます。


これは、未使用のインポートを効果的にツリーシェイクするのに役立つ実装のもう1つの方法です。ただし、長期的には、ファイルごとに直接インポートすることがベストプラクティスになります。

import Button from 'reactstrap/lib/Button';
import UncontrolledPopover from 'reactstrap/lib/UncontrolledPopover';
0
Joshua Stephen

2020年2月現在、Webpackでは使用できません。

ツリーシェーキングメカニズムはES6import/exportに大きく依存しており、Webpackは現在output.libraryTargetのES2015モジュール形式をサポートしていないためです。

別の方法として、ライブラリをRollup(ライブラリのES6モジュールをサポートする)などの他のバンドラーとバンドルすることもできます。

この機能はここで追跡できます: https://github.com/webpack/webpack/issues/29

[〜#〜] update [〜#〜]:ハッキーな回避策がありますが: https://stackoverflow.com/a/ 60010871/92119

0
MyTitle