S3 Sitio web estático Hosting Ruta Todas las rutas a Index.html

250

Estoy usando S3 para alojar una aplicación de JavaScript que usará HTML5 pushStates. El problema es que si el usuario marca alguna de las URL, no se resolverá en nada. Lo que necesito es la capacidad de tomar todas las solicitudes de URL y servir el index.html raíz en mi bucket de S3, en lugar de simplemente hacer una redirección completa. Entonces mi aplicación javascript podría analizar la URL y mostrar la página adecuada.

¿Hay alguna forma de decirle a S3 que sirva index.html para todas las solicitudes de URL en lugar de hacer redirecciones? Esto sería similar a configurar apache para manejar todas las solicitudes entrantes al servir un solo index.html como en este ejemplo: https://stackoverflow.com/a/10647521/1762614 . Realmente me gustaría evitar ejecutar un servidor web solo para manejar estas rutas. Hacer todo desde S3 es muy atractivo.

Mark Nutter
fuente
¿Ha encontrado una solución para esto?
w2lame

Respuestas:

302

Es muy fácil resolverlo sin trucos de URL, con la ayuda de CloudFront.

  • Crear un cubo S3, por ejemplo: reaccionar
  • Cree distribuciones de CloudFront con esta configuración:
    • Objeto raíz predeterminado : index.html
    • Nombre de dominio de origen : dominio de depósito S3, por ejemplo: react.s3.amazonaws.com
  • Vaya a la pestaña Páginas de error , haga clic en Crear respuesta de error personalizada :
    • Código de error HTTP : 403: Prohibido (404: No encontrado, en caso de sitio web estático S3)
    • Personalizar respuesta de error : sí
    • Ruta de la página de respuesta : /index.html
    • Código de respuesta HTTP : 200: OK
    • Haga clic en Crear
lenaten
fuente
8
Gracias. La mejor respuesta hasta ahora.
jgb
y lo que no es tan obvio es que mantengas la ubicación para que puedas hacer rutas "naturales".
Lukasz Marek Sielski el
55
esto funcionó de maravilla para mí, solo el código de error personalizado que necesitaba era 404, no 403
Jeremy S.
44
Un poco pirateo, pero funciona genial :) Sería bueno si CloudFront simplemente nos deja mapear un rango de rutas a un archivo S3 (sin redireccionamiento).
Bob
3
Esto no está funcionando para mí. Esta solución siempre redirige a la página de inicio y no a las páginas correctas ...
Jim
201

La forma en que pude hacer que esto funcionara es la siguiente:

En la sección Editar reglas de redireccionamiento de la consola S3 para su dominio, agregue las siguientes reglas:

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

Esto redirigirá todas las rutas que den como resultado un 404 no encontrado a su dominio raíz con una versión hash-bang de la ruta. Entonces http://yourdomainname.com/posts redirigirá a http://yourdomainname.com/#!/posts siempre que no haya un archivo en / posts.

Sin embargo, para usar HTML5 PushStates, debemos tomar esta solicitud y establecer manualmente el pushState adecuado en función de la ruta hash-bang. Agregue esto al principio de su archivo index.html:

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

Esto toma el hash y lo convierte en un HTML5 pushState. A partir de este momento, puede usar pushStates para tener rutas que no sean hash-bang en su aplicación.

Mark Nutter
fuente
44
¡Esta solución funciona muy bien! De hecho, angularjs realizará automáticamente el historial pushState si el modo html está configurado.
wcandillon
1
Esto fallará con la versión anterior de IE si tiene parámetros GET incluidos en sus URL, ¿correcto? ¿Cómo se soluciona ese problema?
clexmond
3
¡Gracias! Esto funcionó bien para mí en la red troncal con un pequeño ajuste. Agregué un cheque para navegadores antiguos: <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
Tuvo éxito con react-routeresa solución usando HTML5 pushStates y<ReplaceKeyPrefixWith>#/</ReplaceKeyPrefixWith>
Felix D.
55
No funciona en safari y es un gran problema con la estrategia de implementación. Escribir un pequeño js para redirigir es una especie de enfoque en mal estado. Además, el número de redireccionamientos también es un problema. Estoy tratando de averiguar si hay una manera para que todas las URL de S3 apunten a index.html siempre.
moha297
129

