Modern Widget Development with React, PostCSS, and Webpack

29 Sep 2017 3 minutes

Notes on developing Javascript widgets with modern tooling

Recently I was tasked with developing a Javascript widget that users can include on their websites. I wanted to continue to use my current development stack so opted for react, webpack, and PostCSS as a foundation. This article quickly covers some aspects of developing a Javascript widget using modern tooling and libraries.

iframe vs. prefixing and specificity hacking

There are a couple options when trying to manage styles in a widget. Either wrap your application in an iframe. Or use a reset like cleanslate whilst prefixing your selectors and hope for the best. The route you take will really depend on your requirements.

Using an iframe will help with most style bleeding issues, but at a cost: You won’t be able to interact easily with the host page, and media queries are no longer straight forward.

Embedding directly into a page let’s you continue to use media queries and interact directly with the host page, but conflicts will be inevitable. Prefixing classnames and hacking specificity will go a long way but there is no silver bullet.

Embedding without an iframe

Dealing with specificity conflicts

The widget can be included on a variety of sites, these sites most likely will have unpredictable styles from different sources. Ultimately there will be conflicts, but most cases can be covered by deferring script execution as long as possible whilst trying to trump host declaration specificity by using !important.

Encouraging placement of the widget later on in markup will help when there are major conflicts. When the host page has a generic selector using !important, the widget declarations specificity should be higher due to appearing after the host declaration. Although using !important is usually frowned upon, it’s necessary when developing a Javascript widget that is not relying on the use of iframes.

Automatic !important with PostCSS

To cover a majority of cases, automatically adding !important to declarations can be useful and keep your styles clean. Luckily a fantastic plugin postcss-safe-import exists for this with the ability to toggle it for certain declarations.

Making use of webpack style-loader

When using webpack, make use of style-loader to automatically inject your stylesheets. When your application bundle is loaded, styles will be added to the DOM and ready for when your app has bootstrapped.

Embedding with iframe

React-iframe + style injection

If you don’t want to deal with prefixing your classes and fighting specificity, you can wrap your widget in an iframe.

A fantastic react component exists for this react-frame-component and makes it possible to wrap your react application in an iframe with little effort, you can read more about it here.

Handling styles within the iframe can be a little tricky, but by making use of webpack’s css-loader toString() + react-frame-components initialContent you can inject the styles into the iframe (with a few quirks).

{
   test: /\.css$/,
   use: [
     'to-string-loader',
     'css-loader'
   ]
}

const styles = require('./index.css').toString();

const initialContent = ```<!DOCTYPE html><html><head><style>${styles}</style></head><body><div></div></body></html>```;

ReactDOM.render(
  <Frame initialContent={initialContent}>
    <Header>Hello</Header>
  </Frame>,
  document.body
);

Wrapping up

Information on developing Javascript widgets seems to be a little fragmented/non-existent, especially with modern tooling and libraries, so I wrote this article to try and help others. None of this would be possible without the fantastic work of the open source developers behind the libraries and tools discussed here.

Want to work together?

Need a versatile Web Developer and Designer? Want to find out more about what I do?

I'm currently taking on new projects