«экспорт» или «импорт» ведут себя иначе при создании webpack, чем в режиме разработки

#javascript #vue.js #webpack

#javascript #vue.js #webpack

Вопрос:

Я пытаюсь понять, почему приложение (Vuejs3, webpack 5, Babel 7) ведет себя иначе при производстве, чем в режиме разработки. По какой-то причине в производственном режиме импорт и экспорт работают по-разному (т. Е. Файлы вообще не импортируются, т. Е. Их код не запускается во время импорта).

Это структура, которая работает в режиме разработки:

  - foo/
|  -- index.js
|     
|     export {default as Component} from './comp';
|     export {default as SomethingElse} from './comp2';
|
|  -- comp.vue
|
|     alert('hey there!');     
|     export default {...component here...}
|
 - main.js
   
   import './foo';

 

Это прекрасно работает в режиме разработки, но совсем не в производстве. Мне кажется, что код comp.vue никогда не выполняется, и, следовательно, компонент не импортируется / не регистрируется. Вместо этого я попытался использовать реэкспорт / агрегацию index.js , но это ничего не изменило.

Если я перейду main.js на import {Component} from './foo' , тогда все будет работать нормально. Однако import 'file' шаблон используется так часто, что мне было бы сложно его изменить (и он работает в режиме разработки).

Другой способ сделать эту работу — установить исходную карту в eval-cheap-source-map (вместо source-map ) в производстве, который является тем же методом исходной карты, который используется при разработке. И наоборот, если я изменю исходную карту на source-map в режиме разработки, компонент будет успешно загружен.

Это приводит меня к выводу, что webpack каким-то образом обрабатывает экспорт / импорт, отличающийся в производстве от разработки (наблюдение за исходной картой — это просто наблюдение, но стоит отметить). Я немного озадачен тем, почему это происходит, поэтому хотел бы оценить любой опыт, которым вы можете поделиться.

Примечание

Это может быть проблемой с некоторыми шагами оптимизации производственного режима. Есть ли какой-либо способ отключить их (все они, чтобы увидеть, является ли это общей проблемой, а затем отключить / повторно включить их части, чтобы найти «виновника»?)

Комментарии:

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

2. Я могу подтвердить, что это проблема. Я перешел optimization: {minimize: true, minimizer: [new TerserPlugin(), new CssMinimizerPlugin()]} на optimization: {minimize: false}} , и все работает нормально (за исключением огромных размеров файлов ;-)).

3. Интересный комментарий: «побочные эффекты». На самом деле я довольно часто использую этот шаблон для кода настройки в файлах. Он также используется для регистрации компонентов, что приятно, потому что он сохраняет процесс регистрации компонента внутри самого компонента (необходимо только импортировать файл). Но я вижу, как это может сбить с толку оптимизаторов кода. Можно ли настроить эту часть оптимизации (т. Е. Не исключать импорт — импортируется только требуемый код, так что это не должно быть проблемой с размером файла)?

4. webpack.js.org/guides/tree-shaking Не уверен, есть ли способ отметить побочные эффекты (при вызове регистрации) в самом файле

5. optimization: {sideEffects: ...} и optimization: {usedExports: ...} для любой комбинации значений не имеют никакого эффекта. Только удаление new TerserPlugin() из minimizer s позволяет избежать этого. То, как я читаю параметр побочных эффектов, также заключается в том, что по умолчанию этот импорт не удаляется, поэтому мне интересно, есть ли на самом деле что-то еще, поскольку встряхивание дерева для такого случая должно быть отключено по умолчанию (что имеет смысл, поскольку оно слишком агрессивно).).

Ответ №1:

После многих неудачных попыток исправить это в конфигурации webpack я пришел к этой конфигурации:

 optimization: {
    minimize: true,
    minimizer: [
      new CssMinimizerPlugin(),
      new TerserPlugin({
        terserOptions: {
          compress: {
            unused: false
          }
        }
      })
    ]
  },
 

unused (по умолчанию: true) — удаление функций и переменных без ссылок (простые прямые присвоения переменных не считаются ссылками, если не установлено значение «keep_assign»)

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