brief: | i18n.site sekarang mendukung pencarian teks lengkap tanpa server.
Artikel ini memperkenalkan penerapan teknologi pencarian teks lengkap front-end murni, termasuk indeks terbalik yang dibuat oleh IndexedDB, pencarian awalan, pengoptimalan segmentasi kata, dan dukungan multi-bahasa.
Dibandingkan dengan solusi yang ada, pencarian teks lengkap front-end murni i18n.site berukuran kecil dan cepat, cocok untuk situs web berukuran kecil dan menengah seperti dokumen dan blog, dan tersedia secara offline.
Setelah beberapa minggu pengembangan, i18n.site (alat pembuatan situs web markdown multilingualtranslation & yang murni statis) kini mendukung pencarian teks lengkap front-end murni.
Artikel ini akan membagikan implementasi teknis dari i18n.site
pencarian teks lengkap front-end murni. Kunjungi i18n.site
Kode open source : Cari kernel / antarmuka interaktif
Untuk situs web statis murni berukuran kecil dan menengah seperti dokumen/blog pribadi, membangun backend pencarian teks lengkap yang dibuat sendiri terlalu berat, dan pencarian teks lengkap bebas layanan adalah pilihan yang lebih umum.
Solusi pencarian teks lengkap tanpa server terbagi dalam dua kategori besar:
Pertama, penyedia layanan pencarian pihak ketiga yang algolia.com menyediakan komponen front-end untuk pencarian teks lengkap.
Layanan tersebut memerlukan pembayaran berdasarkan volume pencarian, dan sering kali tidak tersedia bagi pengguna di Tiongkok daratan karena masalah seperti kepatuhan situs web.
Itu tidak dapat digunakan secara offline, tidak dapat digunakan di intranet, dan memiliki keterbatasan yang besar. Artikel ini tidak membahas banyak hal.
Yang kedua adalah pencarian teks lengkap front-end murni.
Saat ini, pencarian teks lengkap front-end murni yang umum mencakup lunrjs dan ElasticLunr.js (berdasarkan lunrjs
pengembangan sekunder).
lunrjs
Ada dua cara untuk membangun indeks, dan keduanya memiliki permasalahannya masing-masing.
File indeks yang dibuat sebelumnya
Karena indeks berisi kata-kata dari semua dokumen, maka ukurannya besar. Setiap kali dokumen ditambahkan atau diubah, file indeks baru harus dimuat. Ini akan menambah waktu tunggu pengguna dan menghabiskan banyak bandwidth.
Muat dokumen dan buat indeks dengan cepat
Membangun indeks adalah tugas komputasi yang intensif. Membangun kembali indeks setiap kali Anda mengaksesnya akan menyebabkan kelambatan yang jelas dan pengalaman pengguna yang buruk.
Selain lunrjs
, ada beberapa solusi pencarian teks lengkap lainnya, seperti :
fusejs , hitung kesamaan antar string yang akan dicari.
Kinerja solusi ini sangat buruk dan tidak dapat digunakan untuk pencarian teks lengkap (lihat Fuse.js Kueri yang panjang memerlukan waktu lebih dari 10 detik, bagaimana cara mengoptimalkannya? ).
TinySearch , gunakan filter Bloom untuk mencari, tidak dapat digunakan untuk pencarian awalan (misalnya, masukkan goo
, cari good
, google
), dan tidak dapat mencapai efek penyelesaian otomatis serupa.
Karena kekurangan dari solusi yang ada, i18n.site
mengembangkan solusi pencarian teks lengkap front-end murni baru, yang memiliki karakteristik sebagai berikut :
gzip
adalah 6.9KB
(sebagai perbandingan, ukuran lunrjs
adalah 25KB
)indexedb
, yang memakan lebih sedikit memori dan cepat.Di bawah ini, i18n.site
rincian implementasi teknis akan diperkenalkan secara rinci.
Segmentasi kata menggunakan segmentasi kata asli browser Intl.Segmenter
, dan semua browser utama mendukung antarmuka ini.
Kode segmentasi kata coffeescript
adalah sebagai berikut
SEG = new Intl.Segmenter 0, granularity: "word"
seg = (txt) =>
r = []
for {segment} from SEG.segment(txt)
for i from segment.split('.')
i = i.trim()
if i and !'| `'.includes(i) and !/\p{P}/u.test(i)
r.push i
r
export default seg
export segqy = (q) =>
seg q.toLocaleLowerCase()
di dalam:
/\p{P}/
adalah ekspresi reguler yang cocok dengan tanda baca. Simbol pencocokan khusus meliputi: ! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _
{ | } .</p><ul><li>
split('.')karena
Firefoxsegmentasi kata browser tidak menyegmentasikan
. ` .
5 tabel penyimpanan objek dibuat pada IndexedDB
:
word
: id - kata-katadoc
: id - Dokumen url - Nomor versi dokumendocWord
: Array dokumen id - kata idprefix
: Array awalan - kata idrindex
: Kata id - Dokumen id : Array nomor barisMasukkan array dokumen url
dan nomor versi ver
, dan cari apakah dokumen tersebut ada di tabel doc
Jika tidak ada, buat indeks terbalik. Pada saat yang sama, hapus indeks terbalik untuk dokumen-dokumen yang tidak diteruskan.
Dengan cara ini, pengindeksan tambahan dapat dicapai dan jumlah penghitungan dikurangi.
Dalam interaksi front-end, bilah kemajuan pemuatan indeks dapat ditampilkan untuk menghindari kelambatan saat memuat untuk pertama kalinya. Lihat "Bilah Kemajuan dengan Animasi, Berdasarkan Single progress + Pure css Implementation" English / Chinese .
Proyek ini idb berdasarkan enkapsulasi asinkron IndexedDB
Pembacaan dan penulisan IndexedDB tidak sinkron. Saat membuat indeks, dokumen akan dimuat secara bersamaan untuk membuat indeks.
Untuk menghindari kehilangan sebagian data yang disebabkan oleh penulisan kompetitif, Anda dapat merujuk ke kode coffeescript
di bawah dan menambahkan cache ing
antara membaca dan menulis untuk mencegat penulisan yang bersaing.
pusher = =>
ing = new Map()
(table, id, val)=>
id_set = ing.get(id)
if id_set
id_set.add val
return
id_set = new Set([val])
ing.set id, id_set
pre = await table.get(id)
li = pre?.li or []
loop
to_add = [...id_set]
li.push(...to_add)
await table.put({id,li})
for i from to_add
id_set.delete i
if not id_set.size
ing.delete id
break
return
rindexPush = pusher()
prefixPush = pusher()
Pencarian terlebih dahulu akan mengelompokkan kata kunci yang dimasukkan oleh pengguna.
Asumsikan ada N
kata setelah segmentasi kata. Saat mengembalikan hasil, hasil yang berisi semua kata kunci akan dikembalikan terlebih dahulu, lalu hasil yang berisi N-1
, N-2
,..., 1
kata kunci akan dikembalikan.
Hasil pencarian yang ditampilkan pertama kali memastikan keakuratan kueri, dan hasil yang dimuat selanjutnya (klik tombol muat lebih banyak) memastikan tingkat penarikan kembali.
Untuk meningkatkan kecepatan respons, pencarian menggunakan generator yield
untuk menerapkan pemuatan sesuai permintaan, dan kembali limit
kali ada hasil yang ditanyakan.
Perhatikan bahwa setiap kali Anda mencari lagi setelah yield
, Anda perlu membuka kembali transaksi kueri IndexedDB
.
Untuk menampilkan hasil pencarian saat pengguna sedang mengetik, misalnya ketika wor
dimasukkan, kata-kata yang diawali dengan wor
seperti words
dan work
akan ditampilkan.
Kernel pencarian akan menggunakan tabel prefix
untuk segmentasi kata terakhir demi kata untuk menemukan semua kata yang diawali dengannya, dan mencari secara berurutan.
Fungsi anti-guncangan debounce
juga digunakan dalam interaksi front-end (diimplementasikan sebagai berikut) untuk mengurangi frekuensi input pengguna yang memicu pencarian dan mengurangi jumlah penghitungan.
export default (wait, func) => {
var timeout;
return function(...args) {
clearTimeout(timeout);
timeout = setTimeout(func.bind(this, ...args), wait);
};
}
Tabel indeks tidak menyimpan teks asli, hanya kata-kata, sehingga mengurangi jumlah penyimpanan.
Menyorot hasil pencarian memerlukan memuat ulang teks asli, dan mencocokkan service worker
dapat menghindari permintaan jaringan berulang.
Pada saat yang sama, karena service worker
menyimpan semua artikel dalam cache, setelah pengguna melakukan pencarian, seluruh situs web, termasuk pencarian, tersedia secara offline.
Solusi pencarian front-end murni i18n.site
dioptimalkan untuk MarkDown
dokumen.
Saat menampilkan hasil pencarian, nama bab akan ditampilkan dan bab tersebut akan dinavigasi saat diklik.
Pencarian teks lengkap terbalik diterapkan murni di ujung depan, tidak diperlukan server. Sangat cocok untuk website kecil dan menengah seperti dokumen dan blog pribadi.
i18n.site
Pencarian front-end murni open source yang dikembangkan sendiri, berukuran kecil dan respons cepat, memecahkan kekurangan pencarian teks lengkap front-end murni saat ini dan memberikan pengalaman pengguna yang lebih baik.