crxjs / chrome-extension-tools

Bundling Chrome Extensions can be pretty complex. It doesn't have to be.
https://crxjs.dev/vite-plugin
2.71k stars 181 forks source link

HMR doesn't work for Tailwind classes in content scripts #671

Open AndreiHudovich opened 1 year ago

AndreiHudovich commented 1 year ago

Build tool

Vite

Where do you see the problem?

Describe the bug

It looks like it's the same (or similar) issue that we had in v1 - #288

Everything works perfectly for a popup and options page. But when you add Tailwind classes in the content script source, the injected CSS file in the head isn't updated. Classes are added to the class attributes in HTML code by HMR, but CSS stays intact.

Only restarting Vite helps to capture new classes.

Reproduction

I've added popup, options and content script to test.

https://github.com/andrei-hudovich/crxjs-issue-tailwindcss

Logs

--

System Info

System:
    OS: macOS 13.2.1
    CPU: (8) x64 Intel(R) Core(TM) i5-1038NG7 CPU @ 2.00GHz
    Memory: 112.87 MB / 16.00 GB
    Shell: 5.8.1 - /bin/zsh
  Binaries:
    Node: 18.15.0 - ~/.nvm/versions/node/v18.15.0/bin/node
    npm: 9.6.1 - ~/.nvm/versions/node/v18.15.0/bin/npm
  Browsers:
    Chrome: 111.0.5563.64
  npmPackages:
    @crxjs/vite-plugin: ^2.0.0-beta.15 => 2.0.0-beta.15
    vite: ^4.1.4 => 4.2.0

Severity

annoyance

thmsmlr commented 1 year ago

I found a little work around: https://github.com/crxjs/chrome-extension-tools/issues/609#issuecomment-1563634844

andresgutgon commented 1 year ago

Same issue here. Only reloading vite server I see changes in the CSS.

I also notice that generated file by vite is not updated in dist/css/app.css.js so maybe I have another problem. Just adding here just in case other people is using also Vite.

Also to add more entropy I'm doing the chrome extension in a monorepo with pnpm and turbo-repo where some styles are in a package which I call ui 😂

ghost commented 1 year ago

Same here.

molvqingtai commented 1 year ago

The same problem, use import "./tailwind.css?inline" syntax HMR does not work

AndreiHudovich commented 1 year ago

Still no news on this issue?

yunsii commented 11 months ago

I use workaround for now by:

// tailwind.config.js
{
  safelist: process.env.NODE_ENV === 'development' ? [{ pattern: /./ }] : [],
}
ghost commented 10 months ago

I use workaround for now by:

// tailwind.config.js
{
  safelist: process.env.NODE_ENV === 'development' ? [{ pattern: /./ }] : [],
}

Takes a lot of time to reload, isn't it?

yunsii commented 10 months ago

@carlos-mta It's inevitable, but I think it is better than restart dev server frequently.

AndreiHudovich commented 8 months ago

Some follow-up on this issue.

I had to downgrade the Vite version to the one that CRXJS uses, and it works fine now. It's quite misleading that there is no Vite version specified in peer dependencies for v2.

These versions definitely have HMR for Tailwind:

Bear in mind, though, that you'll have to downgrade your other Vite plugins too, as they probably won't work with Vite 3!

megagames-me commented 8 months ago

Just like to bump this! Downgrading to vite 3.1.7 really isn't an option for me because it's so outdated. If I have time, I'll try to look in and see if I can fix this issue.

kmcaloon commented 8 months ago

Having this issue too with React/Vite/Tailwind within a Chrome Extension content script. I seemed to have found a better workaround than above.

Basically at the root of my app I have one central stylesheet that I am importing that includes the tailwind styles in src/styles/global.css. I always have my global.css open in vscode and whenever I add utility classes in my code and the changes aren't reflected in the app I just resave the global.css and HMR kicks in with the new styles applied.

kaminskypavel commented 6 months ago

happens on

"@crxjs/vite-plugin": "2.0.0-beta.23",
"vite": "^5.1.1"

it's a real shame to go back to rollback 2 version of vite to Vite@3

aything we can do to tackle this?

kaminskypavel commented 6 months ago

I use workaround for now by:

// tailwind.config.js
{
  safelist: process.env.NODE_ENV === 'development' ? [{ pattern: /./ }] : [],
}

I really would NOT recommend doing that. bare in mind this will resolve in a 16mb css file. your vite loading time will be in minutes no milliseconds

Use a more sensible subset of classes instead. for me this was enough, but your milage may vary.

  // !! this is a workaround for a big in crxjs
  // !! https://github.com/crxjs/chrome-extension-tools/issues/671
  // eslint-disable-next-line no-undef
  safelist: process.env.NODE_ENV === 'development' ?
    [
      {
        // colors 
        pattern: /\b((bg|text)-[\w-]+)/,
      },
      {
        // padding and margin
        pattern: /\b((p|px|py|my|mx|spacing-x|spacing-y)-\d+)/,
      },
      {
        // width, high, and size
        pattern: /\b((w|h|s)-\d+)/,
      },
    ] : [],

this will resolve in a 1mb index.css.js file (instead of 16)

ozeron commented 5 months ago

Any updates on this?

pnd280 commented 3 months ago

The workaround @kmcaloon mentioned is the most conventional one here, but it's still pretty annoying to have to manually resave the global CSS file. We could have a plugin to automate this.

// vite-plugin-touch-global-css.ts

import fs from 'fs';
import { Plugin } from 'vite';

function touchFile(filePath: string): void {
  const time = new Date();
  fs.utimesSync(filePath, time, time);
}

type TouchGlobalCSSPluginOptions = {
  cssFilePath: string;
  watchFiles: string[];
};

export default function touchGlobalCSSPlugin({
  cssFilePath,
  watchFiles,
}: TouchGlobalCSSPluginOptions): Plugin {
  return {
    name: 'touch-global-css',
    configureServer(server) {
      server.watcher.on('change', (file) => {
        if (watchFiles.some((watchFile) => file.includes(watchFile))) {
          touchFile(cssFilePath);
        }
      });
    },
  };
}
// vite.config.ts

import path from 'path';
import { defineConfig } from 'vite';
import viteTouchGlobalCss from 'vite-plugin-touch-global-css';

export default defineConfig(() => {
  return {
    plugins: [
      viteTouchGlobalCss({
        cssFilePath: path.resolve(__dirname, 'src/assets/globals.css'),
        watchFiles: ['./src/content-script'],
      }),
    ],
  };
});
Jerrylum commented 2 months ago

The above solution worked for me. Thank you for your help @pnd280

Additionally, we can add support to Windows file system:

export default function touchGlobalCSSPlugin({
  cssFilePath,
  watchFiles,
}: TouchGlobalCSSPluginOptions): Plugin {
  return {
    name: 'touch-global-css',
    configureServer(server) {
      server.watcher.on('change', (file) => {
        file = file.replace(/\\/g, '/') // <-- Add this to add support to Windows
        if (watchFiles.some((watchFile) => file.includes(watchFile))) {
          touchFile(cssFilePath)
        }
      })
    },
  }
}
geanrt commented 3 weeks ago

GUYS I FOUND A SOLUTION!!!! 🎉🎉

Hey everyone,

I finally found a solution right where it all began, using minified libraries! 😂

All you need to do is download the minified Tailwind file from cdn.tailwindcss.com and include it in your project's main file. And that's it! GG!

working well: image image (1) image (2) image (3)