以前写了一篇关于webpack 如何使用的文章:webpack 单页面应用实战,而且写了一个 单页面应用的小项目 放到了github上。正巧公司前段时间用webpack 作了一个项目,项目不大,是基于单页面应用的。可是上线后才发现了一些问题,原来仍是有一些要优化改进的地方。css
webpack 单页面应用实战这篇文章基本已经知足了咱们的需求。好比如下功能咱们都已经实现:html
将css从js中分离出来node
使用loader加载css、图片等webpack
使用插件生成html以便自动引用变动版本号的文件git
配置公共jsgithub
js文件按需加载web
配置开发环境npm
压缩js、css、htmlsegmentfault
给css、js、图片、字体等添加版本号后端
编译后自动打开浏览器
热替换
使用代理结合后端服务开发
编译时区分开发环境、生产环境、热替换环境
config 文件的合并
清空发布目录
看似不错,好像都已经实现了,可是具体到生产环境时仍是有问题的。下面有几处优化(下面仍是结合这个项目)。
这个问题在项目上线以前我没有发现,上线之后,有一次需求变化,我在改变其余js文件的时候,而后打包发布发现公共js的版本号发生了改变,最后检查下来,的确是公共js的内容发生了变化,因此对应的版本号发生了变化。缘由就是webpack默认会把最重要的东西放到公共js里,这里面包含webpack启动应用程序的依赖项、模块与模块的依赖关系、以及文件的版本号等信息。因此一旦任意的js文件发生改变都会体如今公共js上。好比咱们经过webpack构建后生成这样的文件:
再看下common.js 里大体包含什么内容(截取一小部分):
公共js版本号会变的问题在 github 上讨论了一段时间(点击这里),只不过以前没注意。有人用 webpack-md5-hash 插件实现了,可是感受比较麻烦,最终仍是感受webpack 的贡献者实现的这种方式很简单,而且不须要额外的插件,在新版本的webpack中融合的很好。可是提供的这个demo太简单,在项目中咱们仍是要注意一些问题的。好比使用‘热替换’时就会报错。因此咱们要作一些改变,咱们只须要将以前配置公共js的地方:
// webpack.config.js ... plugins:[ // 会把 ‘entry’ 定义的 common 对应的两个js 打包为 ‘common.js’ new webpack.optimize.CommonsChunkPlugin("common", 'js/[name].js', Infinity), ] ...
改成:
// 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 中增长这个配置项:
// webpack.config.js ... resolve:{ root: [ path.resolve('./node_modules') ], ... } ...
这样设置后,webpack编译速度会大大加快,不会每一个文件夹都搜索一遍。