Hay pocos problemas con el enfoque basado en S3 / Redirect mencionado por otros.

  1. Las redirecciones mutuas se producen a medida que se resuelven las rutas de su aplicación. Por ejemplo: www.myapp.com/path/for/test se redirige como www.myapp.com/#/path/for/test
  2. Hay un parpadeo en la barra de URL cuando el '#' aparece y desaparece debido a la acción de su marco de SPA.
  3. El SEO se ve afectado porque - '¡Oye! Es Google forzando su mano en redirecciones '
  4. El soporte de Safari para su aplicación va por un momento.

La solucion es:

  1. Asegúrese de tener la ruta de índice configurada para su sitio web. Principalmente es index.html
  2. Eliminar reglas de enrutamiento de configuraciones S3
  3. Coloque un Cloudfront frente a su cubo S3.
  4. Configure las reglas de la página de error para su instancia de Cloudfront. En las reglas de error especifique:

    • Código de error HTTP: 404 (y 403 u otros errores según la necesidad)
    • Error de almacenamiento en caché TTL mínimo (segundos): 0
    • Respuesta personalizada: sí
    • Ruta de la página de respuesta: /index.html
    • Código de respuesta HTTP: 200

      1. Para las necesidades de SEO + asegurándose de que su index.html no se almacena en caché, haga lo siguiente:
    • Configure una instancia EC2 y configure un servidor nginx.

    • Asigne una IP pública a su instancia EC2.
    • Cree un ELB que tenga la instancia EC2 que creó como instancia
    • Debería poder asignar el ELB a su DNS.
    • Ahora, configure su servidor nginx para que haga lo siguiente: Proxy_pass todas las solicitudes a su CDN (solo para index.html, sirva otros activos directamente desde su cloudfront) y para los bots de búsqueda, redirija el tráfico según lo estipulado por servicios como Prerender.io

Puedo ayudar con más detalles con respecto a la configuración de nginx, solo deje una nota. Lo he aprendido por las malas.

Una vez que la distribución de la distribución frontal de la nube. Invalide su caché de Cloudfront una vez para estar en el modo prístino. Pulse la url en el navegador y todo debería estar bien.

moha297
fuente
66
dado que S3 responde con un 403 Prohibido cuando no existe un archivo, creo que el paso 4 anterior también debe duplicarse para el código de error Http 403
Andreas
44
Para mí esta es la única respuesta que da lugar a un esperado (aceptado) el comportamiento
mabe.berlin
1
@ moha297 en el punto 5 ¿Básicamente está configurando su sitio para buscar desde nginx que luego representa desde CDN (a excepción de index.html y solicitudes de rastreador)? Si ese es el caso, ¿no perderías el beneficio de los servidores periféricos CDN?
Rahul Patel
2
@ moha297 ¿puede explicar este comentario: "Nunca debe servir index.html desde un CDN"? No veo el problema con la publicación de index.html desde S3 con CloudFront.
Carl G
1
Consulte stackoverflow.com/a/10622078/4185989 para obtener más información sobre cómo se trata un TTL de 0 (versión abreviada: Cloudfront lo almacena en caché pero se envía una If-Modified-Sincesolicitud GET al origen); puede ser una consideración útil para las personas que no desean configurar un servidor como en el paso 5.
jmq
18

Es tangencial, pero aquí hay un consejo para aquellos que usan la biblioteca React Router de Rackt con el historial del navegador (HTML5) que desean alojar en S3.

Supongamos que un usuario visita /foo/bearsu sitio web estático alojado en S3. Dada la sugerencia anterior de David , las reglas de redireccionamiento los enviarán a /#/foo/bear. Si su aplicación está construida utilizando el historial del navegador, esto no servirá de mucho. Sin embargo, su aplicación se carga en este momento y ahora puede manipular el historial.

