ทดลองทำเว็บ PWA ด้วยภาษา Kotlin โดย Android Developer ก่อนไปโชว์ที่ meet-up นะฮะ

Minseo Chayabanjonglerd
Fungjai
Published in
8 min readDec 21, 2017

ตอนแรกว่าจะลงบล็อกตัวเอง ไปๆมาๆลงในนี้ดีกว่า
เพราะ เรื่องราวซับซ้อนตั้งแต่ทีแรกเลยจ้าา ตามประสาคนทำเว็บงูๆปลาๆประมาณนึง

ชอบภาพนี้ ภาพโดยคุณเบ็บฮะ

เหตุการณ์เกิดขึ้นโดยพี่ Birth แอดมินในกรุ๊ป Thaialnd Kotlin Developer มาติดต่อให้ไปเป็น speaker งาน meetup kotlin ประมาณกลางเดือนธันวาคม เนื่องจากทางฟังใจก็มีเซอร์พร๊ายยบางอย่างกับ user เลยเร่งทำอยู่ ทำให้ไม่ได้แตะ kotlin ใน android เลย ไม่ได้แตะมานานมาก หัวข้อก็คิดไม่ออก คิดไม่ออกด้วยซํ้าว่าทำแอปไรดี เดี๋ยวให้พี่หมีสุ่ม เอ้ยยผิดๆๆๆๆ จะใช้พี่หมีทำงานอื่นนอกจากสุ่มอาหารในแชทบอทกับโอชินุ้งเฌอปรางไม่ได้นะ

ไม่รู้อะไรดลใจ หรือความขี้เกียจ เลยอ่ะ ทำ PWA ด้วย Kotlin เลยจ้า คิดว่าเว็บหน้าเดียว ทำอะไรสนุกๆซึ่งแฝงความฟังใจ คนน่าจะเล่นแหละนะ

ความฟังใจคืออะไร ดู content เอาแล้วกัน ในเรื่องของแคปชั่นของ playlist อันที่กล่าวถึงเลื่องลือในทวิตภพ content ต่างๆบนหน้าเพจ มีการสัมภาษณ์ตัวเอง ไปจนมีสาระ ให้ทุกคนได้สนุกและแฝงไปด้วยความรู้ :)

ตอนแรกเอา Kotlin wonderland ไปเล่น เอ้าติดตรงเน้ ช้านจะรอดไหมนี่

google it ยังไงก็ไม่เจอ โว้ยยยยยยยยย เลยต้องมาถามใน group นั่นแหละ

สุดท้ายเจ้าของโปรเจก คุณเบ็บ Christopher Hay-Yin Ng บอกว่าใช้ ./gradlew build แล้วเอา public folder ที่ได้ไปแปะบน Firebase Hosting เป็นอันจบ ขอบคุณมากฮะ

ความวายป่วงต่อมา เนื่องจากทีม product ของฟังใจมี give & take แล้วเราโดนคนต่อไป ย้อนเวลา timeline กันสักนิด หลังจาก give & take ช่วงเย็นวันนั้นได้รับการติดต่อเรื่อง meet-up แล้วเสาร์อาทิตย์ดันป่วยด้วย ทำไม่ทันในการ give & take ตอนที่เขียนบล็อกนั้นใช้เวลางานล้วนๆเลย สไลด์ยังไม่มีด้วย ทำได้แค่ไม่กี่หน้าเลย ฮืออ เอาเวลาตอนไหนไปซ้อมพูดซ้อมเปิดสไลด์หล่ะนี่

อะเคร เลิกบ่นๆ มาเริ่มทำกันเลยดีกว่า เราขอไอเดียจากทีมว่าทำอะไรดี ก็ยังมีเรื่องสุ่มอาหารอยู่บ้าง ตอนรอข้าวร้านตามสั่งคิดไปเรื่อยจนได้ไอเดียนึง ไปเห็นรูปนี้ใน hangout พอดี แล้วบวกความฟังใจได้ด้วย

ขอโทษที่ไม่ได้เบลอหน้านะ หนุ่มสาวชาว content กับ marketing ฮือออ รูปใครก็ลืม ไม่ได้ขออีก 555

