Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Styling not applied to vue web component during development

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.

like image 984
Roy Prins Avatar asked Nov 22 '18 13:11

Roy Prins


1 Answers

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.

like image 104
tony19 Avatar answered Sep 21 '22 00:09

tony19