优化专题

363 阅读21分钟

性能优化方案

网络方面

  • 减少网络延迟:网络延迟是指数据包从发送端到接收端所需的时间。减少网络延迟可以提高网络的响应速度和传输效率。一些减少网络延迟的方法包括:
    • 二进制
    • 使用CDN:将网站的内容缓存在分布式服务器上,减少网络延迟。
    • 使用HTTP/2:HTTP/2采用多路复用技术,可以同时传输多个请求和响应,减少网络延迟。
    • 压缩数据:压缩传输的数据可以减少传输时间和网络延迟。
  • 减少网络跳数:减少网络跳数可以减少数据包传输的时间和延迟。
    • 增加带宽:增加带宽可以提高网络的传输速度和吞吐量。一些增加带宽的方法包括:
    • 使用多个网络接口:使用多个网络接口可以提高网络的带宽。
    • 使用负载均衡器:负载均衡器可以将网络流量分配到多个服务器上,提高网络的带宽。
    • 使用高速网络:使用高速网络可以提高网络的带宽和传输速度。
  • 优化网络拓扑结构:优化网络拓扑结构可以提高网络的可靠性和传输效率。一些优化网络拓扑结构的方法包括:
    • 使用高可用性技术:使用高可用性技术可以保证网络的可靠性和可用性。
    • 使用负载均衡器:负载均衡器可以将网络流量分配到多个服务器上,提高网络的可靠性和可用性。
    • 使用冗余网络:使用冗余网络可以提高网络的可靠性和容错能力。
  • 优化协议和算法:优化协议和算法可以提高网络的传输效率和性能。一些优化协议和算法的方法包括:
    • 使用TCP/IP协议:TCP/IP协议是互联网最常用的协议,可以提高网络的传输效率和性能。
    • 使用流控制算法:流控制算法可以根据网络的状况调整传输速度,提高网络的传输效率和性能。
    • 使用数据包分片技术:数据包分片技术可以将大的数据包分成小的数据包传输,提高网络的传输效率和性能。
    • 粘包 拥塞控制 超时快恢复
  • 减少HTTP请求数,合并JS、CSS,合理内嵌CSS、JS
  • 合理设置服务端缓存,提高服务器处理速度。 (强制缓存、对比缓存)
  • 避免重定向,重定向会降低响应速度 (301,302)
  • 使用dns-prefetch,进行DNS预解析
  • 采用域名分片技术,将资源放到不同的域名下。接触同一个域名最多处理6个TCP链接问题。
  • gzip压缩优化 对传输资源进行体积压缩 (html,js,css)
  • 加载数据优先级 : preload(预先请求当前页面需要的资源) prefetch(将来页面中使用的资源) 将数据缓存到HTTP缓存中

浏览器方面

  • 减少HTTP请求数量:HTTP请求数量过多会导致浏览器性能下降,影响页面加载速度。一些减少HTTP请求数量的方法包括:
    • 合并CSS和JavaScript文件:将多个CSS和JavaScript文件合并成一个文件可以减少HTTP请求数量。
    • 使用CSS Sprites:将多张小图片合并成一张大图片,通过CSS进行定位,可以减少HTTP请求数量。
    • 使用缓存:浏览器缓存可以减少HTTP请求数量,提高页面加载速度。
  • 优化图片:图片占用了大量的网络带宽和浏览器内存,对性能的影响比较大。一些优化图片的方法包括:
    • 压缩图片:使用图片压缩工具可以减小图片的大小,减少网络带宽的消耗。
    • 使用合适的图片格式:不同的图片格式有不同的压缩效果和透明度支持,根据图片的实际需求选择合适的图片格式可以减少图片的大小。
    • 使用懒加载技术:使用懒加载技术可以延迟图片的加载,提高页面加载速度。
  • 减少DOM操作:DOM操作会引起浏览器的重新渲染和重绘,对性能的影响比较大。一些减少DOM操作的方法包括:
    • 批量修改DOM元素:将多个DOM操作合并成一次操作,可以减少浏览器的重绘和重新渲染。
    • 使用文档碎片:使用文档碎片可以减少DOM元素的插入和删除操作,提高页面渲染速度。
    • 使用虚拟DOM技术:使用虚拟DOM技术可以减少DOM操作和页面的重绘和重新渲染,提高页面渲染速度。
  • 使用缓存:使用缓存可以减少页面的加载时间和HTTP请求数量,提高页面的性能和响应速度。
  • 延迟加载资源:将页面的资源延迟加载可以提高页面的响应速度和性能。
  • 压缩JavaScript和CSS文件:压缩JavaScript和CSS文件可以减少文件大小,提高页面加载速度。
  • JavaScript强制将计算样式和布局操作提前到当前的任务中 app.offsetHeight 调用就会强制提前
  • 脱离文档流
  • 渲染时给图片增加固定宽高
  • 尽量使用css3 动画
  • 可以使用will-change提取到单独的图层中

