Почему клиент не получает новые версии этого скрипта в общей папке?

В моем проекте есть общая папка и скрипт внутри нее: public/worker.js, который содержит кусок кода:

alert('foo');

Я называю этот скрипт с помощью Worker:

new Worker('worker.js');

Я запускаю Meteor и подключаюсь к своему приложению. foo предупрежден.
Если я изменю public/worker.js код для чего-либо еще:

alert('bar');

Сервер обновляет клиентов, клиент обновляет страницу, но не получает новый код, а использует старый (оповещение foo вместо новой блестящей bar). Очистка кэша с последующим обновлением устраняет проблему. CTRL+F5 не решает эту проблему с кешем, похоже, он не работает для такого вызова скрипта (по крайней мере, не в той версии Firefox, с которой я его тестировал).

Почему именно это происходит?
Как я могу предотвратить это?

3 ответа

Решение

Сценарий кэшируется, и браузер не извлекает новую версию с сервера.

Нам нужно отредактировать заголовок запросов на файлы в /workers папку, используя следующий код на стороне сервера (я завернул его в пакет с api.use('webapp')):

WebApp.rawConnectHandlers.use('/workers', function(req, res, next) {
  res.setHeader('cache-control', 'must-revalidate');
  next();
});

С помощью WebApp.connectHandlers не работал, обратный вызов никогда не вызывался, поэтому я использовал rawConnectHandlers вместо.

Я не уверен на 100%, что это лучший путь, но он работает.

Вы должны изменить заголовок ответа для файла. Возможно, это поможет вам: Явные HTTP-заголовки ответа для файлов в общедоступном каталоге Meteor.

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

Я исправил это так, что во время сборки я включаю номер версии / время сборки / md5 содержимого файла в имя файла, так что в итоге получится что-то вроде worker.12333.js, Преимущество этого состоит в том, что если каждое имя файла ссылается на файл, который по существу неизменен, вы можете установить заголовки с истекшим сроком давности в будущем... Таким образом, вместо того, чтобы указывать браузеру никогда не кэшировать рабочий скрипт, он может кэшировать его навсегда. https://github.com/felthy/grunt-cachebuster - один из таких инструментов, который делает это для Javascript, включенного через теги сценария, но, вероятно, есть и другие.

Проблема с этим заключается в том, что должен быть какой-то механизм, чтобы сообщить Javascript обновленное имя файла, чтобы он знал, для вызова new Worker('worker.12333.js');, Я не уверен, что существующие доступные инструменты справятся с этим, но я просто использую время сборки проекта в секундах в качестве уникального ключа для всех файлов.

<html build-time="12333">
  ...

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

Другие вопросы по тегам