引入外部js脚本加载慢与页面白屏问题的解决


Posted in Javascript onDecember 10, 2018

问题背景

最近做的一个项目需要引入一个外部的第三方js脚本。由于这是一个关于渲染3D建筑的脚本,所以体积比较大,大概有2M,加载完成也得要个好几秒,网速慢的时候十几秒都有可能。

之前也遇到脚本加载慢的问题,但是没这么慢,所以这次就特别写个文章记录一下我的解决过程。

首先上两张项目已完成的截图。

下图是通过第三方脚本渲染出来的3D建筑页面

引入外部js脚本加载慢与页面白屏问题的解决

下图是首页,不需要用到第三方脚本

引入外部js脚本加载慢与页面白屏问题的解决

遇到的问题和需求

  • 引入外部脚本太大,加载时间太长
  • 首页用不到外部脚本,需要先渲染出来
  • 用到外部脚本的页面,要是脚本还没加载好就点进去会报错

解决问题的过程

我一开始通过<script>标签直接引入到入口文件的头部,如下

<head>
<script src="./DDEarth.js"></script>
</head>

这样页面是可以正常加载的,但是页面出来的很慢,一开始会白屏一段时间等待这个js脚本加载完成。虽然脚本体积大是事实,但这用户体验肯定是可以优化的。

后来我又把这个脚本放到了页面底部,也就是</body>标签下面。这样可以先让页面渲染出来,再慢慢加载这个庞大的脚本,于是首页是出来的很快,但是从首页跳转到需要用到这个脚本的页面就会报错,如下

引入外部js脚本加载慢与页面白屏问题的解决

这个错误原因是这个页面需要用到window.DDEarth这个对象,但是由于此时这个脚本还没有加载完成,所以window下并没有这个对象,所以就报错了。

于是我又想到等脚本加载完成再执行相关方法,这时就需要用到onload这个方法了,onload这个方法在脚本加载完成的时候会执行。我引入脚本的时候给它加了个id,方便以后通过dom找到,代码如下:

// 入口文件
 </body>
 <script id="ddEarthScript" src="./DDEarth.js"></script>

// PageTwo.js
componentDidMount() {
   const scriptEle = document.getElementById('ddEarthScript'); // 找到脚本节点
   if (scriptEle) {
    scriptEle.onload = () => {
      // 脚本加载完成执行加载地图的操作
     this.loadEarthMap();
    };
   }
 }

有了以上代码我跳转到PageTwo这个页面的时候,会等到DDEarth.js这个脚本加载完成,再执行加载建筑地图的操作,这样就不会报错了。

但是这又有一个问题,就是如果我跳转到PageTwo的之前,DDEarth.js已经加载完成了,onload这个事件在PageTwo这个页面中就不生效了,loadEarthMap这个方法自然也就不会执行了。

这个时候需要加一个判断,完整代码如下:

// PageTwo.js
componentDidMount() {
  if (window.DDEarth) { // 如果跳转到此页面之前,脚本已加载完成
   this.loadEarthMap();
  } else {
  const scriptEle = document.getElementById('ddEarthScript');
  if (scriptEle) {
   scriptEle.onload = () => {
    this.loadEarthMap();
   };
  }
  }
 }

总结一下我以上解决问题的步骤

在入口文件的底部引入第三方脚本,并给它加个id。当然也可以放在<head>里,但是需要额外加上html5新增的 async 这个属性,这样脚本才能异步加载。

在需要用到这个脚本的页面,先判断脚本有没有加载完成(我这里是直接判断window.DDEarth对象是否为空)。如果已经加载完成,就直接执行相关操作;如果没有,先通过document.getElementById找到那个脚本,然后监听脚本的onload事件,再做相关操作。

