Static page within dynamic nested route not generated on NuxtJS - vue.js

My goal is to have the following page structure
pages
--/users/
--/users/:id/
--/users/:id/edit/
edit should be generated for every :id. Right now my setup works only in development mode. On nuxt generate only the first /users/:id/edit/ is generated. All other routes get a 404 error on production!
Current setup:
- /users
- index.vue
/_id
- index.vue
- edit.vue
I also tried to add another _id.vue which i found in the documentation and here
/users
- _id.vue
- /id
[...]
I checked this as well.
In nuxt.config.js I have
ssr: true,
target: 'static',
Do I need to add something in router property in nuxt.config.js? I am not sure why it is not generated in production.

If you are using static site generation you have to define your static routes, because Nuxt does not know how many users do you have in your data base.
You can set a generate method into your nuxt.config.js file:
generate: {
fallback: true,
async routes() {
const routes = await _getRoutes()
return routes
}
}
And then declare a function called _getRoutes to generate a list of dynamic routes:
async function _getRoutes($content) {
const usersList = [1, 2, 3] // get from your DB
const paths = []
usersList.forEach((userId) => {
paths.push(`/users/${userId}`)
paths.push(`/users/${userId}/edit`)
})
return paths
}

this is a bug with nuxt 2 in vue 2.
for dynamically generated routes, and also not-english nested routes ,
(or maybe just generally non-english routes) when vue hydrates the component , it will face a problem and restarts it . so the data that you cached in data(){} with fetch(), will be empty again .
currently you should use static and/or english-only routes .

Related

Nuxt Generate Freezes

I've been struggling with a Nuxt Generate problem for quite some while. Whenever I add ssr: true to nuxt.config and try to generate dynamic routes, the generation freezes. Nuxt generates x amount of routes just how I want them, but is unable to finish the process. No error is given by Nuxt, just stops at some route. My generate setup is as simple as this:
generate: {
crawler: false,
interval: 150,
routes () {
return axios.get(process.env.API_URL + '/events/routes').then(res => {
/*
API returns an array of event routes:
['/organiser/event', '/organiser/event-1']
*/
return res.data
})
}
}
It seems to work as expected when I manually add an array of routes, as follows:
routes: ['/organiser/event, '/organiser/event-1', '/etc/event']
Any ideas?
The default value of the ssr property is true and thus you can omit ssr: true from nuxt.config.js. And in your case you should omit it because it's causing you issues.

Add static text in html generated by nuxt

I have a nuxt app, and I want to create static html files for all my routes.
I generate my static files successfully.
So after run nuxt generate I have e.g. these folders with index.html inside:
buy/apple
buy/orange
buy/banana
My problem is here.
In my page I want to have this:
<h1>Buy {{fruit_name}}</h1>
and I want fruit_name be static on generated html file.
so e.g. for apple in final html I want to have:
<h1>Buy apple</h1>
for now apple is empty.
So what should I do to set this variable base on route name on generate time.
assume my routes are constant and I set my routes on nuxt.config.js
UPDATE
I try to change them in generated html files, but when I serve it changes not applied. Why?
I found solution:
When generating routes pass payload to related page:
{
route: `/fruit/${name}`,
payload: { fruitName: name }
},
and set data in asyncData hook:
async asyncData({ params, error, payload }) {
if (payload) {
return {
name: payload.name
}
}
}
and here a data set in component and can access it through component and it is static and set in generated html file for each route.

vue and webpack doesn't do lazy loading in components?

The lazy component in vue/webpack seem to be wrong or I miss confuse about the terms.
To do lazy loading of component I use the keyword import and webpack should split this component to sepeate bundle, and when I need to load this component webpack should take care of it and load the component.
but in fact, webpack does make sperate file, but it loaded anyway when the application is running. which is unexpected.
For example I just create a simple vue application (using the cli) and browse to localhost:8080/ and the about page should be loaded (by default) using the import keyword.
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
}
]
So This is by design? I load every time the file I do not need right now (the page about). and if I have 200 pages, when I'll fetch 200 files I dont need. how that ends up? that did I save here by using the import key?
In vuetify for example they uses import key, but the files are loaded anyway and not by demand.
You can also avoid component prefetch using one of the webpack "magic" comments (https://webpack.js.org/guides/code-splitting/#prefetchingpreloading-modules), eg.
components: {
MyComponent: () => import(/* webpackPrefetch: false */ './MyComponent.vue')
}
Feel free to read more about this Vue optimization below:
https://vueschool.io/articles/vuejs-tutorials/lazy-loading-individual-vue-components-and-prefetching/
If you're referring to the default app template from Vue CLI, then you're actually observing the prefetch of the About page, intended to reduce load times for pages the user will likely visit.
If you want to avoid this performance optimization, use this Vue config:
// vue.config.js
module.exports = {
chainWebpack: config => {
config.plugins.delete('prefetch')
config.plugins.delete('preload')
}
}
For troubleshooting reference, Chrome's Network panel includes an Initiator column, which provides a clickable link to the source file that triggered the network call. In this case of the about.js, the source file looks like this:
try using vue-lazyload maybe it can help and for <script> tags you can try async defer it helps in website speed optimizations

how to write global router-function in nuxt.js

I am using Vue.js with Nuxt.js, but I got a problem in router's functions.
In the pure Vue, i can write in main.js like this:
val route = new Router({
routes:{
[...]
}
})
route.beforeEach(to,from,next){
//do something to validate
}
And how to do the same in nuxt.js ? I can not find any file like main.js.
Also, all i know is to deal with the pages folder to achieve router, I can not set the redirect path
please help, thx :)
You can create a plugin for Nuxt
create a plugins/route.js file:
export default ({ app }) => {
// Every time the route changes (fired on initialization too)
app.router.afterEach((to, from) => {
//do something to validate
})
}
and update your nuxt.config.js file:
plugins: ['~/plugins/route']
More details about Nuxt plugins: https://nuxtjs.org/guide/plugins
If anybody might be still interested, it's possible to setup global middleware in nuxt.config.js like this:
router: { middleware: ['foo'] },
then in your middleware/foo.js you do whatever...
export default function({ route, from, store, redirect }) {}
Beware: You can't use this for static sites (nuxt generate), because middleware is not executed on page load, but only on subsequent route changes. Thanks #ProblemsOfSumit for pointing that out.

