前段时间大部门下新成立了一个推广百度OCR、文字识别、图像识别等科技能力在金融领域应用的子部门。由于部门刚成立,基础设施和人力都是欠缺的。当时分到咱们部门的任务是抽调一我的作新部门主站前端开发工做。原本说的是只负责页面的开发工做。当我参加过需求品审会后,了解到新部门人力不足,而我今年主要任务又是在咱们部门作基于Nodejs的前端后端分离的架构升级工做。css
在这以前就是用Nodejs写了两个内部系统,并无大型的线上Web开发经验,也想趁着这个机会锻炼下。而后就主动的跟老板商量了这件事,老板很是支持。以后又跟新部门的产品商量,原本就缺人手的他们也很是乐意我这边承担更多的开发任务。html
这篇文章和本身以前的文章的风格会有很大的区别,不会再去写一些具体技术点和遇到问题的具体解决办法,主要谈的是我整个开发过程当中遇到的一些问题和思考解决他们的方法。前端
内容列表node
技术选型的思考
相关服务申请
前端工程
技术目标
Web安全
内网机器访问外网
发送邮件
网络优化
收获
技术选型的思考mysql
在文章的最开头背景介绍中大概说了网站后端采用Nodejs的开发。为了突出科技能力,网站要求了一些特效。由于我要用CSS3来写这些特效,跟产品PK后结果是浏览器兼容性是IE8.0以上,特效知足大多数主流浏览器便可。那么基于Nodejs的其它技术选型以下:sql
如下选择这些技术的缘由:数据库
yog2(点击到达主页))是百度公司内部基于Express开发的比较成熟的Nodejs Web框架。提供的能力都是跟公司内部的基础服务(同机房访问、运维、日志等)接轨的,并且有一些部门已经在线上大规模使用,若是遇到问题能够有不少经验能够借鉴。
swig是yog2默认支持的模板引擎。
由于Nodejs的语法是遵循CMD规范的。并且在百度内部提倡的也是使用FIS3和Mod.js。因此就选择了公司内部的FIS3(点击到达主页)和Mod.js(点击到达主页)。FIS3不只有百度本身内部在用,也有不少的外部公司在用,好比滴滴等。
由于交互要求兼容一些低版本浏览器和一些奇葩的国产浏览器。为了保证开发时间的可控就选择了本身熟悉的jQuery;
相关服务的申请express
肯定了技术选型以后就是开始申请服务,主要包括如下相关内容:npm
域名申请
服务器申请
Mysql数据库申请
bos存储服务(使用的是百度云的bos存储)
以上都是走的公司的内部流程,具体的就不介绍了。主要介绍下一些服务的做用。一个在网络上运行的网站确定是须要一个域名的,能让网站跑起来很定是须要线上服务器的。存储用户的注册数据须要数据库。由于使用OCR进行人脸识别,要知足识别一张图片上的多张脸。是须要对用户的图片裁切。由于网站是部署在多台机器上,确定不能存储在网站运行的服务器上须要将裁切好的图片存储在专门的存储服务器上,而且返回给网站图片连接,编程
前端工程
使用Nodejs开发的话,前端的工程的概念可能还要广一些会涉及到Nodejs相关的工程化。这部分分两部分介绍:
1.前端
目标:
- 使用 SASS 来作css的模块化管理,而且实时编译成css,生成map文件便于本地调试;
- 将使用 CMD 规范编写的组件和模块化的代码打包编程供页面的业务代码引用;
- 给须要加厂商前缀的css属性自动加厂商前缀;
- 可以实时的将代码部署到测试环境,以方便QA测试;
以上的这些目标均可以使用 FIS3和相关插件来实现。
2.后端
由于咱们线上大规模使用的Nodejs版本是6.x版本。可是开发过程当中处理异步又是使用async和await。因此须要借助编译引擎将这些es7的语法编译成6.x支持的语法。
另外就是借助process.env.NODE_ENV能够读取环境变量的特性,来区分配置一些线上和线下的配置,好比:
const YOG_DEBUG = process.env.YOG_DEBUG;
const PANSHI_DEBUG = process.env.PANSHI_DEBUG;
let mysqlConf;
if (PANSHI_DEBUG === 'true') {
mysqlConf = {
host: '10.00.00.00',
user: 'ppui',
password: 'ppui',
database: 'excel',
port: '5003'
};
} else if (YOG_DEBUG === 'true') {
mysqlConf = {
host: '127.0.0.1',
user: 'root',
password: '',
database: 'pass_panshi',
port: '3306'
技术目标
这里主要谈一些前端的技术目标
1.样式显示和dom操做分离
以前开发过程当中常常遇到的状况是我须要该一个html节点的样式,不当心改了class类名。而js又偏偏使用了这个class操做了dom。这个时候页面运行的时候确定会报错的,增长了项目的维护成本。
有两种方案能够有效的解决这种问题,第一就是添加自定义属性,好比<div class="section" node-type="pagesecond"></div>当我须要操做dom的时候就经过jQuery的属性选择器来操做这个dom而不会去使用class。这样在我调整样式、须要修改class名称的时候也不会影响js代码。第二种就是根据你们常常说的使用-来作html 类名的链接符,而咱们就规定一个规范就是使用下划线(_)来标记我要操做dom节点的名称,好比<div class="section _pagesecond"></div>。
这两种方式,若是是在开发多人维护的项目是都是须要提早预约规范,我在项目中是使用的前者。
2.业务代码和功能代码分离
在前面已经介绍过就是使用cmd规范来组织前端代码。好比为了可以知足我使用属性选择器来做为操做dom的需求。我特意本身封装了一些代码段,好比在base.js文件中有一段这样的代码:
/**
* 根据node-type获取节点信息
*
* @param {any} params 获取节点元素
* @param {any} context 上下文环境
* @returns
*/
exports.nodeTypeDom = function (params, context) {
if (context && context !== '') {
return $('[node-type="' + params + '"]', $('[node-type="' + context + '"]'));
} else {
return $('[node-type="' + params + '"]');
我在其余文件中须要使用这个代码段的时候,只须要像下面这样就能够了。
var baseJs = require('../libjs/base');
var node = baseJs.nodeTypeDom;
// 须要选择 dom 的地方,直接传入自定义属性的值
node('pagesecond').xxxx
除了一些经常使用的代码段这样封装,一些组件也按照这样的方式封装。好比:轮播图组件、文件上传组件、表单校验组件、tab滚动组件。
以上两种方式的好处都可以极大的提升代码的可维护性、阅读性。
Web安全
我在开发过程当中关注的Web安全主要是
sql注入
接口攻击
1.防范sql注入
sql注入简单些说就是指一些违法用户拼接一个特殊的用户名或者是密码,由于咱们要把用户名和密码插入数据库,确定会根据这个用户名和密码拼接一个sql语句。而违法用户的这个特殊用户名语句有可能删掉咱们数据库的全部数据。
由于使用的是MySQL数据库。Nodejs模块使用的也是npm上使用最多的mysql模块。自己这个模块已经提供了访问mysql集群的能力和防注入的能力。
具体方法能够参考官方文档点击这里直达
2.防范接口攻击
这里要作的就是有些违法用户拿到咱们接口的时候,写一个循环频繁的访问咱们的接口。为了防止有些违法用户就是给请求加token。就是在向服务端发起请求的时候返回给前端的一个token,前端请求后端的时候带上这个token。若是token在后端校验经过就销毁这个token 。还有好比验证请求的源IP,这里注意的是咱们验证IP的时候应该获取的是HTTP协议header字段中的x-forwarded-for属性的值。(这两种方法能够一块儿使用)
不事后来从后端RD那边了解到公司有专门的服务能够用来作反做弊,并且策略更全面些。目前在研究准备接入。
内网机器访问外网
关于跨机房访问、同机房访问和内网访问外网,这些基本上都会涉及到运维的话题。百度内部有现成的服务接入文档。各个公司可能提供能力的方式不同。这里很少介绍。
这里谈一些小的细节点。先看下面的一张图:
一句话总结:当一条请求到达接入层以前是不知道要访问内网环境下那个机房的服务器的。相反的内网的机器上若是有一条请求外网的连接,好比:http://weibo.com 。须要经过一个proxy访问外网服务器。
访问接口我使用request模块。配合promise npm上有request-promise由名字咱们就知道他的每一个方法或者是调用结果返回的是什么了。这个模块默认已经提供了代理参数的相关配置。具体的能够参考文档点击直达
这里涉及的知识比较多,好比代理隧道、https请求的代理。在阅读官方配置文档的时候搜索一些关键字了解一些其它相关知识便可。
若是有相关的需求,能够参考个人配置,若是个人配置不能解决你的问题,请仔细阅读官方文档哈。、
let options = {
'url': params.url,
'encoding': 'binary',
'rejectUnauthorized': false // 取消https证书的校验
};
// 解决代理https请求的行为 测试机须要配置环境变量 PANSHI_HTTPS_PROXY
if (process.env.PANSHI_DEBUG !== 'true' || PANSHI_HTTPS_PROXY) {
options.tunnel = false;
options.proxy = 'http://www.huazongyule.com';
发送邮件
到这里关于开发相关介绍已经完毕。这里介绍的就是运营和产品需求的一些功能开发。天天将注册的用户发送给相应的责任人。
若是要知足这个功能须要有邮件服务器。这个在公司内部有公用的能够很容易找到。其它就是配置服务的crontab定时执行脚本查询数据库发送邮件。
这里主要使用了nodejs模块nodemailer。具体的相关配置和发送邮件的方法能够参考官方文档配置点击直达
网络优化
静态文件cdn部署;
合并静态文件;
缓存静态文件;
icon使用Base64
上面列举的是比较典型的几个点。好比像css放head标签头部,script标签放到body标签底部。这些应该属于一个前端工程师的常识吧。
静态文件部署CDN这个很少介绍,每一个公司都会本身的一套方法。这里主要介绍下合并静态文件和缓存静态文件。
1.合并静态文件
默认FIS3是有插件支持合并静态文件的。由于我此次开发的页面较多(总共11个主站页面),且由于采用的分块开发加载模块和静态文件。若是不作合并的话,一个页面加载完须要有10-20条的静态文件的请求。会影响页面的加载速度。
当我准备使用FIS3的插件来合并静态文件的时候发现仍是有些麻烦的须要一个页面一个页面去配置要打包合并的静态文件。最后请教了下其它部门的同事使用咱们接入层服务器提供的comb功能,由服务器帮咱们合并静态文件(其实就是Nginx 的concat模块提供的功能)。这里也不作过多的介绍,自行搜索文章了解就能够了。
2.缓存静态文件
先来看下一张图
上图中红色框出来的都是跟静态文件缓存有关的http协议的字段。若是对这些字段的概念比较模糊能够阅读这篇文章加深下印象《HTTP缓存》点击直达
无论使用express仍是koa(koa可使用koa-static-cache中间件)都用相应的静态文件服务的中间件提供配置这几个字段的能力。express能够经过一下方式配置(具体的能够阅读express文档)
const express = www.fanku1.com require('express')
// 配置与静态文件相关的参数
express.static('xxxxx')
收获
最后就是谈谈此次开发的收获
这个项目开发上线之后,恰好到了大部门的年中总结会,由于本身独立负责了先后端的开发工做,得到了大部门的“闪耀之星”奖励和一些物质奖励(虽然还没见到影