项目场景
很久之前在webpack
中使用postcss-loader
遇到了失效的问题。
最近刚好也遇到了,顺便将解决方案以及出现问题的原因做一个记录。
问题描述
首先,在平时的开发中,我们会对一些css
文件进行处理,比如添加前缀、排序等。
那我们最常见的一段代码如下:
/*reset.css*/@charset"utf-8";*{transition:all0.3s;user-select:none;}
//webpack.config.jsmodule.exports={//......module:{rules:[{test:/\.css$/,use:['style-loader','css-loader','postcss-loader']}]}}
正常打包后,出现的css代码一般会长成如下这样
*{transition:all0.3s;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;}
异常情况
但是天有不测风云,如果当前css
文件通过@import
语法导入了另一个css文件,这时再去打包就会发现,postcss
失效了。
比如,在index.css
文件中导入reset.css
,然后对index.css
进行打包
/*index.css*/@charset"utf-8";@import'reset.css';
打包后的结果如下
是的,长得和源文件一模一样。
原因分析
要分析产生这个问题的原因,必须要知道loader执行的顺序以及每个loader大概要做的事情。
过程分析
1、首先,webpack
通过入口文件开始爬文件进行打包,此时会识别到文件对index.css
有依赖。由于配置过关于css文件的loader
使用规则,index.css
首先会被交给postcss-loader
进行处理
2、当postcss-loader
在对css进行处理时,它主要功能是将css文件内的css代码
进行处理,而不会执行css文件内部的代码。也就是说,css文件中的@import
语法,此时并不会执行。
3、postcss-loader
处理完成后,会将已经具备兼容性前缀的css代码再交给css-loader
进行处理。此时,文件中的@import
就被执行了,reset.css
中的代码开始进入index.css
。
但很可惜,这一步已经晚了,因为postcss-loader
已经下班了。换句话说,默认情况下,loader
的执行顺序是单向的,index.css
文件已经被postcss-loader
处理完毕,不会回头再去处理一遍。
4、css-loader
执行完毕,再交给style-loader
进行样式注入。
原因
根据以上对执行过程的分析,其实可以发现,导致这个问题产生的原因是:
- css文件中的
@import
语法,在postcss-loader
处理时并不会执行 loader
不会逆向进行处理
解决方案
总结:使用importLoaders
属性将文件再交给postcss-loader
处理
module.exports={//......module:{rules:[{test:/\.css$/,use:['style-loader',{loader:'css-loader',options:{importLoaders:1}},'postcss-loader']}]}}
importLoaders
的意思是,如果在这个css文件中有@import
进来的文件,那这些文件将交给前n
个loader
进行处理。
此处我们需要将新文件交给前一个loader,也就是postcss-loader
来处理,所以它的值为1