js方面

  • 使用局部变量:访问局部变量比全局变量更快,因为局部变量存储在栈中,而全局变量存储在堆中。所以,尽量使用局部变量来存储需要多次访问的数据。
  • 避免使用 with 语句:with 语句会导致 JavaScript 引擎需要在执行期间进行额外的查找,降低了代码的性能。因此,应该尽量避免使用 with 语句。
  • 避免使用 eval 函数:eval 函数会将字符串转换为可执行的代码,这会降低代码的性能,并且也有安全风险。因此,尽量避免使用 eval 函数。
  • 使用原生的 JavaScript 方法:原生的 JavaScript 方法比自定义的方法执行得更快,因此在编写代码时尽量使用原生的方法,如使用内置的数组方法,而不是自定义的循环方法。
  • 使用事件委托:事件委托可以减少事件绑定的次数,提高页面的性能。例如,使用事件委托来处理列表中的点击事件,而不是在每个列表项上都绑定一个点击事件。
  • 避免频繁的 DOM 操作:DOM 操作是非常耗费性能的,因此应该尽量避免频繁的 DOM 操作。例如,在循环中避免频繁的修改 DOM,而是将所有的修改放到循环结束后一次性进行。
  • 使用缓存:使用缓存可以避免重复计算和网络请求,提高代码的性能。例如,缓存页面的 DOM 元素和计算结果,避免重复查询和计算。
  • 使用节流和防抖:使用节流和防抖可以减少事件触发的次数,提高页面的性能。例如,在页面滚动时使用节流来减少事件的触发次数。
  • 使用 Web Worker:Web Worker 可以在后台执行 JavaScript 代码,不会阻塞主线程的执行,从而提高页面的性能。例如,可以使用 Web Worker 来执行复杂的计算任务,而不会阻塞用户界面的响应。
  • 压缩 JavaScript 文件:压缩 JavaScript 文件可以减小文件的大小,从而提高页面的加载速度。例如,使用工具如 UglifyJS 来压缩 JavaScript 文件。
  • 少用全局变量
  • 通过原型新增方法
  • 尽量创建对象一次搞定
    • V8会为每个对象分配一个隐藏类,如果对象结构发生改变就会重建隐藏类,结构相同的对象会共且隐藏类
    • 隐藏类描述了对象的结构和属性偏移地址,可以加速查找属性的时间
    • 优化指南
      • 创建对象尽量保持属性顺序一致
      • 尽量不要动态添加和删除属性
  • 尽量保持参数结构稳定 参数数据类型一致

