feat(css): implement @layer and @import rules#15892
feat(css): implement @layer and @import rules#15892noreiller wants to merge 1 commit intowebpack:mainfrom
Conversation
|
For maintainers only:
|
1aa90ae to
9bdbf80
Compare
|
|
||
| if ( | ||
| // Do nothing more for external modules | ||
| /^(\/\/|https?:\/\/|std:)/.test(dep.request) || |
There was a problem hiding this comment.
We can handle externals styles
There was a problem hiding this comment.
External styles are already considered as externals assets and so, no need to transform them. It's done there: https://github.com/webpack/webpack/blob/main/lib/WebpackOptionsApply.js#L119-L163.
There was a problem hiding this comment.
I mean https://webpack.js.org/configuration/experiments/#experimentsbuildhttp, we can bundle http/https CSS
There was a problem hiding this comment.
Oh yes, I forgot that. Thanks, I will check and update the PR.
There was a problem hiding this comment.
@alexander-akait The code is updated with buildHttp experiment and also with assets replacements.
| const replacedSource = `${source.source()}`; | ||
|
|
||
| // We use the replaced source and reset the replacements as a patch for to replace all the code | ||
| // @ts-expect-error | ||
| source._replacements = []; | ||
|
|
||
| source.replace( | ||
| 0, | ||
| source.size(), | ||
| ` | ||
| ${decorations | ||
| .map(([before, after], idx) => { | ||
| return Array(idx) | ||
| .fill() | ||
| .reduce(tpl => Template.indent(tpl), before); | ||
| }) | ||
| .join("\n")} | ||
| ${Array(decorations.length) | ||
| .fill() | ||
| .reduce(tpl => Template.indent(tpl), replacedSource)} | ||
| ${decorations | ||
| .map(([before, after], idx) => { | ||
| return Array(decorations.length - 1 - idx) | ||
| .fill() | ||
| .reduce(tpl => Template.indent(tpl), after); | ||
| }) | ||
| .join("\n")}` | ||
| ); | ||
| } |
There was a problem hiding this comment.
replacing the whole source shouldn't be done here. It breaks all SourceMapping.
Instead insert the decorations before and after the existing code with source.insert
There was a problem hiding this comment.
I did it aft first try but I add issues with source mapping. I think it's related to the issue you mentioned in another comment.
| get type() { | ||
| return "css @import decorator"; | ||
| } | ||
| } |
There was a problem hiding this comment.
It needs serialize and deserialize methods to take care of serialization of this.decorations
| ); | ||
| const decoratorDep = new CssImportDecoratorDependency(decorations); | ||
|
|
||
| dependencyModule.addDependency(decoratorDep); |
There was a problem hiding this comment.
You can't add dependencies during code generation. This need to be added during parsing.
There was a problem hiding this comment.
And you should not add dependencies to other modules. So this need to be handled differently.
There is also the problem that a single module might be imported multiple times with different layer, supports and/or media.
There was a problem hiding this comment.
So what need to be done here is that CssImportDependency need to have layer supports and media properties.
It then need to resolve to different CssModules depending on that. CssModule also need to have layer supports and media properties. These need to be inherited to imported module.
CssImportDependency need to override getResourceIdentifier() to add layer supports and media, because they influence resolving and dependencies are grouped based on that identifier.
CssImportDependency can't use the normalModuleFactory (in CssModulesPlugin). It need to have a custom factory that takes care of copying these properties from the dependency to the module.
I would also omit the decorator dependency at all and take care of adding the decorations in CssModulePlugin.renderChunk. Here you can also use the PrefixSource to apply indent in a SourceMap compatible way.
There was a problem hiding this comment.
Hello @sokra, I rewrote the implementation. I hope it fits with what you said.
| @@ -0,0 +1,112 @@ | |||
| /* | |||
| MIT License http://www.opensource.org/licenses/mit-license.php | |||
| Author Ivan Kopeykin @vankop | |||
| pos++; | ||
| let cc = input.charCodeAt(pos); | ||
| while (_isWhiteSpace(cc)) { | ||
| pos++; | ||
| if (pos === input.length) return pos; | ||
| cc = input.charCodeAt(pos); | ||
| } | ||
| const contentStart = pos; | ||
| let contentEnd; | ||
| for (;;) { | ||
| while (_isWhiteSpace(cc)) { | ||
| pos++; | ||
| if (pos === input.length) return pos; | ||
| cc = input.charCodeAt(pos); | ||
| } | ||
| if (cc === CC_RIGHT_PARENTHESIS) { | ||
| if (level > 0) { | ||
| level -= 1; | ||
| pos++; | ||
| } else { | ||
| contentEnd = pos; | ||
| let previousPos = pos - 1; | ||
| let previousCc = input.charCodeAt(previousPos); | ||
| while (_isWhiteSpace(previousCc)) { | ||
| contentEnd -= 1; | ||
| previousPos -= 1; | ||
| previousCc = input.charCodeAt(previousPos); | ||
| } | ||
| pos++; | ||
| if (callbacks.supports !== undefined) { | ||
| return callbacks.supports( | ||
| input, | ||
| start, | ||
| pos, | ||
| contentStart, | ||
| contentEnd | ||
| ); | ||
| } | ||
| return pos; | ||
| } | ||
| } else if (cc === CC_LEFT_PARENTHESIS) { | ||
| level += 1; | ||
| pos++; | ||
| } else { | ||
| pos++; | ||
| } | ||
| if (pos === input.length) return pos; | ||
| cc = input.charCodeAt(pos); | ||
| } |
There was a problem hiding this comment.
supports and layer share a lot of code. Could we put that into a shared function?
There was a problem hiding this comment.
Yes, I will refactor that.
d0f5e5f to
6ae916d
Compare
|
Hello @sokra @alexander-akait, will you continue to implement the webpack experimental CSS feature or accept new PRs? |
|
@noreiller Let's do rebase, thank you |
6ae916d to
fa8bd27
Compare
|
@noreiller Thanks for your update. I labeled the Pull Request so reviewers will review it again. @alexander-akait Please review the new changes. |
|
Thank you I will review soon |
fa8bd27 to
8af5b74
Compare
|
After merge - #16978 (because it fixed some bugs in tokenizer), I will focus on it, I have idea how we can simplify it |
It's gonna be another complicated rebase... 😮 |
|
@noreiller don't worry, you have
So I will do rebase |
Ok, thanks 🙏 |
The changes add the support of
@layercss at-rule and implements the rules when using@importCSS at-rule.It is part of CSS experiment.
@layerThe following code would be handled by webpack, especially in CSS modules.
@importrulesThis code:
would be transformed to:
Tests
Some tests have been added for CSS modules.
The ones dedicated to
@importrules have also been added but, unfortunately, JSDOM (which relies on CSSOM) does not handle well at-rules so they are disabled until the support is updated.