webpack里使用hash的坑

背景:
我在react项目里使用了css modules。按照在webpack中的标准配置流程,需要设置下css-loader:

{
  test: /\.css$/,
  loader: 'style!css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]' 
}

然后很开心的把项目跑了起来,所有的css中的class都加了一段hash。

然后我把代码传到测试服务器上build,惊人的发现css的class有了不同的hash!
然后搜索了下原因,


[hash] 是根据一个 compilation 对象计算得出的哈希值,如果 compilation 对象的信息不变,则 [hash] 不变


compilation 对象代表对某个版本进行一次编译构建的过程,如果在开发模式下(例如用 –watch 检测变化,实时编译),则每次内容变化时会新建一个 complidation,包含了构建所需的上下文信息(构建器配置、文件、文件依赖)。

简单的说,每次代码改动会造成hash的不同。但老子的代码没改!
然后又看到:

I can also confirm that hashes are different on different OS. This is a logical consequence since Windows uses backslashes as path separator. It's probably also due to the fact that Windows uses CRLF for new lines. There's nothing we can do about it.

所以hash还和不同的os相关(我的测试机为ubuntu,本地为windows)。

由于我的代码是前后端渲染,不只和浏览器相关,node本身也要根据react来渲染出一个html出来,而其中className必须和静态css中的className保持一致。当一套代码跑在多个node上时,会存在html中className与css不同的风险。

那么这个问题该如何规避?
我把hash:base64:5直接改成了path。这样就用文件的路径做为class的唯一标识。但不好的地方,是路径可能很长。
在css-loader中,也进行了一段说明,意识是可以自定义吐出的className:


You can also specify the absolute path to your custom getLocalIdent function to generate classname based on a different schema. Note that this requires webpack >= v2.x. since to be able to pass function in.

{
  test: /\.css$/,
  use: [
    {
      loader: 'css-loader',
      options: {
        modules: true,
        localIdentName: '[path][name]__[local]--[hash:base64:5]',
        getLocalIdent: (context, localIdentName, localName, options) => {
          return 'whatever_random_class_name'
        }
      }
    }
  ]
}

这里需要webpack版本升级到2。

参考:
Hash changes if a filename is changed
你用 webpack 1.x 输出的 hash 靠谱不?

你可能感兴趣的:(webpack里使用hash的坑)