前端项目中,有时候会出现图片视频加载缓慢、首屏加载白屏的问题
之前写了一篇在VU3项目中的解决方案,
现在讲一下在 Vue2 项目中的解决方法,方法思路都差不多,在代码示例上会有一些小差别
通常是由以下原因导致的:
图片或视频格式不当:如果图片或视频格式选择不当,比如选择了无损压缩格式,可能会导致文件大小过大,从而影响加载速度。
页面中同时加载了大量的图片和视频,导致请求次数过多,网络传输速度受限,从而影响页面加载速度。
页面中的图片和视频没有进行优化处理,比如没有进行压缩、没有使用 CDN 加速等。
页面的 HTML、CSS、JavaScript 代码没有进行优化,比如没有使用 webpack 进行打包、没有使用代码分割技术等,导致页面加载时间过长。
页面中的图片和视频没有使用懒加载技术,导致页面一次性加载过多的资源,从而导致页面加载速度变慢。
网络状况不佳,比如网络延迟、带宽受限等,都可能导致图片和视频加载缓慢。
服务器响应时间过长:如果服务器响应时间过长,会导致页面请求资源的时间变慢,从而影响页面加载速度。
使用了不稳定的第三方库:如果使用了不稳定的第三方库或者组件,可能会导致页面加载速度变慢。
浏览器缓存策略不当:如果浏览器缓存策略设置不当,可能会导致浏览器重复请求资源,从而影响页面加载速度。
网络安全策略较为严格:如果网络安全策略较为严格,可能会导致浏览器请求资源时遇到一些限制,从而影响页面加载速度。
因此,在开发 Vue2 项目时,需要注意对图片和视频进行优化处理,减少请求次数,使用懒加载技术,优化代码等,来提升页面加载速度,避免出现加载缓慢、首屏加载白屏的问题。
图片和视频加载缓慢、导致首屏加载白屏的问题,通常可以从以下几个方面入手来解决:
- 图片和视频的优化
- 懒加载
- 骨架屏
- 代码优化
可以通过图片压缩、视频压缩等技术来减小文件大小,从而提高加载速度。同时,还可以通过 CDN 加速来加快资源加载速度。
可以从以下几个方法入手:
- 压缩图片或视频
- 选择合适的图片或视频格式
- 使用图片或视频 CDN 加速
- 使用懒加载技术
可以使用图片或视频压缩工具,将文件大小压缩至合适的大小。对于图片,可以使用在线图片压缩工具或者 Photoshop 等图片编辑软件进行压缩;对于视频,可以使用视频压缩软件,如 HandBrake 等进行压缩。
以下是几个常用的在线图片压缩工具:
- TinyPNG(tinypng.com)
TinyPNG 是一个免费的在线图片压缩工具,可以将 PNG 和 JPEG 格式的图片压缩至合适的大小,而且不会影响图片质量。
- Compressor.io(compressor.io)
Compressor.io 是一个免费的在线图片压缩工具,可以压缩 JPEG、PNG、SVG 和 GIF 等格式的图片。它可以将图片压缩至较小的大小,而且不会影响图片质量。
- Kraken(kraken.io)
Kraken 是一个在线图片优化和压缩服务,可以将 JPEG、PNG 和 GIF 等格式的图片压缩至最小的文件大小。Kraken 还提供了 API 接口,可以方便地集成到项目中。
- ImageOptim(imageoptim.com)
ImageOptim 是一个免费的图片优化工具,它可以自动压缩 JPEG、PNG 和 GIF 等格式的图片,并且可以自动删除图片中的元数据和不必要的信息,从而减小文件大小。
选择合适的图片或视频格式也可以减小文件大小。例如,对于图片,可以选择 JPEG 或者 WebP 格式,对于视频,可以选择 H.264 或者 H.265 格式。
可以使用图片或视频 CDN 加速,将图片或视频资源分布在全球各地的 CDN 节点上,从而加快资源的传输速度,提高页面加载速度。
使用图片或视频 CDN 加速可以显著提高网站的访问速度和用户体验。下面介绍一些实现方法
这种方法比较简单,但是需要手动替换每个 URL,且在 URL 发生变化时需要重新替换。
在 Webpack 中可以使用一些插件来自动替换 URL。例如
url-loader
可以将小于指定大小的图片转换为 base64 编码,并将大于指定大小的图片复制到输出目录并替换为 CDN 上的 URL。html-webpack-plugin
可以将 HTML 文件中的本地资源替换为 CDN 上的 URL。
// webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
// ...
module: {
rules: [
{
test: /\.(png|jpg|jpeg|gif|svg)$/i,
use: [
{
loader: 'url-loader',
options: {
limit: 8192,
fallback: {
loader: 'file-loader',
options: {
name: 'images/[name].[hash:8].[ext]',
publicPath: 'https://cdn.example.com/'
}
}
}
}
]
},
{
test: /\.html$/i,
loader: 'html-loader',
options: {
sources: {
list: [
{
attribute: 'src',
type: 'src',
tag: 'img'
},
{
attribute: 'src',
type: 'src',
tag: 'video'
}
],
urlFilter: (attribute, value, resourcePath) => {
// 只处理本地资源
return !/^(https?:)?\/\//i.test(value);
}
}
}
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
filename: 'index.html'
}),
new MiniCssExtractPlugin({
filename: 'css/[name].[contenthash:8].css'
})
]
// ...
};
在这个示例中,
使用了 `url-loader` 和 `html-loader`,并在 `fallback` 选项中设置了 `publicPath` 属性来指定 CDN 上的 URL。
在 `html-loader` 中,我们使用了 `sources` 选项来指定需要替换的本地资源。`HtmlWebpackPlugin` 和 `MiniCssExtractPlugin` 则用于生成 HTML 和 CSS 文件。
有些第三方库可以帮助我们自动替换 URL,例如
vue-loader
可以将 Vue 组件中的图片和视频 URL 替换为 CDN 上的 URL。vue-lazyload
可以将图片懒加载,并自动替换 URL。
// main.js
import Vue from 'vue';
import App from './App.vue';
import VueLazyload from 'vue-lazyload';
Vue.use(VueLazyload, {
preLoad: 1.3,
error: 'https://cdn.example.com/images/error.png',
loading: 'https://cdn.example.com/images/loading.gif',
attempt: 1,
observer: true,
observerOptions: {
rootMargin: '0px',
threshold: 0.1
},
filter: {
progressive: (listener, options) => {
// 过滤器,用于处理渐进式图片
const isCDN = /^https?:\/\/cdn\.example\.com\//i.test(listener.src);
if (isCDN) {
options.adapter(listener, options);
} else {
listener.el.setAttribute('data-src', listener.src);
}
}
}
});
new Vue({
render: h => h(App)
}).$mount('#app');
```
在这个示例中,我们使用了 `vue-lazyload`,并设置了一些选项来指定 CDN 上的 URL。在过滤器中,我们使用了正则表达式来判断图片是否在 CDN 上,并根据需要将图片 URL 替换为 `data-src` 属性,以便 `vue-lazyload` 可以正确地处理。
以上三种方法都可以实现使用图片或视频 CDN 加速,具体的实现方法可以根据项目的具体情况进行选择和组合。
可以使用懒加载技术,将图片或视频的加载延迟到用户需要访问它们时再加载,从而减少页面一次性请求过多的资源,提高页面加载速度。
在 Vue 2 项目中,可以使用懒加载技术来延迟加载组件,减少首屏加载时间,提高页面性能。下面介绍使用 Vue 2 懒加载技术的方法:
Vue Router 提供了一种简单的懒加载组件的方法,可以在需要时动态加载组件。只需在路由配置中使用
component: () => import('@/views/Home.vue')
的形式,即可将Home.vue
组件懒加载。```
在这个示例中,我们使用了 `import()` 方法来动态加载 `Home.vue` 和 `About.vue` 组件。
// router.js
import Vue from 'vue';
import Router from 'vue-router';
Vue.use(Router);
export default new Router({
routes: [
{
path: '/',
name: 'Home',
component: () => import('@/views/Home.vue')
},
{
path: '/about',
name: 'About',
component: () => import('@/views/About.vue')
}
]
});
在 Webpack 中,可以使用
require.ensure()
或import()
方法来实现懒加载。require.ensure()
可以在需要时异步加载模块,import()
方法则可以异步加载 ES6 模块。```
在这个示例中,使用了 `import()` 方法来异步加载 `About.vue` 组件,并在加载完成后渲染了它。
// main.js
import Vue from 'vue';
import App from './App.vue';
new Vue({
render: h => h(App)
}).$mount('#app');
// 异步加载 About 组件
const loadAbout = () => {
return import(/* webpackChunkName: "about" */ './About.vue');
};
// 异步加载 About 组件并渲染
loadAbout().then(About => {
new Vue({
el: '#about',
render: h => h(About)
});
});
以上两种方法都可以实现 Vue 2 懒加载技术,具体的实现方法可以根据项目的具体情况进行选择和组合。需要注意的是,懒加载会增加代码复杂度,需要根据实际情况进行权衡。
使用懒加载技术,可以将图片和视频的加载延迟到用户需要访问它们时再加载,从而减少页面一次性加载过多的资源,提高首屏加载速度。
以下是使用懒加载技术实现图片和视频懒加载的方法:
使用 Intersection Observer API
Intersection Observer API 是一种新的浏览器 API,可以监听指定元素是否进入了视口,从而触发回调函数。
可以通过监听图片或视频元素是否进入了视口,从而触发加载图片或视频的操作。
以下是一个使用 Intersection Observer API 实现图片懒加载的 Vue 2 示例代码:
在这个示例中,我们使用 Intersection Observer API 监测每个图片容器元素,当它们出现在视口中时,将对应的图片的 show 属性设置为 true,触发图片加载。
同时,我们也停止观察已经出现在视口中的元素,以节省性能。
除了使用 Intersection Observer API,还可以使用一些第三方库来实现图片和视频的懒加载,
如 LazyLoad、Lozad.js、LazyLoad-xt 等。这些库可以更快速地实现懒加载效果,并提供了更多的配置选项,例如触发懒加载的条件、动画效果等。具体使用方法可以参考它们的官方文档。
当然可以,以下是一个使用 LazyLoad 库实现图片懒加载的 Vue 3 示例:
以下是使用 LazyLoad 库实现图片懒加载的 Vue 2 示例代码:
首先,需要安装并导入 LazyLoad 库:
npm install vanilla-lazyload --save
import LazyLoad from 'vanilla-lazyload';
在组件的 mounted 钩子函数中,创建一个 LazyLoad 实例,并传入一个配置对象:
在这个示例中,使用 LazyLoad 库来实现图片懒加载。
- 首先,将每个图片的真实地址存储在
data-src
自定义属性中,而不是src
属性中。- 接着,在组件的 mounted 钩子函数中,创建一个 LazyLoad 实例,并传入一个配置对象,其中
threshold
属性指定元素离可视区域的距离,elements_selector
属性指定要进行懒加载的元素。- 最后,在模板中将图片的
src
属性替换为data-src
属性,这样当图片进入可视区域时,LazyLoad 库会自动将data-src
属性的值赋给src
属性,触发图片加载。
骨架屏(Skeleton Screen)是一种页面加载优化的技术,可以在页面加载过程中显示一个简单的灰色框架,代替还未加载的内容。骨架屏可以提高用户体验,让用户感觉页面加载速度更快,同时也可以减少用户的焦虑感。
在 Vue 2 中,可以使用一些第三方库来实现骨架屏效果,例如 vue-skeleton-webpack-plugin、vue-content-loader、vue-loading-skeleton 等。
vue-content-loader
是一个 Vue.js 组件库,可以帮助我们实现骨架屏效果。它提供了多种预定义的 SVG 形状,可以快速生成骨架屏模板,并且可以自定义颜色、大小、动画等。以下是在 Vue 2中使用
vue-content-loader
实现骨架屏效果的步骤:
以下是在 Vue 2 中使用 vue-content-loader 实现骨架屏效果的步骤:
npm install vue-content-loader --save
import ContentLoader from 'vue-content-loader';
在这个示例中,将 ContentLoader 组件作为根元素,设置宽度和高度属性。ContentLoader 组件的子元素是一个 SVG 矩形元素,它的 x、y、rx、ry、width 和 height 属性都是根据我们的需求设置的。
你可以根据需要添加更多的子元素,以实现更复杂的骨架屏效果。例如,你可以使用线性渐变、径向渐变、动画等特性来让骨架屏看起来更生动。
如果需要,你可以在组件中定义 props 来动态设置 ContentLoader 组件的属性。例如:
在这个示例中,定义了 width 和 height 两个 props,它们分别设置 ContentLoader 组件的宽度和高度。
如果在使用组件时没有传递这些 props,它们将会使用默认值 400 和 300。
以上就是在 Vue 2 中使用 vue-content-loader 实现骨架屏效果的步骤。使用 vue-content-loader 可以快速、简单地创建骨架屏效果,提高用户体验。
vue-skeleton-webpack-plugin
是一个 Webpack 插件,可以帮助我们在打包过程中生成骨架屏模板,并自动注入到 HTML 文件中。以下是使用
vue-skeleton-webpack-plugin
实现骨架屏的示例:
以下是在 Vue 2 中使用 vue-skeleton-webpack-plugin 实现骨架屏的示例:
npm install vue-skeleton-webpack-plugin --save-dev
const VueSkeletonWebpackPlugin = require('vue-skeleton-webpack-plugin');
module.exports = {
// ...
plugins: [
new VueSkeletonWebpackPlugin({
webpackConfig: {
entry: {
app: './src/entry-skeleton.js'
}
},
router: {
mode: 'history',
routes: [
{ path: '/', skeletonId: 'home' },
{ path: '/about', skeletonId: 'about' }
]
},
minimize: true,
quiet: true
})
]
// ...
};
在这个示例中,创建了一个 VueSkeletonWebpackPlugin 实例,并传入了一些配置对象。
其中,
- `webpackConfig` 属性指定入口文件为 `./src/entry-skeleton.js`,
- `router` 属性指定了骨架屏对应的路由和骨架屏 ID,
- `minimize` 属性启用了代码压缩,
- `quiet` 属性禁止输出日志。
import Vue from 'vue';
import App from './App.vue';
import router from './router';
new Vue({
router,
render: h => h(App, { props: { isSkeleton: true } })
}).$mount('#app');
在这个示例中,创建了一个 Vue 实例,并将 `isSkeleton` 属性传递给 App 组件,以便在组件中判断是否为骨架屏模式。
在这个示例中,
使用 `import('vue-skeleton-webpack-plugin/lib/client/skeleton')` 导入 Skeleton 局部组件,并在模板中使用它来包裹真实内容。
还定义了一个 `isSkeleton` 属性,用于判断是否为骨架屏模式。
注意,需要将 Skeleton 局部组件的引入写成函数形式。这是因为在骨架屏模式下,Skeleton 组件不会被打包进正常的代码中,而是由 vue-skeleton-webpack-plugin 在运行时动态注入。
在代码优化时,需要综合考虑多个方面,包括性能、可读性、可维护性等。
下面是一些常见的代码优化方式及其结果问题:
- 懒加载/按需加载
- 缓存机制
- 代码压缩和合并
- 其他优化方式
懒加载/按需加载是指将页面或模块的加载推迟到需要时再进行,以减少初始加载时间和网络请求次数,提高页面性能。然而,在使用懒加载/按需加载时,可能会出现以下问题:
- 首次加载时,用户可能需要等待更长时间才能看到页面内容。
- 如果按需加载的模块过多,可能会出现过多的网络请求,导致页面加载速度变慢。
- 懒加载/按需加载的代码可能会增加复杂度,降低代码的可读性和可维护性。
缓存机制是指将一些静态资源(如图片、CSS、JS 等)缓存在客户端,以减少网络请求次数,提高页面性能。然而,在使用缓存机制时,可能会出现以下问题:
- 如果缓存时间过长,可能会导致用户无法看到最新的内容。
- 如果缓存时间过短,可能会导致用户频繁地重新请求资源,降低页面性能。
- 缓存机制可能会对服务器和客户端产生额外的负担,增加服务器和客户端的开销。
代码压缩和合并是指将多个 JS 或 CSS 文件压缩为一个文件,并将其中的空格、注释等无关字符删除,以减小文件大小,提高页面性能。然而,在使用代码压缩和合并时,可能会出现以下问题:
- 如果压缩和合并的文件过大,可能会导致文件下载时间过长,影响页面性能。
- 代码压缩和合并可能会增加复杂度,降低代码的可读性和可维护性。
- 如果压缩和合并的文件不够灵活,可能会导致无法对不同的页面进行定制和优化。
除了上述方式外,还有一些其他的代码优化方式,如使用更高效的算法或数据结构、减少重绘和回流、优化图片大小和格式等。这些优化方式的效果和问题也各不相同,需要根据具体情况进行选择和评估。
综上所述,代码优化需要综合考虑多个方面,不能只追求性能,还要注意代码的可读性和可维护性,以确保代码质量和用户体验的均衡。
以下是在 Vue 2 项目中,解决首屏加载空白的示例对比:
优化前的示例代码:
My Vue App javascript
Copy
// main.js import Vue from 'vue'; import App from './App.vue'; new Vue({ el: '#app', render: h => h(App) });
在这个示例中,我们没有采取任何优化措施,直接将 Vue App 渲染到了
#app
元素中。这种做法会导致在首次加载页面时出现空白,因为浏览器需要下载并解析vendor.js
和app.js
两个文件,才能渲染页面。优化后的示例代码:
My Vue App // main.js import Vue from 'vue'; import App from './App.vue'; new Vue({ el: '#app', render: h => h(App) });
在这个示例中,采用了以下优化措施:
- 将
vendor.js
和app.js
两个文件的defer
属性设置为true
,表示它们的下载不会阻塞页面的渲染。- 在
head
标签中添加一个空的script
标签,并将其设置为window.__INITIAL_STATE__
的初始值。这个变量可以在后续的异步请求中使用,避免在页面加载过程中出现空白。- 将
#app
元素放在body
标签中,避免在页面加载过程中出现空白。这些优化措施可以显著减少页面加载时间,并且避免在页面加载过程中出现空白。
设置浏览器缓存策略可以减少浏览器重复请求资源,从而提高页面加载速度。可以通过在 HTTP 响应头中设置缓存策略来实现。
以下是一些常见的缓存策略设置方法:
- 设置强缓存
- 设置协商缓存
强缓存是指浏览器在一定时间内直接从本地缓存中获取资源,而不需要向服务器发送请求。可以通过设置 "Expires" 或者 "Cache-Control" 响应头来设置强缓存时间,如下所示:
- Expires:设置过期时间,例如 "Expires: Wed, 21 Oct 2023 07:28:00 GMT"
- Cache-Control:设置缓存策略,例如 "Cache-Control: max-age=3600",表示资源在 3600 秒内有效。
协商缓存是指浏览器在过期时间后,向服务器发送请求,服务器会根据资源的 ETag 或者 Last-Modified 等信息,判断资源是否发生变化。如果资源没有发生变化,服务器会返回 304 状态码,告诉浏览器可以直接使用本地缓存。可以通过设置 "Last-Modified" 和 "ETag" 响应头来设置协商缓存,如下所示:
- Last-Modified:表示资源的最后修改时间,例如 "Last-Modified: Wed, 21 Oct 2023 07:28:00 GMT"
- ETag:表示资源的唯一标识符,例如 "ETag: W/1234567890"
注意,设置缓存策略时需要根据具体情况进行设置,过长的缓存时间可能会导致资源更新不及时,而过短的缓存时间则可能会影响页面加载速度。建议根据实际情况进行调整。