TL;NR 太长不看
涉及到了 CSS Modules
在 Webpack 的 css-loader 中,默认情况下,为所有匹配
/.module.\w+$/i.test(filename)
与/.icss.\w+$/i.test(filename)
正则表达式的文件启用 CSS 模块,这样可以支持诸如:export
等 css modules 特性。在将 Webpack 4 升级到 5 时,往往 css-loader 也会升级。那么需要将原有的
*.scss
改名为*.module.scss
即可;其他诸如 css、less 等同理。
这是一篇过气的碎碎念,只是自己记录一下了,众看官莫笑。
失效了的 :export
魔法
最近在尝试将一个 Webpack 4 升级到 5 (Vite 以后再说),项目基于 花裤衩
的 Vue Element Admin
:
panjiachen.gitee.io/vue-element…
Vue Element Admin 用的是 Vue CLI 4,也就是对应了 Webpack 4;升级到 Vue CLI 5 之后(已经处于维护模式,使用的 Webpack 5),主题什么的全丢了,最明显的是默认为黑色的左侧导航栏变成了白色。找到对应的组件,位于 src\layout\components\Sidebar\index.vue
,不难发现这一句:
import variables from '@/styles/variables.scss'
看来主题颜色是通过这种方式动态调整的,采用的是 :export
这个魔法,见:
gitee.com/panjiachen/…
// the :export directive is the magic sauce for webpack
// https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass
:export {
menuText: $menuText;
menuActiveText: $menuActiveText;
subMenuActiveText: $subMenuActiveText;
menuBg: $menuBg;
menuHover: $menuHover;
subMenuBg: $subMenuBg;
subMenuHover: $subMenuHover;
sideBarWidth: $sideBarWidth;
}
通过该魔法,可以将 scss 、 css 变量共享给 js ,相关文章掘金里就很多,不一一列举。
然而,升级到 Webpack 5 之后这个魔法失效了?在注释提供的文章地址中也看到了近几年的评论:
This doesn't work. 这不好用啊老铁
What version of sass-loader supports this? 哪个 sass-loader 版本支持这特性?
都是这种画风。然后...就没然后了...
背后一凉:这咋办?
好吧,开始搜索关键词: webpack 5 sass :export
无果...
换了几个关键词也不行...
不是 Webpack 5 都出了这么久了,怎么会这么难搜呢?
甚至去 Sass官网,也搜不到 :export
。那这魔法哪里来的?
不过搜到了一些其他的方案,比如:
-
什么?要改 Webpack ?不,我才不要;
-
居然直接全局注入?不行,我也不喜欢。而且看了看 sass-resources-loader 只支持 Webpack 4,那么再见。
-
我用的可是 Webpack,和 Vite 啥关系?罢了,瞅瞅...
嚯?这不也是
:export
魔法吗?一等为什么 Vite 会支持...修改为.module.scss
后缀?呃?
看了看 Vite 文档,这会被认为是一个 CSS modules 文件 ?
魔法来源:CSS Modules
CSS modules 我早有耳闻,不过一直认为离 Vue 很远。这让我意识到之前的思路不对劲,要正视这个工具了。
官方仓库 并没有提及该黑魔法,但是文末提及了 Webpack 的 css loader,于是去查 Webpack 文档,找到了这样的描述:
modules
类型:
Boolean|String|Object
默认值:undefined
启用/禁用 CSS 模块或者 ICSS 及其配置:
undefined
- 为所有匹配/.module.\w+$/i.test(filename)
与/.icss.\w+$/i.test(filename)
正则表达式的文件启用 CSS 模块。
ICSS ?
前面 将 SCSS 变量分享给 JS 这篇文章提及了:
坑 1:必须让 css-loader 使用 icss 模式,否则 vars 为空对象!
这里就没看懂,不过我 console.log
了一下,对应的 vars 确实为空对象,然后就跳过了。看来关键点在这里。
接下来搜索关键词: css modules icss export
找到了 ICSS 仓库。 ICSS, Interoperable CSS ,即:互操作 CSS —— 互操作?原来就是用来做跨语言交换的啊!
果然,找到了 :export
魔法的来源了,就是这里!
:export
An
:export
block defines the symbols that are going to be exported to the consumer. It can be thought of functionally equivalent to the following JS:
module.exports = { "exportedKey": "exportedValue" }
收尾
做完上面的了解,立即将原有的 variables.scss
重命名为 variables.module.scss
,问题解决!
看来原有的注释需要再改进一下,然后重新戳开了注释里的那篇文章,才发现...原来人家已经写明了这是 CSS Module 的魔法...😑
面对非母语的文章容易不怎么耐心下来看,反而花费了更多的时间绕弯。日后还是要多些耐心才是。
还是得好好去看一下 CSS Module...之前太想当然了...