תגי עיצוב, עיצוב, סקריפטים ועדכון של מיני אפליקציות

תומאס סטיינר
תומאס סטיינר

Markup languages

כפי שתיארנו קודם, במקום להשתמש ב-HTML פשוט, המיני אפליקציות נכתבות בדיאלקטים של HTML. אם התמודדתם בעבר עם הוראות ואינטרפולציית טקסט של Vue.js, תרגישו מיד בנוח, אבל מושגים דומים היו קיימים הרבה לפני כן בטרנספורמציות של XML (XSLT). בהמשך מוצגות דוגמאות קוד מ-WXML של WeChat, אבל הקונספט זהה בכל הפלטפורמות של אפליקציות מיניאטוריות: AXML של Alipay , Swan Element של Baidu, TTML של ByteDance (למרות שה-DevTools קורא לו Bxml) ו-HTML של אפליקציית Quick App. בדיוק כמו ב-Vue.js, הקונספט הבסיסי לתכנות אפליקציות מיני הוא model-view-viewmodel (MVVM).

קישור נתונים

קישור הנתונים תואם לאינטרפולציית הטקסט של Vue.js.

<!-- wxml -->
<view>{{message}}</view>
// page.js
Page({
  data: {
    message: "Hello World!",
  },
});

עיבוד רשימה

עיבוד רשימות פועל כמו הוראת v-for של Vue.js.

<!-- wxml -->
<view wx:for="{{array}}">{{item}}</view>
// page.js
Page({
  data: {
    array: [1, 2, 3, 4, 5],
  },
});

רינדור מותנה

רינדור מותנה פועל כמו ההנחיה v-if של Vue.js.

<!-- wxml -->
<view wx:if="{{view == 'one'}}">One</view>
<view wx:elif="{{view == 'two'}}">Two</view>
<view wx:else="{{view == 'three'}}">Three</view>
// page.js
Page({
  data: {
    view: "three",
  },
});

תבניות

במקום לדרוש שכפול של ה-content של תבנית HTML, אפשר להשתמש בתבניות WXML באופן מוצהר באמצעות המאפיין is שמקשר להגדרת תבנית.

<!-- wxml -->
<template name="person">
  <view>
    First Name: {{firstName}}, Last Name: {{lastName}}
  </view>
</template>
<template is="person" data="{{...personA}}"></template>
<template is="person" data="{{...personB}}"></template>
<template is="person" data="{{...personC}}"></template>
// page.js
Page({
  data: {
    personA: { firstName: "Alice", lastName: "Foo" },
    personB: { firstName: "Bob", lastName: "Bar" },
    personC: { firstName: "Charly", lastName: "Baz" },
  },
});

שינוי סגנון

העיצוב מתרחש בדיאלקטים של CSS. השם של WeChat הוא WXSS. השירות של Alipay נקרא ACSS , CSS ב-Baidu, והדיאלקט של ByteDance נקרא TTSS. המשותף להן הוא שהן מרחיבים את ה-CSS באמצעות פיקסלים רספונסיביים. כשכותבים CSS רגיל, המפתחים צריכים להמיר את כל יחידות הפיקסלים כדי להתאים את עצמם למסכים שונים של מכשירים ניידים עם רוחב שונה ויחסי פיקסלים שונים. בשירות TTSS יש תמיכה ביחידה rpx בתור השכבה הבסיסית שלה, כך שהמיני-אפליקציה משתלטת על המשימה של המפתח וממירה את היחידות בשמו, בהתאם לרוחב מסך של 750rpx שצוין. לדוגמה, בטלפון Pixel 3a עם רוחב מסך של 393px (ויחס פיקסלים של 2.75 במכשיר), התגובה 200rpx תהיה 104px במכשיר האמיתי כשנבדקה באמצעות כלי הפיתוח ל-Chrome (393px / 750rpx * 200rpx ≈ 104px). ב-Android, אותו קונספט נקרא פיקסל בלתי תלוי בדחיסות.

כשבודקים תצוגה באמצעות כלי הפיתוח ל-Chrome, שהמרווח הפנימי של הפיקסלים הרספונסיביות שלה צוין עם &#39;200rpx&#39;, נראה שהיא אכן &#39;104px&#39; במכשיר Pixel 3a.
בדיקת המרווח הפנימי בפועל במכשיר Pixel 3a באמצעות כלי הפיתוח ל-Chrome.
/* app.wxss */
.container {
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-between;
  padding: 200rpx 0; /* ← responsive pixels */
  box-sizing: border-box;
}

