Lưu trữ trang web tĩnh S3 Định tuyến tất cả các đường dẫn đến Index.html


250

Tôi đang sử dụng S3 để lưu trữ một ứng dụng javascript sẽ sử dụng HTML5 PushStates. Vấn đề là nếu người dùng đánh dấu bất kỳ URL nào, nó sẽ không giải quyết bất cứ điều gì. Điều tôi cần là khả năng nhận tất cả các yêu cầu url và cung cấp chỉ mục gốc.html trong nhóm S3 của tôi, thay vì chỉ thực hiện chuyển hướng đầy đủ. Sau đó, ứng dụng javascript của tôi có thể phân tích cú pháp URL và phục vụ trang thích hợp.

Có cách nào để bảo S3 phục vụ index.html cho tất cả các yêu cầu URL thay vì thực hiện chuyển hướng không? Điều này sẽ tương tự như thiết lập apache để xử lý tất cả các yêu cầu đến bằng cách cung cấp một index.html như trong ví dụ này: https://stackoverflow.com/a/10647521/1762614 . Tôi thực sự muốn tránh chạy một máy chủ web chỉ để xử lý các tuyến này. Làm mọi thứ từ S3 rất hấp dẫn.


bạn đã tìm thấy giải pháp chưa?
w2lame

Câu trả lời:


301

Thật dễ dàng để giải quyết nó mà không cần hack url, với sự trợ giúp của CloudFront.

  • Tạo nhóm S3, ví dụ: phản ứng
  • Tạo các bản phân phối CloudFront với các cài đặt này:
    • Đối tượng gốc mặc định : index.html
    • Tên miền gốc : Tên miền xô S3, ví dụ: Reac.s3.amazonaws.com
  • Chuyển đến tab Trang lỗi , nhấp vào Tạo phản hồi lỗi tùy chỉnh :
    • Mã lỗi HTTP : 403: Bị cấm (404: Không tìm thấy, trong trường hợp Trang web tĩnh S3)
    • Tùy chỉnh phản hồi lỗi : Có
    • Đường dẫn trang phản hồi : /index.html
    • Mã phản hồi HTTP : 200: OK
    • Nhấp vào Tạo

8
Cảm ơn. Câu trả lời tốt nhất cho đến nay.
jgb

và những gì không rõ ràng bạn giữ vị trí để bạn có thể thực hiện định tuyến "tự nhiên".
Lukasz Marek Sielski

5
điều này hoạt động như một cơ duyên đối với tôi, chỉ có mã lỗi tùy chỉnh tôi cần là 404 chứ không phải 403
Jeremy S.

4
Một chút hack, nhưng hoạt động rất tốt :) Thật tuyệt nếu CloudFront chỉ cho phép chúng tôi ánh xạ một phạm vi đường dẫn đến tệp S3 (không có chuyển hướng).
Bob

3
Điều này không làm việc cho tôi. Giải pháp này luôn chuyển hướng đến trang chủ và không phải là trang chính xác ...
Jim

201

Cách tôi có thể làm cho điều này hoạt động như sau:

Trong phần Chỉnh sửa quy tắc chuyển hướng của Bảng điều khiển S3 cho miền của bạn, hãy thêm các quy tắc sau:

<RoutingRules>
  <RoutingRule>
    <Condition>
      <HttpErrorCodeReturnedEquals>404</HttpErrorCodeReturnedEquals>
    </Condition>
    <Redirect>
      <HostName>yourdomainname.com</HostName>
      <ReplaceKeyPrefixWith>#!/</ReplaceKeyPrefixWith>
    </Redirect>
  </RoutingRule>
</RoutingRules>

Điều này sẽ chuyển hướng tất cả các đường dẫn dẫn đến 404 không được tìm thấy đến tên miền gốc của bạn với phiên bản băm của đường dẫn. Vì vậy, http://yourdomainname.com/posts sẽ chuyển hướng đến http://yourdomainname.com/#!/posts miễn là không có tệp tại / bài viết.

