前言

本实战为学习实践的第四个实战,延续之前的实战三使用 Webpack 进行前后端工程化开发

  • 本实战实现的是:前端开发工程化与性能优化 — 完成之前的 点赞插件的极致性能优化
  • 实战要求

image.png
image.png

  • 回顾实战三都做了些什么

image.png

  • 首先将之前的 DEMO 源代码拿过来,拖拽至 sublime 编辑器中,然后开始实战

1. 根据雅虎军规将页面 CDN 预加载等属性配置完备

  1. 首先配置 CDN 需要有些固定的方法

参考网址:DNS 预读取 | MDN

  1. 把上面的参照方法用到当前的项目中 查看项目中的 kaoweb -> src -> widget -> layout.html ,我们需要的就是把这个配置 DNS 预读取,这样可以减少这个 DNS 的解析时间,同时可以强行的使这个 DNS 可以预先获取

image.png

  1. 首先将上面的参考网址中的两段代码拿过来放到页面的 head 标签中,并进行修改 ```
  1. 4. 将上面的两行代码放到 `head` 标签中,这样就完成了第一步 DNS 预加载功能了
  2. > ![image.png](http://upload-images.jianshu.io/upload_images/9064013-ce8bb38524841597.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  3. #2. 扩展新组件星星点赞组件,首页完成直出并利用 Pjax 完成 SPA
  4. > SPA 指的是:单页Web应用(single page web applicationSPA),就是只有一张Web页面的应用,是加载单个HTML 页面并在用户与应用程序交互时动态更新该页面的Web应用程序。来自 [百度百科](https://baike.baidu.com/item/SPA/17536313?fr=aladdin)<br />
  5. ####1. 首先是:扩展新组件星星点赞组件
  6. 1. 这个是扩展星星组件,首先我们来注册星星组件,注册的方法和上一个实战的注册 **点赞组件 x-praise ** 方法是一样的
  7. - 具体的文件是 koaweb -> src -> public -> scripts -> tags.es 下面是具体的源码

//引入 index.es 文件中导出的构造方法 import PraiseButton from “./index.es”; //new 出来一个对象 const f = new PraiseButton(); //在这里注册的是 x-praise 的标签 xtag.register(‘x-praise’, { //标签内容 content: ‘

‘ + ‘
‘ + ‘
‘ + ‘
‘ + ‘
‘ + ‘
‘ + ‘+1‘, //方法 methods: { praise: function() { let _this = this; //请求接口 f.clickAction(); //执行动画 let animation = _this.querySelector(‘#animation’); animation.className = ‘hide num’; setTimeout(function() { animation.className = ‘hide’; }, 800) } }, //事件 events: { //写点击事件的稀释 click: function(e) { let _this = this; if (e.target.id = “thumb”) { let t = ‘’; if (t) { clearTimeout(t); } t = setTimeout(() => { _this.praise(); }, 500) } } } });

  1. 2. 下面用同样的方法注册一个星星的组件
  2. 2. 在与 tag.es 目录的同一个目录下新建一个 star.es 文件,将 tag.es 的源码 copy 过来再做一些修改
  3. -
  4. 这里需要自己先手写一个星星的 html css
  5. - html
  1. <div class="star">
  2. <div></div>
  3. <div></div>
  4. <div></div>
  5. <div></div>
  6. <div></div>

  1. - css 将这部分的 css 直接 copy koaweb -> src -> public -> css -> index.css 文件中
  2. > ![image.png](http://upload-images.jianshu.io/upload_images/9064013-2291b9b286102322.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  1. .star{
  2. height: 100px;
  3. width: 100px;
  4. margin: 100px auto;
  5. position: relative;
  6. }
  7. .star>div{
  8. position: absolute;
  9. left: 0;
  10. top: 0;
  11. width: 100px;
  12. height: 100px;
  13. background: yellowgreen;
  14. }
  15. .star>div:before{
  16. content: " ";
  17. display: block;
  18. position: absolute;
  19. width: 0;
  20. height: 0;
  21. border-width: 0 50px 100px 50px;
  22. border-style: solid;
  23. border-color: transparent transparent yellowgreen transparent ;
  24. left: 0;
  25. top: -100px;
  26. }
  27. .star>div:nth-child(1){
  28. transform: rotate(72deg);
  29. }
  30. .star>div:nth-child(2){
  31. transform: rotate(144deg);
  32. }
  33. .star>div:nth-child(3){
  34. transform: rotate(216deg);
  35. }
  36. .star>div:nth-child(4){
  37. transform: rotate(288deg);
  38. }
  39. .star>div:nth-child(5){
  40. transform: rotate(360deg);
  41. }
  1. -
  2. 最后 star.es 中的代码如下
  1. //引入 index.es 文件中导出的构造方法

import PraiseButton from “./index.es”; //new 出来一个对象 const f = new PraiseButton(); //在这里注册的是 x-star 的标签 xtag.register(‘x-star’, { //标签内容 content: ‘

‘+ ‘
‘+ ‘
‘+ ‘
‘+ ‘
‘+ ‘
‘+ ‘+1‘, //方法 methods: { praise: function() { let _this = this; //请求接口 f.clickAction(); //执行动画 let animation = _this.querySelector(‘#animation’); animation.className = ‘hide num’; setTimeout(function() { animation.className = ‘hide’; }, 800) } }, //事件 events: { //写点击事件的稀释 click: function(e) { let _this = this; if (e.target.id = “star”) { let t = ‘’; if (t) { clearTimeout(t); } t = setTimeout(() => { _this.praise(); }, 500) } } } });

  1. 4. 上面的已经是有了 x-star 这个组件,现在已经两个组件了,分别是上个实战中生成的 thumb 和刚做成的 star ,在 .es 文件中,通过 `import PraiseButton from "./index.es";` 继承过来,这里需要编辑这个 koaweb -> src -> public -> scripts -> index.es 文件

import css from ‘../css/index.css’; class PraiseButton { constructor() {

  1. }
  2. clickAction() {
  3. axios.get('/index/update')
  4. .then(function(response) {
  5. console.log(response);
  6. })
  7. .catch(function(error) {
  8. console.log(error);
  9. });
  10. }

}

//实战四修改的地方 //首先定义一个 Thumb 继承自上面的 PraiseButton class Thumb extends PraiseButton{ //将 PraiseButton 构造函数内的 constructor 使用 super 方法全部都继承过来 constructor(){ super(); } } //跟上面一样定义一个 Star 继承自 PraiseButton class Star extends PraiseButton{ //将 PraiseButton 构造函数内的 constructor 使用 super 方法全部都继承过来 constructor(){ super(); } }

//因为这里导出的时候有 Star 和 Thunb 所以要把这个注释掉 // export default PraiseButton;

//导出两个定义好的子类 export {Thumb,Star};

// let f = new Thumb(0,$(‘#thumb’)); // f.clickAction();

  1. 5. 接下来就要修改 tag.es star.es 中前面几行的代码了,引用以及 new 出来的实例
  2. - tag.es

//引入 index.es 文件中导出的构造方法 import {Thumb} from “./index.es”; //new 出来一个对象 const f = new Thumb();

  1. - star.es

//引入 index.es 文件中导出的构造方法 import {Star} from “./index.es”; //new 出来一个对象 const f = new Star();

  1. 6. 上面就是将 Star 组件整个的注册好了,下面需要做一个扩展:给这个 Start 组件一个单独的页面,在 koaweb -> src -> widget 文件夹下新建一个 star.html 文件,这个页面也是和 index.html 一样引用的是 layout.html 的模板,只不过是里面用的组件的标签名称不一样,
  2. - 编辑 star.html 文件

  1. 7. 写了 star.html 之后,还要有对应的 js 文件,因为我们整个的页面内容全部都是通过 koaweb -> src -> views -> webAssetsHelp.js 这个文件将页面中的 html JS 以字符串的形式将其拼接出来的,所以在 widget 中有 html 文件那么在 views 中也要他相应的 js 文件
  2. - views 文件夹下新建一个 star.js 文件,先将同目录下的 index.js 中的代码 copy 过来,再进行修改
  3. - 这里只需要修改一行代码中的 html 文件名就可以了
  4. > ![image.png](http://upload-images.jianshu.io/upload_images/9064013-3bd7ad28b17d5961.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  5. - star.js

module.exports = function(templateParams) { //vendor 是 css 的文件名称 var _cssList = [‘vendor’]; var webAssestsHelp = require(‘./webAssetsHelp.js’)(templateParams, _cssList); //拼写 star.html 代码 var _html = “{% extends ‘./layout.html’ %}” + “{% block title %}My Page{% endblock %}” + “{% block styles %}” + webAssestsHelp.styles+ “{% endblock %}” + “{% block content %}{% include ‘../widget/star.html’ %}{% endblock %}”+ “{% block script %}” + webAssestsHelp.scripts+ “{% endblock %}”; return _html; }

  1. 8. 之后需要在 koaweb -> config -> webpack.dev.js 这个开发版本使用的 js 配置文件做想应的更改,将新增的 star.html star.js 引入到配置中,
  2. - 编辑 webpack.dev.js 文件

//入口资源 entry -> tags 中新增代码 path.join(__dirname, ‘../src/public/scripts/star.es’)

//配置插件 plugins 里面新增代码 new HtmlWebpackPlugin({ filename: ‘./views/star.html’, //这里是用 js 文件拼接来生成的 html 代码 主要是引用了 layout.html 模板和 css 、js 的资源 template: path.join(dirname, ‘../src/views/star.js’), inject:false, //定义文件分发时的名称 chunks:[‘vendor’,’index’,’tags’] }), new HtmlWebpackPlugin({ filename: ‘./widget/star.html’, //这里引用的是 html 中组件标签 template: path.join(dirname, ‘../src/widget/star.html’), inject: false, })

  1. > ![image.png](http://upload-images.jianshu.io/upload_images/9064013-b1912eb6aa915ede.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)<br />
  2. ![image.png](http://upload-images.jianshu.io/upload_images/9064013-9911fba7a93443e7.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  3. - 这样星星组件就注册以及扩展成功了
  4. ####2. 接下来就是:首页完成直出并利用 Pjax 完成 SPA
  5. 1. 完成这个步骤需要用到 Pjax ,这里我用到的是 jquery.pjax
  6. > 参考网址:[http://www.bootcdn.cn/jquery.pjax/](http://www.bootcdn.cn/jquery.pjax/)<br />
  7. ![image.png](http://upload-images.jianshu.io/upload_images/9064013-dbd09ac8fe710d39.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)<br />
  8. 这个上面的是 使用方法的 跳转链接,下面的是复制资源链接的按钮
  9. - 将上面网址中的 链接复制至 koaweb -> src -> widget -> layout.html 文件中
  1. > ![image.png](http://upload-images.jianshu.io/upload_images/9064013-838b918410c472fe.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  2. - 点击上面的使用方法的按钮
  3. > 方法链接:[http://www.bootcdn.cn/jquery.pjax/readme/](http://www.bootcdn.cn/jquery.pjax/readme/)<br />
  4. 详细的方法demo:[http://www.bootcdn.cn/jquery.pjax/readme/#usage](http://www.bootcdn.cn/jquery.pjax/readme/#usage)

$(document).pjax(‘a’, ‘#pjax-container’) //上面的 a 指的是需要去做 Pjax 的链接元素,后面的参数 #pjax-container 是要去替换的内容

  1. 2. 编辑 layout,hyml 文件
  1. > ![image.png](http://upload-images.jianshu.io/upload_images/9064013-adb8c37f3c0459fd.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  2. -
  3. Pjax 的时候首先需要指定谁去做 Pjax 这里我指定的是 ,然后就是需要替换的内容
  4. -
  5. 再次编辑 layout.html 文件
  1. <!-- 这里给 href 写注册的路由,让页面可以正常的跳转过去 -->
  2. <a href="/index/star">跳转到星星</a>
  3. <a href="/index/praise">跳转到大拇指</a>
  4. <!-- 这里是需要替换的页面内容元素 -->
  5. <div id="chaneContent">
  6. {% block content %}{% endblock %}
  7. </div>
  1. > ![image.png](http://upload-images.jianshu.io/upload_images/9064013-0c5ab4e4bc3b2e02.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  2. 3. 接下来再去注册在 layout.html 页面中使用的路由
  3. - 编辑 koaweb -> src -> controller -> initController.es 文件

.get(‘/index/star’, index.star()); .get(‘/index/praise’, index.praise());

  1. > ![image.png](http://upload-images.jianshu.io/upload_images/9064013-fe5b0aeb93b6a605.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  2. 4. 再在 koaweb -> src -> controller -> indexController.es 文件中将上面 初始化路由时用到的两个方法给写下来

star(){ return async(ctx,next)=>{ //这里直接返回 star 的内容就可以了,用字符串的形式拿过来就可以了 ctx.body = ‘‘; } }, praise(){ return async(ctx,next)=>{ //这里直接返回 praise 的内容就可以了,用字符串的形式拿过来就可以了 ctx.body = ‘‘; } }

  1. 5. 到这里整个的星星组件就完成了,回顾一下
  2. - layout 中引入 pjax cdn 链接,在 body 中写了两个 a 标签:跳转至星星、跳转至大拇指,还增加了一个 id 放修改内容的容器,在 js 中实现绑定
  3. - 然后在 initController.es 文件中设置路由,再在 indexController.es 文件中定义路由方法
  4. 5. 打开命令行终端启动服务,测试是否成功
  5. - 先在打开的命令行中输入 `gulp` 编译一下文件,gulp 主要是用来编译项目中的 es 文件的,将浏览器不能识别的 .es 文件编译为 .js 文件,gulpfile.js gulp 的配置文件,在里面设置了自动检测 .es 文件的变化,并且如果发生改变会自动进行编译

cd Desktop/koaweb gulp

  1. > ![image.png](http://upload-images.jianshu.io/upload_images/9064013-56777c0c81f66154.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  2. - 接着再新建一个命令行窗口,自动监测 webpack

cd Desktop/koaweb webpack -w

  1. > ![image.png](http://upload-images.jianshu.io/upload_images/9064013-899a3f9aeab370a9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  2. - 然后还需要再开一个命令行窗口启动整个项目的服务, build 是我们整个的编译之后的代码放置的目录,上线时只需要将这个目录下的代码发布就可以了,src 目录里面是我们开发阶段所使用的项目文件夹

cd Desktop/koaweb/bulid node app

  1. > ![image.png](http://upload-images.jianshu.io/upload_images/9064013-48841d3bff9cee55.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  2. - 上面启动服务之后命令行中没有报错就证明启动成功了,这个时候就可以在浏览器中输入地址进行访问了
  3. > ![image.png](http://upload-images.jianshu.io/upload_images/9064013-183ca7e2dca9133b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  4. - 点击上面的跳转链接效果如下,可以来回的无加载式的切换,这个就是 Pjax 的效果 原理是 **pjax = pushState + ajax**
  5. > ![Animation17.gif](http://upload-images.jianshu.io/upload_images/9064013-2e9fb05b754313fe.gif?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  6. 7. 上面的示例是会出现一个 bug 的,在我 跳转至星星之后,刷新页面,会变成一个空白的页面
  7. > ![image.png](http://upload-images.jianshu.io/upload_images/9064013-b8a802b90a8fee6a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  8. - 出现上面的 bug 的因为是在 indexController.es 文件中返回的只是一个组件标签,如果是利用的 Pjax 请求的话就会将这个标签通过 JS 给嵌入到 html 中,但是如果不是 Pjax 请求的话返回的就只是一个空的组件标签其他的什么都没有,所以就需要做一个判断:是否是 Pjax 请求的,如果是的话就还是返回之前的组件标签,如果不是的话就需要渲染一个页面出来
  9. - 编辑 koaweb -> src -> controller -> indexController.es 文件

//修改两个方法

star() { return async(ctx, next) => { //判断请求是的 header中是否有 x-pjax if (ctx.request.header[‘x-pjax’]) { //有的话直接返回组件 //这里直接返回 star 的内容就可以了,用字符串的形式拿过来就可以了 ctx.body = ““; } else { //没有的话直接渲染一个页面 ctx.body = await ctx.render(‘star.html’, function() { title: ‘星星点赞’ }) } } }, praise() { return async(ctx, next) => { //判断请求是的 header中是否有 x-pjax if (ctx.request.header[‘x-pjax’]) { //有的话直接返回组件 //这里直接返回 praise 的内容就可以了,用字符串的形式拿过来就可以了 ctx.body = ““; } else { //没有的话直接渲染一个页面 ctx.body = await ctx.render(‘index.html’, function() { title: ‘大拇指点赞’ }) } } }

  1. 8. 这个时候就可以在最后一个命令行窗口中重新启动服务了

//先取消之前的启动任务 ctrl + c //再重新启动 node app.js

  1. > ![image.png](http://upload-images.jianshu.io/upload_images/9064013-8274ef5ec5aba457.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  2. 9. 这个时候再重新刷新浏览器,这个就都有了,点击跳转和刷新都能够加载出资源来,互不影响
  3. > ![image.png](http://upload-images.jianshu.io/upload_images/9064013-cd6a9560f58fe448.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  4. 10. 到上面为止, “首页完成直出并利用 Pjax 完成 SPA 的任务就完成了
  5. #3. 完成前端缓存的负载均衡操作,封装统一 ORM 库并配置离线包 manifest<br />
  6. ####1. 完成前端的负载均衡操作
  7. 1. 这个标题需要实现的效果,这里以百度官网 www.baidu.com 为例,在打开开发者工具的 Application 面板后再找到 Storage -> Local Storage 点击下面的网址会在右侧看到里面写了一个缓存的数据,如下图所示
  8. > ![image.png](http://upload-images.jianshu.io/upload_images/9064013-fc2649bac5b9002b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  9. - 他们是以键值对的形式存在的,将上面百度用的方法倒入到这个任务上就是说:我们需要在我们的 koaweb 项目中也设置我们自己 localStorage 的键值对
  10. 2. 因为我们的整个 koaweb 项目使用的是 swig 模板,又借助了 koaweb -> src -> views 中的 webAssetsHelp.js 生成的 html 页面,在这个文件里面声明了一个有多个 script 标签组成的 scripts 变量,最后将这个变量 return 了出去使得外面的 html 在页面上可以调用,styles 也用的是同样的方法
  11. > ![image.png](http://upload-images.jianshu.io/upload_images/9064013-743fe19de1f80bc4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  12. 3. 接下来修改 koaweb -> src -> public -> views -> index.js 文件,这个了里面的变量引用不需要了,先注释掉,
  13. > ![image.png](http://upload-images.jianshu.io/upload_images/9064013-2f0ef3dbb947d11f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  14. 4. 上面的注释掉是因为需要的是直接以字符串的形式进行添加,而这个字符串是通过 webAssetsHelp.js 文件 return 出来的,所以修改 webAssetsHelp.js 文件,在下图中的三处标注位置加入下面的三段代码即可
  15. > ![image.png](http://upload-images.jianshu.io/upload_images/9064013-ed706a16e4665620.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

//定义一个接收所有的以字符串形式展示 script 资源的数组 var _scriptsshow = [];

for (var i = 0; i < _regChunk.length; i++) { _scripts += ““; //循环的时候将所有的 script 字符串资源 push 进 _scriptsshow 数组中 _scriptsshow.push(“ + _files.chunks[_regChunk[i]][‘entry’] + “); }

//将 _scriptsshow 导出 scriptsshow:_scriptsshow

  1. 5. 再去编辑 index.es 文件,下面是编辑好之后的源码

module.exports = function(templateParams) { //vendor 是 css 的文件名称 var _cssList = [‘vendor’]; var webAssestsHelp = require(‘./webAssetsHelp.js’)(templateParams, _cssList);

  1. var scriptsshowStr = ``;
  2. //拼写 index.html 代码
  3. var _html = "{% extends './layout.html' %}" +
  4. "{% block title %}My Page{% endblock %}" +
  5. "{% block styles %}" +
  6. webAssestsHelp.styles +
  7. "{% endblock %}" +
  8. "{% block content %}{% include '../widget/index.html' %}{% endblock %}" +
  9. "{% block script %}" +
  10. //在这里进行判断 localStorage 要有 key 值 和 value 值
  11. //逻辑是:判断 localStorage 如果有的话就将里面的 value 拿出来然后放到 head 标签里面 这里直接就放在这个被 script 包裹的位置就可以了;如果是没有的话就去发请求,请求完之后把他放到 localStorage 里面
  12. //这里引用的 script 字符串还是通过 webAssetsHelp.js 文件传过来的
  13. //在下面定义了一立即执行函数
  14. "<script>"+
  15. "(function(){"+
  16. "var scriptsshow = ["+ webAssestsHelp.scriptsshow +"];"+
  17. "for(let i = 0;i < scriptsshow.length;i++){"+
  18. //取值 这个值其实是 script 引用的资源的具体路径名称 下面作为 localStorage 的 key 来使用
  19. "let a = scriptsshow[i];"+
  20. //判断 localStorage 里面是否有上面的值
  21. //localStorage 的用法 https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage
  22. "if(localStorage.getItem(a)){"+
  23. //如果有值的话直接将资源拼接成 script 标签追加加到 head 标签 后面,增加 id 值是为了后面的 remove 避免被资源重复加载
  24. "$('<scr'+'ipt>'+localStorage.getItem(a)+'</scr'+'ipt>').attr({type:'text/javascript',id:i}).appendTo($('head').remove('#'+i));" +
  25. "}"+
  26. "else{"+
  27. //jQuery.getScript() 函数详解 http://www.365mini.com/page/jquery_getscript.htm
  28. //jQuery.getScript()函数用于通过HTTP GET形式的加载JavaScript文件并运行它。
  29. // 该函数用于动态加载JS文件,并在全局作用域下执行文件中的JS代码。
  30. // 该函数可以加载跨域的JS文件。请注意,该函数是通过异步方式加载数据的。
  31. // 该函数属于全局jQuery对象。
  32. "$.getScript({url:a,success:function(data){localStorage.setItem(a,data)}});"+
  33. "}" +
  34. "}" +
  35. "})();"+
  36. "</script>"+
  37. // webAssestsHelp.scripts+
  38. "{% endblock %}";
  39. return _html;

}

  1. 6. 再在第二个命令行中 `webpack -w` 编译一下,在第三个命令行中启动服务 `node app.js`
  2. 6. 在浏览器中打开 http://localhost:3000/index/index,显示如下
  3. > ![image.png](http://upload-images.jianshu.io/upload_images/9064013-66102fd9ce0c9250.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  4. - 右侧页面中的 js 是通过下面的自执行函数将 js 添加至 head 标签里的
  5. 8. 打开开发者工具的 Application 面板后再找到 Storage -> Local Storage 点击下面的网址会在右侧看到里面有当前页面引用的三个 js 文件 Key 是文件的具体路径名称 Value 是其对应的源码,如下图所示
  6. > ![image.png](http://upload-images.jianshu.io/upload_images/9064013-27c60b6195731ae9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  7. 9. 这时可以查看 build -> views -> index.html 中的源码便于更好的理解,这写就是上面的 index.es 中的代码编译之后生成的
  8. > ![image.png](http://upload-images.jianshu.io/upload_images/9064013-1431c7f9ac54cf27.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  9. 10. 这样就完成了这个 **前端缓存的负载均衡操作** ,所谓的**负载均衡**实际上是一个很大的概念,主要的目的就是为了减缓服务器的压力,实现的方法可以有很多种<br />
  10. ####2. 封装统一 ORM 库
  11. 10. 什么是 ORM
  12. > 这个举例来说就是:我在程序里面写了一个对象,这个对象里面有各种各样的描述对象的信息,然后如果有好多的对象又会有好多的信息,当我拿到这个数据里的信息的时候,如果是 PHP 拿的话,他会以数据集的形式给返回来,这些描述性的信息跟我的对象并不是一一对应的,如果是想要这些描述信息和对象是一一对应的话一个个写太麻烦了,所以就做了一个 ORM 库,作为一个映射,把规则布置好,然后让他们去自动匹配就好了,这个就是他的作用
  13. 2. 接下来开始封装
  14. 2. 为了方便我们去查看,先把 koaweb -> config -> webpack.dev 文件中的 MD5 配置都先注释掉,用正常的不用 MD5 的代替

//在页面全局搜索 [hash:5] ,将搜索到的源码复制一遍 然后将之前的注释掉,再在下面粘贴,之后将粘贴出来的源码上的 [hash:5] 给删掉 即可 //一共就三处 26 行 58 行 61 行

  1. > ![image.png](http://upload-images.jianshu.io/upload_images/9064013-769fd33c124bf8f4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)<br />
  2. ![image.png](http://upload-images.jianshu.io/upload_images/9064013-47a788d4cd01b0e7.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  3. 4. 这里实现 ORM 库使用的是一个 JS 的库 LOCALFORAGE
  4. > 库的官网:[https://localforage.github.io/localForage/](https://localforage.github.io/localForage/)<br />
  5. localForage is a JavaScript library that improves the offline experience of your web app by using an asynchronous data store with a simple, localStorage-like API. It allows developers to store many types of data instead of just strings.<br />
  6. localForage includes a localStorage-backed fallback store for browsers with no IndexedDB or WebSQL support. Asynchronous storage is available in the current versions of all major browsers: Chrome, Firefox, IE, and Safari (including Safari Mobile).<br />
  7. localforage是一个JavaScript库使用异步数据存储的一个简单的提高你的Web应用程序的离线经验,localStorage API。它允许开发人员存储多种类型的数据,而不仅仅是字符串。<br />
  8. localforage包括localStorage支持后备存储浏览器不支持IndexedDBWebSQL。在所有主流浏览器的当前版本中都有异步存储:ChromeFirefoxIESafari(包括Safari Mobile)。 -- [百度翻译](http://fanyi.baidu.com/#en/zh/localForage%20is%20a%20JavaScript%20library%20that%20improves%20the%20offline%20experience%20of%20your%20web%20app%20by%20using%20an%20asynchronous%20data%20store%20with%20a%20simple%2C%20localStorage-like%20API.%20It%20allows%20developers%20to%20store%20many%20types%20of%20data%20instead%20of%20just%20strings.%0AlocalForage%20includes%20a%20localStorage-backed%20fallback%20store%20for%20browsers%20with%20no%20IndexedDB%20or%20WebSQL%20support.%20Asynchronous%20storage%20is%20available%20in%20the%20current%20versions%20of%20all%20major%20browsers%3A%20Chrome%2C%20Firefox%2C%20IE%2C%20and%20Safari%20(including%20Safari%20Mobile).)
  9. > 这个 LOCALFORAGE 和上面的 localStorage 使用方法差不多是一样的,他包含了 localStorage API ,而且他还可以对 IndexedDBWebSQL 进行处理的,这个是和 localStorage 最大的区别
  10. -
  11. 这个库的使用方法也是 getItem setItem
  12. - getItem(key, successCallback)<br />
  13. Gets an item from the storage library and supplies the result to a callback. If the key does not exist, getItem() will return null.从存储库获取一个项,并将结果提供给回调。如果该键不存在,则返回null getitem()。
  14. - setItem(key, value, successCallback)<br />
  15. Saves data to an offline store. You can store the following types of JavaScript objects:<br />
  16. 将数据保存到脱机存储区。您可以存储以下类型的JavaScript对象:
  17. > ![image.png](http://upload-images.jianshu.io/upload_images/9064013-ea003b196f9df71f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  18. -
  19. 有一个 API 需要注意一下:SETDRIVER
  20. -
  21. 这个库在那数据时的默认顺序如下:
  22. > ![image.png](http://upload-images.jianshu.io/upload_images/9064013-e5368609681d581f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  23. -
  24. 如果说不想要默认的话,就用这个方法就可以了
  25. > ![image.png](http://upload-images.jianshu.io/upload_images/9064013-89d5d4e89b4fe463.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  26. -
  27. 因为我们这里实现的也是讲数据放在 IndexDB 里,所以这个 用默认的就可以了,无需设置
  28. 5.
  29. 我们这里实现所用的示例是:在项目中放置一个广告,这个广告非常的大,这样的话如果每次都频繁的请求就直接把他放到 IndexDB 里面就可以了
  30. 5.
  31. 因为实现的是一个广告,所以直接将他放置在 layout.html 里面就可以了
  32. 5.
  33. 编辑 layout.html
  34. - 首先在页面中引入 localforage js
  35. > 资源网址:[http://www.bootcdn.cn/localforage/](http://www.bootcdn.cn/localforage/)

//将这个标签引入至页面中

  1. > ![image.png](http://upload-images.jianshu.io/upload_images/9064013-eb7a3a548e57f069.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  2. - 写脚本

//获取这个广告数据 localforage.getItem(‘advertisement’, function(err, value) { //判断如果没有就去请求再把数据存过来 if (value == null) { //1.发请求 $.ajax({ url: ‘/index/adv’, success: function(data) { //2.存 localforage.setItem(‘advertisement’, data); //页面显示查看效果 $(‘body’).append(data); } }) } else { //如果有就直接将其展示出来 $(‘body’).append(value); } });

  1. > ![image.png](http://upload-images.jianshu.io/upload_images/9064013-8d41e882a6a93b19.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  2. 8. 因为在上面请求了一个 /index/adv 的广告接口,所以就需要在 koaweb -> src -> controller 中注册这个路由并添加方法
  3. - 编辑 controller -> initController.es 文件 注册路由

_.get(‘/index/adv’, index.advertisement());

  1. > ![image.png](http://upload-images.jianshu.io/upload_images/9064013-216c3d29d8db588a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  2. - 编辑 controller -> indexController.es 文件 添加路由方法路由

advertisement() { return async(ctx, next) => { ctx.body = “

。。。。。。大幅广告。。。。
“; } }

  1. > ![image.png](http://upload-images.jianshu.io/upload_images/9064013-b13b7c85f521e1a9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  2. 9. 之后在第一个命令行中执行 `gulp` 命令 编译 es 文件,在第二个命令行中执行 `webpack -w` 编译整个项目文件,再在第三个命令行中执行 `node app.js` 启动
  3. 9. 之后再刷新浏览器查看效果
  4. - 可以看到页面中已经有这个 ”广告“
  5. > ![image.png](http://upload-images.jianshu.io/upload_images/9064013-858ce26247e34311.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  6. - 再查看右侧的 Application 面板下的 IndexDB 里面已经有了这个键值对的数据了
  7. > ![image.png](http://upload-images.jianshu.io/upload_images/9064013-89fd20d19c28089d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  8. 11. 这样这个 **封装统一 ORM 库** 就完成了
  9. 11. **拓展:**
  10. - 浏览器的 localStorage 每个域都是 5 兆的容量,如果存的数据很多超过了 5 兆的话,我们就需要想办法把这个容量扩大
  11. - 扩大的话需要用到一个库:[CROSS-STORAGE](https://github.com/zendesk/cross-storage)
  12. - CROSS-STORAGE 这个库的原理举例:<br />
  13. 比如说我们有一个 a.com b.com ,现在 a.com localStorage 容量不够了这个时候可以通过这个库去向 b.com localStorage 去借容量,实现这种跨域的操作,具体的操作是:我在 a 页面创建一个 嵌入到 b 页面里面,然后 a 页面通过 post message 格式的消息传递给 b 页面,简单来说就是 a 页面给 b 页面发送一个请求,然后 b 页面解析这个请求的信息,然后调用 b 页面里面的 localStorage API ,调用完了之后 b 页面再把这个东西给包装了,再通过 post message 的方式讲这个包装好的值再传给 a 页面,然后 a 页面再解析 b 页面传过来的这个消息,然后就得到了这个内容,最后 a 页面的 localStorage 就从原来的 5 兆扩容到了 10 兆,达到了扩容的效果,主要就是之间的消息的传递和解析
  14. ####3. 配置离线包 manifest
  15. 1. 什么是离线包
  16. > 这个意思就是说在我们没有网络的时候,依然可以将页面加载出来,比如说请求的网站的服务器爆炸了,请求页面肯定打不开了,但是如果配置了这个离线包,它就可以在访问时请求到本地缓存的离线的资源,页面就可以展示出来了
  17. 2. 配置离线包用的是 webpack-manifest 插件
  18. > 插件 npm 网址:[https://www.npmjs.com/package/webpack-manifest](https://www.npmjs.com/package/webpack-manifest)
  19. 3. 先把三个命令行中的服务都按 `ctrl + c` 给停掉,然后再新打开一个命令行窗口,依照上面的 npmjs 官网上的方法讲这个包安装到项目中

//进入项目文件夹 cd Desktop/koaweb //装包 npm i webpack-manifest —save-dev

  1. 4. 查看 npmjs 官网上的配置方法
  2. > ![image.png](http://upload-images.jianshu.io/upload_images/9064013-8f8b796ee9a1cda3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  3. - cache 需要缓存的文件
  4. - timestamp 时间戳 这个不用管
  5. - filename 这个写成默认的就可以了
  6. - network 这个是我们要绕过去,不做缓存的文件或者是连接
  7. - fallback 这个是再访问不了因特网的时候,用 404.html 文件替代项目中的所有的 html 页面
  8. - master 这个就是需要引用上面的 cache 里的缓存文件的 html 文件
  9. 5. 整个的操作时在 webpack.dev 文件中的

//在顶部引用的部分添加代码 //引用离线包插件 const Manifest= require(‘webpack-manifest’);

//在 plugins 插件配置里面添加代码 new Manifest({ cache: [ ‘../public/css/vendor.css’, ‘../public/scripts/common/vendor.min.js’, ‘../public/scripts/index.js’, ‘../public/scripts/tags.js’ ], //Add time in comments. timestamp: true, // 生成的文件名字,选填 // The generated file name, optional. filename: ‘cache.manifest’, // 注意星号前面用空格隔开 network: [ ‘http:////cdn.bootcss.com/ ‘, ‘http://localhost:35729/livereload.js‘ ], // 注意中间用空格隔开 // fallback: [‘/ /404.html’], // manifest 文件中添加注释 // Add notes to manifest file. headcomment: “koatesting”, master: [‘../build/layout.html’] })

  1. 6. 之后再第二个命令行中执行 `webpack -w` 重新编译项目文件
  2. - 编译成功之后会发现在 build 文件夹下 新增了一个 cache.manifest 文件
  3. > ![image.png](http://upload-images.jianshu.io/upload_images/9064013-76b17edc38682ed6.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  4. 7. 接下来要成功的使用这个 webpack-manifest 还有一些配置是需要添加的,还是 npmjs 官网上面说的很详细
  5. > ![image.png](http://upload-images.jianshu.io/upload_images/9064013-2a831d559d987cd0.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  6. - 一共需要三步骤
  7. - 生成 cache.manifest 文件 这个上面已经实现了
  8. - 标签加 manifest 属性,并引用manifest文件
  1. <html manifest="path/to/name-of.manifest">
  1. - Apache设置
  2. - manifestmime类型,apache下可以在httpd.conf中加上
  1. AddType text/cache-manifest manifest
  2. AddType text/cache-manifest .appcache
  1. 8. 依照上面的后面两步进行操作
  2. - 修改 layout.html 文件,给顶部的 html 标签增加属性 属性值为 manifest文件 的路径
  1. - 然后再 xampp 中的 Apache 服务的 Config -> httpd.conf 文本文件的最顶部添加两行代码

AddType text/cache-manifest manifest AddType text/cache-manifest .appcache

  1. > ![image.png](http://upload-images.jianshu.io/upload_images/9064013-78ef5208d77156bf.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  2. 9. 之后再在第二个命令行中输入 `webpack -w` ,在第三个命令行中输入 `node app.js`
  3. 9. 刷新浏览器进行预览,控制台展示如下就证明是对了
  4. > ![image.png](http://upload-images.jianshu.io/upload_images/9064013-a46f13296d7ef094.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  5. 11. 如果你在刷新页面的时候会看到控制台报了很多错误,解决方法是将下图中的 禁用缓存 按钮勾选上就 ok 了,这个时候每次刷新页面就不会有问题了
  6. > [图片上传失败...(image-eb1e46-1514106446576)]]<br />
  7. images.jianshu.io/upload_images/9064013-600739091122cf77.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  8. 12. 实际上的操作是在你首次加载完几个页面资源之后将 node 服务停掉,然后页面依旧是可以访问的,每次刷新也是没有任何问题的,因为这个项目有用到 Pjax 加载页面,这样的话资源并不是另一个页面的整个资源,所以在启动 node 服务之后,在页面点击跳转然后要把两个网址的页面都刷新一下,这个时候他才会去记录当前这个页面的缓存资源,这样关掉 node服务之后也可以随意的去刷新并跳转了
  9. > ![Animation18.gif](http://upload-images.jianshu.io/upload_images/9064013-f8818f4c770245a9.gif?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  10. 13. 上面已经是完成了 **配置离线包 manifest** 的任务了
  11. #4. 使用 Webpack 对全部静态资源优化,并能根据上线配置动态配置 CDN
  12. 1. 在配置 CDN 之前需要将上线版本依照开发版本里面 html 的配置的源码部分复制过来进行统一
  13. - 编辑 koaweb -> config -> webpack.prod.js 文件

//顶部新增引用 //引入 html 编译 模块 const HtmlWebpackPlugin = require(‘html-webpack-plugin’);

//在 plugins 插件配置中新增 new HtmlWebpackPlugin({ filename: ‘./views/layout.html’, template: path.join(dirname, ‘../src/widget/layout.html’), inject: false }), new HtmlWebpackPlugin({ filename: ‘./views/index.html’, //这里是用 js 文件拼接来生成的 html 代码 主要是引用了 layout.html 模板和 css 、js 的资源 template: path.join(dirname, ‘../src/views/index.js’), inject: false, //定义文件分发时的名称 chunks: [‘vendor’, ‘index’, ‘tags’] }), new HtmlWebpackPlugin({ filename: ‘./widget/index.html’, //这里引用的是 html 中组件标签 template: path.join(dirname, ‘../src/widget/index.html’), inject: false }), //配置插件 plugins 里面新增代码 new HtmlWebpackPlugin({ filename: ‘./views/star.html’, //这里是用 js 文件拼接来生成的 html 代码 主要是引用了 layout.html 模板和 css 、js 的资源 template: path.join(dirname, ‘../src/views/star.js’), inject: false, //定义文件分发时的名称 chunks: [‘vendor’, ‘index’, ‘tags’] }), new HtmlWebpackPlugin({ filename: ‘./widget/star.html’, //这里引用的是 html 中组件标签 template: path.join(__dirname, ‘../src/widget/star.html’), inject: false })

  1. > ![image.png](http://upload-images.jianshu.io/upload_images/9064013-732c65dcfef31bac.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)<br />
  2. ![image.png](http://upload-images.jianshu.io/upload_images/9064013-1fb48992f573401f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  3. 2. 统一之后,只需要一句配置就可以了,就是在 config 之前在 filename 里面加上服务器的 IP 地址,然后我们就可以访问这个静态资源的服务器了,这个 CDN 他放的是我们的 js css 这些静态资源文件,之前是用 webpack 编译好的,编译好了之后把编译好之后的文件放到了 public 文件夹中了,所以直接在配置时的 output 里面加上 public 的服务器的完整地址,然后就可以通过这个地址进行访问了
  4. - 编辑 webpack.prod.js 文件

//将资源输出到指定的服务器路径上一份,使得在其他地方也可以直接进行资源的访问 这个服务器这里使用的本机来模拟的 下面需要输入的 IP 地址指的就是本机的 IP 加 3000 端口 这个端口号是因为 node 的服务在这个上面,IP 地址的话我这里是 windows 环境,所以在命令行中输入 ipconfig 便可以查看到了 publicPath:’http://192.168.1.104:3000/‘,

  1. > ![image.png](http://upload-images.jianshu.io/upload_images/9064013-1373fdbad103f9a8.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  2. 3. 之后就可以在命令行中执行命令了
  3. - 在第二个命令行窗口中输入

//因为这些需要执行的是上线版本的配置所以用的是下面的命令 npm run webpackprod

  1. 4. 执行过之后去查看 koaweb -> build -> views -> index.htnl 文件,会发现所有的静态资源文件就都引用的是 “服务器” 上的地址了,是绝对路径的
  2. > ![image.png](http://upload-images.jianshu.io/upload_images/9064013-ae2689ad161734fa.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  3. 5. 接下来在第三个命令行窗口下启动 node 服务

node app.js

  1. 6. 接着再去刷新浏览器进行查看,这里有个需要注意的地方就是刷新之前需要将缓存清除掉
  2. - 这个时候可以刷新的时候在控制台中的 Network 面板下看到,除了 bootcdn 上的资源以外其余的 js css 资源就都是请求的服务器上的 CDN 资源了
  3. > ![image.png](http://upload-images.jianshu.io/upload_images/9064013-b3a931e40754184f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  4. - 下面的 livereload.js 未请求到的原因是:这个是 webpack 在自动检测的时候使用的脚本,所以需要将 webpack 的自动检测的服务启动才能够访问得到
  5. > ![image.png](http://upload-images.jianshu.io/upload_images/9064013-53374c5c7b91b9f4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  6. - 在第二个命令行中启动自动检测的服务

webpack -w

  1. - 之后再在第三个命令行中将 node 服务重新启动

//退出当前服务 ctrl + c //启动服务 node app.js

  1. - 之后再刷新页面就会看到已经请求过来了,但是这样的话访问到的就是 开发版本了,所以资源也是 localhost 的资源,而不是在上线版本中配置的 CDN 资源了,所以说这个 livereload 的问题在上线版本是不用管的,因为他主要还是为了便于我们在开发时候的使用
  2. > ![image.png](http://upload-images.jianshu.io/upload_images/9064013-f81c28c164b1b811.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  3. 7. 到了这里这个 **使用 Webpack 对全部静态资源优化,并能根据上线配置动态配置 CDN** 的任务就实现了<br />
  4. #5. lazyLoad.js 重新优化静态文件分发器,使静态资源达到并行最大化
  5. 7. 这个功能实现主要是用开发版本来进行一个测试,这个主要的就是 js 代码的逻辑了
  6. 7. 这个实现的原理是:本来项目中需要加载 index.js vender.js tags.js 这是哪个 js 文件,如果是正常的串行的加载,那么整个的加载时间就是三个文件单独的加载时间相加的总和,但是如果是并行的话,那么最终加载的时间就是三个文件中加载时间最长的那个文件的加载时间,这样就实现了静态资源并行最大化
  7. 7. 下面是具体的操作步骤
  8. 7. 首先到 bootcdn 上找到 lazyload.js 资源
  9. > 资源网址:[http://www.bootcdn.cn/lazyload/](http://www.bootcdn.cn/lazyload/)
  10. 5. 接着将上面的资源网址中的资源链接引入至 koaweb -> src -> public -> widget -> layout.html 文件中
  11. - 编辑 layout.html

//将这个资源的引用防止到资源引用的最顶部

  1. > ![image.png](http://upload-images.jianshu.io/upload_images/9064013-d68a856ff552cac0.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  2. 6. 之后查看 lazyload 的用法
  3. > 资源网址:[http://www.bootcdn.cn/lazyload/readme/#usage](http://www.bootcdn.cn/lazyload/readme/#usage)
  4. - 这里参考的是第二种用法,加载多个 js 文件
  5. > ![image.png](http://upload-images.jianshu.io/upload_images/9064013-5f1762de69cbb45f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  6. 7. 接下修改 koaweb -> src -> views -> index.js 这个拼接 index.html 的脚本文件
  7. - 这里之前的逻辑是,判断 localStorage 是否有,没有的话进行请求、成功之后在全局执行,并以键值对的形式添加至 localStorage 里面
  8. > ![image.png](http://upload-images.jianshu.io/upload_images/9064013-c6f9f83fb62fca6d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  9. - 现在实现 lazyload 的逻辑是:将这三个 js 当作一个整体,如果有的话还是和之前的一样用 script 标签将资源包起来追加到head 里面,如果没有的话这里需要进行一些修改
  10. - 没有的实现逻辑:需要先在整个自执行函数的首行增加一个哨兵变量 `var flag = false;`,在下面判断到某个资源没有就直接将 loaclStorage 中的键值对全部清除掉,将 flag 的值设置为 true,之后再将所有的资源循环出来并通过 axios 请求将资源以键值对的形式存入至 localStorage 中,再用 lazyload 进行页面并行请求 js 资源
  11. - 编辑 这个index.js 文件,先将之前的 else 注释掉再写新的 else ,之后再在 else 的后面写判断是否 使用 lazyload 加载资源

//第二次实现 lazyload 并行加载功能使用的 else “else{“+ //先将 localStorage 直接全部清除掉 “localStorage.clear();”+ //将哨兵变量设为 true 因为下面的 lazyload 需要加载资源 “flag = true;”+ //再用循环的方式给 localStorage 中增加键值对 “for (let q = 0;q < scriptsshow.length;q++) {“+ “let b = scriptsshow[q];”+ //通过 axios 以 Promise 的形式请求资源 //Axios 中文说明: https://www.kancloud.cn/yunye/axios/234845 “axios.get(b)”+ “.then(function(data){“+ “localStorage.setItem(b,data.data);”+ “})”+ “}”+ //JS break 语句解释:http://www.w3school.com.cn/js/js_break.asp //break 语句用于跳出循环 //这里的跳出循环实际上值得是最外面的第一个 for 循环,因为所有的资源都已经配置到 localStorage 中了无需再循环了 //break 语句跳出循环后,会继续执行该循环之后的代码(如果有的话):这里执行的就是下面的 lazyload 加载的代码 “break;”+

  1. "}" +
  2. //用哨兵变量进行判断是否需要 lazyload 加载资源
  3. "if(flag){"+
  4. //之后再使用 lazyload 往页面并行加载资源
  5. //lazyload 资源网址:http://www.bootcdn.cn/lazyload/
  6. //lazyload 使用方法网址:http://www.bootcdn.cn/lazyload/readme/#usage
  7. "LazyLoad.js(scriptsshow,function(){});"+
  8. "}"+
  1. - 注意这里得先将之前的 else 注释掉才可以
  2. > ![image.png](http://upload-images.jianshu.io/upload_images/9064013-921a79de86d5feda.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  3. 8. 之前再在第二、三个命令行窗口下分别启动服务

//2 webpack -w

//3
node app.js

```

  1. 之后将浏览器的缓存清除掉,再刷新浏览器
  • 可以清楚的看到三个 js 文件是并行加载的

image.png

  1. 这里会出现一个 bug 就是通过 lazyload 加载过来的 js 资源并没有像 $.getScript() 请求过来的那样自执行一遍所以,在首次执行的时候这些 js 是没有执行到的,等到再次刷新的时候因为第一次已经将资源全部都写到了 localStorage 中,然后第二次加载时就会将这些资源全部都追加到 head 标签里去
  1. 上面的 lazyLoad.js 重新优化静态文件分发器,使静态资源达到并行最大化 任务就完成了

6. 引入完整的页面监控脚本,完整分析当前页面性能瓶颈

  1. 这个就是将我们页面需要用到的 data 数据传递给我们专门的服务器,然后让他们自己去处理这个图表的东西,我们这边是需要在页面中加入一些 js 来找到我们从当前文件加载开始然后到结束的时间,然后将这个时间给到我们专门的服务器上就可以了,也就是说我们需要做的操作就是在页面中加入 js 文件,然后找到当前文件加载到结束的时间,找到这个时间之后给到我们专门的服务器,他会去做一个性能分析然后就可以了,这个较为简单就不再书写,详情可参考我的另一片文章

总结

以上就是实战四的全部的内容