מאחר שרכיבים (ראו מאוחר יותר) לא משתמשים ב-DOM של צל, סגנונות שהוכרזו בדף היקף החשיפה לכל הרכיבים. הארגון הנפוץ של קובץ גיליון הסגנונות צריך לכלול גיליון סגנונות בסיס אחד עבור סגנונות כלליים, וגיליונות סגנונות נפרדים לכל דף וספציפיים לכל דף באפליקציה המוקטנת. ניתן לייבא סגנונות באמצעות כלל @import שנוהג כמו ה-CSS @import בכלל. כמו ב-HTML, אפשר להצהיר על סגנונות גם בתוך השורה, כולל אינטרפולציה של טקסט דינמי (ראו לפני).

<view style="color:{{color}};" />

ביצוע סקריפטים

מיני אפליקציות תומכות ב'קבוצת משנה בטוחה' של JavaScript, שכוללת תמיכה במודולים עם תחבירים שונים שמזכירים את CommonJS או את RequireJS. אי אפשר להריץ קוד JavaScript דרך eval(), ואי אפשר ליצור פונקציות עם new Function(). הקשר הביצוע של סקריפט הוא V8 או JavaScriptCore במכשירים, ו-V8 או NW.js בסימולטור. בדרך כלל אפשר לכתוב קוד עם ES6 או תחביר חדש יותר, כי כלי הפיתוח הספציפיים ממירים את הקוד ל-ES5 באופן אוטומטי אם יעד ה-build הוא מערכת הפעלה עם הטמעה ישנה של WebView (ראו מאוחר יותר). במסמכי התיעוד של ספקי אפליקציות העל יש אזכור מפורש של שפות הסקריפט שלהם, והן ייחודיות מ-JavaScript. עם זאת, ההצהרה מתייחסת בעיקר לאופן שבו המודולים פועלים, כלומר הם עדיין לא תומכים במודולים רגילים של ES.

כפי שאמרנו קודם, קונספט התכנות של מיני אפליקציות הוא model-view-viewmodel (MVVM). שכבת הלוגיקה ושכבת התצוגה המפורטת פועלות בשרשורים שונים, כך שממשק המשתמש לא נחסם על ידי פעולות ממושכות. במונחי אינטרנט, ניתן לחשוב על סקריפטים שרצים ב-Web Worker.

שפת הסקריפטים של WeChat נקראת WXS, SJS של Alipay, וגם SJS של Alipay. ב-Baidu מדברים על JS כשמתייחסים אליהם. צריך לכלול את הסקריפטים האלה באמצעות סוג מיוחד של תג, לדוגמה, <wxs> ב-WeChat. לעומת זאת, באפליקציה המהירה נעשה שימוש בתגי <script> רגילים ובתחביר JS של ES6.

<wxs module="m1">
  var msg = "hello world";
  module.exports.message = msg;
</wxs>

<view>{{m1.message}}</view>

אפשר גם לטעון מודולים באמצעות מאפיין src או לייבא אותם דרך require().

// /pages/tools.wxs
var foo = "'hello world' from tools.wxs";
var bar = function (d) {
  return d;
};
module.exports = {
  FOO: foo,
  bar: bar,
};
module.exports.msg = "some msg";
<!-- page/index/index.wxml -->
<wxs src="./../tools.wxs" module="tools" />
<view>{{tools.msg}}</view>
<view>{{tools.bar(tools.FOO)}}</view>
// /pages/logic.wxs
var tools = require("./tools.wxs");

console.log(tools.FOO);
console.log(tools.bar("logic.wxs"));
console.log(tools.msg);

ממשק API של JavaScript Bridge

