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 😂
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é.
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 - 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.
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.
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ư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.
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é 🥰
Bài viết liên quan
Đầu tư crypto có phải một nghề không? - 3 min(s) read - published on March 22, 2021[Case Study] - StatcWeb.Studio dùng nocode để làm tool nocode: 200h - 0 sales - 5 min(s) read - published on January 24, 2021[Case Study] Bán No-code MVP làm trong 100h giá $5000 - 11 min(s) read - published on January 15, 2021Chi tiết mình validate idea với nocode - 3 tuần 60 sales - $567 - 7 min(s) read - published on December 15, 2020Do things that don't scale - Lời khuyên tốt nhất để validate idea làm app - 2 min(s) read - published on November 22, 2020GPT-3 sẽ là phát minh quan trọng kể từ Blockchain - 4 min(s) read - published on September 15, 2020#6 - NoCode MVP - Tổng kết - 5 min(s) read - published on August 22, 2020#5 - NoCode MVP - Buông bỏ để hạnh phúc - 2 min(s) read - published on July 28, 2020#4 - NoCode MVP - Ý tưởng. Một lần chơi lớn - 4 min(s) read - published on July 2, 2020#3 - NoCode MVP - Sức mạnh của Bubble.io - 5 min(s) read - published on June 29, 2020