静态资源方面

  • 使用 CDN:CDN(内容分发网络)可以将静态资源分发到离用户更近的服务器,从而加速资源加载速度,提高网站性能。

  • 压缩文件:压缩静态资源文件可以减小文件大小,从而加快资源加载速度。例如,使用工具如 Gzip 压缩静态资源文件。

  • 使用缓存:使用缓存可以避免重复的网络请求,提高网站性能。可以在服务器端设置缓存策略,或者使用浏览器缓存来缓存静态资源文件。

  • 减少请求次数:减少静态资源的请求次数可以提高网站性能。可以将多个小文件合并为一个大文件,或者使用 CSS Sprites 技术来将多个小图片合并为一个大图片,从而减少请求次数。

  • 延迟加载:将静态资源的加载时间延迟到用户需要时再进行加载,可以减少初始页面的加载时间,提高网站性能。例如,使用 lazyload.js 技术来实现图片的延迟加载。

  • 使用适当的图片格式:使用适当的图片格式可以减小文件大小,从而加快资源加载速度。例如,对于图像类的静态资源,可以使用 JPEG 格式来减小文件大小,对于图标类的静态资源,可以使用 SVG 格式来减小文件大小。

  • 使用预加载:在用户浏览到相关内容之前预先加载静态资源,可以加速用户浏览速度。例如,使用 rel="preload" 属性来预加载资源。

  • 图片优化

    • 图片格式
      • jpg:适合色彩丰富的照片、banner图;不适合图形文字、图标(纹理边缘有锯齿),不支持透明度
      • png:适合纯色、透明、图标,支持半透明;不适合色彩丰富图片,因为无损存储会导致存储体积大
      • gif:适合动画,可以动的图标;不支持半透明,不适和存储彩色图片
      • webp:适合半透明图片,可以保证图片质量和较小的体积
      • svg格式图片:相比于jpg和jpg它的体积更小,渲染成本过高,适合小且色彩单一的图标;
    • 避免空的src
    • 减小图片尺寸,节约用户流量
    • img标签设置alt属性 提高图片加载失败的用户体验
    • 原生的loading:lazy 图片懒加载
    • 不同环境下,加载不同尺寸和像素的图片 sizes属性
    • 对于较大的图片可以考虑采用渐进式图片
    • 采用base64URL减少图片请求
    • 采用雪碧图合并图标图片等
    • 推迟加载屏幕外图片
  • HTML优化

    • 语义化
    • 减少HTML嵌套关系、减少DOM节点数量
    • 删除多余空格、空行、注释、及无用的属性等
    • HTML减少iframes使用 (iframe会阻塞onload事件可以动态加载iframe)
    • 避免使用table布局
  • css优化

    • 减少伪类选择器、减少样式层数、减少使用通配符
    • 避免使用CSS表达式,CSS表达式会频繁求值, 当滚动页面,或者移动鼠标时都会重新计算
    • 删除空行、注释、减少无意义的单位、css进行压缩
    • 使用外链css,可以对CSS进行缓存
    • 添加媒体字段,只加载有效的css文件
    • CSS contain属性,将元素进行隔离
    • 减少@import使用,由于@import采用的是串行加载
    • 减少未使用的 CSS
  • js优化

    • 通过async、defer异步加载文件
    • 减少DOM操作,缓存访问过的元素
    • 操作不直接应用到DOM上,而应用到虚拟DOM上。最后一次性的应用到DOM上。
    • 使用webworker解决程序阻塞问题
    • IntersectionObserver
    • 虚拟滚动 vertual-scroll-list
    • requestAnimationFrame、requestIdleCallback
    • 浏览器生命周期
    • 尽量避免使用eval, 消耗时间久
    • 使用事件委托,减少事件绑定个数。
    • 尽量使用canvas动画、CSS动画
    • 减少未使用的 JavaScript
    • 移除阻塞渲染的资源 资源阻止了系统对您网页的首次渲染。建议以内嵌方式提供关键的 JS/CSS,并推迟提供所有非关键的 JS/样式
    • 使用视频格式提供动画内容 使用大型 GIF 提供动画内容会导致效率低下。改用 MPEG4/WebM 视频(来提供动画)和 PNG/WebP(来提供静态图片)以减少网络活动消耗的字节数
    • 应避免向新型浏览器提供旧版JavaScript Polyfill 和 transform 让旧版浏览器能够使用新的 JavaScript 功能。不过,其中的很多函数对新型浏览器而言并非必需。对于打包的 JavaScript,请采用现代脚本部署策略,以便利用 module/nomodule 功能检测机制来减少传送到新型浏览器的代码量,同时保留对旧版浏览器的支持
    • unload事件监听器改用pagehide或visibilitychange事件 unload事件不会可靠地触发,而且监听该事件可能会妨碍系统实施“往返缓存”之类的浏览器优化策略
    • 请移除 JavaScript 软件包中的重复模块

