现代 css 构建中不应使用原生 @import,因其阻塞渲染、无法并行加载、不支持条件加载;应改用预处理器 @use/@import + 构建编译,或动态 link + js 控制加载。

@import 在现代 CSS 构建中基本不该用
它会阻塞渲染、无法并行加载、不支持条件加载,连 postcss-import 都默认劝退。除非你还在维护 IE8 项目,否则别把它当“模块化方案”用。
常见错误现象:Network 面板里看到 CSS 文件串行加载,首屏白屏时间变长;热更新时改一个 @import 文件,整个主样式表重载;Webpack 里开启 css-loader 的 importLoaders 后反而报错。
- 浏览器原生
@import只在解析到该语句时才发起请求,比<link>晚得多 - 不能写在
@media内部(部分旧浏览器直接忽略) -
@import url("xxx.css") screen and (min-width: 768px)这种写法兼容性差,Safari 15.4 之前不支持媒体查询条件
真正可行的 CSS 模块拆分方式:预处理器 + 构建工具链
用 scss 或 less 的 @use/@import(注意:这是预处理器语法,不是 CSS 原生)做逻辑组织,最终由构建工具一次性编译成单个 CSS 文件。
使用场景:组件级样式隔离、主题变量复用、响应式断点集中管理。
立即学习“前端免费学习笔记(深入)”;
-
@use "base/variables"比@import更安全,避免全局污染和重复引入 - Webpack 中配
sass-loader时,additionalData可自动注入全局变量,不用每个文件都@use - PostCSS 插件如
postcss-preset-env不处理@import,只处理编译后的纯 CSS —— 所以预处理器阶段必须收口
如果非要动态加载样式,用 link + JS 控制更可控
比如暗色主题切换、A/B 测试样式包、按路由懒加载组件专属 CSS。这时候 @import 完全无能为力。
性能影响:CSS 文件可设 media="print" 预加载但不阻塞渲染,再用 JS 切换 media 值激活。
- 用
document.createElement("link")动态插入,比在 CSS 里写@import灵活得多 - 注意清除旧
link标签,否则重复插入导致样式叠加冲突 - Vite 中可用
import("/styles/theme-dark.css")直接加载,返回的是一个Promise,适合配合useEffect或生命周期钩子
目录结构建议:按功能分层,而非按技术分层
别搞 /css/base/、/css/components/、/css/utils/ 这种容易过早抽象的目录。真实维护时,你会卡在“这个按钮的 hover 样式到底算 component 还是 utility?”
推荐结构:/styles/themes/、/styles/layouts/、/styles/pages/home.css、/styles/widgets/search-bar.css —— 和代码目录对齐,谁改组件谁顺手改对应样式。
- 所有变量和 mixin 放
/styles/core/,用@use显式引入,不靠隐式全局 - 页面级样式用 BEM 或 CSS Modules,避免跨页面泄漏
- 不要把
@import当作“解耦”手段——真正的解耦靠作用域控制,不是靠文件拆得细
最常被忽略的一点:CSS 的“模块化”本质是作用域问题,不是加载问题。花精力设计选择器命名规则、限制层级深度、用构建工具做 scope 注入,比研究怎么 @import 十个文件有用得多。