Al incluir el historial de Rackt en nuestro proyecto (consulte también Uso de historiales personalizados del proyecto React Router), puede agregar un oyente que conozca las rutas del historial de hash y reemplazar la ruta según corresponda, como se ilustra en este ejemplo:

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

Recordar:

  1. La regla de redireccionamiento S3 de David se dirigirá /foo/beara/#/foo/bear .
  2. Su aplicación se cargará.
  3. El oyente del #/foo/bearhistorial detectará la notación del historial.
  4. Y reemplace la historia con la ruta correcta.

LinkLas etiquetas funcionarán como se espera, al igual que todas las demás funciones del historial del navegador. El único inconveniente que he notado es la redirección intersticial que ocurre en la solicitud inicial.

Esto fue inspirado por una solución para AngularJS , y sospecho que podría adaptarse fácilmente a cualquier aplicación.

Michael Ahlers
fuente
2
Esto me ayudó Michael, ¡Gracias! Es posible que desee cambiar su referencia del historial y simplemente usar BrowserHistory. es decirbrowserHistory.listen
Marshall Moutenot
¡De nada! Encantado de ayudar. Además, acepté, y para este caso de uso en particular, actualicé el fragmento para resolver una advertencia de desaprobación de React Router.
Michael Ahlers
Con el lanzamiento de react-router v3.0.0 esto no funciona, porque react-router v3.0.0 usa History v3.0.0
Varand Pezeshkian
¿Alguna idea de cómo evitar el loop de llamadas infinitas history.listen? Causado al reemplazar el camino, supongo.
Mirko Flyktman
14

Veo 4 soluciones a este problema. Los primeros 3 ya estaban cubiertos en respuestas y el último es mi contribución.

  1. Establezca el documento de error en index.html.
    Problema : el cuerpo de la respuesta será correcto, pero el código de estado será 404, lo que perjudica al SEO.

  2. Establece las reglas de redireccionamiento.
    Problema : URL contaminada #!y la página parpadea cuando se carga.

  3. Configurar CloudFront.
    Problema : todas las páginas devolverán 404 desde el origen, por lo que debe elegir si no almacenará en caché nada (TTL 0 como se sugiere) o si almacenará en caché y tendrá problemas al actualizar el sitio.

  4. Presta todas las páginas.
    Problema : trabajo adicional para renderizar páginas, especialmente cuando las páginas cambian con frecuencia. Por ejemplo, un sitio web de noticias.

Mi sugerencia es utilizar la opción 4. Si prescribe todas las páginas, no habrá errores 404 para las páginas esperadas. La página se cargará bien y el marco tomará el control y actuará normalmente como un SPA. También puede configurar el documento de error para que muestre una página genérica error.html y una regla de redirección para redirigir los errores 404 a una página 404.html (sin el hashbang).

Con respecto a los errores prohibidos 403, no dejo que sucedan en absoluto. En mi aplicación, considero que todos los archivos dentro del depósito de host son públicos y configuro esto con la opción de todos con el permiso de lectura . Si su sitio tiene páginas privadas, permitir que el usuario vea el diseño HTML no debería ser un problema. Lo que necesita proteger son los datos y esto se hace en el backend.

Además, si tiene activos privados, como fotos de usuario, puede guardarlos en otro depósito. Porque los activos privados necesitan el mismo cuidado que los datos y no se pueden comparar con los archivos de activos que se utilizan para alojar la aplicación.

Zanon
fuente
1
y su sitio tiene un gran ejemplo de uso para pre-renderizar todas las páginas. zanon.io/posts/… .- Gracias
frekele 01 de
¿Este cuarto enfoque se dirige al usuario que recarga la URL pushState? Maneja la navegación muy bien, pero en una recarga, aún llegará al servidor.
Alpha
@Alpha, no estoy seguro de haber entendido su pregunta correctamente, pero en una recarga, actuaría como una nueva solicitud. S3 recibiría la solicitud y devolvería la página prerrendida nuevamente. No hay servidor en este caso.
Zanon
@ Zanon Ah, creo que entiendo. Pensé que estaba destinado a almacenar en caché las páginas pre-procesadas y evitar ir a los recursos inexistentes S3. Esto dejaría de lado las rutas que tienen elementos dinámicos, ¿verdad?
Alpha
1
@Zanon Finalmente entiendo, ¡gracias! Sí, a eso me refería. :)
Alpha
13

