skip to Main Content

I’m trying to create an SSG site with Nuxt.js.
When I access a route that isn’t set in the generate property of nuxt.config.js,
I want to display the contents of a 404 page without changing the URL.(using htaccess)

The following is the site under construction

http://we-are-sober.d3v-svr.com/xxxx

This is working as expected.

http://we-are-sober.d3v-svr.com/user/xxxx

This does not work as expected.

The contents of page 404 are displayed for a moment, but soon after that, the process based on the dynamic route of "user/_id.vue" is executed.

The point of the problem is that the non-existent route behaves as if it exists.
Does anyone know how to solve this problem?

Here is the source code.
https://github.com/yhirochick/rewrite_test

404.vue

https://github.com/yhirochick/rewrite_test/blob/master/pages/404.vue

user/_id.vue

https://github.com/yhirochick/rewrite_test/blob/master/pages/user/_id.vue

nuxt.config.js

https://github.com/yhirochick/rewrite_test/blob/master/nuxt.config.js#L43-L45

.htaccess

https://github.com/yhirochick/rewrite_test/blob/master/static/.htaccess

I am Japanese. The above text is based on Google Translate.
It may be difficult to understand, but thank you.

2

Answers


  1. Chosen as BEST ANSWER

    It's a tricky way, but I've found the code that works as I want.

    https://fes.d3v-svr.com/users/xxxxxx It's works that I expect.

    • User xxxxxx doesn't exist
    • Display 404 page
    • The URL /users/xxxxxx as it is

    First, simply set .htaccess to rewrite non-exist page to 404 page

    ErrorDocument 404 /no-user/index.html
    

    Only above, Nuxt execute base on URL /users/xxxxxx/ and re-render the page as "UserXXXXXX" even he is not exist.

    To avoid this, users/_id.vue is like bellow.

    template

    <template>
      <div v-if="ssr">User name: {{ user.name }}</div>
    </template>
    

    script

    <script>
    export default {
      asyncData({ payload }) {
        return { user: payload, ssr:true }
      },
    }
    </script>
    

    It seems to be if a template is empty, nuxt will not execute the script depends on the URL.

    It's very tricky, so I'll continue to how it is works.


  2. My way of handling this kind of issue while minimizing the API calls required are following those steps:

    • generate a brand new Nuxt project
    • install axios: yarn add -D axios
    • add this to the nuxt.config.js file
    import axios from 'axios'
    
    export default {
      ...
      generate: {
        routes: async () => {
          const users = await axios.get('https://jsonplaceholder.typicode.com/users')
          return users.data.map((user) => ({
            route: `/users/${user.id}`,
            payload: user,
          }))
        },
        fallback: 'no-user.html', // this one is not needed anymore if you ditch the redirect!
      },
    }
    

    This will generate all the needed routes, while keeping the calls to a minimum thanks to payload that will be passed later on to the pages. More info can be found in the docs.

    • then, creating the /pages/users/_id.vue page does the trick
    <template>
      <div>
        <div v-if="user">User name: {{ user.name }}</div>
        <div v-else-if="error">{{ error }}</div>
      </div>
    </template>
    
    <script>
    export default {
      asyncData({ payload }) {
        if (payload && Object.entries(payload).length) return { user: payload }
        else return { error: 'This user does not exist' } // this will also catch users going to `/users/`
      },
    }
    </script>
    
    • create some no-user.vue page, error.vue layout and you should be gucci

    At the end, we have 10 users from the mocked API. So those are the following cases:

    • if we go to /users/5, the user is already static so we do have it’s info without any extra API call
    • if we go to /users/11, the user was not present at the time of build, hence he is not here and we are displaying an error
    • if we go to /users, we will still be sent to the /pages/users/_id page, but since the :id will be optional there, it will error and still display the error, an index.vue can of course handle this case

    My github repo for this one can be found here: https://github.com/kissu/so-nuxt-generate-placeholder-users


    This approach is called full static in Nuxt, as explained here: https://nuxtjs.org/announcements/going-full-static/

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search