В этом исследовании рассматривается, как некоммерческая организация Kiwix использует технологию Progressive Web App и API File System Access, чтобы пользователи могли загружать и хранить большие интернет-архивы для использования в автономном режиме. Узнайте о технической реализации кода, работающего с Origin Private File System (OPFS), новой функцией браузера в Kiwix PWA, которая улучшает управление файлами, предоставляя улучшенный доступ к архивам без запросов на разрешение. В статье обсуждаются проблемы и освещаются потенциальные будущие разработки в этой новой файловой системе.
О Кивиксе
По данным Международного союза электросвязи, спустя более 30 лет после рождения Интернета треть населения мира все еще ждет надежного доступа к Интернету . На этом история заканчивается? Конечно, нет. Ребята из Kiwix , некоммерческой организации из Швейцарии, разработали экосистему приложений и контента с открытым исходным кодом, которая направлена на то, чтобы сделать знания доступными для людей с ограниченным или отсутствующим доступом к Интернету. Их идея заключается в том, что если вы не можете легко получить доступ к Интернету, то кто-то может загрузить для вас ключевые ресурсы, где и когда подключение будет доступно, и сохранить их локально для последующего использования в автономном режиме. Многие важные сайты, например, Wikipedia, Project Gutenberg, Stack Exchange или даже выступления TED, теперь можно преобразовать в архивы с высокой степенью сжатия, называемые файлами ZIM, и читать их на лету браузером Kiwix.
Архивы ZIM используют высокоэффективное сжатие Zstandard (ZSTD) (более старые версии использовали XZ ), в основном для хранения HTML, JavaScript и CSS, в то время как изображения обычно преобразуются в сжатый формат WebP . Каждый ZIM также включает URL и индекс заголовка. Сжатие здесь является ключевым моментом, так как вся Википедия на английском языке (6,4 миллиона статей, плюс изображения) сжимается до 97 ГБ после преобразования в формат ZIM, что кажется большим объемом, пока вы не поймете, что сумма всех человеческих знаний теперь может поместиться на телефоне Android среднего класса. Также предлагается множество более мелких ресурсов, включая тематические версии Википедии, такие как математика, медицина и так далее.
Kiwix предлагает ряд собственных приложений, ориентированных на использование на настольных компьютерах (Windows/Linux/macOS), а также на мобильных устройствах (iOS/Android). Однако в этом исследовании основное внимание будет уделено Progressive Web App (PWA) , которое стремится стать универсальным и простым решением для любого устройства с современным браузером.
Мы рассмотрим проблемы, возникающие при разработке универсального веб-приложения, которое должно обеспечивать быстрый доступ к большим архивам контента полностью в автономном режиме, а также некоторые современные API JavaScript, в частности API доступа к файловой системе и Origin Private File System , которые предлагают инновационные и интересные решения этих проблем.
Веб-приложение для использования офлайн?
Пользователи Kiwix — это разношерстная группа с множеством различных потребностей, и Kiwix практически не контролирует устройства и операционные системы, на которых они будут получать доступ к своему контенту. Некоторые из этих устройств могут быть медленными или устаревшими, особенно в регионах с низким уровнем дохода. Хотя Kiwix пытается охватить как можно больше вариантов использования, организация также поняла, что может охватить еще больше пользователей, используя самое универсальное программное обеспечение на любом устройстве: веб-браузер. Поэтому, вдохновленные законом Этвуда , который гласит, что любое приложение, которое может быть написано на JavaScript, в конечном итоге будет написано на JavaScript , некоторые разработчики Kiwix около 10 лет назад приступили к портированию программного обеспечения Kiwix с C++ на JavaScript.
Первая версия этого порта, названная Kiwix HTML5, была для ныне несуществующей Firefox OS и для расширений браузера. В его основе был (и есть) механизм декомпрессии C++ (XZ и ZSTD), скомпилированный в промежуточный язык JavaScript ASM.js, а позже Wasm или WebAssembly , с использованием компилятора Emscripten . Позднее переименованные в Kiwix JS , расширения браузера все еще активно разрабатываются.
Встречайте Progressive Web App (PWA). Осознавая потенциал этой технологии, разработчики Kiwix создали специальную версию PWA Kiwix JS и приступили к добавлению интеграций ОС , которые позволили бы приложению предлагать возможности, аналогичные нативным, особенно в областях автономного использования, установки, обработки файлов и доступа к файловой системе.
Оффлайн-первичные PWA чрезвычайно легкие, поэтому идеально подходят для контекстов с прерывистым или дорогим мобильным Интернетом. Технология, лежащая в основе этого, — API Service Worker и связанный с ним API Cache , используемый всеми приложениями на основе Kiwix JS. Эти API позволяют приложениям выступать в качестве сервера, перехватывая запросы Fetch из основного просматриваемого документа или статьи и перенаправляя их на бэкэнд (JS) для извлечения и построения ответа из архива ZIM.
Хранение, хранение везде
Учитывая большой размер архивов ZIM, хранение и доступ к ним, особенно на мобильных устройствах, вероятно, является самой большой головной болью для разработчиков Kiwix. Многие конечные пользователи Kiwix загружают контент в приложении, когда доступен Интернет, для последующего использования в автономном режиме. Другие пользователи загружают на ПК с помощью торрента, а затем переносят на мобильное устройство или планшет, а некоторые обмениваются контентом на USB-накопителях или портативных жестких дисках в районах с нестабильным или дорогим мобильным Интернетом. Все эти способы доступа к контенту из произвольных доступных пользователю мест должны поддерживаться Kiwix JS и Kiwix PWA.
Первоначально Kiwix JS мог читать огромные архивы, сотни ГБ ( один из наших архивов ZIM — 166 ГБ!) даже на устройствах с небольшим объемом памяти, с помощью File API . Этот API поддерживается всеми браузерами, даже очень старыми , и поэтому он действует как универсальный резервный вариант, когда новые API не поддерживаются. Это так же просто, как определить элемент input
в HTML, в случае Kiwix:
<input
type="file"
accept="application/octet-stream,.zim,.zimaa,.zimab,.zimac, ..."
value="Select folder with ZIM files"
id="archiveFilesLegacy"
multiple
/>
После выбора элемент ввода содержит объекты File, которые по сути являются метаданными, ссылающимися на базовые данные в хранилище. Технически, объектно-ориентированный бэкенд Kiwix, написанный на чистом клиентском JavaScript, считывает небольшие фрагменты большого архива по мере необходимости. Если эти фрагменты необходимо распаковать, бэкенд передает их распаковщику Wasm, получая дополнительные фрагменты по запросу, пока не будет распакован полный блок данных (обычно статья или актив). Это означает, что большой архив никогда не придется полностью считывать в память.
Несмотря на свою универсальность, API файлов имеет недостаток, из-за которого приложения Kiwix JS выглядят неуклюжими и старомодными по сравнению с нативными приложениями: он требует от пользователя выбирать архивы с помощью средства выбора файлов или перетаскивать файл в приложение каждый раз при его запуске , поскольку с помощью этого API невозможно сохранять разрешения на доступ от одного сеанса к другому.
Чтобы смягчить этот плохой UX, как и многие разработчики, разработчики Kiwix JS изначально пошли по пути Electron. ElectronJS — это удивительный фреймворк, который предоставляет мощные функции, включая полный доступ к файловой системе с использованием API Node. Однако у него есть некоторые хорошо известные недостатки:
- Работает только на настольных операционных системах.
- Он большой и тяжелый (70–100 МБ).
Размер приложений Electron, в связи с тем, что в каждое приложение включена полная копия Chromium, очень невыгодно сравнивать с размером минимизированного и упакованного PWA , который составляет всего 5,1 МБ !
Итак, мог ли Kiwix как-то улучшить ситуацию для пользователей PWA?
API доступа к файловой системе спешит на помощь
Около 2019 года Kiwix узнал о появлении API, которое проходило первоначальное тестирование в Chrome 78, тогда оно называлось Native File System API . Оно обещало возможность получить дескриптор файла для файла или папки и сохранить его в базе данных IndexedDB. Что особенно важно, этот дескриптор сохраняется между сеансами приложения, поэтому пользователю не приходится снова выбирать файл или папку при повторном запуске приложения (хотя ему приходится отвечать на быстрый запрос разрешения). К тому времени, как оно достигло производства, оно было переименовано в File System Access API , а основные части были стандартизированы WHATWG как File System API (FSA).
Итак, как работает часть API File System Access ? Несколько важных моментов, на которые следует обратить внимание:
- Это асинхронный API (за исключением специализированных функций в Web Workers).
- Средства выбора файлов или каталогов должны запускаться программно путем захвата жеста пользователя (щелчка или нажатия на элемент пользовательского интерфейса).
- Чтобы пользователь снова дал разрешение на доступ к ранее выбранному файлу (в новом сеансе), также необходим жест пользователя — фактически браузер откажется показывать запрос на разрешение, если он не инициирован жестом пользователя.
Код относительно прост, за исключением необходимости использовать неуклюжий API IndexedDB для хранения файлов и дескрипторов каталогов. Хорошей новостью является то, что есть пара библиотек, которые делают большую часть тяжелой работы за вас, например, browser-fs-access . В Kiwix JS мы решили работать напрямую с API, которые очень хорошо документированы.
Открытие выбора файлов и каталогов
Открытие окна выбора файлов выглядит примерно так (здесь используются Promises, но если вы предпочитаете сахар async/await
, см. руководство Chrome для разработчиков ):
return window
.showOpenFilePicker({ multiple: false })
.then(function (fileHandles) {
return processFileHandle(fileHandles[0]);
})
.catch(function (err) {
// This is normal if app is launching
console.warn(
'User cancelled, or cannot access fs without user gesture',
err,
);
});
Обратите внимание, что для простоты этот код обрабатывает только первый выбранный файл (и запрещает выбирать более одного). Если вы хотите разрешить выбор нескольких файлов с помощью { multiple: true }
, вы просто обертываете все Promises, которые обрабатывают каждый дескриптор, в оператор Promise.all().then(...)
, например:
let promisesForFiles = fileHandles.map(function (fileHandle) {
return processFileHandle(fileHandle);
});
return Promise.all(promisesForFiles).then(function (arrayOfFiles) {
// Do something with the files array
console.log(arrayOfFiles);
}).catch(function (err) {
// Handle any errors that occurred during processing
console.error('Error processing file handles!', err);
)};
Однако, выбор нескольких файлов, возможно, лучше сделать, попросив пользователя выбрать каталог, содержащий эти файлы, а не отдельные файлы в нем, особенно с учетом того, что пользователи Kiwix склонны организовывать все свои файлы ZIM в одном каталоге. Код для запуска выбора каталога почти такой же, как и выше, за исключением того, что вы используете window.showDirectoryPicker.then(function (dirHandle) { … });
.
Обработка дескриптора файла или каталога
Получив дескриптор, его необходимо обработать, поэтому функция processFileHandle
может выглядеть следующим образом:
function processFileHandle(fileHandle) {
// Serialize fileHandle to indexedDB
serializeFSHandletoIdxDB('pickedFSHandle', fileHandle, function (val) {
console.debug('IndexedDB responded with ' + val);
});
return fileHandle.getFile().then(function (file) {
// Do something with the file
return file;
});
}
Обратите внимание, что вам нужно предоставить функцию для хранения дескриптора файла , для этого нет удобных методов, если только вы не используете библиотеку абстракций. Реализацию этого в Kiwix можно увидеть в файле cache.js
, но ее можно значительно упростить, если использовать ее только для хранения и извлечения дескриптора файла или папки.
Обработка каталогов немного сложнее, поскольку вам нужно перебрать записи в выбранном каталоге с помощью async entries.next()
чтобы найти нужные вам файлы или типы файлов. Есть разные способы сделать это, но вот код, используемый в Kiwix PWA, в общих чертах:
let iterableEntryList = dirHandle.entries();
return iterateAsyncDirEntries(iterableEntryList, []).then(function (entryList) {
// Do something with the entry list
return entryList;
});
/**
* Iterates FileSystemDirectoryHandle iterator and adds entries to an array
* @param {Iterator} entries An asynchronous iterator of entries
* @param {Array} archives An array to which to add the entries (may be empty)
* @return {Promise<Array>} A Promise for an array of entries in the directory
*/
function iterateAsyncDirEntries(entries, archives) {
return entries
.next()
.then(function (result) {
if (!result.done) {
let entry = result.value[1];
// Filter for the files you want
if (/\.zim(\w\w)?$/i.test(entry.name)) {
archives.push(entry);
}
return iterateAsyncDirEntryArray(entries, archives);
} else {
// We've processed all the entries
if (!archives.length) {
console.warn('No archives found in the picked directory!');
}
return archives;
}
})
.catch(function (err) {
console.error('There was an error processing the directory!', err);
});
}
Обратите внимание, что для каждой записи в entryList
вам позже понадобится получить файл с помощью entry.getFile().then(function (file) { … })
когда вам понадобится его использовать, или эквивалентно с помощью const file = await entry.getFile()
в async function
.
Можем ли мы пойти дальше?
Требование к пользователю предоставить разрешение , инициированное жестом пользователя при последующих запусках приложения, добавляет немного трения к (повторному) открытию файлов и папок, но это все равно гораздо более плавно, чем необходимость повторно выбирать файл. Разработчики Chromium в настоящее время завершают работу над кодом , который позволит сохранять разрешения для установленных PWA. Это то, чего требовали многие разработчики PWA, и чего с нетерпением ждут.
Но что, если нам не придется ждать?! Разработчики Kiwix недавно обнаружили, что можно устранить все запросы на разрешения прямо сейчас, используя блестящую новую функцию API доступа к файлам, которая поддерживается браузерами Chromium и Firefox (и частично поддерживается Safari, но все еще отсутствует FileSystemWritableFileStream
). Эта новая функция — Origin Private File System .
Полностью нативный подход: частная файловая система Origin
Origin Private File System (OPFS) все еще является экспериментальной функцией в Kiwix PWA, но команда действительно рада побудить пользователей попробовать ее, поскольку она в значительной степени устраняет разрыв между собственными приложениями и веб-приложениями. Вот основные преимущества:
- Архивы в OPFS могут быть доступны без запроса разрешения , даже при запуске. Пользователи могут продолжить чтение статьи и просмотр архива с того места, где они остановились в предыдущем сеансе, без каких-либо проблем.
- Он обеспечивает высокооптимизированный доступ к хранящимся в нем файлам : на Android мы видим увеличение скорости в пять-десять раз.
Стандартный доступ к файлам в Android с использованием API File ужасно медленный, особенно (как это часто бывает у пользователей Kiwix), если большие архивы хранятся на карте microSD, а не в хранилище устройства. Все меняется с этим новым API. Хотя большинство пользователей не смогут хранить файл размером 97 ГБ в OPFS (которая занимает память устройства, а не карту microSD), он идеально подходит для хранения архивов небольшого и среднего размера. Вам нужна самая полная медицинская энциклопедия от WikiProject Medicine? Никаких проблем, при размере 1,7 ГБ она легко помещается в OPFS! (Совет: ищите другие → mdwiki_en_all_maxi в библиотеке внутри приложения .)
Как работает OPFS
OPFS — это файловая система, предоставляемая браузером, отдельная для каждого источника, которую можно рассматривать как аналог хранилища app-scoped на Android. Файлы можно импортировать в OPFS из видимой пользователю файловой системы или загружать напрямую в нее (API также позволяет создавать файлы в OPFS). Попав в OPFS, они изолируются от остальной части устройства. В настольных браузерах на базе Chromium также можно экспортировать файлы обратно из OPFS в видимую пользователю файловую систему.
Чтобы использовать OPFS, первым шагом является запрос доступа к ней с помощью navigator.storage.getDirectory()
(опять же, если вы предпочитаете увидеть код, использующий await
, прочитайте The Origin Private File System ):
return navigator.storage
.getDirectory()
.then(function (handle) {
return processDirHandle(handle);
})
.catch(function (err) {
console.warn('Unable to get the OPFS directory entry', err);
});
Дескриптор, который вы получаете из этого, является тем же самым типом FileSystemDirectoryHandle
, который вы получаете из window.showDirectoryPicker()
упомянутого выше, что означает, что вы можете повторно использовать код, который обрабатывает это (и, к счастью, нет необходимости хранить это в indexedDB
– просто получите его, когда он вам понадобится). Предположим, у вас уже есть некоторые файлы в OPFS, и вы хотите их использовать, затем, используя функцию iterateAsyncDirEntries()
, показанную ранее, вы можете сделать что-то вроде:
return navigator.storage.getDirectory().then(function (dirHandle) {
let entries = dirHandle.entries();
return iterateAsyncDirEntries(entries, [])
.then(function (archiveList) {
return archiveList;
})
.catch(function (err) {
console.error('Unable to iterate OPFS entries', err);
});
});
Не забывайте, что вам по-прежнему необходимо использовать getFile()
для любой записи из массива archiveList
, с которой вы хотите работать.
Импорт файлов в OPFS
Итак, как вообще поместить файлы в OPFS? Не так быстро! Во-первых, нужно оценить объем хранилища, с которым придется работать, и убедиться, что пользователи не попытаются поместить туда файл размером 97 ГБ, если он не поместится.
Получить предполагаемую квоту легко: navigator.storage.estimate().then(function (estimate) { … });
. Немного сложнее решить, как отобразить это пользователю. В приложении Kiwix мы выбрали небольшую панель внутри приложения, видимую прямо рядом с флажком, которая позволяет пользователям опробовать OPFS:
Панель заполняется с помощью estimate.quota
и estimate.usage
, например:
let OPFSQuota; // Global variable, so we don't have to keep checking it
return navigator.storage.estimate().then(function (estimate) {
const percent = ((estimate.usage / estimate.quota) * 100).toFixed(2);
OPFSQuota = estimate.quota - estimate.usage;
document.getElementById('OPFSQuota').innerHTML =
'<b>OPFS storage quota:</b><br />Used: <b>' +
percent +
'%</b>; ' +
'Remaining: <b>' +
(OPFSQuota / 1024 / 1024 / 1024).toFixed(2) +
' GB</b>';
});
Как вы видите, есть также кнопка, которая позволяет пользователям добавлять файлы в OPFS из видимой пользователю файловой системы. Хорошей новостью здесь является то, что вы можете просто использовать File API , чтобы получить необходимый объект File (или объекты), которые будут импортированы. На самом деле, важно не использовать window.showOpenFilePicker()
, потому что этот метод не поддерживается Firefox, тогда как OPFS, безусловно, поддерживается .
Видимая кнопка Добавить файл(ы), которую вы видите на снимке экрана выше, не является устаревшим выбором файлов, но она делает click()
скрытый устаревший выбор (элемент <input type="file" multiple … />
) при щелчке или касании. Затем приложение просто захватывает событие change
скрытого ввода файла, проверяет размер файлов и отклоняет их, если они слишком велики для квоты. Если все хорошо, спросите пользователя, хочет ли он добавить их:
archiveFilesLegacy.addEventListener('change', function (files) {
const filesArray = Array.from(files.target.files);
// Abort if user didn't select any files
if (filesArray.length === 0) return;
// Calculate the size of the picked files
let filesSize = 0;
filesArray.forEach(function (file) {
filesSize += file.size;
});
// Check the size of the files does not exceed the quota
if (filesSize > OPFSQuota) {
// Oh no, files are too big! Tell user...
console.log('Files would exceed the OPFS quota!');
} else {
// Ask user if they're sure... if user said yes...
return importOPFSEntries(filesArray)
.then(function () {
// Tell user we successfully imported the archives
})
.catch(function (err) {
// Tell user there was an error (error catching is important!)
});
}
});
Поскольку в некоторых операционных системах, таких как Android, импорт архивов не является самой быстрой операцией, Kiwix также показывает баннер и небольшой спиннер во время импорта архивов. Команда не придумала, как добавить индикатор прогресса для этой операции: если получится, ответьте на открытке, пожалуйста!
Итак, как Kiwix реализовал функцию importOPFSEntries()
? Это подразумевает использование метода fileHandle.createWriteable()
, который эффективно позволяет каждому файлу быть переданным в OPFS. Вся тяжелая работа выполняется браузером. (Kiwix использует Promises здесь по причинам, связанным с нашей устаревшей кодовой базой, но следует сказать, что в этом случае await
создает более простой синтаксис и избегает эффекта пирамиды гибели.)
function importOPFSEntries(files) {
// Get a handle on the OPFS directory
return navigator.storage
.getDirectory()
.then(function (dir) {
// Collect the promises for each file that we want to write
let promises = files.map(function (file) {
// Create the file and get a writeable handle on it
return dir
.getFileHandle(file.name, { create: true })
.then(function (fileHandle) {
// Get a writer for the file
return fileHandle.createWritable().then(function (writer) {
// Show a banner / spinner, then write the file
return writer
.write(file)
.then(function () {
// Finished with this writer
return writer.close();
})
.catch(function (err) {
console.error('There was an error writing to the OPFS!', err);
});
});
})
.catch(function (err) {
console.error('Unable to get file handle from OPFS!', err);
});
});
// Return a promise that resolves when all the files have been written
return Promise.all(promises);
})
.catch(function (err) {
console.error('Unable to get a handle on the OPFS directory!', err);
});
}
Загрузка потока файлов непосредственно в OPFS
Разновидностью этого является возможность потоковой передачи файла из Интернета непосредственно в OPFS или в любой каталог, для которого у вас есть дескриптор каталога (то есть каталоги, выбранные с помощью window.showDirectoryPicker()
). Он использует те же принципы, что и код выше, но создает Response
состоящий из ReadableStream
и контроллера, который ставит в очередь байты, считанные из удаленного файла. Затем полученный Response.body
передается в новый файл writer внутри OPFS.
В этом случае Kiwix может подсчитывать байты, проходящие через ReadableStream
, и таким образом предоставлять пользователю индикатор прогресса, а также предупреждать его не выходить из приложения во время загрузки. Код немного слишком запутан, чтобы показывать его здесь, но поскольку наше приложение является приложением FOSS, вы можете посмотреть исходный код, если вам интересно сделать что-то подобное. Вот как выглядит пользовательский интерфейс Kiwix (различные значения прогресса, показанные ниже, связаны с тем, что он обновляет только баннер при изменении процента, но обновляет панель прогресса загрузки более регулярно):
Поскольку загрузка может быть довольно длительной операцией, Kiwix позволяет пользователям свободно использовать приложение во время операции, но обеспечивает постоянное отображение баннера, чтобы напомнить пользователям о необходимости не закрывать приложение до завершения операции загрузки.
Реализация мини-файлового менеджера в приложении
В этот момент разработчики Kiwix PWA поняли, что недостаточно иметь возможность добавлять файлы в OPFS. Приложение также должно было предоставить пользователям возможность удалять файлы, которые им больше не нужны, из этой области хранения, а в идеале также экспортировать любые файлы, заблокированные в OPFS, обратно в видимую пользователю файловую систему. Фактически, возникла необходимость реализовать мини -систему управления файлами внутри приложения.
Небольшой привет сказочному расширению OPFS Explorer для Chrome (оно также работает в Edge). Оно добавляет вкладку в инструменты разработчика, которая позволяет вам точно видеть, что находится в OPFS, а также удалять неисправные или сбойные файлы. Оно было бесценным для проверки работоспособности кода, мониторинга поведения загрузок и общей очистки наших экспериментов по разработке.
Экспорт файла зависит от возможности получить дескриптор файла для выбранного файла или каталога, в который Kiwix собирается сохранить экспортируемый файл, поэтому это работает только в контекстах, где он может использовать метод window.showSaveFilePicker()
. Если бы файлы Kiwix были меньше нескольких ГБ, мы могли бы создать большой двоичный объект в памяти, присвоить ему URL-адрес, а затем загрузить его в видимую пользователю файловую систему. К сожалению, это невозможно с такими большими архивами. Если поддерживается, экспорт довольно прост: фактически то же самое, только в обратном порядке, что и сохранение файла в OPFS (получить дескриптор файла для сохранения, попросить пользователя выбрать место для сохранения с помощью window.showSaveFilePicker()
, затем использовать createWriteable()
для saveHandle
). Вы можете увидеть код в репозитории.
Удаление файлов поддерживается всеми браузерами и может быть достигнуто с помощью простого dirHandle.removeEntry('filename')
. В случае Kiwix мы предпочли итерировать записи OPFS, как мы сделали выше, чтобы мы могли сначала проверить, существует ли выбранный файл, и запросить подтверждение, но это может быть не обязательно для всех. Опять же, вы можете изучить наш код, если вам интересно.
Было решено не загромождать пользовательский интерфейс Kiwix кнопками, предлагающими эти опции, а вместо этого разместить небольшие значки прямо под списком архивов. Нажатие на один из этих значков изменит цвет списка архивов, как визуальную подсказку пользователю о том, что он собирается делать. Затем пользователь нажимает или касается одного из архивов, и соответствующая операция (экспорт или удаление) выполняется (после подтверждения).
Наконец, вот демонстрационный видеоролик со всеми функциями управления файлами, рассмотренными выше: добавление файла в OPFS, прямая загрузка файла в него, удаление файла и экспорт в видимую пользователю файловую систему.
Работа разработчика никогда не заканчивается
OPFS — это великолепная инновация для разработчиков PWA, предоставляющая действительно мощные функции управления файлами, которые во многом способствуют сокращению разрыва между собственными приложениями и веб-приложениями. Но разработчики — несчастная группа, они никогда не бывают полностью удовлетворены! OPFS почти идеальна, но не совсем… Замечательно, что основные функции работают как в браузерах Chromium, так и в Firefox, и что они реализованы как на Android, так и на настольных компьютерах. Мы надеемся, что полный набор функций вскоре будет реализован в Safari и iOS. Остаются следующие проблемы:
- Firefox в настоящее время устанавливает ограничение в 10 ГБ на квоту OPFS, независимо от того, сколько базового дискового пространства есть. Хотя для большинства авторов PWA этого может быть достаточно, для Kiwix это довольно ограничительно. К счастью, браузеры Chromium гораздо более щедры.
- В настоящее время невозможно экспортировать большие файлы из OPFS в видимую пользователю файловую систему в мобильных браузерах или настольном Firefox, поскольку
window.showSaveFilePicker()
не реализован. В этих браузерах большие файлы фактически заперты в OPFS. Это противоречит принципам Kiwix, касающимся открытого доступа к контенту и возможности делиться архивами между пользователями, особенно в областях с нестабильным или дорогим подключением к Интернету. - Пользователь не может контролировать, какое хранилище будет потреблять виртуальная файловая система OPFS. Это особенно проблематично на мобильных устройствах, где у пользователей может быть много места на карте microSD, но очень мало места на устройстве.
Но в целом это незначительные мелочи в том, что в остальном является огромным шагом вперед для доступа к файлам в PWA. Команда Kiwix PWA очень благодарна разработчикам и сторонникам Chromium, которые первыми предложили и разработали API доступа к файловой системе, а также за упорную работу по достижению консенсуса среди поставщиков браузеров относительно важности Origin Private File System. Для Kiwix JS PWA это решило множество проблем UX, которые мешали приложению в прошлом, и помогает нам в нашем стремлении улучшить доступность контента Kiwix для всех. Пожалуйста, дайте Kiwix PWA опробовать и расскажите разработчикам, что вы думаете!
Полезные ресурсы о возможностях PWA можно найти на следующих сайтах:
- Демонстрация API проекта Fugu : коллекция веб-приложений, демонстрирующих возможности, которые устраняют разрыв между собственными приложениями и PWA.
- Что PWA могут делать сегодня : демонстрация возможностей PWA сегодня.