Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save kziemski/877b8d49a521932201bf10703d52f3e2 to your computer and use it in GitHub Desktop.
Save kziemski/877b8d49a521932201bf10703d52f3e2 to your computer and use it in GitHub Desktop.
Modification of Webpack style-loader module bundler that enable where to insert the css styles
/*
* Alternative version of StyleTagTransform option of Webpack's style-loader module bundler that enables
* bundled project to insert imported styles on different container elements conditionally.
* This enables usage of Module Federation Apps inside ShadowDom containers.
*
* Users should provide an "attributes" option on the project's Webpack style-loader configuration that contains
* the element's reference on the window object
*/
var css = require('css')
var cssParse = css.parse
var cssStringify = css.stringify
function processRules(list, options) {
return list.map(function (r) {
if (r.selectors) {
r.selectors.forEach(function (s, index) {
var selector = options.selector ? options.selector + ' ' + s : s
r.selectors[index] = selector
})
}
if (r.type === 'media') {
r.rules = processRules(r.rules, options)
}
return r
})
}
function cssWrap(string, options) {
var css = cssParse(string)
css.stylesheet.rules = processRules(css.stylesheet.rules, options)
return cssStringify(css)
}
module.exports = function (css, style) {
var idSelector = '#' + this.attributes.from
var rootElement = window[this.attributes.from]?.root
if (!rootElement) {
throw new Error(`
The project's rootElement configuration was not found, or an incorrect project key was configured.
It should be the entry window['your-app'].root set at project startup`
)
}
if (process.env.NODE_ENV === 'development') {
style.innerHTML = css
return
}
let shadowRoot = null
// If app root element is an instance of shadow root or is contained within a shadow root
if (rootElement instanceof ShadowRoot) {
shadowRoot = rootElement
} else if (rootElement.shadowRoot instanceof ShadowRoot) {
shadowRoot = rootElement.shadowRoot
} else if (rootElement.getRootNode() instanceof ShadowRoot) {
shadowRoot = rootElement.getRootNode()
}
if (shadowRoot) {
style.innerHTML = css
shadowRoot.insertBefore(style, shadowRoot.lastChild)
return
}
var cssWrappered = cssWrap(css, { selector: idSelector })
style.innerHTML = cssWrappered
document.head.appendChild(style)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment