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

Comments

Projects
None yet
8 participants
@husayt
Copy link
Collaborator

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

This question is available on Nuxt.js community (#c100)
@SkaterDad

This comment has been minimized.

Copy link

commented Jan 11, 2017

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

This comment has been minimized.

Copy link
Member

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:

data({ req, env, params, store }) {
  return axios.get(env.baseURL + '/data.json')
  .then((res) => {
    return {
      authors: res.data
     }
  })
}

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 great 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):

data({ req, isServer, params, store }) {
  // server-side logic
  if (isServer) {
    let data = JSON.parse(require('fs').readFileSync('static/data.json', 'utf8'))
    return { authors: data }
  }
  // client-side logic
  return axios.get('/data.json')
  .then((res) => {
    return {
      authors: res.data
     }
  })
}

Furthermore, @SkaterDad got a point, 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 the best solution.

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

export default {
  data ({ 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:

<script>
const authorsPromise = process.BROWSER_BUILD ? System.import('~/data/authors.json') : Promise.resolve(require('~/data/authors.json'))

export default {
  async data ({ req }) {
    let authors = await authorsPromise
    return { authors }
  }
}
</script>

Actually, System.import does not work on the server-side, that's made the condition with process.BROWSER_BUILD.

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 launch npm run 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 Jan 12, 2017

@husayt

This comment has been minimized.

Copy link
Collaborator Author

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

This comment has been minimized.

Copy link
Member

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 referenced this issue Jan 17, 2017

Closed

Server-Side Data #61

@husayt

This comment has been minimized.

Copy link
Collaborator Author

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

This comment has been minimized.

Copy link

commented Feb 22, 2017

@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

This comment has been minimized.

Copy link

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

This comment has been minimized.

Copy link

commented Apr 9, 2017

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

@heishung

This comment has been minimized.

Copy link

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

This comment has been minimized.

Copy link

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

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
You can’t perform that action at this time.