Situs Web Hosting Statis S3 Merutekan Semua Jalur ke Index.html

250

Saya menggunakan S3 untuk meng-host aplikasi javascript yang akan menggunakan pushStates HTML5. Masalahnya adalah jika pengguna menandai salah satu URL, itu tidak akan menyelesaikan apa pun. Yang saya butuhkan adalah kemampuan untuk mengambil semua permintaan url dan melayani root index.html di bucket S3 saya, daripada hanya melakukan redirect penuh. Kemudian aplikasi javascript saya dapat mem-parsing URL dan melayani halaman yang tepat.

Apakah ada cara untuk memberi tahu S3 agar melayani index.html untuk semua permintaan URL alih-alih melakukan pengalihan? Ini mirip dengan menyiapkan apache untuk menangani semua permintaan yang masuk dengan menyajikan satu index.html seperti dalam contoh ini: https://stackoverflow.com/a/10647521/1762614 . Saya benar-benar ingin menghindari menjalankan server web hanya untuk menangani rute ini. Melakukan semuanya dari S3 sangat menarik.

Mark Nutter
sumber
Apakah Anda menemukan solusi untuk ini?
w2lame

Jawaban:

302

Sangat mudah untuk menyelesaikannya tanpa url hacks, dengan bantuan CloudFront.

  • Buat ember S3, misalnya: bereaksi
  • Buat distribusi CloudFront dengan pengaturan ini:
    • Objek Root Default : index.html
    • Nama Domain Asal : domain bucket S3, misalnya: react.s3.amazonaws.com
  • Buka tab Halaman Kesalahan , klik Buat Respons Kesalahan Kustom :
    • Kode Kesalahan HTTP : 403: Dilarang (404: Tidak Ditemukan, dalam hal Situs S3 S3)
    • Kustomisasi Respons Kesalahan : Ya
    • Jalur Halaman Respons : /index.html
    • Kode Respon HTTP : 200: Oke
    • Klik Buat
lenaten
sumber
8
Terima kasih. Jawaban terbaik sejauh ini.
jgb
dan apa yang tidak begitu jelas Anda menjaga lokasi sehingga Anda dapat melakukan routing "alami".
Lukasz Marek Sielski
5
ini bekerja seperti pesona bagi saya, hanya kode kesalahan khusus yang saya butuhkan adalah 404, bukan 403
Jeremy S.
4
Sedikit peretasan, tetapi bekerja dengan sangat baik :) Alangkah baiknya jika CloudFront membiarkan kami memetakan berbagai jalur ke file S3 (tanpa arahan ulang).
Bob
3
Ini tidak bekerja untuk saya. Solusi ini selalu dialihkan ke halaman beranda dan bukan halaman yang benar ...
Jim
201

Cara saya bisa membuatnya bekerja adalah sebagai berikut:

Di bagian Edit Aturan Pengalihan dari Konsol S3 untuk domain Anda, tambahkan aturan berikut:

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

Ini akan mengarahkan ulang semua jalur yang menghasilkan 404 tidak ditemukan ke domain root Anda dengan versi hash-bang path. Jadi http://domainandaanda.com/posts akan dialihkan ke http://domainandaanda.com/#!/posts asalkan tidak ada file di / posting.

Untuk menggunakan pushState HTML5, kita harus menerima permintaan ini dan secara manual membuat pushState yang tepat berdasarkan jalur hash-bang. Jadi tambahkan ini ke bagian atas file index.html Anda:

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

Ini mengambil hash dan mengubahnya menjadi pushState HTML5. Dari titik ini Anda dapat menggunakan pushStates untuk memiliki jalur non-hash-bang di aplikasi Anda.

