Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add parsing when using SSR. Fixes #6. #18

Closed
wants to merge 2 commits into from

Conversation

te-online
Copy link

Adds dom-parser (don't know if you're okay with this module?) to fix Server-Side-Rendering. I don't think we would want different builds for server and browser, so we always need to the module.

Couldn't add any tests for this, because Karma only works in the browser. Any ideas regarding testing?

Increases the gzipped size from 2.5 kB to 2.6 kB.

te-online and others added 2 commits April 13, 2018 19:41
Bump nodejs version for travis to current LTS.
@te-online
Copy link
Author

I have no idea why one of the tests is failing in travis. Can't reproduce on my local machine.

@te-online
Copy link
Author

@developit Is there any chance you could have a look and tell me, what you think? I can make adjustments, but I really think, SSR should be fixed.

@mrhein
Copy link

mrhein commented Aug 26, 2018

This shouldn't be merged ... it will add unnecessary stuff for the client side if you use webpack.
For my build it changed from 17.7 KB gziped to 22.6.

Better add to your SSR code:
global.DOMParser = require('dom-parser')

I often use this snipped..

global.fetch = require('node-fetch')
global.indexedDB = require('fake-indexeddb')
global.DOMParser = require('dom-parser')
global.window = global

@te-online
Copy link
Author

I kind of have to agree, since in the meantime, I don't think dom-parser is actually a very good implementation. However, I don't really understand your workaround? Can you elaborate? Can we avoid having dom-parser in the bundle? I also don't really understand why the package increases your production bundle size so heavily when it just slightly increases the compressed size of this component alone?

@mrhein
Copy link

mrhein commented Aug 26, 2018

The global stuff is for my client bundle because i use web based stuff that doesn't exist in node like IndexedDB, fetch from my store, DOMParser for preact-markup.
I want a isomorph solution thats why i add the special "Browser stuff" to global, it is needed for hydrate my store with a fake (memory based IndexedDB fill it with graphQL query's wich needs fetch ... and so on).

My setup looks like: (client)

preact
  preact-shadow
  preact-markup
  preact-router
  stockroom
  unissist -> IndexDB hydration
  unistore
  yt-player

polyfill bundle uses: (old clients)

promise-polyfill
whatwg-fetch

In my SSR lambda i use render(h(App, { url: '/' })) while have prop url wired to preact-router.
I build two bundle's one for the client and another for SSR i have a special setup here but you could also use preact-cli.

Inside of template.js:
In my case i grep the bundle with const bundle = require('../../dist/ssr/ssr-bundle'), path for preact-cli would be build/ssr-build/ssr-bundle there are some special template optimisations inside for preact-shadow, hydrating the store and so on but after i just do module.exports.App = bundle.default.

const { h } = require('preact')
const { App, template, ... } = require('./template')

For generating the body you can just do `render(h(App, { url: e.path }))

const rendered = template.replace("<div id='app'></div>", body)
res.header('Cache-Control', 'public, max-age=60')
res.send(rendered)

will take the rest ...

Maybe i could build a boilerplate for preact-cli next weekend's if there is a need for.

@te-online
Copy link
Author

Thanks for your response! So what I basically take from your explanation is, you're building different bundles for client and server and in the server bundle you make browser-related stuff available through globals you're defining.

While this sounds great, I don't think it's a solution for everyone. I would urge @developit simply to decide if this is a feature the component should support and then it's probably possible to polyfill with a small footprint, or have a second export for the ssr-supported version, so that existing bundles stay small and others can make use of server-side-rendering.

By not responding to this pull-request for such a long I time, I guess the author already made a decision to not support this.

I've changed to a React module that works on both, client and server.

@developit
Copy link
Owner

developit commented Aug 27, 2018

Apologies for not responding to your PR @te-online! It wasn't intentional, I just get too many Github notifications so things often slip through unnoticed.

I would really like to support this use-case. Anyone using preact-cli is likely to run into the issue you ran into, including once we migrate preactjs.com over to the CLI.

One option I had thought of: what about exporting the server-side parser as a function, and requiring that during SSR it is passed into <Markup>?

import Markup from 'preact-markup';

// etc
  render() {
    return (
      // instead of bundling the parser, allow it to be passed in:
      const parser = typeof document==='undefined' && require('preact-markup/server');
      <Markup parser={parser} markup="html here" />
    );
  }

Otherwise I actually think this PR is the right way to go: dom-parser exports an interface that is compatible with DOMParser, so it's nice and easy to support injecting the parser without relying on an intermediary API to bridge between the two.

@developit developit self-requested a review August 27, 2018 20:10
@te-online
Copy link
Author

Thank you so much for your response! 😊

I like the idea of passing in the parser if necessary. 👍

Unfortunately, I will not be able to update the PR in the upcoming weeks. I could add it to my backlog, though, but would be more than
happy with someone else taking over!

@te-online
Copy link
Author

@developit Your suggestion led me to follow a different approach, where we would leave the choice of parser to the developer using the component. So we can avoid the awkward parser decision on the module side and at the same time provide some flexibility. I don't know if this is a sensible solution 😄

See #22

@danielweck
Copy link

danielweck commented Mar 30, 2021

Better add to your SSR code:
global.DOMParser = require('dom-parser')

FWIW, Preact WMR uses JSDOM, see: #6 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants