Chuyển blog sang Gridsome, tạm biệt Hugo
Giới thiệu
Mình mới chuyển website sang Gridsome, bạn có thể review lại 1 vòng website thấy thế nào nhé.
Mục tiêu của bài viết này là giúp bạn hiểu sơ về Gridsome và tại sao mình bỏ Hugo để dùng nó.
Lúc trước mình viết bài bỏ Wordpress để qua static site với Hugo, nhiều bạn cũng bỏ theo rồi đó, biết đâu lần này cũng vậy 😅
Đây là điểm LightHouse trước và sau khi chuyển sang Gridsome:
Trước
Sau
Gần như full điểm, điểm Performance thấp là do mình có dùng mấy cái iframe của Spotify, sẽ tìm cách khắc phục sau 😂
Tại sao bỏ Hugo?
Khoảng 10 tháng trước, mình có đổi blog từ Wordpress sang Hugo và bắt đầu dùng static site generator từ đó.
Từ đó cũng đã quen với việc viết blog bằng Markdown luôn 😗
Mọi thứ đều ổn cho đến khi mình muốn chỉnh sửa giao diện lại blog.
Vì gần đây mình có làm thêm phần podcast nữa thêm cấu trúc các bài viết bị lộn xộn giữa podcast với blog thường.
Mình muốn sẵn cấu trúc lại blog và sửa lại giao diện luôn.
Và mình thấy là syntax của Hugo để làm frontend và query dữ liệu không 'thuận mắt' cho lắm.
Mình lại biết Vue.js - framework chuyên để làm frontend, thế nên mình chuyển qua Gridsome cho thuận tay.
Nhiều người bảo là lập trình viên thì ngôn ngữ hay framework không quan trọng.
Mình đồng ý nhưng mắc gì phải code cái mình không thích, trong khi không dùng cái mình thấy thuận mắt hơn đúng không nào?
Lát mình sẽ show code của Gridsome với Hugo cho mọi người tự so sánh nhé.
Gridsome là gì?
Tương tự như Hugo, Gridsome cũng là framework dùng để tạo các static website.
Hugo dùng Golang và các library frontend như Bootstrap.
Còn Gridsome dùng Javascript và framework frontend là Vue.js. Gridsome dùng GraphQL để lấy dữ liệu từ các file markdowns, json, api
Có thể nói Gridsome là thay thế (alternative) cho Gatsbyjs (dùng React.js)
Mình có hình giải thích tổng quan cấu trúc của Gridsome bên dưới
GraphQL là gì?
GraphQL - A query language for your API
GraphQL là ngôn ngữ để lấy dữ liệu. Định nghĩ thì có trên mạng hết rồi nha, mình ví dụ luôn cho dễ hiểu.
Mình cần lấy danh sách các podcast trên Spotify của mình, do đó mình dùng Spotify API.
Bước 1 là call API từ Spotify và định nghĩa Schema cho kiểu dữ liệu Podcast (giống định nghĩa table bên SQL ý). Code call api trong file gridsome.server.js
Bước 2 là query thử dữ liệu ở Explorer tool, khi bạn chạy Gridsome project thì explorer url ở local là: http://localhost:8080/___explore
Syntax query data thì bạn có thể Google nhé
Trường hợp này mình chỉ cần lấy các fields: id, name, uri, release_date thôi.
Code để query bên trái, data nhận được bên phải, cực kỳ trực quan đúng không nào.
Bước 3: Sử dụng data trong Vue.js component thôi.
Gridsome và GraphQL có 'overkill' để chỉ làm 1 blog không?
Theo cảm nhận các nhân của mình thì không. Việc dùng Hugo còn rối rắm hơn.
Đây là đoạn code để list danh sách bài viết của Hugo
` <div class="container"> <h1 class="text-center">Danh sách bài viết</h1> <section class="bg-white br-3 pv1 ph4 nested-copy-line-height lh-copy f4 nested-links measure-wide" style="display: block !important; margin-left: auto; margin-right: auto;"> {{- range $i, $p := where .Site.RegularPages "Section" "eq" "posts" -}} {{- $thisYear := $p.Date.Format "2006" }} {{- $lastPage := $i | add -1 | index ( where .Site.RegularPages "Section" "eq" "posts") }} {{- if or (eq $i 0) ( ne ($lastPage.Date.Format "2006") $thisYear ) }} <h3 class="archive-year">{{ $thisYear }}</h3> {{- end }}
<div>
{{ $p.Date.Format "01-02" }}
<a href="{{ $p.Permalink }}" class="no-underline dim link">
{{- cond (eq .Site.Params.titlecase true) (.Title | title | markdownify) (.Title | markdownify) -}}
</a>
</div>
{{- end -}}
</section> </div> `
Còn Vue thì khác, Vue nó tách riêng phần template (html), phần data, phần style (css) ra riêng làm 3, người ta gọi là seperate conerns ý.
Chưa kể có thể tạo các component để reuse một cách dễ dàng hơn Hugo nhiều
Tương tự đây là đoạn code để list danh sách bài viết bên Vue.js. Bạn có thể thấy là mình đã tách ra 2 components con là ListPosts và PaginationPosts
` <template> <Layout> <div class="container-inner mx-auto py-16"> <list-posts :posts="$page.posts.edges" /> <pagination-posts v-if="$page.posts.pageInfo.totalPages > 1" base="/blog" :totalPages="$page.posts.pageInfo.totalPages" :currentPage="$page.posts.pageInfo.currentPage" /> </div> </Layout> </template>
<page-query> query Posts ($page: Int) { posts: allPost (sortBy: "date", order: DESC, perPage: 8, page: $page , filter: { draft: {ne: true}, categories: {containsNone: ["Podcast"]} } ) @paginate { totalCount pageInfo { totalPages currentPage } edges { node { id categories { title path } image title content date (format: "MMMM D, Y") timeToRead path } } } } </page-query>
<script> import PaginationPosts from '../components/PaginationPosts' import ListPosts from '../components/ListPosts'
export default { metaInfo: { title: 'Blog', }, components: { PaginationPosts,ListPosts }, } </script> `
Còn về GraphQL, mình thấy nó còn dễ tiếp cận, và dễ học hơn Golang. Chưa kể bạn có cái Explorer để vọc nữa.
Nhược điểm của Gridsome là gì?
Cộng đồng không nhiều bằng Hugo, nếu có lỗi gì lạ thì tự mò. (Yên tâm, mình chưa gặp lỗi gì cả)
Ít plugin hơn. Cái table of contents cũng chưa có nữa
Nhưng không sao, mình đã biến những nhược điểm như ít plugin để làm blog tối giản nhất.
Mình đã bỏ luôn phần comment rồi. Viết blog được 5 năm nhưng chỉ có khoảng 150 comments và một đống comment spam.
Nên mình đã thay phần comment này bằng một lời nhắn
Ai thực sự cần mình giúp hoặc nghiêm túc góp ý có thể liên lạc thêm. Vừa tăng sự tương tác vừa giúp trải nghiệm đọc blog tốt hơn nữa.
Mình cũng tập trung viết nội dung chất lượng hơn là ngồi lọc comment.
Kết
Vậy bạn có nên chuyển website của mình sang Gridsome không?
Nếu bạn đã biết Vue.js thì mình nghĩ là bạn nên thử nó 1 lần.
À, bạn thấy giao diện mới của website thế nào? Góp ý giúp mình nhé 🥰