S
SolidJS2w ago
oke

SSG isn't truly static

It seems like I have wrong presumption about what SSG meant. I want some routes on my site to be static - i.e. at build time it should do some async server stuff (like reading data from DB, read some files from file system, etc. ) --> Then populate the data into the markup, and return the page static. But that doesn't seem to work. One demonstration is: I have a route called random that generates a random number --> I configured server: { prerender: {routes: ['/random'] }}} (route code below) My expectation is that: This random number is generated ONCE during build time, and then all clients, regardless of page refresh or what not, will always see this same number. After building, if I directly access the '/random' URL that is fine - page refresh won't change the number. However, if I visit the another page first, and then visit the /random page via my navbar (which I uses presume is where the Client-side router kicks in), the page is still dynamic -> It still tries to make HTTP requests to my server functions, and returns a different number each time
13 Replies
oke
okeOP2w ago
Example RandomPage component
// src/routes/(layout)/random.tsx
import { createAsync, query } from '@solidjs/router'

const randomNum = query(async () => {
'use server'
const n = Math.random()
console.log('RANDOM HIT', n)
return n
}, 'random-num')

export default function RandomPage() {
const ranNum = createAsync(() => randomNum())
return <p>{ranNum() || 'undefined'}</p>
}
// src/routes/(layout)/random.tsx
import { createAsync, query } from '@solidjs/router'

const randomNum = query(async () => {
'use server'
const n = Math.random()
console.log('RANDOM HIT', n)
return n
}, 'random-num')

export default function RandomPage() {
const ranNum = createAsync(() => randomNum())
return <p>{ranNum() || 'undefined'}</p>
}
Maybe I missed some steps to make SSG truly work. Or it SSG not possible for only part of an application ?
Alex Lohr
Alex Lohr2w ago
Then you need not "use server", because that's running the function on the server after the page was rendered. Just run the randomization once directly in the scope of the component.
oke
okeOP2w ago
The random number is just an example. It could stand for anything - like calling database to get some fixed build-time config data, reading from the files system Is that okay to do inside the component too?
Brendonovich
Brendonovich2w ago
Start doesn't allow SSG like that, it server renders the first page then the client takes over. Astro is better suited for things like that. You can however use Vite virtual modules to generate build-time data that you can share between the client and server
oke
okeOP2w ago
Thanks for the info. That's good to know. I have tried to develop a Vite plugin to do my processing, but I want to call renderToString on imported SolidJS components (I'm developing an Solidjs email template solution), and I can't seem to do that with a Vite plugin via buildStart hook. I deduced that my Vite plugin runs before the SolidJS plugin/compiler/JSX runtime kicks in. import.meta.glob doesn't work in Vite plugin; and if I use dynamic await import, when I import the TSX file in my Vite plugin, it calls to React.createElement ???
Brendonovich
Brendonovich2w ago
Hm why do you want to renderToString during build if you're making customizable templates?
oke
okeOP2w ago
so that developers build emails using JSX components inside an email_templates folder, then all the HTML are rendered out one-time during build, and then embed that HTML onto the /email_content url and users of the app can just copy the generated HTML via the web interface.
Brendonovich
Brendonovich2w ago
Ah so it's more like an npm package than a website?
oke
okeOP2w ago
In a way I suppose, but I don't think it's an npm package. It's definitely not intended to be customizable after build time. The user story is: A developer uses components like Button, Container, Row, Column to build out Solid-JSX-based email templates --> Then they use SolidStart to build out an Admin Dashboard that have route /email_content/[template_name] that displays the HTML result of these templates so that Marketing can copy the HTML and send them to people I hope I make sense
Brendonovich
Brendonovich2w ago
Ok that make sense - I think you might have trouble with that approach since Start produces website HTML, rather than email HTML which tends to be more specialised. Ah i may have misread your message dw
oke
okeOP2w ago
That's okay. The components Button, Container, Row, Column have been developed to be email-friendly. They are not simple <button> or <div> but a bunch of <table> and <td> under the hood Only thing I want is to be to build those emails once to produce the HTML of each email I could make an API route GET /build_emails --> that calls the renderToString functions on all the JSX Email Templates, and produce a static JSON file that SolidStart can import. --> Then make a Vite plugin so that every time the email_templates folder changes, the plugin re-fetch this API route But that feels like a hack. Also wouldn't work at build time (since at build time there is no server running to serve the GET /build_emails URL). If somehow I could use renderToString and make Vite understands SolidJS JSX in a build process
Brendonovich
Brendonovich2w ago
Yeah look I think you'll have a rought time trying to 100% prerender all the emails, doing the renderToString call on the server during prerendering and on the client after a navigation will probably be easier Otherwise you'd somehow need to get Vite to transform the email code at build time, and then run it at build time, so you could put the result in a virtual module
oke
okeOP2w ago
the renderToString call on the server during prerendering and on the client after a navigation
Yeah that's the current implementation, using a server function. Only issue is every time someone visits the page, the processing (importing component and calling renderToString ) is called again --> problem is potentially further exacerbated by serverless cold start
You'd somehow need to get Vite to transform the email code at build time, and then run it at build time, so you could put the result in a virtual module
I might need to actually need to whip up a manual esbuild pipeline to do this. If only I could re-use the esbuild pipeline that Vite/Vinxi/SolidStart is already using. We'll see if this is enough; seems like SolidStart also employs Babel for its processing I finally succeed. Thanks to the amazing Solidjs community for esbuild-solid-plugin Thanks Brendon a lot too to help me realize the only ways forward and not mess around with non-working ways

Did you find this page helpful?