Webpack 2 - Кодирование отношений верхнего уровня
Финальное редактирование
Разрешение tl; dr заключается в том, что это невозможно. Хотя верхний ответ ниже содержит некоторую хорошую информацию.
Рассмотрим приведенный ниже код, от contacts.js
. Это динамически загруженный модуль, загружаемый по требованию с помощью System.import
в другом месте кода.
Если SharedUtil1
также используется в других модулях, которые также динамически загружаются с помощью System.import
, как бы я хотел иметь SharedUtility1
исключенный из all эти модули и загружались только по требованию в первый раз?
Верхний уровень System.import
SharedUtil1
не будет работать, так как мой экспорт зависит от него: экспорт может быть размещен только на верхнем уровне кода модуля, а не на любом обратном вызове.
Возможно ли это с помощью Webpack? Я на бета-версии 2.0.7.
import SharedUtil1 from '../../SharedUtilities/SharedUtility1';
class Contacts{
constructor(data){
this.data = data;
this.sharedUtil1 = new SharedUtil1();
}
}
export default Contacts;
ОБНОВЛЕНИЕ 1
Я думал, что загрузчик пакетов был тем, что я хотел, но нет, что превратит ваш импортированный модуль в другую функцию, которую вы вызываете с обратным вызовом чтобы перейти к фактическому модулю, как только он загрузится асинхронно. Это означает, что вы не можете прозрачно сделать модуль X загруженным асинхронно без внесения каких-либо изменений в свой код, не говоря уже о том, что вы вернулись к описанной проблеме, если ваш модуль верхнего уровня зависит от асинхронного загруженной зависимости, нет способа экспортировать ее, поскольку экспорт должен находиться на верхнем уровне.
Нет ли способа в Webpack указать, что зависимость X должна быть загружена по требованию, если это необходимо, и иметь какие-либо импортированные модули, которые импортируют ее для прозрачного ожидания процесса импорта? Я бы подумал, что этот случай использования будет синусоидальным для любого удаленного приложения, поэтому я должен думать, что я просто что-то пропустил.
ОБНОВЛЕНИЕ 2
В ответ на Питер я попытался получить работу по дедупликации, поскольку плагин commonChunk относится к коду обмена между конечными точками, как он упоминал, а так как require.ensure
помещает загруженный код в обратный вызов, тем самым предотвращая вас от ES6 export
с любым кодом, который зависит от него.
Что касается дедупликации, contacts.js
и tasks.js
загружают один и тот же sharedUtil, как, например,
import SharedUtil1 from '../../sharedUtilities/sharedUtility1';
Я попробовал запустить webpack как
webpack --optimize-dedupe
а также добавив
plugins: [
new webpack.optimize.DedupePlugin()
]
в webpack.config. В обоих случаях, хотя код sharedUtil по-прежнему помещается как в пакеты контактов, так и в задачи.
Ответы
Ответ 1
Прочитав сообщение в блоге, я наконец понял, что вы намеревались. Я немного смутился словом "зависимости верхнего уровня".
У вас есть два модуля (async-a
и async-b
), которые загружаются по требованию из любого места (здесь модуль main
), и оба имеют ссылку на общий модуль (shared
).
- - -> on-demand-loading (i. e. System.import)
---> sync loading (i. e. import)
main - - -> async-a ---> shared
main - - -> async-b ---> shared
По умолчанию webpack создает дерево фрагментов следующим образом:
---> chunk uses other chunk (child-parent-relationship)
entry chunk [main] ---> on-demand chunk 1 [async-a, shared]
entry chunk [main] ---> on-demand chunk 2 [async-b, shared]
Это нормально, если shared
< async-a/b
или вероятность того, что async-a
и async-b
используются как одним и тем же пользователем, являются низкими. Это по умолчанию, потому что это простейшее поведение и, вероятно, то, что вы ожидаете: один System.import
= > один кусок. По-моему, это также самый распространенный случай.
Но если shared
>= async-a/b
и вероятность того, что пользователь async-a
и async-b
загружен пользователем, высока, существует более эффективная опция chunking: (немного трудно визуализировать):
entry chunk [main] ---> on-demand chunk 1 [async-a]
entry chunk [main] ---> on-demand chunk 2 [async-b]
entry chunk [main] ---> on-demand chunk 3 [shared]
When main requests async-a: chunk 1 and 3 is loaded in parallel
When main requests async-b: chunk 2 and 3 is loaded in parallel
(chunks are only loaded if not already loaded)
Это не поведение по умолчанию, но есть плагин для его архивации: CommonChunkPlugin
в асинхронном режиме. Он находит общие/разделяемые модули в кучу кусков и создает новые куски, которые включают совместно используемые модули. В асинхронном режиме он загружает новый фрагмент параллельно исходным (но теперь меньшим) фрагментам.
new CommonsChunkPlugin({
async: true
})
// This does: (pseudo code)
foreach chunk in application.chunks
var shared = getSharedModules(chunks: chunk.children, options)
if shared.length > 0
var commonsChunk = new Chunk(modules: shared, parent: chunk)
foreach child in chunk.children where child.containsAny(shared)
child.removeAll(shared)
foreach dependency in chunk.getAsyncDepenendenciesTo(child)
dependeny.addChunk(commonsChunk)
Имейте в виду, что CommonsChunkPlugin имеет параметр minChunks
для определения, когда модуль имеет резьбу в качестве shared
(не стесняйтесь предоставлять настраиваемую функцию для выбора модулей).
Вот пример, который подробно объясняет настройку и вывод: https://github.com/webpack/webpack/tree/master/examples/extra-async-chunk
И еще один вариант с большей конфигурацией: https://github.com/webpack/webpack/tree/master/examples/extra-async-chunk-advanced
Ответ 2
Если я понял вас правильно, вы хотите, чтобы одна и та же зависимость загружалась несколько раз, когда разные куски кода объявляли ее как зависимость.
Да, это возможно; как это сделать, зависит как от контекста в вашем приложении, так и от ES6 или ES5.
ECMA Script 5
Webpack 1 был построен в ECMA Script 5 и обычно использует синтаксис CommonJS или RequireJS для экспорта и импорта модулей. При использовании этого синтаксиса для предотвращения дублирования кода можно использовать следующие функции:
- Дедупликация предотвращает включение дублированных файлов в скомпилированные
кода путем создания копий дублирующих функций вместо
переопределяя их.
- Именованные фрагменты позволяют объявлять куски как зависимости, но не сразу оцениваются; все вхождения одного и того же фрагмента будут использовать один и тот же экземпляр.
- CommonsChunkPlugin позволяет обменивать кусок в нескольких точках ввода (применяется только к нескольким страницам страниц).
дедупликации
Из документации веб-пакета:
Если вы используете некоторые библиотеки с крутыми деревьями зависимостей, это может произойти что некоторые файлы идентичны. Webpack может найти эти файлы и дедуплицировать их. Это предотвращает включение дублирующего кода в ваш пакет и вместо этого применяет копию функции во время выполнения. Это не влияет на семантику.
акцент мой, а не источник
Как описано в документации, разделение кода остается неизменным; каждый модуль, которому требуется sharedUtil1
, должен объявить require
как обычно. Чтобы предотвратить загрузку одной и той же зависимости несколько раз, включен параметр веб-пакета, который заставляет webpack явно проверять файлы для дублирования, прежде чем включать их во время выполнения.
Этот параметр включен с помощью
--optimize-dedupe
соответственно. new webpack.optimize.DedupePlugin()
Именованные фрагменты
Из документации по веб-загрузке:
Функция require.ensure
принимает дополнительный третий параметр. Эта должен быть строкой. Если две точки разделения проходят одну и ту же строку, они используют тот же кусок... require.include
может быть полезна, если модуль находится в нескольких дочерних кусках. A require.include
в родительском объекте будет включать модуль и экземпляры модулей в дочерних кусках исчезнут.
Короче говоря, загрузка модулей задерживается до конца при компиляции. Это позволяет удалять повторяющиеся определения до их включения. В документации приведены примеры.
Плагин Common Chunk
Из документации по веб-папке:
CommonsChunkPlugin
может перемещать модули, которые встречаются в нескольких входах куски к новому блоку ввода (кусок общего пользования). Время выполнения перемещено к общему достоянию. Это означает, что старые входные фрагменты являются исходными теперь куски.
Это очень специфично для разделения кусков между несколькими страницами, это не имеет отношения к другим обстоятельствам.
ECMA Script 6
Поддержка расширенных функций импорта модулей - это... работа продолжается. Чтобы понять, где это происходит, см. Следующие ссылки:
Здесь хорошее резюме модулей ES6 и webpack: Модули ES6 с TypeScript и Webpack
Вышеуказанная информация, скорее всего, быстро устареет.
Предложение
Для вашего собственного здравомыслия я предлагаю:
Если оптимизация имеет значение:
Вернитесь к синтаксису CommonJS/RequireJS и обновите его до ECMA Script 6, когда Webpack 2 стабилен и выпущен.
Если синтаксис ECMA Script 6:
Используйте стандартный формат экспорта импорта ECMA Script 6 и добавьте функции оптимизации по мере их появления.
Существует слишком много потоков, чтобы попытаться использовать дополнительные функции загрузки модулей в неустойчивом веб-пакете с порогом. Подождите, пока все опустится, а некоторые действительно хорошие плагины станут доступны даже после его попытки.
Ответ 3
Для создателя Webpack это невозможно. Легко и просто. См. Ответ Peter для получения дополнительной информации о Webpack и ES6.
Вставное изображение было результатом недоразумения. См. Тот же ответ пользователя выше.
![введите описание изображения здесь]()
Ответ 4
System.import
устарел в Webpack. Webpack теперь поддерживает import()
, для которого требуется polyfill для promises.
Разделение кода - с помощью импорта()