The problem with deep routes in a single-page application on Firebase hosting

(Updated below with a bit more info)

We have a one-page reaction-based web application that lives in Firebase Hosting. We used hash-based routing to this point (e.g. mysite.com/#/path/to/content ). We introduced the React Router, which allows us to have more beautiful URLs (for example, mysite.com/path/to/content ), but now the application does not load when we go directly to the deep route. Details below:

Using React Router required us to use URL rewriting in Firebase Hosting. The directions are pretty simple - it seems all you have to do is the following:

 "rewrites": [ { "source": "**", "destination": "/index.html" } ] 

... inside the firebase.json file. In fact, our full firebase.json file looks like this:

 { "firebase": "", "public": "dist", "rules": "rules.json", "ignore": [ "firebase.json", "**/.*", "**/*.map", "**/node_modules/**" ], "rewrites": [ { "source": "**", "destination": "/index.html" } ] } 

There is nothing complicated (we do firebase deploy -f in our build script if you are wondering why the firebase argument firebase empty). The rules.json file is even simpler:

 { "rules":{ ".write":"true", ".read":"true" } } 

When I download the application by going to the base URL and starting the navigation, everything is fine. If I go directly to the route at the same level (e.g. mysite.com/path ), this also works.

BUT

If I go directly to a deep-level route, or even to a top-level route with a trailing slash (for example, mysite.com/path/ or mysite.com/path/to/content ), the application does not load.

In particular, what happens when the index.html page is loaded, and then the browser loads our bundle.js file created by webpack, which is referenced in index.html , but the fact that Firebase Hosting returns for this JS file is the contents of the file index.html. So, predictably, what we see in the browser console is an error:

Uncaught SyntaxError: Unexpected token <

... on line 1 of the "package file". If I look at the contents of the package file in Chrome dev tools, line 1 of the package file will literally be like this:

<!doctype html>

... then it follows the rest of the HTML from the index.html file.

There seems to be a rule of rewriting the Firebase URL: "Oh, you are trying to link to a JS file - I see that I have to return the contents of index.html for everything, so here you go." But it cannot always be, or the site will never work under any circumstances. So why does it work if I start from the root site, but it breaks if I embed a deep URL in the application? I have no idea.

If this helps, here is how my index.html file refers to the package file:

 <script src="bundle.ce843ef7a2ae68e9e319.js"></script></body> 

So, this seems like a problem with Firebase hosting, but I could also see that maybe I didn’t understand React Router at some level, and so I somehow messed up with the client code in such a way that it forces the server to return the wrong one thing.

Here I hope this is some kind of stupid configuration that we are missing. Any help is appreciated!

Thanks!

UPDATE: I deleted our application so that it only returned β€œhello world”, which bypasses all React-based materials, including the React Router, and the problem persists, so I no longer think it has something to do with React-Router although I believe that there is still a slight chance that this might have something to do with React.

+8
reactjs webpack react-router firebase firebase-hosting
source share
3 answers

I heard from Firebase Hosting. Apparently, the bundle.js linked file in our index file needed a slash in front of it to make it an absolute path. So:

 <script src="/bundle.js"></script> 

... instead of this:

 <script src="bundle.js"></script> 

If someone else makes the same stupid mistake, I hope this is helpful.

+11
source share

[TL; DR]

This answer is intended only for educational purposes and for an in-depth study of the problem statement and its solution. For copy / paste purposes, see This answer provided by @hairbo . This is a short version and answers the question simply and beautifully.

Each link to resources such as images, css, js can be referenced in three ways:

1) The Absolute Path

 <script src="http://app-url.com/bundle.js"></script> 

This is an absolute path, and the resource will be loaded from the specified path without first processing the provided path.

2) relative path

 <script src="bundle.js"></script> 

This is a relative path, and it refers to a resource file as if it were in the current working directory. That is, when you are on app-url.com/lvl-1 relative path becomes app-url.com/bundle.js which does not cause problems, because in fact it is the path to the resource.

problem

But when you go to another level, that is, app-url.com/lvl-1/lvl-2 , the current working level becomes app-url.com/lvl-1/ and the relative path is processed as app-url.com/lvl-1/bundle.js but this is not a resource path. Therefore, the index.html file behaves incorrectly because it cannot load the required files.

3) Root relative path

 <script src="/bundle.js"></script> 

Adding a slash (/) before the relative path makes it the root relative path. In this case, all non-absolute paths are considered as root paths in the current area. That is, in this case, the path to the /bundle.js resource /bundle.js treated as app-url.com/bundle.js even if the current working level URL is app-url/lvl-1/lvl-2/lvl-3/... app-url.com/bundle.js is equal to app-url/lvl-1/lvl-2/lvl-3/...

Solution Do not use ~ relative paths ~. Either use absolute paths or root relative paths in all files. Thus, each path will be considered expected.

0
source share

I had the same problem and I fixed adding rewrite rules to my firebase.json file.

This is what my firebase.json file looks like.

  { "hosting": { "public": "webApp/build", "ignore": [ "firebase.json", "**/.*", "**/node_modules/**" ], "cleanUrls": true, "rewrites": [ { "source": "**", "destination": "/index.html" } ] }, "functions": { "source": "functions" } } 

sorry for my english, i'm still learning.

0
source share

All Articles