Mark Nutter
sumber
4
Solusi ini sangat bagus! Bahkan angularjs akan secara otomatis melakukan pushState riwayat jika mode html dikonfigurasi.
wcandillon
1
Ini akan gagal dengan versi IE yang lebih lama jika Anda memiliki paret GET yang disertakan dalam url Anda, benar? Bagaimana Anda mengatasi masalah itu?
clexmond
3
Terima kasih! Ini bekerja dengan baik untuk saya di tulang punggung dengan sedikit perubahan. Saya menambahkan cek untuk browser lama: <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 Grey
10
Berhasil dengan react-routersolusi itu menggunakan HTML5 pushStates dan<ReplaceKeyPrefixWith>#/</ReplaceKeyPrefixWith>
Felix D.
5
Itu tidak bekerja di safari dan merupakan masalah besar dengan strategi penyebaran. Menulis js kecil untuk mengarahkan adalah semacam pendekatan yang buruk. Juga, jumlah pengalihan juga menjadi masalah. Saya mencoba mencari jika ada cara agar semua url S3 selalu mengarah ke index.html.
moha297
129

Ada beberapa masalah dengan pendekatan berbasis S3 / Redirect yang disebutkan oleh orang lain.

  1. Arahan ulang banyak terjadi saat jalur aplikasi Anda diselesaikan. Misalnya: www.myapp.com/path/for/test akan dialihkan ke www.myapp.com/#/path/for/test
  2. Ada flicker di bilah url ketika tanda '#' datang dan pergi karena aksi kerangka SPA Anda.
  3. Seo terkena dampak karena - 'Hei! Google-nya memaksa tangannya di pengalihan '
  4. Dukungan Safari untuk aplikasi Anda berlaku untuk undian.

Solusinya adalah:

  1. Pastikan Anda memiliki rute indeks yang dikonfigurasi untuk situs web Anda. Kebanyakan itu adalah index.html
  2. Hapus aturan perutean dari konfigurasi S3
  3. Letakkan Cloudfront di depan bucket S3 Anda.
  4. Konfigurasikan aturan halaman kesalahan untuk mesin virtual Cloudfront Anda. Dalam aturan kesalahan tentukan:

    • Kode kesalahan Http: 404 (dan 403 atau kesalahan lain sesuai kebutuhan)
    • Caching Kesalahan Minimum TTL (detik): 0
    • Ubahsuaikan respons: Ya
    • Jalur Halaman Respons: /index.html
    • Kode Respons HTTP: 200

      1. Untuk kebutuhan SEO + memastikan index.html Anda tidak cache, lakukan hal berikut:
    • Konfigurasikan instance EC2 dan setup server nginx.

    • Tetapkan ip publik untuk instance EC2 Anda.
    • Buat ELB yang memiliki instance EC2 yang Anda buat sebagai instance
    • Anda harus dapat menetapkan ELB ke DNS Anda.
    • Sekarang, konfigurasikan server nginx Anda untuk melakukan hal-hal berikut: Proxy_pass semua permintaan ke CDN Anda (hanya untuk index.html, sajikan aset lain langsung dari cloudfront Anda) dan untuk bot pencarian, arahkan lalu lintas sebagaimana ditentukan oleh layanan seperti Prerender.io

Saya dapat membantu lebih detail sehubungan dengan pengaturan nginx, tinggalkan saja catatan. Telah mempelajarinya dengan cara yang sulit.

Setelah pembaruan distribusi depan cloud. Batalkan cache cloudfront Anda sekali untuk berada dalam mode murni. Tekan url di browser dan semuanya harus baik.

moha297
sumber
6
karena S3 merespons dengan 403 Dilarang ketika file tidak ada, saya pikir langkah 4 di atas harus diduplikasi untuk kode kesalahan Http 403 juga
Andreas
4
Bagi saya ini adalah satu-satunya jawaban yang menghasilkan perilaku yang diharapkan (diterima)
mabe.berlin
1
@ moha297 pada poin 5 apakah pada dasarnya Anda mengkonfigurasi situs Anda untuk mengambil dari nginx yang kemudian proksi dari CDN (kecuali untuk permintaan index.html dan crawler)? Jika demikian, bukankah Anda akan kehilangan manfaat dari server tepi CDN?
Rahul Patel
2
@ moha297 dapatkah Anda menjelaskan komentar ini: "Anda seharusnya tidak pernah melayani index.html dari CDN"? Saya tidak melihat masalah dengan melayani index.html dari S3 dengan CloudFront.
Carl G
1
Lihat stackoverflow.com/a/10622078/4185989 untuk info lebih lanjut tentang bagaimana TTL 0 diperlakukan (versi singkat: itu di-cache oleh Cloudfront tetapi If-Modified-Sincepermintaan GET dikirim ke asal) - mungkin pertimbangan yang bermanfaat bagi orang yang tidak menginginkan untuk mengatur server seperti pada langkah 5.
jmq
18

