ওয়েব অ্যাপে ইনস্ট্যান্ট নেভিগেশন ও নির্বিঘ্নে পেজ ট্রানজিশন যোগ করা

১. শুরু করার আগে

এই কোডল্যাব আপনাকে শেখায় যে কীভাবে Google Chrome-এর নেটিভভাবে সাপোর্ট করা লেটেস্ট API-এর মাধ্যমে স্যাম্পেল ওয়েব অ্যাপে ইনস্ট্যান্ট নেভিগেশন ও নির্বিঘ্নে পৃষ্ঠা ট্রানজিশন যোগ করতে হয়।

স্যাম্পেল ওয়েব অ্যাপ জনপ্রিয় ফল ও সবজির পুষ্টিগত মান চেক করে। ফলের তালিকা ও ফলের বিবরণ সংক্রান্ত পৃষ্ঠাগুলি সিঙ্গল-পেজ অ্যাপ (SPA) হিসেবে তৈরি করা হয়েছে এবং সবজির তালিকা ও সবজির বিবরণ সংক্রান্ত পৃষ্ঠাগুলি ট্র্যাডিশনাল মাল্টিপল-পেজ অ্যাপ (MPA) হিসেবে তৈরি করা হয়েছে।

মোবাইলে স্যাম্পেল অ্যাপের স্ক্রিনশট মোবাইলে স্যাম্পেল অ্যাপের স্ক্রিনশট

বিশেষ করে, আপনি ইনস্ট্যান্ট নেভিগেশনের জন্য প্রিরেন্ডারিং, ব্যাক/ফরোয়ার্ড ক্যাশে (bfcache) এবং প্রাইভেট প্রিফেচ প্রক্সি এবং নির্বিঘ্নে পৃষ্ঠা ট্রানজিশনের জন্য রুট/শেয়ার করা এলিমেন্ট ট্রানজিশন প্রয়োগ করেন। আপনি MPA পৃষ্ঠার জন্য প্রিরেন্ডারিং ও bfcache এবং SPA পৃষ্ঠার জন্য শেয়ার করা এলিমেন্ট ট্রানজিশন প্রয়োগ করেন।

সাইটের স্পিড সবসময়ই ব্যবহারকারীর অভিজ্ঞতার একটি গুরুত্বপূর্ণ দিক, তাই Google Core Web Vitals চালু করেছে, এটি হল মেট্রিকের একটি সেট যা লোড পারফর্ম্যান্স, ইন্টার‍্যাক্টিভিটি এবং ওয়েব পেজের ভিজ্যুয়াল স্টেবিলিটি পরিমাপ করে যাতে ব্যবহারকারীর বাস্তবিক অভিজ্ঞতা বোঝা যায়। লেটেস্ট API আপনাকে ফিল্ডে আপনার ওয়েবসাইটের Core Web Vitals স্কোর উন্নত করতে সাহায্য করে, বিশেষ করে লোড পারফর্ম্যান্সের জন্য।

ডেমো ছবি, bfcache কীভাবে লোডিং টাইম উন্নত করে

Mindvalley-এর ডেমো

এছাড়াও, ব্যবহারকারীরা মোবাইল নেটিভ অ্যাপে নেভিগেশন ও স্টেট পরিবর্তন অত্যন্ত স্বজ্ঞাত করতে ট্রানজিশন ব্যবহারে অভ্যস্ত। তবে, ওয়েবে এই ধরনের ব্যবহারকারীর অভিজ্ঞতা রেপ্লিকেশন করা সহজ নয়। আপনি বর্তমান ওয়েব-প্ল্যাটফর্ম API-এর মাধ্যমে একই ধরনের এফেক্ট অর্জন করতে পারলেও, ডেভেলপমেন্ট খুব কঠিন বা জটিল হতে পারে, বিশেষ করে Android বা iOS অ্যাপে ফিচার কাউন্টারপার্টের সাথে তুলনা করলে। অ্যাপ ও ওয়েবের মধ্যে ব্যবহারকারী ও ডেভেলপারের অভিজ্ঞতার এই পার্থক্য দূর করার জন্য সিমলেস API ডিজাইন করা হয়েছে।

