3 điểm bởi GN⁺ 2023-10-23 | 1 bình luận | Chia sẻ qua WhatsApp
  • Khi biến website cá nhân thành một binary duy nhất, một người có thể hiểu toàn bộ cấu trúc và tự bảo trì, nhờ đó giảm gánh nặng phụ thuộc của tổ hợp SSG/hosting truyền thống
  • Những tổ hợp như Hugo và GitHub Pages giả định nhiều điều kiện bên ngoài: tính liên tục của dịch vụ, việc duy trì dự án, hệ sinh thái plugin, cách triển khai, Go, v.v.
  • Chỉnh sửa HTML thủ công đơn giản và ổn định, nhưng khó xử lý lặp lại các chức năng chung, quy trình làm việc trở nên mệt mỏi nên cần một cách có thể điều chỉnh thú vị hơn
  • Website động dựa trên Go xử lý những việc rườm rà với site tĩnh, như hiển thị IP hay cập nhật RSS feed, bằng mã phía server, đồng thời trả về HTML hoàn chỉnh cho cả các công cụ không phải trình duyệt
  • Với website cá nhân, bắt đầu nhỏ rồi phát triển bằng thư viện chuẩn và công cụ đơn giản sẽ bền lâu hơn; nếu bắt đầu bằng framework lớn thì khó theo kịp trong quỹ thời gian cá nhân

Vì sao các công cụ website hiện có không phù hợp

  • Đã thử nhiều cách, từ Ghost, Hugo, Jekyll, sr.ht cùng tarball cho đến chỉnh sửa HTML thủ công, nhưng chúng không phù hợp với tiêu chí cá nhân và cũng không đem lại hứng thú
  • Tiêu chí quan trọng nhất là một hệ thống mà một người có thể hiểu từ đầu đến cuối và dễ dàng bảo trì
    • Mã dễ đọc
    • Vòng lặp phản hồi nhanh
    • Niềm vui và sự khéo léo
    • Cấu trúc cho phép tự đào sâu khi có sự cố
  • Trình tạo site tĩnh (SSG) như Hugo nhận template và Markdown làm đầu vào để tạo HTML, và thường được dùng cùng một nền tảng hosting
  • Tổ hợp Hugo và GitHub Pages kéo theo nhiều điều kiện bảo trì
    • Dịch vụ GitHub Pages phải tiếp tục hoạt động
    • Sản phẩm GitHub Pages phải tiếp tục được duy trì
    • Dự án Hugo và tài liệu cộng đồng phải được duy trì
    • Có thể phải phụ thuộc vào hệ sinh thái plugin
    • Binary của Hugo theo thời gian vẫn phải tạo HTML gần như theo cùng một cách
    • Cơ chế triển khai của GitHub Pages phải tiếp tục hoạt động
    • Cần Go
  • Cũng có thể ghim một phiên bản Hugo cụ thể để dùng, nhưng trên thực tế đôi khi vẫn phải nâng cấp vì lỗi

Ưu điểm và giới hạn của việc chỉnh sửa HTML thủ công

  • Cũng đã chọn cách host website trên máy do mình trực tiếp kiểm soát và tự tay chỉnh sửa HTML bằng Vim
  • Phiên bản đầu tiên của j3s.sh được tạo theo cách này, và nhiều ý tưởng layout hiện tại xuất phát từ đó
  • Viết HTML bằng tay mang cảm giác như công việc thủ công nặng nhọc, dẫn đến chủ nghĩa tối giản cực đoan
    • Đưa style trực tiếp vào HTML
    • Giảm tối đa các chức năng chung trên toàn site
    • Tránh styling nhiều nhất có thể
  • Cách này đơn giản, ổn định và dễ bảo trì
    • HTML đã viết có thể tái sử dụng mà không cần sửa
    • Không có phụ thuộc bên ngoài
    • Tạo cảm giác chắc chắn rằng site sẽ được duy trì lâu dài
  • Tuy vậy, vẫn muốn xử lý template hóa các chức năng chung hiệu quả hơn, và cần một cách có thể điều chỉnh một cách thú vị mà không dùng framework hiện có