Ini tangensial, tapi di sini ada tip untuk mereka yang menggunakan perpustakaan Rackt's React Router dengan (HTML5) riwayat browser yang ingin di-host di S3.

Misalkan seorang pengguna mengunjungi /foo/bearsitus web statis S3-host Anda. Dengan saran David sebelumnya , aturan pengalihan akan mengirimnya ke /#/foo/bear. Jika aplikasi Anda dibuat menggunakan riwayat browser, ini tidak akan banyak gunanya. Namun aplikasi Anda dimuat pada titik ini dan sekarang dapat memanipulasi sejarah.

Termasuk riwayat Rackt dalam proyek kami (lihat juga Menggunakan Riwayat Khusus dari proyek React Router), Anda dapat menambahkan pendengar yang mengetahui jalur riwayat hash dan mengganti jalur yang sesuai, seperti yang diilustrasikan dalam contoh ini:

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'))
);

Untuk rekap:

  1. Aturan pengalihan S3 David akan mengarahkan /foo/bearke /#/foo/bear.
  2. Aplikasi Anda akan dimuat.
  3. Pendengar riwayat akan mendeteksi #/foo/bearnotasi riwayat.
  4. Dan ganti histori dengan jalur yang benar.

Linktag akan berfungsi seperti yang diharapkan, seperti semua fungsi riwayat browser lainnya. Satu-satunya downside yang saya perhatikan adalah pengalihan interstitial yang terjadi pada permintaan awal.

Ini terinspirasi oleh solusi untuk AngularJS , dan saya curiga dapat dengan mudah disesuaikan dengan aplikasi apa pun.

Michael Ahlers
sumber
2
Ini membantu saya Michael, Terima kasih! Anda mungkin ingin mengubah referensi dari riwayat dan cukup gunakan BrowserHistory. yaitubrowserHistory.listen
Marshall Moutenot
Sama-sama! Senang untuk membantu. Juga, setuju, dan untuk kasus penggunaan khusus ini saya telah memperbarui snippet untuk menyelesaikan peringatan penghentian dari React Router.
Michael Ahlers
Dengan rilis react-router v3.0.0 ini tidak berfungsi, karena react-router v3.0.0 menggunakan History v3.0.0
Varand Pezeshkian
Adakah cara untuk mencegah history.listen loop panggilan tak terbatas? Disebabkan oleh mengganti jalan saya kira.
Mirko Flyktman
14

Saya melihat 4 solusi untuk masalah ini. 3 yang pertama sudah tercakup dalam jawaban dan yang terakhir adalah kontribusi saya.

  1. Setel dokumen kesalahan ke index.html.
    Masalah : badan respons akan benar, tetapi kode status akan menjadi 404, yang menyakitkan SEO.

  2. Tetapkan aturan pengalihan.
    Masalah : URL tercemar dengan #!dan halaman berkedip saat dimuat.

  3. Konfigurasikan CloudFront.
    Masalah : semua halaman akan mengembalikan 404 dari asal, jadi Anda harus memilih apakah Anda tidak akan menembolok apa pun (TTL 0 seperti yang disarankan) atau jika Anda akan menembolok dan memiliki masalah saat memperbarui situs.

  4. Prerender semua halaman.
    Masalah : pekerjaan tambahan untuk halaman prerender, khususnya ketika halaman sering berubah. Misalnya, situs web berita.

