Принудительная перезагрузка при асинхронном импорте Webpack

В настоящее время я работаю над рефакторингом большой устаревшей кодовой базы только для jquery в одностраничное приложение vue. При этом я надеюсь разделить свою работу на управляемые фрагменты, сохраняя большую часть устаревшей кодовой базы как есть в коде и постепенно извлекая из нее части и части для рефакторинга для vue, используя шину событий в качестве посредник.

Однако у меня возникают проблемы, потому что устаревший код имеет побочные эффекты при импорте. Эти побочные эффекты вызваны тем, что событие jquery во время выполнения привязано к HTML, а создаваемые объекты и экземпляры классов окружают другой HTML, поскольку он устанавливает состояние сразу при импорте. Это вызывает проблему с рефакторингом SPA, так как я хочу иметь возможность перейти со страницы, а затем вернуться к ней, но javascript останется в кэше и не перезагрузится, теперь отсутствуют все обновления HTML и состояния, поскольку vue удалит html состояние было создано, а затем добавить новый html при повторном рендеринге.

Я ищу лучшее решение этой проблемы, чтобы мне не приходилось дважды рефакторить код — один раз в модульный импорт с вызовами инициализации, а затем в реактивную модульную парадигму vue. Для этого я хотел бы выяснить, как использовать асинхронный импорт чанков Webpack для перезагрузки блока кода. Я знаю, что это возможно из-за горячей перезагрузки файла webpack. По сути, я хочу принудительно выполнить горячую перезагрузку определенного импорта при доступе к определенному маршруту.

Вот что я пытаюсь сделать:

async function reloadLegacyCodeOnSPARoutingChange(){
    cleanAnyPolutingGlobals();
    const initLegacyCode = await import(`./LegacyCode.js`); //somehow force it to reload this as if it were a fresh import
    let thingId = this.$store.state.thingPage.thingId;
    await initLegacyCode(thingId);
    await EventBus.$emit('initLegacyCodeState'); //apply the properties from our reactive state system
}

Есть ли эффективный способ сделать это от клиента?


person John Kulp    schedule 30.01.2019    source источник


Ответы (2)


Вы можете динамически импортировать модуль и удалить его из кеша, если флаг useFresh равен true.

async function getFile (useFresh) {
    try {
        useFresh && delete require.cache[require.resolve('./Test')];
    } catch (err) { }
    let newModule = await require('./Test');
}

Примечание. Если вы используете export default в файле, который вы динамически импортируете, вам придется использовать newModule.default для доступа к его объектам.

person varun agarwal    schedule 14.02.2019
comment
Звучит многообещающе! Раньше я пытался возиться с кешем require.resolve, но я попробую еще раз, используя await require, а не функцию асинхронного импорта webpack, хотя я не знаю, являются ли они одной и той же функциональностью с другим синтаксисом. - person John Kulp; 14.02.2019
comment
Они более или менее одинаковы с разным синтаксисом. webpack.js.org/api/module-methods/#commonjs - person varun agarwal; 15.02.2019
comment
Я чувствую, что этот подход должен работать, но мы усердно работали над ним, и, похоже, он просто не перезагружается, хотя кажется, что должен. Спасибо за помощь! - person John Kulp; 15.02.2019

Горячая замена модуля (HMR) не является какой-то черной магией (хотя я так думал). Представьте себе архитектуру клиент/сервер, в которой клиент (ваше приложение) запрашивает сервер (Webpack с включенным HMR), есть ли какие-либо изменения в модуле, который вы пытаетесь импортировать. Если это так, он перезагружает модуль.

// Add this to the file you are initially loading
if (module.hot) {
  module.hot.accept('./LegacyCode.js', async function() {
    console.log('Accepting the updated LegacyCode.js module!');
    let thingId = this.$store.state.thingPage.thingId;
    await initLegacyCode(thingId);
    await EventBus.$emit('initLegacyCodeState');
  })
} 

На сайте webpack есть отличное руководство о том, как работает HMR и как для начала

ПРИМЕЧАНИЕ: AFAICT ваш устаревший код генерирует побочные эффекты при загрузке (например, он портит глобальное состояние). Я был бы очень осторожен с этим, поскольку горячая перезагрузка лучше всего работает, когда модули импортируются детерминированным образом.

person Kostas Pelelis    schedule 11.02.2019
comment
Проблема здесь в том, что у webpack, похоже, нет документации о том, как сказать, что модуль изменился, даже если это не так. Я просмотрел там документацию, но не нашел способа запросить новую копию с сервера. Я просто пропустил что-то прямое с этим? - person John Kulp; 11.02.2019
comment
Что касается побочных эффектов, я уже учел сброс глобального состояния. Причина, по которой эта горячая перезагрузка важна, заключается в том, чтобы быстро исправить модульность этих побочных эффектов для перезапуска в нужное время. - person John Kulp; 11.02.2019
comment
Сервер разработки (теоретически) отслеживает ваши файлы на наличие изменений, поэтому он должен определить, когда модуль изменился. Можете ли вы предоставить конфигурацию вашего веб-пакета? - person Kostas Pelelis; 12.02.2019
comment
Это опять же не то, что я пытаюсь сделать. Я не хочу перезагружать файл при изменении модуля. Я хочу перезагрузить файл, чтобы повторно запустить побочные эффекты javascript без серьезного рефакторинга. Я хочу сделать это, когда клиент идет по определенному маршруту, каждый раз, когда он это делает. Не тогда, когда что-то происходит на сервере. Я хочу горячую перезагрузку, но для производственного использования в повторной загрузке скриптов для повторного запуска, а не для реакции на измененные файлы на сервере. - person John Kulp; 12.02.2019