Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nuxt application returns 404 when dynamic routes are refreshed (Tomcat Server)

I'm doing the following:
- Production Build: npm run generate
- I copy the dist folder into the Tomcat Webapps, and it works fine
- Whenever I refresh a dynamic route, it shows 404

URLs that work:

https://ip:port/entryPath/dashboard/user

URLs that don't work:

https://ip:port/entryPath/dashboard/user/123
https://ip:port/entryPath/dashboard/user/123/settings
https://ip:port/entryPath/dashboard/user/123/privacy

I want to be able to share an URL such as:

https://ip:port/entryPath/dashboard/user/123/activity

So other users just clicking the URL should be directly able to access it. But it just ends up with a 404, no matter where I deploy.

Please Note:
My intention is to deploy the dist folder contents on Tomcat webapps folder.

like image 649
bacon-delight Avatar asked Feb 04 '23 18:02

bacon-delight


2 Answers

When your app is running as a single page app (SPA), everything is happening within that original entry page - you are not actually loading a new page when you navigate between routes. As long as you don't refresh the page, it doesn't matter whether or not those routes correspond to actual html files on the server because your SPA knows what do. However, if you reload the page or enter from a dynamic route, if there's no html file at that URL, a static server will serve a 404 because it doesn't know what else to do.

You might understand all of that already since you're running generate to build out static pages. But Nuxt's generate command only knows to generate pages for the *.vue files in your pages directory. Dynamic routes are ignored. Check your dist folder that you uploaded - there should be a corresponding path for each of your working URLs (which correspond to your pages directory), but you won't find files for your dynamic routes.

To solve this, you need to give an array of dynamic routes to the generate command. You can do that by adding something like this to nuxt.config.js:

  generate: {
    // create an array of all routes for generating static pages
    // careful, this is only used by `npm run generate`. These must match SPA mode routes
    routes: function () {
      return axios.get(
        'https://jsonplaceholder.typicode.com/users'
      )
      .then((response) => {
          let users = response.data.map((user) => {
              return {
                route: '/users/' + user.id,
                payload: user
              }
          });
          return ['/some-other-dynamic-route-or-array-of-routes/', ...users]
       });
     }
   }

Here's a nice article about static sites with Nuxt with examples

You'll know your pages are being generated as expected if you see them in your dist directory. Obviously for something like your user pages, this approach means that new users pages created after your build will not exist until your next build. You could try using the SPA fallback to load the SPA for unmatched routes.

Edit: You could also use hash mode. So instead of https://ip:port/entryPath/dashboard/user/123 your URL would be https://ip:port/entryPath#dashboard/user/123. In this case, the server is always requesting your root SPA index.html, which will use the route to determine what to do (so it should perform as it does now when you navigate to that route). If you do it this way, you will just be using SPA mode and don't need to generate any of your pages at all. This is not good for SEO, but you will have shareable URLs that work right away.

like image 78
meanjean Avatar answered Feb 06 '23 08:02

meanjean


You should setup your server to always request your spa's index.html for all routes that are not a file.

.htaccess

<ifModule mod_rewrite.c>
 RewriteEngine On
 RewriteCond %{REQUEST_FILENAME} !-f
 RewriteCond %{REQUEST_FILENAME} !-d
 RewriteRule (.*) index.html [QSA,L]
</ifModule>
like image 37
Pushkar Raj Avatar answered Feb 06 '23 08:02

Pushkar Raj