Các tập tin tĩnh ================ Phục vụ các tập tin tĩnh trên ổ đĩa ------------------------------------ Thư mục của dự án: :: config public favicon.ico robots.txt 404.html 500.html img myimage.png css mystyle.css js myscript.js src build.sbt Xitrum tự động phục vụ các tập tin tĩnh trong thư mực ``public``. URLs đến các tập tin này: :: /img/myimage.png /css/mystyle.css /css/mystyle.min.css Để dẫn đến chúng thì: :: Để phục vụ các tập tin bình thường trong môi trường phát triển cũng như bản rút gọn của nó trong môi trường sản phẩm (là mystyle.css và mystyle.min.css như trên) thì: :: Để gửi các tập tin tĩnh trên ổ đĩa từ action, sử dụng hàm ``respondFile``. :: respondFile("/absolute/path") respondFile("path/relative/to/the/current/working/directory") Để tối ưu hóa tốc độ phục vụ các tập tin tĩnh, bạn có thể bỏ qua các tập tin không cần thiết với bộ lọc regex. Nếu request url không khớp với pathRegex, Xitrum sẽ respond lỗi 404 cho request đó. Xem ``pathRegex`` trong ``config/xitrum.conf``. index.html fallback ------------------- Nếu không có route (không có action) cho URL ``/foo/bar`` (hoặc ``/foo/bar/``), Xitrum sẽ tìm các tập tin tĩnh ``public/foo/bar/index.html`` (nằm trong thư mục ``public``). Nếu tìm thấy tập tin, Xitrum sẽ respond nó về cho phía client. 404 và 500 ---------- 404.html và 500.html trong thư mục ``public`` được sử dụng khi không có route nào phù hợp hoặc có một lỗi trong quá trình thực thi. Nếu bạn muốn tự kiểm soát lỗi thì: :: import xitrum.Action import xitrum.annotation.{Error404, Error500} @Error404 class My404ErrorHandlerAction extends Action { def execute() { if (isAjax) jsRespond("alert(" + jsEscape("Not Found") + ")") else renderInlineView("Not Found") } } @Error500 class My500ErrorHandlerAction extends Action { def execute() { if (isAjax) jsRespond("alert(" + jsEscape("Internal Server Error") + ")") else renderInlineView("Internal Server Error") } } Response status được đặt thành 404 hoặc 500 trước khi action được thực thi, vì vậy bạn không cần phải đặt chúng một các thủ công. Cung cấp các tập tin tài nguyên trong classpath với WebJars convention ---------------------------------------------------------------------- WebJars ~~~~~~~ `WebJars `_ cung cấp rất nhiều các thư viện web mà bạn có thể sử dụng trong project. Ví dụ, nếu bạn muốn sử dụng `Underscore.js `_, hãy khai báo trong tập tin ``build.sbt`` của project như sau: :: libraryDependencies += "org.webjars" % "underscorejs" % "1.6.0-3" Sau đó trong tập tin giao diện .jade: :: script(src={webJarsUrl("underscorejs/1.6.0", "underscore.js", "underscore-min.js")}) Xitrum sẽ tự động sử dụng ``underscore.js`` cho môi trường phát triển và ``underscore-min.js`` cho môi trường sản phẩm. Kết quả như sau: :: /webjars/underscorejs/1.6.0/underscore.js?XOKgP8_KIpqz9yUqZ1aVzw Nếu bạn muốn sử dụng cũng một tập tin trong cả 2 môi trường: :: script(src={webJarsUrl("underscorejs/1.6.0/underscore.js")}) Khi thư viện này phụ thuộc vào thư viện kia, SBT sẽ tự động tải các thư viện liên quan về. Nếu thấy SBT không tải đúng phiên bản (có thể xác nhận bằng cách chạy lệnh ``sbt xitrumPackage`` rồi xem các tập tin trong thư mục ``target/xitrum/lib`` được tạo ra), bạn có thể ép SBT dùng đúng phiên bản bạn muốn bằng ``dependencyOverrides`` Ví dụ nếu bạn thấy SBT chọn thư viện jQuery phiên bản 2.x, mà bạn lại muốn dùng phiên bản 1.x để có thể hỗ trợ Internet Explorer 6, 7, hoặc 8, thì có thể khai báo như sau: :: dependencyOverrides += "org.webjars" % "jquery" % "1.11.3" Lưu resource file trong tập tin .jar với WebJars convention ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Nếu bạn là nhà phát triển thư viện và muốn phục vụ tập tin myimage.png từ trong thư viện của bạn, vốn đã là một tập tin .jar trong classpath, sau đó lưu myimage.png trong tập tin .jar với `WebJars `_ convention, ví dụ: :: META-INF/resources/webjars/mylib/1.0/myimage.png Để cung cấp tập tin: :: Trong cả môi trường, đường dẫn URL sẽ là: :: /webjars/mylib/1.0/myimage.png?xyz123 Respond một tập tin trong classpath ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Để respond một tập tin trong một classpath element (một tập tin .jar hoặc một thư mục), kể cả khi tập tin không được lưu với `WebJars `_ convention: :: respondResource("path/relative/to/the/classpath/element") Ex: :: respondResource("akka/actor/Actor.class") respondResource("META-INF/resources/webjars/underscorejs/1.6.0/underscore.js") respondResource("META-INF/resources/webjars/underscorejs/1.6.0/underscore-min.js") Cache ở phía client với ETag và max-age --------------------------------------- Xitrum tự động thêm `Etag `_ cho các tập tin tĩnh trên đĩa và classpath. ETags sử dụng cho các tập tin nhỏ như mã MD5 của file content. Chúng sẽ được cache để sử dụng sau. Key của cache entry là ``(file path, modified time)``. Bởi vì modified time ở các server khác nhau thì khác nhau, nên mỗi web server trong một cluster (nhóm) sẽ có riêng local ETag cache. Với các tập tin lớn, chỉ khi sửa đổi tập tin mới sử dụng Etag. Có vẻ không thực sự hoàn hảo bởi không thể đồng nhất các tập tin trên các server khác nhau vì chúng có nhiều ETag khác nhau, nhưng nó vẫn tốt hơn là không sử dụng ETag. ``publicUrl`` và ``webJarsUrl`` tự động thêm ETag vào URL khi chúng được generate. Ví dụ: :: webJarsUrl("jquery/2.1.1/jquery.min.js") => /webjars/jquery/2.1.1/jquery.min.js?0CHJg71ucpG0OlzB-y6-mQ Xitrum cũng đặt ``max-age`` và ``Exprires`` header thành `one year `_. Bạn không cần lo lắng rằng trình duyệt không chọn tập tin mới nhất khi bạn sửa đổi. Bởi vì khi một tập tin trên ổ đĩa được sửa, thuộc tính ``modified time`` của tập tin đó sẽ thay đổi, do đó URL tạo ra bởi ``publicUrl`` và ``webJarUrl`` cũng thay đổi theo. ETag cache của tập tin cũng sẽ thay đổi bởi cache key thay đổi. GZIP ---- Xitrum thực hiện việc nén GZIP tự động. Thuộc tính ``Content-Type`` tại header sẽ cho biết định dạng của respond là ``text/html`` hay ``xml/application`` v.v. Xitrum luôn tự động nén GZIP với các tập tin tĩnh, nhưng định dạng responses được tùy biến, để tối ưu hóa, Xitrum chỉ thực hiện GZIP với các response lớn hơn 1KB. Cache ở phía Server ------------------- Để hạn chế load tập tin từ đĩa, Xitrum cache các tập tin tĩnh nhỏ trong bộ nhớ với quy tắc LRU (Lần cuối sử dụng xa nhất). Xem ``small_static_file_size_in_kb`` và ``max_cached_small_static_files`` trong ``config/xitrum.conf``.