laravel-mix / laravel-mix

The power of webpack, distilled for the rest of us.
MIT License
5.27k stars 808 forks source link

[v6.0.0-beta.14] VueJS - vue-loader `shadowMode` #2643

Closed SergkeiM closed 9 months ago

SergkeiM commented 3 years ago

Description:

Hi, I'm trying to implement webcomponents using Vue.

And using SFC, to inject CSS/SCSS into shadow DOM, Based on this comment, Enabling shadowMode: true in vue-loader should append the styles into this.$root.shadowRoot insted of <head>.

Steps To Reproduce:

My Mix config

const mix = require('laravel-mix');

mix.options({
    vue: {
        shadowMode: true //set shadowMode: true for vue-loader
    }
});

mix.js('src/index.js', 'dist/webcomponents.js').setPublicPath('dist');

Index.js

import Vue from "vue";
import wrap from "@vue/web-component-wrapper";

import Test from "./Test";

const wrappedElement = wrap(Vue, Test);

window.customElements.define("test-component", wrappedElement);

Test.vue

<template>
    <div>
        <h1>{{ title }}</h1>
    </div>
</template>
<style lang="scss">
    h1{
        color: var(--h1-color, red);
    }
</style>
<script>
    export default {
        props: {
            title: {
                type: String,
                default: "Test"
            },
        }
    };
</script>

But all styles are still shown in <head>, tried using laravel-mix v6, but still the same, any suggestion?

thecrypticace commented 3 years ago

We should add a way to pass arbitrary options to vue-loader. I'll open a PR for that this evening

thecrypticace commented 3 years ago

Heh I already did this for Mix v6.

mix.vue({
  options: {
    shadowMode: true,
  },
})
SergkeiM commented 3 years ago

Hi @thecrypticace, thank you for reply.

I tried Mix v6, doesn't work

SergkeiM commented 3 years ago

Hi @thecrypticace

Laravel Mix Version: v6.0.0-beta.14 vue-loader Version: 15.9.5

Mix Config

const mix = require('laravel-mix');

mix.js('src/index.js', 'dist/webcomponents.js').vue({
    version: 2,
    options: {
        shadowMode: true
    }
}).setPublicPath('dist');

Same compontent as above, output:

shadow-css

Do I miss something?

thecrypticace commented 3 years ago

That seems right to me. I'll take another look.

SergkeiM commented 3 years ago

Hi @thecrypticace

I think is something to do with vue-style-loader based on: this and this this

I tried to override mix config for .scss with:

module: {
    rules: [
        {
            test: /\.s(c|a)ss$/,
            use: [
                {
                    loader: 'vue-style-loader',
                    options: {
                        shadowMode: true
                    }
                },
                'css-loader',
                {
                    loader: 'sass-loader',
                    options: {
                        sassOptions: {
                            precision: 8,
                            outputStyle: 'expanded',
                            indentedSyntax: true
                        }
                    }
                }
            ]
        }
    ]
}

But no success.

I could see that shadow mode is enable for both vue-laoder and vue-style-loader but is still appends to head... :(

Update: Tried to do it directly from vue-cli works fine.

SergkeiM commented 3 years ago

Hi @thecrypticace

Closing this, downgrading css-loader to v3 fixes this issue see: PR

thecrypticace commented 3 years ago

I was playing around with this a while ago myself and couldn't get shadowMode to work properly under any circumstance. Additionally we've had some problems with vue-style-loader necessitating reverting that change.

SergkeiM commented 3 years ago

Hi @thecrypticace I used this with Vue Webcomponents and works fine: https://github.com/vuejs/vue-web-component-wrapper

SergkeiM commented 3 years ago

Hi @thecrypticace

With latest release I see you have added, option to choose between vue-style-loader and style-loader v6.0.25

But, by default shadow mode in vue-style-loader is disabled, can we add a posibility to pass options to vue-style-loader

.vue({
    version: 2,
    runtimeOnly: true,
    useVueStyleLoader: true,
    vueStyleLoaderOptions: {
        shadowMode: true
        //or other vue-style-loader options
        // Like manualInject or ssrId  and etc
    }
})