Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 'css/auto' as a css module type #16577

Merged
merged 6 commits into from Jun 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 7 additions & 0 deletions lib/ModuleTypeConstants.js
Expand Up @@ -60,6 +60,12 @@ const CSS_MODULE_TYPE_GLOBAL = "css/global";
*/
const CSS_MODULE_TYPE_MODULE = "css/module";

/**
* @type {Readonly<"css/auto">}
* This is the module type used for CSS files, the module will be parsed as CSS modules if it's filename contains `.module.` or `.modules.`.
*/
const CSS_MODULE_TYPE_AUTO = "css/auto";

/**
* @type {Readonly<"asset">}
* This is the module type used for automatically choosing between `asset/inline`, `asset/resource` based on asset size limit (8096).
Expand Down Expand Up @@ -152,6 +158,7 @@ exports.WEBASSEMBLY_MODULE_TYPE_SYNC = WEBASSEMBLY_MODULE_TYPE_SYNC;
exports.CSS_MODULE_TYPE = CSS_MODULE_TYPE;
exports.CSS_MODULE_TYPE_GLOBAL = CSS_MODULE_TYPE_GLOBAL;
exports.CSS_MODULE_TYPE_MODULE = CSS_MODULE_TYPE_MODULE;
exports.CSS_MODULE_TYPE_AUTO = CSS_MODULE_TYPE_AUTO;
exports.WEBPACK_MODULE_TYPE_RUNTIME = WEBPACK_MODULE_TYPE_RUNTIME;
exports.WEBPACK_MODULE_TYPE_FALLBACK = WEBPACK_MODULE_TYPE_FALLBACK;
exports.WEBPACK_MODULE_TYPE_REMOTE = WEBPACK_MODULE_TYPE_REMOTE;
Expand Down
7 changes: 5 additions & 2 deletions lib/css/CssModulesPlugin.js
Expand Up @@ -11,7 +11,8 @@ const HotUpdateChunk = require("../HotUpdateChunk");
const {
CSS_MODULE_TYPE,
CSS_MODULE_TYPE_GLOBAL,
CSS_MODULE_TYPE_MODULE
CSS_MODULE_TYPE_MODULE,
CSS_MODULE_TYPE_AUTO
} = require("../ModuleTypeConstants");
const RuntimeGlobals = require("../RuntimeGlobals");
const SelfModuleFactory = require("../SelfModuleFactory");
Expand Down Expand Up @@ -149,7 +150,8 @@ class CssModulesPlugin {
for (const type of [
CSS_MODULE_TYPE,
CSS_MODULE_TYPE_GLOBAL,
CSS_MODULE_TYPE_MODULE
CSS_MODULE_TYPE_MODULE,
CSS_MODULE_TYPE_AUTO
]) {
normalModuleFactory.hooks.createParser
.for(type)
Expand All @@ -158,6 +160,7 @@ class CssModulesPlugin {

switch (type) {
case CSS_MODULE_TYPE:
case CSS_MODULE_TYPE_AUTO:
return new CssParser();
case CSS_MODULE_TYPE_GLOBAL:
return new CssParser({
Expand Down
12 changes: 12 additions & 0 deletions lib/css/CssParser.js
Expand Up @@ -6,6 +6,7 @@
"use strict";

const ModuleDependencyWarning = require("../ModuleDependencyWarning");
const { CSS_MODULE_TYPE_AUTO } = require("../ModuleTypeConstants");
const Parser = require("../Parser");
const WebpackError = require("../WebpackError");
const ConstDependency = require("../dependencies/ConstDependency");
Expand All @@ -15,6 +16,7 @@ const CssLocalIdentifierDependency = require("../dependencies/CssLocalIdentifier
const CssSelfLocalIdentifierDependency = require("../dependencies/CssSelfLocalIdentifierDependency");
const CssUrlDependency = require("../dependencies/CssUrlDependency");
const StaticExportsDependency = require("../dependencies/StaticExportsDependency");
const { parseResource } = require("../util/identifier");
const walkCssTokens = require("./walkCssTokens");

/** @typedef {import("../Parser").ParserState} ParserState */
Expand All @@ -37,6 +39,7 @@ const IMAGE_SET_FUNCTION = /^(-\w+-)?image-set$/i;
const OPTIONALLY_VENDOR_PREFIXED_KEYFRAMES_AT_RULE = /^@(-\w+-)?keyframes$/;
const OPTIONALLY_VENDOR_PREFIXED_ANIMATION_PROPERTY =
/^(-\w+-)?animation(-name)?$/i;
const IS_MODULES = /\.module(s)?\.\w+$/i;