什么情况可以用我以上思路?

  • 引入的第三方脚本较大,加载所需时间较长
  • 页面按需加载,整个项目只有其中某几个页面需要用到引入的第三方脚本
  • 第三方脚本没加载完就渲染页面导致的页面报错

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
js实现有过渡渐变效果的图片轮播相册(兼容IE,ff)
Jan 19 Javascript
javascript插件开发的一些感想和心得
Feb 28 Javascript
JS实现获取当前URL和来源URL的方法
Aug 24 Javascript
简易的JS计算器实现代码
Oct 18 Javascript
浅析bootstrap原理及优缺点
Mar 19 Javascript
javaScript之split与join的区别(详解)
Nov 08 Javascript
vue对storejs获取的数据进行处理时遇到的几种问题小结
Mar 20 Javascript
小程序关于请求同步的总结
May 05 Javascript
layui监听单元格编辑前后交互的例子
Sep 16 Javascript
js和jquery判断数据类型的4种方法总结
Aug 28 jQuery
解决vue2中使用elementUi打包报错的问题
Sep 22 Javascript
Openlayers+EasyUI Tree动态实现图层控制
Sep 28 Javascript
JQuery Ajax执行跨域请求数据的解决方案
Dec 10 #jQuery
发布Angular应用至生产环境的方法
Dec 10 #Javascript
webpack优化的深入理解
Dec 10 #Javascript
BootStrap模态框闪退问题实例代码详解
Dec 10 #Javascript
详解为生产环境编译Angular2应用的方法
Dec 10 #Javascript
深入理解Vue.js轻量高效的前端组件化方案
Dec 10 #Javascript
es6基础学习之解构赋值
Dec 10 #Javascript
You might like
php的array数组和使用实例简明教程(容易理解)
2014/03/20 PHP
ThinkPHP查询中的魔术方法简述
2014/06/25 PHP
分享php代码将360浏览器导出的favdb的sqlite数据库文件转换为html
2015/12/09 PHP
PHP的mysqli_thread_id()函数讲解
2019/01/24 PHP
one.php 多项目、函数库、类库 统一为一个版本的方法
2020/08/24 PHP
js控制input框只读实现示例
2014/01/20 Javascript
jQuery如何获取同一个类标签的所有值(默认无法获取)
2014/09/25 Javascript
vue.js初学入门教程(1)
2016/11/03 Javascript
jquery html5 视频播放控制代码
2016/11/06 Javascript
easyui取消表单实时验证,提交时统一验证的简单实例
2016/11/07 Javascript
使用vue.js2.0 + ElementUI开发后台管理系统详细教程(二)
2017/01/21 Javascript
Node调用Java的示例代码
2017/09/20 Javascript
js代码规范之Eslint安装与配置详解
2018/09/08 Javascript
layUI实现三级导航菜单效果
2019/07/26 Javascript
小程序实现上下移动切换位置
2019/09/23 Javascript
浅析vue中的provide / inject 有什么用处
2019/11/10 Javascript
解决echarts echarts数据动态更新和dataZoom被重置问题
2020/07/20 Javascript
[01:37]全新的一集《真视界》——TI7总决赛
2017/09/21 DOTA
[55:44]OG vs NAVI 2019国际邀请赛小组赛 BO2 第一场 8.15
2019/08/17 DOTA
在Python中操作字典之setdefault()方法的使用
2015/05/21 Python
python网络爬虫之如何伪装逃过反爬虫程序的方法
2017/11/23 Python
Python实现定制自动化业务流量报表周报功能【XlsxWriter模块】
2019/03/11 Python
Django模板标签{% for %}循环,获取制定条数据实例
2020/05/14 Python
Python使用plt.boxplot() 参数绘制箱线图
2020/06/04 Python
PyCharm最新激活码PyCharm2020.2.3有效
2020/11/18 Python
Python接口自动化测试框架运行原理及流程
2020/11/30 Python
浅析css3中matrix函数的使用
2016/06/06 HTML / CSS
Hello Molly美国:女性时尚在线
2019/08/26 全球购物
C#中类(class)与结构(struct)的异同
2013/11/03 面试题
如何开发安全的AJAX应用
2014/03/26 面试题
商务英语大学生职业生涯规划书范文
2014/01/01 职场文书
大学生自我评价范文分享
2014/02/21 职场文书
教学质量评估实施方案
2014/03/17 职场文书
党员一句话承诺大全
2014/03/28 职场文书
mysql 8.0.24版本安装配置方法图文教程
2021/05/12 MySQL
css弧边选项卡的项目实践
2023/05/07 HTML / CSS