-
Notifications
You must be signed in to change notification settings - Fork 4.7k
Description
What problem does this address?
@wordpress/wp-build inlines all imported stylesheets into the JS bundle as runtime-injected <style> elements (with data-wp-hash deduplication). This means that if someone adds import './style.scss' in a JS file, it silently "works" at runtime, making it easy to miss that this is the wrong pattern.
In most packages, stylesheets should be imported through the package's root-level style.scss, not directly in JS. Importing in JS bypasses the standard stylesheet pipeline and causes the styles to be injected at runtime via document.head.appendChild. This has several problems:
- Redundancy. If the stylesheet is already in the root
style.scsschain, it gets loaded twice. - Missing from the stylesheet bundle. If the stylesheet is not in the root chain, it's absent from the CSS file that WordPress enqueues, and only loads through the runtime injection.
- No RTL processing. Most packages rely on the build-time RTL transformation to generate
-rtl.cssstylesheets. Runtime-injected styles bypass this entirely, so any directional styles (margins, paddings, borders, etc.) will be broken in RTL locales.
I found three existing cases of this:
packages/block-editor/src/components/block-visibility/modal.jsimports./style.scss. This is redundant because the same file is already in the rootpackages/block-editor/src/style.scss.packages/editor/src/components/collaborators-presence/index.tsximports./styles/collaborators-presence.scss, andlist.tsximports./styles/collaborators-list.scss. These are not in the root stylesheet at all, so they're only loaded through the runtime injection.
What is your proposed solution?
-
Fix the existing cases. Remove the SCSS imports from the JS/TS files above. For the
collaborators-presencestylesheets, also add them topackages/editor/src/style.scss. -
Add a lint rule to prevent importing non-module
.scss/.cssfiles in JS/TS files. This should flag side-effect-only imports likeimport './style.scss'while allowing CSS module imports that have a binding (e.g.,import styles from './style.module.scss'). The rule should apply to packages that use the root-stylesheet convention, and could be configured via an.eslintrc.jsoverride to exclude packages like@wordpress/uithat intentionally import styles in JS. -
Consider restricting
wp-buildinline injection to CSS modules only. Currently thecompileInlineStyletransform inwp-buildprocesses all.css/.scssimports the same way. If it only applied the runtime injection to.module.css/.module.scssfiles, developers would notice that the styles are missing.