Studi kasus ini mempelajari cara Kiwix, sebuah organisasi nonprofit, menggunakan teknologi Progressive Web App dan File System Access API agar pengguna dapat mendownload dan menyimpan arsip Internet berukuran besar untuk penggunaan offline. Pelajari implementasi teknis kode yang berhubungan dengan Origin Private File System (OPFS), fitur browser baru dalam PWA Kiwix yang meningkatkan pengelolaan file, yang memberikan akses yang lebih baik ke arsip tanpa dialog izin. Artikel ini membahas tantangan dan menyoroti potensi pengembangan pada masa mendatang dalam sistem file baru ini.
Tentang Kiwix
Lebih dari 30 tahun setelah kelahiran web, sepertiga populasi dunia masih menunggu akses andal ke internet menurut International Telecommunication Union. Apakah di mana ceritanya berakhir? Tentu saja tidak. Orang-orang di Kiwix, sebuah lembaga nirlaba yang berbasis di Swiss, telah mengembangkan ekosistem aplikasi dan konten open source yang bertujuan untuk menyediakan pengetahuan bagi orang-orang dengan akses internet yang terbatas atau tidak memiliki akses sama sekali. idenya adalah jika Anda tidak dapat mengakses internet dengan mudah, maka seseorang dapat mendownload resource utama untuk Anda, di mana dan kapan konektivitas tersedia, serta menyimpannya secara lokal untuk digunakan secara offline di lain waktu. Banyak situs penting, misalnya Wikipedia, Project Gutenberg, Stack Exchange, atau bahkan TED talks, sekarang 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, karena keseluruhan Wikipedia dalam bahasa Inggris (6,4 juta artikel, plus gambar) dikompresi menjadi 97 GB setelah konversi ke format ZIM, yang terdengar sangat banyak sampai Anda menyadari bahwa jumlah semua pengetahuan manusia kini dapat muat di ponsel Android kelas menengah. Banyak resource yang lebih kecil juga ditawarkan, termasuk versi Wikipedia bertema, 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 dalam pengembangan aplikasi Web universal yang perlu menyediakan 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 mengatasi tantangan tersebut.
Aplikasi Web untuk penggunaan offline?
Pengguna Kiwix adalah pengguna eklektik dengan berbagai kebutuhan, dan Kiwix memiliki sedikit atau tidak memiliki kontrol atas perangkat dan sistem operasi tempat mereka akan mengakses konten mereka. Beberapa perangkat tersebut mungkin lambat atau sudah usang, terutama di wilayah berpendapatan 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 Atwood's Law, 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 porta ini, yang disebut Kiwix HTML5, digunakan untuk OS Firefox yang kini sudah tidak berfungsi dan untuk ekstensi browser. Pada intinya adalah (dan sekarang) mesin dekompresi C++ (XZ dan ZSTD) 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 Kiwix JS khusus, dan mulai menambahkan integrasi OS yang akan memungkinkan aplikasi menawarkan kemampuan seperti aplikasi native, terutama di area penggunaan offline, penginstalan, penanganan file, dan akses sistem file.
PWA offline-first sangat ringan, sehingga sangat cocok untuk konteks di mana ada internet seluler yang terputus-putus atau mahal. Teknologi di balik ini adalah Service Worker API dan Cache API terkait, yang digunakan oleh semua aplikasi berdasarkan Kiwix JS. API ini memungkinkan aplikasi untuk bertindak sebagai server, mencegat Permintaan Pengambilan dari dokumen atau artikel utama yang dilihat, dan mengalihkannya ke backend (JS) untuk mengekstrak dan membuat Respons dari arsip ZIM.
Penyimpanan, penyimpanan di mana saja
Mengingat besarnya ukuran arsip ZIM, penyimpanan dan akses ke sana, terutama pada perangkat seluler, mungkin merupakan masalah terbesar bagi developer Kiwix. Banyak pengguna akhir Kiwix mendownload konten dalam aplikasi, saat Internet tersedia, untuk digunakan secara offline nanti. Pengguna lain mendownload file di PC menggunakan torrent, lalu mentransfernya ke perangkat seluler atau tablet, dan bertukar konten di stik USB atau hard drive portabel di area dengan Internet seluler yang sulit diakses atau mahal. Semua cara untuk mengakses konten dari sembarang lokasi yang dapat diakses pengguna ini harus didukung oleh Kiwix JS dan Kiwix PWA.
Yang awalnya memungkinkan Kiwix JS membaca arsip yang sangat besar, dari
ratusan GB
(salah satu
arsip ZIM kami berukuran 166 GB!) bahkan pada perangkat bermemori rendah, adalah
File API. API ini
didukung secara universal di browser apa pun, bahkan
browser yang sangat lama pun, sehingga
bertindak sebagai penggantian universal ketika API yang lebih baru tidak didukung. 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 menyimpan objek File yang pada dasarnya merupakan metadata yang merujuk ke data pokok dalam penyimpanan. Secara teknis, backend berorientasi objek Kiwix, yang ditulis dalam JavaScript murni sisi klien, membaca potongan kecil arsip besar sesuai kebutuhan. Jika potongan tersebut perlu didekompresi, backend akan meneruskannya ke dekompresi, yang akan mendapatkan potongan lebih lanjut jika diminta, hingga blob penuh didekompresi (biasanya artikel atau aset). Artinya, arsip besar tidak perlu dibaca sepenuhnya ke dalam memori.
Universal seperti apa adanya, File API memiliki kelemahan yang membuat aplikasi Kiwix JS tampak kaku dan kuno dibandingkan dengan aplikasi native: API 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 lainnya, developer Kiwix JS pada awalnya menggunakan rute Elektron. ElectronJS adalah framework luar biasa yang menyediakan fitur canggih, termasuk akses penuh ke sistem file menggunakan Node API. Namun, cara ini memiliki beberapa kelemahan umum:
- Aplikasi ini hanya berjalan di sistem operasi desktop.
- Besar dan berat (70 MB–100 MB).
Ukuran aplikasi Electron, karena salinan lengkap Chromium disertakan dengan setiap aplikasi, sangat buruk dibandingkan dengan hanya 5,1 MB untuk PWA yang diperkecil dan dipaketkan.
Jadi, apakah ada cara Kiwix dapat memperbaiki situasi bagi pengguna PWA?
File System Access API siap membantu
Sekitar tahun 2019, Kiwix menemukan API baru yang sedang menjalani uji coba asal di Chrome 78, lalu disebut Native File System API. Plugin ini menjanjikan kemampuan untuk mendapatkan handle file untuk sebuah file atau folder dan menyimpannya di database IndexedDB. Yang terpenting, handle 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 prompt izin cepat). Pada saat mencapai produksi, nama ini telah diganti namanya menjadi File System Access API, dan bagian intinya distandarkan oleh HOWWG sebagai File System API (FSA).
Jadi, bagaimana cara kerja bagian Akses Sistem File pada API? Beberapa hal penting yang perlu diperhatikan:
- Ini adalah API asinkron (kecuali untuk fungsi khusus di Pekerja Web).
- Pemilih file atau direktori harus diluncurkan secara terprogram dengan menangkap gestur pengguna (klik atau ketuk pada 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 menampilkan permintaan izin jika tidak dimulai oleh gestur pengguna.
Kode ini relatif mudah, selain harus menggunakan IndexedDB API untuk menyimpan nama file dan direktori. Kabar baiknya adalah ada beberapa library yang melakukan banyak tugas sulit untuk Anda, seperti browser-fs-access. Di Kiwix JS, kami memutuskan untuk bekerja langsung dengan API, yang didokumentasikan dengan sangat baik.
Membuka pemilih file dan direktori
Membuka pemilih file terlihat seperti ini (di sini menggunakan Promise, tetapi jika
Anda lebih menyukai async/await
sugar, 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,
);
});
Perlu diperhatikan bahwa agar lebih praktis, kode ini hanya memproses file yang pertama kali dipilih (dan melarang memilih lebih dari satu). Jika Anda ingin mengizinkan pemilihan beberapa file dengan { multiple: true }
, Anda cukup menggabungkan 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 bisa dikatakan lebih baik dengan meminta pengguna
memilih direktori yang berisi file tersebut, bukan file individual di dalamnya,
terutama karena pengguna Kiwix cenderung mengatur semua file ZIM dalam
direktori yang sama. Kode untuk meluncurkan pemilih direktori hampir
sama seperti di atas, kecuali Anda menggunakan
window.showDirectoryPicker.then(function (dirHandle) { … });
.
Memproses nama 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 hal ini, kecuali jika Anda menggunakan library abstraksi. Implementasi
Kiwix untuk hal ini dapat dilihat di file
cache.js
,
tetapi dapat disederhanakan secara signifikan jika hanya digunakan untuk menyimpan dan mengambil
file atau handle folder.
Memproses direktori sedikit lebih rumit karena Anda harus melakukan iterasi melalui entri dalam 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 PWA Kiwix, secara 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 dalam entryList
, Anda nanti harus mendapatkan file
dengan entry.getFile().then(function (file) { … })
saat perlu menggunakannya, atau
yang setara menggunakan const file = await entry.getFile()
dalam
async function
.
Bisakah kita melangkah lebih jauh?
Persyaratan bagi pengguna untuk memberikan izin yang dimulai dengan gestur pengguna pada peluncuran aplikasi berikutnya akan menambahkan sedikit hambatan untuk membuka file dan folder (kembali), tetapi masih jauh lebih mudah daripada dipaksa untuk memilih kembali file. Developer Chromium saat ini menyelesaikan kode yang akan memberikan izin persisten untuk PWA yang diinstal. Hal ini dicari oleh banyak developer PWA, dan sangat diantisipasi.
Tapi bagaimana jika kita tidak harus menunggu?! Kiwix developer baru-baru ini menemukan bahwa
semua permintaan izin dapat dihapus saat ini, dengan menggunakan fitur baru
dari File Access API yang didukung oleh browser Chromium dan Firefox (dan sebagian didukung oleh Safari, tetapi masih
tidak ada FileSystemWritableFileStream
).
Fitur baru ini adalah Origin Private File System.
Menjadi yang sepenuhnya native: Origin Private File System
Origin Private File System (OPFS) masih merupakan fitur eksperimental di PWA Kiwix, tetapi tim sangat antusias untuk mendorong pengguna agar mencobanya karena sebagian besar mampu menjembatani kesenjangan antara aplikasi native dan aplikasi Web. Berikut ini manfaat utamanya:
- Arsip di OPFS dapat diakses tanpa perintah izin, bahkan saat diluncurkan. Pengguna dapat melanjutkan membaca artikel, dan menjelajahi arsip, dari bagian terakhir yang mereka tinggalkan di sesi sebelumnya, tanpa hambatan.
- Fitur ini memberikan akses yang sangat dioptimalkan ke file yang tersimpan di dalamnya: di Android kami melihat peningkatan kecepatan antara lima dan sepuluh kali lebih cepat.
Akses file standar di Android yang menggunakan File API sangat lambat, terutama (seperti yang sering terjadi bagi pengguna Kiwix) jika arsip besar disimpan di kartu microSD, bukan di penyimpanan perangkat. Itu semua berubah dengan API baru ini. Meskipun sebagian besar pengguna tidak dapat menyimpan file sebesar 97 GB di OPFS (yang memakai penyimpanan perangkat, bukan penyimpanan kartu microSD), file ini sangat cocok untuk menyimpan arsip berukuran kecil hingga sedang. Anda menginginkan ensiklopedia medis paling lengkap dari WikiProject Medicine? Tidak masalah, pada 1,7 GB sangat cocok di OPFS! (Tips: cari other → mdwiki_en_all_maxi di in-app library.)
Cara kerja OPFS
OPFS adalah sistem file yang disediakan oleh browser, terpisah untuk setiap asal, yang dapat dianggap mirip dengan penyimpanan terbatas aplikasi di Android. File dapat diimpor ke OPFS dari sistem file yang terlihat oleh pengguna, atau dapat didownload langsung ke dalamnya (API juga memungkinkan pembuatan file di OPFS). Setelah berada di OPFS, file akan diisolasi dari bagian lain perangkat. Di browser berbasis Chromium desktop, Anda juga dapat mengekspor file kembali dari OPFS ke sistem file yang terlihat oleh pengguna.
Untuk menggunakan OPFS, langkah pertama adalah meminta akses ke OPFS, 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 channel 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
membutuhkannya). Anggaplah Anda sudah memiliki beberapa file di OPFS dan ingin menggunakannya, lalu, dengan 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 harus menggunakan getFile()
pada entri apa pun yang ingin Anda gunakan dari array archiveList
.
Mengimpor file ke OPFS
Jadi, bagaimana Anda memasukkan file ke OPFS sejak awal? Tidak secepat itu. Pertama, Anda perlu memperkirakan jumlah penyimpanan yang dapat digunakan, dan memastikan pengguna tidak mencoba memasukkan file berukuran 97 GB jika ukurannya tidak sesuai.
Mendapatkan estimasi kuota itu mudah:
navigator.storage.estimate().then(function (estimate) { … });
. Sedikit lebih sulit
untuk menampilkan ini kepada pengguna. Di aplikasi Kiwix, kami memilih
panel dalam aplikasi kecil 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 Anda lihat, ada juga tombol yang memungkinkan pengguna menambahkan file ke OPFS dari
sistem file yang terlihat oleh pengguna. Kabar baiknya di sini adalah Anda dapat menggunakan File API untuk mendapatkan objek (atau objek) File yang diperlukan yang akan diimpor. Bahkan, sebaiknya Anda tidak menggunakan window.showOpenFilePicker()
karena metode ini
tidak didukung oleh Firefox, sedangkan OPFS paling didukung.
Tombol Tambahkan file yang terlihat dalam screenshot di atas bukanlah alat pilih file lama, tetapi tombol ini melakukan click()
alat pilih lama yang tersembunyi (elemen <input type="file" multiple … />
) saat diklik atau diketuk. Aplikasi
kemudian hanya menangkap peristiwa change
dari input file tersembunyi, memeriksa
ukuran file, dan menolaknya jika terlalu besar untuk kuota. Jika semuanya berjalan lancar, 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 yang paling cepat, Kiwix juga menampilkan banner dan indikator lingkaran berputar kecil saat arsip sedang diimpor. Tim tidak tahu cara menambahkan indikator progres untuk operasi ini: jika Anda berhasil, tolong jawab melalui kartu pos.
Jadi, bagaimana cara Kiwix menerapkan fungsi importOPFSEntries()
? Hal ini melibatkan
penggunaan metode fileHandle.createWriteable()
, yang secara efektif memungkinkan
setiap file di-streaming ke OPFS. Semua kerja keras 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 streaming file langsung ke OPFS
Variasi dari hal ini adalah kemampuan untuk melakukan streaming file dari Internet secara langsung ke OPFS, atau ke direktori apa pun yang sudah memiliki handle direktori (yaitu, direktori yang dipilih dengan window.showDirectoryPicker()
). Kode 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
disalurkan ke penulis file baru
dalam OPFS.
Dalam hal ini, Kiwix dapat menghitung byte yang melewati
ReadableStream
, sehingga memberikan indikator progres kepada pengguna, serta memperingatkan
mereka untuk tidak keluar dari aplikasi selama proses download. Kode ini agak terlalu rumit untuk ditampilkan di sini, tetapi karena aplikasi kita adalah aplikasi FOSS, Anda dapat melihat sumbernya jika tertarik untuk melakukan hal serupa. Seperti inilah tampilan UI Kiwix (nilai progres yang berbeda yang ditampilkan di bawah ini adalah karena hanya mengupdate
banner saat persentase berubah, tetapi memperbarui panel Progres download
secara lebih teratur):
Karena proses download dapat menjadi operasi yang cukup lama, Kiwix memungkinkan pengguna menggunakan aplikasi dengan bebas selama operasi, tetapi memastikan banner selalu ditampilkan, sehingga pengguna diingatkan untuk tidak menutup aplikasi hingga operasi download selesai.
Mengimplementasikan pengelola file mini dalam aplikasi
Pada tahap ini, developer PWA Kiwix menyadari bahwa menambahkan file ke OPFS tidaklah cukup. Aplikasi ini juga perlu memberi pengguna cara untuk menghapus file yang tidak lagi diperlukan dari area penyimpanan ini, dan idealnya, juga, untuk mengekspor file yang terkunci di OPFS kembali ke sistem file yang terlihat oleh pengguna. Oleh karena itu, penerapan sistem pengelolaan file mini di dalam aplikasi menjadi penting.
Sekilas tentang ekstensi OPFS Explorer yang luar biasa untuk Chrome (juga dapat digunakan di Edge). Update ini menambahkan tab di alat developer yang memungkinkan Anda melihat persis apa yang ada di OPFS, dan juga menghapus file jahat atau gagal. Kami sangat berharga 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 memungkinkan Kiwix menggunakan metode window.showSaveFilePicker()
. Jika
file Kiwix lebih kecil dari beberapa GB, kami akan dapat membuat blob
di memori, memberikan URL, lalu mendownloadnya ke sistem file yang terlihat oleh pengguna.
Sayangnya, hal itu tidak mungkin dilakukan dengan arsip sebesar itu. Jika didukung,
ekspor cukup mudah: hampir sama, secara terbalik, seperti menyimpan
file ke OPFS (mendapatkan handle pada file yang akan disimpan, minta pengguna memilih
lokasi untuk menyimpannya dengan window.showSaveFilePicker()
, lalu gunakan
createWriteable()
pada saveHandle
). Anda dapat
melihat kode
di repo.
Penghapusan file didukung oleh semua browser, dan dapat dilakukan dengan dirHandle.removeEntry('filename')
sederhana. Dalam kasus Kiwix, kami lebih memilih untuk
mengiterasi entri OPFS seperti yang kami lakukan di atas, sehingga dapat memeriksa bahwa
file yang dipilih ada terlebih dahulu dan meminta konfirmasi, tetapi hal ini mungkin
tidak diperlukan untuk semua orang. Sekali lagi, Anda dapat
memeriksa kode kami
jika tertarik.
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 bagi pengguna tentang apa yang akan mereka lakukan. Pengguna kemudian 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 oleh pengguna.
Pekerjaan developer tidak pernah selesai
OPFS adalah inovasi hebat bagi developer PWA, yang menyediakan fitur pengelolaan file yang sangat canggih yang sangat berguna untuk menutup kesenjangan antara aplikasi native dan aplikasi Web. Namun, developer adalah kelompok yang menyedihkan—mereka tidak pernah puas! OPFS hampir sempurna, namun belum cukup... Hebatnya, fitur utama dapat berfungsi di browser Chromium dan Firefox, serta dapat diimplementasikan di Android dan desktop. Kami berharap rangkaian fitur lengkap juga akan segera diterapkan di Safari dan iOS. Masalah berikut akan tetap ada:
- Firefox saat ini menetapkan batas 10 GB untuk kuota OPFS, tidak peduli berapa banyak kapasitas disk yang ada. Meskipun bagi sebagian besar penulis PWA, ini mungkin cukup, untuk Kiwix, itu cukup terbatas. Untungnya, browser Chromium jauh lebih murah.
- Saat ini, mengekspor file besar dari OPFS ke
sistem file yang terlihat oleh pengguna di browser seluler atau Firefox desktop tidak dapat dilakukan karena
window.showSaveFilePicker()
tidak diterapkan. Dalam browser ini, file besar secara efektif terjebak dalam OPFS. Hal ini bertentangan dengan etos Kiwix tentang akses terbuka ke konten, dan kemampuan untuk berbagi arsip antarpengguna, terutama di area konektivitas Internet yang terputus-putus atau mahal. - Pengguna tidak dapat mengontrol penyimpanan mana yang akan digunakan oleh sistem file virtual OPFS. Hal ini terutama menimbulkan masalah pada perangkat seluler, yang mungkin memiliki ruang penyimpanan perangkat besar pada kartu microSD, tetapi ukuran yang sangat kecil pada penyimpanan perangkat.
Namun secara keseluruhan, ini adalah masalah kecil yang merupakan langkah maju yang besar untuk akses file di PWA. Tim PWA Kiwix sangat berterima kasih kepada developer dan advokat Chromium yang pertama kali mengusulkan dan mendesain File System Access API, serta atas kerja keras dalam mencapai konsensus di antara vendor browser tentang pentingnya Origin Private File System. Untuk PWA Kiwix JS, PWA Kiwix JS telah menyelesaikan banyak masalah UX yang telah merusak aplikasi di masa lalu, dan membantu kami dalam upaya meningkatkan aksesibilitas konten Kiwix bagi semua orang. Coba PWA Kiwix dan beri tahu developer pendapat Anda.
Untuk beberapa sumber daya hebat tentang kemampuan PWA, lihat situs-situs ini:
- Etalase Project Fugu API: koleksi aplikasi Web yang menunjukkan kemampuan yang menutup kesenjangan antara aplikasi native dan PWA.
- Yang dapat dilakukan PWA sekarang: pameran tentang berbagai hal yang dapat dilakukan PWA saat ini.