นั่นคือ กินมาม่ากับอะไรดี ด้วยความที่มาม่านั้นถือเป็นสวัสดิการใหม่ของฟังใจด้วย 555 เลยเอามาเล่นเลยแล้วกัน คงมีคิดแหละ กลัวขาดสารอาหาร กินกับอะไรดี และมีความต่อยอดกับน้องหมีตัวแตกด้วยหน้าตาเป็นแบบนี้

responsive mobile : https://onemeal-d909a.firebaseapp.com/
desktop in chrome : https://onemeal-d909a.firebaseapp.com/

ตอนที่ไปงาน kotlin workshop ก็ได้เขียนบล็อกมาด้วย ซึ่งเรื่องเว็บอยู่ใน session สุดท้ายเลย แบบคร่าวๆ

เราเลยมาเจาะรายละเอียด โดยอ่านจากบล็อกนี้เป็น reference นิดโหน่ย

มาสร้างโปรเจกกันก่อนนน

ก่อนอื่น download IntelliJ IDEA มาก่อนนะ แล้วลง plug-in Kotlin ให้เรียบร้อย

เปิดโปรแกรมมา เลือก Create New Project

ref : https://medium.com/bcgdv-engineering/building-a-full-stack-web-app-in-kotlin-af8e8fe1f5dc

ถ้าเปิดโปรแกรมมาอยู่แล้วไปที่ File -> New -> Project… หรือในแมคก็ command + N เนอะ

จากนั้นติ๊กเพิ่มที่ Kotlin (JS) แบบในรูปนี้

ใส่ชื่อ GroupId มันก็คือ package เหมือนใน Android Studio เลย และ ArtifectId คือชื่อโปรเจกนั่นแหละ

ติ๊กถูกหมดทั้งสามอันนะ เพื่อความสะดวกของเราเอง

ใส่ชื่อโปรเจกลงไป ดู location ว่าตรงใจเรา จากนั้นกด Finish เป็นอันเสร็จ

โปรเจกสร้างเสร็จจะเป็นแบบนี้

ไปเปิด build.gradle จะเจอด้านบน กด OK เพื่อ sync gradle เลยจ้า

แต่เรามีใส่เพิ่มเล็กน้อย ตามในนี้เลย

แต่ละ moduleKind ของมันก็มีความหมายด้วยนะ

  • plain : แบบ old-school ในการทำงานกับ js โดยการใส่ <script> ใน HTML ซึ่งก็ใช้ตัวนี้กันเป็นส่วนใหญ่เนอะ
  • amd : ภาคอิโวฟของ plain โดยใช้ร่วมกันกับ require.js
  • commonjs : สำหรับทำงานร่วมกันกับ node.js อ่ะ
  • umd : “Universal Module Definition” มันเลือกให้เองว่า 3 ตัวบนจะเอาตัวไหน

ไฟล์ html จะใส่ไว้นอกสุด ชื่อ index.html นะ ใส่ <script> ไป 2 บรรทัด เพราะอะไรเดี๋ยวมาบอกกัน

ไฟล์ kotlin ใส่ไว้ใน src/main/kotlin นะ ชื่อไฟล์ main.kt แปะแบบตามตัวอย่างที่ไป kotlin workshop มาแล้วกัน

พวก resource ต่างๆ เช่น css, img อะไรพวกนี้ ไว้นอกสุดนะ

การ compile file นั้น เราใช้คำสั่ง ./gradlew build ใช่ป่ะ แล้วเบื้องหลังการทำงานหล่ะ……… ไม่มีรูปให้เราดูอย่างเป็นทางการ เอาเป็นว่ามันจะ compile kt ที่เราเขียนเป็น js และเอา folder ที่เกี่ยวข้อง ไปใส่ output folder ที่ public นั่นเอง

compile file kotlin ให้เป็น js และนำมาแปะที่ index.html ได้

และแล้วเราก็ได้ folder public ไปใส่ใน firebase hosting แล้วเย้

ผลหล่ะ เป็นเช่นไร ก็ขึ้นรูป Kotlin แบบนี้ไง จากนั้นก็ firebase deploy ก็ได้หน้าเว็บบน firebase hosting แล้วจ้า

มาละเลงโค้ดให้เป็น HTML ด้วย Kotlin กันเถอะ

