While developing a Vue web component, the style is not applied to the web component, but added to the head of the document. This means that the style is ignored in the shadow DOM. Here is how I wrap the web component in main.js:
import Vue from 'vue'; import wrap from '@vue/web-component-wrapper'; import MyWebComponent from './components/MyWebComponent'; const WrappedElement = wrap(Vue, MyWebComponent); window.customElements.define('my-web-component', WrappedElement); Again, any CSS rules inside the style tags do not take effect.
When I build for production, the styles are added to the web component. I use the following command to do the wrapping:
vue-cli-service build --target wc --name my-web-component ./src/components/MyWebComponent.vue Is there a way to achieve the same thing with vue-cli-service serve?
edit: example repo here: https://github.com/snirp/vue-web-component
edit2: I have the feeling my problem is closely related to this issue. I cannot make much sense of the workarounds, and I would value a more basic solution.
Based on the GitHub issue you linked, the solution is to set the shadowMode option in vue-loader and vue-style-loader. shadowMode is false by default in a Vue CLI project, but we can tweak that in vue.config.js.
First, we'd inspect the Webpack config to determine which loaders to change:
# run at project root vue inspect The command output reveals several loader configs with shadowMode: false:
/* config.module.rule('css') */ { test: /\.css$/, oneOf: [ /* config.module.rule('css').oneOf('vue-modules') */ { resourceQuery: /module/, use: [ /* config.module.rule('css').oneOf('vue-modules').use('vue-style-loader') */ { loader: 'vue-style-loader', options: { sourceMap: false, shadowMode: false // <--- } }, /* ... */ ] }, /* ... */ full list of Webpack loader configs with shadowMode: false:
config.module.rule('vue').use('vue-loader') config.module.rule('css').oneOf('vue-modules').use('vue-style-loader') config.module.rule('css').oneOf('vue').use('vue-style-loader') config.module.rule('css').oneOf('normal-modules').use('vue-style-loader') config.module.rule('css').oneOf('normal').use('vue-style-loader') config.module.rule('postcss').oneOf('vue-modules').use('vue-style-loader') config.module.rule('postcss').oneOf('vue').use('vue-style-loader') config.module.rule('postcss').oneOf('normal-modules').use('vue-style-loader') config.module.rule('postcss').oneOf('normal').use('vue-style-loader') config.module.rule('scss').oneOf('vue-modules').use('vue-style-loader') config.module.rule('scss').oneOf('vue').use('vue-style-loader') config.module.rule('scss').oneOf('normal-modules').use('vue-style-loader') config.module.rule('scss').oneOf('normal').use('vue-style-loader') config.module.rule('sass').oneOf('vue-modules').use('vue-style-loader') config.module.rule('sass').oneOf('vue').use('vue-style-loader') config.module.rule('sass').oneOf('normal-modules').use('vue-style-loader') config.module.rule('sass').oneOf('normal').use('vue-style-loader') config.module.rule('less').oneOf('vue-modules').use('vue-style-loader') config.module.rule('less').oneOf('vue').use('vue-style-loader') config.module.rule('less').oneOf('normal-modules').use('vue-style-loader') config.module.rule('less').oneOf('normal').use('vue-style-loader') config.module.rule('stylus').oneOf('vue-modules').use('vue-style-loader') config.module.rule('stylus').oneOf('vue').use('vue-style-loader') config.module.rule('stylus').oneOf('normal-modules').use('vue-style-loader') config.module.rule('stylus').oneOf('normal').use('vue-style-loader') So, we can set shadowMode: true for those configs in vue.config.js with this snippet:
function enableShadowCss(config) { const configs = [ config.module.rule('vue').use('vue-loader'), config.module.rule('css').oneOf('vue-modules').use('vue-style-loader'), config.module.rule('css').oneOf('vue').use('vue-style-loader'), config.module.rule('css').oneOf('normal-modules').use('vue-style-loader'), config.module.rule('css').oneOf('normal').use('vue-style-loader'), config.module.rule('postcss').oneOf('vue-modules').use('vue-style-loader'), config.module.rule('postcss').oneOf('vue').use('vue-style-loader'), config.module.rule('postcss').oneOf('normal-modules').use('vue-style-loader'), config.module.rule('postcss').oneOf('normal').use('vue-style-loader'), config.module.rule('scss').oneOf('vue-modules').use('vue-style-loader'), config.module.rule('scss').oneOf('vue').use('vue-style-loader'), config.module.rule('scss').oneOf('normal-modules').use('vue-style-loader'), config.module.rule('scss').oneOf('normal').use('vue-style-loader'), config.module.rule('sass').oneOf('vue-modules').use('vue-style-loader'), config.module.rule('sass').oneOf('vue').use('vue-style-loader'), config.module.rule('sass').oneOf('normal-modules').use('vue-style-loader'), config.module.rule('sass').oneOf('normal').use('vue-style-loader'), config.module.rule('less').oneOf('vue-modules').use('vue-style-loader'), config.module.rule('less').oneOf('vue').use('vue-style-loader'), config.module.rule('less').oneOf('normal-modules').use('vue-style-loader'), config.module.rule('less').oneOf('normal').use('vue-style-loader'), config.module.rule('stylus').oneOf('vue-modules').use('vue-style-loader'), config.module.rule('stylus').oneOf('vue').use('vue-style-loader'), config.module.rule('stylus').oneOf('normal-modules').use('vue-style-loader'), config.module.rule('stylus').oneOf('normal').use('vue-style-loader'), ]; configs.forEach(c => c.tap(options => { options.shadowMode = true; return options; })); } module.exports = { // https://cli.vuejs.org/guide/webpack.html#chaining-advanced chainWebpack: config => { enableShadowCss(config); } } Creating <projectroot>/vue.config.js with the snippet above enables Shadow CSS in development mode in your project. See https://github.com/snirp/vue-web-component/pull/1.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With