Saran saya adalah menggunakan opsi 4. Jika Anda mempratinjau semua halaman, tidak akan ada 404 kesalahan untuk halaman yang diharapkan. Halaman akan memuat dengan baik dan kerangka kerja akan mengambil kendali dan bertindak secara normal sebagai SPA. Anda juga dapat mengatur dokumen kesalahan untuk menampilkan halaman generik error.html dan aturan pengalihan untuk mengarahkan 404 kesalahan ke halaman 404.html (tanpa hashbang).

Mengenai 403 kesalahan Terlarang, saya tidak membiarkan mereka terjadi sama sekali. Dalam aplikasi saya, saya menganggap bahwa semua file dalam ember host bersifat publik dan saya mengatur ini dengan opsi semua orang dengan izin baca . Jika situs Anda memiliki halaman yang bersifat pribadi, membiarkan pengguna untuk melihat tata letak HTML seharusnya tidak menjadi masalah. Yang perlu Anda lindungi adalah data dan ini dilakukan di backend.

Juga, jika Anda memiliki aset pribadi, seperti foto pengguna, Anda dapat menyimpannya dalam ember lain . Karena aset pribadi memerlukan perawatan yang sama seperti data dan tidak dapat dibandingkan dengan file aset yang digunakan untuk meng-host aplikasi.

Zanon
sumber
1
dan situs Anda memiliki contoh penggunaan yang bagus dengan prerender untuk semua halaman. zanon.io/posts/… .- Terima kasih
frekele
Apakah pendekatan keempat ini mengatasi pengguna yang memuat ulang URL pushState? Ini menangani navigasi dengan baik tetapi pada reload, itu masih akan mencapai server.
Alpha
@Alpha, saya tidak yakin apakah saya telah memahami pertanyaan Anda dengan benar, tetapi saat memuat ulang, itu akan bertindak sebagai permintaan baru. S3 akan menerima permintaan itu dan mengembalikan halaman yang sudah ditebak sebelumnya. Tidak ada server dalam hal ini.
Zanon
@Zanon Ah, saya pikir saya mengerti. Saya pikir itu dimaksudkan untuk me-cache halaman prerendered dan menghindari pergi untuk sumber S3 yang tidak ada. Ini akan meninggalkan rute yang memiliki elemen dinamis, bukan?
Alpha
1
@Zanon Saya akhirnya mengerti - terima kasih! Ya, itulah yang saya maksud. :)
Alpha
13

Saya mengalami masalah yang sama hari ini tetapi solusi @ Mark-Nutter tidak lengkap untuk menghapus hashbang dari aplikasi angularjs saya.

Bahkan Anda harus pergi ke Edit Izin , klik Tambahkan lebih banyak izin dan kemudian tambahkan Daftar kanan pada ember Anda untuk semua orang. Dengan konfigurasi ini, AWS S3 sekarang akan, dapat mengembalikan 404 kesalahan dan kemudian aturan pengalihan akan menangkap case dengan benar.

Seperti ini : masukkan deskripsi gambar di sini

Dan kemudian Anda bisa pergi ke Edit Aturan Pengalihan dan tambahkan aturan ini:

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

Di sini Anda dapat mengganti subdomain.domain.fr HostName dengan domain Anda dan KeyPrefix #! / Jika Anda tidak menggunakan metode hashbang untuk tujuan SEO.

Tentu saja, semua ini hanya akan berfungsi jika Anda sudah memiliki setup html5mode di aplikasi sudut Anda.

$locationProvider.html5Mode(true).hashPrefix('!');
davidbonachera
sumber
Satu-satunya masalah saya dengan ini adalah bahwa Anda memiliki flash hashbang, yang tidak Anda miliki dengan sesuatu seperti aturan nginx. Pengguna ada di halaman dan menyegarkan: / produk / 1 -> #! / Produk / 1 -> / produk / 1
Intellix
1
Saya pikir Anda harus menambahkan aturan untuk kesalahan 403 daripada memberikan izin daftar kepada semua orang.
Hamish Moffatt
11

Solusi termudah untuk membuat aplikasi Angular 2+ dilayani dari Amazon S3 dan URL langsung berfungsi adalah dengan menentukan index.html baik sebagai dokumen Indeks dan Kesalahan dalam konfigurasi bucket S3.