Me encontré con el mismo problema hoy, pero la solución de @ Mark-Nutter estaba incompleta para eliminar el hashbang de mi aplicación angularjs.

De hecho, debe ir a Editar permisos , hacer clic en Agregar más permisos y luego agregar la Lista correcta en su bucket a todos. Con esta configuración, AWS S3 ahora podrá devolver el error 404 y luego la regla de redireccionamiento captará correctamente el caso.

Así como así: ingrese la descripción de la imagen aquí

Y luego puede ir a Editar reglas de redireccionamiento y agregar esta regla:

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

Aquí puede reemplazar HostName subdominio.domain.fr con su dominio y KeyPrefix #! / Si no utiliza el método hashbang para fines de SEO.

Por supuesto, todo esto solo funcionará si ya ha configurado html5mode en su aplicación angular.

$locationProvider.html5Mode(true).hashPrefix('!');
davidbonachera
fuente
mi único problema con esto es que tienes un flash de hashbang, que no tienes con algo así como una regla nginx. El usuario está en una página y actualiza: / productos / 1 -> #! / Productos / 1 -> / productos / 1
Intellix
1
Creo que debería agregar una regla para un error 403 en lugar de otorgar permisos de lista a todos.
Hamish Moffatt
11

La solución más fácil para hacer que la aplicación Angular 2+ sirva desde Amazon S3 y que funcionen las URL directas es especificar index.html como documentos de índice y error en la configuración del bucket de S3.

ingrese la descripción de la imagen aquí

Sergey Kandaurov
fuente
11
Esta es la misma respuesta de esta respuesta fuertemente rechazada . Funciona bien, pero solo para bodyla respuesta. El código de estado será 404 y dañará el SEO.
Zanon
Porque esto solo funciona para bodysi tienes scripts que importas en headellos, no funcionarán cuando golpees directamente cualquiera de las subrutas en tu sitio web
Mohamed Hajr
4

Dado que el problema sigue ahí, pensé en agregar otra solución. Mi caso fue que quería implementar automáticamente todas las solicitudes de extracción en s3 para realizar pruebas antes de combinarlas y hacerlas accesibles en [mydomain] / pull-request / [pr number] /
(ej. Www.example.com/pull-requests/822/ )

Que yo sepa, los escenarios de reglas no s3 permitirían tener múltiples proyectos en un solo cubo usando el enrutamiento html5, por lo que si bien la sugerencia más votada funciona para un proyecto en la carpeta raíz, no lo hace para múltiples proyectos en sus propias subcarpetas.

Así que señalé mi dominio a mi servidor donde el siguiente trabajo de configuración nginx hizo el trabajo

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

intenta obtener el archivo y, si no lo encuentra, supone que es la ruta html5 y lo intenta. Si tiene una página angular 404 para rutas no encontradas, nunca llegará a @not_found y obtendrá la página angular 404 devuelta en lugar de archivos no encontrados, lo que podría solucionarse con alguna regla en @get_routes o algo así.

Tengo que decir que no me siento muy cómodo en el área de configuración de nginx y el uso de expresiones regulares para el caso, conseguí que funcione con alguna prueba y error, así que mientras esto funciona, estoy seguro de que hay margen de mejora y por favor comparta sus pensamientos .

Nota : elimine las reglas de redireccionamiento s3 si las tenía en la configuración S3.

y por cierto funciona en Safari