Tuy nhiên, để sử dụng HTML5 PushStates, chúng tôi cần thực hiện yêu cầu này và thiết lập thủ công PushState phù hợp dựa trên đường dẫn băm. Vì vậy, hãy thêm phần này vào đầu tệp index.html của bạn:

<script>
  history.pushState({}, "entry page", location.hash.substring(1));
</script>

Cái này lấy hàm băm và biến nó thành một PushState HTML5. Từ thời điểm này, bạn có thể sử dụng PushStates để có các đường dẫn không băm trong ứng dụng của mình.


4
Giải pháp này hoạt động rất tốt! Trong thực tế angularjs sẽ tự động thực hiện lịch sử PushState nếu chế độ html được cấu hình.
wcandillon

1
Điều này sẽ thất bại với phiên bản IE cũ hơn nếu bạn có các thông số GET được bao gồm trong các url của mình, đúng không? Làm thế nào để bạn có được xung quanh vấn đề đó?
clexmond

3
Cảm ơn! Điều này làm việc tốt cho tôi trên xương sống với một điều chỉnh nhỏ. Tôi đã thêm vào một kiểm tra cho các trình duyệt cũ hơn: <script language="javascript"> if (typeof(window.history.pushState) == 'function') { window.history.pushState(null, "Site Name", window.location.hash.substring(2)); } else { window.location.hash = window.location.hash.substring(2); } </script>
AE Gray

10
Thành công với react-routergiải pháp đó bằng cách sử dụng HTML5 PushStates và<ReplaceKeyPrefixWith>#/</ReplaceKeyPrefixWith>
Felix D.

5
Nó không hoạt động safari và là một vấn đề lớn với chiến lược triển khai. Viết một js nhỏ để chuyển hướng là một cách tiếp cận tồi tàn. Ngoài ra, số lượng chuyển hướng cũng là một vấn đề. Tôi đang cố gắng tìm hiểu xem có cách nào để tất cả các url S3 trỏ đến index.html luôn không.
moha297

129

Có một vài vấn đề với cách tiếp cận dựa trên S3 / Redirect được đề cập bởi những người khác.

  1. Chuyển hướng Mutlipl xảy ra khi đường dẫn ứng dụng của bạn được giải quyết. Ví dụ: www.myapp.com/path/for/test được chuyển hướng là www.myapp.com/#/path/for/test
  2. Có một nhấp nháy trong thanh url khi '#' đến và đi do hành động của khung SPA của bạn.
  3. Các seo bị ảnh hưởng bởi vì - 'Này! Google của nó buộc phải chuyển hướng '
  4. Safari hỗ trợ cho ứng dụng của bạn đi quăng.

Giải pháp là:

  1. Hãy chắc chắn rằng bạn có lộ trình chỉ mục được cấu hình cho trang web của bạn. Chủ yếu là index.html
  2. Xóa quy tắc định tuyến khỏi cấu hình S3
  3. Đặt Cloudfront trước thùng S3 của bạn.
  4. Định cấu hình quy tắc trang lỗi cho phiên bản Cloudfront của bạn. Trong các quy tắc lỗi chỉ định:

    • Mã lỗi http: 404 (và 403 hoặc các lỗi khác theo nhu cầu)
    • Lỗi bộ nhớ đệm tối thiểu TTL (giây): 0
    • Tùy chỉnh phản hồi: Có
    • Đường dẫn trang phản hồi: /index.html
    • Mã phản hồi HTTP: 200

      1. Đối với nhu cầu SEO + đảm bảo index.html của bạn không lưu cache, hãy làm như sau:
    • Định cấu hình phiên bản EC2 và thiết lập máy chủ nginx.

    • Chỉ định một ip công khai cho thể hiện EC2 của bạn.
    • Tạo ELB có phiên bản EC2 mà bạn đã tạo làm ví dụ
    • Bạn sẽ có thể gán ELB cho DNS của mình.
    • Bây giờ, hãy định cấu hình máy chủ nginx của bạn để thực hiện các việc sau: Proxy_pass tất cả các yêu cầu tới CDN của bạn (chỉ dành cho index.html, phục vụ các tài sản khác trực tiếp từ đám mây của bạn) và cho các bot tìm kiếm, chuyển hướng lưu lượng truy cập theo quy định của các dịch vụ như Prerender.io

