Ctrl K
ComunidadGuías…

front/vite-plugins/preact-cli-css-modules.js

Rama master · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import { readFileSync, existsSync } from 'fs';
import { resolve as resolvePath } from 'path';

/**
 * preact-cli treats `import style from './file.css'` as CSS modules, while
 * `import './file.css'` stays global. Vite only enables modules for
 * `*.module.css` by default.
 *
 * This plugin rewrites default CSS imports to virtual `.module.css` module IDs
 * so `vite-css-modules` can provide webpack-compatible default exports.
 */
export function preactCliCssModules() {
  const resolvedModules = new Map();

  return {
    name: 'preact-cli-css-modules',
    enforce: 'pre',
    transform(code, id) {
      if (!/\.(jsx?|tsx?)(\?|$)/.test(id) || id.includes('node_modules')) {
        return null;
      }

      const updatedCode = code.replace(
        /import\s+(\w+)\s+from\s+(['"])([^'"]+\.css)\2/g,
        (match, binding, quote, cssPath) => {
          if (cssPath.includes('.module.css')) {
            return match;
          }
          return `import ${binding} from ${quote}${cssPath.replace(/\.css$/, '.module.css')}${quote}`;
        }
      );

      if (updatedCode === code) {
        return null;
      }

      return { code: updatedCode, map: null };
    },
    resolveId(source, importer) {
      if (!importer || !source.endsWith('.module.css') || source.includes('node_modules')) {
        return null;
      }

      const cssPath = source.replace(/\.module\.css$/, '.css');
      const absoluteCssPath = resolvePath(resolvePath(importer, '..'), cssPath);

      if (!existsSync(absoluteCssPath)) {
        return null;
      }

      const virtualModuleId = `${absoluteCssPath}.module.css`;
      resolvedModules.set(virtualModuleId, absoluteCssPath);
      return virtualModuleId;
    },
    load(id) {
      const absoluteCssPath = resolvedModules.get(id);
      if (!absoluteCssPath) {
        return null;
      }

      // The module graph knows this module as the virtual id, so the real file
      // has to be watched explicitly.
      this.addWatchFile(absoluteCssPath);

      return readFileSync(absoluteCssPath, 'utf8');
    },

    /**
     * Vite maps a changed file to its modules by path. Our modules live under a
     * virtual id (`foo.css.module.css`) that no file on disk matches, so editing
     * `foo.css` in dev updated nothing at all (no HMR, not even a reload).
     * Hand back the virtual module so Vite invalidates it and pushes the update.
     */
    hotUpdate({ type, file, modules }) {
      if (type !== 'update') {
        return null;
      }

      const virtualModuleId = `${file}.module.css`;
      if (!resolvedModules.has(virtualModuleId)) {
        return null;
      }

      const virtualModule = this.environment.moduleGraph.getModuleById(virtualModuleId);
      if (!virtualModule || modules.includes(virtualModule)) {
        return null;
      }

      return [...modules, virtualModule];
    }
  };
}