সারাংশ
জানুন কিভাবে আমরা ওয়েব কম্পোনেন্ট, পলিমার এবং ম্যাটেরিয়াল ডিজাইন ব্যবহার করে একটি একক পৃষ্ঠার অ্যাপ তৈরি করেছি এবং এটিকে Google.com-এ উৎপাদনে লঞ্চ করেছি।
ফলাফল
- নেটিভ অ্যাপের চেয়ে বেশি ব্যস্ততা (4:06 মিনিট মোবাইল ওয়েব বনাম অ্যান্ড্রয়েডের 2:40 মিনিট)।
- সেবা কর্মী ক্যাশিং এর জন্য রিটার্ন ব্যবহারকারীদের জন্য 450ms দ্রুত প্রথম পেইন্ট
- 84% দর্শক পরিষেবা কর্মীকে সমর্থন করেছেন
- হোমস্ক্রীনে যোগ করুন 2015 এর তুলনায় +900% বেশি।
- 3.8% ব্যবহারকারী অফলাইনে গিয়েছিলেন কিন্তু 11k পেজ ভিউ জেনারেট করতে থাকেন!
- সাইন ইন করা ব্যবহারকারীদের 50% সক্রিয় বিজ্ঞপ্তিগুলি৷
- ব্যবহারকারীদের কাছে 536k বিজ্ঞপ্তি পাঠানো হয়েছে (12% তাদের ফিরিয়ে এনেছে)।
- 99% ব্যবহারকারীর ব্রাউজার ওয়েব কম্পোনেন্ট পলিফিল সমর্থন করে
ওভারভিউ
এই বছর, আমি Google I/O 2016 প্রগতিশীল ওয়েব অ্যাপে কাজ করার আনন্দ পেয়েছি, যার নাম স্নেহের সাথে "IOWA"। এটি প্রথমে মোবাইল, সম্পূর্ণ অফলাইনে কাজ করে এবং উপাদান ডিজাইনের দ্বারা ব্যাপকভাবে অনুপ্রাণিত হয়৷
IOWA হল একটি একক পৃষ্ঠার অ্যাপ্লিকেশন (SPA) যা ওয়েব কম্পোনেন্ট , পলিমার এবং ফায়ারবেস ব্যবহার করে তৈরি করা হয়েছে এবং অ্যাপ ইঞ্জিন (গো) এ লেখা একটি বিস্তৃত ব্যাকএন্ড রয়েছে। এটি একটি পরিষেবা কর্মী ব্যবহার করে বিষয়বস্তুকে প্রাক-ক্যাশ করে, গতিশীলভাবে নতুন পৃষ্ঠাগুলি লোড করে, দৃষ্টিভঙ্গির মধ্যে সুন্দরভাবে রূপান্তরিত করে এবং প্রথম লোডের পরে সামগ্রী পুনরায় ব্যবহার করে৷
এই কেস স্টাডিতে, আমি আরও কিছু আকর্ষণীয় স্থাপত্য সিদ্ধান্তের মধ্য দিয়ে যাব যা আমরা ফ্রন্টএন্ডের জন্য তৈরি করেছি। আপনি যদি উত্স কোডে আগ্রহী হন, Github এ এটি পরীক্ষা করে দেখুন ।
ওয়েব উপাদান ব্যবহার করে একটি SPA তৈরি করা
একটি উপাদান হিসাবে প্রতিটি পৃষ্ঠা
আমাদের ফ্রন্টএন্ড সম্পর্কে মূল দিকগুলির মধ্যে একটি হল এটি ওয়েব উপাদানগুলির চারপাশে কেন্দ্রীভূত। প্রকৃতপক্ষে, আমাদের এসপিএর প্রতিটি পৃষ্ঠা একটি ওয়েব উপাদান:
<io-home-page date="2016-05-18T17:00:00Z" app="[[app]]"></io-home-page>
<io-schedule-page date="2016-05-18T17:00:00Z" app="{ % templatetag openvariable % }app}}"></io-schedule-page>
<io-attend-page></io-attend-page>
<io-extended-page></io-extended-page>
<io-faq-page></io-faq-page>
কেন আমরা এটা করেছি? প্রথম কারণ এই কোড পঠনযোগ্য হয়. প্রথমবার পাঠক হিসাবে, আমাদের অ্যাপের প্রতিটি পৃষ্ঠা কী তা সম্পূর্ণরূপে স্পষ্ট। দ্বিতীয় কারণ হল ওয়েব উপাদানগুলির একটি SPA নির্মাণের জন্য কিছু চমৎকার বৈশিষ্ট্য রয়েছে। অনেক সাধারণ হতাশা (স্টেট ম্যানেজমেন্ট, ভিউ অ্যাক্টিভেশন, স্টাইল স্কোপিং) চলে যায় <template>
এলিমেন্ট, কাস্টম এলিমেন্টস এবং শ্যাডো ডম- এর অন্তর্নিহিত বৈশিষ্ট্যগুলির জন্য ধন্যবাদ। এগুলি ব্রাউজারে তৈরি করা বিকাশকারী সরঞ্জাম। কেন তাদের সুবিধা নিতে না?
প্রতিটি পৃষ্ঠার জন্য একটি কাস্টম উপাদান তৈরি করে, আমরা বিনামূল্যে অনেক কিছু পেয়েছি:
- পৃষ্ঠা জীবনচক্র ব্যবস্থাপনা।
- পৃষ্ঠার জন্য নির্দিষ্ট CSS/HTML স্কোপড।
- একটি পৃষ্ঠার জন্য নির্দিষ্ট সমস্ত CSS/HTML/JS প্রয়োজন অনুসারে একত্রিত এবং লোড করা হয়।
- ভিউ পুনরায় ব্যবহারযোগ্য. যেহেতু পৃষ্ঠাগুলি DOM নোড, সেগুলিকে কেবল যোগ করা বা সরানো দৃশ্যটি পরিবর্তন করে।
- ভবিষ্যত রক্ষণাবেক্ষণকারীরা আমাদের অ্যাপটিকে সহজভাবে মার্কআপ গ্রোক করে বুঝতে পারবেন।
- ব্রাউজার দ্বারা উপাদান সংজ্ঞা নিবন্ধিত এবং আপগ্রেড করা হয় হিসাবে সার্ভার-রেন্ডার করা মার্কআপ ক্রমান্বয়ে উন্নত করা যেতে পারে।
- কাস্টম উপাদানগুলির একটি উত্তরাধিকার মডেল আছে। DRY কোড ভাল কোড।
- …আরো অনেক কিছু।
আমরা IOWA-তে এই সুবিধাগুলির সম্পূর্ণ সদ্ব্যবহার করেছি। এর কিছু বিস্তারিত মধ্যে ডুব দেওয়া যাক.
গতিশীলভাবে পৃষ্ঠাগুলি সক্রিয় করা হচ্ছে
<template>
উপাদান হল ব্রাউজারের মানক উপায় পুনরায় ব্যবহারযোগ্য মার্কআপ তৈরি করার। <template>
দুটি বৈশিষ্ট্য রয়েছে যেগুলি SPAগুলি ব্যবহার করতে পারে৷ প্রথমত, টেমপ্লেটের একটি উদাহরণ তৈরি না হওয়া পর্যন্ত <template>
-এর ভিতরের যেকোনো কিছু জড় থাকে। দ্বিতীয়ত, ব্রাউজার মার্কআপ পার্স করে কিন্তু বিষয়বস্তু মূল পৃষ্ঠা থেকে পৌঁছানো যায় না। এটি একটি সত্য, মার্কআপের পুনরায় ব্যবহারযোগ্য অংশ। যেমন:
<template id="t">
<div>This markup is inert and not part of the main page's DOM.</div>
<img src="profile.png"> <!-- not loaded by the browser -->
<video id="vid" src="vid.mp4"></video> <!-- doesn't load/start -->
<script>alert("Not run until the template is stamped");</script>
</template>
পলিমার <template>
> এর কয়েকটি টাইপ এক্সটেনশন কাস্টম উপাদান সহ প্রসারিত করে , যথা <template is="dom-if">
এবং <template is="dom-repeat">
। উভয়ই কাস্টম উপাদান যা অতিরিক্ত ক্ষমতা সহ <template>
প্রসারিত করে। এবং ওয়েব উপাদানগুলির ঘোষণামূলক প্রকৃতির জন্য ধন্যবাদ, উভয়ই ঠিক যা আপনি প্রত্যাশা করেন। প্রথম উপাদান স্ট্যাম্প মার্কআপ একটি শর্তাধীন উপর ভিত্তি করে. দ্বিতীয়টি একটি তালিকার প্রতিটি আইটেমের জন্য মার্কআপ পুনরাবৃত্তি করে (ডেটা মডেল)।
কিভাবে IOWA এই ধরনের এক্সটেনশন উপাদান ব্যবহার করে?
আপনি যদি মনে করেন, IOWA এর প্রতিটি পৃষ্ঠা একটি ওয়েব উপাদান। যাইহোক, প্রথম লোডে প্রতিটি উপাদান ঘোষণা করা নির্বোধ হবে । এর অর্থ হল অ্যাপটি প্রথম লোড হলে প্রতিটি পৃষ্ঠার একটি উদাহরণ তৈরি করা। আমরা আমাদের প্রাথমিক লোড পারফরম্যান্সে আঘাত করতে চাইনি, বিশেষ করে যেহেতু কিছু ব্যবহারকারী শুধুমাত্র 1 বা 2 পৃষ্ঠাগুলিতে নেভিগেট করবে৷
আমাদের সমাধান ছিল প্রতারণা করা। IOWA-তে, আমরা প্রতিটি পৃষ্ঠার উপাদানকে একটি <template is="dom-if">
মুড়ে রাখি যাতে এর বিষয়বস্তু প্রথম বুটে লোড না হয়। তারপর আমরা পৃষ্ঠাগুলি সক্রিয় করি যখন টেমপ্লেটের name
বৈশিষ্ট্যটি URL এর সাথে মেলে। <lazy-pages>
ওয়েব উপাদান আমাদের জন্য এই সমস্ত যুক্তি পরিচালনা করে। মার্কআপ এই মত কিছু দেখায়:
<!-- Lazy pages manages the template stamping. It watches for route changes
and sets `template.if = true` on the appropriate template. -->
<lazy-pages>
<template is="dom-if" name="home">
<io-home-page date="2016-05-18T17:00:00Z"></io-home-page>
</template>
<template is="dom-if" name="schedule">
<io-schedule-page date="2016-05-18T17:00:00Z"></io-schedule-page>
</template>
<template is="dom-if" name="attend">
<io-attend-page></io-attend-page>
</template>
</lazy-pages>
আমি এটি সম্পর্কে যা পছন্দ করি তা হল যে প্রতিটি পৃষ্ঠা পার্স করা হয় এবং পৃষ্ঠা লোড হলে এটি যাওয়ার জন্য প্রস্তুত কিন্তু এটির CSS/HTML/JS শুধুমাত্র চাহিদা অনুযায়ী কার্যকর হয় (যখন এটির মূল <template>
স্ট্যাম্প করা হয়)। ওয়েব উপাদান FTW ব্যবহার করে গতিশীল + অলস দৃশ্য।
ভবিষ্যতের উন্নতি
যখন পৃষ্ঠাটি প্রথম লোড হয়, আমরা একবারে প্রতিটি পৃষ্ঠার জন্য সমস্ত HTML আমদানি লোড করছি৷ একটি সুস্পষ্ট উন্নতি হবে অলসভাবে উপাদানের সংজ্ঞা লোড করা যখন তাদের প্রয়োজন হয়। অ্যাসিঙ্ক লোডিং এইচটিএমএল আমদানির জন্য পলিমারের একটি চমৎকার সহায়কও রয়েছে:
Polymer.Base.importHref('io-home-page.html', (e) => { ... });
IOWA এটি করে না কারণ ক) আমরা অলস হয়ে গিয়েছিলাম এবং খ) আমরা কতটা পারফরম্যান্স বুস্ট দেখতে পেতাম তা স্পষ্ট নয়। আমাদের প্রথম পেইন্ট ইতিমধ্যে ~1s ছিল.
পৃষ্ঠা জীবনচক্র ব্যবস্থাপনা
কাস্টম এলিমেন্টস এপিআই একটি উপাদানের অবস্থা পরিচালনার জন্য " লাইফসাইকেল কলব্যাক " সংজ্ঞায়িত করে। আপনি যখন এই পদ্ধতিগুলি প্রয়োগ করেন, আপনি একটি উপাদানের জীবনে বিনামূল্যে হুক পাবেন:
createdCallback() {
// automatically called when an instance of the element is created.
}
attachedCallback() {
// automatically called when the element is attached to the DOM.
}
detachedCallback() {
// automatically called when the element is removed from the DOM.
}
attributeChangedCallback() {
// automatically called when an HTML attribute changes.
}
IOWA-তে এই কলব্যাকগুলি ব্যবহার করা সহজ ছিল৷ মনে রাখবেন, প্রতিটি পৃষ্ঠা একটি স্বয়ংসম্পূর্ণ DOM নোড। আমাদের SPA-তে একটি "নতুন ভিউ"-এ নেভিগেট করা হল DOM-এ একটি নোড সংযুক্ত করা এবং অন্যটিকে সরিয়ে ফেলার ব্যাপার৷
আমরা সেটআপের কাজ সম্পাদন করার জন্য attachedCallback
ব্যবহার করেছি (ইনিট স্টেট, ইভেন্ট শ্রোতাদের সংযুক্ত করুন)। যখন ব্যবহারকারীরা একটি ভিন্ন পৃষ্ঠায় নেভিগেট করেন, তখন detachedCallback
ক্লিনআপ করে (শ্রোতাদের সরান, ভাগ করা অবস্থা পুনরায় সেট করুন)। আমরা আমাদের নিজস্ব কয়েকটির সাথে নেটিভ লাইফসাইকেল কলব্যাকগুলিও প্রসারিত করেছি:
onPageTransitionDone() {
// page transition animations are complete.
},
onSubpageTransitionDone() {
// sub nav/tab page transitions are complete.
}
এগুলি কাজে দেরি করার জন্য এবং পৃষ্ঠা পরিবর্তনের মধ্যে জ্যাঙ্ক কমানোর জন্য দরকারী সংযোজন ছিল। এই বিষয়ে পরে আরো.
পৃষ্ঠা জুড়ে সাধারণ কার্যকারিতা শুকানো
উত্তরাধিকার কাস্টম উপাদানগুলির একটি শক্তিশালী বৈশিষ্ট্য। এটি ওয়েবের জন্য একটি আদর্শ উত্তরাধিকার মডেল প্রদান করে।
দুর্ভাগ্যবশত, পলিমার 1.0 এখনও লেখার সময় উপাদানের উত্তরাধিকার প্রয়োগ করতে পারেনি । ইতিমধ্যে, পলিমারের আচরণ বৈশিষ্ট্যটি ঠিক ততটাই কার্যকর ছিল। আচরণগুলি কেবল মিশ্রিত
সমস্ত পৃষ্ঠায় একই API পৃষ্ঠ তৈরি করার পরিবর্তে, শেয়ার্ড মিক্সিন তৈরি করে কোডবেসকে ড্রাই-আপ করার জন্য এটি বোধগম্য হয়েছে। উদাহরণস্বরূপ, PageBehavior
সাধারণ বৈশিষ্ট্য/পদ্ধতিগুলিকে সংজ্ঞায়িত করে যা আমাদের অ্যাপের সমস্ত পৃষ্ঠাগুলির প্রয়োজন:
PageBehavior.html
let PageBehavior = {
// Common properties all pages need.
properties: {
name: { type: String }, // Slug name of the page.
...
},
attached() {
// If the page defines a `onPageTransitionDone`, call it when the router
// fires 'page-transition-done'.
if (this.onPageTransitionDone) {
this.listen(document.body, 'page-transition-done', 'onPageTransitionDone');
}
// Update page meta data when new page is navigated to.
document.body.id = `page-${this.name}`;
document.title = this.title || 'Google I/O 2016';
// Scroll to top of new page.
if (IOWA.Elements.Scroller) {
IOWA.Elements.Scroller.scrollTop = 0;
}
this.setupSubnavEffects();
},
detached() {
this.unlisten(document.body, 'page-transition-done', 'onPageTransitionDone');
this.teardownSubnavEffects();
}
};
IOWA.IOBehaviors = IOWA.IOBehaviors || {PageBehavior: PageBehavior};
আপনি দেখতে পাচ্ছেন, PageBehavior
সাধারণ কাজগুলি সম্পাদন করে যা একটি নতুন পৃষ্ঠা পরিদর্শন করা হলে চলে৷ document.title
আপডেট করা, স্ক্রোল পজিশন রিসেট করা এবং স্ক্রোল এবং সাব নেভি ইফেক্টের জন্য ইভেন্ট লিসেনার সেট আপ করার মতো জিনিস।
স্বতন্ত্র পৃষ্ঠাগুলি একটি নির্ভরতা হিসাবে লোড করে এবং behaviors
ব্যবহার করে PageBehavior
ব্যবহার করে। প্রয়োজনে তারা এর বেস বৈশিষ্ট্য/পদ্ধতিগুলিকে ওভাররাইড করতেও বিনামূল্যে। একটি উদাহরণ হিসাবে, এখানে আমাদের হোমপেজ "সাবক্লাস" ওভাররাইড করে:
io-home-page.html
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="PageBehavior.html">
<!-- rest of the import dependencies used by the page. -->
<dom-module id="io-home-page">
<template>
<!-- PAGE'S MARKUP -->
</template>
<script>
Polymer({
is: 'io-home-page',
behaviors: [IOBehaviors.PageBehavior], // All pages have common functionality.
// Pages define their own title and slug for the router.
title: 'Schedule - Google I/O 2016',
name: 'home',
// The home page has custom setup work when it's added navigated to.
// Note: PageBehavior's attached also gets called.
attached() {
if (this.app.isPhoneSize) {
this.listen(IOWA.Elements.ScrollContainer, 'scroll', '_onPageScroll');
}
},
// The home page does its own cleanup when a new page is navigated to.
// Note: PageBehavior's detached also gets called.
detached() {
this.unlisten(IOWA.Elements.ScrollContainer, 'scroll', '_onPageScroll');
},
// The home page can define onPageTransitionDone to do extra work
// when page transitions are done, and thus preventing janky animations.
onPageTransitionDone() {
...
}
});
</script>
</dom-module>
শেয়ারিং শৈলী
আমাদের অ্যাপে বিভিন্ন উপাদানে শৈলী শেয়ার করতে, আমরা পলিমারের শেয়ার করা স্টাইল মডিউল ব্যবহার করেছি। স্টাইল মডিউল আপনাকে একবার CSS-এর একটি অংশ সংজ্ঞায়িত করতে এবং একটি অ্যাপ জুড়ে বিভিন্ন জায়গায় পুনরায় ব্যবহার করতে দেয়। আমাদের জন্য, "ভিন্ন স্থান" মানে বিভিন্ন উপাদান।
IOWA-তে, আমরা রঙ, টাইপোগ্রাফি, এবং লেআউট ক্লাস ভাগ করে নেওয়ার জন্য shared-app-styles
তৈরি করেছি এবং আমাদের তৈরি করা অন্যান্য উপাদান জুড়ে।
shared-app-styles.html
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="../bower_components/iron-flex-layout/iron-flex-layout.html">
<link rel="import" href="../bower_components/paper-styles/color.html">
<dom-module id="shared-app-styles">
<template>
<style>
[layout] {
@apply(--layout);
}
[layout][horizontal] {
@apply(--layout-horizontal);
}
.scrollable {
@apply(--layout-scroll);
}
.noscroll {
overflow: hidden;
}
/* Style radio buttons and tabs the same throughout the app */
paper-tabs {
--paper-tabs-selection-bar-color: currentcolor;
}
paper-radio-button {
--paper-radio-button-checked-color: var(--paper-cyan-600);
--paper-radio-button-checked-ink-color: var(--paper-cyan-600);
}
...
</style>
</template>
</dom-module>
io-home-page.html
<link rel="import" href="shared-app-styles.html">
<!-- Rest of import dependencies used by the page. -->
<dom-module id="io-home-page">
<template>
<style include="shared-app-styles">
:host { display: block} /* Other element styles can go here. */
</style>
<!-- PAGE'S MARKUP -->
</template>
<script>Polymer({...});</script>
</dom-module>
এখানে, <style include="shared-app-styles"></style>
হল পলিমারের সিনট্যাক্স যা বলার জন্য "শেয়ারড-অ্যাপ-স্টাইল" নামের মডিউলের শৈলীগুলি অন্তর্ভুক্ত করুন।
শেয়ারিং আবেদনের অবস্থা
এতক্ষণে আপনি জানেন যে আমাদের অ্যাপের প্রতিটি পৃষ্ঠা একটি কাস্টম উপাদান। আমি এটা এক মিলিয়ন বার বলেছি. ঠিক আছে, কিন্তু প্রতিটি পৃষ্ঠা যদি স্বয়ংসম্পূর্ণ ওয়েব কম্পোনেন্ট হয়, তাহলে আপনি হয়তো নিজেকে জিজ্ঞাসা করছেন যে আমরা কীভাবে অ্যাপ জুড়ে রাজ্য শেয়ার করি।
IOWA রাজ্য ভাগ করার জন্য নির্ভরতা ইনজেকশন (কৌণিক) বা রেডাক্স (প্রতিক্রিয়া) এর মতো একটি কৌশল ব্যবহার করে। আমরা একটি গ্লোবাল app
প্রপার্টি তৈরি করেছি এবং শেয়ার করা সাব-প্রপার্টিগুলো বন্ধ করে দিয়েছি। app
আমাদের অ্যাপ্লিকেশনের চারপাশে প্রবেশ করে এটিকে প্রতিটি উপাদানের মধ্যে ইনজেকশন করে যার ডেটা প্রয়োজন। পলিমারের ডেটা বাইন্ডিং বৈশিষ্ট্যগুলি ব্যবহার করা এটিকে সহজ করে তোলে কারণ আমরা কোনও কোড না লিখে ওয়্যারিং করতে পারি:
<lazy-pages>
<template is="dom-if" name="home">
<io-home-page date="2016-05-18T17:00:00Z" app="[[app]]"></io-home-page>
</template>
<template is="dom-if" name="schedule">
<io-schedule-page date="2016-05-18T17:00:00Z" app="{ % templatetag openvariable % }app}}"></io-schedule-page>
</template>
...
</lazy-pages>
<google-signin client-id="..." scopes="profile email"
user="{ % templatetag openvariable % }app.currentUser}}"></google-signin>
<iron-media-query query="(min-width:320px) and (max-width:768px)"
query-matches="{ % templatetag openvariable % }app.isPhoneSize}}"></iron-media-query>
ব্যবহারকারীরা আমাদের অ্যাপে লগ ইন করলে <google-signin>
উপাদানটি তার user
বৈশিষ্ট্য আপডেট করে। যেহেতু সেই প্রপার্টি app.currentUser
এর সাথে আবদ্ধ, যে কোনো পৃষ্ঠা যেটি বর্তমান ব্যবহারকারীকে অ্যাক্সেস করতে চায় তাকে কেবল app
সাথে আবদ্ধ হতে হবে এবং currentUser
উপ-সম্পত্তি পড়তে হবে। নিজেই, এই কৌশলটি অ্যাপ জুড়ে রাজ্য ভাগ করার জন্য দরকারী। যাইহোক, আরেকটি সুবিধা হল যে আমরা একটি একক সাইন-ইন উপাদান তৈরি করেছি এবং এর ফলাফলগুলি পুরো সাইট জুড়ে পুনরায় ব্যবহার করেছি । মিডিয়া প্রশ্নের জন্য একই. প্রতিটি পৃষ্ঠার জন্য নকল সাইন-ইন করা বা মিডিয়া ক্যোয়ারীগুলির নিজস্ব সেট তৈরি করা অযথা হবে৷ পরিবর্তে, অ্যাপ-ব্যাপী কার্যকারিতা/ডেটার জন্য দায়ী উপাদানগুলি অ্যাপ-লেভেলে বিদ্যমান।
পৃষ্ঠার রূপান্তর
আপনি যখন Google I/O ওয়েব অ্যাপে নেভিগেট করবেন, আপনি এর চটকদার পৃষ্ঠার রূপান্তর লক্ষ্য করবেন ( à la material design )।
যখন ব্যবহারকারীরা একটি নতুন পৃষ্ঠায় নেভিগেট করেন, তখন জিনিসগুলির একটি ক্রম ঘটে:
- উপরের নেভিটি নতুন লিঙ্কে একটি নির্বাচন বার স্লাইড করে।
- পৃষ্ঠার শিরোনাম দূরে বিবর্ণ.
- পৃষ্ঠার বিষয়বস্তু নিচের দিকে স্লাইড করে তারপর বিবর্ণ হয়ে যায়।
- সেই অ্যানিমেশনগুলিকে বিপরীত করে, নতুন পৃষ্ঠার শিরোনাম এবং বিষয়বস্তু প্রদর্শিত হবে৷
- (ঐচ্ছিক) নতুন পৃষ্ঠাটি অতিরিক্ত আরম্ভ করার কাজ করে।
আমাদের চ্যালেঞ্জগুলির মধ্যে একটি হল কর্মক্ষমতা ত্যাগ না করে কীভাবে এই চটকদার রূপান্তরটি তৈরি করা যায় তা খুঁজে বের করা। অনেক গতিশীল কাজ হচ্ছে, এবং আমাদের পার্টিতে জ্যাঙ্ককে স্বাগত জানানো হয়নি। আমাদের সমাধান ছিল ওয়েব অ্যানিমেশন API এবং প্রতিশ্রুতির সমন্বয়। দুটি একসাথে ব্যবহার করে আমাদের বহুমুখীতা, একটি প্লাগ এবং প্লে অ্যানিমেশন সিস্টেম এবং দানাদার কন্ট্রোল ডাস জ্যাঙ্ক কমিয়ে দিয়েছে।
এটা কিভাবে কাজ করে
যখন ব্যবহারকারীরা একটি নতুন পৃষ্ঠায় ক্লিক করেন (বা পিছনে/আগামীতে আঘাত করেন), আমাদের রাউটারের runPageTransition()
প্রতিশ্রুতির একটি সিরিজের মাধ্যমে তার যাদু করে। প্রতিশ্রুতি ব্যবহার করা আমাদেরকে অ্যানিমেশনগুলি যত্ন সহকারে সাজানোর অনুমতি দিয়েছে এবং CSS অ্যানিমেশনগুলির "অ্যাসিঙ্ক-নেস" এবং গতিশীলভাবে সামগ্রী লোড করতে সাহায্য করেছে৷
class Router {
init() {
window.addEventListener('popstate', e => this.runPageTransition());
}
runPageTransition() {
let endPage = this.state.end.page;
this.fire('page-transition-start'); // 1. Let current page know it's starting.
IOWA.PageAnimation.runExitAnimation() // 2. Play exist animation sequence.
.then(() => {
IOWA.Elements.LazyPages.selected = endPage; // 3. Activate new page in <lazy-pages>.
this.state.current = this.parseUrl(this.state.end.href);
})
.then(() => IOWA.PageAnimation.runEnterAnimation()) // 4. Play entry animation sequence.
.then(() => this.fire('page-transition-done')) // 5. Tell new page transitions are done.
.catch(e => IOWA.Util.reportError(e));
}
}
"কিপিং থিংস ড্রাই: পৃষ্ঠাগুলিতে সাধারণ কার্যকারিতা" বিভাগ থেকে স্মরণ করুন , পৃষ্ঠাগুলি page-transition-start
এবং page-transition-done
DOM ইভেন্টগুলির জন্য শোনে। এখন আপনি দেখতে পাচ্ছেন যে সেই ইভেন্টগুলি কোথায় ছড়িয়ে পড়ে।
আমরা runEnterAnimation
/ runExitAnimation
সহায়কের পরিবর্তে Web Animations API ব্যবহার করেছি। runExitAnimation
এর ক্ষেত্রে, আমরা কয়েকটি DOM নোড (মাস্টহেড এবং প্রধান বিষয়বস্তু এলাকা) ধরি, প্রতিটি অ্যানিমেশনের শুরু/শেষ ঘোষণা করি এবং দুটিকে সমান্তরালভাবে চালানোর জন্য একটি GroupEffect
তৈরি করি:
function runExitAnimation(section) {
let main = section.querySelector('.slide-up');
let masthead = section.querySelector('.masthead');
let start = {transform: 'translate(0,0)', opacity: 1};
let end = {transform: 'translate(0,-100px)', opacity: 0};
let opts = {duration: 400, easing: 'cubic-bezier(.4, 0, .2, 1)'};
let opts_delay = {duration: 400, delay: 200};
return new GroupEffect([
new KeyframeEffect(masthead, [start, end], opts),
new KeyframeEffect(main, [{opacity: 1}, {opacity: 0}], opts_delay)
]);
}
ভিউ ট্রানজিশন আরও (বা কম) বিস্তৃত করতে শুধু অ্যারে পরিবর্তন করুন!
স্ক্রোল প্রভাব
আপনি যখন পৃষ্ঠাটি স্ক্রোল করেন তখন IOWA এর কিছু আকর্ষণীয় প্রভাব রয়েছে। প্রথমটি হল আমাদের ফ্লোটিং অ্যাকশন বোতাম (এফএবি) যা ব্যবহারকারীদের পৃষ্ঠার শীর্ষে নিয়ে যায়:
<a href="#" tabindex="-1" aria-hidden="true" aria-label="back to top" onclick="backToTop">
<paper-fab icon="io:expand-less" noink tabindex="-1"></paper-fab>
</a>
পলিমারের অ্যাপ-লেআউট উপাদান ব্যবহার করে মসৃণ স্ক্রোল প্রয়োগ করা হয়। তারা স্টিকি/রিটার্নিং টপ নেভিস, ড্রপ শ্যাডো, কালার এবং ব্যাকগ্রাউন্ড ট্রানজিশন, প্যারালাক্স ইফেক্ট এবং মসৃণ স্ক্রোলিং এর মতো আউট-অফ-দ্য-বক্স স্ক্রলিং ইফেক্ট প্রদান করে।
// Smooth scrolling the back to top FAB.
function backToTop(e) {
e.preventDefault();
Polymer.AppLayout.scroll({top: 0, behavior: 'smooth',
target: document.documentElement});
e.target.blur(); // Kick focus back to the page so user starts from the top of the doc.
}
আরেকটি জায়গায় আমরা <app-layout>
উপাদানগুলি ব্যবহার করেছি স্টিকি নেভির জন্য। আপনি ভিডিওতে দেখতে পাচ্ছেন, ব্যবহারকারীরা যখন পৃষ্ঠাটি নিচে স্ক্রোল করে এবং ব্যাক আপ স্ক্রোল করার সময় ফিরে আসে তখন এটি চলে যায়।
আমরা <app-header>
এলিমেন্ট ব্যবহার করেছি অনেকটা যেমন-ই। অ্যাপটিতে ড্রপ করা এবং অভিনব স্ক্রোলিং প্রভাব অর্জন করা সহজ ছিল। অবশ্যই, আমরা সেগুলি নিজেরাই প্রয়োগ করতে পারতাম, তবে পুনঃব্যবহারযোগ্য উপাদানে ইতিমধ্যেই বিশদ বিবরণগুলি কোড করা একটি বিশাল সময় সাশ্রয়কারী ছিল।
উপাদান ঘোষণা. বৈশিষ্ট্য সহ এটি কাস্টমাইজ করুন. আপনি সম্পন্ন!
<app-header reveals condenses effects="fade-background waterfall"></app-header>
উপসংহার
I/O প্রগ্রেসিভ ওয়েব অ্যাপের জন্য, ওয়েব কম্পোনেন্ট এবং পলিমারের আগে থেকে তৈরি ম্যাটেরিয়াল ডিজাইন উইজেটগুলির জন্য আমরা কয়েক সপ্তাহের মধ্যে একটি সম্পূর্ণ ফ্রন্টএন্ড তৈরি করতে সক্ষম হয়েছি। নেটিভ এপিআই-এর বৈশিষ্ট্য (কাস্টম এলিমেন্টস, শ্যাডো ডম, <template>
> ) একটি এসপিএর গতিশীলতাকে স্বাভাবিকভাবেই ধার দেয়। পুনঃব্যবহারযোগ্যতা এক টন সময় বাঁচায়।
আপনি যদি নিজের একটি প্রগতিশীল ওয়েব অ্যাপ তৈরি করতে আগ্রহী হন তবে অ্যাপ টুলবক্সটি দেখুন। পলিমার অ্যাপ টুলবক্স হল পলিমারের সাহায্যে PWA তৈরির জন্য উপাদান, টুল এবং টেমপ্লেটের একটি সংগ্রহ। এটা উঠার এবং দৌড়ানোর একটি সহজ উপায়।