- Rwf là một framework toàn diện để xây dựng ứng dụng web bằng Rust, dựa trên mẫu MVC cổ điển và cung cấp sẵn các tính năng cần thiết để tạo web app nhanh và an toàn
- Các tính năng mặc định bao gồm máy chủ HTTP, ORM cho truy vấn PostgreSQL, template động, xác thực và phiên người dùng, middleware, tác vụ nền và tác vụ theo lịch, cùng migration cơ sở dữ liệu
- Cũng cung cấp REST framework tích hợp hỗ trợ tuần tự hóa JSON, WebSockets, hosting tệp tĩnh, cấu hình theo môi trường, logging và metrics, cùng CLI
- Tích hợp chặt chẽ với Hotwired Turbo để tạo SPA do backend điều khiển, đồng thời cung cấp máy chủ WSGI để migrate từ Django/Flask và máy chủ Rack để migrate từ Rails
- Hiện đang ở trạng thái beta và tìm kiếm những người dùng sớm; tác giả cho biết phần lớn tính năng đã ở trạng thái tốt và tài liệu đủ để sử dụng
Framework web MVC cho Rust
- Rwf là một framework toàn diện để xây dựng ứng dụng web bằng Rust
- Được viết theo mẫu MVC(model-view-controller) cổ điển
- Hướng tới việc mặc định bao gồm các tính năng cần thiết để dễ dàng tạo web app nhanh và an toàn
- Tài liệu được cung cấp tại tài liệu chính thức
Tính năng cung cấp
- Máy chủ và xử lý request
- Dữ liệu và cấu trúc ứng dụng
- Cung cấp ORM thân thiện với người dùng để dễ dàng tạo truy vấn PostgreSQL
- Hỗ trợ migration cơ sở dữ liệu
- Cung cấp Dynamic templates
- Bao gồm Authentication và phiên người dùng tích hợp
- API và xử lý tác vụ
- Vận hành và công cụ phát triển
- Hỗ trợ cấu hình theo môi trường
- Cung cấp logging và metrics
- Bao gồm CLI
Hỗ trợ Hotwired Turbo và migrate
Bắt đầu nhanh
- Tạo một ứng dụng nhị phân Rust và thêm
rwf vào dependencies để sử dụng
cargo add rwf
- Ứng dụng cơ bản dùng
rwf::prelude::* và rwf::http::Server để định nghĩa controller và route
use rwf::prelude::*;
use rwf::http::Server;
#[controller]
async fn index() -> Response {
Response::new().html("Welcome to Rwf!
")
}
#[tokio::main]
async fn main() {
Server::new(vec![
route!("/" => index),
])
.launch()
.await
.unwrap();
}
Ví dụ và trạng thái dự án
- Có thể xem các trường hợp sử dụng phổ biến trong examples
- Rwf hiện đang ở trạng thái beta và đang tìm kiếm những người dùng sớm
- Tác giả cho biết phần lớn tính năng đã ở trạng thái tốt và tài liệu đủ để sử dụng
- Rất hoan nghênh đóng góp; hướng dẫn có tại CONTRIBUTING, hướng dẫn cấu trúc mã tại ARCHITECTURE, và danh sách tính năng mong muốn tại ROADMAP
1 bình luận
Các ý kiến trên Hacker News
Việc ra mắt có vẻ sẽ tạo cảm giác khá phi thực tế, xin chúc mừng. Điều lớn nhất tôi học được sau thời gian dài làm web MVC với Rails là framework phải kiềm chế mạnh logic nghiệp vụ ở tầng model
Tôi nghĩ tốt nhất là không đưa các callback mà Active Record nói tới vào model dữ liệu, chẳng hạn các hook như
afterCreate. Hiện ORM chưa có, nhưng nếu nó nằm trong roadmap thì tôi nghĩ không có còn hơnTuy nhiên điều này chỉ hoạt động đúng khi service, tức tầng logic nghiệp vụ, được khuyến khích mạnh mẽ. Hầu hết các ứng dụng Rails của tôi cấu trúc command/service object bằng các gem như Interactor
Tôi cho rằng chỉ MVC, và do đó chỉ cấu hình mặc định của Rails, không lý tưởng để viết ứng dụng có thể vận hành được vì thiếu tầng service. Và tôi cũng tò mò vì sao không tận dụng ORM hoặc query builder hiện có của cộng đồng. Tôi vẫn chưa viết một dòng Rust nào, nhưng ngày càng tò mò hơn
Tôi nghĩ service hầu như chỉ nên là những đoạn mã cụ thể phức tạp hơn được kích hoạt từ model. Controller mỏng, model dày là tốt nhất về mặt debug, tổ chức và khả năng khám phá; còn dùng nhiều service thì theo kinh nghiệm của tôi dễ sinh ra rất nhiều spaghetti code
Ngay cả từ góc nhìn hướng đối tượng thuần túy, model là đối tượng nền tảng định nghĩa entity.
Usernên biết mọi thứ cần biết về chính nó, và giao tiếp với các entity khác bằng messageTuy nhiên tôi đồng ý về callback. Callback tạo ra nhiều tác dụng phụ kỳ lạ và khiến việc debug thực sự khó khăn
Có thể làm như vậy, nhưng sẽ khá khó suy luận entity có thể được cập nhật bằng những cách nào. Vì bất kỳ số lượng procedure nào cũng có thể cập nhật nó và mỗi cái có thể có quy tắc nghiệp vụ riêng. Nếu vậy thì cứ để procedure ghi trực tiếp vào cơ sở dữ liệu và bỏ model đi cũng được
Nhưng sau hơn 20 năm phát triển phần mềm, tôi đi đến kết luận rằng đóng gói là gánh nặng chứ không phải tính năng, và dữ liệu nên được tách khỏi các thao tác thực hiện trên dữ liệu đó. Điều này được gọi là thiết kế hướng dữ liệu hoặc lập trình hướng dữ liệu, và không chỉ mình tôi đi đến kết luận này
Cũng có những cách modeling khác mở rộng tốt, và có vài bài viết liên quan. Có bài của người Basecamp: https://dev.37signals.com/vanilla-rails-is-plenty/
Tất nhiên cách này rất hướng đối tượng nên tôi cũng không quá thích. Ví dụ framework Phoenix của Elixir dùng context để gom các chức năng liên quan, nói đơn giản có thể xem như facade
Nếu thích service thì có thể dùng, nhưng nói MVC không đủ cho cấp production thì tôi thấy hơi lệch. Xử lý các quy trình nghiệp vụ nặng bằng model callback là không tốt, nhưng với các việc nhỏ để chỉnh dữ liệu về đúng dạng thì khá ổn
Có lẽ tôi cũng thiên lệch vì kinh nghiệm lập trình của tôi bắt đầu từ PHP cho Wordpress, nơi dùng hook rất rộng rãi
Thứ tôi làm có đặc tả bảng có thể chuyển thành định nghĩa SQL hoặc xuất ra form HTML được định dạng đẹp. Một controller riêng xử lý mọi kết nối DB và thao tác CRUD, kèm các hook trước/sau để dễ dàng tham chiếu chéo với bảng khác và ràng buộc khi cần
Nó hoạt động khá tốt, nhưng nếu có thể thì tôi sẽ chuyển sang Laravel ngay lập tức
Nếu là REST framework thì mặc định tôi kỳ vọng nó có thể tạo định nghĩa Swagger/OpenAPI. Tôi xem đó là một trong những killer feature của FastAPI
Tôi cũng không hiểu rõ vì sao lại tự làm ORM thay vì tích hợp với ORM hiện có như diesel.rs, và vì sao tự tạo ngôn ngữ template thay vì chọn một template engine hiện có phổ biến
Ngoài ra thì dự án trông thật sự thú vị và tôi sẽ tiếp tục theo dõi
[0] https://diesel.rs/
[1] https://crates.io/categories/template-engine
Nhìn chung đó là một nỗ lực đầu tiên tốt để khớp kiểu dữ liệu cơ sở dữ liệu với kiểu Rust, nhưng ORM cần linh hoạt hơn và dễ dùng hơn. Vì nó phải làm cho việc viết query dễ hơn, chứ không phải khó hơn :)
Về template, việc tự tạo ngôn ngữ của riêng mình gần như là nghi thức gia nhập câu lạc bộ nerd trên 30 tuổi. Tôi chưa đọc Dragon Book, nhưng hồi đi học rất muốn được học môn đó. Cùng một thứ luôn có nhiều cách triển khai, và tôi thấy việc dùng triển khai này, vốn bắt chước rất sát những gì ERB của Rails làm, là hợp lý
Ở góc nhìn SRE, tôi thấy quan tâm đến https://levkk.github.io/rwf/migrating-from-python/. Một mặt, việc làm được điều này thật sự rất ấn tượng, nhưng từ góc nhìn SRE coi trọng độ ổn định thì trong lòng tôi phải hét lên
Khi quy mô lớn lên, việc này nên do reverse proxy như Caddy, Nginx, Traefik xử lý
Viết một WSGI server ổn định là có thể, và cũng không quá khó nếu chỉ cần chú ý một chút đến các chi tiết như số luồng, vacuum, hay khởi động lại sau mỗi n request như php-fpm ngày xưa. Về cơ bản, nếu triển khai phần lớn các tùy chọn mà uwsgi có thì xem như đang đi đúng hướng. Trong roadmap có việc làm cho Rwf có thể so sánh với việc chạy Gunicorn
Cách chọn tên thật sự đỉnh. Đó cũng là một cách để leo lên đầu kết quả tìm kiếm :P
Nói nghiêm túc thì làm rất tốt. Tạo ra một framework tốt là một công việc lớn đến đáng ngạc nhiên, và luôn thú vị khi thấy mọi người khám phá không gian thiết kế và thử các ý tưởng mới
rwfRustOnWeb.com cũng có thể mua với giá $10 :) Chỉ nói vậy thôi
Tôi thích cách diễn đạt “hãy nghĩ đến Rails, không phải Flask”. Các ngôn ngữ kiểu tĩnh cần có nhiều hơn hoặc tốt hơn những framework có chính kiến kiểu Rails/Django
Làm tốt lắm. Rất đáng thử để được giới thiệu trên https://www.arewewebyet.org/
Hay! Django/Rails được làm bằng một ngôn ngữ hạng nhất
Góp ý là
async-traitgiờ chắc đã ổn định rồi nên có thể không cần macro nữa, và sẽ tốt nếu thêm tích hợp OpenTelemetry để mặc định có metrics và tracing. Với target Linux thì cũng nên dùng jemallocTôi dự định thêm các tag OpenTelemetry vào các hàm của crate
tracing. jemalloc có thể được thêm vào ứng dụng nhị phân sử dụng Rwf, không cần đưa vào như dependency của thư viện[1] https://blog.rust-lang.org/2023/12/21/async-fn-rpit-in-trait...
Tôi đã thử học Rust nhưng bỏ cuộc ngay từ đầu. Từ C#, C/C++, Java, Python chuyển sang nên Rust cảm giác rất lạ
Thứ khiến tôi nản không phải bản thân sự lạ lẫm, mà là tốc độ hoàn thành một công việc chậm hơn so với các ngôn ngữ như C#, Java, Python
Dạo này tôi chủ yếu làm web development nên tính dễ dùng và năng suất là ưu tiên hàng đầu. Rust có thể nhỉnh hơn một chút về throughput và tốc độ, nhưng nhìn các benchmark framework web hiện đại thì C# và Java cũng làm khá tốt ở mặt này
Tôi không muốn điều này bị hiểu là phê phán Rust hay hạ thấp thành tựu lớn là tạo một MVC framework từ đầu. Nó gần với ý “công cụ phù hợp cho công việc phù hợp” hơn
Để vượt qua đường cong học tập cần có động lực mạnh. Có thể là bạn phải dùng ngôn ngữ đó, hoặc bị thu hút bởi lợi ích của type system và độ an toàn, hoặc có lý do cụ thể của riêng mình
Nếu không có động lực như vậy thì hoàn toàn ổn. Ban đầu tôi cũng không có, nên các lần thử học đầu tiên không đi xa. Như nhiều người cảm nhận, Rust mất nhiều thời gian hơn Java hay Python để hoàn thành việc, và đòi hỏi suy nghĩ nhiều hơn từ phía trước. Trong một số tình huống thì điều đó đáng giá, nhưng nếu không rõ vì sao mình nên chấp nhận trade-off đó thì không có lý do mạnh để tiếp tục
Gần đây tôi bỏ loader JS của webpack và dùng một loader Rust nhanh hơn 50 lần, nên tôi cũng đã mê Rust. Rust đem lại cải thiện hiệu năng rất lớn, và hiện giờ C++ và Rust là hai ngôn ngữ tôi thích nhất
Tôi đã đánh giá tất cả các ứng viên thường được nhắc đến cho công việc backend Rust và làm các prototype nhỏ. Đến giờ, dù vẫn ở mức thấp hơn mong muốn, tôi miễn cưỡng đồng ý với kết luận chung rằng nhìn tổng thể Axum là lựa chọn tốt nhất
Các ứng viên khác là Loco và Rocket. Loco thì quá giống Rails, còn Rocket thì sau khi dùng Rust nhiều hơn, các macro bắt đầu khiến tôi khó chịu
Framework này có vẻ khớp hoàn hảo với tiêu chí của tôi là “có sẵn pin nhưng không quá áp đặt”. Một bổ sung tốt cho hệ sinh thái