奇货商城重构——webpack自动化工程
近几年,前端各种框架工具层出不穷,从两三年前还是一个jQuery搞定全站,到之后requirejs/seajs,node,gulp/webpack,Angular/React/Vue,RN/weex的不断涌现,完全颠覆了原来的前端开发模式。
那么这些框架和工具给我们到底带来了什么好处呢?其实我认为最核心莫过于这两点:模块化开发、自动化工程。而本次前端重构所围绕的核心问题就是自动化工程,将原有的gulp版本的项目利用webpack彻底改造,顺利消灭了既繁琐又易错的人工操作。
gulp版本的痛点
我们先来看下奇货商城之前的开发流程:

从上图可以看出,我们奇货前端开发之前存在的一些痛点:
- 前端在后端项目里面修改vm文件联调;
- 开发联调需要上传静态资源到测试域名CDN;
- 不同目录下的资源还需要在CDN上传网站上一级一级目录的点开再上传;
- 上线前需要人工去替换vm文件里的CDN路径;
- 上线前还需要人工去上传静态资源到正式域名CDN;
- 开发模式不支持es6转义,导致低端安卓机无法在本地进行前端调试;
- gulp-babel不完全支持es6转es5,导致部分低端安卓机出现各种莫名其妙的问题;
以上这些痛点,造成的重复性无用功,既浪费精力又着实让人蛋疼,而经过这次的框架重构,只需一键操作,就可完成联调和发布的部署。省心省力还不会出错。
如何利用webpack做自动化
先看一下改版后,奇货商城的开发流程:

从上图可以看到,我们经过改版后做到了:
- vm文件自动生成
- 开发联调直接读取本地静态资源
- 打包后所有资源在同一级目录,一次性拖拽上传(下个版本将实现前静态资源自动上传)
- 只需一行配置项,自动生成对应的线上CDN路径
- 完美的babel-loader,es6语法也可在低端安卓机上轻松本地调试;
下面我们看看如何实现。
项目结构
下面是部分主要目录结构:
├── 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,会有这么几个用处:
- 通过node启express做本地mock数据;
- 开发环境和生产环境的公共配置项,通过
webpack-merge模块做抽离,方便维护; - 可以设置node环境变量,以区分不同环境中的打包配置,这点在后面还有一个大招;
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到后端工程中,最后打包后端项目,再发布。

遇到的困难
公共文件的引入
webpack官方文档并没有如何引入公共html文件的说明,这一点是在翻了N多资料后才发现的,最终的方案是:
去掉webpack.config.js文件中配置的全局html-loader,这样html模版文件就不会被html-loader解析,我们可以使用ejs语法嵌入其他html页面和图片资源。因为没了全局的html-loader解析html文件,使用ejs语法嵌入的资源返回的是ejs代码,还需要使用html-loader来解析成html代码。
(html-loader!)表示引用html-loader这个加载器来解析
<%= require('html-loader!../layout/header.html') %>
但是这样将全局html-loader去掉后,又碰到了下面的问题。
jsp变量的引入
vm中有时需要直接引用后端的变量,如${cssUrl},就像这样:

这时候webpack打包居然就报错了,报错了:

