Что ожидает Webpack 4 от пакета с побочными эффектами: false
Webpack 4 добавил новую функцию: теперь он поддерживает тег sideEffects
флаг в package.json
модули это связывать.
за последние 30 дней мы тесно сотрудничали с каждым из фреймворков, чтобы гарантировать, что они готовы поддерживать webpack 4 в своих соответствующих cli и т. д. Даже популярные библиотеки, такие как lodash-es, RxJS поддерживают флаг sideEffects, поэтому, используя их последнюю версию, вы будет видеть мгновенный размер пакета уменьшается из коробки.
"побочные эффекты": ложный флаг в пакете big-module.json указывает, что модули пакета не имеют побочных эффектов (при оценке) и предоставляют только экспорт. Это позволяет таким инструментам, как webpack, оптимизировать реэкспорт.
хотя вторая ссылка показывает результаты использования флага, она четко не объясняет, что представляет собой побочный эффект. ES6 включает концепцию побочных эффектов для модулей, как описано здесь, но как это связано с тем, что Webpack считает побочными эффектами.
в контексте sideEffects
флаг, что нужно модулю, чтобы избежать использования sideEffects:false
без проблем или, наоборот, что должен делать модуль, чтобы использовать sideEffects:false
без проблем.
для полноты, несмотря на твердый ответ @SeanLarkin ниже, я хотел бы получить разъяснения по поводу следующий:
очевидно, побочные эффекты означают что-то конкретное в fp и включают ведение журнала (консоль или в другом месте) и выброс ошибок. Я предполагаю, что в этом контексте они вполне приемлемы?
может ли модуль содержать круговые ссылки и по-прежнему использовать
sideEffects: false
?есть ли способ проверить или что модуль может проверить, что модуль может
sideEffects: false
помимо попыток отслеживать ошибки вызвано его неправильным использованием?есть ли какие-либо другие факторы, которые помешали бы модулю использовать
sideEffects: false
?
2 ответов
Шон из команды webpack! Я сделаю все возможное вместо того, чтобы наша документация все еще продолжается, чтобы ответить на ваш вопрос здесь!
согласно спецификации модуля ECMA (я не собираюсь пытаться найти ссылку, поэтому вам придется доверять мне здесь, потому что ее похоронили),
каждый раз, когда модуль ре-экспорта весь экспорт (независимо от того, используется или не используется) должен быть оценен и выполнен в случае, если один из этих экспорта создал побочный эффект с другим.
например, я создал небольшой сценарий с фотографией, чтобы лучше визуализировать случай:
на этой фотографии мы видим, что 3 отдельных модуля с одним импортом импортируются в один модуль, который затем принимает экспорт по умолчанию и ре-экспорта их из этого модуля:
вы можете видеть здесь, что ни один из реэкспортов не осуществляется друг другом, поэтому (если webpack был дан сигнал), мы могли бы опустить экспорт b
и c
от даже трассировки или использования (размер и время сборки преимущества производительности).
однако в данном случае мы видим, что экспорт c
"осуществляется" локальными изменениями состояния, потому что он переназначается на суммирование b
и a
. Поэтому (именно поэтому спецификация призывает к этому), нам нужно будет включить оба b
и a
и любой из его зависимостей в пакете.
мы выбрали "sideEffects: false" как способ сэкономить время компиляции и размер сборки, потому что это позволяет нам мгновенно обрезать (явно) экспорт, который разработчики/авторы библиотеки знают, свободны от побочных эффектов (за счет свойства в пакете.json, или еще 2-3 строки конфигурации).
хотя технически этот пример очень примитивен, когда вы начинаете иметь дело с фреймворками или библиотеками, которые повторно экспортируют кучу модулей до более высокого уровня для разработчика Опыт (Три.js, Angular, lodash-es и т. д.), то прирост производительности значителен, когда (если они являются sideEffect Free module exports) вы помечаете их таким образом.
Дополнительные Разъяснения:
- очевидно, что побочные эффекты означают что-то конкретное в fp и включают ведение журнала (консоль или в другом месте) и выбрасывание ошибок. Я предполагаю, что в этом контексте они вполне приемлемы?
в случай, который это пытается решить, да. До тех пор, пока эффекты, созданные против экспорта модулей, не будут реализованы другими, что приведет к недопустимости обрезки.
- может ли модуль содержать круговые ссылки и по-прежнему использовать
sideEffects: false?
это должно, теоретически.
- есть ли способ проверить или что модуль способен использовать
sideEffects: false
за попыткой отслеживать ошибки, вызванные его злоупотребление?
не то, что я знаю, однако это был бы отличный инструмент.
- есть ли какие-либо другие факторы, которые помешали бы модулю использовать
sideEffects: false
?
если свойство не находится в package.json
или определена в module.rules
или mode: production
не установлен (что использует оптимизацию).
этой sideEffects
настройка очень расплывчата и недостаточно описана в документах. Документы в основном как "там sideEffects
флаг для модулей свободных всех побочных эффектов".
сошлись на том, что "не имеет противопоказания" фраза может быть decyphered как "не разговаривать с внешнего модуля на высшем уровне".
мое текущее понимание заключается в том, что этот sideEffects
флаг предназначен только для "реэкспорта", а "реэкспорт":
export { a } from './lib/a'
export { b } from './lib/b'
где-то в <npm-package>/index.js
(или любой другой файл внутри <npm-package>
).
если Webpack обнаруживает, что приложение импортирует только a
С <npm-package>
, и не импортирует b
в любом месте, то Webpack может просто бросить export { b } from './lib/b'
строку с <npm-package>/index.js
в результате не включая
'./lib/b.js'
файл в результирующем пакете (что делает его меньше на размер ).
теперь, если './lib/b.js'
были некоторые строки верхнего уровня кода, делающие некоторые "побочные эффекты", т. е. если './lib/b.js'
что-то сделал например:
window.jQuery = ...
if (!global.Set) global.Set = require('babel-polyfill').Set
new XmlHttpRequest().post('/analytics', data)
затем './lib/b.js'
было бы сказано, что имеют "побочные эффекты", потому что его код верхнего уровня (который выполняется при import './lib/b'
) влияет на что-то за пределами .
в то же время, как './lib/b.js'
код верхнего уровня не выходит за пределы этого *.js
файл, то он не имеет никаких "побочных эффектов":
let a = 1
a = a + 1 + computeSomeValue()
export default a
export const b = a + 1
export const c = b + 1
это все не "побочные эффекты".
и есть окончательный gotcha: если пакет npm имеет любой *.css
файлы, которые пользователь может import
потом эти *.css
файлы будут все "побочные эффекты", потому что:
import 'npm-package/style.css'
не имеет переменной, назначенной этому import
что фактически означает ,что" этот импортированный модуль не используется нигде в приложении " для Webpack. И поэтому Webpack просто отбрасывает 'npm-package/style.css'
файл из пакета как часть процесса "встряхивания дерева", если npm-package
есть sideEffects: false
флаг. Итак, вместо того, чтобы писать sideEffects: false
всегда пишу "sideEffects": ["*.css"]
. Даже если ваш пакет npm не экспортирует файлы CSS, он может сделать это в будущем, и это защитит от вышеупомянутой ошибки "файл CSS не включен".