emosheeep / vite-plugin-lib-inject-css

Inject css at the top of chunk file in lib mode using import statement, support multiple entries.

Home Page:https://stackblitz.com/~/github.com/emosheeep/vite-plugin-lib-inject-css

Repository from Github https://github.comemosheeep/vite-plugin-lib-inject-cssRepository from Github https://github.comemosheeep/vite-plugin-lib-inject-css

The plugin doesn't work when "preserveModules" option is enabled

xbzhang2020 opened this issue · comments

When vite.config.ts is as follows:
截屏2024-12-26 15 10 13

There is no css injected in js bundles after build.
截屏2024-12-26 15 13 30

But if I set build.rollupOptions.output.preserveModules to false, it will work again.
截屏2024-12-26 15 15 59

I got it. Thanks.

Wait! I resolved it.

The build result with build.rollupOptions.output.preserveModules is as follows.

截屏2024-12-26 18 11 55

Here is my vite.config.ts . Maybe you can have a try in the examle.

import type { Plugin } from 'vite';
import { dirname, relative } from 'node:path';
import vue from '@vitejs/plugin-vue';
import { defineConfig } from 'vite';
// import { libInjectCss } from '../src/index';

function libInjectCss(): Plugin {
  return {
    name: 'vite:lib-inject-css',
    generateBundle(_, bundle) {
      for (const chunk of Object.values(bundle)) {
        if (chunk.type !== 'chunk' || !chunk.viteMetadata?.importedCss.size) {
          continue;
        }

        const { importedCss } = chunk.viteMetadata;
        const cssFiles = Array.from(importedCss).map((item) => {
          let cssFilePath = relative(dirname(chunk.fileName), item);
          if (!cssFilePath.startsWith('.')) {
            cssFilePath = `./${cssFilePath}`;
          }
          return `import '${cssFilePath}';`;
        });
        chunk.code = `${cssFiles.join('\n')}\n${chunk.code}`;
      }
    },
    enforce: 'post',
  };
}

export default defineConfig({
  plugins: [vue(), libInjectCss()],
  build: {
    lib: {
      formats: ['es'],
      entry: ['src/demo1/index.ts', 'src/demo2/index.ts'],
    },
    cssCodeSplit: true,
    rollupOptions: {
      external: ['vue'],
      output: {
        preserveModules: true,
      },
    },
  },
});

🤔Is it because the new version of vite fixes this problem? I will try it later

{
  entry: [
    // 'src/index.ts',
    // 'src/common.ts',
    'src/demo1/index.ts',
    'src/demo2/index.ts',
  ],
}

Seems you just removed two lines that I commented, I don't know how it works, maybe preserveModules option can be a warning which doesn’t block the injection logic. How it performs depends on vite, as the plugin relies on viteMetaData.

export default defineConfig({
  build: {
    lib: {
      entry: [
        // 'src/index.ts',
        // 'src/common.ts',
        'src/demo1/index.ts',
        'src/demo2/index.ts',
      ],
    },
    rollupOptions: {
      output: {
        preserveModules: true,
      },
    },
  },
});

But it also works when I add the four entries.

截屏2024-12-27 09 49 55
// vite.config.ts
export default defineConfig({
  plugins: [vue(), libInjectCss()],
  build: {
    lib: {
      formats: ['es'],
      entry: [
        'src/index.ts',
        'src/common.ts',
        'src/demo1/index.ts',
        'src/demo2/index.ts',
      ],
    },
    cssCodeSplit: true,
    rollupOptions: {
      external: ['vue'],
      output: {
        preserveModules: true,
      },
    },
  },
});

What is the version of the Vite you used ?

vite 5.4.10

Wow, I got it, there was a historical problem has been fixed accidentally by this commit 1841f44, maybe I should remove the restrictions and then support code injection when preserveModules option is enabled.

👍。哈哈哈,看起来是调用时机的问题,应该在 generateBundle 钩子中调用注入代码。