Tôi có thể giúp chi tiết hơn về thiết lập nginx, chỉ cần để lại một ghi chú. Đã học nó một cách khó khăn.

Khi cập nhật phân phối phía trước đám mây. Vô hiệu hóa bộ đệm đám mây của bạn một lần ở chế độ nguyên sơ. Nhấn url trong trình duyệt và tất cả sẽ tốt.


6
Vì S3 phản hồi với 403 Bị cấm khi một tệp không tồn tại, tôi nghĩ rằng bước 4 ở trên phải được sao chép cho mã lỗi HTTP 403
Andreas

4
Đối với tôi đây là câu trả lời duy nhất dẫn đến một hành vi được mong đợi (được chấp nhận)
mabe.berlin

1
@ moha297 ở điểm 5 về cơ bản bạn có thể định cấu hình trang web của mình để tìm nạp từ nginx, sau đó proxy từ CDN (ngoại trừ các yêu cầu của trình thu thập thông tin và trình thu thập thông tin)? Nếu đó là trường hợp, bạn sẽ không mất lợi ích của máy chủ cạnh CDN?
Rahul Patel

2
@ moha297 bạn có thể vui lòng giải thích nhận xét này: "Bạn không bao giờ nên phục vụ index.html từ CDN"? Tôi không thấy vấn đề với việc phục vụ index.html từ S3 với CloudFront.
Carl G

1
Xem stackoverflow.com/a/10622078/4185989 để biết thêm thông tin về cách xử lý TTL 0 (phiên bản ngắn: được lưu trữ bởi Cloudfront nhưng If-Modified-Sinceyêu cầu GET được gửi đến nguồn gốc) - có thể là một cân nhắc hữu ích cho những người không muốn để thiết lập một máy chủ như trong bước 5.
jmq

18

Đó là tiếp tuyến, nhưng đây là một mẹo cho những người sử dụng thư viện Bộ định tuyến React của Rackt với lịch sử trình duyệt (HTML5) muốn lưu trữ trên S3.

Giả sử người dùng truy cập /foo/beartại trang web tĩnh được lưu trữ trên S3 của bạn. Đưa ra đề nghị trước đó của David , các quy tắc chuyển hướng sẽ gửi chúng đến . Nếu ứng dụng của bạn được xây dựng bằng lịch sử trình duyệt, điều này sẽ không làm được gì nhiều. Tuy nhiên, ứng dụng của bạn được tải vào thời điểm này và giờ đây nó có thể thao túng lịch sử./#/foo/bear

Bao gồm lịch sử Rackt trong dự án của chúng tôi (xem thêm Sử dụng Lịch sử tùy chỉnh từ dự án Bộ định tuyến React), bạn có thể thêm người nghe biết về các đường dẫn lịch sử băm và thay thế đường dẫn phù hợp, như được minh họa trong ví dụ này:

import ReactDOM from 'react-dom';

/* Application-specific details. */
const route = {};

import { Router, useRouterHistory } from 'react-router';
import { createHistory } from 'history';

const history = useRouterHistory(createHistory)();