webpack方面

  • 减小打包体积:减小打包体积可以加快资源加载速度,提高网站性能。可以使用 Tree Shaking 技术来删除未使用的代码,或者使用 Code Splitting 技术来拆分代码,从而减小打包体积。

  • 使用生产模式:在 Webpack 中使用生产模式可以启用代码压缩、删除未使用的代码和其他优化功能,从而提高打包性能。

  • 使用缓存:使用缓存可以避免重复的打包过程,提高打包性能。可以使用 Webpack 的缓存功能来缓存打包过程中的中间文件,或者使用缓存插件如 hard-source-webpack-plugin 来缓存模块和 chunks。

  • 使用多线程:在 Webpack 中使用多线程可以提高打包性能。可以使用 loader 插件如 thread-loader 来在打包过程中启用多线程,或者使用 parallel-webpack 插件来将多个 Webpack 进程并行执行。

  • 优化 loader:优化 loader 可以提高打包性能。可以使用 HappyPack 插件来在多个进程中并行执行 loader,或者使用 babel-loader-cache-threshold 插件来缓存 babel-loader 运行结果。

  • 使用分析工具:使用分析工具可以找出打包过程中的性能瓶颈,从而进行优化。可以使用 Webpack Bundle Analyzer 插件来分析打包结果,或者使用 Speed Measure Plugin 插件来测量打包过程中的时间和空间占用。

  • 使用 DllPlugin:DllPlugin 可以将常用的库打包成单独的文件,并使用缓存来避免重复打包。这可以减小打包体积并提高打包性能。可以使用 Webpack 的 DllPlugin 插件来实现此功能。

  • 缩小范围 resolve

    • extensions 指定 extension 之后可以不用在 require 或是 import 的时候加文件扩展名,会依次尝试添加扩展名进行匹配
    • alias 配置别名用来加快 webpack 查找模块的速度
    • modules 对于直接声明依赖名的模块(如 react ),webpack 会类似 Node.js 一样进行路径搜索 如果可以确定项目内所有的第三方依赖模块都是在项目根目录下的 node_modules 中的话可以指定 modules: [path.resolve(__dirname, 'node_modules')],
    • mainFields 当从 npm 导入模块时 此选项将决定在 package.json 中使用哪个字段导入模块
    • mainFiles 目录中没有 package.json 默认使用目录下的 index.js 这个文件
    • resolveLoader 解析 loader 时的 resolve 配置
  • noParse module.noParse 字段,可以用于配置哪些模块文件的内容不需要进行解析

    • 基本用在第三方大型类库 且没有依赖 可以通过这个字段配置 以提高整体的构建速度
    • 使用 noParse 的模块内部不用有 import require define 等导入机制
  • IgnorePlugin 用于忽略某些特定的模块,让 webpack 不把这些指定的模块打包进去

    // 插件
    new webpack.IgnorePlugin({
      //匹配引入模块路径的正则表达式
      contextRegExp: /moment$/,
      //匹配模块的对应上下文,即所在目录名
      resourceRegExp: /^\.\/locale/,
    });
    
  • 费时检查 webpack-bundle-analyzer 生成代码分析报告 查看代码体积

  • output 的 libraryTarget 和 library

    • 当使用 webpack 构建一个可以被其他模块导入的库时需要使用他们
    • libraryTarget 的类型
      • var 默认类型 只能通过 script 标签来引入
      • commonjs 只能按照 commonjs 规范导入
      • commonjs2 只能通过 commonjs2 规范导入
      • amd 只能按照 amd 规范导入
      • umd 可以通过 script commonjs amd 引入
  • 单独提取 css mini-css-extract-plugin

    • 指定目录
      new MiniCssExtractPlugin({
        filename: 'css/[name].css'
      }),
    
  • 压缩和优化 css、js、html 资源

    • css 压缩 optimize-css-assets-webpack-plugin 是一个优化和压缩 CSS 资源的插件
    • js 压缩 optimization.minimizer 覆盖 webpack 的默认压缩插件
    • js 压缩 terser-webpack-plugin 是一个优化和压缩 JS 资源的插件
    • html 压缩 HtmlWebpackPlugin 中配置 minify 对象中 collapseWhitespace removeComments 为 true
    • purgecss-webpack-plugin
      • 可以去除未使用的 css,一般与 glob、glob-all 配合使用
      • 必须和 mini-css-extract-plugin 配合使用
  • cdn

    • 使用缓存
      • 静态的 JavaScript、CSS、图片等文件开启 CDN 和缓存,并且文件名带上 HASH 值
      • 为了并行加载不阻塞,把不同的静态资源分配到不同的 CDN 服务器上
    • 域名限制
      • 同一时刻针对同一个域名的资源并行请求是有限制 可以把这些静态资源分散到不同的 CDN 服务上去 多个域名后会增加域名解析时间
      • 可以通过在 HTML HEAD 标签中 加入 link rel="dns-prefetch" href="xxx"去预解析域名,以降低域名解析带来的延迟
    • 文件指纹
      • 打包后输出的文件名和后缀
      • hash 一般是结合 CDN 缓存来使用,通过 webpack 构建之后,生成对应文件名自动带上对应的 MD5 值。如果文件内容改变的话,那么对应文件哈希值也会改变,对应的 HTML 引用的 URL 地址也会改变,触发 CDN 服务器从源服务器上拉取对应数据,进而更新本地缓存。
      • 指纹占位符
        • ext 资源后缀名
        • name 文件名称
        • path 文件的相对路径
        • folder 文件所在的文件夹
        • hash 每次 webpack 构建时生成一个唯一的 hash 值
        • chunkHash 根据 chunk 生成 hash 值,来源于同一个 chunk,则 hash 值就一样
        • contenthash 根据内容生成 hash 值,文件内容相同 hash 值就相同
      • hash 是指的每个文件的 hash 既有任何一个文件修改 所有文件的 hash 都会发生变化
      • chunkHash chunkhash 和 hash 不一样,它根据不同的入口文件(Entry)进行依赖文件解析、构建对应的 chunk,生成对应的哈希值。我们在生产环境里把一些公共库和程序入口文件区分开,单独打包构建,接着我们采用 chunkhash 的方式生成哈希值,那么只要我们不改动公共库的代码,就可以保证其哈希值不会受影响
      • contentHash 使用 chunkhash 存在一个问题,就是当在一个 JS 文件中引入 CSS 文件,编译后它们的 hash 是相同的,而且只要 js 文件发生改变 ,关联的 css 文件 hash 也会改变,这个时候可以使用 contenthash 值,保证即使 css 文件所处的模块里就算其他文件内容改变,只要 css 文件内容不变,那么不会重复构建
      • HashPlugin 插件 自定义 hash 值
  • moduleIds & chunkIds 的优化

    • module: 每一个文件其实都可以看成一个 module
    • chunk: webpack 打包最终生成的代码块,代码块会生成文件,一个文件对应一个 chunk
    • 可选值
      • natural 按使用顺序的数字 ID
      • named 方便调试的高可读性 id
      • deterministic 根据模块名称生成简短的 hash 值 默认
      • size 根据模块大小生成的数字 id
    • 使用
      • optimization.moduleIds
      • optimization.chunkIds
  • 模块联邦

    • umi 最新的加速编译模块 mfsu 用到了这个技术
    • 使用 Module Federation 时,每个应用块都是一个独立的构建,这些构建都将编译为容器
    • 容器可以被其他应用或者其他容器应用
    • 一个被引用的容器被称为 remote, 引用者被称为 host,remote 暴露模块给 host, host 则可以使用这些暴露的模块,这些模块被成为 remote 模块
    • 参数配置
      • name 必传值,即输出的模块名,被远程引用时路径为name/{name}/{expose}
      • library 声明全局变量的方式,name 为 umd 的 name
      • filename 构建输出的文件名
      • remotes 远程引用的应用名及其别名的映射,使用时以 key 值作为 name
      • exposes 被远程引用时可暴露的资源路径及其别名
      • shared 与其他应用之间可以共享的第三方依赖,使你的代码中不用重复加载同一份依赖 公共作用域概念 使用方和被使用方的模块会统一放到一个池子里 供双方使用
  • 使用内置插件 const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");

  • 需要结合 react.lazy 和 React.Suspense 异步加载来结合使用

