首页加载速度优化

要说面试的时候问到最多的问题,那性能优化绝对是躲不开的话题,基本每个公司面试我都遇到了相关问题,其中,首页加载速度优化又是其中最常问的问题,网上的文章比较零零散散,没有一个总结到十分满意的,于是自己便来总结一下

这张图是我发现的比较宝藏,比较全面的一张首页加载优化图,便以此图来进行相关总结

目录

一. 资源加载优化

  1. 压缩资源
  2. 启用Gzip压缩
  3. 使用缓存
  4. [使用内容分发网络 (CDN)](#使用内容分发网络 (CDN) "#%E4%BD%BF%E7%94%A8%E5%86%85%E5%AE%B9%E5%88%86%E5%8F%91%E7%BD%91%E7%BB%9C-cdn")
  5. 使用HTTP/2
  6. 优化DNS解析
  7. 减少HTTP请求数
  8. 预加载和预获取
  9. 使用更高效的图片格式
  10. 图片懒加载和路由懒加载

二. 页面渲染优化

  1. 优化CSS
  2. 使用CSS3动画代替JavaScript动画
  3. 将JavaScript放在页面底部
  4. 使用async和defer属性
  5. 减少和优化DOM操作
  6. [使用Virtual DOM](#使用Virtual DOM "#%E4%BD%BF%E7%94%A8virtual-dom")
  7. 避免布局抖动
  8. 使用will-change提示浏览器优化
  9. [使用服务端渲染 (SSR)](#使用服务端渲染 (SSR) "#%E4%BD%BF%E7%94%A8%E6%9C%8D%E5%8A%A1%E7%AB%AF%E6%B8%B2%E6%9F%93-ssr")
  10. 延迟加载资源

资源加载优化

压缩资源

通过 Webpack 配置,可以自动压缩 HTML、CSS 和 JavaScript 文件。

javascript 复制代码
// webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');

module.exports = {
    mode: 'production',
    entry: './src/index.js',
    output: {
        filename: 'bundle.js',
        path: __dirname + '/dist'
    },
    module: {
        rules: [
            {
                test: /\.css$/,
                use: [MiniCssExtractPlugin.loader, 'css-loader']
            }
        ]
    },
    optimization: {
        minimize: true,
        minimizer: [
            new TerserPlugin(),
            new CssMinimizerPlugin()
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './src/index.html',
            minify: {
                collapseWhitespace: true,
                removeComments: true,
                removeRedundantAttributes: true,
                useShortDoctype: true
            }
        }),
        new MiniCssExtractPlugin({
            filename: 'styles.css'
        })
    ]
};

启用Gzip压缩

通过 Webpack 配置,可以生成 Gzip 压缩文件。

js 复制代码
//在请求时会带上该请求头,声明它支持的压缩算法
Accept-Encoding: gzip, deflate, br
javascript 复制代码
// webpack.config.js
const CompressionPlugin = require('compression-webpack-plugin');

module.exports = {
    // 其他配置...
    plugins: [
        new CompressionPlugin({
            filename: '[path][base].gz',
            algorithm: 'gzip',
            test: /\.(js|css|html|svg)$/,
            threshold: 10240,
            minRatio: 0.8
        })
    ]
};

使用缓存

服务端通过配置协商缓存和强缓存,来实现请求的缓存,这里以强缓存为例

javascript 复制代码
// 设置强缓存
const express = require('express');
const path = require('path');

const app = express();

// 强缓存中间件
app.use((req, res, next) => {
    const options = {
        maxAge: '1y', // 缓存一年
        immutable: true
    };

    // 设置 Cache-Control 头
    res.set('Cache-Control', `public, max-age=${options.maxAge}, immutable`);
    next();
});

// 将静态文件托管到 public 目录
app.use(express.static(path.join(__dirname, 'public'), {
    maxAge: '1y' // 缓存一年
}));

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
    console.log(`Server is running on port ${PORT}`);
});

使用内容分发网络 (CDN)

通过 Webpack 配置,将静态资源路径指向 CDN。

javascript 复制代码
output: { 
filename: '[name].[contenthash].js',
path: __dirname + '/dist',
publicPath: 'https://cdn.example.com/' // 指向你的 CDN 地址 
},

使用HTTP/2

启用 HTTP/2 需要在服务器配置中完成,Webpack 本身不直接支持 HTTP/2 配置。

http 复制代码
# Nginx 配置
server {
    listen 443 ssl http2;
    server_name example.com;
    # SSL 配置
}

优化DNS解析

在 HTML 中添加 DNS 预获取。

html 复制代码
<link rel="dns-prefetch" href="//example.com">

减少HTTP请求数

通过 Webpack 配置,合并文件和使用图片精灵,同时我们可以将一些小图片转为base64格式(虽然会减少请求,但是转为base64资源体积会变大一点,所有不推荐进行大图片base64处理)

javascript 复制代码
// webpack.config.js
const SpriteLoaderPlugin = require('svg-sprite-loader/plugin');

module.exports = {
    // 其他配置...
    module: {
        rules: [
            {
                test: /\.svg$/,
                use: ['svg-sprite-loader']
            }
        ]
    },
    plugins: [
        new SpriteLoaderPlugin()
    ]
};

预加载和预获取

使用 Webpack 插件进行预加载和预获取。

javascript 复制代码
// webpack.config.js
const PreloadWebpackPlugin = require('preload-webpack-plugin');

module.exports = {
    // 其他配置...
    plugins: [
        new PreloadWebpackPlugin({
            rel: 'preload',
            as: 'script',
            include: 'allChunks'
        })
    ]
};

使用更高效的图片格式

