Может ли Webpack встряхнуть дерево, чтобы удалить импорт, уже удаленный встряхиванием дерева

Можно ли настроить Webpack так, чтобы его встряхивание дерева было достаточно умным, чтобы удалить импорт, от которого зависел только другой экспорт с встряхиванием дерева?

Пример:

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: {
  concatenateModules: false,
  usedExports: true,
  sideEffects: true
}

При компиляции с вышеизложенным получаем:


/***/ "./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');
}

/***/ })

/******/ });

Обратите внимание, что и mango, и orange помечены как используемые, даже несмотря на то, что banana() (который вызывает orange()) был удален в результате встряхивания дерева. В результате в минимизированный пакет Terser/Uglify включены они оба.

Есть ли способ сделать Webpack или Terser/UglifyJS умнее, а также удалить импорт символов, которые не используются в post-tree-shaking?


person incaren    schedule 20.02.2021    source источник


Ответы (1)


Это удалит их, то, что вы видите, не является производственным пакетом (из-за комментариев и не минимизированного кода).

В dev-сборках webpack просто отмечает неиспользуемые операции экспорта/импорта комментарием, как в вашем примере пакета.

Tree-shaking — это процесс, который будет применяться только при производственной сборке. Он удаляет неиспользуемые токены из пакета.

Просто попробуйте запустить сборку в рабочем режиме и проверьте минифицированный пакет, вы должны ожидать, что в нем не будет banana и orange.

person felixmosh    schedule 24.02.2021
comment
Вы правы в том, что banana будет удалено, а orange не будет, так как оно не помечено как неиспользуемое! Знаете ли вы, как сделать Webpack достаточно умным, чтобы он также удалял orange? - person incaren; 25.02.2021
comment
Это зависит от того, применялась ли оптимизация конкатенации модулей. Если ваша конфигурация TS генерирует модули commonjs, она не будет применяться. Попробуйте установить для свойства модуля значение esnext в файле tsconfig. - person felixmosh; 26.02.2021
comment
Я уже сделал это (т.е. я использую @babel/preset-env с модулями, установленными на false), но позвольте мне посмотреть, генерирует ли tsc другой код в этом случае! - person incaren; 27.02.2021
comment
Вы пытались изменить поле module в файле tsconfig? - person felixmosh; 01.03.2021