Deploy

Hi everyone I'm deplyong my first solid start website, but the data seems to be static. I change it on the Sanity CMS, but when I come to the page the data remains the same. Any idea how to solve it?
81 Replies
Daniel Sousa @TutoDS
And I'm seeing Error | Uncaught Client Exception Can anyone please help me? 🙏
Daniel Sousa @TutoDS
I think it's realted with iconify, but why?
No description
Raqueebuddin Aziz
Relevant code?
Daniel Sousa @TutoDS
It's my entire home page I'm trying to deploy it on render.com and on my vps with coolify but isn't fetching the data it's always static I update the data, and keeps showing the old data 😦
<Button
data-aos={'fade-up'}
as={'a'}
href={'/sobre-nos'}
class={'inline-flex items-center gap-1'}
variant={'text'}
>
Sobre nós
<Icon icon={'ph:arrow-right'} />
</Button>
<Button
data-aos={'fade-up'}
as={'a'}
href={'/sobre-nos'}
class={'inline-flex items-center gap-1'}
variant={'text'}
>
Sobre nós
<Icon icon={'ph:arrow-right'} />
</Button>
I'm using the icons for buttons etc no idea how to solve it and how to use the new data instead of the old data Anyone can help me please? 😦
Raqueebuddin Aziz
Send the code on how you data fetch
Daniel Sousa @TutoDS
I disable the SSR and seems to works For home page:
const getHome = cache(async (): Promise<Home | undefined> => {
'use server';

try {
return client.fetch<Home>(getHomeQuery);
} catch {
return;
}
}, 'home');
const getHome = cache(async (): Promise<Home | undefined> => {
'use server';

try {
return client.fetch<Home>(getHomeQuery);
} catch {
return;
}
}, 'home');
Daniel Sousa @TutoDS
The only problem I'm facing is this error with iconify (with SSR disable)
No description
Daniel Sousa @TutoDS
with SSR disable the data updates when I change it on sanity, but the iconify error keeps appearing and I don't know how to solve it 😦 I'm totally desesperated, I need to deploy this today 😦
Raqueebuddin Aziz
do you ever invalidate the getHome cache? or do you mean it doesn't happen even on reload? how are you using iconify btw? unocss?
Daniel Sousa @TutoDS
No, I installed @iconify/solid How I can do that? It's appearing on reload and hard reload
Raqueebuddin Aziz
Let me send some docs does sanity have some websocket thingy that tells you when it's updated? if yes, you need to run this when that happens
import { revalidate } from '@solidjs/router';

revalidate(getHome.key)
import { revalidate } from '@solidjs/router';

