ทดลองทำเว็บ PWA ด้วยภาษา Kotlin โดย Android Developer ก่อนไปโชว์ที่ meet-up นะฮะ
ตอนแรกว่าจะลงบล็อกตัวเอง ไปๆมาๆลงในนี้ดีกว่า
เพราะ เรื่องราวซับซ้อนตั้งแต่ทีแรกเลยจ้าา ตามประสาคนทำเว็บงูๆปลาๆประมาณนึง
เหตุการณ์เกิดขึ้นโดยพี่ 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 พอดี แล้วบวกความฟังใจได้ด้วย
นั่นคือ กินมาม่ากับอะไรดี ด้วยความที่มาม่านั้นถือเป็นสวัสดิการใหม่ของฟังใจด้วย 555 เลยเอามาเล่นเลยแล้วกัน คงมีคิดแหละ กลัวขาดสารอาหาร กินกับอะไรดี และมีความต่อยอดกับน้องหมีตัวแตกด้วยหน้าตาเป็นแบบนี้
ตอนที่ไปงาน kotlin workshop ก็ได้เขียนบล็อกมาด้วย ซึ่งเรื่องเว็บอยู่ใน session สุดท้ายเลย แบบคร่าวๆ
เราเลยมาเจาะรายละเอียด โดยอ่านจากบล็อกนี้เป็น reference นิดโหน่ย
มาสร้างโปรเจกกันก่อนนน
ก่อนอื่น download IntelliJ IDEA มาก่อนนะ แล้วลง plug-in Kotlin ให้เรียบร้อย
เปิดโปรแกรมมา เลือก Create New Project
ถ้าเปิดโปรแกรมมาอยู่แล้วไปที่ 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.jscommonjs
: สำหรับทำงานร่วมกันกับ node.js อ่ะumd
: “Universal Module Definition” มันเลือกให้เองว่า 3 ตัวบนจะเอาตัวไหน
Compiling Kotlin to Javascript
ไฟล์ 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 นั่นเอง
และแล้วเราก็ได้ folder public ไปใส่ใน firebase hosting แล้วเย้
ผลหล่ะ เป็นเช่นไร ก็ขึ้นรูป Kotlin แบบนี้ไง จากนั้นก็ firebase deploy
ก็ได้หน้าเว็บบน firebase hosting แล้วจ้า
มาละเลงโค้ดให้เป็น HTML ด้วย Kotlin กันเถอะ
เนื่องจากใช้เวลาศึกษาไปแปปนึงแล้วแบ่บบบ เออมันยากเว้ย ไปเจอวิธีนึง เป็นการเขียน kotlin แล้วมันจะแปลงเป็น html โดยเขียนโค้ดเป็น html บน kotlin นั่นแหละ งงไหม มาเริ่มกันดีกว่า
เช่น อันนี้คือเราสามารถสร้าง html ใหม่ได้เลยจาก kotlin
https://kotlinlang.org/docs/reference/type-safe-builders.html
เราเลยแบ่งเองเป็น 2 แบบ ตามที่เราใช้ คือ
แบบแรก คือ อ้างอิง id ของ div จากหน้า html ก็คือแบบ Kotlin wonderland นั่นเอง
ข้อดี คือ จัดการลำดับตำแหน่งบนล่างได้
ข้อเสีย คือ มันใส่พวก h1 h2 p อะไรพวกนี้ไม่ได้ (ถ้าได้วานบอกนะ ไม่เกี่ยวกับแก้ css นะ)
แบบที่สอง คือ 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 ด้วย เผื่อใครยังไม่เคยลองทำเนอะ
Your First Progressive Web App
องค์ประกอบ PWA มี 3 อย่าง เราจะมาเจาะทีละอย่างกัน แต่ใช้ไม่ครบทุกอย่างนะ
- 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 เดียวกันไง แบบให้ทีมเข้าไปดูได้งี้
Your First Progressive Web App | Web Fundamentals | Google Developers
แต่เราไปทำใน inspect แทน คือ จิ้ม offline นั่นแหละ ง่ายดี
เมื่อใส่ครบหมดแล้ว มา audit กันดีกว่า
ใช้ lighthouse ในการ check score ว่าเว็บเราได้กี่คะแนน
เรา inspect มัน ไปที่แถบ Audit กดปุ่มสีฟ้า แล้วไปกันเลยโซนิคค
มันจะตรวจให้ 4 หัวข้อใหญ่ดังนี้
จากนั้นรอแปปนึง หน้าเว็บเรามีหน้าเดียว ไม่ได้ใหญ่โตอะไร ผลออกมาเป็นดังนี้
อีกตัวที่เราแนะนำ คือ
เอาไว้ดู performance เว็บเรา ว่าจะแก้อย่างไร ให้โหลดหน้าเว็บได้ไวขึ้น เช่น ลดขนาดรูป อะไรงี้
ให้เขาส่งเมลล์ผลไปให้ แทบไม่ต้องแก้อะไรเลยอ่ะ เพราะมีแค่นี้ไง -..-
สุดท้าย ทดสอบก่อนวันงาน
เราอยากให้เล่นได้ด้วย และ UX ดีด้วย คนจะได้มาเล่นกันเราเยอะๆ เลยกระจายไปตามกลุ่มต่างๆให้ลองเล่นกันก่อน
สิ่งที่ปรับคือขนาดรูป ใหญ่เกินจอมือถือไปอีกกก กับขนาดปุ่มที่ดันสั้นไป
มางาน 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.html
จากนั้นมีเบรก ของเราคือรีบไปกินเบอร์เกอร์ก่อนเลย หิวมาก ก่อนเปิดงานมีการ set อุปกรณ์วุ่นวายอยู่ เลยต้องเข้าไปดูด้วย แหะๆ อาหารงานนี้จัดเต็มแบบเบาๆในมื้อเย็น ที่ใครหลายคนกินแล้วก็นอน ;P
หลังจากกินข้าวเย็นเสร็จก็รีบไป set จอ เตรียมพร้อมพรีเซนต์ บอกเลยว่า…………ตื่นเต้นน้อยกว่าตอนซ้อมพรีเซนต์ในทีมซะอีก งงม่ะ 555 การพรีเซนต์ก็เป็นไปได้อย่างราบรื่น มีมุขที่ฮาบ้าง ไม่ฮาบ้าง สลับกันไป ขอบคุณที่คนที่มาดูจบจนงานน๊าาา ขอบคุณที่หลายๆคนชอบ session ของเรา :)
บางคนอาจจะอยากฟังย้อนหลัง เพจกูโค้ดได้ไลฟ์งานนี้ด้วยน๊าาา มาถึงงานสักพักพี่ปอนด์ก็มา set ระบบอะไรพวกนี้ ถ้าใครอยาก support อะไรพี่เขาก็ติดต่อที่เพจได้เลยจ้าา
สุดท้าย ฝากร้านขายของกันนิดนุงงงงง
อันนี้สไลด์ ก็ไม่ต่างจากที่พูดเท่าไหร่มั้ง
เผื่อใครสนใจจะลองดู ยอมรับว่าโค้ดไม่สวยเท่าไหร่เลย แง
ถ้าสวยๆเราชอบไปดูที่อันนี้ เป็นหน้าเว็บของ ThaiKotlinWeb ซึ่งเป็น kotlin ทั้งเว็บ ถือเป็นตัวอย่างที่ดีค่ะ
และลองไปเล่นน้องหมีสุ่มมาม่าได้ที่
#พื้นที่โฆษณา กด like เพจหนูด้วยน๊าาา
สุดท้ายขอบคุณทีมงาน Thailand Kotlin Developer สำหรับการจัดงานในครั้งนี้ ดูแลเราเป็นอย่างดีเลย ได้คุยกันบ้างกับหลายๆท่านในวันงาน
ขอบคุณเพจ กูโค้ด ที่ไลฟ์สดในงานครั้งนี้ พี่ปอนด์คุยสนุกดี 555 ใครอยากสปอนเซอร์ทีมกูโค้ดติดต่อหลังไมค์ได้นะ
และสปอนเซอร์หลักในวันงาน Dtac House สำหรับงานวันนั้น
และที่สำคัญที่สุด คนที่มากดบัตรมาฟังเราสดในงาน รวมถึงคนที่ดูไลฟ์อยู่ที่บ้าน คนที่ดูไลฟ์ย้อนหลังด้วยนะคะ ขอบคุณมากนะคะ //รับมง เอ้ยย ใช่หรอ? หมายถึงรับคุมะมง… ท่าทางแอร์จะดังนะ ;P