Bạn đã bao giờ xây dựng ứng dụng web bằng VueJS chưa? Bạn đã từng nghe nói tới 2 khái niệm Server Side Rendering (SSR) và Client Side Rendering (CSR) chưa? Bài viết này, chúng ta sẽ cùng nhau tìm hiểu và làm rõ hai khái niệm này, cũng như giải pháp để render VueJS app phía server.
Trước khi bắt tay vào tìm hiểu Nuxtjs, chúng ta cùng xem qua hai cơ chế render ứng dụng web nhé.
Nội dung chính của bài viết
So sánh Client-side rendering (CSR) vs Server-side rendering (SSR)
Theo truyền thống, khi xây dựng các trang web hay ứng dụng web đều có chiến lược chung là đó là server sẽ chuẩn bị sẵn các nội dung HTML để gửi xuống trình duyệt. Các nội dung này sẽ được trình duyệt kết hợp với CSS để tạo thành tranh web cho bạn sử dụng.
Sau này, xuất hiện các Javascript framework hiện đại như ReactJS, VueJS… đã làm thay đổi cách tiếp cận khi phát triển ứng dụng web, cách tiếp cận mới mang tới khả năng giảm gánh nặng cho server, xây dựng mô hình phân tán thay vì tập trung tại server.
Đến đây, rất nhiều diễn đàn lại nảy sinh tranh luận gay gắt xem cách tiếp CSR hay SSR, cái nào tốt hơn, cái nào tối ưu!?
Server Side rendering (SSR) là gì ?
Đây là cơ chế cổ điển, được dùng rất phổ biến từ xưa đến nay rồi. Gọi là server side rendering vì mọi thứ sẽ được xử lý tập trung ở phía server.
Về cơ bản thì luồng của cơ chế này như hình bên dưới đây:
Có thể tóm gọn lại gồm các bước như sau:
- Khi trình duyệt gửi một request tới server, server sẽ xử lý logic, lấy dữ liệu trong database, làm bla bla… cuối cùng tạo sẵn nội dung HTMl và trả lại cho trình duyệt.
- Trình duyệt nhận được nội dung HTML, dựa vào nội dung HTML mà nó có thể tải thêm các file javascript hay CSS để hiển thị nội dung trang HTML
Có lẽ phần lớn các trang web kiểu như vnexpress, dantri, vntalking… đều đang sử dụng cách tiếp cận này.
Client Side rendering (CSR) là gì ?
Cách tiếp cận này thì hoàn toàn khác với cách SSR. Hiểu đơn giản với cách tiếp cận này thì việc render HTML, CSS sẽ được thực hiện ở client. Khi trình duyệt gửi yêu cầu tới server, máy chủ sẽ gửi một loạt tài nguyên cần thiết để khởi tạo và chạy ứng dụng web, từ đó việc render nội dung sẽ thực hiện trên trình duyệt.
Kiểu tiếp cận này khá phổ biến với các ứng dụng web kiểu Single Page (SPA – Single Page Application), ứng dụng sẽ lấy dữ liệu thông qua REST API.
Các ứng dụng kiểu SPA sẽ không phải tải lại trang mỗi khi nội dung thay đổi. Với các JS framework hiện đại như React, Vue, Angular… đều hỗ trợ để xây dựng ứng dụng kiểu như vậy.
Vậy khi nào sử dụng SSR hay CSR?
Client-side rendering
- Ứng dụng có giao diện phức tạp, tương tác nhiều với người dùng
- Dữ liệu lớn và động
- Tập trung vào các trang web phục vụ lượng lớn người dùng
Server-side rendering
- Đồ họa phức tạp, chuyên sâu vào tính toán, cần sức mạnh xử lý của server.
- Dữ liệu nhỏ, ít thay đổi
Ok, bạn đã hiểu cơ bản hai cơ chế render này rồi đúng không? Phần tiếp theo, chúng ta sẽ bắt tay vào tìm hiểu NuxtJS, một framework giúp bạn tạo ứng dụng SPA nhưng chạy trên server thay vì trên client. Thế mới hay chứ J
NuxtJS là gì?
Như các bạn đã biết, các JS framework như Vue, React, Angular… giúp bạn nhanh chóng tạo các ứng dụng web app theo cơ chế Client Side Rendering. Điều này có thể tốt cho trải nghiệm người dùng nhưng nó lại không tốt cho SEO, các con bot của Google có lẽ vẫn còn hơi “ngu”, chưa crawl được nội dung các ứng dụng kiểu Single page như vậy. Đó cũng là điểm cộng của cơ chế Server side rendering, và là nguyên nhân chính để cho ra đời các framework như Nuxt.JS.
Nuxt.JS là một Javascript framework để tạo các ứng dụng VueJS. Mục tiêu là để chúng ta có thể tạo một ứng dụng linh hoạt nhưng được render phía máy chủ, tương tự một trang web tĩnh giống như các website thông thường (điều mà có lợi cho SEO).
NuxtJS tập trung vào khía cạnh render giao diện người dùng. Ngoài ra, Nuxt.js có rất nhiều tính năng giúp bạn phát triển giữa phía client và server như Dữ liệu bất đồng bộ (Asynchronous Data), Middleware, Layouts, v.v.
Bài viết này, chúng ta sẽ cùng nhau tìm hiểu NuxtJS, cách cài đặt và cũng cách nó hoạt động để xây dựng ứng dụng được hỗ trợ bởi Vue phía server.
NuxtJS hoàn toàn tương tự với NextJS framework, cũng là một framework được xây dựng để tạo các ứng dụng React phía máy chủ.
😃 Đọc thêm:
- Hướng dẫn học ReactJS trong 5 phút cho người mới
- Vuejs tutorial cho người mới – Tự xây dựng Todo App
Tại sao nên sử dụng NuxtJS
Nuxt.JS có rất nhiều tính năng hữu ích, giúp bạn nhanh chóng xây dựng các ứng dụng web, có thể kể tới như:
- Automatic Code Splitting
- Hỗ trợ Vue hoàn hảo
- Static File Rendering
- Hỗ trợ phiên bản HTTP/2
- Hệ thống router và dữ liệu bất đồng bộ dễ sử dụng
- Hỗ trợ tính năng Hot reloading (rất hữu ích cho các bạn developer)
- .v.v…
Khởi tạo một dự án với Nuxt.JS
Để bắt đầu một dự án Nuxt.JS vô cùng đơn giản, chỉ đôi dòng lệnh là bạn đã khởi tạo xong và chạy được hello world rồi.
Giống với React, bạn có công cụ create-react-app thì Nuxt.JS cũng có công cụ tương tự, có tên là create-nuxt-app (Hay là các nhóm phát triển bắt chước ý tưởng của nhau nhỉ!? )
Câu lệnh đơn giản như sau:
npx create-nuxt-app <project-name> Hoặc yarn create nuxt-app <project-name>
create-nuxt-app
trong máy tính đã nhé. Câu lệnh cài đặt: npm install -g create-nuxt-app
. Và cả npx nữa nhé: npm i npx
Với câu lệnh create-nuxt-app, bạn còn có nhiều tùy chọn nâng cao khác nữa, như bạn muốn tích hợp sẵn server-side frameworks, UI frameworks, testing frameworks… hay không? Trong khuôn khổ bài viết, chúng ta chỉ tìm hiểu cơ bản thôi.
Ok, sau khi tạo dự án xong thì chạy thử thôi.
npm run dev
Sau khi chạy ứng dụng thành công, bạn vào trình duyệt gõ: http://localhost:3000. Kết quả thu được là giao diện trang web mặc định như dưới đây:
Chúc mừng bạn đã có khởi đầu thành công.
Cấu trúc thư mục dự án Nuxt.JS
Cấu trúc mặc định được tạo gồm các thư mục và các tệp như hình dưới đây. Chúng ta sẽ cùng nhau xem xét ý nghĩa và công dụng của chúng.
Assets: Chứa những tài nguyên phục vụ hiển thị trang web như ảnh, fonts chữ, hay CSS…
Components: Cũng giống như ứng dụng Vue thông thường, các component là các thành phần được tạo ra để bạn tái sử dụng trong ứng dụng như: Button, Input, Card, Dialog…
Layouts: thư mục layouts là nơi chứa các thành phần tạo nên layout của ứng dụng như layout dọc, layout ngang. Đây là nơi hợp lý nhất mà bạn có thể để các thành phần như Header, Footer, Theme…
Middleware: Middleware là nới bạn dùng để tạo các function mà chạy trước khi render trang.
Pages: Thư mục này chứa các view của ứng dụng cũng như định nghĩa routes cho ứng dụng luôn.
Plugins: Chứa các javascript plugin mà bạn muốn chạy trước khi khởi tạo root vue.js application.
Static: Tương tự như thư mục assets nhưng mà nó cho phép truy cập trực tiếp, được map tự động với domain từ client mà không cần phải qua router hay biến môi trường. Ví dụ: /static/robots.txt sẽ được truy cập trực tiếp: http://localhost:3000/robots.txt
Store: Chứa các tệp của vuex, dùng quản lý state của ứng dụng. Vuex Store được cài đặt kèm với Nuxt nhưng mặc định thì lại bị disable. Muốn enable chúng, bạn chỉ cần tạo một tệp index.js trong thư mục store là được.
nuxt.config.js: Cấu hình ứng dụng Nuxt
package.json: Tương tự như dự án react, vue, nodejs… là nơi cấu hình build, và chứa các dependencies và scripts
Routing
Cách thức hoạt động của router trong Nuxt là nó tự động tạo cấu hình vue-router dựa trên cây các tệp .vue trong thư mục pages.
Để dễ hình dung hơn, chúng ta sẽ xem xét ví dụ dưới đây:
pages/ --|index.vue --|product.vue --|index.vue --|one.vue
Với cấu trúc các tệp .vue như trên, khi generate ra route, bạn sẽ thu được kết quả như sau:
router: { routes: [ { name: 'index', path: '/', component: 'pages/index.vue' }, { name: 'product', path: '/product', component: 'pages/product/index.vue' }, { name: 'product-one', path: '/product/one', component: 'pages/product/one.vue' } ] }
Bạn nên nhớ là việc tạo route là hoàn toàn tự động.
Route lồng nhau
NuxtJS cho phép bạn tạo các route lồng nhau bằng cách sử dụng các route con của vue-router.
Để định nghĩa component cha của một route lồng nhau, bạn cần tạo một file vue với tên trùng với thư mục chứa các tệp vue con.
pages/ --| products/ -----| _id.vue -----| index.vue --| products.vue
Giờ generate ra route, bạn sẽ thu được kết quả:
router: { routes: [ { path: '/products', component: 'pages/products.vue', children: [ { path: '', component: 'pages/products/index.vue', name: 'products' }, { path: ':id', component: 'pages/products/_id.vue', name: 'products-id' } ] } ] }
Khi navigate giữa các page, Nuxt khuyến khích chúng ta sử dụng nuxt-link
component thay vì dùng router-link
.
Triển khai ứng dụng Nuxt.JS
Đây là công đoạn cuối cùng của quá trình phát triển bất kỳ ứng dụng nào. Sau khi bạn phát triển, kết quả cuối cùng sẽ là triển khai lên server thật của khách hàng để chạy thật. Người ta gọi đây là “lễ trưởng thành của một thanh niên”
Nhìn vào file package.json
, bạn sẽ thấy 4 câu lệnh sau:
Mình sẽ giải thích chi tiết từng câu lệnh:
Câu lệnh | Công dụng |
dev | Chạy một development server trên localhost:8080, hỗ trợ hot-reloading |
build | Build ứng dụng với Webpack và minify các tệp CSS, JS |
start | Chạy server ở chế độ production (sau khi chạy nuxt build) |
generate | Build ứng dụng và generate tất cả cá route tương ứng với các HTML files (sử dụng cho các static hosting) |
Như vậy, khi bạn muốn deploy ứng dụng Nuxt, bạn có thể chọn một trong 3 chế độ deploy:
- Server-Side Rendering (Câu lệnh: npm run build)
- Static Generated (Câu lệnh: npm run generate)
- Single Page Applications
Riêng với chế độ Single Page Application, bạn cần thêm tham số này vào trong nuxt.config.js
export default { mode: 'spa' }
Sau đó, quay trở lại package.json để thêm vào trong scripts.
"scripts": { "dev": "nuxt --spa", "build": "nuxt build --spa", "start": "nuxt start --spa", "generate": "nuxt generate --spa", },
Vậy là xong rồi đấy.
Tạm kết
Qua bài viết này, chúng ta đã hiểu cơ bản NuxtJS là gì, cấu trúc dự án Nuxt cũng cách để deploy một ứng dụng Nuxt. Về cá nhân mình, mình rất thích Javascript, từ việc code web app với Vue, React rồi mobile với React Native… Giờ đây, với NuxtJS, mình lại có thêm một công cụ tuyệt vời nữa để tiếp tục gắn bó lâu dài với JS.
Bạn cảm thấy thế nào về Nuxt này? Cho mọi người biết cảm nhận ở mục bình luận nhé.
Bình luận. Cùng nhau thảo luận nhé!