vite-plugin-federation icon indicating copy to clipboard operation
vite-plugin-federation copied to clipboard

Cannot import scoped css from remote component into host app

Open estellegr opened this issue 2 years ago • 5 comments

When I import a remote component into my host app, css inside a styled tag with the scoped attribute does not get loaded. However, when I use the module attribute (or no attribute at all) it works fine.

Versions

  • vite-plugin-federation: 1.2.0
  • vite: 4.0.1

Reproduction

remote/src/Header.vue

<script setup lang="ts"></script>

<template>
  <div class="header">
    <div class="header__logo">
      <img src="@/assets/vue.svg" alt="logo" />
    </div>
    <div class="header__title">
      <h1>Remote Header</h1>
    </div>
  </div>
</template>

<style scoped>
.header {
  display: flex;
  align-items: center;
  column-gap: 1.6rem;
  padding: 1.6rem;
  border-bottom: 1px solid #e5e5e5;
}
</style>

host/src/components/Home.vue

<script lang="ts">
import Header from 'remote-app/Header';
</script>

<template>
  <Header />
  <h3>Home Content (Local)</h3>
</template>

remote/vite.config.ts

/// <reference types="vitest" />
import { defineConfig } from 'vite';
import { resolve } from 'path'

import viteTsConfigPaths from 'vite-tsconfig-paths';
import vue from '@vitejs/plugin-vue';
import federation from "@originjs/vite-plugin-federation";

const pathSrc = resolve(__dirname, "src");

export default defineConfig({
  cacheDir: '../../node_modules/.vite/remote',

  server: {
    port: 5001,
    host: 'localhost',
  },

  preview: {
    port: 5001,
    host: 'localhost',
  },

  base: process.env.NODE_ENV === "production" ? "http://localhost:5001/" : "/",

  resolve: {
    alias: {
      '@': `${pathSrc}`,
    },
  },

  plugins: [
    vue(),
    viteTsConfigPaths({
      root: '../../',
    }),
    federation({
      name: 'remote-app',
      filename: 'remoteEntry.js',
      exposes: {
        './Header': `${pathSrc}/Header.vue`,
      }
  }),
  ],

  build: {
    target: "esnext",
    assetsInlineLimit: 40960,
    cssCodeSplit: false,
    sourcemap:true,
    rollupOptions: {
      output: {
        minifyInternalExports: false
      }
    }
  },
});

host/vite.config.ts

/// <reference types="vitest" />
import { defineConfig, searchForWorkspaceRoot } from 'vite';
import vue from '@vitejs/plugin-vue'
import federation from "@originjs/vite-plugin-federation";

export default defineConfig({
  cacheDir: '../../node_modules/.vite/host',

  server: {
    port: 5000,
    host: 'localhost',
    fs: {
      allow: [
        searchForWorkspaceRoot(process.cwd()),
        "../..",
      ]
    }
  },

  preview: {
    port: 5000,
    host: 'localhost',
  },

  plugins: [
    vue(),
    federation({
      name: 'host',
      filename: 'remoteEntry.js',
      remotes: {
        "remote-app": 'http://localhost:5001/assets/remoteEntry.js',
      },
      shared: ['vue']
    })
  ],

  build: {
    target: 'esnext',
    cssCodeSplit: true,
    minify: false,
    rollupOptions: {
      output: {
        format: 'system',
        entryFileNames: 'assets/[name].js',
        minifyInternalExports: false
      }
    }
  },
});

What is Expected?

When using <style module> or <style> I get the correct CSS : Capture d’écran 2023-02-21 à 11 45 13

What is actually happening?

With <style scoped> I don't have any styling : Capture d’écran 2023-02-21 à 11 48 52

Thanks for your help 🙏

estellegr avatar Feb 21 '23 10:02 estellegr

After searching, I found that in my In my dist/Header.css I've got this :

.header[data-v-e0f4b3c9]{display:flex;align-items:center;column-gap:1.6rem;padding:1.6rem;border-bottom:1px solid #e5e5e5}

Turns out the attribute generated by the scoped attribute is given to the component children as the following (look for the attribute data-v-e0f4b3c9) Capture d’écran 2023-02-22 à 11 43 32

If I set the attribute data-v-e0f4b3c9 to the header div, it works : Capture d’écran 2023-02-22 à 11 43 46

Anybody has a workaround to set the attribute data-v-e0f4b3c9 to the correct node ?

estellegr avatar Feb 22 '23 10:02 estellegr

an awful workaround is to use a <div> as the parent in the meanwhile 😅

david2am avatar Mar 22 '23 22:03 david2am

i met the same problem. I have to use css syntex without scoped in component project, but it may invoke other repeat css name problem

zacard-orc avatar Apr 09 '23 11:04 zacard-orc

没错,老夫也遇到了。而且正如3楼老外哥说的,还需要如vue2保持根元素唯一。

Becessary avatar Apr 11 '23 02:04 Becessary

After searching, I found that in my In my dist/Header.css I've got this :

.header[data-v-e0f4b3c9]{display:flex;align-items:center;column-gap:1.6rem;padding:1.6rem;border-bottom:1px solid #e5e5e5}

Turns out the attribute generated by the scoped attribute is given to the component children as the following (look for the attribute data-v-e0f4b3c9) Capture d’écran 2023-02-22 à 11 43 32

If I set the attribute data-v-e0f4b3c9 to the header div, it works : Capture d’écran 2023-02-22 à 11 43 46

Anybody has a workaround to set the attribute data-v-e0f4b3c9 to the correct node ?

I have the same problem, how did you solve it? please help!

weilephp avatar Jul 22 '24 07:07 weilephp