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:
/static
the best place to put data files? export default {
data({ req, params, store }) {
return axios.get('/data.json')
.then((res) => {
return {
authors: res.data
}
})
}
}
Thanks in advance
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.
Hi @husayt
To answer your questions:
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.
static/
the best place to put data files?If you want to access them via an http call, it's a good place yes.
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.
I'm not sure to understand the question, but all the code example I wrote works for all of them :)
@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
@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?
Hi @Atinux, thanks for detailed reply.
As for disappearing data here is the screen gif, showing that data disappears few seconds after loading.
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>
@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.
@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.
is there a proper way to automatically webpack assets such as images that are defined in a json file?
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>
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.
Most helpful comment
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 theenv
of yournuxt.config.js
:Then in you data method:
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):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).
The other advantage of using Webpack is that you don't have to expose this data in the
static/
folder, you can have adata
folder an doimport 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):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 everytimedata.json
changes. But in production, if you're changing the data file directly on your server, you will have to runnuxt 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 :)