Subscribe on changes!

defineCustomElements styles are not applied

avatar
Jul 22nd 2021

Version

3.2.0-beta.4

Reproduction link

https://stackblitz.com/edit/vue-zhkjiz?file=src/main.js Hint: Stackblitz doesnt reload the DOM for this when you change some code you need to reload the tab in the browser otherwise element are already defined

Steps to reproduce

Create a new Vue3 Component with the vu3 cli my preset :

{
  "useTaobaoRegistry": false,
  "packageManager": "yarn",
  "presets": {
    "vue3-tsc": {
      "useConfigFiles": true,
      "plugins": {
        "@vue/cli-plugin-babel": {},
        "@vue/cli-plugin-typescript": {
          "classComponent": true,
          "useTsWithBabel": true
        },
        "@vue/cli-plugin-eslint": {
          "config": "prettier",
          "lintOn": [
            "commit"
          ]
        },
        "@vue/cli-plugin-unit-jest": {},
        "@vue/cli-plugin-e2e-cypress": {}
      },
      "vueVersion": "3",
      "cssPreprocessor": "dart-sass"
    }
  }
}

then modify main.ts to

import { defineCustomElement} from "vue";
import App from "./App.vue";
customElements.define("mbmxp-vue3-component", defineCustomElement(App));

which creates then a webcomponent with shadow-dom open all fine

but now the Problem is the styles from the scss file are not apply to the webcomponent because the styles are moved into the <head> and not into <webcomponent-tag> this is the reason why its not working

What is expected?

Styles are moved to the shadow dom and in the example the headline should be red

What is actually happening?

styles are added to the <head> and not applied to the shadow dom


Hi, I just wanted to thank you for the new defineCustomElement feature, unfortunately it doesn't quite work with the styles, some of which are not stored correctly in the DOM and therefore don't reach the shadow dom. Screenshot 2021-07-22 at 09 10 42

avatar
Jul 22nd 2021

I tried also some rules in the vue.config.js but it doesnt fixed the problem

    config.module
      .rule('scss')
      .oneOf('vue')
      .use('vue-style-loader')
      .loader('vue-style-loader')
      .tap((options) => {
        options.shadowMode = true;
        return options;
      });

    config.module
      .rule('vue')
      .use('vue-loader')
      .tap((options) => {
        options.shadowMode = true;
        return options;
      });
avatar
Jul 22nd 2021

This is expected because defineCustomElement only handles the runtime interop - the styles in SFCs need to be compiled differently when targeting WCs and that will require tooling updates as well.

avatar
Jul 22nd 2021

@yyx990803 You mentioned SFC - is there any other way to get defineCustomElement works with styles in Shadow DOM, even without SFC ?

avatar
Jul 22nd 2021

What tooling updates are needed? Can you please explain? or sending a link please

avatar
Jul 23rd 2021

https://twitter.com/youyuxi/status/1414594164168269828?s=21 i just have this information @yyx990803

avatar
Aug 10th 2021

It's nice to see that this made it into Vue 3.2, thanks!

@yyx990803 I would also like to have some information on what tooling updates we'll need, are these features tracked somewhere? Without full support for styles we can't use it as of now, and I'm guessing that's a common requirement for many projects.

I did find that with vue-loader 16.5 you can set the customElement option but it doesn't seem to support nested component styles. For example, if I have Vue component A that uses Vue component B, and both A and B have their individual <style> tags. When I use defineCustomElement for component A with the customElement: true setting in the vue-loader it'll only add a <style> tag in the shadow DOM with the styles from component A and nothing from B. Is this also expected?