Xây dựng Severless Blog đơn giản với khả năng tùy chỉnh cao

Xây dựng Severless Blog đơn giản với khả năng tùy chỉnh cao

avatar

Phong Nguyen

2024.01.10

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 Images

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
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. Images Link

Các bước thực hiện

  1. Fork repository về github của bạn
  2. Build và run ở local
  3. Viết blog đầu tiên
  4. Deploy
  5. Domain management

1. Fork repository

  1. Truy cập repository tailwind-nextjs-starter-blog
  2. Fork repository Images Đặt tên repository tùy ý Images

2. Build và run ở local

  1. Clone repository mà bạn vừa mới copy từ github về máy local Images
  2. Build và run ở local

Yêu cầu môi trường local:

  • Node.js v18.17 or later
  • yarn v3 or later
  • git 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
    

    Images

  • Nếu không có vấn đề gì thì bạn có thể truy cập http://localhost:3000 Images

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 Images 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.

Images

Để 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 folder scripts với nội dung bên dưới Images

    postContentlayer.mjs
    import { 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
    

    Images

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. Images Images

  • 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

  • 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ó.

  1. 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.

  2. Get started với Amplify Hosting Images

  3. Chọn Github Images

  4. Cho phép Amplify có quyền truy cập Github Images Images

  5. 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 Images

  6. Add repository branch Images

  7. Build settings: Click Advanced settings, Overide Package version như hình Images

  8. Review: Save and deploy Images

  9. Quá trình deploy sẽ diễn ra trong vài phút. Images

Cũng có khả năng quá trình Build sẽ gặp lỗi: Images

Xử lý lỗi Build

  1. Update Build settings Images Sử dụng Linux 2023 Images

  2. Redeploy Images Thành công!!! truy cập domain default để confirm. Images Images

5. Domain management

Tiền đề là bạn đã mua domain ở Route 53 (Đã có Public Hosted zones) Images

  1. Tại Amplify Console -> Domain management -> Click Add domain Images

  2. Chọn domain -> Configure domain Images

  3. 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 Images Save

  4. Quá trình config domain sẽ diễn ra trong chốc lát. Images

  5. Truy cập domain: Cả khi Domain activation chưa hoàn tất vẫn có thể truy cập domain được Images

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:

  1. Tạo branch develop
  2. Liên kết Amplify với branch develop Images
  3. 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