Skip to content

Commit

Permalink
refactor(css): rewrite @layer/@supports implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
noreiller committed Aug 5, 2022
1 parent 17c1cc7 commit 6ae916d
Show file tree
Hide file tree
Showing 6 changed files with 168 additions and 149 deletions.
8 changes: 2 additions & 6 deletions examples/css/README.md
Expand Up @@ -443,13 +443,13 @@ document.getElementsByTagName("main")[0].className = _style_module_css__WEBPACK_
# dist/output.css

```javascript

.img {
width: 150px;
height: 150px;
background: url(89a353e9c515885abd8e.png);
}


@media screen {
@font-face {
font-family: 'Open Sans';
Expand All @@ -459,7 +459,6 @@ document.getElementsByTagName("main")[0].className = _style_module_css__WEBPACK_
src: url(8b49cef9eef7a6b1c4cb.ttf) format('truetype');
}
}

@supports(touch-action: none) {
/*!
* jQuery UI Draggable 1.13.1
Expand All @@ -474,7 +473,6 @@ document.getElementsByTagName("main")[0].className = _style_module_css__WEBPACK_
touch-action: none;
}
}

@layer base {
@supports(font-weight: bold) {
@media screen and (min-width: 1024px) {
Expand Down Expand Up @@ -527,13 +525,13 @@ head{--webpack-app-0:_2,_4,_6,_7,_1,_8,large%main/_9;}
## production

```javascript

.img {
width: 150px;
height: 150px;
background: url(89a353e9c515885abd8e.png);
}


@media screen {
@font-face {
font-family: 'Open Sans';
Expand All @@ -543,7 +541,6 @@ head{--webpack-app-0:_2,_4,_6,_7,_1,_8,large%main/_9;}
src: url(8b49cef9eef7a6b1c4cb.ttf) format('truetype');
}
}