pixiv থেকে Shared Element Transitions API ডেমো Tokopedia থেকে Shared Element Transitions API ডেমো

pixiv এবং Tokopedia থেকে ডেমো

পূর্বশর্ত

এই বিষয়ে জ্ঞান:

আপনি কী শিখবেন:

কীভাবে প্রয়োগ করতে হয়:

  • প্রি-রেন্ডারিং
  • bfcache
  • প্রাইভেট প্রিফেচ প্রক্সি
  • রুট/শেয়ার করা এলিমেন্ট ট্রানজিশন

আপনি কী তৈরি করবেন

Next.js দিয়ে তৈরি করা একটি স্যাম্পেল ওয়েব অ্যাপ যা লেটেস্ট ইনস্ট্যান্ট ও সিমলেস ব্রাউজার ক্ষমতার সাথে সমৃদ্ধ:

  • প্রিরেন্ডারিংয়ের মাধ্যমে প্রায় সাথে সাথেই নেভিগেশন
  • ব্রাউজারের ব্যাকওয়ার্ড ও ফরওয়ার্ড বোতামের মাধ্যমে ইনস্ট্যান্ট লোড করার জন্য bfcache
  • প্রাইভেট প্রিফেচ প্রক্সি বা স্বাক্ষরিত এক্সচেঞ্জ (SXG) সহ ক্রস-অরিজিন নেভিগেশন থেকে দুর্দান্ত প্রথম ইম্প্রেশন
  • রুট/শেয়ার করা এলিমেন্ট ট্রানজিশন সহ পেজের মধ্যে নির্বিঘ্ন ট্রানজিশন

আপনার কী প্রয়োজন হবে

  • Chrome ভার্সন 101 বা তার পরবর্তী যেকোনও ভার্সন

২. শুরু করুন

Chrome ফ্ল্যাগ চালু করা

  1. about://flags-এ নেভিগেট করুন এবং তারপর Prerender2 ও documentTransition API রানটাইম ফ্ল্যাগ চালু করুন।
  2. আপনার ব্রাউজার রিস্টার্ট করুন।

কোড পান

  1. আপনার পছন্দের ডেভেলপমেন্ট এনভায়রনমেন্টে এই GitHub রিপোজিটরি থেকে কোড খুলুন:
git clone -b codelab git@github.com:googlechromelabs/instant-seamless-demo.git
  1. সার্ভার রান করার জন্য প্রয়োজনীয় ডিপেন্ডেন্সি ইনস্টল করুন:
npm install
  1. পোর্ট ৩০০০-এ সার্ভার চালু করুন:
npm run dev
  1. আপনার ব্রাউজারে http://localhost:3000 লিঙ্কে যান।

এখন আপনি নিজের অ্যাপ এডিট ও উন্নত করতে পারবেন। আপনি যখনই কোনও পরিবর্তন করবেন, অ্যাপটি রিলোড হবে এবং আপনার করা পরিবর্তন সরাসরি দেখা যাবে।

৩. প্রিরেন্ডারিং ইন্টিগ্রেট করা

এই ডেমোর জন্য, সার্ভার সাইডে ইচ্ছাকৃতভাবে দেরি করার কারণে স্যাম্পেল অ্যাপে সবজি-বিবরণ পৃষ্ঠার লোড টাইম খুব ধীর। প্রিরেন্ডারিংয়ের মাধ্যমে আপনি এই অপেক্ষার সময় কমাতে পারবেন।

vegetable-list পৃষ্ঠায় প্রিরেন্ডার বোতাম যোগ করতে এবং ব্যবহারকারী ক্লিক করার পরে প্রিরেন্ডারিং ট্রিগার করতে:

  1. একটি বোতাম কম্পোনেন্ট তৈরি করুন, যা স্পেকুলেশন-রুলস স্ক্রিপ্ট ট্যাগ ডাইনামিকভাবে যোগ করে:

components/prerender-button.js

import { useContext } from 'react'
import ResourceContext from './resource-context'

// You use resource context to manage global states.
// In the PrerenderButton component, you update the prerenderURL parameter when the button is clicked.
export default function PrerenderButton() {
  const { dispatch } = useContext(ResourceContext)
  const handleClick = (e) => {
    e.preventDefault()
    e.stopPropagation()
    const parent = e.target.closest('a')
    if (!parent) {
      return
    }
    const href = parent.getAttribute('href')
    dispatch({ type: 'update', prerenderURL: href })
  }

  return (
    <button className='ml-auto bg-gray-200 hover:bg-gray-300 px-4 rounded' onClick={handleClick}>
      Prerender
    </button>
  )
}
  1. list-item.js ফাইলে PrerenderButton কম্পোনেন্ট ইমপোর্ট করুন।

components/list-item.js

// Codelab: Add a PrerenderButton component.
import PrerenderButton from './prerender-button'

...
function ListItemForMPA({ item, href }) {
  return (
    <a href={href} className='block flex items-center'>
      <Icon src={item.image} />
      <div className='text-xl'>{item.name}</div>
      {/* Codelab: Add PrerenderButton component. */}
      <PrerenderButton />
    </a>
  )
}
  1. Speculation Rules API যোগ করতে কম্পোনেন্ট তৈরি করুন।

অ্যাপ যখন prerenderURL স্টেট আপডেট করে, তখন SpeculationRules কম্পোনেন্ট ডায়নামিক পদ্ধতিতে পৃষ্ঠায় স্ক্রিপ্ট ট্যাগ যোগ করে।

components/speculationrules.js

import Script from 'next/script'
import { useContext, useMemo } from 'react'
import ResourceContext from './resource-context'

export default function SpeculationRules() {
  const { state } = useContext(ResourceContext)
  const { prerenderURL } = state

  return useMemo(() => {
    return (
      <>
        {prerenderURL && (
          <Script id='speculationrules' type='speculationrules'>
            {`
            {
              "prerender":[
                {
                  "source": "list",
                  "urls": ["${prerenderURL}"]
                }
              ]
            }
          `}
          </Script>
        )}
      </>
    )
  }, [prerenderURL])
}
  1. অ্যাপের সাথে কম্পোনেন্ট ইন্টিগ্রেট করুন।

pages/_app.js

// Codelab: Add the SpeculationRules component.
import SpeculationRules from '../components/speculationrules'

function MyApp({ Component, pageProps }) {
  useAnalyticsForSPA()

  return (
    <ResourceContextProvider>
      <Layout>
        <Component {...pageProps} />
      </Layout>
      {/* Codelab: Add SpeculationRules component */}
      <SpeculationRules />
      <Script id='analytics-for-mpa' strategy='beforeInteractive' src='/analytics.js' />
    </ResourceContextProvider>
  )
}

export default MyApp
  1. প্রিরেন্ডার করুন বিকল্পে ক্লিক করুন।

এখন আপনি লোডিংয়ের ক্ষেত্রে উল্লেখযোগ্য উন্নতি দেখতে পাবেন। বাস্তব ব্যবহারের ক্ষেত্রে, কিছু হিউরিস্টিকসের মাধ্যমে ব্যবহারকারী পরবর্তী যে পৃষ্ঠাটি দেখতে পারেন তার জন্য প্রিরেন্ডারিং ট্রিগার করা হয়।

প্রিরেন্ডারিংয়ের জন্য স্যাম্পেল অ্যাপ ডেমো ভিডিও

Analytics

ডিফল্ট হিসেবে, DOMContentLoaded ইভেন্ট ঘটলে, স্যাম্পেল ওয়েব অ্যাপে analytics.js ফাইলটি একটি পৃষ্ঠা-ভিউ ইভেন্ট পাঠায়। তবে, এটি করা বুদ্ধিমানের কাজ নয় কারণ প্রিরেন্ডারিং ফেজ চলাকালীন এই ইভেন্ট ফায়ার হয়।