VueJs 2: Unable to render view when using history mode and route params

I am trying to set up SPA routes using history mode as follows:
{
mode: 'history',
routes: [
{
path: '/',
component: Home
},
{
path: '/articles',
component: ArticleList,
children: [
{
path: ':title',
component: ArticleView
}
]
}
]
}
As I am using the history mode routing on vue and on express application I've set up "express-history-api-fallback" as the last middleware in the pipeline:
const app = express();
const root = path.join(__dirname, '../client/dist');
app.use(express.static(root));
/* other middlewares */
app.use(fallback('index.html', {root: root}));
At the moment of a page reload, everything works fine. I.e. loading a url http://application/articles, opens correctly the view, BUT when I try to access the view that takes in a parameter, no matter what, the view does not get loaded and two requests are made to the express.
I.E. a request to http://application/articles/test will resolve into two requests. One to http://application/articles/test and another one to http://application/articles/app.[calculated-hash].js
As far as I understand, the first request fetches the index.html the other request fetches the bundled js script.
Also, on the express app, all routes to api start with 'api' prefix.
Question:
What is wrong with my setup/code using history mode and route params because no routes with parameters are loaded when trying to access them when entering url manually or hitting refresh?
Update:
Using connect-history-api-fallback produces the same results
The problem was with the script tag the webpack injects into the index.html
<script type="text/javascript" src="app.06503cbc260646a996d9.js"></script>
The src attribute value was missing a '/' prefix thus the resolution of files failed.
So to make it work, I've linked the src file like this:
<script type="text/javascript" src="/app.06503cbc260646a996d9.js"></script>
As I am using the webpack to bundle js files, on the webpack config I've added output.publicPath '/'
More info: connect-history-api-fallback bugtracker