enonic / lib-react4xp

React for XP: handling and rendering of pre-built React components in Enonic XP
Apache License 2.0
2 stars 2 forks source link

JS-dependent styling #322

Open espen42 opened 2 years ago

espen42 commented 2 years ago

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:

espen42 commented 2 years ago

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 commented 2 years ago

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 commented 2 years ago

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.

ComLock commented 1 year ago

Related https://github.com/enonic/lib-react4xp/issues/780

ComLock commented 1 year ago

This polyfill is not needed anymore since document has been removed https://github.com/enonic/lib-react4xp/issues/738

ComLock commented 1 year ago

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)