1

问题重现

不知道各位旁友在webpack的使用中,有没有碰到下面的问题情景:

  1. 在使用了css Module的情况下,同时又希望用一些global的布局,其实在css Module中直接用

:global(.title) {
    color: green;
}

也是可以实现的,但是如果需要引入第三方css,如Animate.css,如果对每一个classname都进行手动的全局定义,工作量可不小。

  1. 关于css的打包问题,对于一些组件的样式,可以将css打包在js文件中,但是一些全局的css,或者一些需要第一时间加载的css (如pace.css,在页面加载过程中就需要第一时间解析出样式),就需要使用ExtractTextPlugin打包成为单独的css文件了。

以上都是需要对于同一类型文件的不同处理。在webpack中就体现成用正则表达式进行文件名匹配。

为了更优雅的命名,第一种情景来举例,我将全局的样式文件命名成foo.global.less,其他需要进行css module处理的则正常命名,如bar.less

思路

在进入主题之前,我先分享一个实用的在线正则网站refiddle,包含了不仅仅Javascript的正则

下面的重头戏便是
如何正则匹配*.global.less*.less(不包括*.global.less)?

众所周知,webpack中是不存在多次正则匹配的,所以需要分别使用2个正则表达式来解决上面两种字符串的匹配。

*.global.less字符串匹配?恩, so easy,/\.global\.less$/, 那么*.less(不包括*.global.less)呢?

显然,这就需要用到正则的位置匹配了((^\.global)[^\.global]都是不正确的),匹配前面不是.global的的位置。

分类 语法 说明
捕获 (exp) 匹配exp,并捕获文本到自动命名的组里
捕获 (?<name>exp) 匹配exp,并捕获文本到名称为name的组里,也可以写成(?'name'exp)
捕获 (?:exp) 匹配exp,不捕获匹配的文本,也不给此分组分配组号
位置匹配 (?=exp) 匹配exp前面的位置
位置匹配 (?<=exp) 匹配exp后面的位置
位置匹配 (?!exp) 匹配后面跟的不是exp的位置
位置匹配 (?<!exp) 匹配前面不是exp的位置
注释 (?#comment) 这种类型的分组不对正则表达式的处理产生任何影响,用于提供注释让人阅读

如上表,很显然需要使用(?<!exp),所以正则表达式是/(?<!global)\.less$/,完结撒花!

但是!真的就这样可以了吗??很不幸的是在js中并没有实现(?<=exp)(?<!exp)的位置匹配。(可能是大家伙都没想到Js能走到今天这个地步,以为只是在浏览器上耍耍,数据验证没必要太复杂吧, ? )
参看RegExp.

经过一番查找和头脑风暴,最终得到了Js中不包含某子串的正则匹配
/^(.(?!\.global))+\.less$/

(?!\.global)匹配的是后面不是.global的位置
(.(?!\.global))+匹配的就是若干个后面跟着不是.global的字符
^字符串首位置不能丢!,如果丢了,/(.(?!\.global))+\.less$/也能够匹配foo.global.less,因为从foo后面的.开始,后面跟着的就不是.global了。

但是对于.global.less字符串,该正则也无能为力了。

参考

  1. 正则表达式30分钟入门教程

  2. JavaScript RegExp

  3. 正则表达式匹配“不包含某个字符串” (通俗易懂还有图!)


moyuyc
1.1k 声望261 粉丝

前端学生