React方面

  • 使用纯函数组件:使用纯函数组件可以避免组件渲染过程中的额外操作,从而提高渲染性能。可以使用 React.memo() 或 PureComponent 来将组件包装成纯函数组件。
  • 使用 shouldComponentUpdate(): shouldComponentUpdate() 方法可以控制组件何时重新渲染,从而避免不必要的渲染,提高渲染性能。
  • 使用 key 属性:在渲染列表时,使用 key 属性可以告诉 React 哪些列表项已更改,从而避免不必要的渲染,提高渲染性能。
  • 使用虚拟化列表:在渲染大型列表时,使用虚拟化列表可以避免一次性渲染所有列表项,从而提高渲染性能。可以使用库如 react-window 和 react-virtualized 来实现虚拟化列表。
  • 使用懒加载:使用懒加载可以延迟组件加载时间,从而提高初始加载性能。可以使用库如 React.lazy() 和 Suspense 来实现懒加载。
  • 使用优化工具:使用优化工具可以找出 React 应用中的性能瓶颈,并提供优化建议。可以使用 Chrome DevTools 中的 Performance 和 Profiler 面板来分析应用性能,或者使用库如 React DevTools和 React Performance 来监测应用性能。
  • 避免不必要的渲染:避免不必要的渲染可以提高渲染性能。可以使用 React.memo() 或 PureComponent 来避免不必要的渲染,或者使用 shouldComponentUpdate() 方法来控制组件何时重新渲染。同时,可以使用 shouldComponentUpdate() 方法来检查组件属性是否发生变化,从而避免不必要的渲染。
  • React源码方面的优化点就不放在这里面了 太杂太乱