เนื่องจากใช้เวลาศึกษาไปแปปนึงแล้วแบ่บบบ เออมันยากเว้ย ไปเจอวิธีนึง เป็นการเขียน kotlin แล้วมันจะแปลงเป็น html โดยเขียนโค้ดเป็น html บน kotlin นั่นแหละ งงไหม มาเริ่มกันดีกว่า

เช่น อันนี้คือเราสามารถสร้าง html ใหม่ได้เลยจาก kotlin

เราเลยแบ่งเองเป็น 2 แบบ ตามที่เราใช้ คือ

แบบแรก คือ อ้างอิง id ของ div จากหน้า html ก็คือแบบ Kotlin wonderland นั่นเอง

ข้อดี คือ จัดการลำดับตำแหน่งบนล่างได้

ข้อเสีย คือ มันใส่พวก h1 h2 p อะไรพวกนี้ไม่ได้ (ถ้าได้วานบอกนะ ไม่เกี่ยวกับแก้ css นะ)

kotlin wonderland

แบบที่สอง คือ append มันเข้าไป โดยไม่ต้องสน div บน html แต่ประการใด มันจะเพิ่มให้จากบนไปล่างเลย

และเราต้องเพิ่ม dependency ไปตัวนึง ในที่นี้เราใช้ kotlinx-html-js คือ compile 'org.jetbrains.kotlinx:kotlinx-html-js:0.6.3' และเพิ่ม script <script src=”kotlinx-html-js.js”></script> บนไฟล์ html ด้วยนะ ไม่งั้นที่เราเขียนจะไม่เห็นบนหน้าเว็บ

ข้อเสียคือ วางตำแหน่งตรงแสดงผลหลังการสุ่มยาก และ ผลสุ่มมีปัญหา คือมันอยู่ล่าง link facebook แล้วทุกครั้งที่กด มันจะเพิ่ม item ด้านล่างขึ้นเรื่อยๆด้วย อาจจะมีการสลับ order ในหน้า HTML

ดังนั้น เราใช้ทั้งสองแบบในการทำ โดยตรง header information ต่างๆจะใช้แบบที่สอง ส่วนผลการสุ่มแบบใช้แบบแรก และส่วน link social ใช้เป็น HTML แปะปกติ เพื่อให้แสดงผลได้สวยงามตามใจเรา บอกตรงๆเรายังไม่ค่อยคล่องมาก

ส่วน css ก็แปะตาม html ปกติ เพียงแต่ใน kotlin ก็ระบุ id ก็แค่นั้นเลย เราแยกสองไฟล์ระหว่างอันหลัก กับปุ่ม social ทั้งหลาย (ตอนแรกใส่ page ของหมีไปแล้ว และเพิ่ม github ไปทีหลัง)

สุดท้ายทั้งหมดทั้งมวล เป็นแบบนี้

ร่ายวิชา PWA กันในเว็บของเรา

คอนเซปของ PWA นั้น คือต้องการให้เว็บเหมือน Native App ตัวนึง เนื่องจากเดี๋ยวนี้คนไม่ค่อยโหลดแอปใหม่กันแล้ว เลยใช้วิธีนี้เพื่อ hold user ให้ใช้งานเราอยู่ ทำให้มีขนาดโดยรวมไม่ใหญ่มากจนเกินไป แต่บางอย่างก็ไม่สามารถทำ PWA ได้นะ เช่น เกมส์ RoV เป็นต้น

PWA คือ Progressive web app นั่นคือเป็น web app ที่หน้าตาเหมือน native app นั่นเอง
- สามารถรองรับการแสดงผลแบบ responsive ได้
- สามารถ add to home screen พร้อมโลโก้ของเว็บแอปเหมือนแอปในมือถือเลย โดยไป setting ที่ manifest.json
- สามารถแสดงผลแบบ offline โดยเก็บ cache เพื่อดึงมาแสดงผลได้รวดเร็วขึ้น โดยไปสร้าง js มีไฟล์นึง ที่เป็น service worker

ถ้าเราอยากรู้ว่าเว็บไหนเป็น PWA ในเว็บนี้มีรวบรวมไว้ให้

ทาง Google มี codelab ด้วย เผื่อใครยังไม่เคยลองทำเนอะ

