解决webpack编译后导致-webkit-box被强制去除了的问题


问题

今天遇到了一个问题,发现重构同事的 dist css 在我这里有兼容性问题。我只引用了他的源文件,未经过任何更改。排处了由于 Dom 结构不同的原因之外,唯一的不一样的地方,就是我引入他的文件后,在本地还进行了webpack 编译。那么问题只能出在了这里了。

经过对比两份文件发现,对比如下

1
2
3
4
5
6
7
8
9
10
11
12
13
// 重构同事的css
.detail-title{
-ms-flex:1;
flex:1;
-webkit-box-flex:1;
box-flex:1
}
// 我编译后的文件
.detail-title{
-ms-flex:1;
flex:1;
box-flex:1
}

咦, -webkit-box-flex 竟然被自动去除了。难道说在某种 webpack 插件下, -webkit-box 会自动被去除吗?

在网上搜了下,发现确实是有这种情况。有些插件的机制判断这个内容是不需要的,强行被去除了。可以看这个 issue

即使你是使用了 postCss, autoprefix 去添加了前缀,但是你用了去除的插件也会被去除。


解决办法

首先看下是什么插件导致了你的代码被强制的去除了。

大概的原因可能有以下几种:

最开始可能是由于 UglifyJsPlugin 中默认把 minimize = true 开启了, 而这个字段在css-loaderpostcss-loader中设置成 true 会开启优化模式,所以会对代码进行优化压缩。
css-loader 中又会使用 cssnano 进行压缩, 而 cssnano中又会进行无关前缀的清理。

为什么插件竟然会影响到loader ? 可以关注下这个 issue

这个插件(UglifyJsPlugin) 在 webpack2.x 貌似已经修复了。 css-loaderautoprefixer也已经做了相应的优化处理。如果你没有升级,你可以设置下面的方式试试:

  1. css-loader 传递参数:?minimize&-autoprefixer

  2. autoprefixer 传递参数

    1
    2
    3
    postcss: function() {
    return [autoprefixer, cssnano({ safe: true })];
    },

如果还有问题,再检查下,代码里有没有用到其他的去除优化工具。

我这边出的问题就是在这里。用了OptimizeCSSPlugin, 它默认把前缀给去掉了。所以这里我直接把这个 plugin 删除了。之所以我这里可以直接删除,是因为重构同事给到的就是去除压缩好了的。没有必要再去压缩去除一次。

1
2
3
4
5
6
7
8
// Compress extracted CSS. We are using this plugin so that possible
// duplicated CSS from different components can be deduped.

new OptimizeCSSPlugin({
cssProcessorOptions: config.build.productionSourceMap
? { safe: true, map: { inline: false } }
: { safe: true }
}),

再来看下为什么用了OptimizeCSSPlugin去除了prefix呢?看了下源码,也是又引入了cssnano

1
2
3
if (this.options.cssProcessor === undefined) {
this.options.cssProcessor = require('cssnano');
}


引申问题 - ssi 找不到定义的变量

由这个打包的问题,想到了前几天的另一个 webpack 的问题, index.shtml 文件中引入的 ssi, 如果变量用 ${variable} 读取,而不是$variable 读取,webpack 编译时就会报错。但实际上,这两种语法都是可以被 server 端解析的。探究了下会被报错的原因:

webpack 的 HtmlWebpackPlugin 在编译模板的时候,用的是 lodash 的 template 方式, 也就是 ${variable} 的形式。

所以你用了 ${variable} 的形式的话,他就会去编译这个变量,但是呢,这个 variable 你是从 ssi 上读的,又没有定义,它找不到,所以就会报错了。

所以就老老实实的,如果你用的 htmlWebpackPlugin 就用 $varialbe 的形式吧。

1
2
3
4
5
// correct
<!--#include virtual="xxx.cgi?refresh_token=$wxRefreshToken&appid=$wxAppid" -->';

// wrong: wxAppid is not defined
<!--#include virtual="xxx.cgi?refresh_token=$wxRefreshToken&appid=${wxAppid}" -->';

总结

相关参考

  1. issue1: # Why does the UglifyJsPlugin affect other loaders?
  2. issue2: # 「前端」从UglifyJSPlugin强制开启css压缩探究webpack插件运行机制
  3. issue3: # Using plugin “webpack.optimize.UglifyJsPlugin” led to remove the style “display: -webkit-flex;

觉得略坑。还是花了大概一下午看这个问题,呜呜呜(ಥ _ ಥ)!