用户体验

  • 减少页面加载时间:快速加载的页面可以提高用户体验。可以通过优化图片大小、使用浏览器缓存、压缩代码、使用 CDN 加速等方式减少页面加载时间。
  • 优化网站速度:优化网站速度可以提高用户体验。可以使用网站性能测试工具来评估网站速度,并根据测试结果优化网站。
  • 使用响应式设计:使用响应式设计可以提供更好的用户体验,因为它可以根据不同的设备和屏幕大小自适应调整布局和样式。
  • 减少网络请求:减少网络请求可以提高页面加载速度和响应速度。可以将多个 CSS 和 JavaScript 文件合并成单个文件,减少图片数量等方式减少网络请求。
  • 减少页面重绘和重排:减少页面重绘和重排可以提高页面加载速度和响应速度。可以使用 CSS3 动画代替 JavaScript 动画,减少重排和重绘。
  • 提供反馈和进度指示器:提供反馈和进度指示器可以帮助用户了解应用程序正在加载的内容,提高用户体验。可以使用加载指示器、进度条等方式提供反馈和进度指示器。
  • 使用预加载和预渲染:使用预加载和预渲染可以提高页面加载速度和响应速度,从而提高用户体验。可以使用浏览器的预加载和预渲染功能来实现预加载和预渲染。
  • 提供离线访问:提供离线访问可以让用户在无网络连接的情况下访问应用程序,提高用户体验。可以使用 Service Worker 技术来实现离线访问。

