简体   繁体   中英

Can Webpack tree-shake to remove imports already removed by tree-shaking

Can Webpack be configured so that its tree-shaking is smart enough to remove imports depended on by only other tree-shaken exports?

Example:

entry.js

import { apple } from './appleBanana';
console.log(apple());

appleBanana.js

import { mango, orange } from './mangoOrange';

export function apple() {
  console.log('apple');
  mango();
}

export function banana() {
  console.log('banana');
  orange();
}

mangoOrange.js

export function mango() {
  console.log('mango');
}

export function orange() {
  console.log('orange');
}

webpack.config.js optimization

optimization: {
  concatenateModules: false,
  usedExports: true,
  sideEffects: true
}

When compiling with the above, we get:


/***/ "./client/entry/Test.ts":
/*!******************************!*\
  !*** ./client/entry/Test.ts ***!
  \******************************/
/*! no exports provided */
/*! all exports used */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony import */ var _appleBanana__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./appleBanana */ "./client/entry/appleBanana.ts");

console.log(Object(_appleBanana__WEBPACK_IMPORTED_MODULE_0__[/* apple */ "a"])());

/***/ }),

/***/ "./client/entry/appleBanana.ts":
/*!*************************************!*\
  !*** ./client/entry/appleBanana.ts ***!
  \*************************************/
/*! exports provided: apple, banana */
/*! exports used: apple */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return apple; });
/* unused harmony export banana */
/* harmony import */ var _mangoOrange__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./mangoOrange */ "./client/entry/mangoOrange.ts");

function apple() {
  console.log('apple');
  return Object(_mangoOrange__WEBPACK_IMPORTED_MODULE_0__[/* mango */ "a"])();
}
function banana() {
  console.log('banana');
  return Object(_mangoOrange__WEBPACK_IMPORTED_MODULE_0__[/* orange */ "b"])();
}

/***/ }),

/***/ "./client/entry/mangoOrange.ts":
/*!*************************************!*\
  !*** ./client/entry/mangoOrange.ts ***!
  \*************************************/
/*! exports provided: mango, orange */
/*! exports used: mango, orange */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return mango; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return orange; });
function mango() {
  console.log('mango');
}
function orange() {
  console.log('orange');
}

/***/ })

/******/ });

Note that both mango and orange are marked as used, even though banana() (which calls orange() ) got removed by tree-shaking. As a result, in the Terser/Uglify minified bundle, they both get included.

Is there a way to make Webpack or Terser/UglifyJS smarter and also remove imports to symbols that are not used in the post-tree-shaking?

It will remove them, what you are seeing is not a production bundle (due to comments & not minified code).

In dev builds, webpack just marks that there are unused exports/imports with a comment, like in your example bundle.

Tree-shaking is a process that will be applied only at production build , it removes these unused tokens from the bundle.

Just try to run build in production mode, and check the minified bundle, you should expect that banana & orange will not exists in it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM