threepointone/glamor

andrew's server side rendering issues

Closed this issue · 9 comments

I'm still trying to track down the root cause of the issue. I tried switching the tests to use the npm version of the lib and it didn't break, so there must be something else going on.

Okay, figured it out. It's not a bug in glamor, but it's potentially a gotcha worth knowing about because it's not an uncommon pattern for server-side rendering.

I use webpack for my server builds, and exclude all node_modules from my code bundle. I do this externalisation by iterating over the members of node_modules. This process includes glamor but not glamor/server. This means that the core lib was being excluded from my bundle, but the server component was being included, which meant including its own version of the core lib. The ultimate result was that the styles were being added to the stylesheet singleton in a different copy of the library to that which was doing the server rendering.

I fixed the issue by explicitly adding 'glamor/server' to my webpack externals.

Amazing catch, talk about roundabout! I'll add a note to the docs soon. Before closing this, any ideas on anything else I could do to prevent this problem? Can't think of anything clean. Please, and thank you!

One idea is I'd just merge glamor / glamor/react if tree shaking was more mainstream.

So it's quite similar to a problem I had client-side, when I was using a CDN rather than NPM version of Relay, but had a dependency that depended on Relay internals, so I ended up with two versions of Relay.

So whenever you might decide to exclude a module from a bundle, you need to make sure that you have no other dependencies that use a different entry point. I think it's a matter of more wide-spread education about how bundling works, rather than something specific to this library.

Maybe it's enough to note that because the library exposes multiple entry points, users should be careful when bundling to ensure they don't get any duplicate copies. It's a hard issue to describe concisely...

added a note in the server rendering docs, closing this issue for now, but I'll still keep an eye open for a better fix. thanks!

Hi, I'm currently having the same issue with duplicate style tags. If treat glamor and glamor/server as external in the server bundle, the styles are still duplicated.

I assumed adding the keys on window._glam would mean glamor on the client-side would be able to work out that the style already exists and avoid adding it. Is this not how it works?

Ok so I found the issue in my code ( a React app), and I think it would catch a lot of other people out too.

So this inserts the styles twice, because App is imported first, all styles are added before rehydrate has time to run.

import App from 'components/App/App';
rehydrate(window._glam);

Also imports always run before other statements (or get transpiled before other statements), so no matter what order you list them in -rehydrate will be called after.

My hack solution at the moment is to use a regular require() call so I have more freedom with the ordering:

rehydrate(window._glam);
const App = require('components/App/App').default;

I suppose an alternative solution would be to only apply the styles in the render function of the top level component or something, but again that's not ideal. Any other ideas?

At least I think it should be mentioned in the docs - that rehydrate must run before any style code is run - or just explain what it does in more detail.

jschr commented

I just ran into a similar issue. Using Typescript, I was running into some incompatibilities with the default typings so in my fumbling around I had switched my glamor import to glamor/umd and forgot about it.

My understanding of the issue is that since I was using the glamor/umd build rather than glamor/lib (which glamor/server uses), the stylesheet singleton wasn't the same as the server's anymore so I ended up with empty style definitions.

Definitely a user error but wanted to post in the rare case this might save someone else half a day of debugging.