9

I'm trying to render my React component inside an iframe. I got it to work by using the library "react-frame-component". The problem is that the styles are loaded outside the iframe, at the end of "head" element. I want to change it to be loaded inside the "head" of "iframe" element. I'm using Webpack to generate the bundles with JS and CSS included and I saw that I can change where "style-loader" will load the styles by setting the option "insertInto", but this is throwing an error:

Uncaught Error: Couldn't find a style target. This probably means that the value for the 'insertInto' parameter is invalid.

This is my React component:

import Frame from 'react-frame-component'
...
ReactDOM.render(
  <Frame id="someId">
    <Provider store={Store.get()}>
      <Container/>
    </Provider>,
  </Frame>,
  document.body
);

This is my "style-loader" in Webpack configuration:

{
  loader: 'css-loader',
  options: {
    insertInto: () => document.querySelector("#someId"),
  },
}

I think the problem is that the component was not rendered when webpack tried to include the styles. How to solve this?

Sandro Simas
  • 1,268
  • 3
  • 21
  • 35
  • 1
    You can't do that thus Webpack is working at a lower level with the raw content of your HTML, while your React is generating HTML content long after client browser running your javascript. You can make a ` – Up209d May 07 '18 at 07:33

1 Answers1

2

You would need to load the styles into a temporary element as placeholder, and then use Javascript to clone those styles into the new frame.

// index.html
...
<div id="dynamic-styles"></div>
...
// webpack.config.js
...
{
  loader: 'css-loader',
  options: {
    insertInto: () => document.getElementById("dynamic-styles"),
  },
}
...
// some.js
...

const stylesContainer = document.getElementById('dynamic-styles');
const frame = document.getElementById('someID');
const frameHead = frame.contentWindow.document.head;

[...stylesContainer.children].forEach(styleNode => {
  const newStyle = document.createElement('style');
  newStyle.textContent = styleNode.textContent;

  frameHead.appendChild(newStyle);
});

I haven't tested the above snippet but I know the concept works. I feel it gets the point across.

There may be a better way to do this but I haven't looked into it enough to figure it out yet. It'd be nice to be able to get webpack to make separate style bundles so that each configured frame could just automatically lazy load it's own dedicated bundled css

AlexMorley-Finch
  • 6,785
  • 15
  • 68
  • 103