S
SolidJS•2y ago
Bersaelor

How to get `onMount` to be called on the client for a server-rendered site

I've set up a new project using solid-start with solid-start-aws. Running npm run build creates an index.mjs which I can then use as the lambda-function that creates the static website (with some minor corrections https://github.com/solidjs/solid-start/pull/898 ) Now, when using solid-start for a server rendered website, how do I run initialization code on the client? I.e. I would like to initialize some third party frameworks on the client. the following log will never appear on the client:
onMount(() => {
console.log("Framework being initialized");
framework.init('apikey');
});
onMount(() => {
console.log("Framework being initialized");
framework.init('apikey');
});
9 Replies
Levi B.
Levi B.•2y ago
That's weird It's supposed to run on the client I'm using onMount in ssr and it runs on the client
Bersaelor
Bersaelor•2y ago
thank you for that answer, I was genuinely unsure whether it should run or not actually, the onMount part doesn't seem to run on the server either, strange on the server I can only see the logs from the function routeData({ params }: RouteDataArgs) { so I created a minimal example https://github.com/Bersaelor/solid-start-on-lambda and the onMount method is not called when run via the lambda method SSR your SSR is via a node server?
Levi B.
Levi B.•2y ago
Yes it's a node server
Bersaelor
Bersaelor•2y ago
maybe the problem is in the solid-start-aws adapter, that the resulting index.mjs doesn't "hydrate" as well?
Levi B.
Levi B.•2y ago
Yeah I thought it might be a hydration problem
Carlo Nyte
Carlo Nyte•2y ago
Yea onMount only runs on the client. It's logic that runs while the client is loading the page
Bersaelor
Bersaelor•2y ago
yup, well in the minimal example I linked onMount doesn't run unfortunately. I would love if it were running, then I could use the onMount to init my tracking script and audio player. Atm, I have to do:
export default function Home() {
const clientJS = `
const amplScript = document.querySelector('#${amplScriptId}');
amplScript.onload = function () {
amplitude.init("${ampAPiKey}");
console.log('amplitude initialized');
amplitude.track('Open Deeplink', trackingParams);
};
const buttons = document.querySelectorAll('#appstorelink');
buttons.forEach((b) => {
b.addEventListener('click', trackAppStoreClick);
});
`
return (
// ...
<script id={amplScriptId} async src="https://cdn.amplitude.com/.." />
<script type="text/javascript">{clientJS}</script>
// ...
)
}
export default function Home() {
const clientJS = `
const amplScript = document.querySelector('#${amplScriptId}');
amplScript.onload = function () {
amplitude.init("${ampAPiKey}");
console.log('amplitude initialized');
amplitude.track('Open Deeplink', trackingParams);
};
const buttons = document.querySelectorAll('#appstorelink');
buttons.forEach((b) => {
b.addEventListener('click', trackAppStoreClick);
});
`
return (
// ...
<script id={amplScriptId} async src="https://cdn.amplitude.com/.." />
<script type="text/javascript">{clientJS}</script>
// ...
)
}
In the example app https://github.com/Bersaelor/solid-start-on-lambda I have
onMount(() => {
// this will only run via `run dev` not when run through SSR
console.log("Site for id: ", params.id, " has been mounted");
document.body.style.backgroundColor = "#AACC00";
})
onMount(() => {
// this will only run via `run dev` not when run through SSR
console.log("Site for id: ", params.id, " has been mounted");
document.body.style.backgroundColor = "#AACC00";
})
and the page is loaded without changing color. Not only that, but if you look into the .aws-sam/TestSSRFunction/index.mjs file which has all the code needed for the SSR of the site, there is no more AACC00, so the contents of the onMount seem to be entirely gone after solid-start build I think I made some progress, so when you run solid-start build it'll create the following folders:
dist/
- client/
- assets/
- manifest.json
- route-manifest.json
- ssr-manifest.json
- server/
- index.mjs
dist/
- client/
- assets/
- manifest.json
- route-manifest.json
- ssr-manifest.json
- server/
- index.mjs
Now, the lambda method returns the output of the handler method inside index.mjs. The /assets files I had synced to an AWS S3 bucket which is server when the user fetches url.com/assets/. Now, in my case the manifest.json, the ssr-manifest.json are not served from the s3 bucket as they don't have the prefix `assets`. Let's try getting them server too, if that will make a difference
Carlo Nyte
Carlo Nyte•2y ago
Yup this is way above my level of understanding 😅. How'd you make out so far though?
Bersaelor
Bersaelor•2y ago
It's just that the server renders one index.html file with most of the static site and sends it tot he client. Parallel to that, we also have a few *.js files sitting in the assets/public folder that are created for the hydration. Most of the site loads from the main html but if you look in the sites structure it also references a few *_-6b112e12.js for your routes which will have the dynamic code. Now the node.js implementation probably responds with all these files. A lambda method has only one response value, which is the main *.html . The other files, like imgs or the statis js assets need to be supplied from somewhere else. In my case I have a Cloudfront distribution that'll check the requested assets url, and either hand over the main html from lambda, or the static files form an S3 bucket Maybe i'll get around to write a blog post about Solidjs+AWS Lambda this weekend and detail all that I did with the example app 🙂
Want results from more Discord servers?
Add your server