webpack 使用优化(一)

之前写了一篇关于webpack 如何使用的文章:webpack 单页面应用实战,并且写了一个 单页面应用的小项目 放到了github上。正巧公司前段时间用webpack 做了一个项目,项目不大,是基于单页面应用的。但是上线后才发现了一些问题,原来还是有一些要优化改进的地方。

webpack 单页面应用实战这篇文章基本已经满足了我们的需求。比如以下功能我们都已经实现:

  • 将css从js中分离出来
  • 使用loader加载css、图片等
  • 使用插件生成html以便自动引用变更版本号的文件
  • 配置公共js
  • js文件按需加载
  • 配置开发环境
  • 压缩js、css、html
  • 给css、js、图片、字体等添加版本号
  • 编译后自动打开浏览器
  • 热替换
  • 使用代理结合后端服务开发
  • 编译时区分开发环境、生产环境、热替换环境
  • config 文件的合并
  • 清空发布目录

看似不错,好像都已实现了,但是具体到生产环境时还是有问题的。下面有几处优化(下面还是结合这个项目)。

优化-公共js版本号会变化的问题

这个问题在项目上线之前我没有发现,上线以后,有一次需求变化,我在改变其他js文件的时候,然后打包发布发现公共js的版本号发生了改变,最后检查下来,的确是公共js的内容发生了变化,所以对应的版本号发生了变化。原因就是webpack默认会把最重要的东西放到公共js里,这里面包含webpack启动应用程序的依赖项、模块与模块的依赖关系、以及文件的版本号等信息。所以一旦任意的js文件发生改变都会体现在公共js上。比如我们通过webpack构建后生成这样的文件:
图片描述

再看下common.js 里大致包含什么内容(截取一小部分):
图片描述

公共js版本号会变的问题在 github 上讨论了一段时间(点击这里),只不过之前没注意。有人用 webpack-md5-hash 插件实现了,但是感觉比较麻烦,最终还是感觉webpack 的贡献者实现的这种方式很简单,并且不需要额外的插件,在新版本的webpack中融合的很好。但是提供的这个demo太简单,在项目中我们还是要注意一些问题的。比如使用‘热替换’时就会报错。所以我们要做一些改变,我们只需要将之前配置公共js的地方:

1
2
3
4
5
6
7
// webpack.config.js
...
plugins:[
// 会把 ‘entry’ 定义的 common 对应的两个js 打包为 ‘common.js’
new webpack.optimize.CommonsChunkPlugin("common", 'js/[name].js', Infinity),
]
...

改为:

1
2
3
4
5
6
7
8
// webpack.config.js
...
new webpack.optimize.CommonsChunkPlugin(
devServer ?
{name: "common", filename: "js/common.js"}:
{names: ["common", "webpackAssets"]}
),
...

注意: ‘devServer’ 是一个标识变量,代表‘热替换’ ,如有疑惑看上一篇配置变量标识

改成这种设置以后,当时热替换模式的时候不对common.js做处理,如果是开发模式或者发布模式,会从common.js中将各个文件的版本号以及其他重要信息抽出来,放到‘webpackAssets.js’文件中(名称可以自定义)。生成的文件如下,会多出一个文件,这个文件只有几kb:
图片描述

改成这种做法后,一旦其他的文件发生改变,都会在webpackAssets.js文件中得到体现,项目的发布升级,只要额外的将这个文件升级上去即可,而不用将公共js升级上去。这样的优化会非常有利于处理缓存的问题。

优化-设置模块目录

如果项目小不设置webpack请求的模块目录没关系,但是一般项目越来越大,webpack会查找很多无用的文件,这时候设置模块目录很有必要性,可以提高webpack编译的速度。即设置 resolve.root 属性。还有一个属性是 moduleDirectories,这两个的区别可以点这里。resolve.root 接收的参数是 node_modules 文件加的绝对路径。我们在之前的webpack.config.js 中增加这个配置项:

1
2
3
4
5
6
7
8
9
// webpack.config.js
...
resolve:{
root: [
path.resolve('./node_modules')
],
...
}
...

这样设置后,webpack编译速度会大大加快,不会每个文件夹都搜索一遍。


扫码可在移动端查看这篇文章:
图片描述