Open seahindeniz opened 1 year ago
is this feature in plan?
There is an open PR that should address this issue https://github.com/vitejs/vite/pull/12206. I added it with higher priority to discuss the addition of a new option. Let's use this issue to track the feature.
This is the workaround I used.
Run this code in the connectedCallback:
const styleTag = document.createElement("style");
styleTag.innerHTML = <link-to-css>;
this.shadowRoot.appendChild(styleTag);
This is the workaround I used.
@RogierdeRuijter Can you expand on what you mean by the connectedCallback? Is the connectedCallback part of Vue? In my use case I'm not using web components but rather, I am mounting my app inside a shadow DOM to use that as a micro front end.
@seahindeniz Do you have any updates on this issue? I feel that this is a crucial part of building Microfrontends with Vue. ShadowDOM is probably the best and least hacky way to encapsulate styles within micro-frontends. Perhaps you know a workaround that is not too hacky? I feel that manually moving styles from the document head into the shadow DOM is brittle.
Hi @Oumar96, I totally agree with you and unfortunately no solution so far
+1, same request here.
+1. do we have any solution for this?
+1 - looking for a way to apply Vite generated CSS into a shadow root
try this
@gs-rpal Could you share the vite config file instead of the screenshot?
+1, it would be great to have this option as some kind of vite's configuration or plugin.
@gs-rpal please share that config 🙏 ❤️
The only workaround for this for now is to query the document for <link>
or <style>
elements, then add them to your ShadowRoot.
StylesSheet
s can be added to this.shadowRoot.adoptedStyleSheets
in all modern browsers.
const styleElements = document.documentElement.querySelectorAll('..... select all the <link>s and <style>s you want ...')
const sheets = Array.from(styleElements).map(el => el.sheet)
// Apply the desired style sheets to your custom element (via the shadow root):
this.shadowRoot.adoptedStyleSheets = [...sheets]
If you cannot support adoptedStyleSheets
because you support older browsers, then you can clone elements and place them in the root:
const styleElements = document.documentElement.querySelectorAll('..... select all the links and styles you want ...')
const styleClones = Array.from(styleElements).map(el => el.cloneNode(true))
// Append clones of the desired style elements to your custom element (via the shadow root):
this.shadowRoot.prepend(...styleClones)
[!Note]
prepend()
instead ofappend()
so that they will be above your shadow roots existing styles, if any, so that your own root's styles override the shared ones that you bring in.
i would also like the element that are created to be not document.createElement but shadowroot.createElement... current way is copy whole internals to add a custom renderer in place... this would help with custom element registery where there is already a proposal for and a polyfill
vue is just not made for webcomponents.. could be oke for mfe stuff if it fixes lot of these issues there many more on like not syncing the attributes if you use a custom element as a root its not ready for most of the newer browser api's and its not made for smaller webcomponents/custom elements.. there only thing is lit or fast something like this... this hacking with out real good support just makes is very brittle because you have to copy and rely on non exposed internals... that dont follow semver :) cause there internals... and hard to follow...
sorry for the rant .. vue just needs to give webcomponents some serious love to be atlease useable for mfe stuff there currently only properly suited for spa things
for singlar webcomponents since vue creates a vue app even if you make a button its about 800% slower then something like lit and 10 times more heavy on memory usage.
vue just needs to give webcomponents some serious love
This is the vite
repo tho.
yea true
FYI I’ve created a plugin that does just what I was looking for. Please try it out and let’s see whether it fits your use cases too. I’m pretty sure it’s very specific to my specific usage scenarios, so it’ll not fit anyone’s needs, but nothing stops us from using it as a starting point for a more adaptable plugin.
Link here: https://www.npmjs.com/package/vite-plugin-shadow-style
try this
@gs-rpal Any updates? Could you share the config file?
Hello, this feature would be really great to support injection into Shadow roots! Is there already a nice workaround for this?
Hello, this feature would be really great to support injection into Shadow roots! Is there already a nice workaround for this?
Hi, probably my solution I linked above can help you with style injection into shadow roots: https://www.npmjs.com/package/vite-plugin-shadow-style
Hello @hood thanks for your comment, but somehow for the dev mode it deactivates the shadow root and for build mode it gives me the warning:
rendering chunks (141)...[vite-plugin-shadow-style] Multiple CSS files found in the output bundle. This plugin currently only supports handling a single css output.
A question to the "vite" team: is it possible to add a feature where it is possible to configure where to inject the styles? Right now only "head" is possible... The code for it is here:
I also tried the solution from @gs-rpal but it only seems to work for dev mode.
Hello guys, is there any progress for this feature? Thank you 🙏 cc: @bluwy
try this
worked for me! But need create Shadow Dom in Vue and after this code put in ShadowRoot your css code create shadowdom main.js:
import vue from 'vue';
import MyComponent from 'src/MyComponent';
let treeHead = document.querySelector(".container");
let holder = document.createElement("div");
let shadow = treeHead.attachShadow({mode: 'open'});
shadow.appendChild(holder);
let app = new Vue({
el: holder,
render: h => h(MyComponent, {})
});
I would need this feature so bad for my current project! A custom target, where the Styles should be inserted would be so great - with it we would be totally flexible! Is there any progress on this feature? 🙏🙏🙏🙏
Something else to consider is SSR Declarative Shadow DOM. Link tags will be hoisted to the head ignoring the template and waiting for client code to append the tags results in FOUC.
Is there any updates on this? I ended up importing the styles using 'style.css?inline'
and adding them manually inside the shadow dom. But it feels quite hacked.
FYI it is impossible to add fonts and icons to shadow dom via <style>
tag because @font-face
isn't supported there yet:
https://issues.chromium.org/issues/41085401
The workaround is to use <link>
instead:
https://github.com/mdn/interactive-examples/issues/887#issuecomment-470703209
my currently working solution (both with serve
and build
commands) is:
in vite.config.ts
import { defineConfig } from "vite";
import cssInjectedByJsPlugin from "vite-plugin-css-injected-by-js";
export function defineConfig(() => {
const globalStylesIdentifier = "__myStylesIdentifier";
return {
plugins: [
cssInjectedByJsPlugin({
injectCode: (cssCode, _options) => {
return (
`try{` +
`var s = document.createElement('style');` +
`s.appendChild(document.createTextNode(${cssCode}));` +
`window.${globalStylesIdentifier} = window.${globalStylesIdentifier} || []; window.${globalStylesIdentifier}.push(s);` +
`}catch(e){` +
`console.error('${globalStylesIdentifier}', e);` +
`}`
);
},
dev: {
enableDev: true,
removeStyleCodeFunction: function removeStyleCode(_id) {
// The 'id' corresponds to the value of the 'data-vite-dev-id' attribute found on the style element. This attribute is visible even when the development mode of this plugin is not activated.
},
},
})
]
};
};
in app.ts
or where in my application code I want to inject the styles
const myShadowDomRoot = myDiv.shadowRoot;
if (myShadowDomRoot) {
const styles = window.__myStylesIdentifier || [];
while (styles.length) {
myShadowDomRoot.prepend(styles.pop() || "");
}
}
Description
Vue started to support mounting app inside of a shadow-root element within this PR. With the following code, I can mount my Vue app under a shadow-root node
However, Vite loads style/script elements under the document head element because of the following function and since style elements are getting appended outside of the shadow-root scope, style definitions are not getting applied to HTML elements under the shadow-root. https://github.com/vitejs/vite/blob/356ddfe2e534800c1fd59fa502a2c4c8945f4f92/packages/vite/src/node/plugins/importAnalysisBuild.ts#L63-L119
As a use case, I need to mount a multiple apps to DOM under a shadow-root to avoid scope related collisions.
Suggested solution
Mentioned function can support different parent element to append style/script elements
Alternative
No response
Additional context
No response
Validations