Skip to content

Commit a2004fe

Browse files
committed
refactor: Determine CSS module by filename, not directory (#1714)
* refactor: Determine CSS module by filename, not directory * docs: Adding changeset * refactor: Project creation pull from templates 'main' branch * test: Updating tests * revert: Accidentally removed log message
1 parent 84c552e commit a2004fe

File tree

23 files changed

+115
-103
lines changed

23 files changed

+115
-103
lines changed

.changeset/cyan-tomatoes-count.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
'preact-cli': major
3+
---
4+
5+
Alters CSS Module detection to instead rely upon file names, rather than directory names.
6+
7+
Treating all CSS files found within `routes/` and `components/` as CSS Modules was not obvious, nor did it offer an easy way to opt out (or in) without editing the Webpack config itself.
8+
9+
This change makes is so that users can opt into CSS Modules from anywhere in their app by instead naming their CSS files according to the pattern `*.module.css`.
10+
11+
Anyone using CSS Modules within `routes/` or `components/` will need to alter their CSS files to be `x.module.css`. If you've disabled CSS Modules in your `preact.config.js`, you can remove that bit of configuration and use file names to instead determine behavior.

packages/cli/global.d.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,16 @@ declare module 'shelljs' {
1515
};
1616
export = shell;
1717
}
18+
19+
declare module '*.module.css' {
20+
const classes: { [key: string]: string };
21+
export default classes;
22+
}
23+
declare module '*.module.sass' {
24+
const classes: { [key: string]: string };
25+
export default classes;
26+
}
27+
declare module '*.module.scss' {
28+
const classes: { [key: string]: string };
29+
export default classes;
30+
}

