Как использовать побочные эффекты в Webpack?

внешний интерфейс Vue.js Webpack MobX

Оригинальная ссылка

webpack v4 добавил новыйsideEffectsхарактеристики, даваяpackage.jsonПрисоединяйсяsideEffects: falseОбъявляет, содержит ли модуль пакета побочные эффекты, которые могут предоставить больше места для оптимизации дерева.

Сначала посмотрите на картинку, чтобы почувствовать:

Примечание: когда вызывается бета-версия v4pure module, а позже изменился наsideEffects

Основываясь на нашем понимании побочных эффектов в fp, мы можем думать, что пока мы уверены, что модули в текущем пакете не содержат побочных эффектов, мы пометим пакет, опубликованный в npm, какsideEffects: false, мы можем предоставить пользователям лучший опыт упаковки. Принцип заключается в том, что веб-пакет может отправлять пакеты, помеченные как не имеющие побочных эффектов.import {a} from xxПеревести вimport {a} from 'xx/a', так что ненужный импорт автоматически обрезается, а эффект тот жеbabel-plugin-import.

Поэтому я очень рад добавить эту конфигурацию в несколько моих библиотек (конечно, без побочных эффектов).

Пока я не увидел, как @Sean Larkin отправил такой pr на vue несколько месяцев назад:chore(package.json): Add sideEffects: false field in package.json,я тогда немного запутался.Согласно моему пониманию vue,в коде много побочных эффектов.Например,многие функции имеют правильныеVue.prototypeСсылка даже изменена и не должна быть установленаsideEffects: falseВот так. Однако дело в том, что мне влепили по морде, т.к. Йода быстро слил этот пр. . Это прямо заставило меня не осмелиться датьmobxДобавьте эту конфигурацию, потому что я понятия не имею, к чему относятся эти побочные эффекты веб-пакета. .

Пока два дня назад кто-то не далmobx-utilsЯ поднял вопрос и сказал, что эту конфигурацию можно добавить, чтобы помочь встряхнуть дерево.В своих сомнениях я вспомнил pr vue и перечитал его снова.Я обнаружил, что кто-то уже задавал тот же вопрос, что и я, в pr:

Hy Sean!

Could you please specify what you mean by "vue's original source files"?

I looked at the index.js file in the src/core folder and to my knowledge there are plenty sideeffects that would be prune away by tree shaking. (e.g Object.defineProperty)

I hope you can help me understand how this works.

Оригинальный пиар Шона гласит следующее:

This PR adds the "sideEffects": false property in vue's package.json file. This allow's webpack (for those who want to opt-in to requiring vue's original source files (instead of the flattened esm bundles) and want to remove flow type through a babel-transform, then this will allow webpack to aggressively ignore and treeshake unused exports throughout the module system.

Шон имеет в виду, что когда вы импортируете исходные файлы vue по запросу вместо связанных пакетов, webpack может помочь вам лучше трясти дерево. Например, вы обращаетесь к модулю в vue следующим образом:import Vue from 'vue/src/core'.

Затем Шон сказал, что этот побочный эффект не тот побочный эффект (в fp), а затем дал ответ на stackoverflow, чтобы объяснить побочные эффекты, центральная идея:

whenever a module reexports all exports (regardless if used or unused) need to be evaluated and executed in the case that one of those exports created a side-effect with another.

Всякий раз, когда модуль реэкспортирует все экспорты (независимо от того, используются они или нет), которые необходимо оценить и выполнить, один из экспортов имеет побочные эффекты для других.

Честно до сих пор не понимаю. . Если вам интересно, посмотрите оригинальный ответ:what-does-webpack-4-expect-from-a-package-with-sideeffects-false

перевернутьофициальная документацияа такжеофициальный пример, я только что узнал об изменениях в бандле после sideEffects, но так и не могу объяснить разницу между webpack sideEffects и sideEffect в fp, и не могу объяснить, почему у vue явно много побочных эффектов, которые еще можно настроитьsideEffects: false ?

Председатель Мао учил нас: самостоятельности, достаточному питанию и одежде.

Сотрясение дерева и побочные эффекты

Предыстория Tree Shaking не будет представлена.Предположительно, многие знают, что функция Tree Shaking веб-пакета заключается в том, чтобы пометить неиспользуемые экспортированные элементы как неиспользуемые и больше не экспортировать их в модуль, который их реэкспортирует. Это слишком много, чтобы сказать, посмотрите на код:

// a.js
export function a() {}
// b.js
export function b(){}
// package/index.js
import a from './a'
import b from './b'
export { a, b }
// app.js
import {a} from 'package'
console.log(a)

Когда у нас есть app.js в качестве входа, код после встряхивания дерева станет таким:

// a.js
export function a() {}
// b.js 不再导出 function b(){}
function b() {}
// package/index.js 不再导出 b 模块
import a from './a'
import b from './b'
export { a }
// app.js
import {a} from 'package'
console.log(a)

После работы с подъемом и uglify в webpack следы модуля b будут полностью стерты.

Но если в модуль b добавить какие-то побочные эффекты, например простой лог:

// b.js
export function b(v) { reutrn v }
console.log(b(1))

После веб-пакета вы обнаружите, что содержимое модуля b становится таким:

// b.js
console.log(function (v){return v}(1))

Хотя экспорт модуля b игнорируется, код побочного эффекта сохраняется. Из-за побочных эффектов, вызванных различными странными операциями, которые могут быть введены после преобразования трансформатора тока (ссылка:Ваш Tree-Shaking бесполезен), много раз мы обнаружим, что даже при встряхивании дерева размер нашего пакета по-прежнему значительно не уменьшается. И обычно мы ожидаем, что, поскольку модуль b не используется, весь код в нем не должен быть импортирован.

На этом этапе вступает в игру роль побочных эффектов: если импортируемый пакет/модуль помечен какsideEffects: false, то независимо от того, действительно ли он имеет побочные эффекты или нет, пока на него нет ссылки, весь модуль/пакет будет полностью удален. кmobx-react-devtoolНапример, мы обычно используем это так:

import DevTools from 'mobx-react-devtools';

class MyApp extends React.Component {
  render() {
    return (
      <div>
        ...
        { process.env.NODE_ENV === 'production' ? null : <DevTools /> }
      </div>
    );
  }
}

Это очень распространенный сценарий импорта по требованию, но безsideEffects: falseПри настройке, даже еслиNODE_ENVустановлен вproduction, упакованный код по-прежнему будет содержатьmobx-react-devtoolspackage, хотя мы и не использовали его элементы экспорта, ноmobx-react-devtoolsЕго все равно будут импортировать, потому что он «может» иметь побочные эффекты. Но когда мы добавляем sideEffects false, встряхивание дерева может безопасно полностью удалить его из бандла.

Сценарии использования побочных эффектов

Как упоминалось выше, для пакетов, которые мы публикуем в npm, обычно сложно убедиться, что они содержат побочные эффекты (возможно, часть кода может бытьтрансформаторный горшок), но мы можем в основном гарантировать, что этот пакет повлияет на объекты вне пакета, например, изменить ли свойства окна, переопределить ли собственные методы объекта и т. д. Если мы можем гарантировать это, мы действительно можем знать, можно ли установить весь пакет.sideEffects: falseНу и неважно, действительно есть побочные эффекты или нет,Это приемлемо для веб-пакета. Это также объясняет, почему вы можете добавить vue, пакет, полный побочных эффектов.sideEffects: false.

Так что на самом деле в веб-пакетеsideEffects: falseДело не в том, что мой модуль действительно не имеет побочных эффектов, он просто сообщает веб-пакету при встряхивании дерева:Когда я разрабатывал этот пакет, я ожидал, что он не будет иметь побочных эффектов.Даже если он будет иметь побочные эффекты после завершения пакета, студенты, изучающие веб-пакет, могут быть уверены, что встряхивают дерево как пакет без побочных эффектов!.

Другими словами, пока ваш пакет не используется для таких вещей, как полифиллы или прокладки, не стесняйтесь добавлять их в него.sideEffects: falseБар!