history.listen(function (location) {
  const path = (/#(\/.*)$/.exec(location.hash) || [])[1];
  if (path) history.replace(path);
});

ReactDOM.render(
  <Router history={history} routes={route}/>,
  document.body.appendChild(document.createElement('div'))
);

Tóm lại:

  1. Quy tắc chuyển hướng S3 của David sẽ hướng /foo/bearđến/#/foo/bear .
  2. Ứng dụng của bạn sẽ tải.
  3. Người nghe lịch sử sẽ phát hiện #/foo/bearký hiệu lịch sử.
  4. Và thay thế lịch sử bằng con đường chính xác.

Link thẻ sẽ hoạt động như mong đợi, cũng như tất cả các chức năng lịch sử trình duyệt khác. Nhược điểm duy nhất tôi nhận thấy là chuyển hướng xen kẽ xảy ra theo yêu cầu ban đầu.

Điều này được lấy cảm hứng từ một giải pháp cho AngularJS và tôi nghi ngờ có thể dễ dàng thích nghi với bất kỳ ứng dụng nào.


2
Điều này đã giúp tôi Michael, Cảm ơn! Bạn có thể muốn thay đổi tham chiếu của mình từ lịch sử và chỉ cần sử dụng BrowserHistory. tức làbrowserHistory.listen
Marshall Moutenot

Không có gì! Vui mừng được giúp đỡ. Ngoài ra, đã đồng ý và trong trường hợp sử dụng cụ thể này, tôi đã cập nhật đoạn mã để giải quyết cảnh báo không dùng từ Bộ định tuyến React.
Michael Ahlers

Với việc phát hành Reac-router v3.0.0, điều này không hoạt động, bởi vì Reac-router v3.0.0 sử dụng History v3.0.0
Varand Pezeshkian

Bất kỳ ý tưởng làm thế nào để ngăn chặn vòng lặp cuộc gọi vô hạn history.listen? Nguyên nhân bằng cách thay thế con đường tôi đoán.
Mirko Flyktman

14

Tôi thấy 4 giải pháp cho vấn đề này. 3 người đầu tiên đã được trả lời trong câu trả lời và câu trả lời cuối cùng là sự đóng góp của tôi.

  1. Đặt tài liệu lỗi thành index.html.
    Vấn đề : phần thân phản hồi sẽ đúng, nhưng mã trạng thái sẽ là 404, điều này làm tổn thương SEO.

  2. Đặt quy tắc chuyển hướng.
    Vấn đề : URL bị ô nhiễm #!và nhấp nháy trang khi được tải.

  3. Định cấu hình CloudFront.
    Vấn đề : tất cả các trang sẽ trả về 404 từ nguồn gốc, vì vậy bạn cần chọn nếu bạn sẽ không lưu trữ bất cứ thứ gì (TTL 0 như được đề xuất) hoặc nếu bạn sẽ lưu trữ bộ đệm và gặp sự cố khi cập nhật trang web.

  4. Prerender tất cả các trang.
    Vấn đề : công việc bổ sung cho các trang trước, đặc biệt khi các trang thay đổi thường xuyên. Ví dụ, một trang web tin tức.

Đề xuất của tôi là sử dụng tùy chọn 4. Nếu bạn đăng ký trước tất cả các trang, sẽ không có lỗi 404 cho các trang dự kiến. Trang sẽ tải tốt và khung sẽ kiểm soát và hoạt động bình thường như một SPA. Bạn cũng có thể đặt tài liệu lỗi hiển thị trang error.html chung và quy tắc chuyển hướng để chuyển hướng lỗi 404 sang trang 404.html (không có hashbang).

Về 403 Lỗi bị cấm, tôi không để chúng xảy ra. Trong ứng dụng của mình, tôi cho rằng tất cả các tệp trong nhóm máy chủ đều ở chế độ công khai và tôi đặt tùy chọn này với tùy chọn mọi người với quyền đọc . Nếu trang web của bạn có các trang riêng tư, cho phép người dùng xem bố cục HTML sẽ không thành vấn đề. Những gì bạn cần bảo vệ là dữ liệu và điều này được thực hiện trong phần phụ trợ.

Ngoài ra, nếu bạn có tài sản riêng, như ảnh người dùng, bạn có thể lưu chúng vào một nhóm khác . Bởi vì tài sản riêng cần được chăm sóc giống như dữ liệu và không thể so sánh với các tệp tài sản được sử dụng để lưu trữ ứng dụng.


1
và trang web của bạn có một ví dụ tuyệt vời về việc sử dụng để trình bày trước cho tất cả các trang. zanon.io/posts/ từ .- Cảm ơn bạn
frekele

Cách tiếp cận thứ tư này có giải quyết được việc người dùng tải lại URL PushState không? Nó xử lý điều hướng tốt, nhưng khi tải lại, nó vẫn sẽ đến máy chủ.
Alpha

@Alpha, tôi không chắc là tôi đã hiểu chính xác câu hỏi của bạn chưa, nhưng khi tải lại, nó sẽ hoạt động như một yêu cầu mới. S3 sẽ nhận được yêu cầu và trả lại trang đã đăng ký trước. Không có máy chủ trong trường hợp này.
Zanon

@Zanon Ah, tôi nghĩ tôi hiểu. Tôi nghĩ rằng nó có nghĩa là để lưu trữ các trang đã được đăng ký trước và tránh sử dụng các tài nguyên chưa có trong S3. Điều này sẽ bỏ qua các tuyến đường có các yếu tố năng động, phải không?
Alpha

1
@Zanon Cuối cùng tôi cũng hiểu - cảm ơn! Vâng, đó là những gì tôi muốn nói. :)
Alpha

