این نرم افزار کد بخشی از دوره آموزشی توسعه برنامه های وب پیشرفته است که توسط تیم آموزش توسعه دهندگان گوگل توسعه یافته است. اگر به ترتیب روی کدها کار کنید، بیشترین ارزش را از این دوره خواهید گرفت.
برای جزئیات کامل در مورد دوره، به نمای کلی توسعه برنامه های وب پیشرفته مراجعه کنید .
مقدمه
در این آزمایشگاه شما از Lighthouse برای ممیزی وب سایت برای استانداردهای برنامه پیشرو وب (PWA) استفاده خواهید کرد. همچنین قابلیت آفلاین را با API service worker اضافه خواهید کرد.
چیزی که یاد خواهید گرفت
- نحوه ممیزی سایت ها با Lighthouse
- چگونه قابلیت های آفلاین را به برنامه اضافه کنیم
آنچه شما باید بدانید
- HTML، CSS و جاوا اسکریپت اولیه
- آشنایی با ES2015 Promises
آنچه شما نیاز خواهید داشت
- کامپیوتر با دسترسی ترمینال/پوسته
- اتصال به اینترنت
- مرورگر کروم (برای استفاده از Lighthouse)
- یک ویرایشگر متن
- اختیاری: Chrome در دستگاه Android
مخزن pwa-training-labs را از github دانلود یا کلون کنید و در صورت نیاز نسخه LTS Node.js را نصب کنید.
به دایرکتوری offline-quickstart-lab/app/
بروید و یک سرور توسعه محلی راه اندازی کنید:
cd offline-quickstart-lab/app npm install node server.js
شما می توانید سرور را در هر زمان با Ctrl-c
خاتمه دهید.
مرورگر خود را باز کنید و به localhost:8081/
بروید. باید ببینید که سایت یک صفحه وب ساده و ثابت است.
توجه: همه سرویسکاران را لغو ثبت کنید و تمام کشهای سرویسکار را برای لوکال هاست پاک کنید تا با آزمایشگاه تداخل نداشته باشند. در Chrome DevTools، میتوانید با کلیک کردن بر روی پاک کردن دادههای سایت از بخش پاک کردن فضای ذخیرهسازی تب Application به این مهم دست یابید.
پوشه offline-quickstart-lab/app/
را در ویرایشگر متن دلخواه خود باز کنید. app/
پوشه جایی است که آزمایشگاه را می سازید.
این پوشه شامل:
-
images/
پوشه حاوی تصاویر نمونه است -
styles/main.css
شیوه نامه اصلی است -
index.html
صفحه اصلی HTML برای سایت نمونه ما است -
package-lock.json
وpackage.json
وابستگی های برنامه را دنبال می کنند (تنها وابستگی ها در این مورد برای سرور توسعه محلی است) -
server.js
یک سرور توسعه محلی برای آزمایش است -
service-worker.js
فایل Service Worker است (در حال حاضر خالی است)
قبل از شروع تغییرات در سایت، اجازه دهید با Lighthouse حسابرسی کنیم تا ببینیم چه چیزی می تواند بهبود یابد.
به برنامه (در کروم) بازگردید و برگه حسابرسی ابزارهای برنامهنویس را باز کنید. شما باید نماد Lighthouse و گزینه های پیکربندی را ببینید. "Mobile" را برای Device انتخاب کنید، همه حسابرسی ها را انتخاب کنید، یکی از گزینه های Throttling را انتخاب کنید و گزینه Clear storage را انتخاب کنید:
روی اجرای ممیزی ها کلیک کنید. ممیزی ها چند لحظه طول می کشد تا کامل شوند.
توضیح
پس از تکمیل ممیزی، باید گزارشی با امتیازات در ابزارهای توسعهدهنده ببینید. باید نمرات را نشان دهد، چیزی شبیه به این (نمرات ممکن است دقیقاً یکسان نباشند):
توجه: امتیازات Lighthouse یک تقریبی است و می تواند تحت تأثیر محیط شما باشد (مثلاً اگر تعداد زیادی پنجره مرورگر باز دارید). نمرات شما ممکن است دقیقاً مشابه امتیازهای نشان داده شده در اینجا نباشد.
و بخش Progressive Web App باید شبیه به این باشد:
این گزارش دارای امتیازات و معیارهایی در پنج دسته است:
- برنامه وب پیشرو
- کارایی
- دسترسی
- بهترین شیوه ها
- سئو
همانطور که می بینید، برنامه ما در دسته برنامه وب پیشرو (PWA) امتیاز ضعیفی کسب می کند. بیایید امتیاز خود را بهبود بخشیم!
لحظه ای به بخش PWA گزارش نگاه کنید و ببینید چه چیزی کم است.
ثبت نام کارگر خدماتی
یکی از خرابی های ذکر شده در گزارش این است که هیچ خدمتگزار ثبت نام نشده است. ما در حال حاضر یک فایل Service Worker خالی در app/service-worker.js
.
اسکریپت زیر را درست قبل از بسته شدن تگ </body>
به پایین index.html
اضافه کنید:
<script>
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('service-worker.js')
.then(reg => {
console.log('Service worker registered! 😎', reg);
})
.catch(err => {
console.log('😥 Service worker registration failed: ', err);
});
});
}
</script>
توضیح
این کد فایل خالی sw.js
service worker را پس از بارگیری صفحه ثبت می کند. با این حال فایل سرویس کارگر فعلی خالی است و کاری انجام نمی دهد. بیایید کد سرویس را در مرحله بعد اضافه کنیم.
منابع پیش کش
یکی دیگر از مشکلات ذکر شده در گزارش این است که برنامه در حالت آفلاین با کد وضعیت 200 پاسخ نمی دهد. برای حل این مشکل باید کارمند خدمات خود را به روز کنیم.
کد زیر را به فایل Service Worker ( sw.js
) اضافه کنید:
const cacheName = 'cache-v1';
const precacheResources = [
'/',
'index.html',
'styles/main.css',
'images/space1.jpg',
'images/space2.jpg',
'images/space3.jpg'
];
self.addEventListener('install', event => {
console.log('Service worker install event!');
event.waitUntil(
caches.open(cacheName)
.then(cache => {
return cache.addAll(precacheResources);
})
);
});
self.addEventListener('activate', event => {
console.log('Service worker activate event!');
});
self.addEventListener('fetch', event => {
console.log('Fetch intercepted for:', event.request.url);
event.respondWith(caches.match(event.request)
.then(cachedResponse => {
if (cachedResponse) {
return cachedResponse;
}
return fetch(event.request);
})
);
});
حالا به مرورگر برگردید و سایت را رفرش کنید. کنسول را بررسی کنید تا ببینید که سرویس دهنده:
- ثبت شده است
- نصب شده است
- فعال شد
توجه: اگر قبلاً سرویسکار را ثبتنام کردهاید، یا برای فعال کردن همه رویدادها با مشکل مواجه هستید، ثبت نام هر سرویسکار را لغو کرده و صفحه را بازخوانی کنید. اگر موفق نشد، همه نمونههای برنامه را ببندید و دوباره باز کنید.
سپس، سرور توسعه محلی را در خط فرمان خود با اجرای Ctrl + c
خاتمه دهید. سایت را دوباره رفرش کنید و مشاهده کنید که با وجود آفلاین بودن سرور، بارگذاری می شود!
توجه: ممکن است یک خطای کنسول ببینید که نشان میدهد سرویسکار نمیتواند واکشی شود: An unknown error occurred when fetching the script. service-worker.js Failed to load resource: net::ERR_CONNECTION_REFUSED
. این خطا به این دلیل نشان داده میشود که مرورگر نمیتواند اسکریپت Service Worker را واکشی کند (زیرا سایت آفلاین است)، اما این مورد انتظار است زیرا ما نمیتوانیم از سرویسکار برای ذخیره خود استفاده کنیم. در غیر این صورت مرورگر کاربر برای همیشه با همان سرویس دهنده گیر می کرد!
توضیح
هنگامی که سرویسکار توسط اسکریپت ثبت در index.html
ثبت شد، رویداد install
سرویسکار رخ میدهد. در طول این رویداد، شنونده رویداد install
یک کش با نام را باز میکند و فایلهای مشخصشده با متد cache.addAll
را ذخیره میکند. این "پیش کش" نامیده می شود زیرا در طول رویداد install
اتفاق می افتد، که معمولاً اولین بار است که کاربر از سایت شما بازدید می کند.
پس از نصب یک سرویسکار، و اگر سرویسکار دیگری در حال حاضر صفحه را کنترل نکند، سرویسکار جدید «فعال میشود» (شنونده رویداد activate
در سرویسکار فعال میشود) و شروع به کنترل صفحه میکند.
هنگامی که منابع توسط صفحهای درخواست میشود که یک سرویسکار فعال آن را کنترل میکند، درخواستها مانند یک پروکسی شبکه از طریق کارگر خدمات ارسال میشوند. برای هر درخواست یک رویداد fetch
راه اندازی می شود. در سرویسکار ما، شنونده رویداد fetch
حافظههای پنهان را جستجو میکند و در صورت وجود منبع ذخیرهشده به آن پاسخ میدهد. اگر منبع ذخیره نشده باشد، منبع به طور معمول درخواست می شود.
ذخیره منابع به برنامه اجازه می دهد تا با اجتناب از درخواست های شبکه به صورت آفلاین کار کند. اکنون برنامه ما می تواند در صورت آفلاین بودن با کد وضعیت 200 پاسخ دهد!
توجه: رویداد activate برای هیچ چیز غیر از ورود به سیستم در این مثال استفاده نمی شود. این رویداد برای کمک به رفع اشکالات مربوط به چرخه عمر کارگر خدمات گنجانده شد.
اختیاری : همچنین میتوانید با گسترش بخش ذخیرهسازی حافظه پنهان، منابع ذخیرهشده را در تب Application Developer Tools مشاهده کنید:
سرور توسعه را با node server.js
راه اندازی مجدد کنید و سایت را به روز کنید. سپس دوباره تب Audits را در Developer Tools باز کنید و با انتخاب New Audit (علامت مثبت در گوشه سمت چپ بالا) بازرسی Lighthouse را دوباره اجرا کنید. هنگامی که ممیزی به پایان رسید، باید ببینید که امتیاز PWA ما به طور قابل توجهی بهتر است، اما همچنان میتوان آن را بهبود بخشید. ما در بخش بعدی به بهبود امتیاز خود ادامه خواهیم داد.
توجه: این بخش اختیاری است زیرا آزمایش بنر نصب برنامه وب خارج از محدوده آزمایشگاه است. می توانید آن را به تنهایی با استفاده از اشکال زدایی از راه دور امتحان کنید.
امتیاز PWA ما هنوز عالی نیست. برخی از خرابیهای باقیمانده ذکر شده در گزارش این است که از کاربر خواسته نمیشود برنامه وب ما را نصب کند، و اینکه ما یک صفحه نمایش یا رنگهای برند را در نوار آدرس پیکربندی نکردهایم. ما می توانیم این مشکلات را برطرف کنیم و با رعایت برخی معیارهای اضافی، افزودن به صفحه اصلی را به تدریج پیاده سازی کنیم. مهمتر از همه، ما باید یک فایل مانیفست ایجاد کنیم.
یک فایل Manifest ایجاد کنید
یک فایل در app/
به نام manifest.json
ایجاد کنید و کد زیر را اضافه کنید:
{
"name": "Space Missions",
"short_name": "Space Missions",
"lang": "en-US",
"start_url": "/index.html",
"display": "standalone",
"theme_color": "#FF9800",
"background_color": "#FF9800",
"icons": [
{
"src": "images/touch/icon-128x128.png",
"sizes": "128x128"
},
{
"src": "images/touch/icon-192x192.png",
"sizes": "192x192"
},
{
"src": "images/touch/icon-256x256.png",
"sizes": "256x256"
},
{
"src": "images/touch/icon-384x384.png",
"sizes": "384x384"
},
{
"src": "images/touch/icon-512x512.png",
"sizes": "512x512"
}
]
}
تصاویر ارجاع شده در مانیفست قبلاً در برنامه ارائه شده است.
سپس HTML زیر را به پایین تگ <head>
در index.html
اضافه کنید:
<link rel="manifest" href="manifest.json">
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="application-name" content="Space Missions">
<meta name="apple-mobile-web-app-title" content="Space Missions">
<meta name="theme-color" content="#FF9800">
<meta name="msapplication-navbutton-color" content="#FF9800">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="msapplication-starturl" content="/index.html">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="icon" sizes="128x128" href="/images/touch/icon-128x128.png">
<link rel="apple-touch-icon" sizes="128x128" href="/images/touch/icon-128x128.png">
<link rel="icon" sizes="192x192" href="icon-192x192.png">
<link rel="apple-touch-icon" sizes="192x192" href="/images/touch/icon-192x192.png">
<link rel="icon" sizes="256x256" href="/images/touch/icon-256x256.png">
<link rel="apple-touch-icon" sizes="256x256" href="/images/touch/icon-256x256.png">
<link rel="icon" sizes="384x384" href="/images/touch/icon-384x384.png">
<link rel="apple-touch-icon" sizes="384x384" href="/images/touch/icon-384x384.png">
<link rel="icon" sizes="512x512" href="/images/touch/icon-512x512.png">
<link rel="apple-touch-icon" sizes="512x512" href="/images/touch/icon-512x512.png">
به سایت برگردید. در تب Application Developer Tools، بخش Clear storage را انتخاب کرده و روی Clear site data کلیک کنید. سپس صفحه را رفرش کنید. حال قسمت Manifest را انتخاب کنید. شما باید نمادها و گزینه های پیکربندی را که در فایل manifest.json
پیکربندی شده اند ببینید. اگر تغییرات خود را نمی بینید، سایت را در یک پنجره ناشناس باز کنید و دوباره بررسی کنید.
توضیح
فایل manifest.json
به مرورگر میگوید که چگونه برخی از جنبههای پیشرونده برنامه شما، مانند مرورگر کروم، نماد صفحه اصلی و صفحه نمایش اسپلش را استایل و قالببندی کند. همچنین میتوان از آن برای پیکربندی برنامه وب خود برای باز کردن در حالت standalone
، مانند برنامه بومی (به عبارت دیگر، خارج از مرورگر) استفاده کرد.
پشتیبانی هنوز برای برخی از مرورگرها تا زمان نگارش این مقاله در دست توسعه است و تگهای <meta>
زیرمجموعهای از این ویژگیها را برای مرورگرهایی که هنوز پشتیبانی کامل ندارند پیکربندی میکنند.
ما مجبور شدیم اطلاعات سایت را پاک کنیم تا نسخه کش قدیمی index.html
را حذف کنیم (زیرا آن نسخه پیوند مانیفست را نداشت). یکی دیگر از ممیزی Lighthouse را امتحان کنید و ببینید که نمره PWA چقدر بهبود یافته است!
فعال کردن اعلان نصب
گام بعدی برای نصب برنامه ما این است که به کاربران اعلان نصب را نشان دهیم. Chrome 67 به طور خودکار از کاربران درخواست میکند، اما از Chrome 68 ، درخواست نصب باید به صورت برنامهریزی در پاسخ به اشاره کاربر فعال شود.
دکمه و بنر «نصب برنامه» را به بالای index.html
(درست بعد از تگ <main>
) با کد زیر اضافه کنید:
<section id="installBanner" class="banner">
<button id="installBtn">Install app</button>
</section>
سپس با افزودن سبک های زیر به styles/main.css
، بنر را استایل دهید:
.banner {
align-content: center;
display: none;
justify-content: center;
width: 100%;
}
فایل را ذخیره کنید. در نهایت تگ اسکریپت زیر را به index.html
اضافه کنید:
<script>
let deferredPrompt;
window.addEventListener('beforeinstallprompt', event => {
// Prevent Chrome 67 and earlier from automatically showing the prompt
event.preventDefault();
// Stash the event so it can be triggered later.
deferredPrompt = event;
// Attach the install prompt to a user gesture
document.querySelector('#installBtn').addEventListener('click', event => {
// Show the prompt
deferredPrompt.prompt();
// Wait for the user to respond to the prompt
deferredPrompt.userChoice
.then((choiceResult) => {
if (choiceResult.outcome === 'accepted') {
console.log('User accepted the A2HS prompt');
} else {
console.log('User dismissed the A2HS prompt');
}
deferredPrompt = null;
});
});
// Update UI notify the user they can add to home screen
document.querySelector('#installBanner').style.display = 'flex';
});
</script>
فایل را ذخیره کنید. با استفاده از اشکال زدایی از راه دور ، برنامه را در Chrome در دستگاه Android باز کنید. وقتی صفحه بارگیری میشود، باید دکمه «نصب برنامه» را ببینید (آن را روی دسکتاپ نمیبینید، بنابراین مطمئن شوید که در حال آزمایش روی موبایل هستید). روی دکمه کلیک کنید و اعلان افزودن به صفحه اصلی باید ظاهر شود. مراحل نصب برنامه را روی دستگاه خود دنبال کنید. پس از نصب، باید بتوانید برنامه وب را در حالت مستقل (خارج از مرورگر) با ضربه زدن روی نماد صفحه اصلی تازه ایجاد شده باز کنید.
توضیح
کد HTML و CSS یک بنر و دکمه مخفی اضافه می کند که می توانیم از آن برای فعال کردن درخواست نصب به کاربران اجازه دهیم.
هنگامی که رویداد beforeinstallprompt
، از تجربه پیشفرض (که در آن Chrome 67 و beforeinstallevent
خودکار از کاربران درخواست میکند نصب کنند) جلوگیری میکنیم و قبل از نصب را در متغیر deferredPrompt
جهانی ثبت میکنیم. سپس دکمه «نصب برنامه» به گونهای پیکربندی میشود که درخواست را با متد prompt()
beforeinstallevent
نشان دهد. پس از انتخاب کاربر (نصب یا عدم نصب)، وعده userChoice
با انتخاب کاربر ( outcome
) حل می شود. در نهایت، زمانی که همه چیز آماده شد، دکمه نصب را نمایش می دهیم.
شما یاد گرفته اید که چگونه سایت ها را با Lighthouse ممیزی کنید، و چگونه اصول عملکرد آفلاین را پیاده سازی کنید. اگر بخش های اختیاری را تکمیل کرده باشید، نحوه نصب برنامه های وب را در صفحه اصلی نیز یاد گرفته اید!
منابع بیشتر
Lighthouse منبع باز است! میتوانید آن را فورک کنید، آزمایشهای خود را اضافه کنید و باگها را پرونده کنید. Lighthouse همچنین به عنوان یک ابزار خط فرمان برای ادغام با فرآیندهای ساخت در دسترس است.
برای مشاهده تمامی کدهای دوره آموزشی PWA به کدلبورد خوش آمدید دوره مراجعه کنید/