2012-02-07 39 views
21

Tôi đang cố gắng để có được nginx để làm việc với xử lý URI pushState dựa trên của mình rằng backbone.js quản lý cho tôi trong một ứng dụng Javascript.Viết lại nginx cho pushState-URL

Hiện tại, truy cập URI bằng một cấp, ví dụ: example.com/users hoạt động tốt, nhưng không phải là hai cấp hoặc sâu hơn URI, như example.com/users/all, được đề cập trong Backbone documentation:

Ví dụ, nếu bạn có một đường/tài liệu/100, máy chủ web của bạn phải có thể để phục vụ trang đó, nếu trình duyệt truy cập URL trực tiếp

Vì vậy, là xa làm quen với các tùy chọn viết lại nginx, tôi vẫn chắc chắn rằng tôi có thể làm điều gì đó như rewrite^/index.html; để chuyển hướng tất cả mọi thứ để index.html của tôi , nhưng loosi ng ra trên bất kỳ tệp tĩnh cuối cùng nào (hình ảnh, javascript & css) được lưu trữ trên cùng một máy chủ mà tôi cần để có thể truy cập.

Vì vậy, tôi nên làm gì thay vì cấu hình hiện tại, được hiển thị bên dưới, để thực hiện công việc này?

server { 
    listen 80; 
    server_name example.com; 

    location/{ 
     root /var/www/example.com; 
     try_files $uri /index.html; 
    } 

} 

Trả lời

19

Đây là những gì tôi đã làm cho đơn đăng ký của mình. Mỗi tuyến đường kết thúc bằng một '/' (trừ gốc rễ nó tự) sẽ phục vụ index.html:

location ~ ^/.+/$ { 
    rewrite .* /index.html last; 
    } 

Bạn cũng có thể thêm tiền tố tuyến đường của bạn:

Backbone.history.start({pushState: true, root: "/prefix/"}) 

và sau đó:

location ~ ^/prefix/ { 
    rewrite .* /index.html last; 
    } 

Hoặc xác định quy tắc cho từng trường hợp.

+3

đề nghị đầu tiên của bạn dường như đòi hỏi phải có dấu gạch chéo ... viết lại hoạt động khi tôi đi đến "/ search /" nhưng không phải "/ tìm kiếm" – andrhamm

+1

bạn sẽ giải quyết nó như thế nào nếu bạn không có dấu gạch chéo? –

+0

Có lẽ một regexp chấp nhận bất cứ điều gì trừ index.html? –

14

tôi quản lý nó như thế này:

#set root and index 
root /var/www/conferences/video/; 
index index.html; 

#route all requests that don't serve a file through index.html 
location/{ 
    if (!-e $request_filename){ 
     rewrite ^(.*)$ /index.html break; 
    } 
} 
+1

Tôi nhận 500 bằng cách sử dụng này. –

+0

cấu hình này hoạt động cho tôi! – llazzaro

30

tôi đã kết thúc đi với giải pháp này:

server { 

    listen 80; 
    server_name example.com; 
    root /var/www/example.com; 

    # Any route containing a file extension (e.g. /devicesfile.js) 
    location ~ ^.+\..+$ { 
     try_files $uri =404; 
    } 

    # Any route that doesn't have a file extension (e.g. /devices) 
    location/{ 
     try_files $uri /index.html; 
    } 

} 

Bằng cách này, ít nhất tôi vẫn nhận được đúng 404 lỗi nếu một tập tin không được tìm thấy .

+2

Cảm ơn, điều này đã làm việc cho tôi. Việc có một 404 thực sự là quan trọng - nếu một tệp JS được yêu cầu không tồn tại và HTML được trả về thay vào đó, trình duyệt sẽ cố gắng phân tích nó thành JS và ném tất cả các loại lỗi JS. Điều đó có thể làm hỏng một SPA. – ccnokes

+1

Điều này sẽ cao hơn. Đơn giản, thanh lịch và 404 cho tệp thực sự quan trọng – Igonato

7

Với mặt hàng đường dẫn ứng dụng:

/ 
/foo 
/foo/bar 
/foo/bar/baz 
/foo/bar/baz/123 
/tacos 
/tacos/123 

Sử dụng:

server { 
    listen 80; 
    server_name example.com; 
    root /var/www/example.com; 

    gzip_static on; 

    location/{ 
     try_files $uri $uri/ /index.html; 
    } 

    # Attempt to load static files, if not found route to @rootfiles 
    location ~ (.+)\.(html|json|txt|js|css|jpg|jpeg|gif|png|svg|ico|eot|otf|woff|woff2|ttf)$ { 
     try_files $uri @rootfiles; 
    } 

    # Check for app route "directories" in the request uri and strip "directories" 
    # from request, loading paths relative to root. 
    location @rootfiles { 
     rewrite ^/(?:foo/bar/baz|foo/bar|foo|tacos)/(.*) /$1 redirect; 
    } 
} 

Trong khi @Adam-Waite's answer công trình cho thư mục gốc và đường dẫn ở cấp độ gốc, sử dụng nếu trong bối cảnh vị trí được xem là một antipattern , thường thấy khi chuyển đổi chỉ thị kiểu Apache. Xem: http://wiki.nginx.org/IfIsEvil.

Các câu trả lời khác không bao gồm các tuyến đường có chiều sâu thư mục cho trường hợp sử dụng của tôi trong ứng dụng React tương tự sử dụng bộ phản ứng và bộ định tuyến HTML5 được kích hoạt. Khi một tuyến đường được tải hoặc làm mới trong "thư mục" chẳng hạn như example.com/foo/bar/baz/213123, tệp index.html của tôi sẽ tham chiếu tệp js ở đường dẫn tương đối và giải quyết thành example.com/foo/bar/baz/js/app.js thay vì example.com/js/app.js.

Đối với trường hợp với độ sâu thư vượt cấp độ đầu tiên như /foo/bar/baz, lưu ý thứ tự của các thư mục được khai báo trong chỉ thị @rootfiles: những con đường dài nhất có thể cần phải đi đầu tiên, tiếp theo là con đường nông tiếp theo và cuối cùng /foo/bar/foo.

0

Kể từ khi có thể có ajax yêu cầu api, những bộ quần áo sau đây cho trường hợp này,

server { 
    listen 80; 
    server_name example.com; 
    root /var/www/example.com; 

    # Any route containing a file extension (e.g. /devicesfile.js) 
    location ~ ^.+\..+$ { 
     try_files $uri =404; 
    } 

    # Any route that doesn't have a file extension (e.g. /devices) 
    location/{ 
     try_files $uri /index.html; 
    } 

    # The location block above provides the shortest prefix, of length one, 
    # and so only if all other location blocks fail to provide a match, 
    # this block will be used. 

    # Ajax api starts with /v1/ will be proxied 
    location /v1/ { 
     proxy_pass http://proxy; 
    } 
} 
Các vấn đề liên quan