13

Tôi đã gặp vấn đề tương tự ngày hôm nay nhưng giải pháp của @ Mark-Nutter vẫn chưa hoàn thành để xóa hashbang khỏi ứng dụng angularjs của tôi.

Trong thực tế, bạn phải vào Chỉnh sửa quyền , nhấp vào Thêm quyền khác và sau đó thêm Danh sách đúng vào nhóm của bạn cho mọi người. Với cấu hình này, AWS S3 sẽ có thể trả về lỗi 404 và sau đó quy tắc chuyển hướng sẽ bắt đúng trường hợp.

Chỉ như thế này : nhập mô tả hình ảnh ở đây

Và sau đó bạn có thể vào Chỉnh sửa quy tắc chuyển hướng và thêm quy tắc này:

<RoutingRules>
    <RoutingRule>
        <Condition>
            <HttpErrorCodeReturnedEquals>404</HttpErrorCodeReturnedEquals>
        </Condition>
        <Redirect>
            <HostName>subdomain.domain.fr</HostName>
            <ReplaceKeyPrefixWith>#!/</ReplaceKeyPrefixWith>
        </Redirect>
    </RoutingRule>
</RoutingRules>

Tại đây, bạn có thể thay thế tên miền HostName.domain.fr bằng tên miền của mình và KeyPrefix #! / Nếu bạn không sử dụng phương thức hashbang cho mục đích SEO.

Tất nhiên, tất cả những thứ này sẽ chỉ hoạt động nếu bạn đã thiết lập html5mode trong ứng dụng góc cạnh của mình.

$locationProvider.html5Mode(true).hashPrefix('!');

Vấn đề duy nhất của tôi với điều này là bạn có một flash hashbang, thứ mà bạn không có với một thứ như quy tắc nginx. Người dùng đang ở trên một trang và làm mới: / sản phẩm / 1 -> #! / Sản phẩm / 1 -> / sản phẩm / 1
Intellix

1
Tôi nghĩ bạn nên thêm một quy tắc cho lỗi 403 thay vì cấp quyền danh sách cho mọi người.
Hamish Moffatt

11

Giải pháp đơn giản nhất để làm cho ứng dụng Angular 2+ được phân phối từ Amazon S3 và các URL trực tiếp hoạt động là chỉ định index.html cả dưới dạng tài liệu Index và Error trong cấu hình nhóm S3.

nhập mô tả hình ảnh ở đây


11
Đây là cùng một câu trả lời của câu trả lời bị đánh giá thấp này . Nó hoạt động tốt, nhưng chỉ tại bodycác phản ứng. Mã trạng thái sẽ là 404 và nó sẽ làm tổn thương SEO.
Zanon

Bởi vì điều này chỉ hoạt động bodynếu bạn có bất kỳ tập lệnh nào mà bạn nhập vào, headchúng sẽ không hoạt động khi bạn truy cập trực tiếp vào bất kỳ tuyến phụ nào trên trang web của bạn
Mohamed Hajr

4

vì vấn đề vẫn còn đó tôi mặc dù tôi đưa ra một giải pháp khác. Trường hợp của tôi là tôi muốn tự động triển khai tất cả các yêu cầu kéo đến s3 để thử nghiệm trước khi hợp nhất làm cho chúng có thể truy cập được trên [mydomain] / pull-request / [pr number] /
(ví dụ: www.example.com/pull-requests/822/ )

