stencil-router icon indicating copy to clipboard operation
stencil-router copied to clipboard

Apache configuration for resolving route

Open apiaget opened this issue 7 years ago • 4 comments

Resources: Before submitting an issue, please consult our docs.

Stencil version: (run npm list @stencil/core from a terminal/cmd prompt and paste output below):

@ionic/[email protected] E:\Users\adm\stencil-project
`-- @stencil/[email protected]

Stencil router version :

$ npm list @stencil/router
@ionic/[email protected] E:\Users\adm\stencil-project
`-- @stencil/[email protected]

I'm submitting a ... (check one with "x") [x] bug report [ ] feature request [ ] support request => Please do not submit support requests here, use one of these channels: https://forum.ionicframework.com/ or https://stencil-worldwide.slack.com

Current behavior:

When accessing a stencil PWA hosted with Apache, I can browse in the app without problem. Except if I reload, I get a 404. When accessing a stencil PWA in dev (localhost:3333), I can reload on any path and the route is correctly resolved.

Expected behavior:

The route should be resolved in dev and in prod (Apache hosting)

Steps to reproduce:

  1. Access : https://eaux-vives.shop/
  2. Browse the app using the mouse, no 404 error should arise
  3. On /offres , press F5 : a 404 arise.

I also created a quick video reproducing my problem : https://www.youtube.com/watch?v=31G4-hNpw5g

Related code:

My app-route is as follow :

renderRouter() {
    return (
      <stencil-router>
        <stencil-route-switch>
          <stencil-route url="/" component="page-voucher" exact={true} />
          <stencil-route url="/offres" component="page-offer" />
          <stencil-route url="/info" component="page-info" />
          <stencil-route url='/bon/:voucherId' component='page-voucher-detail' />
        </stencil-route-switch>
      </stencil-router>
    );
  }

  render() {
    return (
      <ion-app>
        <app-header></app-header>

        <main>
          {this.renderRouter()}
        </main>

        
      </ion-app>
    );
  }

The .htaccess is as follow :

SetOutputFilter DEFLATE
AddOutputFilterByType DEFLATE "application/atom+xml" "application/javascript" "application/json" "application/ld+json" "application/manifest+json" "application/rdf+xml" "application/rss+xml" "application/schema+json" "application/vnd.geo+json" "application/vnd.ms-fontobject" "application/x-font-ttf" "application/x-javascript" "application/x-web-app-manifest+json" "application/xhtml+xml" "application/xml" "font/eot" "font/opentype" "image/bmp" "image/svg+xml" "image/vnd.microsoft.icon" "image/x-icon" "text/cache-manifest" "text/css" "text/html" "text/javascript" "text/plain" "text/vcard" "text/vnd.rim.location.xloc" "text/vtt" "text/x-component" "text/x-cross-domain-policy" "text/xml"

# SECTION BEGIN GIT PROTECTION
RedirectMatch 404 /\.git
# SECTION END GIT PROTECTION

RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^ %{REQUEST_SCHEME}://%1%{REQUEST_URI} [R=301,L]

RewriteEngine on
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule (.*) https://eaux-vives.shop/$1 [R=301,L]

<Files sw.js>
	<IfModule mod_headers.c>
		Header set Cache-Control "no-cache"
	</IfModule>
</Files>

Other information:

I tried adding something like that to my htaccess, but, as expected, now everytime I do "F5", I get redirected to the homepage (/) :

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^(.*) / [R=302,NC,L]

I tried several code I could find googling thing like "htaccess configuration PWA/SPA" but couldn't find a working one...

I hope that I gave enough information, if not, I will update any missing information as soon as possible.

Thanks !

apiaget avatar Oct 14 '18 14:10 apiaget

For me it's the contrary with Nginx. In dev mode, I have to hard-reload, otherwise i get the index.html, whereas in prod mode everything works fine.

Do you have some traces ?

Perhaps, try to compare the headers from the initial HTTP request and the one from reload.

