vite-ssg: Initialstate is not updated for subsequent routes

Try the example below and for all paths you will get the same initialstate. Seems it only uses the first one. I would expect for every page initialstate.data to be the path of that page.

// src/main.ts

// ...

export const createApp = ViteSSG(
  App,
  { routes },
  ({ app, router, routes, isClient, initialState, routePath }) => {
    // ...

    if (import.meta.env.SSR) {
      initialState.data = routePath 
    } else {
    
      console.log(initialState.data) // => { routePath :"/" }
    }

    // ...
  }
)

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 4
  • Comments: 38 (37 by maintainers)

Commits related to this issue

Most upvoted comments

@husayt just clone this repo and change the lines 91 and 120: on former remove the inicial state and later add the initial state, on build you will have on each html page its own state, just modify the router example with your logic

@userquin if this issue is fixed I expect the code above to just work. That would make vite-SSG so much more powerful and flexible

@userquin one more thing, as I expected , router hook is not required. It just works

@husayt The console log is just a trace, the state saved is not that state, if you see this line https://github.com/antfu/vite-ssg/blob/main/src/node/build.ts#L133, the state is saved here but using the initial state outside the promise loop defined here https://github.com/antfu/vite-ssg/blob/main/src/node/build.ts#L91 instead using the state of each page, that should be declared here https://github.com/antfu/vite-ssg/blob/main/src/node/build.ts#L120.

With my changes, your initial state will have the scoped page state, that’s, each page with its own state. Just see the /a.html state on my screenshot.

The state you’ve on the console is a not the state that will be saved, since the L133 is using the reference on L91 and not using the state on L120, that it is the state your are showing on console.

The initialState on L91 is the global state while the state that should be retrieved from L120 is the page scoped.

@userquin not sure about page or global scoped state, but here is the bug originating from how the static pages generated during SSG. On one side to generate the body of html plugin uses page specific state, but it adds the same

<script>window.__INITIAL_STATE__={data:{...}</script>

to the footer of all of these pages

it seems it generates initial html first

[vite-ssg] Build for server...
vite v2.5.6 building SSR bundle for production...
saving { name:"ALPHA" } 

and then when rendering pages it uses bits from the html generated during initial render

[vite-ssg] Rendering Pages... (378)
saving { name:"ALPHA" } 
saving { name:"BETA" }

If you use mock: true option on ssgOptions: see https://github.com/antfu/vite-ssg/blob/main/src/node/build.ts#L106, the window is defined…

I’ve never get it working (JSDOM), it always throws an error, maybe we need to add some thing… see

@userquin do we need import.meta.env.VITE_SSG since we already have isClient? i thought that import.meta.env.VITE_SSG === !isClient

Something similar to this:

export const createApp = ViteSSG(
  App,
  { routes },
  // NEW GLOBAL STATE CALLBACK
  (/* ARGS NOT AVAILABLE YET*/) => {
    // here global state will be loaded
  },
  ({ app, router, routes, isClient, initialState, routePath, globalState }) => {
    ...
    if (isClient) {
      // restore page state
      // restore global state
    } else {
      if (import.meta.env.VITE_SSG) {
        // here the `initialState` will be always the page state, the global state will be handled from  NEW GLOBAL STATE CALLBACK
        initialState.data = { name: routePath ==="/a" ? ''ALPHA" : "BETA" }
        console.log('saving ' ,initialState.data)
      } else {
        // here store the global state: `globalState` will be populated by NEW GLOBAL STATE CALLBACK
      }
    }
    ...
  }
)

You are right, I would say we need both for vite-ssg to be most flexible. The callback you propose can initialize the state and we also need to provide a configurable way to allow for custom serialization/deserialization of all states (global and page isolated states), and this is already provided by the transformState callback. So, maybe a callback like initializeGlobalState in the ViteSSG function might be helpful.

Concerning the page state, it believe it’s best to provide a composable like useAsyncData or usePageState maybe.

I now experience the same issue.