Theo hiểu biết tốt nhất của tôi, không phải kịch bản quy tắc s3 sẽ cho phép có nhiều dự án trong một nhóm sử dụng định tuyến html5, do đó, trong khi hầu hết các đề xuất được bình chọn đều hoạt động cho một dự án trong thư mục gốc, thì nó không dành cho nhiều dự án trong các thư mục con riêng.

Vì vậy, tôi đã chỉ tên miền của mình đến máy chủ của mình, nơi theo cấu hình nginx đã thực hiện công việc

location /pull-requests/ {
    try_files $uri @get_files;
}
location @get_files {
    rewrite ^\/pull-requests\/(.*) /$1 break;
    proxy_pass http://<your-amazon-bucket-url>;
    proxy_intercept_errors on;
    recursive_error_pages on;
    error_page 404 = @get_routes;
}

location @get_routes {
    rewrite ^\/(\w+)\/(.+) /$1/ break;
    proxy_pass http://<your-amazon-bucket-url>;
    proxy_intercept_errors on;
    recursive_error_pages on;
    error_page 404 = @not_found;
}

location @not_found {
    return 404;
}

nó cố lấy tập tin và nếu không tìm thấy thì đó là tuyến html5 và thử nó. Nếu bạn có một trang góc 404 cho các tuyến không tìm thấy, bạn sẽ không bao giờ truy cập @not_found và trả lại trang 404 góc thay vì các tệp không tìm thấy, có thể được sửa với một số nếu quy tắc trong @get_routes hoặc một cái gì đó.

Tôi phải nói rằng tôi không cảm thấy quá thoải mái trong lĩnh vực cấu hình nginx và sử dụng regex cho vấn đề đó, tôi đã làm việc này với một số thử nghiệm và lỗi vì vậy trong khi điều này hoạt động tôi chắc chắn có chỗ để cải thiện và hãy chia sẻ suy nghĩ của bạn .

Lưu ý : xóa quy tắc chuyển hướng s3 nếu bạn có chúng trong cấu hình S3.

và btw hoạt động trong Safari


hi .. cảm ơn vì giải pháp ... bạn đặt tập tin nginx này ở đâu để triển khai s3. nó có giống như beanstalk đàn hồi mà tôi cần tạo thư mục .exextensions và đặt nó trong tập tin proxy.config không?
dùng3124360

@ user3124360 Không chắc chắn về beanstack đàn hồi, nhưng trong trường hợp của tôi, tôi trỏ tên miền của mình đến ví dụ ec2 và có cấu hình nginx ở đó. Vì vậy, yêu cầu đi CLIENT -> DNS -> EC2 -> S3 -> CLIENT.
Andrew Arnautov

vâng Tôi đang làm một cái gì đó rất giống ... với nginx config ở đây github.com/davezuko/react-redux-starter-kit/issues/1099 ... cảm ơn vì đã đăng tệp conf của bạn .. tôi thấy cách phát triển EC2 này -> Kết nối S3 ngay bây giờ
user3124360

3

Đã tìm kiếm cùng một loại vấn đề. Tôi đã kết thúc bằng cách sử dụng hỗn hợp các giải pháp được đề xuất ở trên.

Đầu tiên, tôi có một thùng s3 với nhiều thư mục, mỗi thư mục đại diện cho một trang web Reac / redux. Tôi cũng sử dụng cloudfront để vô hiệu hóa bộ đệm.

Vì vậy, tôi đã phải sử dụng Quy tắc định tuyến để hỗ trợ 404 và chuyển hướng chúng đến cấu hình băm:

