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

JS-dependent styling #322

Open
2 tasks
espen42 opened this issue Jan 5, 2022 · 6 comments
Open
2 tasks

JS-dependent styling #322

espen42 opened this issue Jan 5, 2022 · 6 comments

Comments

@espen42
Copy link
Contributor

espen42 commented Jan 5, 2022

Solutions where styling at runtime is based on javascript (such as https://cssinjs.org/?v=v10.9.0 or babel-plugin-transform-scss) is currently not supported. Two issues around that:

  • Hydration is disabled inside content studio. So the styling JS is never called in the client.
  • JS code relies on client-side code (document.querySelector etc). When run as SSR, it fails.
@espen42
Copy link
Contributor Author

espen42 commented Jan 5, 2022

Tentative workaround for SSR failing with babel-plugin-transform-scss: add this extra nashornPolyfill:

document.querySelector = () => null;
document.querySelectorAll = () => [];
document.head = {
    appendChild: () => {}
}
document.createElement = () => ({
    dangerouslySetInnerHTML: {},
    style: {},
    innerHTML: {},
    setAttribute: () => {}
});
window=window || {};

This will produce un-styled output from SSR: styling is not applied before client-side rendering (hydration) is run. Consequences: in cases where hydration is disabled (eg. in CS edit mode when passing in the recommended request argument to the render methods), edit mode will display an un-styled render. Also consequences to SEO?

@espen42 espen42 self-assigned this Jan 5, 2022
@espen42 espen42 changed the title JSS JS-dependent styling Jan 5, 2022
@espen42
Copy link
Contributor Author

espen42 commented Feb 23, 2022

There is a possible workaround for the problem with styling in content studio, tried for the Material UI framework MUI.

In the XP controller, when calling the react4xp .render* methods, replace the mode attribute in the request argument object with the value "live". Best not to mutate the request object itself though:

const res = React4xp.render(
        "myEntry",
        myProps,
        { ...request, mode: "live" }    //  <--
    );

Several things to note around this though:

This does not solve issues around JS calls that break server side rendering, those must be solved separately (eg. skipping SSR entirely with clientRender: true, or adding nashorn polyfilling, or using SSR mode in the framework - MUI seems to have that, for example).

Also: usually, react4xp uses request.mode to detect content studio rendering and hold back JS page contributions. Forcing this value to "live" tricks react4xp into always adding them. Two important consequences (which were the reason for default-removing JS in content studio):

Firstly, this may cause a worse user experience for content studio editors, since the react components are now always active/clickable in the previews, and this may interfere with working with react4xp-rendered parts and layouts the WYSIWYG page builder.

Secondly, in early testing of react4xp, some cases were found where react4xp's client-side JS from the pagecontributions interfered with the JS of content studio itself and sometimes breaking stuff. It's unclear whether this is still an issue in current versions of XP / content studio / react4xp, but it's recommended to keep an eye out for this and test thoroughly.

With this in mind, this workaround may still be a viable option for some.

@VirtueMe
Copy link

VirtueMe commented Mar 5, 2022

This hit me hard with Emotion and react-select

Is there a way to unset document?

My polifyll for this to get this to work was as follows:

if (document && !document.querySelectorAll) {
  document.head = {
    appendChild: () => {},
    insertBefore: () => {}
  }

  document.createTextNode = (text) => ({
    innerHTML: { text }
  })

  document.querySelector = () => null;

  document.querySelectorAll = () => []

  document.createElement = (name) => ({
    name,

    dangerouslySetInnerHTML: {},

    style: {},

    innerHTML: {},

    appendChild: () => {},
    insertBefore: () => {},

    setAttribute: () => {}
  })
}

Now it displays in Content Studio, but it doesn't look nice.

@espen42 espen42 removed their assignment May 4, 2022
@ComLock
Copy link
Contributor

ComLock commented Apr 4, 2023

Related #780

@ComLock
Copy link
Contributor

ComLock commented Apr 4, 2023

This polyfill is not needed anymore since document has been removed #738

@ComLock
Copy link
Contributor

ComLock commented Apr 4, 2023

We plan to support Emotion, but probably not in the next release.

If one sets ssr: false (only client-side rendering), then Emotions should work.

(side-note: Content Studio Edit Mode won't work)

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

No branches or pull requests

3 participants