Langsung menggunakan Portal: navigasi yang lancar di web

Pelajari cara Portals API yang diusulkan dapat meningkatkan UX navigasi Anda.

Utsunomiya Yusuke
Yusuke Utsunomiya

Memastikan halaman Anda dimuat dengan cepat adalah kunci untuk memberikan pengalaman pengguna yang baik. Namun, satu area yang sering kita abaikan adalah transisi halaman, yaitu yang dilihat oleh pengguna saat mereka berpindah antar-halaman.

Proposal API platform web baru yang disebut Portals bertujuan untuk membantu hal ini dengan menyederhanakan pengalaman saat pengguna menjelajahi seluruh situs Anda.

Lihat cara kerja Portal:

Navigasi dan sematan yang lancar dengan Portal. Dibuat oleh Adam Argyle.

Apa yang diaktifkan Portal

Aplikasi Web Satu Halaman (SPA) menawarkan transisi yang bagus, tetapi memerlukan kompleksitas yang lebih tinggi untuk membuatnya. Aplikasi Multi-halaman (MPA) jauh lebih mudah dibuat, tetapi Anda berakhir dengan layar kosong di antara halaman.

Portal menawarkan yang terbaik dari kedua hal tersebut: kompleksitas yang rendah dari MPA dengan transisi SPA yang mulus. Anggap saja seperti <iframe> yang memungkinkan penyematan, tetapi tidak seperti <iframe>, metode ini juga dilengkapi dengan fitur untuk menavigasi ke kontennya.

Melihat orang percaya: silakan lihat terlebih dahulu apa yang kami pamerkan di Chrome Dev Summit 2018:

Dengan navigasi klasik, pengguna harus menunggu dengan layar kosong hingga browser selesai merender tujuan. Dengan Portal, pengguna dapat menikmati animasi, sedangkan <portal> melakukan pra-render konten dan membuat pengalaman navigasi yang lancar.

Sebelum Portal, kami dapat merender halaman lain menggunakan <iframe>. Kita juga dapat menambahkan animasi untuk memindahkan {i>frame<i} di sekitar laman. Namun, <iframe> tidak akan mengizinkan Anda membuka kontennya. Portal menutup celah ini, memungkinkan kasus penggunaan yang menarik.

Coba Portal

Mengaktifkan melalui about://flags

Coba Portal di Chrome 85 dan versi yang lebih baru dengan membalik tanda eksperimental:

  • Aktifkan flag about://flags/#enable-portals untuk navigasi asal yang sama.
  • Untuk menguji navigasi lintas origin, aktifkan juga flag about://flags/#enable-portals-cross-origin.

Selama fase awal eksperimen Portal ini, sebaiknya gunakan direktori data pengguna yang sepenuhnya terpisah untuk pengujian dengan menyetel flag command line --user-data-dir. Setelah Portal diaktifkan, konfirmasi di DevTools bahwa Anda memiliki HTMLPortalElement baru yang mengkilap.

Screenshot konsol DevTools menampilkan HTMLPortalElement

Menerapkan Portal

Mari kita lihat contoh implementasi dasar.

// Create a portal with the wikipedia page, and embed it
// (like an iframe). You can also use the <portal> tag instead.
portal = document.createElement('portal');
portal.src = 'https://en.wikipedia.org/wiki/World_Wide_Web';
portal.style = '...';
document.body.appendChild(portal);

// When the user touches the preview (embedded portal):
// do fancy animation, e.g. expand …
// and finish by doing the actual transition.
// For the sake of simplicity, this snippet will navigate
// on the `onload` event of the Portals element.
portal.addEventListener('load', (evt) => {
   portal.activate();
});

Semudah itu. Coba kode ini di konsol DevTools, halaman wikipedia akan terbuka.

GIF demo gaya portal pratinjau

Jika Anda ingin membuat sesuatu seperti yang kami tunjukkan di Chrome Dev Summit yang berfungsi seperti demo di atas, cuplikan berikut ini akan menarik bagi Anda.

// Adding some styles with transitions
const style = document.createElement('style');
style.innerHTML = `
  portal {
    position:fixed;
    width: 100%;
    height: 100%;
    opacity: 0;
    box-shadow: 0 0 20px 10px #999;
    transform: scale(0.4);
    transform-origin: bottom left;
    bottom: 20px;
    left: 20px;
    animation-name: fade-in;
    animation-duration: 1s;
    animation-delay: 2s;
    animation-fill-mode: forwards;
  }
  .portal-transition {
    transition: transform 0.4s;
  }
  @media (prefers-reduced-motion: reduce) {
    .portal-transition {
      transition: transform 0.001s;
    }
  }
  .portal-reveal {
    transform: scale(1.0) translateX(-20px) translateY(20px);
  }
  @keyframes fade-in {
    0%   { opacity: 0; }
    100% { opacity: 1; }
  }
`;
const portal = document.createElement('portal');
// Let's navigate into the WICG Portals spec page
portal.src = 'https://wicg.github.io/portals/';
// Add a class that defines the transition. Consider using
// `prefers-reduced-motion` media query to control the animation.
// https://developers.google.com/web/updates/2019/03/prefers-reduced-motion
portal.classList.add('portal-transition');
portal.addEventListener('click', (evt) => {
  // Animate the portal once user interacts
  portal.classList.add('portal-reveal');
});
portal.addEventListener('transitionend', (evt) => {
  if (evt.propertyName == 'transform') {
    // Activate the portal once the transition has completed
    portal.activate();
  }
});
document.body.append(style, portal);

