登录
注册
开源
企业版
高校版
搜索
帮助中心
使用条款
关于我们
开源
企业版
高校版
私有云
模力方舟
AI 队友
登录
注册
Gitee 2025 年度开源项目评选中
代码拉取完成,页面将自动刷新
捐赠
捐赠前请先登录
取消
前往登录
扫描微信二维码支付
取消
支付完成
支付提示
将跳转至支付宝完成支付
确定
取消
Watch
不关注
关注所有动态
仅关注版本发行动态
关注但不提醒动态
3
Star
45
Fork
21
DreamCoders
/
CoderGuide
代码
Issues
1169
Pull Requests
0
Wiki
统计
流水线
服务
JavaDoc
PHPDoc
质量分析
Jenkins for Gitee
腾讯云托管
腾讯云 Serverless
悬镜安全
阿里云 SAE
Codeblitz
SBOM
我知道了,不再自动展开
更新失败,请稍后重试!
移除标识
内容风险标识
本任务被
标识为内容中包含有代码安全 Bug 、隐私泄露等敏感信息,仓库外成员不可访问
SPA(单页应用)首屏加载速度慢怎么解决?
待办的
#IAG9QA
陌生人
拥有者
创建于
2024-07-29 16:07
<h2>一、什么是首屏加载</h2><p>首屏时间(First Contentful Paint),指的是浏览器从响应用户输入网址地址,到首屏内容渲染完成的时间,此时整个网页不一定要全部渲染完成,但需要展示当前视窗需要的内容</p><p>首屏加载可以说是用户体验中<strong>最重要</strong>的环节</p><h3>关于计算首屏时间</h3><p>利用<code>performance.timing</code>提供的数据:</p><p><img src="https://jsd.onmicrosoft.cn/gh/iGaoWei/codercdn@master/question/20240627/6a4a4d0d-9197-46fe-8e8d-0d6e49099ea2.png" alt="" data-href="" style=""/></p><p>通过<code>DOMContentLoad</code>或者<code>performance</code>来计算出首屏时间</p><pre><code class="language-js">// 方案一: document.addEventListener('DOMContentLoaded', (event) => { console.log('first contentful painting'); }); // 方案二: performance.getEntriesByName("first-contentful-paint")[0].startTime // performance.getEntriesByName("first-contentful-paint")[0] // 会返回一个 PerformancePaintTiming的实例,结构如下: { name: "first-contentful-paint", entryType: "paint", startTime: 507.80000002123415, duration: 0, };</code></pre><h2>二、加载慢的原因</h2><p>在页面渲染的过程,导致加载速度慢的因素可能如下:</p><ul><li>网络延时问题</li><li>资源文件体积是否过大</li><li>资源是否重复发送请求去加载了</li><li>加载脚本的时候,渲染内容堵塞了</li></ul><h2>三、解决方案</h2><p>常见的几种SPA首屏优化方式</p><ul><li>减小入口文件积</li><li>静态资源本地缓存</li><li>UI框架按需加载</li><li>图片资源的压缩</li><li>组件重复打包</li><li>开启GZip压缩</li><li>使用SSR</li></ul><h3>减小入口文件体积</h3><p>常用的手段是路由懒加载,把不同路由对应的组件分割成不同的代码块,待路由被请求的时候会单独打包路由,使得入口文件变小,加载速度大大增加</p><p><img src="https://jsd.onmicrosoft.cn/gh/iGaoWei/codercdn@master/question/20240627/ddab4bbd-863b-4fab-a6ba-68d3651307be.png" alt="" data-href="" style=""/></p><p>在<code>vue-router</code>配置路由的时候,采用动态加载路由的形式</p><pre><code class="language-js">routes:[ path: 'Blogs', name: 'ShowBlogs', component: () => import('./components/ShowBlogs.vue') ]</code></pre><p>以函数的形式加载路由,这样就可以把各自的路由文件分别打包,只有在解析给定的路由时,才会加载路由组件</p><h3>静态资源本地缓存</h3><p>后端返回资源问题:</p><ul><li>采用HTTP缓存,设置Cache-Control,Last-Modified,Etag等响应头</li><li>采用Service Worker离线缓存</li></ul><p>前端合理利用<code>localStorage</code></p><h3>UI框架按需加载</h3><p>在日常使用<code>UI</code>框架,例如<code>element-UI</code>、或者<code>antd</code>,我们通常会直接引用整个<code>UI</code>库</p><pre><code class="language-js">import ElementUI from 'element-ui' Vue.use(ElementUI)</code></pre><p>但实际上我用到的组件只有按钮,分页,表格,输入与警告 所以我们要按需引用</p><pre><code class="language-js">import { Button, Input, Pagination, Table, TableColumn, MessageBox } from 'element-ui'; Vue.use(Button) Vue.use(Input) Vue.use(Pagination)</code></pre><h3>组件重复打包</h3><p>假设<code>A.js</code>文件是一个常用的库,现在有多个路由使用了<code>A.js</code>文件,这就造成了重复下载</p><p>解决方案:在<code>webpack</code>的<code>config</code>文件中,修改<code>CommonsChunkPlugin</code>的配置</p><pre><code class="language-js">minChunks: 3</code></pre><p><code>minChunks</code>为3表示会把使用3次及以上的包抽离出来,放进公共依赖文件,避免了重复加载组件</p><h3>图片资源的压缩</h3><p>图片资源虽然不在编码过程中,但它却是对页面性能影响最大的因素</p><p>对于所有的图片资源,我们可以进行适当的压缩</p><p>对页面上使用到的<code>icon</code>,可以使用在线字体图标,或者雪碧图,将众多小图标合并到同一张图上,用以减轻<code>http</code>请求压力。</p><h3>开启GZip压缩</h3><p>拆完包之后,我们再用<code>gzip</code>做一下压缩 安装<code>compression-webpack-plugin</code></p><pre><code class="language-js">cnmp i compression-webpack-plugin -D</code></pre><p>在<code>vue.congig.js</code>中引入并修改<code>webpack</code>配置</p><pre><code class="language-js">const CompressionPlugin = require('compression-webpack-plugin') configureWebpack: (config) => { if (process.env.NODE_ENV === 'production') { // 为生产环境修改配置... config.mode = 'production' return { plugins: [new CompressionPlugin({ test: /\.js$|\.html$|\.css/, //匹配文件名 threshold: 10240, //对超过10k的数据进行压缩 deleteOriginalAssets: false //是否删除原文件 })] } }</code></pre><p>在服务器我们也要做相应的配置 如果发送请求的浏览器支持<code>gzip</code>,就发送给它<code>gzip</code>格式的文件 我的服务器是用<code>express</code>框架搭建的 只要安装一下<code>compression</code>就能使用</p><pre><code >const compression = require('compression') app.use(compression()) // 在其他中间件使用之前调用</code></pre><h3>使用SSR</h3><p>SSR(Server side ),也就是服务端渲染,组件或页面通过服务器生成html字符串,再发送到浏览器</p><p>从头搭建一个服务端渲染是很复杂的,<code>vue</code>应用建议使用<code>Nuxt.js</code>实现服务端渲染</p><h3>小结:</h3><p>减少首屏渲染时间的方法有很多,总的来讲可以分成两大部分 :资源加载优化 和 页面渲染优化</p><p>下图是更为全面的首屏优化的方案</p><p><img src="https://jsd.onmicrosoft.cn/gh/iGaoWei/codercdn@master/question/20240627/4a5c3715-9061-45a9-b3d5-a340e6033f65.png" alt="" data-href="" style=""/></p><p>大家可以根据自己项目的情况选择各种方式进行首屏渲染的优化</p>
<h2>一、什么是首屏加载</h2><p>首屏时间(First Contentful Paint),指的是浏览器从响应用户输入网址地址,到首屏内容渲染完成的时间,此时整个网页不一定要全部渲染完成,但需要展示当前视窗需要的内容</p><p>首屏加载可以说是用户体验中<strong>最重要</strong>的环节</p><h3>关于计算首屏时间</h3><p>利用<code>performance.timing</code>提供的数据:</p><p><img src="https://jsd.onmicrosoft.cn/gh/iGaoWei/codercdn@master/question/20240627/6a4a4d0d-9197-46fe-8e8d-0d6e49099ea2.png" alt="" data-href="" style=""/></p><p>通过<code>DOMContentLoad</code>或者<code>performance</code>来计算出首屏时间</p><pre><code class="language-js">// 方案一: document.addEventListener('DOMContentLoaded', (event) => { console.log('first contentful painting'); }); // 方案二: performance.getEntriesByName("first-contentful-paint")[0].startTime // performance.getEntriesByName("first-contentful-paint")[0] // 会返回一个 PerformancePaintTiming的实例,结构如下: { name: "first-contentful-paint", entryType: "paint", startTime: 507.80000002123415, duration: 0, };</code></pre><h2>二、加载慢的原因</h2><p>在页面渲染的过程,导致加载速度慢的因素可能如下:</p><ul><li>网络延时问题</li><li>资源文件体积是否过大</li><li>资源是否重复发送请求去加载了</li><li>加载脚本的时候,渲染内容堵塞了</li></ul><h2>三、解决方案</h2><p>常见的几种SPA首屏优化方式</p><ul><li>减小入口文件积</li><li>静态资源本地缓存</li><li>UI框架按需加载</li><li>图片资源的压缩</li><li>组件重复打包</li><li>开启GZip压缩</li><li>使用SSR</li></ul><h3>减小入口文件体积</h3><p>常用的手段是路由懒加载,把不同路由对应的组件分割成不同的代码块,待路由被请求的时候会单独打包路由,使得入口文件变小,加载速度大大增加</p><p><img src="https://jsd.onmicrosoft.cn/gh/iGaoWei/codercdn@master/question/20240627/ddab4bbd-863b-4fab-a6ba-68d3651307be.png" alt="" data-href="" style=""/></p><p>在<code>vue-router</code>配置路由的时候,采用动态加载路由的形式</p><pre><code class="language-js">routes:[ path: 'Blogs', name: 'ShowBlogs', component: () => import('./components/ShowBlogs.vue') ]</code></pre><p>以函数的形式加载路由,这样就可以把各自的路由文件分别打包,只有在解析给定的路由时,才会加载路由组件</p><h3>静态资源本地缓存</h3><p>后端返回资源问题:</p><ul><li>采用HTTP缓存,设置Cache-Control,Last-Modified,Etag等响应头</li><li>采用Service Worker离线缓存</li></ul><p>前端合理利用<code>localStorage</code></p><h3>UI框架按需加载</h3><p>在日常使用<code>UI</code>框架,例如<code>element-UI</code>、或者<code>antd</code>,我们通常会直接引用整个<code>UI</code>库</p><pre><code class="language-js">import ElementUI from 'element-ui' Vue.use(ElementUI)</code></pre><p>但实际上我用到的组件只有按钮,分页,表格,输入与警告 所以我们要按需引用</p><pre><code class="language-js">import { Button, Input, Pagination, Table, TableColumn, MessageBox } from 'element-ui'; Vue.use(Button) Vue.use(Input) Vue.use(Pagination)</code></pre><h3>组件重复打包</h3><p>假设<code>A.js</code>文件是一个常用的库,现在有多个路由使用了<code>A.js</code>文件,这就造成了重复下载</p><p>解决方案:在<code>webpack</code>的<code>config</code>文件中,修改<code>CommonsChunkPlugin</code>的配置</p><pre><code class="language-js">minChunks: 3</code></pre><p><code>minChunks</code>为3表示会把使用3次及以上的包抽离出来,放进公共依赖文件,避免了重复加载组件</p><h3>图片资源的压缩</h3><p>图片资源虽然不在编码过程中,但它却是对页面性能影响最大的因素</p><p>对于所有的图片资源,我们可以进行适当的压缩</p><p>对页面上使用到的<code>icon</code>,可以使用在线字体图标,或者雪碧图,将众多小图标合并到同一张图上,用以减轻<code>http</code>请求压力。</p><h3>开启GZip压缩</h3><p>拆完包之后,我们再用<code>gzip</code>做一下压缩 安装<code>compression-webpack-plugin</code></p><pre><code class="language-js">cnmp i compression-webpack-plugin -D</code></pre><p>在<code>vue.congig.js</code>中引入并修改<code>webpack</code>配置</p><pre><code class="language-js">const CompressionPlugin = require('compression-webpack-plugin') configureWebpack: (config) => { if (process.env.NODE_ENV === 'production') { // 为生产环境修改配置... config.mode = 'production' return { plugins: [new CompressionPlugin({ test: /\.js$|\.html$|\.css/, //匹配文件名 threshold: 10240, //对超过10k的数据进行压缩 deleteOriginalAssets: false //是否删除原文件 })] } }</code></pre><p>在服务器我们也要做相应的配置 如果发送请求的浏览器支持<code>gzip</code>,就发送给它<code>gzip</code>格式的文件 我的服务器是用<code>express</code>框架搭建的 只要安装一下<code>compression</code>就能使用</p><pre><code >const compression = require('compression') app.use(compression()) // 在其他中间件使用之前调用</code></pre><h3>使用SSR</h3><p>SSR(Server side ),也就是服务端渲染,组件或页面通过服务器生成html字符串,再发送到浏览器</p><p>从头搭建一个服务端渲染是很复杂的,<code>vue</code>应用建议使用<code>Nuxt.js</code>实现服务端渲染</p><h3>小结:</h3><p>减少首屏渲染时间的方法有很多,总的来讲可以分成两大部分 :资源加载优化 和 页面渲染优化</p><p>下图是更为全面的首屏优化的方案</p><p><img src="https://jsd.onmicrosoft.cn/gh/iGaoWei/codercdn@master/question/20240627/4a5c3715-9061-45a9-b3d5-a340e6033f65.png" alt="" data-href="" style=""/></p><p>大家可以根据自己项目的情况选择各种方式进行首屏渲染的优化</p>
评论 (
0
)
登录
后才可以发表评论
状态
待办的
待办的
进行中
已完成
已关闭
负责人
未设置
标签
Html/JS/CSS
未设置
标签管理
里程碑
未关联里程碑
未关联里程碑
Pull Requests
未关联
未关联
关联的 Pull Requests 被合并后可能会关闭此 issue
分支
未关联
未关联
master
开始日期   -   截止日期
-
置顶选项
不置顶
置顶等级:高
置顶等级:中
置顶等级:低
优先级
不指定
严重
主要
次要
不重要
参与者(1)
1
https://gitee.com/DreamCoders/CoderGuide.git
git@gitee.com:DreamCoders/CoderGuide.git
DreamCoders
CoderGuide
CoderGuide
点此查找更多帮助
搜索帮助
Git 命令在线学习
如何在 Gitee 导入 GitHub 仓库
Git 仓库基础操作
企业版和社区版功能对比
SSH 公钥设置
如何处理代码冲突
仓库体积过大,如何减小?
如何找回被删除的仓库数据
Gitee 产品配额说明
GitHub仓库快速导入Gitee及同步更新
什么是 Release(发行版)
将 PHP 项目自动发布到 packagist.org
评论
仓库举报
回到顶部
登录提示
该操作需登录 Gitee 帐号,请先登录后再操作。
立即登录
没有帐号,去注册