CSS và Tối ưu Image, Font, Script trong NextJS

Trước khi đi vào chủ đề chính chúng ta sẽ tìm hiểu khái quát về Web Vitals.

Web vitals là một sáng kiến của Google cung cấp các chỉ số và hướng dẫn thống nhất để đo lường trải nghiệm người dùng trên website.

Core web vitals là một phần trong web vitals gồm 3 số liệu chính về loading, interactivity và visual stability: LCP (largest contentful paint), FID (fisrt input delay) và CLS (cumulative layout shift)

Để website có trải nghiệm tốt và có xếp hạng cao trên Google bạn cần có kết quả tốt cho 3 chỉ số trên.

LCP:

LCP đo lường thời gian mà phần tử lớn nhất trên viewport được load xong. Nó có thể là text, video hoặc image chiếm đa số viewport. Thời gian này sẽ được tính từ thời điểm bắt đầu load trang cho đến khi người dùng có thể nhìn thấy nó trên màn hình.

Tương tự với LCP, chúng ta có khái nhiệm về FCP(first contentful paint) sẽ đo lường thời gian phần từ đầu tiên được render lên màn hình.

FID:

FID là nhận thức của người dùng trong khi tương tác với web page, thông số này không thể đo lường thông qua kĩ thuật mà phải đo bằng trải nghiệm của người dùng thật (ví dụ như khi người dùng ấn vào 1 text-box hoặc 1 button bị delay hoặc không có hiện tượng gì xảy ra)

CLS:

CLS đo lường độ ổn định về layout của website. CLS xảy ra khi một element bị dịch chuyển sau khi DOM đã được render và ảnh hưởng đến các element khác. Điểm số dịch chuyển của mỗi phần tử được tính vào CLS nếu nó có những dịch chuyển không mong muốn. Một phaafn tử được thêm mới hoặc thay đổi kích thước sẽ không tính vào CLS nếu những phần tử đã load vẫn duy trì vị trí của chúng.

Bây giờ chúng ta sẽ bắt đầu vào chủ đề chính.

CSS trong NextJS

Trong NextJS cung cấp cho chúng ta 2 scope của CSS là Global CSSComponent CSS.

Global CSS:

Để add 1 stylesheet là một global css chúng ta sẽ import file đó vào trong pages\_app.tsx:

Ở đây, chúng ta đã import file global.css vào trong _app.ts, global css thường được để trong thư mục styles. Global css sẽ ảnh hưởng lên tất cả các page và component trong app. Để tranh conflict css chúng ta sẽ chỉ import global css trong _app.tsx.

NextJS cũng hỗ trợ import css của bên thứ 3 thông qua node_modules cả ở page và component.

Sau khi build NextJS app, tất cả các global css sẽ được gộp thành 1 file.

Component CSS:

Để tạo một component css trong NextJS, chúng ta sẽ tạo các module có tên trùng với file tsx, ví dụ như blog.tsx và blog.module.css. NextJS sẽ tự động map tsx và css theo tên file để tạo component css. Tất cả các class trong component là duy nhất và sẽ không bị conflict bởi các css của component khác.

Sau khi build NextJS app, các component css sẽ được minimal thành nhiều file đọc lập.

Inline CSS:

Có hai cách đơn giản để viết inline css trong NextJS:

Đây là các đơn giản và hay được dùng nhiều nhất

Chúng ta cũng có thể viết inline css theo styled-jsx

Cách viết này không phổ biết và khó đọc

Sass:

NextJs cũng hỗ trợ Sass và Scss, nó có thể dùng css bình thường. Để sử dụng chúng trong app chúng ta cần cài thêm module sass:

npm install sass

Image trong NextJS

NextJS cung cấp component trong 'next/image' để giải quyết những vấn đề về optimization image:

  • Cải thiện vấn đề về performance: Luôn cung cấp đúng size ảnh cho từng thiết bị
  • Ổn định layout website
  • Load page nhanh hơn: Hình ảnh chỉ được tải khi nó nằm trong viewport
  • Thay đổi hình ảnh theo kích thước yêu cầu

Ví dụ về sử dụng image trong app.

Có hai trường hợp sử dụng ảnh trong NextJS: local imageremote image

Khi sử dụng local image (như những hình ảnh trong thư mục public) , Image trong NextJS sẽ tự động xác định height và width của hình ảnh để đảm bảo CLS cho website. và nó có thể render trong quá trình build.

Khi sử dụng remote image, NextJS không thể xác định được height, width của hình ảnh vì vậy để đảm bảo CLS cho website chúng ta cần cung cấp trước height, width cho chúng.

Có 3 cách để đảm bảo CLS cho một website:

  • Sử dụng static import
  • Xác định height, width cho imgae từ trước
  • Sử dụng layout=fill để kích thước hnhf ảnh luôn bằng kích thước của parent element của nó

Priority:

NextJs cung cấp một thuộc tính là priority cho image để xác định cho những phần tử LCP. Nó là score của website được chấm điểm tốt hơn bởi google.

Font trong NextJS:

Trong NextJS, trong quá trình build mặc định font sẽ lấy theo inline css mà bỏ qua các khai báo font khác. Điều này sẽ tạo ra kêt quả tốt hơn cho LCP và FCP.

Để add font cho NextJS app, chúng ta sẽ override lại thẻ Head trong NextJS

Đồng thời nó sẽ tự động tối ưu font của Google Fonts và Typekit.

Script trong NextJS

NextJS cho phép chúng ta tùy chọn priority cho script từ các bên thứ ba để giúp tối ưu việc load app. NextJS cung cấp strategy property để giải quyết vấn đề trên:

  • beforeInteractive : Load script trước khi trang có thể tương tác
  • afterInteractive : Load sau khi trang được tương tác, đây là option mặc định
  • lazyOnload : Load trong thời gian rảnh sau khi trang được load xong

Mỗi script nên có id property để NextJS có thể xác định và optimize script.

Cảm ơn các bạn đã đọc bài viết!