front/vite-plugins/preact-cli-css-modules.js
Rama master · réplica de lectura del repositorio original.
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];
}
};
}