גשר JavaScript שמחבר את המיני אפליקציות למערכת ההפעלה מאפשר להשתמש ביכולות של מערכת ההפעלה (ראו גישה לתכונות מתקדמות. יש בו גם כמה שיטות נוחות. סקירה כללית זמינה בממשקי ה-API השונים של WeChat, Alipay, Baidu, ByteDance ו-Quick App.

זיהוי התכונות הוא פשוט וקל, כי כל הפלטפורמות מספקות שיטה canIUse() (שהיא נקראת כך) שנראה שהשם שלה הוא בהשראת האתר caniuse.com. לדוגמה, התג tt.canIUse() של ByteDance מאפשר בדיקות תמיכה בממשקי API, בשיטות, בפרמטרים, באפשרויות, ברכיבים ובמאפיינים.

// Testing if the `<swiper>` component is supported.
tt.canIUse("swiper");
// Testing if a particular field is supported.
tt.canIUse("request.success.data");

עדכונים

למיני-אפליקציות אין מנגנון עדכון סטנדרטי (דיון לגבי תקן אפשרי). לכל הפלטפורמות של מיני אפליקציות יש מערכת קצה עורפי, שמאפשרת למפתחי אפליקציות מיני להעלות גרסאות חדשות של המיני אפליקציות שלהם. לאחר מכן, אפליקציית-על משתמשת במערכת הקצה העורפי הזו כדי לחפש ולהוריד עדכונים. חלק מאפליקציות-העל מבצעות עדכונים מלאים ברקע, ללא כל השפעה של מיני האפליקציה עצמה על תהליך העדכון. אפליקציות-על אחרות נותנות שליטה רבה יותר למיני-אפליקציות עצמן.

כדוגמה לתהליך מתוחכם, בפסקאות הבאות מתואר מנגנון העדכון של WeChat למיני אפליקציות בפירוט רב יותר. WeChat בודק אם יש עדכונים זמינים בשני התרחישים הבאים:

  1. כל עוד WeChat פועל, אנחנו בודקים באופן קבוע אם יש עדכונים של מיני אפליקציות קטנות שהיו בשימוש לאחרונה. אם נמצא עדכון, מתבצעת הורדה של העדכון והחלתו באופן סינכרוני בפעם הבאה שהמשתמש מפעיל את אפליקציית המיני במצב התחלתי. הפעלה במצב התחלתי (cold start) של אפליקציות מיני מתרחשת גם אם אפליקציית המיני לא פעלה באותו רגע כשהמשתמש פתח אותה (אנחנו ב-WeChat סוגרים ידנית אפליקציות מיני אחרי שהאפליקציה הייתה ברקע במשך 5 דקות).
  2. WeChat בודק גם אם יש עדכונים כשמיני אפליקציה מופעלת. במיני אפליקציות שהמשתמש לא פתח במשך זמן רב, מתבצע חיפוש של העדכון והורדה שלו באופן סינכרוני. במהלך ההורדה של העדכון, המשתמש יצטרך להמתין. כשההורדה תסתיים, העדכון ייכנס לתוקף והמיני-אפליקציה תיפתח. אם ההורדה נכשלת, למשל בגלל בעיה בחיבור לרשת, המיני-אפליקציה תיפתח ללא קשר. במיני אפליקציות שהמשתמש פתח לאחרונה, כל עדכון פוטנציאלי מורד באופן אסינכרוני ברקע, והוא יחול בפעם הבאה שהמשתמש יפעיל את המיני אפליקציה.

מיני אפליקציות יכולות להצטרף לעדכונים מוקדמים יותר באמצעות UpdateManager API. היא מספקת את הפונקציונליות הבאה:

  • הצגת התראה לאפליקציה המוקטנת כשמבוצעת בדיקה אם יש עדכונים. (onCheckForUpdate)
  • מודיעה לאפליקציה המוקטנת כאשר יש עדכון זמין להורדה. (onUpdateReady)
  • מודיעה לאפליקציה המוקטנת כאשר לא ניתן להוריד עדכון. (onUpdateFailed)
  • ההרשאה הזו מאפשרת לאפליקציה המינית להתקין לפי הגדרת האדמין עדכון זמין. העדכון הזה יפעיל מחדש את האפליקציה. (applyUpdate)

פלטפורמת WeChat מספקת גם אפשרויות נוספות להתאמה אישית של עדכונים למפתחי מיני אפליקציות במערכת הקצה העורפי שלה: 1. אפשרות אחת מאפשרת למפתחים לבטל את ההסכמה לעדכונים סינכרוניים למשתמשים שכבר התקינו את גרסת המיני של האפליקציה המינימלית, ובמקום זאת מאלצת את העדכונים להיות אסינכרוניים. 2. אפשרות אחרת מאפשרת למפתחים להגדיר גרסה מינימלית נדרשת של גרסת המיני-אפליקציה שלהם. הפעולה הזו תגרום לעדכונים אסינכרוניים מגרסה נמוכה יותר מהגרסה המינימלית הנדרשת, ולאחר מכן היא תטען מחדש בכוח את אפליקציית המיני אחרי החלת העדכון. היא גם תחסום את פתיחת גרסה ישנה יותר של המיני אפליקציה אם הורדת העדכון תיכשל.

אישורים

המאמר הזה נכתב על ידי Joe Medley, Kayce Basques, Milica Mihajlija, אלן קנט וקיית' גו.