Studi kasus ini mengeksplorasi cara Kiwix, sebuah organisasi nonprofit, menggunakan teknologi Progressive Web App dan File System Access API untuk memungkinkan pengguna mendownload dan menyimpan arsip Internet berukuran besar untuk penggunaan offline. Pelajari penerapan teknis kode yang menangani Origin Private File System (OPFS), fitur browser baru dalam PWA Kiwix yang meningkatkan pengelolaan file, sehingga memberikan akses yang lebih baik ke arsip tanpa permintaan izin. Artikel ini membahas tantangan dan menyoroti potensi pengembangan di masa mendatang dalam sistem file baru ini.
Tentang Kiwix
Lebih dari 30 tahun setelah kelahiran web, sepertiga populasi dunia masih menunggu akses internet yang andal menurut International Telecommunication Union. Apakah di sinilah kisahnya berakhir? Tentu saja tidak. Tim di Kiwix, organisasi nirlaba yang berbasis di Swiss, telah mengembangkan ekosistem aplikasi dan konten open source yang bertujuan untuk menyediakan pengetahuan bagi orang-orang dengan akses Internet terbatas atau tidak ada. Idenya adalah jika Anda tidak dapat mengakses Internet dengan mudah, seseorang dapat mendownload resource utama untuk Anda, di mana dan kapan konektivitas tersedia, dan menyimpan resource tersebut secara lokal untuk digunakan secara offline nanti. Banyak situs penting, misalnya Wikipedia, Project Gutenberg, Stack Exchange, atau bahkan TED Talks, kini dapat dikonversi menjadi arsip yang sangat terkompresi, yang disebut file ZIM, dan dibaca dengan cepat oleh browser Kiwix.
Arsip ZIM menggunakan kompresi Zstandard (ZSTD) yang sangat efisien (versi lama menggunakan XZ), sebagian besar untuk menyimpan HTML, JavaScript, dan CSS, sedangkan gambar biasanya dikonversi ke format WebP yang dikompresi. Setiap ZIM juga menyertakan URL dan indeks judul. Kompresi adalah kuncinya di sini, karena seluruh Wikipedia dalam bahasa Inggris (6,4 juta artikel, ditambah gambar) dikompresi menjadi 97 GB setelah dikonversi ke format ZIM, yang terdengar seperti banyak sampai Anda menyadari bahwa jumlah semua pengetahuan manusia kini dapat muat di ponsel Android menengah. Banyak referensi yang lebih kecil juga ditawarkan, termasuk versi tematik Wikipedia, seperti matematika, kedokteran, dan sebagainya.
Kiwix menawarkan berbagai aplikasi native yang menargetkan penggunaan desktop (Windows/Linux/macOS) serta seluler (iOS/Android). Namun, studi kasus ini akan berfokus pada Progressive Web App (PWA) yang bertujuan menjadi solusi universal dan sederhana untuk perangkat apa pun yang memiliki browser modern.
Kita akan melihat tantangan yang dihadapi dalam mengembangkan aplikasi Web universal yang perlu memberikan akses cepat ke arsip konten besar secara offline sepenuhnya, dan beberapa JavaScript API modern, terutama File System Access API dan Origin Private File System, yang memberikan solusi inovatif dan menarik untuk tantangan tersebut.
Aplikasi Web untuk penggunaan offline?
Pengguna Kiwix adalah kelompok yang beragam dengan berbagai kebutuhan, dan Kiwix memiliki sedikit atau tidak ada kontrol atas perangkat dan sistem operasi tempat mereka akan mengakses konten mereka. Beberapa perangkat ini mungkin lambat atau sudah usang, terutama di area berpenghasilan rendah di dunia. Meskipun Kiwix mencoba mencakup sebanyak mungkin kasus penggunaan, organisasi ini juga menyadari bahwa mereka dapat menjangkau lebih banyak pengguna dengan menggunakan software paling universal di perangkat apa pun: browser web. Jadi, terinspirasi oleh Hukum Atwood, yang menyatakan bahwa Aplikasi apa pun yang dapat ditulis dalam JavaScript, pada akhirnya akan ditulis dalam JavaScript, beberapa developer Kiwix, sekitar 10 tahun yang lalu, mulai mem-porting software Kiwix dari C++ ke JavaScript.
Versi pertama port ini, yang disebut Kiwix HTML5, ditujukan untuk Firefox OS yang kini tidak digunakan lagi dan untuk ekstensi browser. Pada intinya adalah (dan masih) mesin dekompresi C++ (XZ dan ZSTD) yang dikompilasi ke bahasa JavaScript perantara ASM.js, dan kemudian Wasm, atau WebAssembly, menggunakan compiler Emscripten. Kemudian diganti namanya menjadi Kiwix JS, ekstensi browser masih dikembangkan secara aktif.
Masukkan Progressive Web App (PWA). Menyadari potensi teknologi ini, developer Kiwix membuat versi PWA khusus Kiwix JS, dan mulai menambahkan integrasi OS yang akan memungkinkan aplikasi menawarkan kemampuan seperti native, terutama di area penggunaan offline, penginstalan, penanganan file, dan akses sistem file.
PWA offline-first sangat ringan, sehingga sangat cocok untuk konteks dengan Internet seluler yang tidak stabil atau mahal. Teknologi di balik hal ini adalah Service Worker API dan Cache API terkait, yang digunakan oleh semua aplikasi berdasarkan Kiwix JS. API ini memungkinkan aplikasi bertindak sebagai server, mencegat Permintaan Pengambilan dari dokumen atau artikel utama yang sedang dilihat, dan mengalihkan permintaan tersebut ke backend (JS) untuk mengekstrak dan membuat Respons dari arsip ZIM.
Penyimpanan, penyimpanan di mana saja
Mengingat ukuran arsip ZIM yang besar, penyimpanan dan akses ke arsip tersebut, terutama di perangkat seluler, mungkin merupakan masalah terbesar bagi developer Kiwix. Banyak pengguna akhir Kiwix mendownload konten dalam aplikasi, saat Internet tersedia, untuk penggunaan offline nanti. Pengguna lain mendownload di PC menggunakan torrent, lalu mentransfernya ke perangkat seluler atau tablet, dan beberapa pengguna bertukar konten di flash drive USB atau hard drive portabel di area dengan Internet seluler yang tidak stabil atau mahal. Semua cara mengakses konten dari lokasi arbitrer yang dapat diakses pengguna harus didukung oleh Kiwix JS dan Kiwix PWA.
Yang awalnya memungkinkan Kiwix JS membaca arsip yang sangat besar, berukuran ratusan GB
(satu
arsip ZIM kami berukuran 166 GB!) bahkan di perangkat dengan memori rendah, adalah
File API. API ini
didukung secara universal di browser apa pun, bahkan
browser yang sangat lama, sehingga
berfungsi sebagai penggantian universal, untuk saat API yang lebih baru tidak didukung. Caranya
semudah menentukan elemen input
dalam HTML, dalam kasus Kiwix:
<input
type="file"
accept="application/octet-stream,.zim,.zimaa,.zimab,.zimac, ..."
value="Select folder with ZIM files"
id="archiveFilesLegacy"
multiple
/>
Setelah dipilih, elemen input akan menyimpan objek File yang pada dasarnya adalah metadata yang mereferensikan data pokok dalam penyimpanan. Secara teknis, backend berorientasi objek Kiwix, yang ditulis dalam JavaScript sisi klien murni, membaca potongan kecil dari arsip besar sesuai kebutuhan. Jika slice tersebut perlu didekompresi, backend akan meneruskannya ke dekompresor Wasm, mendapatkan slice lebih lanjut jika diminta, hingga blob lengkap didekompresi (biasanya artikel atau aset). Artinya, arsip besar tidak perlu dibaca sepenuhnya ke memori.
Meskipun bersifat universal, File API memiliki kelemahan yang membuat aplikasi Kiwix JS tampak clunky dan kuno dibandingkan dengan aplikasi native: aplikasi ini mengharuskan pengguna memilih arsip menggunakan pemilih file, atau tarik lalu lepas file ke dalam aplikasi, setiap kali aplikasi diluncurkan, karena dengan API ini, tidak ada cara untuk mempertahankan izin akses dari satu sesi ke sesi berikutnya.
Untuk mengurangi UX yang buruk ini, seperti banyak developer, developer Kiwix JS awalnya menggunakan rute Electron. ElectronJS adalah framework luar biasa yang menyediakan fitur canggih, termasuk akses penuh ke sistem file menggunakan Node API. Namun, metode ini memiliki beberapa kelemahan yang sudah diketahui:
- Aplikasi ini hanya berjalan di sistem operasi desktop.
- File ini besar dan berat (70 MB–100 MB).
Ukuran aplikasi Electron, karena fakta bahwa salinan lengkap Chromium disertakan dengan setiap aplikasi, dibandingkan dengan hanya 5,1 MB untuk PWA yang diminimalkan dan dipaketkan.
Jadi, apakah ada cara bagi Kiwix untuk meningkatkan situasi bagi pengguna PWA?
File System Access API untuk membantu
Sekitar tahun 2019, Kiwix mengetahui API baru yang sedang menjalani uji coba origin di Chrome 78, yang kemudian disebut Native File System API. API ini menjanjikan kemampuan untuk mendapatkan handle file untuk file atau folder dan menyimpannya dalam database IndexedDB. Yang terpenting, nama sebutan ini tetap ada di antara sesi aplikasi, sehingga pengguna tidak dipaksa untuk memilih file atau folder lagi saat meluncurkan kembali aplikasi (meskipun mereka harus menjawab perintah izin cepat). Pada saat mencapai produksi, API ini telah diganti namanya menjadi File System Access API, dan bagian inti distandarisasi oleh WHATWG sebagai File System API (FSA).
Jadi, bagaimana cara kerja bagian File System Access dari API? Beberapa poin penting yang perlu diperhatikan:
- Ini adalah API asinkron (kecuali untuk fungsi khusus di Web Worker).
- Pemilih file atau direktori harus diluncurkan secara terprogram dengan mengambil gestur pengguna (klik atau ketuk elemen UI).
- Agar pengguna dapat memberikan izin lagi untuk mengakses file yang dipilih sebelumnya (dalam sesi baru), gestur pengguna juga diperlukan—bahkan browser akan menolak untuk menampilkan dialog izin jika tidak dimulai oleh gestur pengguna.
Kode ini relatif mudah, selain harus menggunakan IndexedDB API yang canggung untuk menyimpan handle file dan direktori. Kabar baiknya, ada beberapa library yang melakukan banyak pekerjaan berat untuk Anda, seperti browser-fs-access. Di Kiwix JS, kami memutuskan untuk bekerja langsung dengan API, yang sangat didokumentasikan dengan baik.
Membuka pemilih file dan direktori
Membuka pemilih file terlihat seperti ini (di sini menggunakan Promises, tetapi jika
Anda lebih memilih sugar async/await
, lihat
tutorial Chrome untuk Developer):
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,
);
});
Perhatikan bahwa untuk memudahkan, kode ini hanya memproses file pertama yang dipilih (dan melarang pemilihan lebih dari satu). Jika ingin mengizinkan pemilihan
beberapa file dengan { multiple: true }
, cukup gabungkan semua Promise yang
memproses setiap handle dalam pernyataan Promise.all().then(...)
, misalnya:
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);
)};
Namun, memilih beberapa file mungkin lebih baik dilakukan dengan meminta pengguna untuk
memilih direktori yang berisi file tersebut, bukan file individual di
direktori tersebut, terutama karena pengguna Kiwix cenderung mengatur semua file ZIM mereka di
direktori yang sama. Kode untuk meluncurkan pemilih direktori hampir
sama dengan di atas, kecuali Anda menggunakan
window.showDirectoryPicker.then(function (dirHandle) { … });
.
Memproses handle file atau direktori
Setelah memiliki handle, Anda perlu memprosesnya, sehingga fungsi
processFileHandle
dapat terlihat seperti ini:
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;
});
}
Perhatikan bahwa Anda harus menyediakan fungsi untuk menyimpan handle file, tidak ada
metode praktis untuk ini, kecuali jika Anda menggunakan library abstraksi. Implementasi Kiwix
untuk hal ini dapat dilihat dalam file
cache.js
,
tetapi dapat disederhanakan secara signifikan jika hanya digunakan untuk menyimpan dan mengambil
handle file atau folder.
Memproses direktori sedikit lebih rumit karena Anda harus melakukan iterasi
pada entri di direktori yang dipilih dengan entries.next()
asinkron untuk menemukan
file atau jenis file yang Anda inginkan. Ada berbagai cara untuk melakukannya, tetapi
ini adalah kode yang digunakan di Kiwix PWA, dalam garis besar:
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);
});
}
Perhatikan bahwa untuk setiap entri di entryList
, Anda nantinya harus mendapatkan file
dengan entry.getFile().then(function (file) { … })
saat perlu menggunakannya, atau
yang setara menggunakan const file = await entry.getFile()
di
async function
.
Bisakah kita melangkah lebih jauh?
Persyaratan bagi pengguna untuk memberikan izin yang dimulai dengan gestur pengguna pada peluncuran aplikasi berikutnya menambahkan sedikit hambatan untuk pembukaan (ulang) file dan folder, tetapi masih jauh lebih lancar daripada dipaksa untuk memilih ulang file. Developer Chromium saat ini menyelesaikan kode yang akan memungkinkan izin persisten untuk PWA yang diinstal. Hal ini merupakan sesuatu yang telah banyak diminta oleh developer PWA, dan sangat diantisipasi.
Tapi, bagaimana jika kita tidak perlu menunggu? Developer Kiwix baru-baru ini menemukan bahwa saat ini
Anda dapat menghapus semua permintaan izin, dengan menggunakan fitur baru
yang menarik dari File Access API yang didukung oleh browser Chromium dan Firefox (dan sebagian didukung oleh Safari, tetapi masih
tidak memiliki FileSystemWritableFileStream
).
Fitur baru ini adalah Origin Private File System.
Beralih sepenuhnya ke native: Sistem File Pribadi Origin
Origin Private File System (OPFS) masih merupakan fitur eksperimental di PWA Kiwix, tetapi tim sangat senang untuk mendorong pengguna mencobanya karena fitur ini sebagian besar menjembatani kesenjangan antara aplikasi native dan aplikasi Web. Berikut adalah manfaat utamanya:
- Arsip di OPFS dapat diakses tanpa permintaan izin, bahkan saat peluncuran. Pengguna dapat melanjutkan membaca artikel, dan menjelajahi arsip, dari bagian yang terakhir dibaca di sesi sebelumnya, tanpa hambatan sama sekali.
- Fitur ini memberikan akses yang sangat dioptimalkan ke file yang disimpan di dalamnya: di Android, kami melihat peningkatan kecepatan antara lima hingga sepuluh kali lebih cepat.
Akses file standar di Android menggunakan File API sangat lambat, terutama (seperti yang sering terjadi pada pengguna Kiwix) jika arsip besar disimpan di kartu microSD, bukan di penyimpanan perangkat. Semuanya berubah dengan API baru ini. Meskipun sebagian besar pengguna tidak akan dapat menyimpan file berukuran 97 GB di OPFS (yang menggunakan penyimpanan perangkat, bukan penyimpanan kartu microSD), OPFS sangat cocok untuk menyimpan arsip berukuran kecil hingga sedang. Anda ingin ensiklopedia medis terlengkap dari WikiProject Medicine? Tidak masalah, dengan ukuran 1,7 GB, file tersebut mudah muat di OPFS. (Tips: cari other → mdwiki_en_all_maxi di library dalam aplikasi.)
Cara kerja OPFS
OPFS adalah sistem file yang disediakan oleh browser, terpisah untuk setiap origin, yang dapat dianggap mirip dengan penyimpanan cakupan aplikasi di Android. File dapat diimpor ke OPFS dari sistem file yang terlihat pengguna, atau dapat didownload langsung ke dalamnya (API juga memungkinkan pembuatan file di OPFS). Setelah berada di OPFS, file tersebut akan terisolasi dari bagian perangkat lainnya. Di browser berbasis Chromium desktop, Anda juga dapat mengekspor file kembali dari OPFS ke sistem file yang terlihat pengguna.
Untuk menggunakan OPFS, langkah pertama adalah meminta akses ke sistem file tersebut, menggunakan
navigator.storage.getDirectory()
(sekali lagi, jika Anda lebih suka melihat kode menggunakan
await
, baca
Sistem File Pribadi Origin):
return navigator.storage
.getDirectory()
.then(function (handle) {
return processDirHandle(handle);
})
.catch(function (err) {
console.warn('Unable to get the OPFS directory entry', err);
});
Nama sebutan yang Anda dapatkan dari ini adalah jenis
FileSystemDirectoryHandle
yang sama dengan yang Anda dapatkan dari window.showDirectoryPicker()
yang disebutkan di atas, yang berarti Anda dapat menggunakan kembali kode yang menanganinya (dan
untungnya tidak perlu menyimpannya di indexedDB
– cukup dapatkan saat Anda
memerlukannya). Misalkan Anda sudah memiliki beberapa file di OPFS dan ingin menggunakannya, lalu, menggunakan fungsi iterateAsyncDirEntries()
yang ditampilkan sebelumnya, Anda dapat melakukan hal seperti:
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);
});
});
Jangan lupa bahwa Anda masih perlu menggunakan getFile()
pada entri yang ingin Anda gunakan
dari array archiveList
.
Mengimpor file ke OPFS
Jadi, bagaimana cara memasukkan file ke OPFS? Tidak semudah itu. Pertama, Anda perlu memperkirakan jumlah penyimpanan yang harus digunakan, dan memastikan bahwa pengguna tidak mencoba memasukkan file berukuran 97 GB jika tidak muat.
Mendapatkan estimasi kuota sangat mudah:
navigator.storage.estimate().then(function (estimate) { … });
. Yang sedikit lebih sulit
adalah mencari cara untuk menampilkannya kepada pengguna. Di aplikasi Kiwix, kami memilih
panel kecil dalam aplikasi yang terlihat tepat di samping kotak centang yang memungkinkan pengguna mencoba
OPFS:
Panel diisi menggunakan
estimate.quota
dan
estimate.usage
,
misalnya:
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>';
});
Seperti yang dapat Anda lihat, ada juga tombol yang memungkinkan pengguna menambahkan file ke OPFS dari
sistem file yang terlihat pengguna. Kabar baiknya adalah Anda cukup menggunakan
File API untuk mendapatkan
objek File (atau beberapa objek) yang diperlukan yang akan diimpor. Bahkan, sebaiknya
jangan gunakan window.showOpenFilePicker()
karena metode ini
tidak didukung oleh Firefox, sedangkan OPFS pasti didukung.
Tombol Tambahkan file yang terlihat dan Anda lihat pada screenshot di atas bukan pemilih file lama, tetapi tombol tersebut akan click()
pemilih lama yang tersembunyi (elemen <input type="file" multiple … />
) saat diklik atau diketuk. Aplikasi
kemudian hanya merekam peristiwa change
dari input file tersembunyi, memeriksa
ukuran file, dan menolaknya jika terlalu besar untuk kuota. Jika semuanya
baik, tanyakan kepada pengguna apakah mereka ingin menambahkannya:
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!)
});
}
});
Karena pada beberapa sistem operasi, seperti Android, mengimpor arsip bukanlah operasi tercepat, Kiwix juga menampilkan banner dan indikator lingkaran berputar kecil saat arsip sedang diimpor. Tim tidak mengetahui cara menambahkan indikator progres untuk operasi ini: jika Anda mengetahuinya, harap kirimkan jawabannya melalui kartu pos.
Jadi, bagaimana Kiwix menerapkan fungsi importOPFSEntries()
? Hal ini melibatkan
penggunaan metode fileHandle.createWriteable()
, yang secara efektif memungkinkan setiap
file di-streaming ke OPFS. Semua pekerjaan berat ditangani oleh browser. (Kiwix menggunakan Promise di sini karena alasan yang berkaitan dengan codebase
lama kami, tetapi harus dikatakan bahwa dalam hal ini await
menghasilkan sintaksis
yang lebih sederhana, dan menghindari efek piramida malapetaka.)
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);
});
}
Mendownload aliran file langsung ke OPFS
Variasi dari hal ini adalah kemampuan untuk melakukan streaming file dari Internet langsung
ke OPFS, atau ke direktori mana pun yang memiliki handle direktori (yaitu, direktori yang dipilih dengan window.showDirectoryPicker()
). Variasi ini menggunakan prinsip
yang sama dengan kode di atas, tetapi membuat Response
yang terdiri dari
ReadableStream
dan pengontrol yang mengantrekan byte yang dibaca dari file
jarak jauh. Response.body
yang dihasilkan kemudian
di-piping ke penulis file baru
di dalam OPFS.
Dalam hal ini, Kiwix dapat menghitung byte yang melewati
ReadableStream
, sehingga memberikan indikator progres kepada pengguna, dan juga memperingatkan
mereka agar tidak keluar dari aplikasi selama download. Kodenya agak terlalu rumit
untuk ditampilkan di sini, tetapi karena aplikasi kami adalah aplikasi FOSS, Anda dapat
melihat sumbernya
jika tertarik untuk melakukan hal serupa. Tampilan UI Kiwix
seperti ini (nilai progres yang berbeda yang ditampilkan di bawah ini karena hanya memperbarui banner
saat persentase berubah, tetapi memperbarui panel Progres download
lebih rutin):
Karena proses download dapat berlangsung cukup lama, Kiwix memungkinkan pengguna menggunakan aplikasi secara bebas selama operasi, tetapi memastikan banner selalu ditampilkan, sehingga pengguna diingatkan untuk tidak menutup aplikasi hingga operasi download selesai.
Menerapkan pengelola file mini dalam aplikasi
Pada tahap ini, developer PWA Kiwix menyadari bahwa menambahkan file ke OPFS saja tidak cukup. Aplikasi juga perlu memberi pengguna cara untuk menghapus file yang tidak lagi mereka perlukan dari area penyimpanan ini, dan idealnya, juga, untuk mengekspor file apa pun yang dikunci di OPFS kembali ke sistem file yang terlihat pengguna. Secara efektif, Anda perlu menerapkan sistem pengelolaan file mini di dalam aplikasi.
Kami ingin menyampaikan apresiasi kepada ekstensi OPFS Explorer yang luar biasa untuk Chrome (ekstensi ini juga berfungsi di Edge). Fitur ini menambahkan tab di alat developer yang memungkinkan Anda melihat apa yang ada di OPFS, dan juga menghapus file yang tidak sah atau gagal. Hal ini sangat penting untuk memeriksa apakah kode berfungsi, memantau perilaku download, dan secara umum membersihkan eksperimen pengembangan kami.
Ekspor file bergantung pada kemampuan untuk mendapatkan handle file pada file atau direktori yang dipilih
tempat Kiwix akan menyimpan file yang diekspor, sehingga ini hanya
berfungsi dalam konteks yang dapat menggunakan metode window.showSaveFilePicker()
. Jika
file Kiwix lebih kecil dari beberapa GB, kita dapat membuat blob
di memori, memberinya URL, lalu mendownloadnya ke sistem file yang terlihat pengguna.
Sayangnya, hal itu tidak dapat dilakukan dengan arsip yang begitu besar. Jika didukung,
ekspor cukup mudah: secara virtual sama, secara terbalik, seperti menyimpan
file ke dalam OPFS (dapatkan handle pada file yang akan disimpan, minta pengguna untuk memilih
lokasi untuk menyimpannya dengan window.showSaveFilePicker()
, lalu gunakan
createWriteable()
di saveHandle
). Anda dapat
melihat kode
di repo.
Penghapusan file didukung oleh semua browser, dan dapat dilakukan dengan
dirHandle.removeEntry('filename')
sederhana. Dalam kasus Kiwix, sebaiknya kita
mengulangi entri OPFS seperti yang kita lakukan di atas, sehingga kita dapat memeriksa apakah
file yang dipilih ada terlebih dahulu dan meminta konfirmasi, tetapi hal itu mungkin tidak
diperlukan untuk semua orang. Sekali lagi, Anda dapat
memeriksa kode kami
jika berminat.
Diputuskan untuk tidak mengacaukan UI Kiwix dengan tombol yang menawarkan opsi ini, dan sebagai gantinya menempatkan ikon kecil langsung di bawah daftar arsip. Mengetuk salah satu ikon ini akan mengubah warna daftar arsip, sebagai petunjuk visual kepada pengguna tentang tindakan yang akan mereka lakukan. Kemudian, pengguna mengklik atau mengetuk salah satu arsip, dan operasi yang sesuai (ekspor atau hapus) dilakukan (setelah konfirmasi).
Terakhir, berikut adalah demo screencast dari semua fitur pengelolaan file yang dibahas di atas—menambahkan file ke OPFS, langsung mendownload file ke dalamnya, menghapus file, dan mengekspor ke sistem file yang terlihat pengguna.
Pekerjaan developer tidak pernah selesai
OPFS adalah inovasi yang bagus bagi developer PWA, yang menyediakan fitur pengelolaan file yang sangat canggih dan sangat membantu dalam menutup kesenjangan antara aplikasi native dan aplikasi Web. Namun, developer adalah sekelompok orang yang menyedihkan—mereka tidak pernah puas! OPFS hampir sempurna, tetapi tidak sepenuhnya… Sangat bagus bahwa fitur utama berfungsi di browser Chromium dan Firefox, serta diterapkan di Android dan desktop. Kami berharap kumpulan fitur lengkap juga akan diimplementasikan di Safari dan iOS dalam waktu dekat. Masalah berikut masih ada:
- Firefox saat ini menetapkan batas 10 GB pada kuota OPFS, berapa pun jumlah ruang disk yang ada. Meskipun bagi sebagian besar penulis PWA, hal ini mungkin cukup, tetapi bagi Kiwix, hal ini cukup membatasi. Untungnya, browser Chromium jauh lebih longgar.
- Saat ini, Anda tidak dapat mengekspor file besar dari OPFS ke
sistem file yang terlihat pengguna di browser seluler, atau Firefox desktop, karena
window.showSaveFilePicker()
tidak diterapkan. Di browser ini, file besar terperangkap secara efektif di OPFS. Hal ini bertentangan dengan etos Kiwix tentang akses terbuka ke konten, dan kemampuan untuk berbagi arsip antarpengguna terutama di area dengan konektivitas Internet yang terputus-putus atau mahal. - Pengguna tidak dapat mengontrol penyimpanan yang akan digunakan sistem file virtual OPFS. Hal ini sangat bermasalah pada perangkat seluler, tempat pengguna mungkin memiliki ruang penyimpanan yang besar di kartu microSD, tetapi sangat sedikit di penyimpanan perangkat.
Namun, secara keseluruhan, ini adalah masalah kecil dalam langkah besar untuk akses file di PWA. Tim PWA Kiwix sangat berterima kasih kepada developer dan pendukung Chromium yang pertama kali mengusulkan dan mendesain File System Access API, serta atas kerja kerasnya dalam mencapai konsensus di antara vendor browser tentang pentingnya Origin Private File System. Untuk Kiwix JS PWA, aplikasi ini telah menyelesaikan banyak masalah UX yang telah menghambat aplikasi di masa lalu, dan membantu kami dalam upaya meningkatkan aksesibilitas konten Kiwix untuk semua orang. Harap coba Kiwix PWA dan beri tahu developer pendapat Anda.
Untuk beberapa referensi yang bagus tentang kemampuan PWA, lihat situs berikut:
- Project Fugu API showcase: kumpulan aplikasi Web yang menampilkan kemampuan yang menjembatani kesenjangan antara aplikasi native dan PWA.
- Yang dapat dilakukan PWA saat ini: menampilkan hal-hal yang dapat dilakukan dengan PWA saat ini.