@yacent
2016-10-21T17:25:46.000000Z
字数 3260
阅读 831
面试
课程查询网站
介绍:课程评课网站主要适用于给同学们解决选课困难的问题,在每学期开学的时候,同学都会面临选课困难,会纠结于什么课比较好,给分如何等问题。但是我们又没有别的渠道,除了问上过这个课程的人,所以做了一个课程评价查询的网站。
那么,这个课程查询网站从功能上来说,
第一,首页是一个搜索框,支持实时搜索提示以及拼音搜索,可供用户进行相对应课程的搜索,
第二,用户查看相关课程的评价,课程详情页包括课程的相关信息以及评价,同时用户可为某项课程添加评论并打分。
第三,用户可添加不存在的课程。
技术栈使用,前端在pc端主要是裸写,因为觉得控件不是特别多,裸写比较快,移动端主要用了frozenUI,后端使用的是python的tonardo框架。然后使用grunt 来进行项目构建,监听等。
项目大致情况是这样。
有没有遇到什么困难?怎么解决的?
问题1:
浏览器渲染过程
css优化
雅虎军规
模块加载
XSS攻击
是在开发过程中遇到了这样一个问题,当时在一个js脚本文件当中,因为写了一个长时间运行的函数,而导致在pc端打开页面的时候,页面出现了2-3s的页面空白时间,一开始我以为是网速慢,可是某次,我在没有加载js文件的前提下,发现页面瞬间就出来了,这让我很疑惑,感觉不太像是网速慢的原因,这让我觉得是因为js文件的原因了,所以我去寻找原因,在google上面查找相关问题的描述,在一篇文章当中,寻找到了 js阻塞页面渲染 这段关键词,就顺着这个继续寻找下去了。后来通过学习和阅读 HTML文档的加载顺序 以及 浏览器渲染过程 了解到了真正的原因,是因为自己将script标签放置在了head标签头部,而由于浏览器的同步模型,在遇到script标签的时候,会阻塞后面的渲染,等待脚本文件下载、解析和执行完毕,才会继续向下渲染,所以原来出现了2-3s的空白,正是因为脚本的位置的原因以及脚本当中的长时间处理函数而导致的页面无法继续渲染而出现短暂的空白。再结合浏览器渲染过程,等待js文件下载解析执行完毕的原因,是因为js脚本有可能改变DOM结构,所以在js脚本执行完整之前,前面所渲染出来的DOM结构有可能都是没有意义,所以浏览器会等js脚本执行完毕,再继续向下渲染DOM。
在学习了这个之后,我的解决办法就是,将script标签放置在body的底部,在这之后,发现,就是虽然onload事件的完成时间虽然没有太大变化,但是domComplete的时间比原来快了很多,这也说明了js脚本放在head当中会对页面渲染造成阻塞。然后函数当中的长时间运行函数,我也是使用了setTimeout去处理,首先js引擎是单线程的,如果放在js文件当中,他必须是要讲这个长时间函数执行完毕,才会继续向下执行其余的代码,在学习探讨过程中,有了解到浏览器的常驻线程,即有setTimeout,即用了类似于多线程的思想,使用setTimeout,让复杂计算在另外一个线程当中计算,计算完毕,根据JS的运行机制,会在计算完毕之后,告诉主栈队列,已准备完毕,请求操作,这样可以实现脚本的快速执行。
【可以顺带说说 HTML文档的解析 DTD 和 树的构建过程】
【减少 repaint和reflow】
【CSS优化】
后来,一开始写这个的时候,一直都是用这jquery的方式进行函数式的编程,通过函数进行调用,后来学习到了模块化的思想,于是尝试使用模块化的思想进行代码的编写,在这个项目当中,比如对于课程的查询模块,单独一个文件出来,里面实现了对于课程查询的处理的相关业务逻辑,只暴露出相关的特权函数进行使用。但是,拆分出来之后,发现在body的底部,瞬间多了很多的js脚本文件的引用,就jqeury的,然后又查询模块的,然后添加评论模块的等等,会发现加载过程中,虽然页面出现时没有什么问题的,但是会发现页面加载时间太久,就是等待所有脚本加载完成时间太久,而且会发现文件与文件之间的顺序太重要了,如果调换了某一个顺序,有可能后面的就出错了,这是依赖性的问题。之后,查找模块化,发现自己还漏了一个很重要的东西,就是loader,虽然模块化实现了封装性,但是加载的便利性还是没有解决,了解到AMD、CMD这两种loader,也是挺方便的,不仅解决了页面加载时间过程的问题,因为他们是通过异步加载脚本的方式进行,又解决了脚本直接的依赖性问题。模块加载器很好的解决了上面的问题,也因此学习到了AMD和CMD规范和模块加载。
这是这个项目当中遇到的比较大的问题了,在完成了之后,也继续学了性能优化,比如css优化的方式,页面的一些优化方式以及js当中的一些优化手段。在之后的实践当中,也有尝试将优化的方法用到其中。
问题2:
网站刚上线,让师兄帮忙看了看网站,提一些建议,他就写了一段脚本,把我网站给攻击了,因为课程详情页当中有一个评论框,当时是没有做任何限制的,从而师兄直接写了一段脚本,不断地乱输入内容并提交,导致数据瞬间爆炸,一开始并不知道是怎么回事,只能从后台管理系统当中,将数据删除掉,但是删除的速度永远比不上脚本的速度,打算是解决这个问题,想着是使用验证码的方式吧,因为现在是没有验证码的,只要有内容,并且点击了提交按钮就可以了。这个点多亏是后台同学以前自己写过验证码的实现,所以很快的复用进来了,前端主要在获取到验证码的时候,首先判断用户输入的验证码,验证码值已由后台返回到前端当中,只需要判断该值是否与用户输入相等。后台会返回一小段该验证码的散列值,将该值连同数据一起发送,后台接收到之后,将该散列值相对应的图片删除,保证验证码只能使用一次。
后来师兄停止了使用脚本攻击,而是在评论框中写了一小段代码,点击的时候,不断触发alert,这也导致了我页面的直接的崩溃。我求助于他是什么原因,他告诉我去学习一下XSS攻击,后来知道XSS攻击,就是恶意攻击者往Web页面里插入恶意html代码,当用户浏览该页之时,嵌入的恶意html代码会被执行,从而达到恶意用户的特殊目的。我也学习到了一些防御的方法,最为简单的就是对输入的内容进行转义,对标签等的符号转换为html实体字符。我再其中也是用了这种方式进行的,对输入的内容进行转义。了解到的还有一些其他的方式,比如是使用白名单过滤,即首先根据用户输入的内容,构建出抽象语法树,然后通过所规定的白名单,从中抽取出相应的元素,构建出一个新的树,再加入到DOM当中。
【顺带学习了 CSRF攻击! 令牌、验证码、referrer等】
问题3:
有,比如我在实现搜索的时候,一开始是只支持中文搜索,拼音搜索只会返回无该课程,后觉得应该实现一个拼音搜索。但是一开始的话,没有什么什么头绪,想着去某些有类似功能的网站看看别人是怎么实现的,查阅了一些博客后,觉得目前这个功能实现,如果要自己写的话,还是挺困难的,所以我想能不能使用别人已经写好的库,我就去google 查询相关的知识,但是一开始如何精准地定位到我要的东西,就进行了一个模糊查询,然后在某篇博客上,看到了把中文转拼音的方法,我就去看,然后使用了别人写的python 库,对自己已有的课程数据进行操作,在每条记录当中添加一个表项,它是一个数组,其中存储了对于课程名字每个字的拼音。对自己课程拼音初始化完,我再去找如何实现输入框中输入拼音进行匹配。我又去翻了一些博客,在一篇博客上,看到了分词的方法,其中有提到结巴分词,然后博主自己也有实现一个分词的代码,我去找了一下结巴,但是觉得没有博主写的简单,就采用博主的方式。实现的方法主要是在搜索框中输入了拼音串,然后整串都传到后台进行处理,后台主要是通过正则表达式进行相应的分词,切成字的拼音,然后组合后再进行查询,返回数据给前端。但是这个一开始做了之后,发现有时候会出现毛病,比如输入pingen ,分词到底是分成ping en 还是pinggen,这会影响搜索结果,但我想不到好的办法,就两种都分,然后分别查询,有一个查询得到就返回,两个查询都没有结果才返回无该课程。