@supports(touch-action: none) {
/*!
* jQuery UI Draggable 1.13.1
Expand All @@ -558,7 +555,6 @@ head{--webpack-app-0:_2,_4,_6,_7,_1,_8,large%main/_9;}
touch-action: none;
}
}

@layer base {
@supports(font-weight: bold) {
@media screen and (min-width: 1024px) {
Expand Down
81 changes: 81 additions & 0 deletions lib/css/CssImportModule.js
@@ -0,0 +1,81 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Aurélien Manca @noreiller
*/

"use strict";

const NormalModule = require("../NormalModule");
const makeSerializable = require("../util/makeSerializable");

/** @typedef {import("../../declarations/WebpackOptions").WebpackOptionsNormalized} WebpackOptions */
/** @typedef {import("../Compilation")} Compilation */
/** @typedef {import("../Module").LibIdentOptions} LibIdentOptions */
/** @typedef {import("../NormalModule").NormalModuleCreateData} NormalModuleCreateData */
/** @typedef {import("../RequestShortener")} RequestShortener */
/** @typedef {import("../ResolverFactory").ResolverWithOptions} ResolverWithOptions */
/** @typedef {import("../WebpackError")} WebpackError */
/** @typedef {import("../util/fs").InputFileSystem} InputFileSystem */

/**
* @typedef {Object} Decoration
* @property {string=} layer
* @property {string=} media
* @property {string=} supports
*/

const SOURCE_TYPES = new Set(["css"]);

class CssImportModule extends NormalModule {
/**
* @param {NormalModuleCreateData} createData createData object
* @param {Decoration[]} decorations Decoration list
*/
constructor(createData, decorations) {
super(createData);

/** @type {[string, string][]} */
this.decorations = decorations.reduce((acc, { layer, supports, media }) => {
if (layer) {
acc.push([`@layer ${layer} {`, `}`]);
}

if (supports) {
acc.push([`@supports(${supports}) {`, `}`]);
}

if (media) {
acc.push([`@media ${media} {`, `}`]);
}

return acc;
}, []);
}

/**
* @returns {Set<string>} types available (do not mutate)
*/
getSourceTypes() {
return SOURCE_TYPES;
}

serialize(context) {
const { write } = context;

write(this.decorations);

super.serialize(context);
}

static deserialize(context) {
const { read } = context;

this.decorations = read();

return super.deserialize(context);
}
}

makeSerializable(CssImportModule, "webpack/lib/css/CssImportModule");

module.exports = CssImportModule;
66 changes: 55 additions & 11 deletions lib/css/CssModulesPlugin.js
Expand Up @@ -5,12 +5,12 @@

"use strict";

const { ConcatSource } = require("webpack-sources");
const { ConcatSource, PrefixSource } = require("webpack-sources");
const HotUpdateChunk = require("../HotUpdateChunk");
const RuntimeGlobals = require("../RuntimeGlobals");
const SelfModuleFactory = require("../SelfModuleFactory");
const Template = require("../Template");
const CssExportDependency = require("../dependencies/CssExportDependency");
const CssImportDecoratorDependency = require("../dependencies/CssImportDecoratorDependency");
const CssImportDependency = require("../dependencies/CssImportDependency");
const CssLocalIdentifierDependency = require("../dependencies/CssLocalIdentifierDependency");
const CssSelfLocalIdentifierDependency = require("../dependencies/CssSelfLocalIdentifierDependency");
Expand All @@ -23,13 +23,16 @@ const memoize = require("../util/memoize");
const nonNumericOnlyHash = require("../util/nonNumericOnlyHash");
const CssExportsGenerator = require("./CssExportsGenerator");
const CssGenerator = require("./CssGenerator");
const CssImportModule = require("./CssImportModule");
const CssParser = require("./CssParser");

/** @typedef {import("webpack-sources").Source} Source */
/** @typedef {import("../../declarations/WebpackOptions").CssExperimentOptions} CssExperimentOptions */
/** @typedef {import("../Chunk")} Chunk */
/** @typedef {import("../Compiler")} Compiler */
/** @typedef {import("../Module")} Module */
/** @typedef {import("../NormalModule").NormalModuleCreateData} NormalModuleCreateData */
/** @typedef {import("./CssImportModule").Decoration} CssImportModuleDecoration */

const getCssLoadingRuntimeModule = memoize(() =>
require("./CssLoadingRuntimeModule")
Expand Down Expand Up @@ -117,19 +120,12 @@ class CssModulesPlugin {
compilation.dependencyFactories.set(
CssImportDependency,
normalModuleFactory
// new CssImportModuleFactory()
);
compilation.dependencyTemplates.set(
CssImportDependency,
new CssImportDependency.Template()
);
compilation.dependencyFactories.set(
CssImportDecoratorDependency,
normalModuleFactory
);
compilation.dependencyTemplates.set(
CssImportDecoratorDependency,
new CssImportDecoratorDependency.Template()
);
compilation.dependencyTemplates.set(
StaticExportsDependency,
new StaticExportsDependency.Template()
Expand Down Expand Up @@ -181,6 +177,25 @@ class CssModulesPlugin {
? new CssExportsGenerator()
: new CssGenerator();
});
normalModuleFactory.hooks.createModule.tap(
"CssModulesPlugin",
(createData, resolveData) => {
const decorations = /** @type {CssImportModuleDecoration[]} */ ([]);
resolveData.dependencies.forEach(dependency => {
if (dependency.category === "css-import") {
const { layer, supports, media } =
/** @type {CssImportDependency} */ (dependency);
decorations.push({ layer, supports, media });
}
});
if (decorations.length) {
return new CssImportModule(
/** @type {NormalModuleCreateData} */ (createData),
decorations
);
}
}
);
const orderedCssModulesPerChunk = new WeakMap();
compilation.hooks.afterCodeGeneration.tap("CssModulesPlugin", () => {
const { chunkGraph } = compilation;
Expand Down Expand Up @@ -414,7 +429,36 @@ class CssModulesPlugin {
codeGenResult.sources.get("css") ||
codeGenResult.sources.get("css-import");
if (s) {
source.add(s);
if (module.decorations) {
source.add(
module.decorations
.map(([before], idx) => {
return Array(idx)
.fill()
.reduce(tpl => Template.indent(tpl), before);
})
.join("\n") + "\n"
);
source.add(
new PrefixSource(
Array(module.decorations.length)
.fill()
.reduce(tpl => ` ${tpl}`, ""),
s
)
);
source.add(
module.decorations
.map(([, after], idx) => {
return Array(module.decorations.length - 1 - idx)
.fill()
.reduce(tpl => Template.indent(tpl), after);
})
.join("\n")
);
} else {
source.add(s);
}
source.add("\n");
}
const exports =
Expand Down
112 changes: 0 additions & 112 deletions lib/dependencies/CssImportDecoratorDependency.js

This file was deleted.

0 comments on commit 6ae916d

Please sign in to comment.