代码层面

  • 优化循环和条件语句:循环和条件语句是代码中最常见的结构,也是性能问题最容易出现的地方。在循环中避免使用数组的 push 和 pop 操作,因为它们会导致数组长度的不断变化。在条件语句中使用 switch 语句代替多个 if 语句可以提高效率。
  • 减少 DOM 操作:DOM 操作是非常耗费性能的操作之一,尤其是在操作大量的 DOM 元素时。可以使用批量 DOM 操作、缓存 DOM 元素引用、使用文档片段等方式减少 DOM 操作。
  • 避免使用全局变量:全局变量可以方便地访问和修改,但它们也会增加代码的复杂性和耦合度,并可能导致命名冲突和内存泄漏。在代码中尽量避免使用全局变量,可以使用模块化的方式管理变量。
  • 使用节流和防抖技术:在处理用户输入、滚动等操作时,节流和防抖技术可以减少事件触发次数,从而提高性能和响应速度。可以使用 Lodash 等工具库来实现节流和防抖。
  • 使用 Web Worker:在处理复杂的计算和操作时,可以使用 Web Worker 来将任务分配给后台线程,从而减少主线程的负担,提高页面的响应速度。
  • 避免使用过多的递归调用:递归调用可以让代码更加简洁和可读,但是在处理大量数据时,过多的递归调用会导致性能问题。可以使用迭代替换递归,或者使用尾递归优化来解决性能问题。
  • 使用缓存技术:在处理大量数据时,可以使用缓存技术来减少重复计算和数据读取,从而提高性能和效率。可以使用浏览器缓存、内存缓存、本地存储等方式实现缓存。
  • 避免重复代码和多余计算:在编写代码时,避免重复代码和多余计算可以提高代码的效率和可维护性。可以使用函数封装、变量复用等方式避免重复代码和多余计算。

Web Worker

Web Worker 是 HTML5 提供的一项技术,可以在浏览器中创建一个独立的工作线程,用于执行一些耗时的任务,如计算复杂的数据、处理大量的数据等。Web Worker 可以让这些任务在后台运行,不会阻塞主线程,从而提高页面的性能和响应速度。

Web Worker 的特点和使用方法如下:

  1. 独立的线程:Web Worker 在浏览器中创建一个独立的线程,与主线程相互独立,可以同时执行多个任务。

  2. 安全性:Web Worker 中不能访问主线程的 DOM 和全局对象,也不能执行一些特定的操作,如 alert(),因此具有较高的安全性。

  3. 通信:Web Worker 可以通过消息传递机制与主线程进行通信,主线程和 Web Worker 可以相互发送和接收消息。

  4. 使用限制:Web Worker 不能直接访问主线程的变量和函数,需要通过消息传递机制来交换数据和执行操作。

Web Worker 的使用步骤如下:

  1. 创建 Worker 对象:在主线程中使用 new Worker() 方法创建一个 Web Worker 对象,参数是要执行的 JavaScript 文件的 URL。

  2. 向 Worker 发送消息:通过 postMessage() 方法向 Web Worker 发送消息,可以发送字符串、数字、对象等类型的数据。

  3. 处理消息:Web Worker 中使用 onmessage 事件监听消息,通过 event.data 属性获取消息内容,可以对消息进行处理并返回结果。

  4. 向主线程发送消息:Web Worker 中使用 postMessage() 方法向主线程发送消息,主线程通过 onmessage 事件监听消息,并对消息进行处理。

  5. 关闭 Worker:通过 terminate() 方法关闭 Web Worker,释放资源。

示例代码

<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8">
	<title>Web Worker 示例</title>
	<script>
		var worker = new Worker('worker.js'); // 创建 Web Worker 对象
		worker.onmessage = function(event) { // 监听 Web Worker 返回的消息
			console.log('斐波那契数列:' + event.data);
		};
		worker.postMessage(10); // 向 Web Worker 发送消息
	</script>
</head>
<body>
</body>
</html>

  • worker.js
function fibonacci(n) {
	if (n < 2) {
		return n;
	} else {
		return fibonacci(n-1) + fibonacci(n-2);
	}
}

onmessage = function(event) { // 监听主线程发送的消息
	var result = fibonacci(event.data); // 计算斐波那契数列
	postMessage(result); // 向主线程返回计算结果
};