masukkan deskripsi gambar di sini

Sergey Kandaurov
sumber
11
Ini adalah jawaban yang sama dari jawaban yang sangat tidak disukai ini . Ini berfungsi dengan baik, tetapi hanya untuk bodytanggapan. Kode status akan menjadi 404 dan itu akan merugikan SEO.
Zanon
Karena ini hanya berfungsi bodyjika Anda memiliki skrip yang Anda impor di skrip headtersebut tidak akan berfungsi ketika Anda langsung menekan salah satu sub-rute di situs web Anda
Mohamed Hajr
4

karena masalahnya masih ada saya meskipun saya melempar solusi lain. Kasus saya adalah bahwa saya ingin menyebarkan semua permintaan tarik ke s3 secara otomatis untuk pengujian sebelum bergabung membuatnya dapat diakses di [domain saya] / permintaan-tarik / [nomor pr] /
(mis. Www.example.com/pull-requests/822/ )

Sepengetahuan saya, tidak ada skenario s3 aturan skenario akan memungkinkan untuk memiliki beberapa proyek dalam satu ember menggunakan html5 perutean sementara sementara di atas sebagian besar suara saran berfungsi untuk proyek di folder root, itu tidak untuk beberapa proyek di subfolder sendiri.

Jadi saya mengarahkan domain saya ke server saya di mana nginx config berikut melakukan pekerjaan

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;
}

itu mencoba untuk mendapatkan file dan jika tidak ditemukan menganggap itu adalah rute HTML5 dan mencobanya. Jika Anda memiliki halaman sudut 404 untuk rute yang tidak ditemukan, Anda tidak akan pernah sampai ke @not_found dan membuat Anda membuka halaman 404 sudut bukan file yang ditemukan, yang bisa diperbaiki dengan beberapa jika aturan dalam @get_routes atau sesuatu.

Saya harus mengatakan saya tidak merasa terlalu nyaman di bidang nginx config dan menggunakan regex dalam hal ini, saya dapat ini bekerja dengan beberapa trial and error jadi sementara ini berfungsi saya yakin ada ruang untuk perbaikan dan silakan berbagi pemikiran Anda .

Catatan : hapus aturan pengalihan s3 jika Anda memilikinya dalam konfigurasi S3.

dan btw berfungsi di Safari

Andrew Arnautov
sumber
hai .. terima kasih untuk solusinya ... di mana Anda meletakkan file conf nginx ini untuk penyebaran s3. apakah itu sama dengan batang kacang elastis di mana saya harus membuat folder .exextensions dan meletakkannya di file proxy.config?
user3124360
@ user3124360 Tidak yakin tentang beanstack elastis, tetapi dalam kasus saya, saya menunjukkan nama domain saya ke EC2 misalnya dan memiliki konfigurasi nginx di sana. Jadi permintaan pergi KLIEN -> DNS -> EC2 -> S3 -> KLIEN.
Andrew Arnautov
ya saya melakukan sesuatu yang sangat mirip ... dengan nginx config di sini github.com/davezuko/react-redux-starter-kit/issues/1099 ... terima kasih telah memposting file conf Anda .. saya melihat bagaimana mengembangkan EC2 ini -> Koneksi S3 sekarang
user3124360
3

Sedang mencari jenis masalah yang sama. Saya akhirnya menggunakan campuran solusi yang disarankan yang dijelaskan di atas.

Pertama, saya memiliki ember s3 dengan beberapa folder, setiap folder mewakili situs web react / redux. Saya juga menggunakan cloudfront untuk pembatalan cache.

Jadi saya harus menggunakan Aturan Routing untuk mendukung 404 dan mengarahkan mereka ke konfigurasi hash:

<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>

Dalam kode js saya, saya harus menanganinya dengan baseNamekonfigurasi untuk react-router. Pertama-tama, pastikan dependensi Anda saling beroperasi, saya telah menginstal history==4.0.0yang tidak kompatibel dengan react-router==3.0.1.