Website Go dạng một binary duy nhất

  • Nếu viết toàn bộ website bằng một ngôn ngữ, có thể đóng gói kết quả vào một binary duy nhất để triển khai
  • Go là một lựa chọn phù hợp cho việc bảo trì cá nhân và triển khai đơn giản
    • Dễ để một người bảo trì
    • Nhấn mạnh hướng dùng ít phụ thuộc
    • Ngôn ngữ tương đối đơn giản
    • cam kết tương thích ngược
    • Dễ tạo binary biên dịch tĩnh
    • Hầu hết biên dịch trong chưa đến 10 giây
    • Thư viện chuẩn phát triển tốt
  • Kết quả là j3s.sh trở thành một binary phục vụ website

Sự đơn giản mà website động mang lại

  • Trong một số trường hợp, website tạo động có thể đơn giản hơn website tạo tĩnh
    • Không cần nghĩ ra các cách đi vòng để tạo nội dung
    • Có thể tạo ngay nội dung cần thiết
  • Chức năng in địa chỉ IP của khách truy cập được triển khai đơn giản bằng http.HandlerFunc của Go
    • Đọc header X-Forwarded-For
    • Gắn handler vào đường dẫn /ip
    • Có thể gọi cùng hàm ở những nơi cần thiết
  • Nếu triển khai cùng chức năng đó trên site tĩnh, có thể cần phụ thuộc bên ngoài như JavaScript, và cũng phải xét đến trường hợp không có JavaScript
    • Một số độc giả từ chối chạy JavaScript
  • Nếu server trả về HTML đã chứa sẵn địa chỉ IP, client vẫn nhận được phản hồi đúng ngay cả khi không hiểu JavaScript
    • Cách này cũng hiệu quả với các công cụ không phải trình duyệt
  • RSS feed trên trang chủ được tạo khi website khởi động
    • Có thể lấy lại các bài viết mới nhất của bạn bè
    • RSS feed fetcher tự viết được kỳ vọng sẽ hoạt động lâu dài mà không cần bảo trì
    • Hiểu chính xác cách nó hoạt động bên trong

Triển khai và cách bắt đầu

  • Việc triển khai được xử lý bằng một shell script ngắn
    • Lấy Git repository về
    • Nếu nhánh local bị tụt lại, chạy git merge origin/main
    • Build bằng go build
    • Di chuyển binary đến /usr/local/bin/j3s.sh
    • Khởi động lại service bằng service j3s.sh restart
  • Script này được chạy mỗi phút bằng cronjob, nên khi repository được cập nhật, site sẽ được build lại
    • Nếu test ở local rồi upload, site public sẽ được cập nhật trong vòng 1 phút
    • Đơn giản đến mức chỉ cần biết một chút về shell là có thể hiểu trong vòng 10 giây
  • Website cá nhân mang lại cảm giác độc đáo trên web ngày nay, và có thể phản ánh sâu sắc những điều người vận hành coi trọng
  • Nếu site tĩnh phù hợp với ai đó thì cứ dùng như vậy, nhưng với người có hệ giá trị tương tự, thử làm website động có thể rất hợp
    • Có thể bắt đầu nhỏ
    • Có thể lặp đi lặp lại thêm các ý tưởng thú vị
    • Vì là site của mình nên hardcode cũng được
    • Có thể làm bằng ngôn ngữ mình thích như Rust, Perl, Python, v.v.
  • Nên bắt đầu nhỏ
    • Trước hết tạo index.html, rồi tập trung vào việc phục vụ nó bằng ngôn ngữ đã chọn
    • RSS hay Markdown thì thêm sau khi cần đến
    • Nếu có thể, hãy dùng công cụ đơn giản và dễ bảo trì nhất, như thư viện chuẩn
    • Với Ruby có thể cân nhắc lựa chọn nhỏ hơn như Sinatra thay vì Rails; với Python, lựa chọn nhỏ hơn như Gin thay vì Flask
    • Cũng có thể thử trước xem liệu có tự triển khai được với 0 thư viện hay không
  • Nếu bắt đầu bằng framework lớn hoặc dự án liên tục có breaking change, sẽ khó theo kịp trong quỹ thời gian cá nhân và dễ nhanh chóng kiệt sức
  • Web cần thêm nhiều sự kỳ lạ, phấn khích và cá tính; việc thử tạo website động được khuyến khích