原因排查
出现这个问题的原因应该是由于HtmlWebpackPlugin这个插件引用的模版默认是ejs,当不使用全局html-loader的时候,模板文件其实是以ejs解析的,而${cssUrl}在ejs中也识别为一个变量,当然就报错了。
解决方法
这过程中,整个周末都在想这个问题,甚至已经开始考虑用gulp+webpack的方案了。。
又翻了很多资料,突然想到既然是ejs模板,可以尝试了一些ejs去写,而不是非要把这个模板以html的方式loader进来,然后就有了如下方法:
<link href="<%= '${cssUrl}' %>" rel="stylesheet">
这时候就被识别为一个字符串了!成功解决。
进一步探索,巧用node环境变量
上面的方法解决的其实也是挺丑的,因为本地开发的时候需要引用本地文件的,上线的时候又得傻乎乎地去一个个地方去替换:
<!-- <link href="<%= skinCss %>" rel="stylesheet"> -->
<link href="/skins/pay/pay.css" rel="stylesheet">
然后马上试了下,在模板文件中用ejs去读node环境变量process.env.NODE_ENV,果然能取到值,就有了下面这个相对完美的方案:
<%
if (process.env.NODE_ENV === 'production') {
skinCss = '${cssUrl}';
} else {
skinCss = '/skins/pay/pay.css';
}
%>
<link href="<%= skinCss %>" rel="stylesheet">
其中production就是利用node启动webpack时配置的,在这里派上了大用场。
End
到这里,我们奇货商城已经实现了前端工程自动化,再也不用一遍又一遍地去vm里修改路径,人工去记着改了哪些文件,要上传哪些静态资源。更加不用担心漏传什么资源文件而导致线上bug辣。
奇货商城重构——webpack自动化工程的更多相关文章
- Webpack自动化工程
近几年,前端各种框架工具层出不穷,从两三年前还是一个jQuery搞定全站,到之后requirejs/seajs,node,gulp/webpack,Angular/React/Vue,RN/weex的 ...
- 从0开始搭建vue+webpack脚手架(四)
之前1-3部分是webpack最基本的配置, 接下来会把项目结构和配置文件重新设计,可以扩充更多的功能模块. 一.重构webpack的配置项 1. 新建目录build,存放webpack不同的配置文件 ...
- 近期热门微信小程序demo源码下载汇总
近期微信小程序demo源码下载汇总,乃小程序学习分析必备素材!点击标题即可下载: 即速应用首发!原创!电商商场Demo 优质微信小程序推荐 -秀人美女图 图片下载.滑动翻页 微信小程序 - 新词 GE ...
- 【前端】一步一步使用webpack+react+scss脚手架重构项目
前言 前几天做了一个项目:[node]记录项目的开始与完成——pipeline_kafka流式数据库管理项目:因为开发时间紧迫,浅略的使用了一下react,感觉这个ui库非常的符合我的口味,现在趁着有 ...
- 高性能流媒体服务器EasyDSS前端重构(一)-从零开始搭建 webpack + vue + AdminLTE 多页面脚手架
本文围绕着实现EasyDSS高性能流媒体服务器的前端框架来展开的,具体EasyDSS的相关信息可在:www.easydss.com 找到! EasyDSS 高性能流媒体服务器前端架构概述 EasyDS ...
- 一步一步使用webpack+react+scss脚手架重构项目
前几天做了一个项目:[node]记录项目的开始与完成——pipeline_kafka流式数据库管理项目:因为开发时间紧迫,浅略的使用了一下react,感觉这个ui库非常的符合我的口味,现在趁着有空闲时 ...
- 高性能流媒体服务器EasyDSS前端重构(四)- webpack + video.js 打造流媒体服务器前端
接上篇 接上篇<高性能流媒体服务器EasyDSS前端重构(三)- webpack + vue + AdminLTE 多页面引入 element-ui> 本文围绕着实现EasyDSS高性能流 ...
- 高性能流媒体服务器EasyDSS前端重构(三)- webpack + vue + AdminLTE 多页面引入 element-ui
接上篇 接上篇<高性能流媒体服务器EasyDSS前端重构(二) webpack + vue + AdminLTE 多页面提取共用文件, 优化编译时间> 本文围绕着实现EasyDSS高性能流 ...
- 高性能流媒体服务器EasyDSS前端重构(二) webpack + vue + AdminLTE 多页面提取共用文件, 优化编译时间
本文围绕着实现EasyDSS高性能流媒体服务器的前端框架来展开的,具体EasyDSS的相关信息可在:www.easydss.com 找到! 接上回 <高性能流媒体服务器EasyDSS前端重构(一 ...
随机推荐
- dotpeek的导出
在开始写之前先说明下,搜了很久的度娘,就是没找到dotpeek的导出功能,····,看来用的人不多, ------------------------------------------------- ...
- monkeyscript - 定制化monkey流程
作为移动端测试必须掌握的初级Android稳定性工具:monkey,提到它时,脑海里一般涌现出两句话: 1.我会用,很简单 就是一行命令,一回车就开始跑起来了 2.使用问题多,不好用 太随机,很多操作 ...
- #Laravel 笔记# 多语言化 App::setLocale() 持久化。
App::getLocale();获取当前语言 App::setLocale();设置语言配置文件 语言配置文件config/app.php locale 是默认语言,fallback_locale为 ...
- 【Log4j】分包,分等级记录日志信息
在开发中我们经常会将不同包下的日志信息在不同的地方输出,以便于以后出问题能够直接在对应的文件中找到对应的信息! 例如:在spring+SpringMVC+mybatis的框架中,我们经常会将sprin ...
- DNS,TCP,IP,HTTP,socket,Servlet概念整理
DNS,TCP,IP,HTTP,socket,Servlet概念整理 常见的协议虽然很容易理解,但是看了之后过一段时间不看还是容易忘,笔记如下,比较零碎,勉强供各位复习.如有错误欢迎指正. D ...
- 【canvas学习笔记二】绘制图形
上一篇我们已经讲述了canvas的基本用法,学会了构建canvas环境.现在我们就来学习绘制一些基本图形. 坐标 canvas的坐标原点在左上角,从左到右X轴坐标增加,从上到下Y轴坐标增加.坐标的一个 ...
- .net core 项目文件结构浅析
1:launch.json (配置调试用的) 通过vs code创建的项目,都会有这个文件,是启动调试的配置文件: (vscode默认支持nodejs调试) 要调试调试c#代码 需要安装 C# 插件 ...
- NLPIR大数据挖掘平台新增敏感词扫描功能
在网络日益发达的现在,也伴随着有益信息与造成不稳定因素的信息也随之日益泛滥,为了网民的思想健康,也为了社会的和谐,在许多对外公共场合下,有些内容是要经过审查才能显示的.在网络审查初期,都是通过人工审核 ...
- Making the Grade (bzoj1592)
题目描述 FJ打算好好修一下农场中某条凹凸不平的土路.按奶牛们的要求,修好后的路面高度应当单调上升或单调下降,也就是说,高度上升与高度下降的路段不能同时出现在修好的路中. 整条路被分成了N ...
- phpstudy命令行中数据表插入中文显示不了的问题
在PHPstudy环境下,做MySQL操作,往数据表里面插入数据的时候,如果是中文的数据就会显示不了或者是问号?. 这个问题搞了我一晚上了,终于知道问题所在. 下载的PHPstudy的MySQL数据库 ...