Ketergantungan saya adalah:

  • "history": "3.2.0",
  • "reaksi": "15.4.1",
  • "react-redux": "4.4.6",
  • "react-router": "3.0.1",
  • "react-router-redux": "4.0.7",

Saya telah membuat history.jsfile untuk memuat riwayat:

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;

Potongan kode ini memungkinkan untuk menangani 404 yang dikirim oleh server dengan hash, dan menggantinya dalam sejarah untuk memuat rute kami.

Anda sekarang dapat menggunakan file ini untuk mengkonfigurasi toko Anda dan file Root Anda.

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;

Semoga ini bisa membantu. Anda akan melihat dengan konfigurasi ini saya menggunakan injektor redux dan injektor saga homebrew untuk memuat javascript secara asinkronisasi melalui perutean. Jangan pedulikan garis tesis ini.

Guillaume Cisco
sumber
3

Anda sekarang dapat melakukan ini dengan Lambda @ Edge untuk menulis ulang path

Berikut adalah fungsi lambda @ Edge yang berfungsi:

  1. Buat fungsi Lambda baru, tetapi gunakan salah satu Cetak Biru yang sudah ada, bukan fungsi kosong.
  2. Cari "cloudfront" dan pilih generasi respons-cloudfront dari hasil pencarian.
  3. Setelah membuat fungsi, ganti konten dengan yang di bawah ini. Saya juga harus mengubah runtime node menjadi 10.x karena cloudfront tidak mendukung node 12 pada saat penulisan.
'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);
};

Dalam perilaku cloudfront Anda, Anda akan mengeditnya untuk menambahkan panggilan ke fungsi lambda itu di "Permintaan Penampil" masukkan deskripsi gambar di sini

Tutorial Lengkap: https://aws.amazon.com/blogs/compute/implementing-default-directory-indexes-in-amazon-s3-backed-amazon-cloudfront-origins-using-lambdaedge/

Loren
sumber
1
Contoh kode Anda hanya melewatkan satu baris:return callback(null, request);
Pherrymason
2

Jika Anda mendarat di sini mencari solusi yang bekerja dengan React Router dan AWS Amplify Console - Anda sudah tahu bahwa Anda tidak dapat menggunakan aturan pengalihan CloudFront secara langsung karena Amplify Console tidak memaparkan CloudFront Distribution untuk aplikasi.

Solusi, bagaimanapun, sangat sederhana - Anda hanya perlu menambahkan aturan redirect / tulis ulang di Amplify Console seperti ini:

Memperkuat aturan penulisan ulang konsol untuk React Router

Lihat tautan berikut untuk info lebih lanjut (dan aturan ramah-salin dari tangkapan layar):

Yaro
sumber
0

Saya sendiri sedang mencari jawaban untuk ini. S3 tampaknya hanya mendukung pengalihan, Anda tidak bisa hanya menulis ulang URL dan secara diam-diam mengembalikan sumber daya yang berbeda. Saya sedang mempertimbangkan untuk menggunakan skrip build saya untuk membuat salinan index.html saya di semua lokasi jalur yang diperlukan. Mungkin itu juga akan berhasil untuk Anda.

Ed Thomas
sumber
2
Membuat file indeks untuk setiap jalur juga terlintas di benak saya, tetapi akan sulit untuk memiliki jalur dinamis seperti example.com/groups/5/show . Jika Anda melihat jawaban saya untuk pertanyaan ini, saya percaya itu memecahkan sebagian besar masalah. Ini sedikit peretasan, tapi setidaknya berhasil.
Mark Nutter
Lebih baik menggunakan di belakang server nginx dan mengembalikan index.html untuk semua url yang masuk. Saya telah berhasil melakukan ini dengan penyebaran heroku dari aplikasi bara.
moha297
-3

Hanya dengan memberikan jawaban yang sangat sederhana. Cukup gunakan strategi lokasi hash untuk router jika Anda hosting di S3.

export const AppRoutingModule: ModuleWithProviders = RouterModule.forRoot (rute, {useHash: true, scrollPositionRestoration: 'enabled'});

Meester Over
sumber