มาร์กอัปมินิแอป การจัดรูปแบบ การเขียนสคริปต์ และการอัปเดต

Markup languages

ตามที่ระบุไว้ก่อนหน้านี้ แทนที่จะเขียนด้วย HTML ธรรมดา มินิแอปจะเขียนด้วยภาษา HTML หากเคยรับมือกับการแทรกข้อความและคำสั่ง Vue.js คุณจะรู้สึกได้ทันทีที่บ้าน แต่ก็ยังมีแนวคิดที่คล้ายกันมาก่อนในการแปลง XML (XSLT) คุณดูตัวอย่างโค้ดจาก WXML ของ WeChat ได้ที่ด้านล่าง แต่แนวคิดสำหรับแพลตฟอร์มมินิแอปทั้งหมดจะมีแนวคิดเดียวกัน ได้แก่ AXML ของ Alipay, Swan Element, 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",
  },
});

เทมเพลต

เทมเพลต WXML จะใช้แบบประกาศผ่านแอตทริบิวต์ is ที่ลิงก์ไปยังคำจำกัดความของเทมเพลตได้โดยไม่ต้องมีการโคลน content ของเทมเพลต HTML

<!-- 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 โปรแกรม 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 ซึ่งระบุระยะห่างจากขอบของพิกเซลที่ปรับเปลี่ยนตามอุปกรณ์ด้วย &quot;200rpx&quot; แสดงว่าจริงๆ แล้วมีขนาด &quot;104px&quot; ในอุปกรณ์ 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;
}

เนื่องจากคอมโพเนนต์ (ดูภายหลัง) ไม่ได้ใช้ Shadow DOM สไตล์ที่ประกาศไว้ในการเข้าถึงหน้าเว็บลงในคอมโพเนนต์ทั้งหมด การจัดระเบียบไฟล์สไตล์ชีตทั่วไปคือต้องมีสไตล์ชีตรูท 1 รายการสำหรับสไตล์ส่วนกลาง และสไตล์ชีตแต่ละรายการต่อหน้าเฉพาะสำหรับแต่ละหน้าของแอปขนาดเล็ก คุณนำเข้ารูปแบบได้ด้วยกฎ @import ที่มีลักษณะการทำงานเหมือนกฎ @import ในกฎดังกล่าว เช่นเดียวกับใน HTML คุณจะประกาศสไตล์ในบรรทัดได้ ซึ่งรวมถึงการประมาณค่าในช่วงข้อความแบบไดนามิก (ดูก่อน)

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

การเขียนสคริปต์

มินิแอปรองรับ JavaScript "ชุดย่อยที่ปลอดภัย" ที่มีการรองรับโมดูลที่ใช้ไวยากรณ์ที่แตกต่างกันซึ่งจะทำให้นึกถึง CommonJS หรือ RequireJS ไม่สามารถเรียกใช้โค้ด JavaScript ผ่าน eval() และจะไม่สามารถสร้างฟังก์ชันด้วย new Function() บริบทของการเรียกใช้สคริปต์คือ V8 หรือ JavaScriptCore ในอุปกรณ์ และ V8 หรือ NW.js ในเครื่องจำลอง โดยปกติแล้ว คุณจะเขียนโค้ดด้วย ES6 หรือไวยากรณ์ที่ใหม่กว่าได้ เนื่องจากเครื่องมือสำหรับนักพัฒนาเว็บจะเปลี่ยนรูปแบบโค้ดเป็น ES5 โดยอัตโนมัติหากเป้าหมายของบิลด์เป็นระบบปฏิบัติการที่มีการติดตั้งใช้งาน WebView เวอร์ชันเก่า (ดูภายหลัง) เอกสารประกอบของผู้ให้บริการ Super App ระบุไว้อย่างชัดเจนว่าภาษาสคริปต์ของผู้ให้บริการนั้นไม่ควรสับสนและต่างจาก JavaScript อย่างไรก็ตาม ข้อความนี้มักหมายถึงวิธีการทำงานของโมดูล กล่าวคือ ยังไม่รองรับโมดูล ES มาตรฐาน

ตามที่ได้กล่าวไว้ก่อนหน้า แนวคิดการจัดโปรแกรมแอปขนาดเล็กคือ model-view-viewmodel (MVVM) เลเยอร์ตรรกะและเลเยอร์มุมมองจะทำงานบนเทรดที่ต่างกัน ซึ่งหมายความว่าอินเทอร์เฟซผู้ใช้จะไม่ถูกบล็อกโดยการดำเนินการที่ใช้เวลานาน ในแง่ของเว็บ ให้ลองนึกว่าสคริปต์ที่ทำงานใน Web Worker

ภาษาสคริปต์ของ WeChat เรียกว่า WXS, SJS ของ Alipay และ ByteDance ก็เช่นเดียวกัน SJS Baidu พูดถึง JS เมื่อพูดถึง สคริปต์เหล่านี้ต้องรวมโดยใช้แท็กชนิดพิเศษ เช่น <wxs> ใน WeChat ในทางตรงกันข้าม แอป Quick ใช้แท็ก <script> ปกติและไวยากรณ์ ES6JS

<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

บริดจ์ 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");

การอัปเดต