<RoutingRules>
    <RoutingRule>
        <Condition>
            <KeyPrefixEquals>website1/</KeyPrefixEquals>
            <HttpErrorCodeReturnedEquals>404</HttpErrorCodeReturnedEquals>
        </Condition>
        <Redirect>
            <Protocol>https</Protocol>
            <HostName>my.host.com</HostName>
            <ReplaceKeyPrefixWith>website1#</ReplaceKeyPrefixWith>
        </Redirect>
    </RoutingRule>
    <RoutingRule>
        <Condition>
            <KeyPrefixEquals>website2/</KeyPrefixEquals>
            <HttpErrorCodeReturnedEquals>404</HttpErrorCodeReturnedEquals>
        </Condition>
        <Redirect>
            <Protocol>https</Protocol>
            <HostName>my.host.com</HostName>
            <ReplaceKeyPrefixWith>website2#</ReplaceKeyPrefixWith>
        </Redirect>
    </RoutingRule>
    <RoutingRule>
        <Condition>
            <KeyPrefixEquals>website3/</KeyPrefixEquals>
            <HttpErrorCodeReturnedEquals>404</HttpErrorCodeReturnedEquals>
        </Condition>
        <Redirect>
            <Protocol>https</Protocol>
            <HostName>my.host.com</HostName>
            <ReplaceKeyPrefixWith>website3#</ReplaceKeyPrefixWith>
        </Redirect>
    </RoutingRule>
</RoutingRules>

Trong mã js của tôi, tôi cần xử lý nó với một baseNamecấu hình cho bộ định tuyến phản ứng. Trước hết, hãy chắc chắn rằng các phần phụ thuộc của bạn có thể tương thích với nhau, tôi đã cài đặt history==4.0.0không tương thích vớireact-router==3.0.1 .

Phụ thuộc của tôi là:

  • "lịch sử": "3.2.0",
  • "phản ứng": "15.4.1",
  • "phản ứng-redux": "4.4.6",
  • "bộ định tuyến phản ứng": "3.0.1",
  • "Reac-router-redux": "4.0.7",

Tôi đã tạo một history.jstệp để tải lịch sử:

import {useRouterHistory} from 'react-router';
import createBrowserHistory from 'history/lib/createBrowserHistory';

export const browserHistory = useRouterHistory(createBrowserHistory)({
    basename: '/website1/',
});

