Để ứng dụng website trông đẹp mắt với các animation mọi nơi, chúng ta thường nhúng hàng tá các framework UI, javascript. Nhưng liệu rằng user sẽ kiên nhẫn tới khi các nội dung, hình ảnh tuyệt vời đó được hiển thị lên sau hàng chục giây chờ đợi hay không? Câu trả lời chắc chắn là không rồi. Vậy phải làm sao mới khiến cho user không phải chờ đợi quá lâu trong khi vẫn mang tới cho họ 1 ứng dụng có UI/UX tốt nhất? Hãy cùng tìm hiểu cách mà Niteco đã và đang phát triển các dự án Ecommerce Website cho 1 trong các khách hàng lớn nhất của Niteco.

server-side-rendering

Server-side Rendering 

Đối với 1 ứng dụng Ecommerce Web, SEO luôn được ưu tiên hàng đầu trước khi nghĩ đến những thứ khác. Do đó dễ hiểu rằng các Ecommerce Website đều được xây dựng theo kịch bản Server-Side-Rendering thay vì Client-Side-Rendering như các ứng dụng trang đơn (SPA) mới hiện nay. Server-Side-Rendering có ưu điểm chính là hỗ trợ SEO tốt, bên cạnh đó giúp tốc độ tải ban đầu nhanh chóng, nhưng hạn chế là khiến khả năng tương tác người dùng kém đi. Việc tăng tốc độ lẫn khả năng tương tác của người dùng sẽ là nhiệm vụ không hề dễ dàng với developer.

client-side-rendering

Client-side rendering

Bởi lẽ, chúng ta vừa phải giảm thiểu tối đa các thư viện javascript, style để trang được tải về nhanh nhất, giúp người dùng có thể tương tác với trang chỉ sau khoảng chưa đến 2s, vừa phải đảm bảo khả năng tương tác của người dùng lẫn giao diện vẫn đạt được yêu cầu đến từ khách hàng. Để trung hòa được các yếu tố có vẻ mâu thuẫn trên, mình và các đồng nghiệp đã quyết định đánh đổi việc giảm thiểu sử dụng các thư viện javascript lẫn các framework style bằng việc tự phát triển các component của riêng mình và tối ưu nhất có thể để hạn chế sự dư thừa không cần thiết nhưng vẫn mang lại hiệu quả tối đa về trải nghiệm người dùng lẫn tốc độ của ứng dụng.

Để cải thiện performance của 1 website thì đó là sự tối ưu hóa các thành phần sau:

1. HTML:

Khi bắt đầu gõ từng dòng mã html thì ban đầu chúng ta có thể không để ý tới thứ tự cũng như số lượng DOM được viết ra, vì dù thế nào thì chỉ cần UI hiển thị ra đúng theo design là được. Điều đó không hẳn sai nhưng đối với 1 ứng dụng web lớn thì việc DOM bị phình to do dư thừa sẽ là điều không tránh khỏi. Vì thế mỗi 1 thẻ HTML được viết ra phải được cân nhắc 1 cách kĩ lưỡng với mục đích giảm thiểu tối đa số dòng nhất có thể. Điều này đòi hỏi không chỉ kinh nghiệm mà còn là kĩ năng giúp phân biệt giữa 1 FE developer giỏi và tệ.

2. Style:

Đối với style, việc minify file css là điều bắt buộc phải làm. Hiện tại Niteco đang dùng thư viện clean-css cho việc này với các tùy chỉnh phù hợp với từng dự án. Tuy nhiên việc minify chỉ là bước sau cùng cho việc optimize. Bởi lẽ bước đầu tiên cần làm là có 1 convention từ đầu về việc viết các class name như nào. Hiện tại thì việc sử dụng BEM kết hợp với các Atomic class có thể giúp giảm thiểu việc đè style cũng như tái sử dụng các class dùng chung.

Việc tách các components cũng là 1 bước quan trọng để giúp cho việc tái sử dụng style và đảm bảo việc không duplicate style. Bên cạnh đó việc chia các file style giúp việc load những file này theo page cũng giúp giảm size và tăng tốc độ hiển thị style 1 cách nhanh chóng.

3. Javascript:

Việc tương tác với người dùng luôn là phần quan trọng với 1 webapp với rất nhiều tính năng khác nhau. Tuy nhiên, nó cũng phát sinh ra muôn vàn vấn đề phải cải thiện để giúp việc người dùng có thể tương tác với website sớm nhất có thể.

