Latar belakang
Service worker memberi developer web kemampuan untuk merespons permintaan jaringan yang dibuat oleh aplikasi web mereka, sehingga mereka dapat terus bekerja meskipun sedang offline, melawan lie-fi, dan menerapkan interaksi cache yang kompleks seperti stale-while-revalidate. Namun, service worker secara historis terikat dengan origin tertentu—sebagai pemilik aplikasi web, Anda bertanggung jawab untuk menulis dan men-deploy service worker guna mencegat semua permintaan jaringan yang dibuat aplikasi web Anda. Dalam model tersebut, setiap pekerja layanan bertanggung jawab untuk menangani bahkan permintaan lintas-asal, misalnya ke API pihak ketiga atau untuk font web.
Bagaimana jika penyedia API pihak ketiga, atau font web, atau layanan umum lainnya memiliki kemampuan untuk men-deploy pekerja layanan mereka sendiri yang memiliki peluang untuk menangani permintaan yang dibuat oleh origin lain ke origin mereka? Penyedia dapat menerapkan logika jaringan kustom mereka sendiri, dan memanfaatkan satu instance cache yang kredibel untuk menyimpan respons mereka. Sekarang, berkat pengambilan asing, jenis deployment pekerja layanan pihak ketiga tersebut menjadi kenyataan.
Men-deploy pekerja layanan yang menerapkan pengambilan asing akan bermanfaat bagi penyedia layanan apa pun yang diakses melalui permintaan HTTPS dari browser—cukup pikirkan skenario saat Anda dapat menyediakan versi layanan yang tidak bergantung pada jaringan, tempat browser dapat memanfaatkan cache resource umum. Layanan yang dapat memanfaatkannya mencakup, tetapi tidak terbatas pada:
- Penyedia API dengan antarmuka RESTful
- Penyedia font web
- Penyedia analisis
- Penyedia hosting gambar
- Jaringan penayangan konten generik
Bayangkan, misalnya, Anda adalah penyedia analisis. Dengan men-deploy pekerja layanan pengambilan asing, Anda dapat memastikan bahwa semua permintaan ke layanan Anda yang gagal saat pengguna offline akan diantrekan dan di-replay setelah konektivitas kembali. Meskipun klien layanan dapat menerapkan perilaku serupa melalui pekerja layanan pihak pertama, mengharuskan setiap klien menulis logika khusus untuk layanan Anda tidak sebesar mengandalkan pekerja layanan pengambilan asing bersama yang Anda deploy.
Prasyarat
Token Uji Coba Origin
Pengambilan asing masih dianggap eksperimental. Agar desain ini tidak terburu-buru sebelum ditentukan sepenuhnya dan disepakati oleh vendor browser, desain tersebut telah diimplementasikan di Chrome 54 sebagai Uji Coba Origin. Selama pengambilan asing masih bersifat eksperimental, untuk menggunakan fitur baru ini dengan layanan yang Anda host, Anda harus meminta token yang dicakup untuk asal layanan tertentu. Token harus disertakan sebagai header respons HTTP di semua permintaan lintas-asal untuk resource yang ingin Anda tangani melalui pengambilan asing, serta dalam respons untuk resource JavaScript pekerja layanan Anda:
Origin-Trial: token_obtained_from_signup
Uji coba ini akan berakhir pada Maret 2017. Pada saat itu, kami berharap telah mengetahui perubahan yang diperlukan untuk menstabilkan fitur, dan (semoga) mengaktifkannya secara default. Jika pengambilan asing tidak diaktifkan secara default pada saat itu, fungsi yang terikat dengan token Uji Coba Origin yang ada akan berhenti berfungsi.
Untuk memfasilitasi eksperimen dengan pengambilan asing sebelum mendaftar untuk token Uji Coba Origin resmi, Anda dapat mengabaikan persyaratan di Chrome untuk komputer lokal dengan membuka chrome://flags/#enable-experimental-web-platform-features
dan mengaktifkan tanda "Fitur Platform Web Eksperimental". Perhatikan bahwa tindakan ini perlu dilakukan di setiap instance Chrome yang ingin Anda gunakan dalam eksperimen lokal, sedangkan dengan token Uji Coba Origin, fitur tersebut akan tersedia untuk semua pengguna Chrome Anda.
HTTPS
Seperti semua deployment pekerja layanan, server web yang Anda gunakan untuk menayangkan resource dan skrip pekerja layanan harus diakses melalui HTTPS. Selain itu, intersepsi pengambilan asing hanya berlaku untuk permintaan yang berasal dari halaman yang dihosting di origin aman, sehingga klien layanan Anda harus menggunakan HTTPS untuk memanfaatkan penerapan pengambilan asing Anda.
Menggunakan Pengambilan Asing
Setelah prasyarat selesai, mari kita pelajari detail teknis yang diperlukan untuk menyiapkan dan menjalankan pekerja layanan pengambilan asing.
Mendaftarkan pekerja layanan
Tantangan pertama yang mungkin Anda hadapi adalah cara mendaftarkan pekerja layanan. Jika sudah pernah menggunakan pekerja layanan sebelumnya, Anda mungkin sudah memahami hal-hal berikut:
// You can't do this!
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('service-worker.js');
}
Kode JavaScript ini untuk pendaftaran pekerja layanan pihak pertama masuk akal dalam konteks aplikasi web, yang dipicu oleh pengguna yang membuka URL yang Anda kontrol. Namun, ini bukan pendekatan yang tepat untuk mendaftarkan pekerja layanan pihak ketiga, jika satu-satunya interaksi browser dengan server Anda adalah meminta sub-resource tertentu, bukan navigasi lengkap. Jika browser meminta, misalnya, gambar dari server CDN yang Anda kelola, Anda tidak dapat menambahkan cuplikan JavaScript tersebut ke respons dan berharap cuplikan tersebut akan dijalankan. Metode pendaftaran pekerja layanan yang berbeda, di luar konteks eksekusi JavaScript normal, diperlukan.
Solusinya berupa header HTTP yang dapat disertakan server Anda dalam respons apa pun:
Link: </service-worker.js>; rel="serviceworker"; scope="/"
Mari kita uraikan contoh header tersebut menjadi komponennya, yang masing-masing dipisahkan oleh karakter ;
.
</service-worker.js>
diperlukan, dan digunakan untuk menentukan jalur ke file pekerja layanan (ganti/service-worker.js
dengan jalur yang sesuai ke skrip Anda). Ini berkaitan langsung dengan stringscriptURL
yang akan diteruskan sebagai parameter pertama kenavigator.serviceWorker.register()
. Nilai harus diapit dalam karakter<>
(seperti yang diwajibkan oleh spesifikasi headerLink
), dan jika URL relatif, bukan absolut, yang diberikan, URL tersebut akan ditafsirkan sebagai relatif terhadap lokasi respons.rel="serviceworker"
juga diperlukan, dan harus disertakan tanpa perlu penyesuaian.scope=/
adalah deklarasi cakupan opsional, setara dengan stringoptions.scope
yang dapat Anda teruskan sebagai parameter kedua kenavigator.serviceWorker.register()
. Untuk banyak kasus penggunaan, Anda tidak masalah menggunakan cakupan default, jadi jangan ragu untuk menghapusnya kecuali jika Anda tahu bahwa Anda memerlukannya. Batasan yang sama seputar cakupan maksimum yang diizinkan, beserta kemampuan untuk melonggarkan batasan tersebut melalui headerService-Worker-Allowed
, berlaku untuk pendaftaran headerLink
.
Sama seperti pendaftaran pekerja layanan "tradisional", penggunaan header Link
akan menginstal pekerja layanan yang akan digunakan untuk permintaan berikutnya yang dibuat terhadap cakupan terdaftar. Isi respons yang menyertakan header khusus akan digunakan apa adanya, dan langsung tersedia untuk halaman, tanpa menunggu pekerja layanan asing menyelesaikan penginstalan.
Perlu diingat bahwa pengambilan asing saat ini diterapkan sebagai Uji Coba Origin, sehingga selain header respons Link, Anda juga harus menyertakan header Origin-Trial
yang valid. Kumpulan header respons minimum yang harus ditambahkan untuk mendaftarkan pekerja layanan pengambilan asing Anda adalah
Link: </service-worker.js>; rel="serviceworker"
Origin-Trial: token_obtained_from_signup
Men-debug pendaftaran
Selama pengembangan, sebaiknya konfirmasi bahwa pekerja layanan pengambilan asing telah diinstal dan memproses permintaan dengan benar. Ada beberapa hal yang dapat Anda periksa di Developer Tools Chrome untuk mengonfirmasi bahwa semuanya berfungsi seperti yang diharapkan.
Apakah header respons yang tepat dikirim?
Untuk mendaftarkan service worker pengambilan asing, Anda perlu menetapkan header Link pada respons ke resource yang dihosting di domain Anda, seperti yang dijelaskan sebelumnya dalam postingan ini. Selama periode Uji Coba Origin, dan dengan asumsi Anda tidak menetapkan chrome://flags/#enable-experimental-web-platform-features
, Anda juga perlu menetapkan header respons Origin-Trial
. Anda dapat mengonfirmasi bahwa server web Anda menetapkan header tersebut dengan melihat entri di panel Jaringan DevTools:
Apakah pekerja layanan Pengambilan Luar Negeri terdaftar dengan benar?
Anda juga dapat mengonfirmasi pendaftaran pekerja layanan yang mendasarinya, termasuk cakupannya, dengan melihat daftar lengkap pekerja layanan di panel Aplikasi DevTools. Pastikan untuk memilih opsi "Tampilkan semua", karena secara default, Anda hanya akan melihat pekerja layanan untuk origin saat ini.
Pengendali peristiwa penginstalan
Setelah Anda mendaftarkan pekerja layanan pihak ketiga, pekerja layanan tersebut akan mendapatkan kesempatan untuk merespons peristiwa install
dan activate
, seperti halnya pekerja layanan lainnya. Fungsi ini dapat memanfaatkan peristiwa tersebut untuk, misalnya, mengisi cache dengan resource yang diperlukan selama peristiwa install
, atau memangkas cache yang sudah tidak berlaku dalam peristiwa activate
.
Selain aktivitas penyimpanan cache peristiwa install
normal, ada langkah tambahan yang diperlukan di dalam pengendali peristiwa install
pekerja layanan pihak ketiga Anda. Kode Anda harus memanggil registerForeignFetch()
, seperti dalam contoh berikut:
self.addEventListener('install', event => {
event.registerForeignFetch({
scopes: [self.registration.scope], // or some sub-scope
origins: ['*'] // or ['https://example.com']
});
});
Ada dua opsi konfigurasi, keduanya diperlukan:
scopes
mengambil array dari satu atau beberapa string, yang masing-masing mewakili cakupan untuk permintaan yang akan memicu peristiwaforeignfetch
. Tapi tunggu, Anda mungkin berpikir, Saya sudah menentukan cakupan selama pendaftaran pekerja layanan! Memang benar, dan cakupan keseluruhan tersebut masih relevan—setiap cakupan yang Anda tentukan di sini harus sama dengan atau merupakan sub-cakupan dari cakupan keseluruhan pekerja layanan. Batasan cakupan tambahan di sini memungkinkan Anda men-deploy pekerja layanan serbaguna yang dapat menangani peristiwafetch
pihak pertama (untuk permintaan yang dibuat dari situs Anda sendiri) dan peristiwaforeignfetch
pihak ketiga (untuk permintaan yang dibuat dari domain lain), serta memperjelas bahwa hanya sebagian dari cakupan yang lebih besar yang akan memicuforeignfetch
. Dalam praktiknya, jika Anda men-deploy pekerja layanan yang didedikasikan untuk hanya menangani peristiwaforeignfetch
pihak ketiga, Anda hanya perlu menggunakan satu cakupan eksplisit yang sama dengan cakupan keseluruhan pekerja layanan Anda. Itulah yang akan dilakukan contoh di atas, menggunakan nilaiself.registration.scope
.origins
juga menggunakan array yang berisi satu atau beberapa string, dan memungkinkan Anda membatasi pengendaliforeignfetch
agar hanya merespons permintaan dari domain tertentu. Misalnya, jika Anda mengizinkan 'https://example.com' secara eksplisit, permintaan yang dibuat dari halaman yang dihosting dihttps://example.com/path/to/page.html
untuk resource yang ditayangkan dari cakupan pengambilan asing akan memicu pengendali pengambilan asing, tetapi permintaan yang dibuat darihttps://random-domain.com/path/to/page.html
tidak akan memicu pengendali Anda. Kecuali jika Anda memiliki alasan khusus untuk hanya memicu logika pengambilan asing untuk sebagian asal jarak jauh, Anda cukup menentukan'*'
sebagai satu-satunya nilai dalam array, dan semua origin akan diizinkan.
Pengendali peristiwa Forefetch
Setelah Anda menginstal service worker pihak ketiga dan mengonfigurasinya melalui registerForeignFetch()
, service worker tersebut akan mendapatkan kesempatan untuk mencegat permintaan sub-resource lintas origin ke server Anda yang berada dalam cakupan pengambilan asing.
Dalam pekerja layanan pihak pertama tradisional, setiap permintaan akan memicu peristiwa fetch
yang dapat direspons oleh pekerja layanan Anda. Service worker pihak ketiga kami diberi kesempatan untuk menangani peristiwa yang sedikit berbeda, bernama foreignfetch
. Secara konseptual, kedua peristiwa tersebut cukup mirip, dan memberi Anda kesempatan untuk memeriksa permintaan yang masuk, dan secara opsional memberikan respons melalui respondWith()
:
self.addEventListener('foreignfetch', event => {
// Assume that requestLogic() is a custom function that takes
// a Request and returns a Promise which resolves with a Response.
event.respondWith(
requestLogic(event.request).then(response => {
return {
response: response,
// Omit to origin to return an opaque response.
// With this set, the client will receive a CORS response.
origin: event.origin,
// Omit headers unless you need additional header filtering.
// With this set, only Content-Type will be exposed.
headers: ['Content-Type']
};
})
);
});
Meskipun memiliki kesamaan konseptual, ada beberapa perbedaan dalam praktik saat memanggil respondWith()
di ForeignFetchEvent
. Daripada hanya memberikan Response
(atau Promise
yang me-resolve dengan Response
) ke respondWith()
, seperti yang Anda lakukan dengan FetchEvent
, Anda harus meneruskan Promise
yang me-resolve dengan Objek dengan properti tertentu ke respondWith()
ForeignFetchEvent
:
response
diperlukan, dan harus ditetapkan ke objekResponse
yang akan ditampilkan ke klien yang membuat permintaan. Jika Anda memberikan apa pun selainResponse
yang valid, permintaan klien akan dihentikan dengan error jaringan. Tidak seperti saat memanggilrespondWith()
di dalam pengendali peristiwafetch
, Anda harus memberikanResponse
di sini, bukanPromise
yang di-resolve denganResponse
. Anda dapat membuat respons melalui rantai promise, dan meneruskan rantai tersebut sebagai parameter kerespondWith()
foreignfetch
, tetapi rantai harus diselesaikan dengan Objek yang berisi propertiresponse
yang ditetapkan ke objekResponse
. Anda dapat melihat demonstrasinya dalam contoh kode di atas.origin
bersifat opsional, dan digunakan untuk menentukan apakah respons yang ditampilkan buram atau tidak. Jika Anda tidak menyertakannya, respons akan menjadi buram, dan klien akan memiliki akses terbatas ke isi dan header respons. Jika permintaan dibuat denganmode: 'cors'
, menampilkan respons buram akan dianggap sebagai error. Namun, jika menentukan nilai string yang sama dengan asal klien jarak jauh (yang dapat diperoleh melaluievent.origin
), Anda secara eksplisit memilih ikut serta untuk memberikan respons yang didukung CORS kepada klien.headers
juga bersifat opsional, dan hanya berguna jika Anda juga menentukanorigin
dan menampilkan respons CORS. Secara default, hanya header dalam daftar header respons yang ada dalam daftar aman CORS yang akan disertakan dalam respons Anda. Jika Anda perlu memfilter lebih lanjut apa yang ditampilkan, header akan mengambil daftar satu atau beberapa nama header, dan akan menggunakannya sebagai daftar yang diizinkan untuk ditampilkan dalam respons. Hal ini memungkinkan Anda memilih ikut serta dalam CORS sekaligus mencegah header respons yang berpotensi sensitif diekspos langsung ke klien jarak jauh.
Perlu diperhatikan bahwa saat pengendali foreignfetch
dijalankan, pengendali tersebut memiliki akses ke semua kredensial dan otoritas standby asal yang menghosting pekerja layanan. Sebagai developer yang men-deploy pekerja layanan yang mengaktifkan pengambilan asing, Anda bertanggung jawab untuk memastikan bahwa Anda tidak membocorkan data respons dengan hak istimewa yang tidak akan tersedia berdasarkan kredensial tersebut. Mewajibkan keikutsertaan untuk respons CORS adalah salah satu langkah untuk membatasi eksposur yang tidak disengaja, tetapi sebagai developer, Anda dapat secara eksplisit membuat permintaan fetch()
di dalam pengendali foreignfetch
yang tidak menggunakan kredensial tersirat melalui:
self.addEventListener('foreignfetch', event => {
// The new Request will have credentials omitted by default.
const noCredentialsRequest = new Request(event.request.url);
event.respondWith(
// Replace with your own request logic as appropriate.
fetch(noCredentialsRequest)
.catch(() => caches.match(noCredentialsRequest))
.then(response => ({response}))
);
});
Pertimbangan klien
Ada beberapa pertimbangan tambahan yang memengaruhi cara pekerja layanan pengambilan asing menangani permintaan yang dibuat dari klien layanan Anda.
Klien yang memiliki pekerja layanan pihak pertama mereka sendiri
Beberapa klien layanan Anda mungkin sudah memiliki pekerja layanan pihak pertama mereka sendiri, yang menangani permintaan yang berasal dari aplikasi web mereka. Apa artinya ini bagi pekerja layanan pengambilan pihak ketiga dan asing Anda?
Pengendali fetch
di pekerja layanan pihak pertama mendapatkan kesempatan pertama untuk merespons semua permintaan yang dibuat oleh aplikasi web, meskipun ada pekerja layanan pihak ketiga dengan foreignfetch
yang diaktifkan dengan cakupan yang mencakup permintaan. Namun, klien dengan pekerja layanan pihak pertama masih dapat memanfaatkan pekerja layanan pengambilan asing Anda.
Di dalam pekerja layanan pihak pertama, penggunaan fetch()
untuk mengambil resource lintas-asal akan memicu pekerja layanan pengambilan asing yang sesuai. Artinya, kode seperti berikut dapat memanfaatkan pengendali foreignfetch
Anda:
// Inside a client's first-party service-worker.js:
self.addEventListener('fetch', event => {
// If event.request is under your foreign fetch service worker's
// scope, this will trigger your foreignfetch handler.
event.respondWith(fetch(event.request));
});
Demikian pula, jika ada pengendali pengambilan pihak pertama, tetapi tidak memanggil event.respondWith()
saat menangani permintaan untuk resource lintas asal, permintaan tersebut akan otomatis "dilewati" ke pengendali foreignfetch
Anda:
// Inside a client's first-party service-worker.js:
self.addEventListener('fetch', event => {
if (event.request.mode === 'same-origin') {
event.respondWith(localRequestLogic(event.request));
}
// Since event.respondWith() isn't called for cross-origin requests,
// any foreignfetch handlers scoped to the request will get a chance
// to provide a response.
});
Jika pengendali fetch
pihak pertama memanggil event.respondWith()
, tetapi tidak menggunakan fetch()
untuk meminta resource dalam cakupan pengambilan asing, pekerja layanan pengambilan asing Anda tidak akan mendapatkan kesempatan untuk menangani permintaan.
Klien yang tidak memiliki pekerja layanan sendiri
Semua klien yang membuat permintaan ke layanan pihak ketiga bisa mendapatkan keuntungan ketika layanan tersebut men-deploy pekerja layanan pengambilan asing, meskipun klien tersebut belum menggunakan pekerja layanannya sendiri. Tidak ada hal khusus yang perlu dilakukan klien untuk memilih menggunakan pekerja layanan pengambilan asing, selama mereka menggunakan browser yang mendukungnya. Artinya, dengan men-deploy pekerja layanan pengambilan asing, logika permintaan kustom dan cache bersama Anda akan langsung menguntungkan banyak klien layanan Anda, tanpa perlu melakukan langkah lebih lanjut.
Menyatukan semuanya: tempat klien mencari respons
Dengan mempertimbangkan informasi di atas, kita dapat menyusun hierarki sumber yang akan digunakan klien untuk menemukan respons untuk permintaan lintas-asal.
- Pengendali
fetch
pekerja layanan pihak pertama (jika ada) - Pengendali
foreignfetch
pekerja layanan pihak ketiga (jika ada, dan hanya untuk permintaan lintas-asal) - Cache HTTP browser (jika ada respons baru)
- Jaringan
Browser dimulai dari atas dan, bergantung pada penerapan pekerja layanan, akan terus menelusuri daftar hingga menemukan sumber respons.
Pelajari lebih lanjut
Selalu dapatkan info terbaru
Implementasi Uji Coba Origin pengambilan asing Chrome dapat berubah sewaktu-waktu saat kami menangani masukan dari developer. Kami akan terus memperbarui postingan ini melalui perubahan langsung, dan akan mencatat perubahan spesifik di bawah saat perubahan tersebut terjadi. Kami juga akan membagikan informasi tentang perubahan besar melalui akun Twitter @chromiumdev.