Размер и состав кеша
Согласованный пакет содержит несколько ответов. Когда таких глав станет много, автономная библиотека начнёт расходовать заметное место. Нельзя решить задачу только увеличением числовой константы. Нужно понимать, что именно сохраняется, какие файлы повторяются и какие данные можно восстановить из сети. Добавим понятный учёт состава и размера.
Количество страниц сайта не равно количеству копий на устройстве. ProfessorWeb может развиваться до большой библиотеки, а читатель сохранит один курс или несколько выбранных глав. Такой выбор должен быть явным. Массовая загрузка всех материалов без запроса пользователя увеличивает время, расход трафика и вероятность незавершённой подготовки, не обязательно улучшая чтение.
Два разных размера
Размер HTML, CSS и изображения в байтах помогает сравнить учебные пакеты. Общий расход браузерного хранилища origin включает дополнительные данные и служебные структуры. Эти величины не обязаны совпадать. Поэтому интерфейс должен говорить «размер тел сохранённых ответов», когда программа считает тела, и «оценка использования хранилища», когда обращается к Storage API.
Следующая полная функция assets/package-size.js получает имя кеша и описатель пакета. Она читает только перечисленные ответы, не делает сетевых запросов и не включает закладки IndexedDB. Отсутствие ресурса записывается отдельно. Такое измерение не становится проверкой наличия всей библиотеки автоматически.
export async function measurePackage(cacheName, plan) {
const cache = await caches.open(cacheName);
let bodyBytes = 0;
const missing = [];
const details = [];
for (const item of plan.resources) {
const response = await cache.match(item.url);
if (!response) {
missing.push(item.url);
continue;
}
const bytes = (await response.blob()).size;
bodyBytes += bytes;
details.push({url: item.url, bytes});
}
return {bodyBytes, missing, details};
}
Ожидаемый результат содержит сумму, подробность и список пропусков. Он не выдаёт отсутствие файла за нулевой полноценный ресурс. Читатель будущего отчёта сможет понять, получилась маленькая глава или неполный пакет. Сам Response, полученный через cache.match, используется здесь только для чтения тела; ответ, который одновременно возвращается странице и измеряется, потребует клонирования.
Blob.size отражает число байтов полученного тела. Значение Content-Length может относиться к передаваемому представлению и отсутствовать; сжатие и способ доставки тоже меняют его интерпретацию. Не заменяйте подсчёт тел произвольной суммой заголовков без проверки смысла. Blob.size.
Вымышленный расчёт
Для упражнения предположим HTML15000 байт, CSS6000 и SVG2400. Сумма равна23400 байтам. Это учебные числа, а не размер настоящих страниц ProfessorWeb. Если новый XML-пакет добавляет изображение120000 байт, его состав существенно меняется, хотя число HTML-страниц осталось прежним.
При нескольких главах общий CSS может встречаться в разных пакетах. Логическая сумма размеров каждой главы тогда считает общую зависимость повторно. Физическое устройство хранения и дедупликация браузера не обязаны следовать нашей таблице. Выберите конкретную метрику: размер автономного набора как списка уникальных URL или сумма самостоятельных пакетов. Для интерфейса курса обычно понятнее первый вариант.
Вместо вымышленного процента загрузки показывайте завершённые ресурсы и текущий шаг. Если заранее известны проверенные размеры, можно оценить общий объём, но это всё равно описание выбранного выпуска. При смене файла или отсутствии информации оценка пересчитывается. Количество завершённых глав нельзя выдавать за процент сохранённых байтов, когда изображения отличаются на порядок.
Мягкий бюджет
Редакция может установить собственный бюджет, например число байтов тел для выбранного курса. Это продуктовая политика, а не объявленная браузером квота. Перед подготовкой приложение сравнит ожидаемый размер с лимитом и предложит уменьшить набор. После подготовки фактическое чтение ответов позволит уточнить результат. Между этими шагами операция всё равно способна завершиться ошибкой.
Новый кандидат временно существует рядом со старым рабочим пакетом. Значит, свободного места должно хватить не только для окончательного набора, но и для перехода. Удаление старого до подготовки экономит пространство ценой возможности потерять рабочую копию. В нашем примере такой обмен не скрывается: если места мало, пользователь выбирает, какую необязательную копию убрать.
Для списка выбранных курсов полезно показать состав перед подтверждением. Человек видит главы и обязательные зависимости, снимает ненужные пункты и получает обновлённую оценку. Приложение не добавляет автоматически соседние материалы лишь потому, что они упомянуты в тексте. Обычная ссылка и согласие на загрузку остаются разными действиями.
Не удаляйте закладки ради загрузки изображения. HTML-пакет обычно можно получить заново; выбранное место продолжения может существовать только локально. Разные типы данных имеют разную ценность и политику очистки. Мы не превращаем все данные origin в одинаковую очередь файлов, которые можно без объяснения вытеснить.
Общая оценка origin
StorageManager.estimate возвращает приблизительные usage и quota. Она относится к origin и может включать разные хранилища. Поля способны быть недоступными, а результат изменяется со временем. Простая разность quota минус usage не является обещанием успешной следующей записи. StorageManager.estimate.
Для будущего интерфейса полезно показывать оценку отдельно от размеров выбранного курса. Например, «набор ответов: известная сумма; использование хранилища: приблизительное значение браузера». Такая подпись позволяет человеку понять две разные цифры. Точный показатель свободного места с десятичными знаками создавал бы ложное ощущение гарантии.
Операцию записи обязательно обрабатывайте через обычную ветку ошибки. Даже достаточная предварительная оценка не отменяет отказ. Другие вкладки могут записать данные, браузер может применить собственные ограничения, пользователь способен изменить состояние хранилища. Только завершённая запись позволяет обновить статус сохранения конкретного ресурса.
Состав важнее общего числа
Не все изображения нужны для основного объяснения. Редакционный договор может разделить обязательную схему и необязательное декоративное изображение. Тогда готовность пакета определяется обязательной частью, а интерфейс честно сообщает об отсутствии дополнительной. Нельзя задним числом назвать обязательный файл необязательным лишь потому, что его загрузка не удалась.
Такое решение принимается до подготовки и отражается в описателе. Базовый release.json сейчас содержит только обязательные ресурсы. Добавление категорий потребует изменения функции подготовки: она должна отдельно возвращать готовность и предупреждения, а не игнорировать каждую ошибку catch. Мы не считаем текущий модуль готовым к произвольной сложной схеме.
Выбор состава и мягкий бюджет делают автономную функцию управляемой. Читатель сохраняет нужные главы, редактор видит тяжёлые зависимости, а программа продолжает проверять каждый фактический результат. Следующий урок добавит данные, которые нельзя путать с загружаемыми ответами: локальные закладки и место продолжения чтения.