通过 Webpack 配置,使用现代图片格式,如 WebP(但是得注意浏览器兼容性)。

javascript 复制代码
// webpack.config.js
const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');

module.exports = {
    // 其他配置...
    module: {
        rules: [
            {
                test: /\.(jpe?g|png|gif|svg)$/i,
                type: 'asset',
                use: [
                    {
                        loader: ImageMinimizerPlugin.loader,
                        options: {
                            minimizerOptions: {
                                plugins: [
                                    ['imagemin-webp', { quality: 75 }]
                                ]
                            }
                        }
                    }
                ]
            }
        ]
    }
};

图片懒加载和路由懒加载

通过IntersectionObserver API和自定义指令来实现图片懒加载,路由懒加载即用vue的动态路由@import引入即可

javascript 复制代码
export default {
    inserted(el) {
        const loadImage = () => {
            const imageElement = el.tagName === 'IMG' ? el : el.querySelector('img');
            
            if (imageElement) {
                imageElement.src = imageElement.dataset.src;
                imageElement.onload = () => el.classList.add('loaded');
            }
        };

        const handleIntersect = (entries, observer) => {
            entries.forEach(entry => {
                if (entry.isIntersecting) {
                    loadImage();
                    observer.unobserve(el);
                }
            });
        };

        const options = {
            root: null,
            threshold: 0.1
        };

        const observer = new IntersectionObserver(handleIntersect, options);
        observer.observe(el);
    }
};

页面渲染优化

优化CSS

将 CSS 外链放在页面顶部,因为这样可以确保页面在加载时尽快应用样式,从而避免样式闪烁(FOUC,Flash of Unstyled Content)并提升用户体验。

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Example Page</title>
    <!-- 将 CSS 外链放在页面顶部 -->
    <link rel="stylesheet" href="styles/main.css">
    <link rel="stylesheet" href="styles/theme.css">
</head>
</html>

使用CSS3动画代替JavaScript动画

使用 CSS3 动画而不是 JavaScript 动画(原理: transform等css3属于是独立的图层,不会影响其他图层,而且使用GPU加速),以减少重排和重绘。

css 复制代码
.box {
    transition: transform 0.5s, opacity 0.5s;
}

.box:hover {
    transform: translateX(100px);
    opacity: 0.5;
}

将JavaScript放在页面底部

将 JavaScript 文件放在 <body> 标签的底部(现代浏览器支持async和defer后就不需要了)

html 复制代码
<body>
    <!-- Content -->
    <script src="bundle.js"></script>
</body>

使用async和defer属性

使用 asyncdefer 属性加载外部 JavaScript 文件。

html 复制代码
<script src="bundle.js" async></script>
<!-- 或者 -->
<script src="bundle.js" defer></script>

减少和优化DOM操作

减少不必要的 DOM 操作,合并多次操作为一次。

javascript 复制代码
// Before
element.style.width = '100px';
element.style.height = '100px';

// After
element.style.cssText = 'width: 100px; height: 100px;';

使用Virtual DOM

使用虚拟 DOM 技术(如 React)减少直接操作 DOM 带来的开销。

javascript 复制代码
// 使用 React 示例
import React, { useState } from 'react';

function App() {
    const [count, setCount] = useState(0);

    return (
        <div>
            <p>{count}</p>
            <button onClick={() => setCount(count + 1)}>Increment</button>
        </div>
    );
}

避免布局抖动

在操作 DOM 和样式时,避免可能导致重排的操作,对样式进行统一处理

javascript 复制代码
// Before
element.style.margin = '10px';
element.style.padding = '20px';
element.style.border = '1px solid #000';

// After
element.style.cssText = 'margin: 10px; padding: 20px; border: 1px solid #000;';

使用will-change提示浏览器优化

使用 will-change 属性可以提示浏览器即将发生的变化,使浏览器提前进行优化。

css 复制代码
.box {
    will-change: transform, opacity;
}

使用服务端渲染 (SSR)

使用服务端渲染技术提前生成 HTML 内容,减少客户端渲染的负担。

javascript 复制代码
// 使用 Next.js 进行 SSR 示例
import React from 'react';
import { renderToString } from 'react-dom/server';
import App from './App';

const html = renderToString(<App />);

延迟加载资源

延迟加载图片和非关键 CSS、JavaScript 文件。

html 复制代码
<img src="image.jpg" loading="lazy" alt="Lazy loaded image">

<script>
    var link = document.createElement('link');
    link.rel = 'stylesheet';
    link.href = 'non-critical-styles.css';
    document.head.appendChild(link);
</script>
相关推荐
一條狗13 分钟前
隨筆 20241224 ts寫入excel表
开发语言·前端·typescript
小码快撩18 分钟前
vue应用移动端访问缓慢问题
前端·javascript·vue.js
低调之人23 分钟前
Fiddler勾选https后google浏览器网页访问不可用
前端·测试工具·https·fiddler·hsts
Riesenzahn28 分钟前
使用vue如何监听元素尺寸的变化?
前端·javascript
阿征学IT32 分钟前
圣诞快乐(h5 css js(圣诞树))
前端·javascript·css
程序员黄同学35 分钟前
如何使用 Flask 框架创建简单的 Web 应用?
前端·python·flask
Sword9936 分钟前
豆包 MarsCode AI Apply功能揭秘:自动代码应用与 Diff 实现
前端·人工智能·豆包marscode
前端与小赵36 分钟前
什么是全栈应用,有哪些特点
前端
a1ex36 分钟前
shadcn/ui 动态 pagination
前端
安小华0271 小时前
html(超文本标记语言)
前端·html