องค์ประกอบ PWA มี 3 อย่าง เราจะมาเจาะทีละอย่างกัน แต่ใช้ไม่ครบทุกอย่างนะ

  1. Manifest เรียกง่ายๆก็เปรียบเสมือน manifest ของ android คือต้องสร้าง icon เหมือนกัน ใส่ธีมสีเหมือนกัน และ กำหนดหน้าแรกเหมือนกัน

สิ่งที่ต้องเตรียม คือ การทำโลโก้ของเว็บเรา ซึ่งมันจะเป็นไอคอนแสดงบนหน้าจอมือถือเหมือนแอปเลย ขนาดเป็นดังนี้

และสร้างไฟล์ manifest.json ไว้ที่เดียวกับ index.html แบบนี้

สรุปแบบรวบรัด

  • Name คือชื่อเว็บของเรา
  • short_name คือเหมือนที่เราสร้างแอปแอนดรอยด์ ที่เราใส่ชื่อแอป ซึ่งมันจำกัดให้ใส่ได้แค่ 12 ตัวอักษร
  • icons อันที่เรากล่างถึงเมื่อกี้
  • start_url อยากให้เปิดเจออันไหนเป็นหน้าแรก ส่วนใหญ่ก็ index.html แหละ
  • display อันนี้ไม่รู้แฮะ
  • background_color พื้นหลังตอน launch screen ก่อนเข้า index.html เป็นสีอะไร
  • theme_color ธีมสีของแอป เอ้ยย เว็บของเรา เหมือนธีมสีในแอปจริงๆ

ใส่เพิ่มใน index.html ในส่วน head แต่ถ้าใครใช้ safari ของ iOS มันไม่ได้รองรับเต็มตัว เลยต้องใส่โค้ดเหล่านี้เพิ่มลงไปด้วย

เมื่อใส่เสร็จ ลอง inspect ไปดู ถ้าทำถูกตรงครบถ้วนจะเป็นดังนี้

อัดคลิปให้ดูเลยว่ามือถือแอนดรอยด์กับไอแพด จะเป็นยังไง

2. Service Worker เป็นส่วนการทำงาน ที่ทำให้เว็บเราสามารถ offline ได้

เนื่องจากภาษา Kotlin เอง สามารถทำงานร่วมกันกับ JAVA ใน Android ฉันใด
มันก็ทำงานกับ js ในเว็บได้ ฉันนั้น

ดังนั้น เราสร้าง service-worker.js ไว้ชั้นเดียวกับ index.html นะ จริงๆเราทำเป็น kotlin ได้ แต่เวลาที่มีมันไม่ทันเนอะ

  • อันที่เป็น name ก็ใส่ชื่อไป อาจจะเหมือนหรือต่างก็ไม่มีผล นอกจากชื่อไม่เหมือนกันเนอะ
  • filesToCache ใส่ไฟล์ที่เราต้องการจะทำ cache ในความเป็นจริงไม่ต้องใส่ทั้งหมดนะ แล้วแต่เราเลย อาจจะใส่แค่ css กับปุ่มเหมือน twitter lite ก็ได้นะ ผลคืออย่าให้เห็นพี่ไดโนเสาร์วิ่งเล่นได้ตอน offline ก็พอหล่ะ
  • เพิ่ม event ของ service worker ลงไป

ถ้าอ่านแล้วมาเอา build เกิดอะไรขึ้นบ้างน๊าาาาาา PWA จะมาไหมเอ่ย ติ๊กต๊อกๆๆๆๆๆๆ………… สรุป build ผ่าน แต่ PWA ไม่มา ตั้งแต่ข้อแรกแล้วเนอะ

ดังนั้นเรามาเพิ่มสองไฟล์นี้ที่ build.gradle ใส่เพิ่มหลังจาก index.html

from new File("manifest.json")
into "{projectDir}/public"
from new File("service-worker.js")
into "{projectDir}/public"

และใส่เพิ่มใน index.html เพื่อเรียก service-worker ขึ้นมาทำงาน

ถ้าทำถูกต้องจะได้แบบนี้

แต่มีความเซอร์พร๊ายยอ่ะ เห็นด้านบนป่ะ ลองมือบอนไปกด กลายเป็นลงแอปใน Chrome เลยจ้าาา งงไหม เรางง 555