แอปขนาดเล็กไม่มีกลไกการอัปเดตที่เป็นมาตรฐาน (การหารือเกี่ยวกับการกำหนดมาตรฐานที่เป็นไปได้) แพลตฟอร์มมินิแอปทั้งหมดมีระบบแบ็กเอนด์ ซึ่งช่วยให้นักพัฒนาแอปมินิสามารถอัปโหลดมินิแอปเวอร์ชันใหม่ได้ จากนั้นแอปขั้นสูงจะใช้ระบบแบ็กเอนด์ดังกล่าวเพื่อตรวจหาและดาวน์โหลดการอัปเดต แอประดับสูงบางแอปอัปเดตเองทั้งหมดในเบื้องหลัง โดยไม่มีวิธีใดๆ ที่จะทำให้ตัวแอปขนาดเล็กเองส่งผลต่อขั้นตอนการอัปเดต ส่วน Super App อื่นๆ จะให้การควบคุมตัวมินิแอปได้มากกว่า

เพื่อเป็นตัวอย่างของกระบวนการที่ซับซ้อน ย่อหน้าต่อไปนี้จะอธิบายกลไกการอัปเดตของ WeChat สำหรับมินิแอปอย่างละเอียดยิ่งขึ้น WeChat จะตรวจหาการอัปเดตที่มีอยู่ใน 2 สถานการณ์ต่อไปนี้

  1. WeChat จะตรวจสอบการอัปเดตของมินิแอปที่ใช้งานล่าสุดเป็นประจำตราบใดที่ WeChat ยังทำงานอยู่ หากพบอัปเดต ระบบจะดาวน์โหลดอัปเดตและใช้พร้อมกันในครั้งถัดไปที่ผู้ใช้เปิดแอปมินิแอปตั้งแต่ต้น การเริ่มแอปขนาดเล็กแบบ Cold Start เมื่อมินิแอปไม่ได้ทำงานอยู่ในขณะที่ผู้ใช้เปิดแอป (WeChat บังคับปิดมินิแอปหลังจากทำงานในเบื้องหลังเป็นเวลา 5 นาที)
  2. นอกจากนี้ WeChat ยังตรวจสอบการอัปเดตเมื่อมินิแอปเริ่มต้นอีกด้วย สำหรับมินิแอปที่ผู้ใช้ไม่ได้เปิดเป็นเวลานาน จะมีการตรวจหาและดาวน์โหลดอัปเดตพร้อมกัน ขณะกำลังดาวน์โหลดอัปเดต ผู้ใช้ต้องรอ เมื่อดาวน์โหลดเสร็จแล้ว ระบบจะส่งการอัปเดต จากนั้นแอปขนาดเล็กจะเปิดขึ้น หากการดาวน์โหลดล้มเหลว เช่น เนื่องจากการเชื่อมต่อเครือข่ายไม่ดี มินิแอปจะเปิดขึ้นไม่ว่าในกรณีใด สำหรับมินิแอปที่ผู้ใช้เปิดเมื่อเร็วๆ นี้ ระบบจะดาวน์โหลดอัปเดตที่เป็นไปได้แบบไม่พร้อมกันในพื้นหลังและจะนำไปใช้ในครั้งถัดไปที่ผู้ใช้เริ่มต้นมินิแอปแบบ Cold

โดยมินิแอปจะเลือกรับการอัปเดตก่อนหน้านี้ได้โดยใช้ UpdateManager API โดยมีฟังก์ชันการทำงานดังต่อไปนี้

  • แจ้งเตือนมินิแอปเมื่อมีการตรวจหาการอัปเดต (onCheckForUpdate)
  • แจ้งมินิแอปเมื่อดาวน์โหลดและพร้อมให้อัปเดตแล้ว (onUpdateReady)
  • แจ้งเตือนมินิแอปเมื่อดาวน์โหลดอัปเดตไม่ได้ (onUpdateFailed)
  • อนุญาตให้แอปขนาดเล็กบังคับติดตั้งการอัปเดตที่มีอยู่ ซึ่งจะเป็นการรีสตาร์ทแอป (applyUpdate)

นอกจากนี้ WeChat ยังมีตัวเลือกการกำหนดค่าการอัปเดตเพิ่มเติมให้กับนักพัฒนาแอปขนาดเล็กในระบบแบ็กเอนด์ด้วย ดังนี้ 1. ตัวเลือกหนึ่งช่วยให้นักพัฒนาซอฟต์แวร์สามารถเลือกไม่รับการอัปเดตแบบพร้อมกันสำหรับผู้ใช้ที่ติดตั้งมินิ App เวอร์ชันขั้นต่ำแล้ว และบังคับให้อัปเดตเป็นแบบไม่พร้อมกันแทน 2. อีกตัวเลือกหนึ่งช่วยให้นักพัฒนาแอปตั้งค่าเวอร์ชันต่ำสุดของมินิแอปของตนได้ การดำเนินการนี้จะทำให้การอัปเดตแบบไม่พร้อมกันจากเวอร์ชันที่ต่ำกว่าเวอร์ชันขั้นต่ำที่กำหนดจะบังคับให้โหลดมินิแอปซ้ำหลังจากนำการอัปเดตไปใช้ และยังบล็อกการเปิดมินิแอปเวอร์ชันเก่าหากดาวน์โหลดอัปเดตไม่สำเร็จ

กิตติกรรมประกาศ

บทความนี้ได้รับการตรวจสอบโดย Joe Medley, Kayce Basques, Milica Mihajlija, Alan Kent และ Keith Gu