/**
* @param {string} str url string
Expand Down Expand Up @@ -169,6 +172,15 @@ class CssParser extends Parser {
}

const module = state.module;
if (
module.type === CSS_MODULE_TYPE_AUTO &&
IS_MODULES.test(
parseResource(module.matchResource || module.resource).path
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not parser.state.module.resource?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just added to the test about the matchResource part, only use module.resource won't correctly handle the matchResource feature

)
) {
this.defaultMode = "local";
}

const locConverter = new LocConverter(source);
/** @type {Set<string>}*/
const declaredCssVariables = new Set();
Expand Down
2 changes: 1 addition & 1 deletion schemas/plugins/css/CssGeneratorOptions.json
@@ -1,3 +1,3 @@
{
"$ref": "../../WebpackOptions.json#/definitions/CssParserOptions"
"$ref": "../../WebpackOptions.json#/definitions/CssGeneratorOptions"
}
2 changes: 1 addition & 1 deletion schemas/plugins/css/CssParserOptions.json
@@ -1,3 +1,3 @@
{
"$ref": "../../WebpackOptions.json#/definitions/CssGeneratorOptions"
"$ref": "../../WebpackOptions.json#/definitions/CssParserOptions"
}
2 changes: 2 additions & 0 deletions test/configCases/css/css-auto/colors.js
@@ -0,0 +1,2 @@
export const red = '#f00';
export const green = '#0f0';
3 changes: 3 additions & 0 deletions test/configCases/css/css-auto/global.less
@@ -0,0 +1,3 @@
body {
color: green;
}
17 changes: 17 additions & 0 deletions test/configCases/css/css-auto/index.js
@@ -0,0 +1,17 @@
import "./global.less";
import * as style1 from "./style1.module.less";
import * as style2 from "./style2.modules.less";
import * as style3 from "./style3.module.less!=!./loader.js!./style3.module.js";
import * as style4 from "./style4.module.less!=!./loader.js!./style4.js";
import * as style5 from "./style5.module.css!=!./loader.js!./style4.js";

it("should correctly compile css/auto", () => {
const style = getComputedStyle(document.body);
expect(style.getPropertyValue("color")).toBe(" green");
expect(style.getPropertyValue("background")).toBe(" #f00");
expect(style1.class).toBe("./style1.module.less-class");
expect(style2.class).toBe("./style2.modules.less-class");
expect(style3.class).toBe("./style3.module.less!=!./loader.js!./style3.module.js-class");
expect(style4.class).toBe("./style4.module.less!=!./loader.js!./style4.js-class");
expect(style5.class).toBe("./style5.module.css!=!./loader.js!./style4.js-class");
});
8 changes: 8 additions & 0 deletions test/configCases/css/css-auto/loader.js
@@ -0,0 +1,8 @@
/** @type {import("../../../../").PitchLoaderDefinitionFunction} */
exports.pitch = async function (remaining) {
const result = await this.importModule(
this.resourcePath + '.webpack[javascript/auto]' + '!=!' + remaining, {
publicPath: ''
});
return result.default || result;
};
3 changes: 3 additions & 0 deletions test/configCases/css/css-auto/style1.module.less
@@ -0,0 +1,3 @@
.class {
color: red;
}
3 changes: 3 additions & 0 deletions test/configCases/css/css-auto/style2.modules.less
@@ -0,0 +1,3 @@
.class {
color: blue;
}
6 changes: 6 additions & 0 deletions test/configCases/css/css-auto/style3.module.js
@@ -0,0 +1,6 @@
import { green, red } from './colors.js';

export default `
.class { color: ${green}; }
body { background: ${red}; }
`;
6 changes: 6 additions & 0 deletions test/configCases/css/css-auto/style4.js
@@ -0,0 +1,6 @@
import { green, red } from './colors.js';

export default `
.class { color: ${green}; }
body { background: ${red}; }
`;
3 changes: 3 additions & 0 deletions test/configCases/css/css-auto/style6.modules.css
@@ -0,0 +1,3 @@
.class {
color: blue;
}
8 changes: 8 additions & 0 deletions test/configCases/css/css-auto/test.config.js
@@ -0,0 +1,8 @@
module.exports = {
moduleScope(scope) {
const link = scope.window.document.createElement("link");
link.rel = "stylesheet";
link.href = "bundle0.css";
scope.window.document.head.appendChild(link);
}
};
17 changes: 17 additions & 0 deletions test/configCases/css/css-auto/webpack.config.js
@@ -0,0 +1,17 @@
/** @type {import("../../../../types").Configuration} */
module.exports = {
target: "web",
mode: "development",
experiments: {
css: true
},
module: {
rules: [
{
test: /\.less$/,
use: "less-loader",
type: "css/auto"
}
]
}
};