ซึ่งกดไปแล้ว ก็เข้าหน้าเว็บของเรานั่นแหละ

3. Notification ส่วนของการแจ้งเตือน เว็บปกติจะแจ้งเตือนไม่ได้ถูกม่ะ แต่ในแอปทำได้ เนื่องด้วย concept ที่ต้องการให้เว็บคล้ายๆ Native app ดังนั้น PWA จึงมี Notification ขึ้นมา ซึ่งเราไม่ได้ใส่ เพราะในตอนนี้ไม่รู้ใส่ไปทำไมอ่ะ แล้ววุ่นวายด้วยไง ต้องมานั่นโน้นนี่ ตัดจบเลยแล้วกันสำหรับ Noti เนอะๆ

มีเครื่องมือทดสอบระหว่างทำด้วยนะ

คู่มือที่ต้องมีติดตัวสำหรับ front-end/web developer นั่นก็คือ 200 OK จ้า เป็น extendion ที่อยู่ใน chrome เพื่อดูว่าถ้าเว็บเรามี response code เป็น 200 คือไม่มี internet มันจะใช้ได้ไหม

หน้าตาจะเป็นแบบนี้

ความสามารถหลักๆ ทำให้เป็น response code 200 แล้วหน้าเว็บไม่พังได้ แชร์เว็บได้ในวงเดียวกัน วงอะไร วง network เดียวกันไง แบบให้ทีมเข้าไปดูได้งี้

แต่เราไปทำใน inspect แทน คือ จิ้ม offline นั่นแหละ ง่ายดี

วงใหญ่ๆเอาชัดๆ แลกมาด้วยพื้นที่สีขาวด้านบน

เมื่อใส่ครบหมดแล้ว มา audit กันดีกว่า

ใช้ lighthouse ในการ check score ว่าเว็บเราได้กี่คะแนน

เรา inspect มัน ไปที่แถบ Audit กดปุ่มสีฟ้า แล้วไปกันเลยโซนิคค

https://onemeal-d909a.firebaseapp.com/

มันจะตรวจให้ 4 หัวข้อใหญ่ดังนี้

จากนั้นรอแปปนึง หน้าเว็บเรามีหน้าเดียว ไม่ได้ใหญ่โตอะไร ผลออกมาเป็นดังนี้

อันนี้แก้หลายๆอย่างไปแล้ว คะแนนก็เลยดี

อีกตัวที่เราแนะนำ คือ

เอาไว้ดู performance เว็บเรา ว่าจะแก้อย่างไร ให้โหลดหน้าเว็บได้ไวขึ้น เช่น ลดขนาดรูป อะไรงี้

ให้เขาส่งเมลล์ผลไปให้ แทบไม่ต้องแก้อะไรเลยอ่ะ เพราะมีแค่นี้ไง -..-

สุดท้าย ทดสอบก่อนวันงาน

เราอยากให้เล่นได้ด้วย และ UX ดีด้วย คนจะได้มาเล่นกันเราเยอะๆ เลยกระจายไปตามกลุ่มต่างๆให้ลองเล่นกันก่อน

ผลจะประมาณนี้แหละ ให้น้องหมีทำนายกัน รูปก็มาจากโน้นนี่ พี่กูทั้งนั้น T__T

สิ่งที่ปรับคือขนาดรูป ใหญ่เกินจอมือถือไปอีกกก กับขนาดปุ่มที่ดันสั้นไป

อันนี้ความกว้างรูปเกินจอไปแระ

มางาน meetup ในวันที่ 13 ธันวาคม ที่ DTAC HOUSE

ก่อนอื่นก็ต้องทำบล็อกนี้เพื่อเรียบเรียงข้อมูล ทำสไลด์ และซ้อมพรีเซนต์

แบนเนอร์อันสวยงามของงานฮะ

ก็เป็นงานแรกที่เราได้เป็น speaker นะ แล้วโค้ดเราก็ไม่ได้สวยงามมาก วิธีก็ไม่ได้ดีมากด้วย เหมือนเราได้มาลองทำอะไรใหม่ๆมากกว่า

