背景
今天在吃早饭的时候就被同事@,说有一块页面效果在测试服务器的部署效果跟本地不一样:代码在本地运行没有问题,部署后发现有一个分割线的位置明显不对。来到公司后看了同事的演示,觉得可能是 css 代码压缩时出现了问题。
通过 chrome 查看相关 css,发现了问题所在,有一段代码是这样写的:
1 | .clz_editor_container { |
压缩后在 chrome 中代码变成了这样的:
1 | .clz_editor_container[data-v-5fd4dedf]{ |
然而实际浏览器中前两句都没有生效。
因为在代码压缩时,相同的代码会默认选择比较靠后的,因此 display: -ms-flexbox; -ms-flex-direction: column;,而 -ms-flexbox 和 -ms-flex-direction 是为了兼容 IE 浏览器而存在的, 所以这两句 css 都没有生效。
而没有压缩的代码在浏览器中运行时,浏览器自动选择了合适的 css 语句所以没有出现问题。
解决方案很简单啦,这应该是同事写代码粗心导致的,直接把 display: flex; flex-direction: column;加上就行了。而且 idea 里面自动代码兼容性补全功能,所以用 idea 写出的代码应该不会出现这个问题。
然后有同事说应该有一些工具能够自动补全的,于是 google 了一下,发现这种问题早就有非常好的解决方案,那就是 PostCSS 的插件 autoprefixer。
解决方案
首先安装 webpack 插件 postcss-loader 和 autoprefixer
1 | $ npm i autoprefixer postcss-loader --save-dev |
然后修改 webpack 配置文件,在插件系统中更改 LoaderOptionsPlugin,在 options 中增加 postcss
1 | new webpack.LoaderOptionsPlugin({ |
然后在所有 css 相关的 loader 中增加 postcss-loader
1 | { |
注意 postcss-loader 应该放在 less-loader 和 css-loader 之间,处理顺序为:
less-loader -> postcss-loader -> css-loader -> style-loader
修改前面出问题的 css 为原生
1 | .clz_editor_container { |
重新打包压缩后的 css 如下
重新打开查看效果,问题解决。
注意如果你在 css 中使用 @import 引入其它 css 文件,而被引入的文件在 webpack 打包后又没有加入浏览器前缀的话,建议在 css-loader 中加入 importLoaders=1 参数
1 | { |
PostCSS
PostCSS 是什么?官方给出的定义是: PostCSS 是一个用 JavaScript 转化 CSS 的工具。准确的说,PostCSS 是一个平台,通过一些插件,能做很多事情:
(1) 增加代码可读性
比如刚才我们用的 autoprefixer,通过给 css 添加供应商前缀,让我们的 css 代码更加优雅。
(2) 使用未来 CSS 的语法特性
通过使用 cssnext 插件,可以允许我们使用最新的 css 语法,而不用等待浏览器支持。
(3)global css 终结者
PostCSS 通过 CSS Modules 对 css 命名做模块化处理,一般为添加前缀和后缀,让我们写 css 的时候不必担心命名太通用,只要觉得有意义即可。
(4)避免 css errors
通过使用 stylelint 来避免 css errors。
(4)更强大的栅格系统
LostGrid 通过 calc() 轻松创建强大的栅格系统。
(5)更多插件 更多功能
PostCSS webpack
在 webpack 中使用 PostCSS 的一般方式
- 安装相关依赖
1 | $ npm install postcss-loader --save-dev |
- 创建 postcss.config.js
1 | module.exports = { |
可以通过在不同路径下创建不同的 config 来实现配置覆盖的功能,在根目录下创建的 postcss.config.js 会被子目录中的配置文件覆盖。
- 添加 PostCSS Loader 到 webpack.config.js 中,记得要把它放在 css-loader 和 style-loader 后面,如果有其它 loader,如 sass-loader 或者 less-loader, 要放在它们前面。
1 | module.exports = { |
- 如果不想使用 postcss.config.js 的话,也可以把插件直接写入到 webpack.config.js 中
1 | module.exports = { |
demo
假如有 style.css 如下
1 | :root { |
webpack 配置文件下
1 | var cssnext = require('cssnext'); |
运行 webpack 命令后,dist 文件夹下面的 style.css 如下
1 | div { |
这里一共使用了三个插件,cssnext 解析 css 自定义属性和 val() 函数,autoprefixer 添加浏览器前缀,postcss-px2rem 完成 px 到 rem 单位的转化。
参考资料
- 参考 PostCSS 官方网站,了解 PostCSS 的更多内容。
- autoprefixer
- cssnext