Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

What is the best way to load json. #123

Closed
husayt opened this issue Jan 11, 2017 · 10 comments
Closed

What is the best way to load json. #123

husayt opened this issue Jan 11, 2017 · 10 comments
Labels

Comments

@husayt
Copy link
Contributor

husayt commented Jan 11, 2017

I have a json file with data to initialise my pages. I put it in /static folder e.g. /static/data.json. Then I use axios.get() to load it from /data.json. That works on the client, but fails on the server.

I have these questions, which I think will be very useful for wider audience as well:

  1. What is wrong with the example below?
  2. Is /static the best place to put data files?
  3. is loading them via axios the best way ?
  4. What if I want to load from 3 different locations for server, for client and for static build?
 export default {
    data({ req, params, store }) {
      
      return axios.get('/data.json')
        .then((res) => {
          return {
            authors: res.data
          }
        })
    }
  }

Thanks in advance

@SkaterDad
Copy link

Is this a file you will be changing often on the fly?

If this configuration can be baked into the builds, another option could be to import the JSON file in the components that need it, utilizing Webpack's JSON loader? Or convert it to a JS module and export the values.

@Atinux
Copy link
Member

Atinux commented Jan 12, 2017

Hi @husayt

To answer your questions:

What is wrong with the example below?

When the http call is made from the server, axios has no idea that you're on http://localhost:3000, so it can't call the route /data.json. You have to give the full url.

It can be made by setting a baseURL variable in the env of your nuxt.config.js:

// nuxt.config.js
module.exports = {
  env: {
    baseURL: (process.env.NODE_ENV === 'production' ? 'http//your-url' : 'http://localhost:3000')
  }
}

Then in you data method:

async asyncData({ req, params, store }) {
  const authors = await axios.get(process.env.baseURL + '/data.json').then(res => res.data)

  return { authors }
  })
}

I recommend to use the axios module to avoid giving a baseUrl environment key.

Is static/ the best place to put data files?

If you want to access them via an http call, it's a good place yes.

Is loading them via axios the best way ?

Not really since from the server-side, you will have to make an HTTP call, which is not the best for performances.

So you can load the file from the server-side using fs.readFile to solve this (and also avoid to set the baseURL in the nuxt.config.js):

async asyncData({ req, isServer, params, store }) {
  const data = {}

  if (process.server) {
    data.authors = JSON.parse(require('fs').readFileSync('../static/data.json', 'utf8'))
  } else {
    data.authors = await axios.get('/data.json').then(res => res.data)
  }

  return { authors }
}

Furthermore, if your data does not change often (and I guess it does not if it's in the static folder), then importing the file via Webpack is a great solution (credits to @SkaterDad for pointing it out).

<script>
import authors from '~/static/data.json'

export default {
  asyncData ({ params }) {
    return { authors }
  }
}
</script>

The other advantage of using Webpack is that you don't have to expose this data in the static/ folder, you can have a data folder an do import authors from '~/data/authors.json'

Another advantage, is that you can use the code-splitting feature to avoid putting the data.json inside the page bundle and load it asynchronously on the client-side (so it could be cached separately):

<script>
const getAuthors = () => import('~/data/authors.json').then(m => m.default || m)

export default {
  async asyncData ({ req }) {
    const authors = await getAuthors()

    return { authors }
  }
}
</script>

The only disadvantage of using webpack is that data.json is linked to your bundle. In development there is no problem since Webpack will listen on the file and re-bundle everytime data.json changes. But in production, if you're changing the data file directly on your server, you will have to run nuxt build manually to reflect the changes.

What if I want to load from 3 different locations for server, for client and for static build?

I'm not sure to understand the question, but all the code example I wrote works for all of them :)

@Atinux Atinux closed this as completed Jan 12, 2017
@husayt
Copy link
Contributor Author

husayt commented Jan 15, 2017

@Atinux thanks for very detailed reply. This will be very useful addition to FAQ page.

We covered the following data file reading patterns:

  1. to ajax download resources from both server/client (with axios) via baseurl, based on environment
  2. read local files on server side via fs.readFile
  3. import with webpack

There might be even more patterns.

So all is cool with running it in dev mode. Now I hit two problems running from static generated files (after generate completed).

  1. the data is embedded in window.___NUXT___ variable in the html and I would prefer it to be loaded from external file
  2. When I open the page I can see all the information from the file ( basically list of names), but then in two seconds the list disappears. I have been trying to debug to catch what event is causing it, but maybe you are aware of something like that.

Thanks

@Atinux
Copy link
Member

Atinux commented Jan 16, 2017

@husayt

The data embedded in window.__NUXT__ is required to hydrate the application before mounting it, this cannot be loaded from an external file.

For your error you're experiencing, can you provide me some code samples so I can reproduce this behaviour on my setup?

@Atinux Atinux mentioned this issue Jan 17, 2017
@husayt
Copy link
Contributor Author

husayt commented Jan 21, 2017

Hi @Atinux, thanks for detailed reply.

As for disappearing data here is the screen gif, showing that data disappears few seconds after loading.

sozler

Here is the code:

<template>
  <section class="container">
  
    <h1 class="title">    {{title}}</h1>
    <li v-for="author in authors">
      <nuxt-link :to="{ name: 'authors-id', params: { id: author.id } }">{{ author.text }}</nuxt-link>
    </li>
  </section>
  
</template>

<script>
  import {axiosGet} from '~plugins/util'

  export default {
    data({ env,req,params,store}) {
     return axiosGet(env.baseURL +'rest/authors.json')
        .then((res) => {
          return {
            authors: res.data,
            title: 'Müəlliflər'
          }
        })
    },
    head() {
      return {
        title: this.title
      }
    },
  }
</script>

@patrickrodee
Copy link

@husayt I've encountered the exact same issue. It appears to be an issue with Vue's vdom throwing a mismatch of the server rendered DOM and the virtual DOM. I've encountered it with homegrown Vue SSR and Nuxt. If the Nuxt team can get a fix, that'd be dope.

@NateTheGreatt
Copy link

NateTheGreatt commented Mar 27, 2017

@husayt I'm not sure if this is causing your issue, but you have invalid HTML in your template. Your <li> tag needs to be wrapped in a <ul> tag. Hopefully that will fix the problem.

@max-schu
Copy link

max-schu commented Apr 9, 2017

is there a proper way to automatically webpack assets such as images that are defined in a json file?

@heishung
Copy link

heishung commented Oct 2, 2017

hi i need help i'm try trans variable {{location.slug}} in nuxt-link ,

<nuxt-link :to="{ name: 'location', params: { slug: location.slug} }"> <img alt="" src="~/assets/public/orchidcruise-cabins-suites.png" width="100%"> <div class="product-title has-text-centered"> <span class="text">{{location.name}}</span> </div></nuxt-link>

@lock
Copy link

lock bot commented Nov 5, 2018

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@lock lock bot locked as resolved and limited conversation to collaborators Nov 5, 2018
@danielroe danielroe added the 2.x label Jan 18, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
9 participants