Xin chào các độc giả của 2coffee.dev. Một tuần nữa lại trôi qua, nhanh đến nỗi mà khi nhìn lại trang chủ, không ngờ rằng mình lại ngừng viết trong một khoảng thời gian dài như thế. Thành thật mà nói tuần vừa rồi khá là bận rộn, tôi vừa tập trung phát hành một bản cập nhật quan trọng cho sản phẩm tại nơi đang làm việc. Có lẽ vì thế mà khái niệm thời gian đã tạm thời bị vùi lấp. Hmm... Phải nghĩ ra xem có gì để kể không chứ!
Song song với việc đó, tôi đang cố gắng tối ưu hoá lại trải nghiệm người dùng cho trang blog. Bằng cách sửa một số lỗi tồn đọng từ trước, làm cho đường dẫn đến liên kết hiển thị rõ ràng hơn, thêm một vài hiệu ứng vui mắt và bổ sung thêm một số tinh chỉnh giao diện. Chỉ nhiêu đấy thôi mà cũng ngốn thời gian ra mặt. Sáng đi làm, tối về quay cuồng với guồng tối ưu không hồi kết.
Một vấn đề mới phát sinh trong lúc tối ưu hoá là quá trình render markdown lại gặp vấn đề. Cụ thể là khi sử dụng một số thẻ mới thì trang web bị vỡ giao diện. Chà! Kiếp nạn này bao giờ mới hết. Nếu nhớ không nhầm, phải có 2-3 bài viết nói về những vấn đề đã gặp phải với markdown. Cũng có khả năng là lúc trước đã quá xem nhẹ nên bây giờ phải đối mặt với những vấn đề như thế này.
Đằng nào cũng phải đụng đến nên quyết tâm sửa lại luôn một thể. Không sử dụng showdown nữa mà chuyển sang một thư viện khác có tên là marked.js. Chọn luôn tiêu chuẩn gfm của Github để định dạng. Làm như vậy sẽ hạn chế được những thay đổi sau này.
Trong rất nhiều bài viết trước đây, tôi có sử dụng một thẻ markdown để hiển thị hình ảnh thumbnail cho bài viết. Nhưng từ sau khi đập đi xây lại, phần hiển thị hình ảnh thumbnail đã được viết trực tiếp vào trong code. Còn phần hình ảnh đầu bài viết dùng code để tạm ẩn đi. Bây giờ chuyển sang tính năng mới, cần phải loại bỏ hết thẻ markdown bị thừa.
Nên công việc tiếp theo là cần sửa lại hàng loạt bài viết. Trang web có cách vận hành khá thú vị, đó là trang quản lý hết sức sơ sài. Không như những phiên bản trước có một trang quản lý "xịn sò", phiên bản này chỉ có một vài tính năng vừa đủ như tạo/cập nhật bài viết. Để truy cập vào trang chỉnh sửa, chỉ cần thêm một postfix /edit
vào sau đường dẫn đến bài viết thì nó sẽ dẫn đến trang chỉnh sửa. Tất nhiên là trước đó phải đăng nhập bằng tài khoản có quyền admin, còn không thì bạn sẽ thấy một thông báo lỗi rằng trang không khả dụng.
Như vậy đếm sơ sơ có hơn 300 bài viết cần phải sửa lại, tương đương phải thực hiện lại các thao tác chỉnh sửa hơn 300 lần 🤮. Chưa kể mạng không phải lúc nào cũng tải được trang web trong vòng 3s. Vì thế lại một lần nữa, tôi tìm đến giải pháp CLI.
Ý tưởng về một ứng dụng CLI giúp quản lý bài viết không mới. Thực tế từ lúc xây dựng phiên bản mới cho trang blog tôi đã nghĩ đến việc quản lý bài viết bằng những dòng lệnh. Mỗi bài viết là một file markdown, lưu trữ ở dưới máy, chỉnh sửa xong thì dùng một lệnh để xuất bản các bài viết lên là được. Vừa nhanh mà vừa tiện. Nhưng đến khi nghiêm túc ngồi "break" ra những thứ cần làm thì chao ôi... có lẽ mình nên làm cách đơn giản hơn. Hãy nhớ lại sứ mệnh của 2coffee.dev, mang đến những bài viết chất lượng chứ không phải là cặm cụi nửa tháng mà vẫn chưa ra ngô ra khoai.
Giờ đây thời cơ đã đến, đã có những thứ xây dựng từ trước và tận dụng lại được. Ứng dụng CLI xuất phát từ nhu cầu: quản lý được bài viết và chỉnh sửa phải nhanh gọn. Vì thế chức năng cơ bản chỉ cần kéo (pull) được danh sách bài viết về, chỉnh sửa hàng loạt rồi đẩy (push) bài viết lên, lấy cảm hứng tương tự như cách dùng git.
Nếu bạn còn nhớ về bài viết ứng dụng cli để tối ưu hoá hình ảnh, tôi đã tạo ra một cli xử lý hình ảnh từ trước đó. Ban đầu định viết tiếp phần code mới vào đây nhưng thực tế phải viết thêm nhiều code nên cách nhanh nhất là viết vào chung với dự án page-fresh - vốn là trang blog này. Nó có chứa nhiều mã giúp lấy dữ liệu từ máy chủ, mình có thể tận dụng để không cần phải viết lại nữa.
Để đơn giản hết mức có thể, các tệp pull.ts
, push.ts
... để đại diện cho lệnh pull
và push
. pull
để kéo bài viết về còn push
để xuất bản bài viết. Mỗi lúc cần chạy thì cú pháp sử dụng sẽ là:
$ deno run -A pull.ts
$ deno run -A push.ts
Để hỗ trợ thêm cờ (flag), kiểu như là --change
, --force
giống như các ứng dụng CLI chính thống thì cứ gõ thêm vào deno run
rồi dùng Deno.args
để phân tích dữ liệu và xử lý.
const args = Deno.args;
const flags: { [key: string]: string | boolean } = {};
for (let i = 0; i < args.length; i++) {
if (args[i].startsWith("--")) {
const flag = args[i].substring(2); // loại bỏ '--'
if (i + 1 < args.length && !args[i + 1].startsWith("--")) {
flags[flag] = args[i + 1]; // lấy giá trị của flag
i++;
} else {
flags[flag] = true;
}
}
}
pull.ts
chứa mã lấy dữ liệu về. Khi chạy lệnh pull
nó sẽ kéo tất cả nội dung bài viết về và lưu lại dưới dạng tệp *.md
, với * là url của bài viết.
$ deno run -A cli/commands/pull.ts
ℹ Kéo về 212 bài viết, bỏ qua 0 bài viết, thay đổi 0 bài viết (VI)
ℹ Kéo về 202 bài viết, bỏ qua 0 bài viết, thay đổi 0 bài viết (EN)
✔ Đã xong
Sau đó tôi tạo thêm một tệp article.ts
để kiểm tra các bài viết đã thay đổi ở dưới máy. Đó là các bài viết được chỉnh sửa và chuẩn bị để xuất bản. Ví dụ:
$ deno run -A cli/commands/article.ts --change
ℹ Các thay đổi của bài viết tiếng Việt:
- 1-thang-hoc-rust-nhung-dieu-co-ban-cua-ngon-ngu-lap-trinh-rust.md
ℹ Các thay đổi của bài viết tiếng Anh:
- a-compilation-of-free-and-high-quality-serverless-databases.md
✔ Đã xong
Sau khi sửa xong, dùng lệnh push
để xuất bản một bài chỉ định trước. Ví dụ:
$ deno run -A cli/commands/push.ts --file data/1-thang-hoc-rust-nhung-dieu-co-ban-cua-ngon-ngu-lap-trinh-rust.md
Hoặc push
toàn bộ những bài đã sửa. Ví dụ:
$ deno run -A cli/commands/push.ts --change
ℹ Tìm thấy 1 bài viết tiếng Việt, 1 bài viết tiếng Anh
- 1-thang-hoc-rust-nhung-dieu-co-ban-cua-ngon-ngu-lap-trinh-rust.md
- a-compilation-of-free-and-high-quality-serverless-databases.md
✔ Đã cập nhật 1-thang-hoc-rust-nhung-dieu-co-ban-cua-ngon-ngu-lap-trinh-rust.md
✔ Đã cập nhật a-compilation-of-free-and-high-quality-serverless-databases.md
✔ Đã xong
Ngay lập tức các bài viết tìm thấy được đẩy lên. Trong push.ts
có một hàm gọi API để xuất bản bài viết với quyền admin. Nên buộc phải có cookie của tài khoản quản trị. Cookie có thể lấy bằng cách vào trang web sao chép rồi dán thẳng vào trong code. Nhưng cookie có thời hạn khá ngắn cho nên viết thêm một tệp login.ts
xử lý việc lấy cookie sẽ tiện hơn cho quá trình sử dụng sau này.
Cơ chế login cũng đơn giản. Bên trong login.ts
khởi tạo một server cục bộ lắng nghe ở cổng 3069
, bên trong có 1 endpoint tên là /callback
. Khi gọi vào 2coffee.dev, ví dụ như là https://2coffee.dev/auth?redirect_url=http://localhost:3069/callback?token=<cookie>
thì nó sẽ gọi lại vào endpoint /callback
kèm theo token
chính là cookie của admin, với điều kiện là admin đã đăng nhập từ trước. Lưu lại token vào certificate.txt
để sử dụng cho các lần tiếp theo.
Kết hợp tất cả lại, tôi đã có 4 tệp login.ts
, pull.ts
, push.ts
, articles.ts
. Nếu cứ gõ đi gõ lại deno run
sẽ rất dài, vì thế hãy nghĩ cách tối giản lại. Một lệnh gì đó giống như như là 2cf
, khi đó chỉ cần gõ 2cf login
, 2cf pull
, 2cf push
... tiện hơn biết bao.
Tạo một tệp cli.sh
ngay trong thư mục của dự án page-fresh:
#!/bin/bash
case $1 in
login)
cd /Users/hoaitx/src/hoaitx/page-fresh && deno run -A cli/commands/login.ts $2
;;
pull)
cd /Users/hoaitx/src/hoaitx/page-fresh && deno run -A cli/commands/pull.ts $2
;;
push)
cd /Users/hoaitx/src/hoaitx/page-fresh && deno run -A cli/commands/push.ts $2
;;
article)
cd /Users/hoaitx/src/hoaitx/page-fresh && deno run -A cli/commands/article.ts $2
;;
*)
echo "Usage: $0 {login|pull|push|article}"
;;
esac
Như vậy lúc này chỉ cần ./cli.sh login
, ./cli.sh pull
...
Ở đây tôi dùng Mac và cài Oh My Zsh nên có thể đặt alias cho dòng lệnh. Tiếp tục mở tệp .zshrc
và thêm vào function 2cf()
.
function 2cf() {
/Users/hoaitx/src/hoaitx/page-fresh/cli.sh "$@"
}
Reload lại .zshrc
:
$ source ~/.zshrc
Thế là đã xong, từ giờ đã có thể dùng lệnh 2cf
:
$ 2cf login
$ 2cf pull
$ 2cf push
...
Cuối cùng để cho CLI trở nên sinh động hơn, tôi sử dụng thêm 2 package là ora và chalk. ora dùng để tạo hiệu ứng xử lý còn chalk để thay đổi màu sắc của văn bản trong terminal.
Trong tương lai, tôi sẽ tiếp tục phát triển ứng dụng CLI này với mục đích thay thế hoàn toàn trang quản trị và tiến tới một vài tính năng tự động khác.
Bí mật ngăn xếp của Blog
Là một lập trình viên, bạn có tò mò về bí mật công nghệ hay những khoản nợ kỹ thuật về trang blog này? Tất cả bí mật sẽ được bật mí ngay bài viết dưới đây. Còn chờ đợi gì nữa, hãy bấm vào ngay!
Đăng ký nhận thông báo bài viết mới
Xin chào, tôi tên là Hoài - một anh Dev kể chuyện bằng cách viết ✍️ và làm sản phẩm 🚀. Với nhiều năm kinh nghiệm lập trình, tôi đã đóng góp một phần công sức cho nhiều sản phẩm mang lại giá trị cho người dùng tại nơi đang làm việc, cũng như cho chính bản thân. Sở thích của tôi là đọc, viết, nghiên cứu... Tôi tạo ra trang Blog này với sứ mệnh mang đến những bài viết chất lượng cho độc giả của 2coffee.dev.Hãy theo dõi tôi qua các kênh LinkedIn, Facebook, Instagram, Telegram.
Bình luận (4)