kael avatar Oct 14 '18 18:10 kael

You got me on the right track !

By comparing what was served in dev mode and in an Apache 2 production server, I found a solution. I realized that in dev mode, the content of the index.html file is always served, no matter the route. The js loaded in index.html seems to interpret the url.

I simply had to reproduce that behaviour in my .htaccess

Here is what I ended up using :

SetOutputFilter DEFLATE
AddOutputFilterByType DEFLATE "application/atom+xml" "application/javascript" "application/json" "application/ld+json" "application/manifest+json" "application/rdf+xml" "application/rss+xml" "application/schema+json" "application/vnd.geo+json" "application/vnd.ms-fontobject" "application/x-font-ttf" "application/x-javascript" "application/x-web-app-manifest+json" "application/xhtml+xml" "application/xml" "font/eot" "font/opentype" "image/bmp" "image/svg+xml" "image/vnd.microsoft.icon" "image/x-icon" "text/cache-manifest" "text/css" "text/html" "text/javascript" "text/plain" "text/vcard" "text/vnd.rim.location.xloc" "text/vtt" "text/x-component" "text/x-cross-domain-policy" "text/xml"

# SECTION BEGIN GIT PROTECTION
RedirectMatch 404 /\.git
# SECTION END GIT PROTECTION

RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^ %{REQUEST_SCHEME}://%1%{REQUEST_URI} [R=301,L]

RewriteEngine on
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule (.*) https://eaux-vives.shop/$1 [R=301,L]

# here is what I added :
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.html [L]

<Files sw.js>
	<IfModule mod_headers.c>
		Header set Cache-Control "no-cache"
	</IfModule>
</Files>

About the problem you face in dev mode, I neved experienced it, are you using the last version of stencil-router ? I also realized that some bugs I had a few days ago during builds disapearded when I switched from stencil 0.13.2 to 0.14next...

apiaget avatar Oct 14 '18 19:10 apiaget

Nice to read you've found a solution.

For the hard-reload thing, it's always been that way with Stencil & Nginx. Perhaps it's due to a misconfiguration on Nginx, although not sure. Concretely, when testing the app on mobile in dev mode, I have to flush the browser (including IndexedDB) to be able to reload, otherwise i get the index.html.

In all cases, I'm forcing a reload of the service worker using a no-cache header following this article.

Can you elaborate about the index.html file ? I'm actually facing a similar issue with routing, but with an edgy case where the same request doesn't end the same way depending on the user-agent (200 with one, 404 with another one), I need to debug more to determine if it's coming from Nginx or from Stencil-Router.

kael avatar Oct 14 '18 20:10 kael

I quick installed nginx 1.13.1 (on windows 10) and configured my vhost as follow :

server
{
	listen 127.0.0.1:80;
	server_name "eaux-vives3.shop";
	root "E:/users/adm/stencil-project/www/";

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

With this configuration and the one for apache 2 a few posts ago, I could get my application working the same way in :

  • dev (using npm start)
  • apache 2
  • nginx 1.13.2

Regarding the index.html file, as it is a single page application, all the logic/html/templates/etc. are loaded through JS files. And theses JS files are called in the index.html file. I started using stencil a few days ago so I am in no way an expert but here is what I understood :

  1. User access any url of the single page application
  2. The server has to return the content of index.html (without "editing" the url)
  3. Some JS files are loaded
  4. stencil-router located in one of the JS files "convert" the url to a route
  5. according to that route, stencil-router will load the correct components/css/etc and display the correct page.

The behaviour explained allow the users to navigate through the app :

  • by accessing www.my-website.com then navigating through the website with the different internal links (no problem, status 200 all the time)
  • by accessing directly to a specific page (ex : www.my-website.com/movies/1) (this one led to a 404 before the adjustments in the vhosts)

I should add that all my link in the app are generated using the stencil-route-link component. When I was only using a tags, I had problems (I do not remember exactly which... --'').

apiaget avatar Oct 15 '18 17:10 apiaget