Andrew Arnautov
fuente
hola ... gracias por la solución ... ¿dónde colocas este archivo nginx conf para la implementación de s3? ¿es lo mismo que beanstalk elástico donde necesito crear la carpeta .extensions y ponerla en el archivo proxy.config?
user3124360
@ user3124360 No estoy seguro sobre el bean bean apilado, pero en mi caso apunto mi nombre de dominio a la instancia ec2 y tengo la configuración nginx allí. Entonces la solicitud va CLIENTE -> DNS -> EC2 -> S3 -> CLIENTE.
Andrew Arnautov el
Sí, estoy haciendo algo muy similar ... con la configuración de nginx aquí github.com/davezuko/react-redux-starter-kit/issues/1099 ... gracias por publicar su archivo conf ... veo cómo desarrollar este EC2 -> Conexión S3 ahora
user3124360
3

Estaba buscando el mismo tipo de problema. Terminé usando una mezcla de las soluciones sugeridas descritas anteriormente.

Primero, tengo un cubo s3 con múltiples carpetas, cada carpeta representa un sitio web react / redux. También uso cloudfront para la invalidación de caché.

Así que tuve que usar Reglas de enrutamiento para admitir 404 y redirigirlas a una configuración 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>

En mi código js, ​​necesitaba manejarlo con una baseNameconfiguración para react-router. En primer lugar, asegúrese de que sus dependencias sean interoperables, ya history==4.0.0que las instalé con las que no era compatible react-router==3.0.1.

Mis dependencias son:

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

He creado un history.jsarchivo para cargar el historial:

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;

Este código permite manejar el 404 enviado por el servidor con un hash y reemplazarlo en el historial para cargar nuestras rutas.

Ahora puede usar este archivo para configurar su tienda y su archivo raíz.

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;

Espero eso ayude. Notarás que con esta configuración utilizo el inyector redux y un inyector de sagas homebrew para cargar JavaScript de forma asincrónica a través del enrutamiento. No importa con estas líneas.

Guillaume Cisco
fuente
3

Ahora puede hacer esto con Lambda @ Edge para reescribir las rutas

Aquí hay una función lambda @ Edge que funciona:

  1. Cree una nueva función Lambda, pero use uno de los Blueprints preexistentes en lugar de una función en blanco.
  2. Busque "cloudfront" y seleccione cloudfront-response-generation de los resultados de búsqueda.
  3. Después de crear la función, reemplace el contenido con el siguiente. También tuve que cambiar el tiempo de ejecución del nodo a 10.x porque cloudfront no era compatible con el nodo 12 en el momento de la escritura.
'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);
};

En sus comportamientos frente a la nube, los editará para agregar una llamada a esa función lambda en "Solicitud de visor" ingrese la descripción de la imagen aquí

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

Loren
fuente
1
Su ejemplo de código pierde solo una línea:return callback(null, request);
Pherrymason
2

Si aterrizó aquí buscando una solución que funcione con React Router y AWS Amplify Console, ya sabe que no puede usar las reglas de redirección de CloudFront directamente, ya que Amplify Console no expone CloudFront Distribution para la aplicación.

Sin embargo, la solución es muy simple: solo necesita agregar una regla de redireccionamiento / reescritura en Amplify Console de esta manera:

Regla Amplify Console Rewrite para React Router

Consulte los siguientes enlaces para obtener más información (y una regla fácil de copiar de la captura de pantalla):

Yaro
fuente
0

Estaba buscando una respuesta a esto yo mismo. Parece que S3 solo admite redireccionamientos, no puede simplemente reescribir la URL y devolver silenciosamente un recurso diferente. Estoy considerando usar mi script de compilación para simplemente hacer copias de mi index.html en todas las ubicaciones de ruta requeridas. Quizás eso también funcione para ti.

Ed Thomas
fuente
2
La generación de archivos de índice para cada ruta también se me pasó por la mente, pero sería difícil tener rutas dinámicas como example.com/groups/5/show . Si ve mi respuesta a esta pregunta, creo que eso resuelve el problema en su mayor parte. Es un truco, pero al menos funciona.
Mark Nutter
Es mejor implementar detrás de un servidor nginx y devolver index.html para todas las URL entrantes. He hecho esto con éxito con el despliegue heroku de aplicaciones Ember.
moha297
-3

Solo para poner la respuesta extremadamente simple. Solo use la estrategia de ubicación hash para el enrutador si está alojando en S3.

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

Meester Over
fuente