Webpack自动化工程
近几年,前端各种框架工具层出不穷,从两三年前还是一个jQuery搞定全站,到之后requirejs/seajs,node,gulp/webpack,Angular/React/Vue,RN/weex的不断涌现,完全颠覆了原来的前端开发模式。
那么这些框架和工具给我们到底带来了什么好处呢?其实我认为最核心莫过于这两点:模块化开发、自动化工程。而本次前端重构所围绕的核心问题就是自动化工程,将原有的gulp版本的项目利用webpack彻底改造,顺利消灭了既繁琐又易错的人工操作。
gulp版本的痛点我们先来看下奇货商城之前的开发流程:
从上图可以看出,我们奇货前端开发之前存在的一些痛点:
以上这些痛点,造成的重复性无用功,既浪费精力又着实让人蛋疼,而经过这次的框架重构,只需一键操作,就可完成联调和发布的部署。省心省力还不会出错。
如何利用webpack做自动化先看一下改版后,奇货商城的开发流程:
从上图可以看到,我们经过改版后做到了:
下面我们看看如何实现。
项目结构下面是部分主要目录结构:
├── build (所有的webpack配置项) │ ├── build.js │ ├── dev-client.js │ ├── dev-server.js │ ├── utils.js (★入口配置,生成文件配置,vm生成都靠这个文件) │ ├── webpack.base.conf.js (基础配置) │ ├── webpack.dev.conf.js (开发模式配置) │ └── webpack.prod.conf.js (生成环境配置) ├── config (node环境变量,入口文件的配置) │ ├── dev.env.js │ ├── entry.js (页面文件列表) │ ├── index.js (★主配置文件) │ ├── prod.env.js │ └── skinEntry.js (皮肤文件列表) ├── dist (打包后生成的文件夹,已全部转成vm) │ ├── goods │ │ ├── detail.vm │ ├── index.vm │ └── static (打包后-静态资源文件) │ ├── css │ ├── js │ └── skins (打包后皮肤文件夹) │ ├── default │ │ ├── default.1184b4d7.js │ │ ├── default.f07ae9df.css │ │ └── default.html │ ├── huotu │ └── pay ├── mock ├── package.json ├── routes ├── src (源文件) │ ├── js │ │ ├── components │ │ ├── goods │ │ │ ├── detail.js │ │ │ └── skins │ │ │ ├── default.js │ │ │ ├── huotu.js │ │ ├── index.js │ ├── less │ │ ├── components │ │ ├── goods │ │ │ ├── detail.less │ │ │ └── skins │ │ │ ├── default.less │ │ │ ├── huotu.less │ ├── index.less │ └── pages │ ├── components │ ├── goods │ │ ├── detail.html │ │ └── skins │ │ ├── default.html │ │ ├── huotu.html │ └── index.html ├── static │ └── images └── unit (公共库) ├── common (业务组件) │ ├── js │ └── less ├── layout (公共页面) │ ├── footer.html │ └── header.html └── lib (第三方组件)以上是我们奇商城的前端目录结构。
webpack的一些必用的loader和plugin,例如less-loader, style-loader, file-loader, html-loader, 还有UglifyJsPlugin, ExtractTextPlugin, OptimizeCSSPlugin等等,在这里就不详细展开了。
我们重点说说以下几点核心:
node脚本调用webpack通过node脚本来调用webpack,而不是直接在命令行启动webpack,会有这么几个用处:
HtmlWebpackPlugin这货可以说是整个构建过程里,核心中的核心了。
自动生成vm、开发环境调用本地资源,以及皮肤文件的管理都有这个插件的功。部分代码:
new HtmlWebpackPlugin({ filename: process.env.NODE_ENV === 'production' ? path + name + '.vm' : path + name + '.html', template: template, inject: false, chunks: [pathBuild + name, 'vendor', 'manifest'] })通过判断node环境变量,决定生成vm还是本地html;
CommonsChunkPlugin通过这个插件实现了js模块打包,公共模块提取,客户端缓存&增量发布,皮肤文件生成。部分代码:
for (let i = 0; i < entry.length; i++) { let item = entry[i] let path = item.path let name = item.name let pathBuild = path.replace(/\//g, '-'); result[pathBuild + name] = './src/js/' + path + name + '.js' } for (let i = 0; i < skinEntry.length; i++) { let item = skinEntry[i] let path = item.path let name = item.name if (process.env.NODE_ENV === 'production') { result['../skins/' + path + name] = './src/js/goods/skins/' + name + '.js' } else { result['skins/' + path + name] = './src/js/goods/skins/' + name + '.js' } } Object.assign(result, { vendor: ['@unit/common/js/base', '@unit/common/js/util'] }) // 公共文件提取 new webpack.optimize.CommonsChunkPlugin({ name: 'vendor', // 注意不要.js后缀 chunks: utils.computeChunks(entryConfig, '') }) // 避免修改业务代码导致vendor的md5改变,保留文件缓存 new webpack.optimize.CommonsChunkPlugin({ name: 'manifest', chunks: ['vendor'] }) 自动化部署自动化部署是在打包服务器通过脚本实现的,先通过npm命令打包前端工程,然后将代码copy到后端工程中,最后打包后端项目,再发布。
遇到的困难 公共文件的引入