browserHistory.listen((location) => {
    const path = (/#(.*)$/.exec(location.hash) || [])[1];
    if (path) {
        browserHistory.replace(path);
    }
});

export default browserHistory;

Đoạn mã này cho phép xử lý 404 được gửi bởi sever bằng hàm băm và thay thế chúng trong lịch sử để tải các tuyến đường của chúng tôi.

Bây giờ bạn có thể sử dụng tệp này để định cấu hình cửa hàng của mình và tệp Root của bạn.

import {routerMiddleware} from 'react-router-redux';
import {applyMiddleware, compose} from 'redux';

import rootSaga from '../sagas';
import rootReducer from '../reducers';

import {createInjectSagasStore, sagaMiddleware} from './redux-sagas-injector';

import {browserHistory} from '../history';

export default function configureStore(initialState) {
    const enhancers = [
        applyMiddleware(
            sagaMiddleware,
            routerMiddleware(browserHistory),
        )];

    return createInjectSagasStore(rootReducer, rootSaga, initialState, compose(...enhancers));
}
import React, {PropTypes} from 'react';
import {Provider} from 'react-redux';
import {Router} from 'react-router';
import {syncHistoryWithStore} from 'react-router-redux';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import variables from '!!sass-variable-loader!../../../css/variables/variables.prod.scss';
import routesFactory from '../routes';
import {browserHistory} from '../history';

const muiTheme = getMuiTheme({
    palette: {
        primary1Color: variables.baseColor,
    },
});

const Root = ({store}) => {
    const history = syncHistoryWithStore(browserHistory, store);
    const routes = routesFactory(store);

    return (
        <Provider {...{store}}>
            <MuiThemeProvider muiTheme={muiTheme}>
                <Router {...{history, routes}} />
            </MuiThemeProvider>
        </Provider>
    );
};

Root.propTypes = {
    store: PropTypes.shape({}).isRequired,
};

export default Root;

Hy vọng nó giúp. Bạn sẽ nhận thấy với cấu hình này, tôi sử dụng trình tiêm redux và trình tiêm sagas homebrew để tải javascript không đồng bộ thông qua định tuyến. Đừng bận tâm với những dòng luận văn.


3

Bây giờ bạn có thể làm điều này với Lambda @ Edge để viết lại các đường dẫn

Đây là một chức năng lambda @ Edge hoạt động:

  1. Tạo một hàm Lambda mới, nhưng sử dụng một trong các Bản thiết kế có sẵn thay vì một chức năng trống.
  2. Tìm kiếm trên nền tảng đám mây của Nhật Bản và chọn tạo phản hồi trên nền tảng đám mây từ kết quả tìm kiếm.
  3. Sau khi tạo chức năng, thay thế nội dung bằng bên dưới. Tôi cũng đã phải thay đổi thời gian chạy của nút thành 10.x vì cloudfront không hỗ trợ nút 12 tại thời điểm viết.
'use strict';
exports.handler = (event, context, callback) => {

    // Extract the request from the CloudFront event that is sent to Lambda@Edge 
    var request = event.Records[0].cf.request;

    // Extract the URI from the request
    var olduri = request.uri;

    // Match any '/' that occurs at the end of a URI. Replace it with a default index
    var newuri = olduri.replace(/\/$/, '\/index.html');

    // Log the URI as received by CloudFront and the new URI to be used to fetch from origin
    console.log("Old URI: " + olduri);
    console.log("New URI: " + newuri);

    // Replace the received URI with the URI that includes the index page
    request.uri = newuri;

    return callback(null, request);
};

Trong các hành vi trên đám mây của bạn, bạn sẽ chỉnh sửa chúng để thêm một cuộc gọi đến chức năng lambda đó trên "Yêu cầu người xem" nhập mô tả hình ảnh ở đây

Hướng dẫn đầy đủ: https://aws.amazon.com/bloss/compute/im vâying-default-default-index-in-amazon-s3-backed-amazon-cloudfront-origins-USElambdaedge /


1
Ví dụ mã của bạn chỉ bỏ lỡ một dòng:return callback(null, request);
Pherrymason

2

Nếu bạn đã đến đây để tìm giải pháp hoạt động với React Router và AWS Amplify Console - bạn đã biết rằng bạn không thể sử dụng trực tiếp các quy tắc chuyển hướng CloudFront vì Amplify Console không hiển thị Phân phối CloudFront cho ứng dụng.

Tuy nhiên, giải pháp rất đơn giản - bạn chỉ cần thêm quy tắc chuyển hướng / viết lại trong Bảng điều khiển Amplify như thế này:

Amplify Quy tắc viết lại bảng điều khiển cho Bộ định tuyến React

Xem các liên kết sau để biết thêm thông tin (và quy tắc thân thiện với bản sao từ ảnh chụp màn hình):


0

Tôi đã tìm kiếm một câu trả lời cho điều này bản thân mình. S3 dường như chỉ hỗ trợ chuyển hướng, bạn không thể viết lại URL và âm thầm trả lại một tài nguyên khác. Tôi đang xem xét sử dụng tập lệnh xây dựng của mình để tạo các bản sao của index.html trong tất cả các vị trí đường dẫn cần thiết. Có lẽ điều đó sẽ làm việc cho bạn quá.


2
Việc tạo các tệp chỉ mục cho mỗi đường dẫn cũng đã vượt qua tâm trí của tôi, nhưng sẽ rất khó để có các đường dẫn động như example.com/groups/5/show . Nếu bạn thấy câu trả lời của tôi cho câu hỏi này, tôi tin rằng phần lớn vấn đề sẽ giải quyết được. Đó là một chút hack nhưng ít nhất nó hoạt động.
Đánh dấu

Tốt hơn là triển khai phía sau máy chủ nginx và trả về index.html cho tất cả các url đến. Tôi đã thực hiện điều này thành công với việc triển khai heroku các ứng dụng than hồng.
moha297

-3

Chỉ để đặt câu trả lời cực kỳ đơn giản. Chỉ cần sử dụng chiến lược vị trí băm cho bộ định tuyến nếu bạn đang lưu trữ trên S3.

export const AppRoutingModule: ModuleWithProviders = RouterModule.forRoot (tuyến, {useHash: true, scrollPocationRestoration: 'enable'});

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.