目录
常用方法
1、压缩和合并资源
压缩
合并静态资源
2、图片优化
3、异步加载
4、预加载关键资源
5、CSS优化
6、JavaScript优化
7、缓存策略
8、服务端渲染(SSR)
缘由
可选用框架
9、CDN加速
10、延迟加载非关键资源
首屏优化是指在网页加载过程中,尽快展示给用户可见的内容,以提高用户体验和页面加载速度。
通过压缩CSS、JavaScript和HTML等静态资源文件,并将它们合并为较少的文件,可以减少网络请求次数和文件大小,加快页面加载速度。
以下是一个示例Webpack配置文件,展示如何使用css-minimizer-webpack-plugin
、mini-css-extract-plugin
压缩CSS文件和terser-webpack-plugin
压缩JavaScript文件。
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
// 入口文件
entry: './src/index.js',
// 输出文件
output: {
filename: 'bundle.min.js',
path: __dirname + '/dist',
},
// 模块加载器
module: {
rules: [
// 处理CSS文件
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, 'css-loader'],
},
// 处理JavaScript文件
{
test: /\.js$/i,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', '@babel/preset-react'],
},
},
},
],
},
// 插件
plugins: [
new MiniCssExtractPlugin({
filename: 'styles.min.css',
}),
],
// 优化配置
optimization: {
minimizer: [
// 压缩CSS文件
new CssMinimizerPlugin(),
// 压缩JavaScript文件
new TerserPlugin(),
],
},
};
在index.html
文件中,我们将引入压缩和合并后的静态资源文件。
React App
通过上述代码,我们将压缩和合并后的CSS文件和JavaScript文件引入到了index.html
中。这样做可以减少网络请求次数和文件大小,提高页面加载速度。
使用适当的图片格式(如JPEG、PNG、WebP)和压缩算法,对图片进行优化,减小图片文件大小,提高加载速度。同时,可以使用懒加载技术,延迟加载非首屏可见区域的图片,减少首屏的加载时间。一个懒加载示例
示例代码使用 IntersectionObserver API 实现图片懒加载,如果浏览器不支持该 API,则会回退到基于滚动事件的实现方式。
具体来说,该示例首先获取所有带有 data-src 属性的图片元素,并将它们保存在一个数组中。然后,如果浏览器支持 IntersectionObserver API,则创建一个 IntersectionObserver 对象,并为每个图片元素添加观察器。当图片元素进入视口时,观察器会将其 data-src 属性值设置为 src 属性值,并移除 data-src 属性。最后,观察器会取消对该图片元素的观察。
如果浏览器不支持 IntersectionObserver API,则会使用一个 lazyLoad 函数,该函数会在滚动、窗口大小调整或设备方向变化时被触发。在该函数中,会遍历所有带有 data-src 属性的图片元素,并检查它们是否在视口中可见。如果是,则将其 data-src 属性值设置为 src 属性值,并移除 data-src 属性。最后,会从数组中删除已经加载的图片元素,并检查数组是否为空。如果为空,则取消事件监听。
将不影响首屏展示的资源(如统计代码、广告等)使用异步加载方式引入,避免阻塞首屏内容的加载。
可以使用JavaScript的动态脚本加载技术。通过动态创建标签,并将其插入到文档中,可以实现异步加载资源而不阻塞首屏内容的加载。
function loadExternalScript(url) {
return new Promise((resolve, reject) => {
const script = document.createElement('script');
script.src = url;
script.async = true;
script.onload = () => {
resolve();
};
script.onerror = () => {
reject(new Error(`Failed to load script ${url}`));
};
document.head.appendChild(script);
});
}
// 异步加载统计代码
loadExternalScript('https://example.com/analytics.js')
.then(() => {
// 统计代码加载完成后执行的逻辑
console.log('Analytics script loaded');
})
.catch((error) => {
console.error(error);
});
// 异步加载广告代码
loadExternalScript('https://example.com/advertisement.js')
.then(() => {
// 广告代码加载完成后执行的逻辑
console.log('Advertisement script loaded');
})
.catch((error) => {
console.error(error);
});
在上面的代码中,loadExternalScript()
函数用于动态加载外部脚本。通过将async
属性设置为true
,确保脚本以异步方式加载,不会阻塞其他资源的加载。然后,我们可以在then()
方法中执行相应的逻辑,以响应脚本加载完成的事件。
通过预加载关键资源(如字体文件、重要的CSS和JavaScript文件等),可以在首屏展示之前提前加载这些资源,加快后续页面加载的速度。
要实现预加载关键资源,可以使用HTML中的link
和script
标签的rel
属性来指定资源的加载方式。
演示如何预加载字体文件、CSS和JavaScript文件:
预加载关键资源示例
在上述示例中,我们使用了link
标签来预加载字体文件、CSS和script
标签来预加载JavaScript文件。具体解释如下:
link
标签用于预加载字体文件。href
属性指定字体文件的URL,as
属性设置为"font",表示该资源是字体文件,type
属性指定资源的MIME类型,crossorigin
属性用于处理跨域请求。link
标签预加载CSS文件。as
属性设置为"style",表示该资源是样式表。script
标签预加载JavaScript文件。as
属性设置为"script",表示该资源是脚本文件,defer
属性用于延迟脚本的执行。通过以上代码,浏览器在解析HTML时会提前加载这些关键资源,以加快后续页面加载的速度。
避免使用过多的CSS文件和行内样式,尽量减少CSS文件的大小。另外,可以将CSS放在页面头部,以便尽早渲染页面
示例页面
欢迎来到示例页面
这是一个简单的示例页面。
这样,浏览器在加载页面时会先加载CSS文件,并根据CSS规则渲染页面,从而提高页面的加载速度和性能。
另外,还可以避免使用行内样式,因为它会增加HTML文件的大小,使得页面加载更慢。如果必须使用行内样式,也应该尽量减少其数量和大小,以便提高页面性能。
将JavaScript代码放在页面底部,以减少对页面渲染的阻塞。另外,可以通过代码压缩、去除不必要的注释和空格等方式来减小JavaScript文件的大小。
JavaScript代码放在页面底部示例
示例中,将script
标签放在了body
标签的最后。这样做可以让浏览器在加载完页面主要内容后再加载JavaScript文件,从而减少对页面渲染的阻塞。
合理设置缓存策略,利用浏览器缓存来减少重复加载相同资源的次数,提高页面加载速度
// 假设我们有一个名为 "api.js" 的模块,用于发送网络请求
// 缓存对象,用于存储已经请求过的数据和过期时间
const cache = {};
// 发送网络请求的函数
async function fetchData(url) {
// 检查缓存中是否存在数据
if (cache[url] && cache[url].expires > Date.now()) {
console.log('从缓存中获取数据:', cache[url].data);
return cache[url].data;
}
// 发送网络请求
const response = await fetch(url);
const data = await response.json();
// 设置缓存有效期为1小时
const expires = Date.now() + 3600000;
// 将数据和过期时间存入缓存
cache[url] = { data, expires };
console.log('从服务器获取数据:', data);
return data;
}
// 在页面中使用 fetchData 函数来获取数据
async function getData() {
const url = 'https://api.example.com/data';
try {
const data = await fetchData(url);
// 处理数据
console.log('处理数据:', data);
} catch (error) {
console.error('请求失败:', error);
}
}
// 调用获取数据的函数
getData();
定义了一个 fetchData
函数来发送网络请求,并使用一个名为 cache
的对象用于存储已经请求过的数据和过期时间。
当调用 fetchData
函数时,它首先检查缓存中是否已经存在对应 URL 的数据和过期时间。如果存在且有效,则直接从缓存中获取数据,并返回。否则,则发送网络请求获取数据,并将数据与有效期时间戳存入缓存中。
在调用 getData
函数时,它会调用 fetchData
函数来获取数据,并对返回的数据进行处理。
通过这样的缓存策略,当多次调用 getData
函数时,如果 URL 相同,那么后续的请求会直接从缓存中获取数据,而不需要再次发送网络请求。这样可以减少重复加载相同数据的次数,提高页面加载速度和用户体验。
SSR(服务器端渲染)能够提高首屏渲染的原因有以下几点:
前端可以使用一些框架或库来实现服务器端渲染(SSR),下面是几个常用的前端框架:
Next.js
:Next.js是一个基于React的SSR框架。它提供了简单的API和约定,使得构建SSR应用变得更加容易。Next.js支持自动代码分割、预取和缓存,以提高性能。它还提供了静态导出功能,可以将应用程序预渲染为静态HTML文件。Nuxt.js
:Nuxt.js是一个基于Vue.js的SSR框架。它提供了类似于Next.js的功能,可以帮助开发者快速构建Vue.js应用的SSR版本。Nuxt.js支持自动路由、代码分割和服务端数据获取等特性。Angular Universal
:Angular Universal是Angular官方提供的SSR解决方案。它允许在服务器上预渲染Angular应用,以提供更好的性能和SEO效果。Angular Universal可以与Angular CLI集成,方便开发者进行构建和部署。使用内容分发网络(CDN)来加速静态资源的传输,将资源缓存在离用户较近的服务器上,减少网络延迟。
下面以一个网站为例,说明CDN如何工作:
假设有一个名为 www.example.com 的网站,该网站拥有许多静态资源,如图像、CSS文件和JavaScript文件等。这些资源可能存储在网站的主机上,但是由于主机的位置和用户之间的距离不同,因此用户在访问这些资源时可能会遇到网络延迟。
为了解决这个问题,网站所有者可以使用CDN服务。CDN服务通常由多个服务器组成,这些服务器分布在全球各地,每个服务器都缓存了网站的静态资源。当用户请求这些资源时,CDN会将请求路由到最近的服务器,从而减少网络延迟并提高资源加载速度。
例如,当用户从中国访问 www.example.com 时,CDN会将用户请求路由到位于中国的服务器。如果该服务器上已经缓存了所需的静态资源,那么用户将立即获得资源。否则,CDN将从主机上获取资源,并将其缓存到服务器上,以便以后的请求可以更快地获取资源。
总之,使用CDN可以提高网站性能,减少网络延迟,提高用户体验。
一般直接在模板中使用script
标签src
属性引用。 也可以在项目中配置基础路径
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
// 其他配置项...
output: {
// 设置输出路径和文件名
path: path.resolve(__dirname, 'dist'),
filename: '[name].[contenthash].js',
publicPath: 'https://cdn.example.com/' // 设置CDN路径
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
// 在HTML模板中使用CDN路径
cdnPath: 'https://cdn.example.com/'
}),
// 其他插件...
],
// 其他配置项...
};
将非关键资源(如广告、推荐内容等)的加载延迟到首屏渲染完成之后,以提高首屏展示速度
延迟加载示例
首屏内容