Tại Niteco, việc đầu tiên các dev làm đó là nói không với Jquery. Jquery đã được phát triển từ lâu nhưng tới hiện tại nó lại là 1 gánh nặng cho bất cứ việc phát triển 1 website mới nào. Jquery cung cấp rất nhiều api hữu ích nhưng đồng thời cũng khiến nó trở nên dư thừa. Bạn sẽ chẳng bao giờ dùng hết 100% các api mà Jquery cung cấp và chẳng có website nào làm được điều đó. Vậy phải dùng thư viện nào thay thế cho Jquery? Câu trả lời là không dùng thư viện nào cả.

Tất cả dòng code đều là vanilla javascript để đảm bảo tối ưu source code nhất có thể, có chăng điều cần lưu ý là các thư viện được cải đặt phải đảm bảo phù hợp với dự án và đảm bảo bạn sẽ lazyload các thư viện này sau đó. Công việc viết lại các component bằng vanilla javascript ban đầu sẽ khá dễ dàng, tuy nhiên công việc sẽ trở lên khó khăn hơn nhiều cho tới khi số lượng dòng code nhiều lên và độ phức tạp của các component tăng lên.

Nếu bạn đã quá quen việc phát triển các ứng dụng web bằng Reactjs, Anguluarjs … thì việc viết lại từ đầu bằng vanilla javascript có thể sẽ mang lại một trải nghiệm hề vui vẻ chút nào, và thực sự là đội ngũ dev tại Niteco cũng cảm thấy vậy. Khi số dòng code tăng lên đáng kể và số bug cũng nhiều không kém sẽ khiến nhiều dự án bị chậm trễ deadline và có nguy cơ bị tạm dừng. Nếu ai bảo việc viết code javascript là dễ dàng thì chắc chắn đó là những người chưa thực sự trải qua các dự án kiểu này.

Javascript sẽ trở nên rất rất tệ nếu bạn không thể kiểm soát từng dòng code, chưa kể đến việc phải đáp ứng cho mỗi dòng code viết ra có thể chạy trên các trình duyệt với các version khác nhau. Để cải thiện và tăng chất lượng code, chúng tôi ở Niteco, đã quyết định viết lại toàn bộ các component bằng typescript với việc quản lý chặt chẽ từng biến, từng function cũng như việc kiểm tra tự động code trước khi tạo các Pull Merge.

Bên cạnh đó thì việc lazyload file javascript sẽ là điều bắt buộc. Để làm được điều này thì mình dựa vào cơ chế dynamic import của webpack để chunk ra các file javascript tương ứng và kết hợp với IntersectionObserver API để chỉ tải các file cần dùng theo từng page. Thậm chí khi user bắt đầu tương tác, thì các file javascript cần dùng mới được tải về.

Ngoài những cách trên ra thì việc sử dụng thêm service worker để cache lại các resource như image, javascript, … sẽ giúp cho việc hiển thị website tăng lên một cách đáng kể. Tuy nhiên việc này lại phải dựa trên yêu cầu cụ thể của từng dự án một.

Đó chỉ là việc tối ưu performance về phía client, vẫn còn rất nhiều việc cần làm phía server side để có thể tăng tốc cho 1 website nhưng nó không nằm trong nội dung của bài này.

Để kết luận cho bài viết này, mình chỉ muốn nói rằng việc cải thiện performance của 1 website đòi hỏi một kĩ năng của 1 developer giỏi, trong đó, sự tỉ mỉ trong từng dòng code lẫn mindset trong việc phân chia components là điều rất quan trọng.

Với cá nhân mình mới bắt tay vào thực hiện, quả thực đó là 1 thách thức đáng kể với rất nhiều áp lực. Nhưng một khi đã thuần thục và hiểu được ý nghĩa của từng dòng code mà bản thân mình viết ra, mình lại cảm thấy hào hứng với những gì mà mình đã làm được và thấy vui vì các kĩ năng của mình đã được nâng lên 1 level mới 😂. Việc cải thiện performance của ứng dụng web vẫn sẽ luôn được nâng cấp cùng với tốc độ phát triển công nghệ web trong tương lai. Là một lập trình viên, mình rất mong điều đó diễn ra trong tương lai gần.

Để được học hỏi, trao đổi và làm việc với anh Mạnh, hãy ứng tuyển ngay vào các vị trí đang tuyển dụng tại Niteco nhé: Niteco tuyển dụng.