Xây dựng Severless Blog đơn giản với khả năng tùy chỉnh cao
Phong Nguyen
Gần đây mình đã tìm được một blog template khá đẹp và dễ dàng tùy chỉnh. Cách viết blog và deploy cũng vô cùng đơn giản. Bài viết này sẽ hướng dẫn cách để bạn sở hữu 1 blog cá nhân chỉ với chưa đến 2 tiếng.
Nguồn cảm hứng tự build blog cá nhân
Gần đây mình có đọc được 1 bài blog của anh Thái, không phải Thái VG mà là anh Thái Hacker. Tìm hiểu một chút thì thật sự quá ngưỡng mộ tài năng và thành công của anh, nhưng cái mình để ý hơn nữa đó là trang blog của anh ấy - khoảng 500 bài blog được viết liên tục trong hơn 18 năm. Một con số thật đáng nể phục, anh ấy viết tất cả những gì anh ấy gặp phải trong cuộc sống và công việc dưới góc nhìn đầy tinh tế và giọng văn vô cùng lôi cuốn.
Mình cũng từng có thói quen viết blog cách đây vài năm, thời điểm đó công ty khuyến khích và cũng có khen thưởng cho những blog nhiều view. Kể từ khi nghỉ việc đến nay thì mình cũng mất luôn cái thói quen viết blog ấy.
Mình nhận ra có nhiều người có blog cá nhân, bạn bè mình khi được hỏi thì đâu đấy cũng có vài bài memo về những thứ mình làm. Và rồi mình cũng nhận ra rằng kiến thức mình tích lũy được dần cũng sẽ bị quên đi ít nhiều, sẽ tốt biết bao nếu những thứ đó được memo một cách chỉnh chu, hoặc chí ít mình có thể tìm lại và hiểu dc ngay lập tức.
Có nhiều nền tảng blog (có phí hoặc free) mà bạn chỉ cần đăng ký tài khoản xong đã có thể bắt đầu viết được rồi. Tuy nhiên mình muốn một blog mang dấu ấn cá nhân đáp ứng các tiêu chí sau:
- Phí duy trì rất ít hoặc gần bằng zero
- Dễ dàng viết bài sử dụng markdown
- Dễ dàng tùy chỉnh theo ý muốn
- Thay đổi layout
- Thay đổi màu sắc
- Thêm tính năng
- etc... bất kể điều gì mình muốn vì mình giữ source code.
- Deploy đơn giản chỉ cần
git push
Và rồi mình cũng tìm được 1 open source đáp ứng đầy đủ các yêu cầu trên, sau đây mình sẽ hướng dẫn cách để thực hiện.
Yêu cầu
- Tài khoản AWS (Cho mục đích Deploy sử dụng Amplify, Có thể deploy dùng Vercel hoặc Netlify)
- Tài khoản Github
- Đã mua domain trên Route 53, Nếu chưa có các bạn tham khảo cách đăng ký domain tại đây
- Kỹ năng git
Các kỹ năng trên đủ để bạn có thể xây dựng blog cá nhân theo hướng dẫn này rồi. Tuy nhiên, để có thể tùy chỉnh nâng cao bạn cần có thêm kỹ năng:
- Nextjs
- Tailwindcss
- AWS skill
Kết quả đạt được.
Trước khi thực hiện theo guidline này thì chúng ta cần xem trước demo cái đã:
Default: Demo
Một số trang đã được customize lại từ template gốc xem tại đây
Và cả cái blog các bạn đang view cũng là sản phẩm customized từ template gốc.
Giới thiệu về template
Theo cha đẻ của template tailwind-nextjs-starter-blog, Anh ta muốn xây dựng 1 blog với rất nhiều tính năng gần với các templates phổ biến biện tại như beautiful-jekyll và
Hugo Academic nhưng với hệ sinh thái tốt nhất của React và các phương pháp hay nhất trong phát triển web hiện tại.
Và đây là những tính năng của blog mà chúng ta chuẩn bị build. Link
Các bước thực hiện
- Fork repository về github của bạn
- Build và run ở local
- Viết blog đầu tiên
- Deploy
- Domain management
1. Fork repository
- Truy cập repository tailwind-nextjs-starter-blog
- Fork repository Đặt tên repository tùy ý
2. Build và run ở local
Yêu cầu môi trường local:
Node.js
v18.17 or lateryarn
v3 or latergit
v2.14.1 or later
Mở git bash và chạy lệnh sau:
Lưu ý rằng nếu bạn đang sử dụng Windows, bạn có thể cần phải chạy:
set PWD="$(pwd)"
Build
yarn
Start server
yarn dev
Nếu không có vấn đề gì thì bạn có thể truy cập http://localhost:3000
3. Viết blog đầu tiên
Sau khi lướt qua các page một lượt rồi thì bây giờ chúng ta tiến hành viết blog đầu tiên. Cách đơn giản để bắt đầu là copy lại từ 1 bài blog có sẵn.
Copy bài code-sample.mdx
và add thêm Copy
vào title Bạn có thể tìm bài post mới thêm này tại menu markdown
hoặc code
hoặc features
. http://localhost:3000/tags/markdown.
Mặc dù Post mới đã hiển thị tuy nhiên có 2 lỗi xảy ra trên Windows vẫn chưa được fix ở thời điểm mình biết blog này.
- Tính năng Search không hoạt động
- Không tự động count số bài Post khi thêm bài viết mới.
Để fix lỗi này các bạn làm theo cách sau:
Commenting out the onSuccess hook in
contentlayer.config.ts
Warning: Don't push to git repo
], }, // onSuccess: async (importData) => { // const { allBlogs } = await importData() // createTagCount(allBlogs) // createSearchIndex(allBlogs) // }, })
Tạo file
postContentlayer.mjs
trong folderscripts
với nội dung bên dướipostContentlayer.mjsimport { writeFileSync } from 'fs' import GithubSlugger from 'github-slugger' import { allCoreContent, sortPosts } from 'pliny/utils/contentlayer.js' import { allBlogs } from '../.contentlayer/generated/index.mjs' import siteMetadata from '../data/siteMetadata.js' const isProduction = process.env.NODE_ENV === 'production' /** * Count the occurrences of all tags across blog posts and write to json file */ export async function createTagCount() { const tagCount = {} allBlogs.forEach((file) => { if (file.tags && (!isProduction || file.draft !== true)) { file.tags.forEach((tag) => { const formattedTag = GithubSlugger.slug(tag) if (formattedTag in tagCount) { tagCount[formattedTag] += 1 } else { tagCount[formattedTag] = 1 } }) } }) writeFileSync('./app/tag-data.json', JSON.stringify(tagCount)) } export async function createSearchIndex() { if ( siteMetadata?.search?.provider === 'kbar' && siteMetadata.search.kbarConfig.searchDocumentsPath ) { writeFileSync( `public/${siteMetadata.search.kbarConfig.searchDocumentsPath}`, JSON.stringify(allCoreContent(sortPosts(allBlogs))) ) console.log('Local search index generated...') } } async function postContentlayer() { await createTagCount() await createSearchIndex() } postContentlayer()
Sau khi thêm Post hay change tags của Post. Bạn cần mở tab git bash mới và run lệnh dưới để count số lượng bài Post của từng tag và generate
public\search.json
cho chức năng Search.node ./scripts/postContentlayer.mjs
Sau khi chạy lẹnh trên xong thì Memu MARKDOWN
đã update số lượng bài Post và chức năng Search đã hoạt động.
- Push thay đổi lên github branch
main
. Lưu ý là không commit đoạn comment out phía trên lên github nhé
Vậy là xem như chúng ta đã thêm được 1 bài Post, Còn vấn đề xóa bài viết cũ, customize giao diện v.v hãy để sau nhé, trước mắt hãy deploy thành công cái đã.
4. Deploy sử dụng AWS Amplify
Có những cách deploy blog này:
Sử dụng Vercel
- Đây là cách dễ dàng nhất.
- Chỉ cần tạo account Vercel và liên kết với github.
- Giao diện dễ sử dụng.
- https://cloudmentor-pro.vercel.app/
Sử dụng Netlify
Static hosting services / GitHub Pages / Firebase etc.
Buid ra content tĩnh -> Push lên S3 -> Cấu hình Cloudfront Distribution trỏ đến Origin S3 -> Custom domain với Route 53
Sử dụng AWS Amplify
- Có hơi phức tạp với những người không quen với AWS
- Ưu điểm là sau này có thể tận dụng các tính năng của Amplify để xây dựng thành 1 web động kết hợp với các Serverless Service khác.
Mình muốn focus vào việc làm sao để viết blog nhanh chóng mà không quan tâm nhiều đến hạ tầng hay config v.v. Lại có thể dễ dàng chuyển thành web động sử dụng AWS Service nên quyết định chọn Amplify.
Giới thiệu về AWS Amplify
- Fastest, easiest way to develop mobile and web apps that scale.
- AWS Amplify is a set of products and tools that enable mobile and front-end web developers to build and deploy secure, scalable full-stack applications, powered by AWS.
AWS Amplify cho phép bạn xây dựng scalable full-stack applications, hỗ trợ build và deploy tự động. Các bạn có thể tìm hiểu về Amplify ở những bài viết khác.
Ở bài này mình chỉ demo sử dụng Amplify để host 1 web Nextjs without Backend. Đương nhiên nếu bạn hiểu rõ về Amplify, có thể customize blog trở thành 1 web động không quá khó.
Truy cập aws account, di chuyển đến AWS Amplify Console. Mình sử dụng Region
Singapore
để đạt latency tối thiểu cho người dùng ở Việt Nam.Sau khi Amplify có quyền truy cập Github chúng ta thực hiện lại bước kết nối
Build settings: Click Advanced settings, Overide Package version như hình
Cũng có khả năng quá trình Build sẽ gặp lỗi:
Xử lý lỗi Build
5. Domain management
Tiền đề là bạn đã mua domain ở Route 53 (Đã có Public Hosted zones)
Tại Amplify Console -> Domain management -> Click Add domain
Add domain: Mình sử dụng sub-domain cho blog chứ không dùng root domain nên setting như bên dưới Save
Truy cập domain: Cả khi Domain activation chưa hoàn tất vẫn có thể truy cập domain được
Multi environment deployment
Như vậy là chúng ta đã hoàn thành quy trình Deploy blog chỉ bằng việc git push
lên branch main
. Mỗi lần push code lên nhánh main
thì quá trình Provision -> Build -> Deploy sẽ diễn ra 1 cách tự động.
Trường hợp chúng ta muốn thêm 1 môi trường để test thì cách làm như sau:
- Tạo branch
develop
- Liên kết Amplify với branch
develop
- Có thể custom domain như cách đã làm với branch
main
Customize Blog template
Để tùy chỉnh blog theo mong muốn các bạn folow theo hướng dẫn của repo gốc nhé.
Nếu có khả năng lập trình Nextjs, bạn có thể tùy chỉnh layout theo ý muốn. Trường hợp của mình, mình đã nhờ 1 bạn dev để viết 1 layout mới đáp ứng tiêu chí của mình. Nếu các bạn Ok với 3 layout hiện tại thì không cần custom layout cũng được.
Sử dụng Amplify có thể kết hợp với Cognito - xây dựng chức năng đăng ký / đăng nhập. Kết hợp với DynamoDB, Api gateway, Lambda .v.v để thêm các tính năng như 1 dynamic web.
Đấy là những cái nâng cao, còn để viết blog cá nhân thôi thì mọi thứ ở hướng dẫn này mình nghĩ là đủ cho bạn.
Tổng kết
Xây dựng blog hay viết blog là điều không khó, cái khó là duy trì được thói quen này. Mình hy vọng bài viết này không chỉ giúp các bạn xây dựng 1 blog cá nhân, mà còn mang lại nguồn cảm hứng viết blog, vừa có giá trị lưu lại kiến thức bản thân còn có thể chia sẻ cho nhiều người.
Source
- Repo mình Fork từ repo gốc: https://github.com/cloudmentor-pro/tailwind-nextjs-starter-blog
- Blog mình demo: https://blog.cloudmentor.click/ (Có thể sẽ bị xóa)
- Blog mình đã xây dựng: https://blog.cloudmentor.pro/