gatsby-remark-highlight-code icon indicating copy to clipboard operation
gatsby-remark-highlight-code copied to clipboard

Solid plugin, shame there's no SSR support

Open endymion1818 opened this issue 5 years ago • 16 comments

This is a fab plugin and I love it ... it would be really nice if it was rendered on the server instead of the client if that's at all possible.

The reason being, I publish both a React app version of my site and a static HTML version. With the plugin enabled the styles of my code blocks have been removed altogether. I can work around it, so not a breaking issue, but it would also mean less javascript being sent down the wire...

endymion1818 avatar Sep 21 '20 13:09 endymion1818

Hey @endymion1818 thx for the issue. I do understand and see your point, but can't you render it on the server side, it doesn't work aka you are facing problem rendering it on the server?

or is the problem the fact that it is rendered both on server side and then loaded on the front end side again?

peterpeterparker avatar Sep 21 '20 14:09 peterpeterparker

note: the source of web components attached by this plugin are available in our mono-repo in case you want to play with it ;)

https://github.com/deckgo/deckdeckgo/tree/master/webcomponents/highlight-code

peterpeterparker avatar Sep 21 '20 14:09 peterpeterparker

Unfortunately it doesn't render on the server at all by the looks of things ... I tried it locally and it rendered without any styles:

Screenshot 2020-09-21 at 15 41 34 Screenshot 2020-09-21 at 15 42 01

Code looks pretty great when JS is enabled but it would just be awesome to do this on the server first...

endymion1818 avatar Sep 21 '20 14:09 endymion1818

Thank you for your answer. To be honest with you, I am not sure that I will be able to debug it and fix it, SSR is tricky and I don't use it with this plugin by myself.

But we can give it a short try. Can you provide a simple sample repo to reproduce the issue?

peterpeterparker avatar Sep 21 '20 14:09 peterpeterparker

I appreciate that, no worries if not ...

Here's the initial implementation PR I have: https://github.com/endymion1818/deliciousreverie/pull/94/files

Thanks for looking at it 👍

endymion1818 avatar Sep 21 '20 14:09 endymion1818

thank you for the repo.

I should "just" checkout the PR and then npm run build? or what are the cmds?

Just want to be sure that I perform the exact same operations as you.

peterpeterparker avatar Sep 21 '20 14:09 peterpeterparker

yeah, npm run build && npm run serve will put it on port 9000

endymion1818 avatar Sep 21 '20 14:09 endymion1818

oki doki. I'll give a try this evening. Like I said, don't expect too much, but I'll try ;)

peterpeterparker avatar Sep 21 '20 14:09 peterpeterparker

I appreciate that, thank you 👍

endymion1818 avatar Sep 21 '20 14:09 endymion1818

Ah, you'll also need a .env file in the root with the following value:

JS_DISABLED=true

endymion1818 avatar Sep 21 '20 15:09 endymion1818

Ok now I understand what do you mean. You want to use Gatsby prerendering but would like the component to be generated as it would be on the browser side or with SSR and, the result to be, including its shadowed content, added to the output files, is that correct?

Basically a prerender which execute the scripts and save the content including the shadowed content in the html files.

For example

<component>
  <div>my-content</div>
</component>

would be injected in prerendered output files as

<component>
    #shadow-root
    <style>:host {background: red;}</style>
    <div><slot/></div>
  <div>my-content</div>
</component>

Summarized you would like Gatsby to server render the Web Components to generate the output bundle files.

Well, if this is correct, I am not sure, but I would say that it is currently not possible. Not just this Web Component but generally speaking Gatsby not being able to evaluate server side render of Web Components.

I might be wrong of course and I would be more than happy if someone would correct me, otherwise looks like there isn't much I can do.

What do you think, am I missing something?

peterpeterparker avatar Sep 21 '20 18:09 peterpeterparker

I think I understand what you mean, and also why it's not possible ... because these aren't just applied styles, you're adding to the DOM, which is not something that can happen at build time.

Thats a shame, but I totally get it.

I've done a little more research, and maybe StencilJS is a way to render web components on the server ... there seems to be a Gatsby plugin, but I assume it'll need some work to integrate with ... work which I'm not going to ask you to do, you've already created this, which is awesome.

I'll still use this plugin on the site I have with JS-enabled, I'm happy I can make code pretty there :-D

endymion1818 avatar Sep 21 '20 19:09 endymion1818

I think I've got the same understanding as you, Stencil WC can be rendered on the server side but how to achieve this with Gatsby is not that clear to me at this point.

Happy to hear you are going to use the plugin anyway and that it suits you!

Thanks again for the good issue!

Of course I suggest that we keep this open. If anyone want or can jump in and solves it or bring the discussion further, let me know, that would be awesome!

peterpeterparker avatar Sep 21 '20 20:09 peterpeterparker

@BrunnerLivio found a way to make Stencil and Gatsby work together with SSR. Here's his recipe, I think it would solve this feature request as long as Primsjs can work on the server side (need to check that it does no use the window object).


Make sure you have already integrated stencil-ds-output-targets. In our case we have two packages:

@my/webcomponents-library Only the webcomponents from Stencil @my/react-webcomponents-library The output from the React

It must have the output target dist-hydrate-script for the WebComponents package (@my/webcomponents-library) In your stencil.config.ts

const config: Config = {
  outputTargets: [
    { type: 'dist-hydrate-script' },
    ...
  ]
...
}

Use CommonJS output target for the React output target package (@my/react-bwecomponents-library) Personally, I’ve just inspired myself by Ionic:

  • Copy the rollup.config.js
  • Copy the tsconfig.json
  • Build your app using tsc -p . && rollup -c

Make sure you don’t reference window anywhere within your library More on this here

Add the following to your Gatsby App: In gatsby-node.js :

exports.onPostBuild = async () => {
  const stencil = require("@my/webcomponents-library/hydrate");
  const files = glob.sync("public/**/*.html");
  return Promise.all(
    files.map(async (file) => {
      try {
        const html = fs.readFileSync(file, "utf8");
        const result = await stencil.renderToString(html, {});
        fs.writeFileSync(file, result.html);
        return result;
      } catch (e) {
        // Ignore error where path is a directory
        if (e.code === "EISDIR") {
          // eslint-disable-next-line consistent-return
          return;
        }
        throw e;
      }
    })
  );
};

In gatsby-browser.js :

const { defineCustomElements } = require("@my/webcomponents-library/loader");
defineCustomElements();

Done! Import your components via:

import { MyComponent } from "@my/react-webcomponents-library";

peterpeterparker avatar Apr 29 '21 16:04 peterpeterparker

In addition: https://github.com/jonearley/gatsby-plugin-stencil

peterpeterparker avatar Apr 30 '21 04:04 peterpeterparker

Thanks! I'll check those out

endymion1818 avatar May 06 '21 20:05 endymion1818