packages/cli/src/commands/create.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,11 @@ exports.create = async function createCommand(repo, dest, argv) {
220220
if (!repo.includes('/')) {
221221
repo = `${ORG}/${repo}`;
222222
info(`Assuming you meant ${repo}...`);
223+
224+
// TODO: Remove this after updating all templates
225+
if (repo.endsWith('default') || repo.endsWith('typescript')) {
226+
repo += '#next';
227+
}
223228
}
224229

225230
if (!existsSync(resolve(cwd, dest, 'src'))) {

packages/cli/src/lib/webpack/run-webpack.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ function writeJsonStats(cwd, stats) {
143143
function allFields(stats, field, fields = [], name = null) {
144144
const info = stats.toJson({
145145
errors: true,
146-
warnings: false,
146+
warnings: true,
147147
errorDetails: false,
148148
});
149149
const addCompilerPrefix = msg =>

packages/cli/src/lib/webpack/webpack-base-config.js

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ function getSassConfiguration(...includePaths) {
6363
* @returns {import('webpack').Configuration}
6464
*/
6565
module.exports = function createBaseConfig(env) {
66-
const { cwd, isProd, isWatch, src, source } = env;
66+
const { cwd, isProd, src, source } = env;
6767
const IS_SOURCE_PREACT_X_OR_ABOVE = isInstalledVersionPreactXOrAbove(cwd);
6868
// Apply base-level `env` values
6969
env.dest = resolve(cwd, env.dest || 'build');
@@ -224,20 +224,15 @@ module.exports = function createBaseConfig(env) {
224224
],
225225
},
226226
{
227-
// User styles
228227
test: /\.(p?css|less|s[ac]ss|styl)$/,
229-
include: [source('components'), source('routes')],
228+
exclude: /\.module\.(p?css|less|s[ac]ss|styl)$/,
230229
use: [
231-
isWatch
232-
? require.resolve('style-loader')
233-
: MiniCssExtractPlugin.loader,
230+
isProd
231+
? MiniCssExtractPlugin.loader
232+
: require.resolve('style-loader'),
234233
{
235234
loader: require.resolve('css-loader'),
236235
options: {
237-
modules: {
238-
localIdentName: '[local]__[hash:base64:5]',
239-
},
240-
importLoaders: 1,
241236
sourceMap: true,
242237
},
243238
},
@@ -251,18 +246,25 @@ module.exports = function createBaseConfig(env) {
251246
},
252247
},
253248
],
249+
// Don't consider CSS imports dead code even if the
250+
// containing package claims to have no side effects.
251+
// Remove this when webpack adds a warning or an error for this.
252+
// See https://github.com/webpack/webpack/issues/6571
253+
sideEffects: true,
254254
},
255255
{
256-
// External / `node_module` styles
257-
test: /\.(p?css|less|s[ac]ss|styl)$/,
258-
exclude: [source('components'), source('routes')],
256+
test: /\.module\.(p?css|less|s[ac]ss|styl)$/,
259257
use: [
260-
isWatch
261-
? require.resolve('style-loader')
262-
: MiniCssExtractPlugin.loader,
258+
isProd
259+
? MiniCssExtractPlugin.loader
260+
: require.resolve('style-loader'),
263261
{
264262
loader: require.resolve('css-loader'),
265263
options: {
264+
modules: {
265+
localIdentName: '[local]__[hash:base64:5]',
266+
},
267+
importLoaders: 1,
266268
sourceMap: true,
267269
},
268270
},
@@ -276,11 +278,6 @@ module.exports = function createBaseConfig(env) {
276278
},
277279
},
278280
],
279-
// Don't consider CSS imports dead code even if the
280-
// containing package claims to have no side effects.
281-
// Remove this when webpack adds a warning or an error for this.
282-
// See https://github.com/webpack/webpack/issues/6571
283-
sideEffects: true,
284281
},
285282
{
286283
test: /\.(xml|html|txt|md)$/,
@@ -371,7 +368,7 @@ module.exports = function createBaseConfig(env) {
371368

372369
mode: isProd ? 'production' : 'development',
373370

374-
devtool: isWatch ? 'eval-cheap-module-source-map' : 'source-map',
371+
devtool: isProd ? 'source-map' : 'eval-cheap-module-source-map',
375372

376373
node: {
377374
__filename: false,

packages/cli/tests/build.test.js

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,9 @@ describe('preact build', () => {
177177
await rename(join(dir, 'index.js'), join(dir, 'renamed-src/index.js'));
178178
await rename(join(dir, 'style.css'), join(dir, 'renamed-src/style.css'));
179179

180-
await expect(buildFast(dir, { src: 'renamed-src' })).resolves.not.toThrow();
180+
await expect(
181+
buildFast(dir, { src: 'renamed-src' })
182+
).resolves.not.toThrow();
181183
});
182184

183185
it('--dest', async () => {
@@ -361,18 +363,13 @@ describe('preact build', () => {
361363
expect(builtStylesheet).toMatch('h2{color:green}');
362364
});
363365

364-
it('should use CSS Modules in `routes` and `components` directories', async () => {
365-
let dir = await subject('css-auto-modules');
366+
it('should use plain CSS & CSS Modules together, determining loading method by filename', async () => {
367+
let dir = await subject('css-modules');
366368
await buildFast(dir);
367369
const builtStylesheet = await getOutputFile(dir, /bundle\.\w{5}\.css$/);
368-
const builtSplitStylesheet = await getOutputFile(
369-
dir,
370-
/route-index\.chunk\.\w{5}\.css$/
371-
);
372370

373371
expect(builtStylesheet).toMatch('h1{color:red}');
374-
expect(builtStylesheet).toMatch(/\.text__\w{5}{color:tan}/);
375-
expect(builtSplitStylesheet).toMatch(/\.text__\w{5}{color:red}/);
372+
expect(builtStylesheet).toMatch(/\.text__\w{5}{color:blue}/);
376373
});
377374

378375
it('should inline critical CSS only', async () => {
@@ -394,12 +391,14 @@ describe('preact build', () => {
394391
expect(builtStylesheet).toMatch('h1{background:#673ab8}');
395392
});
396393

397-
it('should use SASS styles', async () => {
394+
it('should use SASS, SCSS, and CSS Modules for each', async () => {
398395
let dir = await subject('css-sass');
399396
await buildFast(dir);
397+
const builtStylesheet = await getOutputFile(dir, /bundle\.\w{5}\.css$/);
400398

401-
let body = await getBody(dir);
402-
looksLike(body, images.sass);
399+
expect(builtStylesheet).toMatch('h1{background:blue;color:red}');
400+
expect(builtStylesheet).toMatch(/\.text__\w{5}{color:blue}/);
401+
expect(builtStylesheet).toMatch(/\.text__\w{5}{background:red}/);
403402
});
404403
});
405404

packages/cli/tests/images/build.js

Lines changed: 20 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,18 @@ exports.default = {
77
'assets/icons/mstile-150x150.png': 9050,
88
'assets/favicon.ico': 15086,
99

10-
'ssr-build/ssr-bundle.77c49.css': 1281,
11-
'ssr-build/ssr-bundle.77c49.css.map': 2081,
10+
'ssr-build/ssr-bundle.dba70.css': 1281,
11+
'ssr-build/ssr-bundle.dba70.css.map': 2081,
1212
'ssr-build/ssr-bundle.js': 10453,
1313
'ssr-build/ssr-bundle.js.map': 46403,
1414
'ssr-build/asset-manifest.json': 82,
1515

16-
'bundle.7a791.js': 21563,
17-
'bundle.7a791.js.map': 86009,
18-
'bundle.7a791.legacy.js': 22586,
19-
'bundle.7a791.legacy.js.map': 107151,
20-
'bundle.9bde9.css': 945,
21-
'bundle.9bde9.css.map': 1758,
16+
'bundle.12615.js': 21560,
17+
'bundle.12615.js.map': 85822,
18+
'bundle.12615.legacy.js': 22549,
19+
'bundle.12615.legacy.js.map': 106841,
20+
'bundle.354c3.css': 945,
21+
'bundle.354c3.css.map': 1758,
2222

2323
'dom-polyfills.8a933.legacy.js': 5221,
2424
'dom-polyfills.8a933.legacy.js.map': 18676,
@@ -31,31 +31,21 @@ exports.default = {
3131
'push-manifest.json': 450,
3232
'asset-manifest.json': 943,
3333

34-
'route-home.chunk.040d2.js': 307,
35-
'route-home.chunk.040d2.js.map': 1684,
36-
'route-home.chunk.040d2.legacy.js': 364,
37-
'route-home.chunk.040d2.legacy.js.map': 1982,
38-
'route-home.chunk.f1c94.css': 112,
39-
'route-home.chunk.f1c94.css.map': 224,
34+
'route-home.chunk.f910e.js': 307,
35+
'route-home.chunk.f910e.js.map': 1516,
36+
'route-home.chunk.f910e.legacy.js': 347,
37+
'route-home.chunk.f910e.legacy.js.map': 1770,
38+
'route-home.chunk.6eaee.css': 112,
39+
'route-home.chunk.6eaee.css.map': 224,
4040

41-
'route-profile.chunk.8c3bd.js': 3121,
42-
'route-profile.chunk.8c3bd.js.map': 12280,
43-
'route-profile.chunk.8c3bd.legacy.js': 3266,
44-
'route-profile.chunk.8c3bd.legacy.js.map': 15684,
45-
'route-profile.chunk.e0d39.css': 118,
46-
'route-profile.chunk.e0d39.css.map': 231,
41+
'route-profile.chunk.ef912.js': 3106,
42+
'route-profile.chunk.ef912.js.map': 12220,
43+
'route-profile.chunk.ef912.legacy.js': 3243,
44+
'route-profile.chunk.ef912.legacy.js.map': 15558,
45+
'route-profile.chunk.0af3e.css': 118,
46+
'route-profile.chunk.0af3e.css.map': 231,
4747
};
4848

49-
exports.sass = `
50-
<body>
51-
<div class="background__sL1ip">
52-
<h1>Header on background</h1>
53-
<p>Paragraph on background</p>
54-
</div>
55-
{{ ... }}
56-
</body>
57-
`;
58-
5949
exports.prerender = {};
6050

6151
exports.prerender.heads = {};

packages/cli/tests/images/create.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@ exports.default = [
1313
'src/assets/icons/mstile-150x150.png',
1414
'src/components/app.js',
1515
'src/components/header/index.js',
16-
'src/components/header/style.css',
16+
'src/components/header/style.module.css',
1717
'src/index.js',
1818
'src/manifest.json',
1919
'src/routes/home/index.js',
20-
'src/routes/home/style.css',
20+
'src/routes/home/style.module.css',
2121
'src/routes/profile/index.js',
22-
'src/routes/profile/style.css',
22+
'src/routes/profile/style.module.css',
2323
'src/style/index.css',
2424
'src/sw.js',
2525
'src/template.html',

packages/cli/tests/subjects/css-auto-modules/components/index.js

Lines changed: 0 additions & 4 deletions
This file was deleted.

packages/cli/tests/subjects/css-auto-modules/components/style.css

Lines changed: 0 additions & 3 deletions
This file was deleted.

0 commit comments

Comments
 (0)