เริ่มเปิดงานแล้วจ้าาาา

หลังจากเปิดงานด้วยทางสปอนเซอร์ DTAC ก็เริ่ม session แรก เรื่อง Kotlin Reflection โดยพี่ต้า speaker จาก Ampos ค่ะ

อันนี้พี่เขาอธิบายเกี่ยวกับการใช้ reflection ใน kotlin มีการ live code ให้ดูกันด้วย เราอาจจะไม่ค่อยเห็นท่านี้ในโค้ดที่เราใช้จริงๆเท่าไหร่นัก

ขาตั้งไมค์รุ่นใหม่ สั่งงานด้วยเสียง เอ้ยยย ผิดๆๆ

ถ้าใครอยากศึกษา Reflection เพิ่มเติมก็จะมี document ของ Kotlin ให้อ่านนะจ๊ะ

https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.reflect/index.htm

l

จากนั้นมีเบรก ของเราคือรีบไปกินเบอร์เกอร์ก่อนเลย หิวมาก ก่อนเปิดงานมีการ set อุปกรณ์วุ่นวายอยู่ เลยต้องเข้าไปดูด้วย แหะๆ อาหารงานนี้จัดเต็มแบบเบาๆในมื้อเย็น ที่ใครหลายคนกินแล้วก็นอน ;P

หลังจากกินข้าวเย็นเสร็จก็รีบไป set จอ เตรียมพร้อมพรีเซนต์ บอกเลยว่า…………ตื่นเต้นน้อยกว่าตอนซ้อมพรีเซนต์ในทีมซะอีก งงม่ะ 555 การพรีเซนต์ก็เป็นไปได้อย่างราบรื่น มีมุขที่ฮาบ้าง ไม่ฮาบ้าง สลับกันไป ขอบคุณที่คนที่มาดูจบจนงานน๊าาา ขอบคุณที่หลายๆคนชอบ session ของเรา :)

บางคนอาจจะอยากฟังย้อนหลัง เพจกูโค้ดได้ไลฟ์งานนี้ด้วยน๊าาา มาถึงงานสักพักพี่ปอนด์ก็มา set ระบบอะไรพวกนี้ ถ้าใครอยาก support อะไรพี่เขาก็ติดต่อที่เพจได้เลยจ้าา

สุดท้าย ฝากร้านขายของกันนิดนุงงงงง

อันนี้สไลด์ ก็ไม่ต่างจากที่พูดเท่าไหร่มั้ง

เผื่อใครสนใจจะลองดู ยอมรับว่าโค้ดไม่สวยเท่าไหร่เลย แง

ถ้าสวยๆเราชอบไปดูที่อันนี้ เป็นหน้าเว็บของ ThaiKotlinWeb ซึ่งเป็น kotlin ทั้งเว็บ ถือเป็นตัวอย่างที่ดีค่ะ

และลองไปเล่นน้องหมีสุ่มมาม่าได้ที่

#พื้นที่โฆษณา กด like เพจหนูด้วยน๊าาา

https://www.facebook.com/MikkiPastel

สุดท้ายขอบคุณทีมงาน Thailand Kotlin Developer สำหรับการจัดงานในครั้งนี้ ดูแลเราเป็นอย่างดีเลย ได้คุยกันบ้างกับหลายๆท่านในวันงาน
ขอบคุณเพจ กูโค้ด ที่ไลฟ์สดในงานครั้งนี้ พี่ปอนด์คุยสนุกดี 555 ใครอยากสปอนเซอร์ทีมกูโค้ดติดต่อหลังไมค์ได้นะ
และสปอนเซอร์หลักในวันงาน Dtac House สำหรับงานวันนั้น

และที่สำคัญที่สุด คนที่มากดบัตรมาฟังเราสดในงาน รวมถึงคนที่ดูไลฟ์อยู่ที่บ้าน คนที่ดูไลฟ์ย้อนหลังด้วยนะคะ ขอบคุณมากนะคะ //รับมง เอ้ยย ใช่หรอ? หมายถึงรับคุมะมง… ท่าทางแอร์จะดังนะ ;P

--

--

Minseo Chayabanjonglerd
Fungjai

Android Developer | Content Creator AKA. MikkiPastel | Web2 & Web3 Contributor