Deteksi fitur juga mudah dilakukan untuk meningkatkan kualitas situs secara bertahap menggunakan Portal.

if ('HTMLPortalElement' in window) {
  // If this is a platform that have Portals...
  const portal = document.createElement('portal');
  ...
}

Jika Anda ingin segera merasakan pengalaman Portal, coba gunakan uskay-portals-demo.glitch.me. Pastikan Anda mengaksesnya dengan Chrome 85 atau versi yang lebih baru, dan aktifkan tanda eksperimental.

  1. Masukkan URL yang ingin Anda lihat pratinjaunya.
  2. Halaman tersebut kemudian akan disematkan sebagai elemen <portal>.
  3. Klik pratinjau.
  4. Pratinjau akan diaktifkan setelah animasi.

GIF menggunakan demo error saat menggunakan Portal

Lihat spesifikasinya

Kami aktif mendiskusikan spesifikasi Portal di Grup Komunitas Inkubasi Web (WICG). Untuk memahami dengan cepat, lihat beberapa skenario utama. Berikut adalah tiga fitur penting yang harus Anda pahami:

  • Elemen <portal>: Elemen HTML itu sendiri. API-nya sangat sederhana. Class ini terdiri dari atribut src, fungsi activate, dan antarmuka untuk pesan (postMessage). activate menggunakan argumen opsional untuk meneruskan data ke <portal> setelah aktivasi.
  • Antarmuka portalHost: Menambahkan objek portalHost ke objek window. Hal ini memungkinkan Anda memeriksa apakah halaman disematkan sebagai elemen <portal>. Library ini juga menyediakan antarmuka untuk pengiriman pesan (postMessage) kembali ke host.
  • Antarmuka PortalActivateEvent: Peristiwa yang diaktifkan saat <portal> diaktifkan. Ada fungsi rapi yang disebut adoptPredecessor yang dapat Anda gunakan untuk mengambil halaman sebelumnya sebagai elemen <portal>. Hal ini memungkinkan Anda membuat navigasi yang mulus dan membuat pengalaman yang unik di antara dua halaman.

Mari kita lihat lebih dari sekadar pola penggunaan dasar. Berikut adalah daftar tidak lengkap tentang hal yang dapat Anda capai dengan Portal beserta kode contoh.

Menyesuaikan gaya saat disematkan sebagai elemen <portal>

// Detect whether this page is hosted in a portal
if (window.portalHost) {
  // Customize the UI when being embedded as a portal
}

Pesan antara elemen <portal> dan portalHost

// Send message to the portal element
const portal = document.querySelector('portal');
portal.postMessage({someKey: someValue}, ORIGIN);

// Receive message via window.portalHost
window.portalHost.addEventListener('message', (evt) => {
  const data = evt.data.someKey;
  // handle the event
});

Mengaktifkan elemen <portal> dan menerima peristiwa portalactivate

// You can optionally add data to the argument of the activate function
portal.activate({data: {somekey: 'somevalue'}});

// The portal content will receive the portalactivate event
// when the activate happens
window.addEventListener('portalactivate', (evt) => {
  // Data available as evt.data
  const data = evt.data;
});

Mengambil pendahulunya

// Listen to the portalactivate event
window.addEventListener('portalactivate', (evt) => {
  // ... and creatively use the predecessor
  const portal = evt.adoptPredecessor();
  document.querySelector('someElm').appendChild(portal);
});

Mengetahui halaman Anda diadopsi sebagai pendahulunya

// The activate function returns a Promise.
// When the promise resolves, it means that the portal has been activated.
// If this document was adopted by it, then window.portalHost will exist.
portal.activate().then(() => {
  // Check if this document was adopted into a portal element.
  if (window.portalHost) {
    // You can start communicating with the portal element
    // i.e. listen to messages
    window.portalHost.addEventListener('message', (evt) => {
      // handle the event
    });
  }
});

Dengan menggabungkan semua fitur yang didukung Portal, Anda dapat membangun pengalaman pengguna yang sangat menarik. Misalnya, demo di bawah menunjukkan bagaimana Portal dapat memungkinkan pengalaman pengguna yang lancar antara situs dan konten penyematan pihak ketiga.

Kasus penggunaan dan rencana

Semoga Anda menyukai tur singkat Portals ini! Kami tidak sabar ingin melihat karya-karya Anda. Misalnya, Anda mungkin ingin mulai menggunakan Portal untuk navigasi yang sulit seperti: melakukan pra-rendering halaman untuk produk terlaris Anda dari halaman listingan kategori produk.

Hal penting lainnya yang perlu diketahui adalah Portal dapat digunakan dalam navigasi lintas asal, seperti <iframe>. Jadi, jika Anda memiliki beberapa situs yang saling mereferensikan satu sama lain, Anda juga dapat menggunakan Portal untuk membuat navigasi yang mulus di antara dua situs yang berbeda. Kasus penggunaan lintas asal ini sangat unik untuk Portal, dan bahkan dapat meningkatkan pengalaman pengguna SPA.

Kami menerima masukan

Portal siap untuk eksperimen di Chrome 85 dan versi yang lebih baru. Masukan dari komunitas sangat penting untuk perancangan API yang baru, jadi silakan mencobanya dan sampaikan pendapat Anda. Jika Anda memiliki permintaan fitur atau masukan, silakan buka repo GitHub WiCG.