revalidate(getHome.key)
Daniel Sousa @TutoDS
I think not, but if I refresh the page the data now appears to be ok the problem is only that error on getComputedStyle
Raqueebuddin Aziz
maybe try unocss to use iconify icons? that usually works for my solid start app
Daniel Sousa @TutoDS
I'm using tailwindcss
Raqueebuddin Aziz
UnoCSS
The instant on-demand Atomic CSS engine
Daniel Sousa @TutoDS
but I will take a look
Raqueebuddin Aziz
you can keep using tailwindcss you can only use unocss just for icons
Daniel Sousa @TutoDS
about the revalidate, where I should put the revalidate?
Raqueebuddin Aziz
if sanity has some way to tell you when the data on the server is updated there usually its called like a subscribe function
Raqueebuddin Aziz
const subscription = client.listen(query, params)
.subscribe(update => {
const comment = update.result
console.log(`${comment.author} commented: ${comment.text}`)
})
const subscription = client.listen(query, params)
.subscribe(update => {
const comment = update.result
console.log(`${comment.author} commented: ${comment.text}`)
})
this is from their docs so inside the subscribe function
Daniel Sousa @TutoDS
If you see, the error is only appearing on the home page
Raqueebuddin Aziz
Sanity.io
Real-time Updates | Content Lake
How API clients can listen for data changes in realtime.
Raqueebuddin Aziz
no errors for me on firefox linux
Daniel Sousa @TutoDS
Can you try to navigate between routes and go back to home page please?
Raqueebuddin Aziz
still nothing in the console
Daniel Sousa @TutoDS
Ok, for me appears this sometimes
Raqueebuddin Aziz
If its iconify, I'd try unocss or look in iconify/solid github issues
Daniel Sousa @TutoDS
I need to see why it's happening to me only
Daniel Sousa @TutoDS
because I try to deploy on my VPS (https://impulsionar.devserver7.com/) and have the same error
Impulsionar
Impulsionar undefined
undefined
Daniel Sousa @TutoDS
@Raqueebuddin Aziz for some reason, now I can open the "Projetos" menu (projects) and the error keeps appearing me
Daniel Sousa @TutoDS
https://impulsionar.onrender.com/ So i try to use the tailwind plugin
Impulsionar
Impulsionar
Daniel Sousa @TutoDS
the only problem is the dynamic ones that I can't load Any idea?
Raqueebuddin Aziz
Which are the dynamic ones?
Daniel Sousa @TutoDS
it's coming from the sanity cms
Rodrigo
Rodrigo5mo ago
I may be wrong but I've experienced that A LOT with Icon Libraries. The problem is they are not ready for SSR so when Solid tries to do that... boom. And the error is very random. I use tabler icons for solidjs and it's laughable. In my case, since I was using plenty of icons and my site is an app, I just went ahead and disabled SSR. If you are using just 1 or 2, and absolutely need SSR: 1. try to wrap the components representing the icons with the client_only directive from solidjs 2. try to use the icon sources
Daniel Sousa @TutoDS
I disable minify and the error appears on embla carousel I’m out of ideas
Daniel Sousa @TutoDS
I'm disabling SSR now to test already wrap my carousel on client only, but didn't solve it Any suggestion? Is always returning only the fallback values (only on the deploy) Keep facing the error on embla
Daniel Sousa @TutoDS
Remove the carousel and the error appears again
No description
Daniel Sousa @TutoDS
I'm totally lost Hello everyone I remove AOS and seems that works fine now
Madaxen86
Madaxen865mo ago
Can you share how you initialised AOS? Because it is a library that can only run on the client as it adds eventlisteners in the document which access the windows properties which don’t exist during SSR. Thus it needs to be initialised within a onMount guess. Like this: https://stackblitz.com/edit/github-vkbuzw?file=src%2Froutes%2Findex.tsx
Daniel Sousa @TutoDS
function AosInit(props: { children: JSXElement }) {
createEffect(() => {
if (isServer) {
return;
}

Aos.init({
anchorPlacement: 'top-bottom',
mirror: true,
offset: -100,
once: false,
});
});

return <>{props.children}</>;
}

export { AosInit };
function AosInit(props: { children: JSXElement }) {
createEffect(() => {
if (isServer) {
return;
}

Aos.init({
anchorPlacement: 'top-bottom',
mirror: true,
offset: -100,
once: false,
});
});

return <>{props.children}</>;
}

export { AosInit };
And use clientOnly to import on app.tsx I create a component for initialize the AOS Should I do it for page?
Daniel Sousa @TutoDS
Other thing that I'm facing only on the deploy is the SEO, I'm fetching the seo settings from Sanity, but I put a console.log and it's show me everything correct, but the meta tags are empty
No description
Daniel Sousa @TutoDS
Could be because of this memo:
const value = createMemo(
() =>
({
title: seoSettings()?.title ?? 'Impulsionar',
defaultDescription: seoSettings()?.defaultDescription ?? '',
slogan: seoSettings()?.slogan ?? '',
keywords: seoSettings()?.keywords ?? [
'impulsionar',
'marketing',
'design',
'social media',
'branding',
],
}) satisfies SeoSettings,
);
const value = createMemo(
() =>
({
title: seoSettings()?.title ?? 'Impulsionar',
defaultDescription: seoSettings()?.defaultDescription ?? '',
slogan: seoSettings()?.slogan ?? '',
keywords: seoSettings()?.keywords ?? [
'impulsionar',
'marketing',
'design',
'social media',
'branding',
],
}) satisfies SeoSettings,
);
Madaxen86
Madaxen865mo ago
You can try to wrap the Meta components in a Show and only display them when createAsync is resolved.
<Show when={poll()} keyed>
{(poll) => (
<>
<Title>{poll.title || ""}</Title>
<Metadata {...poll} />
</>
)}
</Show>
<Show when={poll()} keyed>
{(poll) => (
<>
<Title>{poll.title || ""}</Title>
<Metadata {...poll} />
</>
)}
</Show>
Daniel Sousa @TutoDS
Ok, but the create async is inside of a context About the AOS should I initialize it per page?
function DefaultSeo() {
const seoSettings = useSeo();

return (
<>
<Meta charset="UTF-8" />
<Meta name="viewport" content="width=device-width, initial-scale=1.0" />
<Meta http-equiv="content-language" content="Portuguese" />
<Meta name="language" content="Portuguese" />

{/* Default social tags */}
<Meta property="og:locale" content="Portuguese" />
<Meta property="og:type" content="website" />
<Meta property="og:image" content="/media/design.webp" />

{/* Favicon */}
<Link rel="icon" href="/favicon.svg" type="image/svg+xml" />

{/* Robots */}
<Meta name="robots" content="index, follow" />

<Show when={seoSettings()} keyed={true}>
{(seo) => (
<>
<Title>
{seo.title}

<Show when={seo.slogan} keyed={true}>
{(slogan) => <> - {slogan}</>}
</Show>
</Title>

<Show when={seo.defaultDescription} keyed={true}>
{(description) => <Meta name="description" content={description} />}
</Show>
<Meta name="keywords" content={seo.keywords?.join(', ')} />

{/* Social tags */}
<Meta property="og:site_name" content={seo.title} />
<Meta
property="og:title"
content={`${seo.title} ${seo.slogan && `- ${seo.slogan}`}`}
/>
<Meta property="og:description" content={seo.defaultDescription} />
</>
)}
</Show>
</>
);
}
function DefaultSeo() {
const seoSettings = useSeo();

return (
<>
<Meta charset="UTF-8" />
<Meta name="viewport" content="width=device-width, initial-scale=1.0" />
<Meta http-equiv="content-language" content="Portuguese" />
<Meta name="language" content="Portuguese" />

{/* Default social tags */}
<Meta property="og:locale" content="Portuguese" />
<Meta property="og:type" content="website" />
<Meta property="og:image" content="/media/design.webp" />

{/* Favicon */}
<Link rel="icon" href="/favicon.svg" type="image/svg+xml" />

{/* Robots */}
<Meta name="robots" content="index, follow" />

<Show when={seoSettings()} keyed={true}>
{(seo) => (
<>
<Title>
{seo.title}

<Show when={seo.slogan} keyed={true}>
{(slogan) => <> - {slogan}</>}
</Show>
</Title>

<Show when={seo.defaultDescription} keyed={true}>
{(description) => <Meta name="description" content={description} />}
</Show>
<Meta name="keywords" content={seo.keywords?.join(', ')} />

{/* Social tags */}
<Meta property="og:site_name" content={seo.title} />
<Meta
property="og:title"
content={`${seo.title} ${seo.slogan && `- ${seo.slogan}`}`}
/>
<Meta property="og:description" content={seo.defaultDescription} />
</>
)}
</Show>
</>
);
}
This is my seo component And the context:
const SeoContext = createContext<Accessor<SeoSettings>>();

const SeoContextProvider = (props: { children: JSXElement }) => {
const seoSettings = createAsync(() => getSeoSettings());
console.log(seoSettings());

const value = createMemo(
() =>
({
title: seoSettings()?.title ?? 'Impulsionar',
defaultDescription: seoSettings()?.defaultDescription ?? '',
slogan: seoSettings()?.slogan ?? '',
keywords: seoSettings()?.keywords ?? [
'impulsionar',
'marketing',
'design',
'social media',
'branding',
],
}) satisfies SeoSettings,
);

return <SeoContext.Provider value={value}>{props.children}</SeoContext.Provider>;
};

function useSeo() {
const context = useContext(SeoContext);

if (!context) {
throw new Error('useSeo mut be used within a `SeoContextProvider`.');
}

return context;
}
const SeoContext = createContext<Accessor<SeoSettings>>();

const SeoContextProvider = (props: { children: JSXElement }) => {
const seoSettings = createAsync(() => getSeoSettings());
console.log(seoSettings());

const value = createMemo(
() =>
({
title: seoSettings()?.title ?? 'Impulsionar',
defaultDescription: seoSettings()?.defaultDescription ?? '',
slogan: seoSettings()?.slogan ?? '',
keywords: seoSettings()?.keywords ?? [
'impulsionar',
'marketing',
'design',
'social media',
'branding',
],
}) satisfies SeoSettings,
);

return <SeoContext.Provider value={value}>{props.children}</SeoContext.Provider>;
};

function useSeo() {
const context = useContext(SeoContext);

if (!context) {
throw new Error('useSeo mut be used within a `SeoContextProvider`.');
}

return context;
}
By the way tahnks @Madaxen86 and @Raqueebuddin Aziz for your time helping me 🙏
Madaxen86
Madaxen865mo ago
This does only depend on where you use the animations. If you use it on every page then keep it in the app. I don't face any issues during SSR with the simple onMount implementation.
Daniel Sousa @TutoDS
Thank you I will remove my create effect and use on mount Because at this point when I remove all the animations the carousel is working without any error, so I will try to put the animations now again with onMount https://impulsionar.onrender.com Apparently works I added the data-aos on the second section only Now need to put on other pages to see
Madaxen86
Madaxen865mo ago
If getSeo is wrapped in cache you bsically get context through the cache. I think there's no need to have a context as all requests of getSeo will get deduped.
Daniel Sousa @TutoDS
And try to fix the seo Oh ok makes sense One question any way to prevent createAsync to infer the type or undefined when I know that isn’t undefined
Madaxen86
Madaxen865mo ago
createAsync may always be undefined because it is async. What you can do in JSX is use the show component with the callback as children like:
const seo = createAsync(()=>getSeo(),{
deferStream:true
})


return <Suspense>
<Show when={sea()} keyed> // seo is T | undefined
{(data) => ( //now data is narrowed to T
<>
<Title>{data.title || ""}</Title>
...
</>
)}
</Show>
<Suspense>
const seo = createAsync(()=>getSeo(),{
deferStream:true
})


return <Suspense>
<Show when={sea()} keyed> // seo is T | undefined
{(data) => ( //now data is narrowed to T
<>
<Title>{data.title || ""}</Title>
...
</>
)}
</Show>
<Suspense>
inside effects you can make a copy and narrow with if:
const data = createMemo(()=>{
const _seo = seo(); // _seo is T | undefined
if (!_seo) {
return defaultValues
}
// seo is narrowed to T
...
})
const data = createMemo(()=>{
const _seo = seo(); // _seo is T | undefined
if (!_seo) {
return defaultValues
}
// seo is narrowed to T
...
})
Daniel Sousa @TutoDS
Thank you About the AOS, should I use the clientOnly to import it on app.tsx?
Madaxen86
Madaxen865mo ago
Seems not necessary to me. In the stackblitz it worked without clientOnly
Daniel Sousa @TutoDS
thanks Deploying on render.com seems to be working on my own vps with coolify not 😦
Madaxen86
Madaxen865mo ago
What’s the error on Coolify?
Daniel Sousa @TutoDS
two pages dont open
Daniel Sousa @TutoDS
The pages don't load but if I open in new tab works perfectly I figure out the problem with help of @davedbase Is basically a createEffect that I have to set search parameters Thanks everyone I think it's working now
Failed to load module script: Expected a JavaScript module script but the server responded with a MIME type of "text/html". Strict MIME type checking is enforced for module scripts per HTML spec.
After all isn't working everything 😦 But i can't replicate it anymore @Madaxen86 any tips for speed optimization? https://pagespeed.web.dev/analysis/https-impulsionar-devserver7-com/0lepc0s8od?form_factor=mobile
Madaxen86
Madaxen865mo ago
How CSS Opacity Animations Can Delay The Largest Contentful Paint |...
Chrome doesn't count elements with an opacity of 0 as LCP candidates. If the elements are repainted later on this can increase the LCP.
Madaxen86
Madaxen865mo ago
Maybe also use an different image on mobile so you don’t have to transform it on the fly or pretransform the image on upload. Lighthouse is not always correct.
davedbase
davedbase5mo ago
You're using Sanity CMS from what I remember. The page speed is likely b/c it's calling Sanity on every request. You could cache the sanity value so that you aren't waiting on a full round-trip.
Daniel Sousa @TutoDS
I have cache on all the requests but how can cache the sanity it self?
davedbase
davedbase5mo ago
Yeah it may not be the data fetching specifically (sorry I replied too quickly without reading Pagespeed properly). I think your suspense boundaries aren't in the right spots. The page is loading client side instead of SSRing. Plus the animations. Both might be killing your LCP.
Daniel Sousa @TutoDS
For the image, you suggest anything specific to detect the device?
Madaxen86
Madaxen865mo ago
Just use a srcset with the different image sizes. The browser will then pick the correct one. When using a cms you usually can configure to create different sizes (for phone, tablet, desktop,…) when you upload the image. Then you can make an image component which has all the sizes in a srcset.
Daniel Sousa @TutoDS
Usually, I'm getting the image, and set the dimensions, for example While the image is loading:
function getBlurHashImage(image: Image | ImageWithAlt) {
if (image.asset.metadata?.lqip) {
return image.asset.metadata?.lqip;
}

return urlFor(image)
.size(25, 25)
.quality(60)
.blur(60)
.fit('max')
.auto('format')
.url();
}
function getBlurHashImage(image: Image | ImageWithAlt) {
if (image.asset.metadata?.lqip) {
return image.asset.metadata?.lqip;
}

return urlFor(image)
.size(25, 25)
.quality(60)
.blur(60)
.fit('max')
.auto('format')
.url();
}
I get or the blur hash image, or get a very small image probably I can do it for that images Which sizes do you usally use?
davedbase
davedbase5mo ago
You should checkout unpic: https://unpic.pics/img/solid/
Unpic
@unpic/solid – Unpic
High-performance, responsive SolidJS image component
davedbase
davedbase5mo ago
There's a Sanity adapter for it too It has a placeholder option as well: https://unpic.pics/placeholder/
Daniel Sousa @TutoDS
I need to test it I did it manually
function OptimizedImage(props: OptimizedImageProps) {
const [sources, restOfProps] = splitProps(props, ['src', 'blurHash', 'srcSet']);
const [imageRef, setImageRef] = createSignal<Element>();
const [imgData, setImgData] = createSignal<{ isLoading: boolean; src: string }>({
isLoading: true,
src: '',
});

function loadImage() {
const img = new Image();
img.onload = () => {
setImgData({ src: sources.src, isLoading: false });
};

img.src = sources.src;
}

createEffect(() => {
const observer = new IntersectionObserver(entries => {
entries.forEach(entry => {
if (entry.isIntersecting) {
if (sources.blurHash) {
setImgData(prev => ({ ...prev, src: String(sources.blurHash) }));
}

loadImage();

observer.unobserve(entry.target);
}
});
});

if (imageRef()) {
observer.observe(imageRef() as Element);
}

onCleanup(() => {
observer.disconnect();
});
});

return (
<img
{...restOfProps}
ref={setImageRef}
class={cn([
'bg-gray-500 blur-none transition-all duration-300 ease-in-out',
{ 'blur-xl': imgData().isLoading },
restOfProps.class ?? '',
])}
src={imgData().src}
srcSet={sources.srcSet}
alt={restOfProps.alt}
/>
);
}
function OptimizedImage(props: OptimizedImageProps) {
const [sources, restOfProps] = splitProps(props, ['src', 'blurHash', 'srcSet']);
const [imageRef, setImageRef] = createSignal<Element>();
const [imgData, setImgData] = createSignal<{ isLoading: boolean; src: string }>({
isLoading: true,
src: '',
});

function loadImage() {
const img = new Image();
img.onload = () => {
setImgData({ src: sources.src, isLoading: false });
};

img.src = sources.src;
}

createEffect(() => {
const observer = new IntersectionObserver(entries => {
entries.forEach(entry => {
if (entry.isIntersecting) {
if (sources.blurHash) {
setImgData(prev => ({ ...prev, src: String(sources.blurHash) }));
}

loadImage();

observer.unobserve(entry.target);
}
});
});

if (imageRef()) {
observer.observe(imageRef() as Element);
}

onCleanup(() => {
observer.disconnect();
});
});

return (
<img
{...restOfProps}
ref={setImageRef}
class={cn([
'bg-gray-500 blur-none transition-all duration-300 ease-in-out',
{ 'blur-xl': imgData().isLoading },
restOfProps.class ?? '',
])}
src={imgData().src}
srcSet={sources.srcSet}
alt={restOfProps.alt}
/>
);
}
I'm using this on almost all the images
davedbase
davedbase5mo ago
Ooof that's a lot of work
Daniel Sousa @TutoDS
the images for the hero sections only use the onLoad I need to test it Thanks I will try to find the documentation how to use it with sanity
davedbase
davedbase5mo ago
Yeah your component is doing a lot more work than it needs to. I'd switch to unpic and let someone else manage that complexity 🙂
Daniel Sousa @TutoDS
<Image
src={urlFor(image).auto('format').width(1000).url()}
layout="fullWidth"
background={getBlurHashImage(image)}
alt={image.alt}
class={'absolute inset-0 size-full object-cover object-center'}
/>
<Image
src={urlFor(image).auto('format').width(1000).url()}
layout="fullWidth"
background={getBlurHashImage(image)}
alt={image.alt}
class={'absolute inset-0 size-full object-cover object-center'}
/>
I'm trying this way, let me check
Daniel Sousa @TutoDS
Afff, these appears me agian
No description
Daniel Sousa @TutoDS
@davedbase I replace all the images with Unpic page, but the result as the same: https://pagespeed.web.dev/analysis/https-impulsionar-devserver7-com/0pdvgxabp2?form_factor=mobile
davedbase
davedbase5mo ago
It's good that you're using a proper image component (something you don't have to maintain) now you'll have to dive deeper into the optimization though.
Madaxen86
Madaxen865mo ago
I think there’s still something going on with the aos’ animations that cause the FCP and LCP to be so slow. By visually testing, it seems just fine.
Daniel Sousa @TutoDS
Yeah...
Daniel Sousa @TutoDS
Seems that the rror comes back 😭😭
No description
Want results from more Discord servers?
Add your server