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

Using non-stencil custom elements breaks SSR #1782

Closed
patrickarlt opened this issue Aug 4, 2019 · 2 comments
Closed

Using non-stencil custom elements breaks SSR #1782

patrickarlt opened this issue Aug 4, 2019 · 2 comments
Labels
ionitron: stale issue This issue has not seen any activity for a long period of time

Comments

@patrickarlt
Copy link

patrickarlt commented Aug 4, 2019

Stencil version:

@stencil/core@1.2.2

I'm submitting a:

[x] bug report
[ ] feature request
[ ] support request => Please do not submit support requests here, use one of these channels: https://stencil-worldwide.herokuapp.com/ or https://forum.ionicframework.com/

Current behavior:

I'm working on a component library and we are using a non-Stencil custom element <focus-trap>. When we use <focus-trap> in our project prerendering our code with the renderToString method we get from the dist-hydrate-script build target. We get this error.

window.customElements.define("focus-trap", FocusTrap);
                      ^

TypeError: Cannot read property 'define' of null

Expected behavior:
Give the info in the existing prerendering guide I wouldn't expect this to work. BUT given that Stencil promotes Web Components so heavily I think it could be reasonable expected the Stencil shouldn't choke on this because people might pull in other web component based code into their Stencil projects.

Steps to reproduce:

In a new Stencil project install focus trap npm i @a11y/focus-trap and make a component like:

import { Component, h } from "@stencil/core";
import "@a11y/focus-trap";

@Component({
  tag: "my-component",
  styleUrl: "my-component.css",
  shadow: true
})
export class MyComponent {
  render() {
    return (
      <focus-trap>
        <div>Hello, World! I'm in a focus trap!</div>
      </focus-trap>
    );
  }
}

Then add { type: "dist-hydrate-script" } to your outputTargets in stencil.config.js and run stencil build.

next call renderToString:

const { renderToString } = require("./hydrate/");

async function render() {
  const results = await renderToString(`
    <!DOCTYPE html>
    <html dir="ltr" lang="en">
    <head>
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=5.0">
      <title>Stencil Component Starter</title>

      <script type="module" src="/https://github.com/dist/stencil-scratch.esm.js"></script>
      <script nomodule src="/https://github.com/dist/stencil-scratch.js"></script>

    </head>
    <body>

      <my-component></my-component>

    </body>
    </html>
  `);

  console.log(results);
}

render();

Related code:

It looks like https://github.com/ionic-team/stencil/blob/90f72634c579c5e4f16a88b0ab672d7ac8c5d7b2/src/hydrate/runner/window-initialize.ts#L39-L41 is what causes this by setting window.customElements back to null it make it unavailable. I tried commenting this out and everything seems to work fine but I don't know what other negative impacts removing this might have.

Other information:

This comes from https://github.com/andreasbm/focus-trap/blob/master/src/lib/focus-trap.ts#L208 which assumes it is being loaded on the client. While the prerendering guide talks about using Build.isBrowser variable to avoid cases like this there are a few reasons why this is difficult in this case.

  • This error occurs as soon as the code from focus-trap is evaluated. I tried something like
    if (Build.isBrowser) {
      import("@a11y/focus-trap").then(() => {
        // set a flag to know if I should wrap in <focus-trap> (browser) for a <div> (prerender)
      });
    }
    But this doesn't work. The code still gets evaluated right away and the error gets thrown.
  • This could be solved in focus trap by wrapping window.customElements.define in an if statement works but this only solve this issue for focus trap not all custom elements.
    if (window && window.customElements) {
      window.customElements.define("focus-trap", FocusTrap);
    }
@splitinfinities
Copy link
Contributor

Hey there, thank you for the patience getting back to you. The new team is getting started and we're working through the backlog now.

We do not support Stencil versions less than v2, and you seem to be using an older version of Stencil. If you can upgrade to the latest version and let me know if this issue still exists, I would appreciate it.

Let me know if you need anything else!

@ionitron-bot ionitron-bot bot added the ionitron: stale issue This issue has not seen any activity for a long period of time label Feb 6, 2022
@ionitron-bot
Copy link

ionitron-bot bot commented Feb 6, 2022

Thanks for the issue! This issue is being closed due to inactivity. If this is still an issue with the latest version of Stencil, please create a new issue and ensure the template is fully filled out.

Thank you for using Stencil!

@ionitron-bot ionitron-bot bot closed this as completed Feb 6, 2022
@ionitron-bot ionitron-bot bot locked and limited conversation to collaborators Feb 6, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
ionitron: stale issue This issue has not seen any activity for a long period of time
Projects
None yet
Development

No branches or pull requests

2 participants