-
-
Notifications
You must be signed in to change notification settings - Fork 470
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
feat: allow to pass options to insert
function through style.use()
#535
Conversation
Allow to pass additional parameter to `style.use(anything)` which will be passed to `insert` function. This allows to insert each tag in different places and especially useful for Shadow DOM Resolves webpack-contrib#328
|
Good idea, anyway can you provide examples:
I want to add more tests and examples here? |
@alexander-akait previously we injected style tag to all shadow doms present on page because there was no way to specify which component loaded styles: component.js import css from './preferences.less';
import ReactDOM from "react-dom";
import React from "react";
class MyComponent extends React.Component {}
const attachMyComponentToPage = ($target, props) => {
if (!$target) {
$target = $(`<div id="MyComponentShadow" data-ad-view="true"></div>`);
$('body').append($target);
}
let shadow = $target[0].attachShadow({mode: 'open'});
ReactDOM.render(<MyComponent {...props} />, shadow, () => {
css.use();
});
}; Settings for styleLoader {
injectType: 'lazyStyleTag',
insert: function insert(el) {
let id = '_' + Math.random().toString(36).substr(2, 9);
console.log('Style loader insert:', el, id);
el.setAttribute('data-ad-id', id);
let shadows = document.querySelectorAll('[data-ad-view]');
shadows.forEach(function (node) {
if (node.shadowRoot) {
node.shadowRoot.appendChild(el.cloneNode(true));
} else {
node.appendChild(el.cloneNode(true));
}
});
if (shadows.length === 0) {
document.querySelector('head').appendChild(el.cloneNode(true));
}
},
styleTagTransform: function (css, style) {
let id = style.getAttribute('data-ad-id');
let styleNodes = [];
let shadows = document.querySelectorAll('[data-ad-view]');
shadows.forEach(function (node) {
console.log('Handling node', node);
if (node.shadowRoot) {
console.log('Found shadow, appending child');
let styleNode = node.shadowRoot.querySelector(`style[data-ad-id="${id}"]`);
if (styleNode) styleNodes.push(styleNode);
} else {
console.log('Ordinary node, appending child');
let styleNode = node.querySelector(`style[data-ad-id="${id}"]`);
if (styleNode) styleNodes.push(styleNode);
}
});
if (shadows.length === 0) {
console.log('No data-ad-view elements found, appending to page head');
let styleNode = document.querySelector(`style[data-ad-id="${id}"]`);
if (styleNode) styleNodes.push(styleNode);
}
for (let styleNode of styleNodes) {
if (styleNode.styleSheet) {
styleNode.styleSheet.cssText = css;
} else {
while (styleNode.firstChild) {
styleNode.removeChild(styleNode.firstChild);
}
styleNode.appendChild(document.createTextNode(css));
}
}
},
}; Let me explain what all this mess does. I assume this isn't perfect solutions and there is way to do it better with current version (without proposed changes to .use method). Here, in Because we often display multiple widgets on same page and all widgets use multiple .css files (one for antd, one for fontawesome, one for custom styles) we end up with a bunch of With changes proposed in this PR you can pass parameters to component.js import css from './preferences.less';
import ReactDOM from "react-dom";
import React from "react";
class MyComponent extends React.Component {}
const attachMyComponentToPage = ($target, props) => {
if (!$target) {
$target = $(`<div id="MyComponentShadow" data-ad-view="true"></div>`);
$('body').append($target);
}
let shadow = $target[0].attachShadow({mode: 'open'});
ReactDOM.render(<MyComponent {...props} />, shadow, () => {
css.use({target: shadow}); // Note we're now passing shadow root to .use call
});
}; Settings for styleLoader {
injectType: 'lazyStyleTag',
insert: function insert(el, options) {
(options.target || document.querySelector('head')).appendChild(el);
}
}; I think there might be other use cases (maybe you need to know which component invoked particular styles) but this^^ is main one I had in mind. While writing this comment I thought it might be useful to pass options from |
sounds good too Note - maybe help in future webpack-contrib/css-loader#1368 |
Done. Also changed options.insertOptions = insertOptions || {}; to just options.insertOptions = insertOptions; in case someone would like to pass |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's add test for unuse
to sure we remove the same target
If I understand correctly, |
Yep, just need to add test(s) to avoid break it/regression in future |
I'm not very proficient with Jest, I hope these tests are okay |
Okay, I will finish tests after merge it |
I will finish this PR |
@alexander-akait Thanks! Do you have any plans when to release new version (to npm) with these changes? |
@OlegWock today/tomorrow, want to finish some features for css-loader, because it requires more logic here |
Allow to pass additional parameter to
style.use(anything)
which will be passed toinsert
function. This allows to insert each tag in different places and especially useful for Shadow DOMResolves #328
This PR contains a:
Motivation / Use-Case
I'm using style-loader in WebExtension and we heavily rely on Shadow DOM (we inject our widgets into 3rd party sites and want them look always nice, same on all sites). But it was a pain to inject styles into Shadow DOM (you better not peek on my old webpack config haha!). This small change allows to pass custom options (any object basically) to the
styles.use
call, which later will be passed toinsert
function. This allows customizinginsert
logic: now you can insert each style into different place and do whatever you want for each style individuallyBreaking Changes
This shouldn't break anything
Additional Info
Resolves #328 (not in the proposed way tho)