এই সমস্যার সমাধান করতে document.prerendering এবং prerenderingchange ইভেন্ট চালু করতে:

  • analytics.js ফাইলটি আবার লিখুন:

public/analytics.js

  const sendEvent = (type = 'pageview') => {
    // Codelab: Make analytics prerendering compatible.
    // The pageshow event could happen in the prerendered page before activation.
    // The prerendered page should be handled by the prerenderingchange event.
    if (document.prerendering) {
      return
    }
    console.log(`Send ${type} event for MPA navigation.`)
    fetch(`/api/analytics?from=${encodeURIComponent(location.pathname)}&type=${type}`)
  }
  ...

  // Codelab: Make analytics prerendering compatible.
  // The prerenderingchange event is triggered when the page is activated.
  document.addEventListener('prerenderingchange', () => {
    console.log('The prerendered page was activated.')
    sendEvent()
  })
  ...

দারুণ, আপনি নিজের অ্যানালিটিক্স সফলভাবে পরিবর্তন করেছেন যাতে সেগুলি প্রিরেন্ডারিংয়ের সাথে মানানসই হয়। এখন আপনি ব্রাউজার কনসোলে সঠিক সময় সহ পৃষ্ঠা-ভিউ লগ দেখতে পারবেন।

৪. bfcache ব্লকার সরান

unload ইভেন্ট হ্যান্ডলার সরান

অপ্রয়োজনীয় unload ইভেন্ট থাকা একটি সাধারণ ভুল যা আর সাজেস্ট করা হয় না। এটি bfcache-কে কাজ করতে বাধা দেয়, শুধু তাই নয়, এটি নির্ভরযোগ্যও নয়। যেমন, এটি সবসময় মোবাইল এবং Safari-তে কাজ করে না।

unload ইভেন্টের পরিবর্তে, আপনি pagehide ইভেন্ট ব্যবহার করেন, যা unload ইভেন্ট ফায়ার হওয়ার সব ক্ষেত্রে এবং কোনও পৃষ্ঠা bfcache-এ রাখা হলে ফায়ার হয়।

unload ইভেন্ট হ্যান্ডলার সরাতে:

  • analytics.js ফাইলে, unload ইভেন্ট হ্যান্ডলারের কোডটি pagehide ইভেন্ট হ্যান্ডলারের কোড দিয়ে পরিবর্তন করুন:

public/analytics.js

// Codelab: Remove the unload event handler for bfcache.
// The unload event handler prevents the content from being stored in bfcache. Use the pagehide event instead.
window.addEventListener('pagehide', () => {
  sendEvent('leave')
})

ক্যাশে-কন্ট্রোল হেডার আপডেট করুন

Cache-control: no-store HTTP হেডার সহ পৃষ্ঠাগুলি ব্রাউজারের bfcache ফিচার থেকে উপকৃত হয় না, তাই এই হেডারের সাথে মিতব্যয়ী হওয়া ভাল অভ্যাস। বিশেষ করে, পৃষ্ঠায় যদি লগ-ইন স্ট্যাটাসের মতো ব্যক্তিগত বা গুরুত্বপূর্ণ তথ্য না থাকে, তাহলে সম্ভবত আপনাকে Cache-control: no-store HTTP হেডার সহ এটি পরিবেশন করতে হবে না।

স্যাম্পেল অ্যাপের ক্যাশে-কন্ট্রোল হেডার আপডেট করতে:

  • getServerSideProps কোড পরিবর্তন করুন:

pages/vegetables/index.js

export const getServerSideProps = middleware(async (ctx) => {
  const { req, res } = ctx
  // Codelab: Modify the cache-control header.
  res.setHeader('Cache-Control', 'public, s-maxage=10, stale-while-revalidate=59')
  ...

pages/vegetables/[name].js

export const getServerSideProps = middleware(async (ctx) => {
  const { req, res, query } = ctx
  // Codelab: Modify the cache-control header.
  res.setHeader('Cache-Control', 'public, s-maxage=10, stale-while-revalidate=59')
  ...

কোনও পৃষ্ঠা bfcache থেকে রিস্টোর করা হয়েছে কিনা তা নির্ধারণ করুন

পৃষ্ঠাটি প্রাথমিকভাবে লোড হওয়ার সময় এবং bfcache থেকে পৃষ্ঠাটি রিস্টোর করার সময় load ইভেন্টের ঠিক পরেই pageshow ইভেন্টটি ফায়ার করে। pageshow ইভেন্টের একটি persisted প্রপার্টি আছে, যা bfcache থেকে পৃষ্ঠাটি রিস্টোর করা হলে সত্য এবং না হলে মিথ্যা। আপনি persisted প্রপার্টি ব্যবহার করে সাধারণ পৃষ্ঠা লোড থেকে bfcache রিস্টোর আলাদা করতে পারবেন। প্রধান অ্যানালিটিক্স পরিষেবাগুলি bfcache সম্পর্কে সচেতন হওয়া উচিত, তবে আপনি bfcache থেকে পৃষ্ঠাটি রিস্টোর করা হয়েছে কিনা তা চেক করতে এবং ম্যানুয়ালি ইভেন্ট পাঠাতে পারেন।

কোনও পৃষ্ঠা bfcache থেকে রিস্টোর করা হয়েছে কিনা তা নির্ধারণ করতে:

  • analytics.js ফাইলে এই কোড যোগ করুন।

public/analytics.js

  // Codelab: Use the pageshow event handler for bfcache.
  window.addEventListener('pageshow', (e) => {
    // If the persisted flag exists, the page was restored from bfcache.
    if (e.persisted) {
      console.log('The page was restored from bfcache.')
      sendEvent()
    }
  })

ওয়েব পেজ ডিবাগ করা

Chrome ডেভেলপার টুল আপনার পৃষ্ঠাগুলি bfcache-এর জন্য অপ্টিমাইজ করা হয়েছে কিনা তা নিশ্চিত করতে এবং সেগুলিকে অনুপযুক্ত করে তুলতে পারে এমন কোনও সমস্যা শনাক্ত করতে সাহায্য করতে পারে।

কোনও নির্দিষ্ট পৃষ্ঠা পরীক্ষা করতে:

  1. Chrome-এ পৃষ্ঠায় নেভিগেট করুন।
  2. Chrome ডেভেলপার টুলে, অ্যাপ্লিকেশন > ব্যাক-ফরওয়ার্ড ক্যাশে > টেস্ট রান করুন বিকল্পে ক্লিক করুন।

Chrome ডেভেলপার টুল, পৃষ্ঠাটি bfcache থেকে রিস্টোর করা যাবে কিনা তা নির্ধারণ করতে, নেভিগেট করে অন্য পৃষ্ঠায় গিয়ে আবার ফিরে আসার চেষ্টা করে।

49bf965af35d5324.png

সফল হলে, প্যানেল আপনাকে জানায় যে ব্যাক-ফরোয়ার্ড ক্যাশে থেকে পৃষ্ঠাটি রিস্টোর করা হয়েছে:

47015a0de45f0b0f.png

এটি করা না গেলে, প্যানেল আপনাকে জানাবে যে পৃষ্ঠাটি ফিরিয়ে আনা যায়নি এবং তার কারণও জানাবে। আপনি যদি ডেভেলপার হিসেবে কোনও সমস্যার সমাধান করতে পারেন, তাহলে প্যানেল আপনাকে সেই বিষয়েও জানাবে।

dcf0312c3fc378ce.png

৫. ক্রস-সাইট প্রিফেচিং চালু করুন

প্রিফেচিং আগে থেকেই ফেচ করা শুরু করে যাতে ব্যবহারকারী নেভিগেট করার সময় বাইটগুলি ব্রাউজারে আগে থেকেই থাকে, যা নেভিগেশনকে দ্রুত করে। এটি Core Web Vitals উন্নত করার এবং নেভিগেশনের আগে কিছু নেটওয়ার্ক অ্যাক্টিভিটি অফসেট করার একটি সহজ উপায়। এটি সরাসরি Largest Contentful Paint (LCP) ত্বরান্বিত করে এবং নেভিগেশনের সময় First Input Delay (FID) ও Cumulative Layout Shift (CLS)-এর জন্য আরও জায়গা দেয়।

প্রাইভেট প্রিফেচ প্রক্সি ক্রস-সাইট প্রিফেচ চালু করে, কিন্তু ডেস্টিনেশন সার্ভারে ব্যবহারকারীর ব্যক্তিগত তথ্য প্রকাশ করে না।

Private Prefetch Proxy কীভাবে কাজ করে

প্রাইভেট প্রিফেচ প্রক্সির মাধ্যমে ক্রস-সাইট প্রিফেচিং চালু করুন

ওয়েবসাইটের মালিকরা সুপরিচিত ট্রাফিক-অ্যাডভাইস রিসোর্সের মাধ্যমে প্রিফেচিংয়ের উপর নিয়ন্ত্রণ বজায় রাখেন, যা ওয়েব ক্রলারের জন্য /robots.txt-এর মতো, এটি HTTP সার্ভারকে ঘোষণা করতে দেয় যে প্রয়োগকারী এজেন্টদের সংশ্লিষ্ট পরামর্শ প্রয়োগ করা উচিত। বর্তমানে, ওয়েবসাইটের মালিকরা এজেন্টকে নেটওয়ার্ক কানেকশন বাতিল বা থ্রটল করার পরামর্শ দিতে পারেন। ভবিষ্যতে, অন্যান্য পরামর্শ যোগ করা হতে পারে।

ট্রাফিক-অ্যাডভাইস রিসোর্স হোস্ট করতে:

  1. এই JSON-এর মতো ফাইল যোগ করুন:

public/.well-known/traffic-advice

[
  {
    "user_agent": "prefetch-proxy",
    "google_prefetch_proxy_eap": {
      "fraction": 1
    }
  }
]

google_prefetch_proxy_eap ফিল্ড হল আগেভাগে অ্যাক্সেস প্রোগ্রামের জন্য একটি বিশেষ ফিল্ড এবং fraction ফিল্ড হল প্রাইভেট প্রিফেচ প্রক্সি যে প্রিফেচ অনুরোধ পাঠায় তার ভগ্নাংশ নিয়ন্ত্রণ করার ফিল্ড।

ট্রাফিক সংক্রান্ত পরামর্শ application/trafficadvice+json MIME-এর প্রকারের সাথে রিটার্ন করতে হবে।

  1. next.config.js ফাইলে, রেসপন্স হেডার কনফিগার করুন:

next.config.js

const nextConfig = {
  // Codelab: Modify content-type for traffic advice file.
  async headers() {
    return [
      {
        source: '/.well-known/traffic-advice',
        headers: [
          {
            key: 'Content-Type',
            value: 'application/trafficadvice+json',
          },
        ],
      },
    ]
  },
}

module.exports = nextConfig

৬. Shared Element Transitions API ইন্টিগ্রেট করুন

ব্যবহারকারী যখন ওয়েবে এক পৃষ্ঠা থেকে অন্য পৃষ্ঠায় নেভিগেট করেন, তখন প্রথম পৃষ্ঠাটি অদৃশ্য হয়ে যায় এবং নতুন পৃষ্ঠাটি উপস্থিত হওয়ার সাথে সাথে তারা যে কন্টেন্ট দেখেন তা হঠাৎ এবং অপ্রত্যাশিতভাবে পরিবর্তিত হয়। এই ধরনের বিচ্ছিন্ন ব্যবহারকারীর অভিজ্ঞতা বিভ্রান্তিকর এবং এর ফলে ব্যবহারকারীকে অনেক বেশি মানসিক চাপ নিতে হয়, কারণ তিনি কীভাবে বর্তমান অবস্থায় পৌঁছালেন তা তাকে নিজেকেই বুঝে নিতে হয়। এছাড়াও, এই অভিজ্ঞতা ব্যবহারকারীদের পৃষ্ঠা লোড হওয়ার সময়কে আরও বেশি করে বুঝতে সাহায্য করে, যখন তারা তাদের কাঙ্ক্ষিত গন্তব্য লোড হওয়ার জন্য অপেক্ষা করে।

স্মুথ লোডিং অ্যানিমেশন কগনিটিভ লোড কমায় কারণ ব্যবহারকারীরা এক পৃষ্ঠা থেকে অন্য পৃষ্ঠায় নেভিগেট করার সময় প্রাসঙ্গিকতা বজায় থাকে এবং লোডিংয়ের সময় অনুভূত লেটেন্সি কমে যায় কারণ ব্যবহারকারীরা এই সময় আকর্ষণীয় ও আনন্দদায়ক কিছু দেখতে পান। এইসব কারণে, বেশিরভাগ প্ল্যাটফর্ম সহজে ব্যবহার করা যায় এমন প্রিমিটিভ প্রদান করে যা ডেভেলপারদের নির্বিঘ্ন ট্রানজিশন তৈরি করতে দেয়, যেমন Android, iOS, MacOS ও Windows।

Shared Element Transitions API ডেভেলপারদের ওয়েবে একই ক্ষমতা প্রদান করে, ট্রানজিশন ক্রস-ডকুমেন্ট (MPA) বা ইন্ট্রা-ডকুমেন্ট (SPA) যাই হোক না কেন।

pixiv থেকে Shared Element Transitions API ডেমো Tokopedia থেকে Shared Element Transitions API ডেমো

pixiv এবং Tokopedia থেকে ডেমো

স্যাম্পেল অ্যাপের SPA অংশের জন্য Shared Element Transitions API ইন্টিগ্রেট করতে:

  1. use-page-transition.js ফাইলে ট্রানজিশন ম্যানেজ করতে কাস্টম হুক তৈরি করুন:

utils/use-page-transition.js

import { useEffect, useContext, useRef, useCallback } from 'react'
import ResourceContext from '../components/resource-context'

// Call this hook on this first page before you start the page transition. For Shared Element Transitions, you need to call the transition.start() method before the next page begins to render, and you need to do the Document Object Model (DOM) modification or setting of new shared elements inside the callback so that this hook returns the promise and defers to the callback resolve.
export const usePageTransitionPrep = () => {
  const { dispatch } = useContext(ResourceContext)

  return (elm) => {
    const sharedElements = elm.querySelectorAll('.shared-element')
    // Feature detection
    if (!document.createDocumentTransition) {
      return null
    }

    return new Promise((resolve) => {
      const transition = document.createDocumentTransition()
      Array.from(sharedElements).forEach((elm, idx) => {
        transition.setElement(elm, `target-${idx}`)
      })
      transition.start(async () => {
        resolve()
        await new Promise((resolver) => {
          dispatch({ type: 'update', transition: { transition, resolver } })
        })
      })
    })
  }
}

// Call this hook on the second page. Inside the useEffect hook, you can refer to the actual DOM element and set them as shared elements with the transition.setElement() method. When the resolver function is called, the transition is initiated between the captured images and newly set shared elements.
export const usePageTransition = () => {
  const { state, dispatch } = useContext(ResourceContext)
  const ref = useRef(null)
  const setRef = useCallback((node) => {
    ref.current = node
  }, [])

  useEffect(() => {
    if (!state.transition || !ref.current) {
      return
    }
    const { transition, resolver } = state.transition
    const sharedElements = ref.current.querySelectorAll('.shared-element')
    Array.from(sharedElements).forEach((elm, idx) => {
      transition.setElement(elm, `target-${idx}`)
    })
    resolver()
    return () => {
      dispatch({ type: 'update', transition: null })
    }
  })

  return setRef
}
  1. তালিকা পৃষ্ঠায় usePageTransitionPrep() কাস্টম হুক কল করুন এবং তারপর click ইভেন্টের মধ্যে transition.start() পদ্ধতি ট্রিগার করতে অ্যাসিঙ্ক ফাংশন কল করুন।

ফাংশনের মধ্যে, shared-element ক্লাস এলিমেন্ট সংগ্রহ করা হয় এবং শেয়ার করা এলিমেন্ট হিসেবে রেজিস্টার করা হয়।

components/list-item.js

// Codelab: Add the Shared Element Transitions API.
import { usePageTransitionPrep } from '../utils/use-page-transition'
...

function ListItemForSPA({ item, href }) {
  // Codelab: Add Shared Element Transitions.
  const transitionNextState = usePageTransitionPrep()
  const handleClick = async (e) => {
    const elm = e.target.closest('a')
    await transitionNextState(elm)
  }
  return (
    <Link href={href}>
      <a className='block flex items-center' onClick={handleClick}>
        <Icon src={item.image} name={item.name} className='shared-element' />
        <div className='text-xl'>{item.name}</div>
      </a>
    </Link>
  )
}
  1. বিবরণ পৃষ্ঠায়, transition.start() কলব্যাক ফাংশন শেষ করতে usePageTransition() হুক কল করুন।

এই কলব্যাকে, বিবরণ পৃষ্ঠায় শেয়ার করা এলিমেন্টও রেজিস্টার করা হয়।

pages/fruits/[name].js

// Codelab: Add the Shared Element Transitions API.
import { usePageTransition } from '../../utils/use-page-transition'

const Item = ({ data }) => {
  const { name, image, amountPer, nutrition } = data
  // Codelab: Add the Shared Element Transitions API.
  const ref = usePageTransition()

  return (
    <div className={'flex flex-col items-center justify-center py-4 px-4 sm:flex-row'} ref={ref}>
      <div className='flex flex-col items-center sm:w-2/4'>
        <Image
          className='object-cover border-gray-100 border-2 rounded-full shared-element'
          src={image}
          width='240'
          height='240'
          alt={`picture of ${name}`}
        />
        <h1 className='text-4xl font-bold mt-4'>{name}</h1>
      </div>

      <div className='sm:w-2/4 w-full'>
        <Nutrition amountPer={amountPer} nutrition={nutrition} />
      </div>
    </div>
  )
...
}

এখন আপনি দেখতে পাবেন যে ছবির এলিমেন্টগুলি তালিকা এবং বিবরণ পৃষ্ঠায় শেয়ার করা হয়েছে এবং পৃষ্ঠা ট্রানজিশনে নির্বিঘ্নে কানেক্ট করা হয়েছে। এমনকি আপনি CSS সিউডো-এলিমেন্ট-এর সাহায্যে অ্যানিমেশন কাস্টমাইজ করে আরও আকর্ষণীয় করে তুলতে পারেন।

শেয়ার করা এলিমেন্ট ট্রানজিশন ছাড়া স্যাম্পেল অ্যাপ ডেমো ভিডিও শেয়ার করা এলিমেন্ট ট্রানজিশন সহ স্যাম্পেল অ্যাপ ডেমো ভিডিও

৭. অভিনন্দন

অভিনন্দন! আপনি কম-ঘর্ষণ, আকর্ষক এবং স্বজ্ঞাত ব্যবহারকারীর অভিজ্ঞতা সহ একটি তাত্ক্ষণিক এবং নির্বিঘ্ন ওয়েব অ্যাপ তৈরি করেছেন।

আরও জানুন

প্রি-রেন্ডারিং

bfcache

ক্রস-সাইট প্রিফেচিং

সাইনড এক্সচেঞ্জ

রুট/শেয়ার করা এলিমেন্ট ট্রানজিশন

এইসব API এখনও ডেভেলপমেন্টের প্রাথমিক পর্যায়ে রয়েছে, তাই আপনার মতামত crbug.com-এ অথবা প্রাসঙ্গিক API-এর Github রিপোজিটরিতে সমস্যা হিসেবে শেয়ার করুন।