บทความนี้ มีความ Geek พอประมาณ เหมาะกับคนที่เริ่มศึกษา และคร่ำหวอดอยู่ในแวดวง Angular นะครับ ถ้าท่านอยากเสพความ Geek พอหอมปากหอมคอ อันเชิญได้เลยฮะ
หลังจากที่เริ่มโยนตัวเอง เข้าไปสู่ Dev สายโหด ผมก็อยากท้าทายตัวเองบ้าง โดยเริ่มจากสิ่งที่คิดว่าง่ายๆ ก่อน เช่น อัพเดทเวอร์ชันของ Front-end Framework ของเว็บแอปพลิเคชัน ที่ตัวเองดูแลอยู่
ตอนนี้เว็บแอปพลิเคชันที่ผมกำลังดูแลอยู่ ดำรงอยู่มาถึงเวอร์ชั่น 7 แล้วฮะ ซึ่งได้รับอุปการคุณจาก น้องบิ๊กกี้ อดีตพนักงานคนเก่ง ที่ช่วยทำให้เว็บแอปพลิเคชันของบริษัทเรา สดใหม่อยู่ตลอดเวลา
และแล้ววันนี้ ก็มาถึง
เมื่อผมอยากอัพเดทเวอร์ชั่นให้มันเป็น Angular 8
สิ่งแรกที่ต้องเริ่มลงมือก่อน นั่นก็คืออ่าน Guideline ของ Angular ก่อนครับ ว่าเราต้องเตรียมตัว เตรียมใจอะไรบ้าง
ปอลิง ….
- จากภาพ ผมเลือกความซับซ้อนของเว็บแอป เป็น Advanced เลยครับ เพราะมันค่อนข้าง ใหญ่และซับซ้อนในระดับหนึ่ง
กดตุ่ม Show me how to update! เลยฮะ
จากนั้น พรึ๊งงงงงงงงงงงงงง
เราจะพบกับ คำแนะนำดีๆ สำหรับการเปลี่ยนผ่านจาก Angular 7.2 เป็น Angular 8.0
ดูเหมือนง่าย แค่ทำไปตามขั้นตอน อันไหนทำแล้ว ก็ติ๊กถูกไว้ เตือนใจตัวเอง
…..
พอเริ่มลงมือทำล่ะเอ็งเอ๊ยยยยยยยยยย
ยืนงงในดง Code กันเลยทีเดียว
ผมขอยกเคสหลักๆ ที่ผมเจอ พร้อมกับวิธีแก้ ดังนี้เลยครับ
เปิด terminal มาเลยจ่ะ
ใช้คำสั่ง ng update @angular/cli @angular/core
จากนั้น ดูก่อนว่า มีอะไรบ้างที่ Incompatible กัน ก็ค่อยๆ ไล่แก้ ไล่จัดการไปครับ
พอเริ่มแก้เรื่องความเข้ากันได้จบแล้ว ไปต่อที่เรื่องของ Coding กันต่อเลยครับ
- เลิกใช้ rxjs-compat ทั้ง Project เลยครับ
วิธีการตามเก็บตามเช็ดแบบง่าย ๆ ก็คือ ลบ “rxjs-compat” ออกจาก package.json เลยครับ จากนั้น npm i และ ng build โหมด production
หลังจากนั้น จะพบว่ามี error เกิดขึ้นเต็มเลย ก็ไล่แก้ไปครับ โดยให้แต่ละ Component ทำการ Import สิ่งที่ตัวเองต้องใช้จาก “rxjs” แทนการเรียกใช้จาก “rxjs-compat” - ใช้ HttpClientModule แทน HttpModule
สำหรับเคสผม ไม่มีประเด็นนี้ครับ เพราะเราเปลี่ยนมาใช้ HttpClientModule นานแล้วครับ - Style ที่เคยเขียน “/deep/” ต้องเปลี่ยนไปเป็น “::ng-deep” แทน
เคสนี้ผมเจอไม่เยอะครับ จะเจอก็แค่ ไฟล์ scss บางไฟล์ที่มีคลาสเล็กๆ เอาไว้เขียนทับ Style ของพวก Library ที่ใช้งานอยู่
แต่อย่าเพิ่งดีใจไปครับ ::ng-deep เอง ก็กำลังจะถูกทอดทิ้งในอีกไม่ช้า แต่ระหว่างนี้ Angular แนะนำให้ใช้แทน /deep/ ไปก่อนครับ - เปลี่ยนมาใช้ TypeScript 3.4
ประเด็นเรื่อง Syntax ยังไม่ค่อยเจอครับ การเขียน Code ของโปรแกรมเมอร์ในทีม ค่อนข้างสอดคล้องกับ Convention ของ Angular และมีการปรับปรุงอยู่เสมอ - ViewChild กระทบแบบ Shiftหายวายป่วงมาก
เคสนี้ ผมพบเจอว่า Project นี้ใช้ ViewChild กันแบบฟุ่มเฟือยมาก พอมาเจอการเปลี่ยนแปลงครั้งนี้ ถึงกับ Compile ไม่ผ่านกันเลยทีเดียว
Angular แนะนำให้ใส่อะไรบางอย่างเพิ่มด้วย นั่นก็คือ
จากเดิมที่เราเคยเขียนแนวๆ นี้
@ViewChild(‘foo’) foo !: ElementRef;
แต่ครั้งนี้ เราจะต้องเขียนใหม่เป็น
@ViewChild(‘foo’, {static: false}) foo !: ElementRef;
ส่วนรายละเอียดว่า ทำไมต้องกำหนด Property เพิ่ม อ่านได้จากที่นี่ครับ - ใช้ Dart Sass แทน Node Sass
อันนี้เป็นเรื่องราวดีๆ ที่ทำให้ Compile พวกไฟล์ scss ไวขึ้น สำหรับเคสผม ผมลบ node-sass ออกจาก devDependency ไปเลยครับ - การเรียกใช้งาน Document Object
เดิมที่เคยเรียกใช้งานจาก @angular/platform-browser ไม่มีแล้วนะครับ
ย้ายมาอยู่ที่ @angular/common แล้วนะครับ
ลองใช้คำสั่ง ng update @angular/cli @angular/core อีกรอบ
สิ่งแรกที่จะเห็นว่ามีการเปลี่ยนแปลงเกิดขึ้นแน่ๆ คือ Angular จะทำการเปลี่ยน Routing ให้เป็น lazy-loading แบบใหม่ เช่น
จาก loadChildren: ‘./admin/admin.module#AdminModule’
เป็น loadChildren: () => import(‘./admin/admin.module’).then(m => m.AdminModule)
เคสนี้ ผมไม่ได้รับผลกระทบอะไรครับ ผ่านข้อนี้ไปได้อย่างง่ายดาย
ยังไม่หมดแค่นี้นะครับ หนทางยังอีกยาวไกล
Code นี่แดงแล้ว แดงอีก
อะไรบ้างที่พังพินาศ แล้วต้องหาวิธีแก้ไข
- เรื่องการใช้ @HostListener(“window:scroll”) กับ onScrollEvent ใน DatePicker
สำหรับวิธีแก้ของผม คือ การแก้ไข metadata ของ ViewChild นิดหน่อยครับ ก่อนที่จะเอามันไปใช้ที่อื่นๆ
จาก
@ViewChild(BsDatepickerDirective, {static: true}) datepicker: BsDatepickerDirective;
เป็น
@ViewChild(BsDatepickerDirective, {static: false}) datepicker: BsDatepickerDirective;
- ต้อง Import BrowserAnimationsModule ใน AppModule ด้วย มิฉะนั้นแล้ว หน้าไหนที่ต้องใช้ Animation จะพังแน่นอน
- ngx-loading ใน Module ต่างๆ พังแน่นอน (ต้องอัพเดทเป็น Version ล่าสุดก่อนนะครับ เพื่อให้เข้ากันได้กับ Angular 8) จากนั้น ไล่เปลี่ยนจาก
import { LoadingModule } from “ngx-loading”;
เป็น
import { NgxLoadingModule } from “ngx-loading”;
หลังจากที่ผมปลุกปล้ำกับมันอยู่สักพัก ก็ลอง build ในโหมด production ดู ก็จะพบกับความตื่นตาตื่นใจดังนี้ครับ
ตอนที่ผมสั่ง build ผมก็สงสัยล่ะว่า ทำไมมัน build ให้สองรอบ หรือผมทำอะไรผิด ????? ผมเลยไปนั่งไล่ดูไฟล์ tsconfig.json
แล้วก็พบว่า มีบางอย่างแอบเปลี่ยนไป
ตอนนี้ถึงบางอ้อละครับ…
ค่าเริ่มต้นใน Angular 8 จะ build ไฟล์ออกมาเป็น es2015 แทน es5 ของเดิมครับ
หมายความว่า ทุกครั้งที่เราสั่ง build จะได้กลุ่มก้อนของไฟล์ build ออกมา 2 เวอร์ชั่น นั่นก็คือ es2015 และ es5
ซึ่งกระทบกับผู้ใช้งานไหม ?
กระทบแน่นอนครับ !!!!
ถ้าผู้ใช้เปิดเว็บด้วย Browser รุ่นใหม่ๆ ตอนที่มันจะพ่นของออกมาใส่หน้าจอให้ผู้ใช้เห็น มันจะไปหยิบเอา es2015 มาให้แทนครับ แต่ถ้าผู้ใช้ เปิดด้วย Browser เก่าๆ เช่น Internet Explorer 9-11 ตัว Angular เองจะไปหยิบเอา ไฟล์ build ที่เป็น es5 มาให้ใช้แทน
ถ้าลองเปรียบเทียบจากภาพด้านบน สองภาพที่ผมนำมาแปะไว้ จะเห็นได้ชัดเจนว่า ไฟล์ที่ build ให้เป็น es5 จะมีขนาดใหญ่กว่า es2015
ถ้ามีประเด็นไหนที่ผมเจอเพิ่มเติม จะมีภาค 2 ของบทความนี้ต่อแน่นอนฮะ เพราะตอนนี้ก็ กำลังไล่เช็คการทำงานของเว็บ ว่ามีอะไรชำรุด เสียหาย ไปอีกหรือเปล่า
ขอบคุณทุกคนที่ติดตามอ่านครับ