1 bình luận

 
GN⁺ 2023-10-23
Ý kiến trên Hacker News
  • Trên di động, chiều rộng trang web không được tính đúng nên muốn đọc phải cuộn ngang qua lại
    Ngay trước đó tôi vừa đọc câu “tôi có những tiêu chuẩn rất cao và khác thường”, nên nói thật là thấy hơi buồn cười :)

    • Đây không phải là bài viết được cấu trúc bằng HTML với các phần, đoạn văn, v.v.; nó chỉ là một tệp văn bản thuần được render bằng cách xử lý khoảng trắng pre, nên trông như một đoạn văn khổng lồ ¯_(ツ)_/¯
    • Ngay cả trong công cụ đọc của Safari cũng không có định dạng gì, điều đó cũng khá ấn tượng
      Tôi đã thấy nhiều kiểu định dạng kỳ quặc, nhưng đây là lần đầu thấy hoàn toàn không có định dạng
    • Chế độ đọc của Firefox Mobile giải quyết được, nên thực ra chỉ bất tiện cỡ bấm một nút
      Dù vậy, ấn tượng đầu tiên không tốt
    • Lập luận của tác giả và việc không thiết kế phù hợp với nền tảng mâu thuẫn với nhau
      Không hiểu nổi
    • Tôi cũng nghĩ vậy
      Tự hào về bản thân thì tốt thôi, nhưng tôi đơn giản là quyết định không đọc nữa
  • Cốt lõi là “giữ cho đơn giản” rốt cuộc nghĩa là gì, và “có thể hiểu được” là gì
    Những bài kiểu này bỏ qua phần tranh luận thú vị và mặc nhiên cho rằng cách tiếp cận của mình là đơn giản, mục tiêu là sự đơn giản
    Khi có thể chọn một lớp trừu tượng, chẳng hạn thư viện hay framework, dịch vụ hay API, thì dùng nó đơn giản hơn hay không dùng đơn giản hơn?
    Nếu không dùng mà tự làm, bạn sẽ hiểu rõ hơn toàn bộ hệ thống vận hành ra sao, nên theo một nghĩa nào đó nó đơn giản hơn
    Nhưng độ phức tạp vẫn phát sinh, và tùy trường hợp bạn còn phải tự tạo cả lớp trừu tượng
    Ngược lại, nếu dùng thì nó che giấu độ phức tạp, nên trên luồng bình thường có thể xem hệ thống là đơn giản hơn, nhưng độ phức tạp đó vẫn tồn tại và bị ẩn đi nên bạn không hiểu nó
    Cả hai cách, từ một góc nhìn nhất định, đều rõ ràng có vẻ đơn giản; nhưng phải vượt qua cái “rõ ràng” đó mới thấy được trade-off

    • Giả sử bạn muốn làm bánh táo
      Thông thường bạn sẽ mua nguyên liệu và dụng cụ, rồi nướng trong một cái lò đã có sẵn
      Nhưng nếu muốn làm bánh táo từ đầu, trước hết bạn phải tạo ra vũ trụ, và có lẽ bạn sẽ tạo ra vũ trụ đơn giản nhất có hỗ trợ bánh táo
      Toàn bộ stack có thể đơn giản hơn, nhưng bước cuối cùng là làm chiếc bánh thật sự có thể trở nên phức tạp hơn, và hương vị cũng chưa chắc là ngon nhất
      Đổi lại, bạn có được một chiếc bánh mà mình hiểu hoàn toàn từ nguyên lý thứ nhất
    • Điều đang nói ở đây có vẻ gần với khác biệt giữa “đơn giản (simple)” và “dễ (easy)”
      Có thể bạn sẽ thích bài nói này của Rich Hickey: https://paulrcook.com/blog/simple-made-easy
      Bạn có thể thêm tính năng để làm một thứ dễ tạo ra hoặc dễ triển khai hơn, nhưng chính phần thêm đó khiến tổng thể phức tạp hơn và khó hiểu hoặc khó truy vết vấn đề hơn
    • Liên quan đến bài này thì tôi không hiểu rõ bình luận này
      Ở cuối, tác giả nói rất rõ là ai cứ làm theo cách của người đó
      Hơn nữa, tác giả cũng nói mình không hài lòng khi dùng những hệ thống khó hiểu hoặc gây gánh nặng cho bản thân
      Có lẽ nên đọc cả phần sau đoạn đầu
  • Rất tuyệt!
    Tôi tuyệt đối không đồng ý với kiểu “các bạn cũng nên làm thế này!” :)
    Khả năng bảo trì là một trong những giá trị cốt lõi của tôi, nên tôi cũng tự bảo dưỡng xe đạp như bạn
    Nhưng với tôi nó không phải ưu tiên số 1 đến mức đó, nên những lựa chọn như thế này không hợp lý
    Chiếc laptop Framework là điểm thể hiện rõ khác biệt giữa chúng ta
    Bạn liên tục đạt mức 9 điểm ở phía DIY, còn tôi thì đảm bảo khả năng phục hồi bằng cách có một chiếc ThinkPad dự phòng 10 năm tuổi có thể chạy gấp Linux và Neovim bất cứ lúc nào; và nếu cả nó cũng hỏng, tôi tin rằng sau này vẫn sẽ có nhiều ThinkPad dưới 100 đô la
    Tôi mang theo đủ kiến thức khoa học máy tính và toán học để, nếu một ngày nào đó cần, có thể viết một parser từ Markdown sang HTML bằng các tổ hợp tử Haskell, chậm, không chính thức và đầy lỗi; nhưng tôi không nghĩ ngày đó sẽ đến sớm
    Nếu có thể, tôi muốn tuyển bạn
    Bạn sẽ là đối trọng hoàn hảo cho rất nhiều người đang nghiêng về hướng ngược lại

    • Tôi tò mò “nghiêng về hướng ngược lại” nghĩa là gì
  • Tôi đã đọc bài này rất vui
    Tác giả thành thật với bản thân và nghiêm túc với độc giả
    Không viện cớ, chỉ là chính mình, và cố đạt mục tiêu theo cách phù hợp với giá trị của mình và đem lại niềm vui
    Những giá trị đó không hợp với bạn cũng không sao, và thực ra đó là điều đẹp đẽ
    Giờ bạn đã có thêm manh mối về những con đường mình có thể khám phá
    Bài viết tử tế, khiêm nhường và chân thật; tôi nghĩ tác giả và bài viết làm thế giới tốt đẹp hơn một chút

    • Nghiêm túc thì đúng, nhưng thành thật với bản thân thì gần như hoàn toàn ngược lại
      Khiêm nhường cũng vậy
      Toàn bộ bài gần như là tự khen mình, và lác đác có những đoạn giống /r/confidentlyincorrect
    • Dễ xem bài này không phải là viết cho độc giả, mà là một bài tập và công cụ hỗ trợ để tác giả đạt các mục tiêu nội tại như học hỏi hay cảm giác kiểm soát
      Độc giả chỉ là đối tượng phụ, nên dù trải nghiệm đọc có khắc nghiệt kiểu Sparta đến đâu thì đó cũng không phải trọng tâm; trải nghiệm của tác giả mới là trọng tâm
    • Nếu đã đọc rồi, bạn có thể chia sẻ chút nội dung không?
      Có vẻ nhiều người đến từ nền tảng di động đã bỏ cuộc quá sớm
  • Tôi đọc lướt qua, và người này gần như chắc chắn đang troll chúng ta
    Trang web nói là dùng “plain HTML” theo đúng nghĩa đen, nhưng thực ra là plain text
    Ở đây hoàn toàn không có HTML để định dạng
    Không có tiêu đề, không có đoạn văn, không có danh sách, thậm chí không có cả thẻ a
    Phần HTML và CSS ít ỏi được thêm vào lại khiến trang render tệ hơn
    Tác giả là troll

    • Phần tử đó đã được đánh dấu là phần tử bị loại bỏ ít nhất từ 15 năm trước
  • “Tôi có những tiêu chuẩn rất cao và khác thường”, và nói rằng “script này chạy mỗi phút dưới dạng cronjob, nếu kho git đã được cập nhật thì sẽ build lại site”
    Tức là sẽ fetch một kho có lẽ chẳng có mấy commit trong một năm tới 525.600 lần/năm
    Tôi hiểu vì sao có chữ “khác thường” trong đó

    • Nếu không có commit mới thì git fetch về cơ bản gần như chỉ là một lần so sánh chuỗi [0], nên tôi nghĩ nó không tốn kém như cách người ta nói
      [0] https://stackoverflow.com/a/44476803
    • Trong tình huống này, thay vì “khác thường” thì gần với điên rồ hơn
      Đừng hỏi, phải nói thẳng ra
    • Ở đây đang giả định quá nhiều về cách triển khai của tôi hoạt động!
      Tất cả các kho git của tôi đều nằm trên cùng máy chủ đang host website
      git không fetch từ xa mà fetch cục bộ, nên về cơ bản là xong ngay lập tức
      Ngay cả nếu là fetch từ xa thì cũng vẫn ổn
      525.600 HTTP request mỗi năm còn ít lãng phí hơn heartbeat của NetworkManager
      Trên Arch, mặc định là 1 request heartbeat mỗi 30 giây
      Nhân tiện, một server nginx cơ bản với 8 CPU có thể xử lý hơn 500 nghìn HTTP request mỗi giây
  • Gửi OP:
    Tôi thấy có rất nhiều bài viết rất chỉ trích ở đây
    Nói một cách lịch sự thì… đừng bận tâm
    Những lời chỉ trích có thể đúng, nhưng ngành này đang chạy theo những “phải làm” và “đáng lẽ phải thế” mang tính tập thể, và nhanh chóng hướng tới sự ngu ngốc quy mô lớn
    Phần lớn trong số đó hiện chỉ có mức hợp lý ngang truyền thuyết đô thị
    Thứ ngày nay được gọi là “engineering” sẽ đáng để cười cho qua, nếu chúng ta không đang tích cực xây dựng tương lai trên nền đó
    Cha tôi từng là kỹ sư hàng không vũ trụ, và chắc ông sẽ trở mình dưới mộ nếu thấy thứ được gọi là engineering trong phát triển phần mềm hiện đại
    Đây là phần bình luận nên ai cũng có quyền nói, nhưng cá nhân tôi phải mất 25 năm trong ngành mới học được cách phớt lờ những tiếng nói ồn ào đó, và trong những cơ hội hiếm hoi có thể, làm điều mà tôi thấy là hợp lý
    Huống chi đây còn là site cá nhân, đúng không?
    Câu chữ cũ “dành cho những người điên rồ” trong quảng cáo của Apple giờ nghe cũng xa rời sự thật
    Internet đã thành ra thế này, và những nơi từng là startup giờ đã trở thành những quái vật doanh nghiệp lớn nhất trên địa hình, nên cũng chẳng có gì đáng ngạc nhiên
    Câu trích “người trong đấu trường” của Theodore Roosevelt dạo này thật sự rất đúng
    Cứ tiếp tục, OP, cứ tiếp tục…

    • Cảm ơn vì lời động viên! Tôi cố gắng đón nhận nhẹ nhàng các phê bình, đặc biệt là trên HN, đặc biệt là về bài viết trên website cá nhân của mình
      Website của tôi không phải một site được tối ưu hoàn hảo, mà là sân chơi thiêng liêng và độc đáo của riêng tôi
      Mọi thứ đều do tôi tự viết và tiến hóa theo thời gian
      Rõ ràng phong cách của tôi đôi khi khiến người ta khó chịu, và tôi đã quen với những phê bình như vậy
      Tôi cũng đưa ra những quyết định kỳ lạ để bẻ nội dung vào hình dạng mình thích, nhưng tôi nghĩ chính điều đó làm nội dung của tôi trở nên đáng mến
      Vì nó không giống những thứ khác ngoài kia
      Có thể còn những góc cạnh thô ráp, nhưng nó sẽ ngày càng tốt hơn khi tôi khám phá “hình thức cá nhân” :)
      Với tôi, website giống như một dự án nghệ thuật dài hạn
      Nó phải thể hiện tác giả, và trong trường hợp của tôi, site của tôi thể hiện tôi một cách đầy tự tin
  • Vì bạn đã khoe của bạn rồi, tôi cũng cho xem của tôi
    Website, game engine và webserver của tôi là một binary duy nhất
    Mã nguồn là 1000 dòng C, kích thước binary là 164KB
    Tôi không biết vì sao nó lại to chết tiệt như vậy
    Tôi cũng tự nhúng cả webserver
    Các server hiện có thêm quá nhiều độ phức tạp ẩn
    Trò interactive fiction bằng tiếng Đức là kết quả có thể xem ở đây: http://vmd34232.contaboserver.net/
    Không theo dõi, không quảng cáo, không mục đích thương mại

    • Hay đấy, trước đây tôi từng dùng parchment.js để load file z5 do inform7 tạo trên website của mình
      Có thể thử nén file thực thi bằng upx https://upx.github.io/
    • Làm tôi nhớ đến site của mình :)
      https://toldby.ai/
      Của tôi không phải single binary mà là asp.net
  • Tôi hoàn toàn đồng ý với mọi điểm được nêu trong bài, nhưng website này làm ví dụ thì hơi tệ
    Website được nói là “một binary duy nhất”, nhưng chiến lược deploy lại bao gồm việc compile thay vì chạy artifact binary
    Nói rằng sẽ không phụ thuộc vào github pages, nhưng lại phụ thuộc vào tài nguyên bên ngoài của openlibrary.org
    Nói rằng tự làm thì có thể tận dụng chuẩn mở, nhưng các file .html trong thoughts/ là cấu trúc plain text mang phần mở rộng giả
    Khi mọi người chọn con đường này, họ thường cố nhét mọi thứ vào lần tải trang ban đầu, nhưng ở đây có nhiều file tĩnh được phục vụ động
    Mã Golang không cache bất kỳ response nào và cũng không lưu template trong bộ nhớ
    File go.mod có nhiều dependency, mà tất cả trông như không được dùng
    Quan trọng nhất là không có thảo luận nào về việc tinh thần single binary có ưu điểm kỹ thuật gì so với hạ tầng hiện đại
    Cá nhân tôi nghĩ đây là một ý tưởng hay, nhưng đây là ví dụ tệ

    • Thực ra không phải single binary
      Đó là một binary duy nhất hoạt động cùng filesystem
      Toàn bộ nội dung nằm trên filesystem
      “Single binary” là một webserver Golang gọn nhẹ phục vụ nội dung từ filesystem
  • “Tiêu chuẩn rất cao và khác thường” cơ đấy; khác thường thì đúng, nhưng thiết kế website thành phẩm quá tệ đến mức không thể hiển thị văn bản cho vừa màn hình, nên tiêu chuẩn thực ra lại rất thấp