Skip to content

Native CSS support #14893

Open
Open
@sokra

Description

@sokra

Current State: opt-in via experiments.css: true

Explainer (not everything is implemented yet):

  • experiments.css: true enables the native css support in webpack
  • This will be enabled by default in webpack 6
  • There will be multiple modes depending on how you reference CSS
    • A: import "./style.css": Attaches the stylesheet to the document as side effect of importing. @import and url() are resolved.
    • B: import stylesheet from "./style.css" asset { type: "css" }: Exports the unattached stylesheet as default export. You can adopt it according to the spec. @import is not allowed (yet), but url() will be resolved.
    • C: import { main } from "./style.module.css": Like A, but renames all css classes, keyframes and css variables and exports the new names. Global selectors are only allowed with explicit :global selector prefix. @import and url() are resolved.
    • D: new URL("./style.css", import.meta.url): Gives an URL to a stylesheet including all styles. @import and url() are resolved.
    • E: import { main } from "./style.module.css": Like C, but for the node.js target. It generates a JSON module with the exports from the CSS.
  • A and C will bundle all CSS of a chunk into a single CSS file (per chunk)
  • splitChunks will allow to move CSS around
  • output.cssFilename and output.cssChunkFilename allows to configure the filename template for css files. By default it copies filename resp. chunkFilename with extension changed to .css
  • HMR will update CSS when you edit it.
  • There is external CSS that will lead to @import "..." in the output css files
  • There are external assets that will lead to a external url.
  • class names are based on module ids, so you need to make sure that SSR and Client module ids match
    • E1: Compute module ids in a deterministic way -> DeterministicModuleIdsPlugin
    • E2: Store module ids in a file and load them on the other side -> SyncModuleIdsPlugin
  • In addition to the default bindings, you can use type: "css/..." in rules to apply loader results as css. e. g. for Sass support.
  • This will replace mini-css-extract-plugin and css-loader
  • It will be more performant, by using a css tokenizer instead of postcss
  • There is a css minimizer in production mode.

Implemented:

  • A
  • @import url("...");
  • @import "...";
  • url()
  • chunking
  • on demand loading
  • HMR
  • splitChunks
  • output.cssFilename
  • external type css-import
  • external type asset
  • :export blocks
  • C (partially)
    • classes
    • ids
    • keyframes + animation
    • css variables + var()
    • var(xxx from "...")
    • var(xxx from global)
  • correct css order in output file
  • warnings for ordering issues
  • E
  • E1
  • E2
  • image-set()
  • @import url("...") layer(test);
  • @import url("...") supports(...);
  • @import url("...") media query;
  • move all external imports to top
  • do not ignore #import and make them external
  • inherit layer, supports(...) and media from parent module
  • supports style resolution in package.json and test it + test support loader usage
  • Implement CSS Module fetchpriority
  • prefetch/preload for CSS
  • external import with media/supports
  • Correct publicPath for assets modules inside CSS files
  • pathinfo for @import
  • prefeth/preload only for CSS import() generates prefetch/preload runtime for JS
  • default type: css enables CSS modules support (i.e. for CSS without CSS modules you need set type: "css/global"), which might be a bit confusing for developers, because some developer just want to use pure CSS and parsing CSS modules can affect on perf, I think we should do:
    • type: "css/auto" - enable/disable CSS modules based on path, it is css/module or css
    • type: "css" - no CSS modules and don't try to parse CSS modules things
    • type: "css/module" - CSS modules with local mode
    • type: "css/global" CSS modules with global mode
  • rewrite to be align with CSS spec
  • src()
  • unstable ?hash generation in --webpack-main when you have multiple same modules
  • improve logic in callback (more perfomance?) + better error reporting for @import
  • implement /* webpackIgnore: true */ for url()/image-set()
  • url() in css leaves an asset JS Module in js chunk
  • :import blocks
  • @value
  • Experiments.css reliance on fact that css should be loaded before js is a huge breaking change #17611 - allow link be before/after script + bug with safari
  • support legacy browser? experimental.css not support legacy browser? #16147
  • CSS entry without JS file (option to do only extract without runtime + for dynamic?) and hmr

Not implemented/tested, but Planned (ordered by priority):

  • C (partially)
    • composes: xxx
    • composes: xxx from "..."
    • composes: xxx from global
  • re-export for :export/@value/var()/classes and nested @import
  • icss interpolation for everything
  • local() and global() in declarations
  • more at-rules rename in css modules
  • move tests frompostcss-modules-* packages
  • css/global test
  • move tests from css-loader
  • moove test from extract plugin
  • internal refactor CSS parser + use ICSS prefix for deps + inheritance for deps
  • D
  • B
  • remove empty async chunks
  • exportGlobals
  • improve hashing of locals for production
  • pure mode
  • image()
  • css minimizer
  • contenthashing for CSS files
  • normalize media/supports/layer to lowercase?
  • url("font.svg#svgFontName") created invalid filename
  • wasm css tokenizer

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    Status

    Priority - High

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions