减少JavaScript阻塞,提升网页加载速度与用户体验的策略

304 阅读4分钟

优化脚本位置:

将所有<script>标签放置在<body>标签的底部,紧靠</body>标签之前。这样可以确保页面在加载脚本之前已经完成渲染,从而避免阻塞页面的加载和用户交互。

减少脚本数量

通过合并多个JavaScript文件,减少页面中<script>标签的数量,从而减少HTTP请求次数。这不仅可以降低浏览器的解析负担,还能提高整体性能。

使用无阻塞加载技术

  • defer属性:为<script>标签添加defer属性,使脚本在DOM加载完成后异步执行,但不会阻塞页面渲染。
  • async属性:使用async属性标记关键代码为异步加载,确保脚本不会阻塞页面渲染。
  • 动态创建<script>元素:通过JavaScript动态创建<script>元素并插入DOM中,实现延迟加载,避免阻塞页面。

懒加载

对于非核心功能的JavaScript代码,可以采用懒加载的方式,仅在用户需要时才加载相关脚本,从而减少初始页面加载时间。

懒加载的原理:就是先在页面中把所有的图片统一使用一张占位图进行占位,把真正的路径存在元素的“data-url”(这个名字起个自己认识好记的就行)属性里,当js监听到该图片元素进入可视窗口时,即将自定义属性中的地址存储到src属性中,达到懒加载的效果

1.vue中方案:vue-lazyload插件

安装vue-lazyloa插件 (注意版本问题)

插件github地址:github.com/hilongjw/vu…

vue-lazyload 支持 Vue 1.x 和 Vue 2.x 版本,对于 Vue 3.x 版本,可以使用基于 vue-lazyload 的衍生插件,如 vue3-lazy 或 vue-lazyload-next

npm install --save vue-lazyload@1.3.3   

全局注册:main.js

// main.js 文件
import VueLazyload from 'vue-lazyload'
// Vue.use(VueLazyload) //无配置项
// 配置项
const loadimage = require('assets/img/common/loading.gif')
// const errorimage = require('assets/img/common/error.gif')
Vue.use(VueLazyload, {
  preLoad: 1.3, //预加载的宽高比
  loading: loadimage, //图片加载状态下显示的图片
  // error: errorimage, //图片加载失败时显示的图片
  attempt: 1, // 加载错误后最大尝试次数
})
// img元素上使用v-lazy="src";<img v-lazy="showImage"/>

组件使用 (通过require使用)

<img v-lazy="img" />
    
 data() {
    return {
      img: require("@/assets/img/fy.jpg"),
    };
  },

2.使用浏览器自带Api IntersectionObserver

IntersectionObserver 是一个现代浏览器提供的 JavaScript API,用于异步监测 DOM 元素与其祖先元素或视口之间的交集状态。它能够检测元素是否进入或离开视口,并提供关于交集区域的信息,如交集比例、边界框等。这种 API 在懒加载图片、滚动触发动画、广告曝光监控等场景中非常实用

IntersectionObserver 的核心功能包括:

  1. 创建观察器:通过 new IntersectionObserver() 构造函数创建一个观察器实例,并指定回调函数和配置选项。
  2. 观察目标元素:使用 observe 方法将目标元素添加到观察器中,当目标元素与视口发生交集时,回调函数会被触发。
  3. 配置选项:可以设置根元素、阈值(threshold)、偏移量(rootMargin)等参数来定制观察行为。
  4. 异步机制:IntersectionObserver 使用异步方式报告交集状态变化,不会阻塞页面渲染
 <div class="viewport" id="viewport">
    <div class="observed" id="observed" data-src="xxx"></div>
  </div>
​
let viewport = document.getElementById("viewport"); // 可视区域
let observed = document.getElementById("observed"); // 被观察元素
let options = {
  root: viewport, // 指定可视区元素
};
let IO = new IntersectionObserver(IOCallback, options); // 初始化实例
IO.observe(observed); // 开始观察// 回调函数
function IOCallback(entries, observer) {
  console.info("entries", entries);
  console.info("observer", observer);
  entries.forEach((entry) => {
    //元素进入可视区域
    if (entry.isIntersecting) {
      const img = entry.target;
      //获取元素真正的地址
      img.src = img.getAttribute("data-src");
      // 取消观察
      observer.unobserve(img);
    }
  });
}

压缩和合并JS文件

使用工具如Webpack合并多个JS文件,并进行压缩,以减少文件大小和HTTP请求次数。

使用Webpack进行压缩和合并

Vue CLI默认使用Webpack作为构建工具,可以通过配置vue.config.js来实现JS文件的压缩和合并。

步骤:

1.安装依赖

npm install compression-webpack-plugin --save-dev

2.配置vue.config.js

     const CompressionPlugin = require('compression-webpack-plugin');
     module.exports = {
       configureWebpack: {
         plugins: [
           new CompressionPlugin({
             test: /.js(?.*)?$/i, // 只处理js文件
             threshold: 10240, // 只处理大于10kb的文件
             deleteOriginalAssets: false // 是否删除源文件
           })
         ]
       },
       optimization: {
         splitChunks: {
           chunks: 'all'
         }
       }
     };

使用TerserWebpackPlugin进行压缩

TerserWebpackPlugin是Webpack中用于压缩JavaScript代码的插件,Vue CLI默认已经集成了这个插件。

  1. 配置vue.config.js
     const TerserPlugin = require('terser-webpack-plugin');
     module.exports = {
       configureWebpack: {
         optimization: {
           minimize: true,
           minimizer: [
             new TerserPlugin({
               terserOptions: {
                 compress: {
                   drop_console: true, // 删除console.log等调试语句
                   drop_debugger: true // 删除debugger语句
                 }
               }
             })
           ]
         }
       }
     };

缓存策略

合理利用浏览器缓存,设置HTTP响应头中的缓存控制指令(如Cache-ControlExpires),以减少重复请求。

使用CDN

将静态资源部署到CDN上,以减少延迟并提高加载速度。

性能监测与优化

定期使用性能分析工具(如Chrome DevTools)检测瓶颈,分析网络请求和JavaScript执行时间,找到并优化性能瓶颈。

通过以上方法,可以有效减少因JS过多而导致的请求阻塞问题,提升网页的加载速度和用户体验。