前端代码分割与懒加载:让你的应用飞起来

前端代码分割与懒加载:让你的应用飞起来

毒舌时刻

代码分割和懒加载?听起来就像是前端工程师为了掩饰自己代码写得太烂而发明的借口。你写的代码那么大,加载时间那么长,不分割能行吗?

你以为随便分割一下代码就能解决性能问题?别做梦了!如果分割策略不合理,反而会导致更多的网络请求,让应用变得更慢。

为什么你需要这个

  1. 减少初始加载时间:通过代码分割,只加载当前页面所需的代码,减少初始加载时间,提高用户体验。
  2. 优化资源利用:只加载用户需要的代码,避免加载不必要的资源,优化内存和带宽使用。
  3. 提高首屏渲染速度:快速加载首屏所需的代码,让用户尽快看到页面内容。
  4. 支持大型应用:对于大型应用,代码分割可以避免打包后的文件过大,导致加载时间过长。

反面教材

// 这是一个典型的不使用代码分割的应用 import React from 'react'; import ReactDOM from 'react-dom'; import Home from './pages/Home'; import About from './pages/About'; import Contact from './pages/Contact'; import Dashboard from './pages/Dashboard'; import Settings from './pages/Settings'; import UserProfile from './pages/UserProfile'; import AdminPanel from './pages/AdminPanel'; import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'; function App() { return ( <Router> <Routes> <Route path="/" element={<Home />} /> <Route path="/about" element={<About />} /> <Route path="/contact" element={<Contact />} /> <Route path="/dashboard" element={<Dashboard />} /> <Route path="/settings" element={<Settings />} /> <Route path="/user-profile" element={<UserProfile />} /> <Route path="/admin" element={<AdminPanel />} /> </Routes> </Router> ); } ReactDOM.render(<App />, document.getElementById('root')); 

问题

  • 所有页面的代码都打包在一个文件中,导致初始加载时间过长
  • 即使用户只访问首页,也会加载所有页面的代码
  • 大型应用的打包文件会变得非常大,影响加载速度
  • 无法实现按需加载,浪费带宽和内存

正确的做法

React中的代码分割与懒加载

// 使用React.lazy和Suspense实现懒加载 import React, { lazy, Suspense } from 'react'; import ReactDOM from 'react-dom'; import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'; // 懒加载页面组件 const Home = lazy(() => import('./pages/Home')); const About = lazy(() => import('./pages/About')); const Contact = lazy(() => import('./pages/Contact')); const Dashboard = lazy(() => import('./pages/Dashboard')); const Settings = lazy(() => import('./pages/Settings')); const UserProfile = lazy(() => import('./pages/UserProfile')); const AdminPanel = lazy(() => import('./pages/AdminPanel')); // 加载中组件 const Loading = () => <div>Loading...</div>; function App() { return ( <Router> <Suspense fallback={<Loading />}> <Routes> <Route path="/" element={<Home />} /> <Route path="/about" element={<About />} /> <Route path="/contact" element={<Contact />} /> <Route path="/dashboard" element={<Dashboard />} /> <Route path="/settings" element={<Settings />} /> <Route path="/user-profile" element={<UserProfile />} /> <Route path="/admin" element={<AdminPanel />} /> </Routes> </Suspense> </Router> ); } ReactDOM.render(<App />, document.getElementById('root')); 

Webpack中的代码分割

// webpack.config.js module.exports = { entry: { main: './src/index.js', }, output: { filename: '[name].[contenthash].js', chunkFilename: '[name].[contenthash].chunk.js', }, optimization: { splitChunks: { chunks: 'all', cacheGroups: { vendor: { test: /[\\/]node_modules[\\/]/, name: 'vendors', chunks: 'all', }, }, }, }, }; 

基于路由的代码分割

// 使用React Router和React.lazy实现基于路由的代码分割 import React, { lazy, Suspense } from 'react'; import { BrowserRouter as Router, Routes, Route, Navigate } from 'react-router-dom'; // 懒加载路由组件 const Home = lazy(() => import('./pages/Home')); const About = lazy(() => import('./pages/About')); const Contact = lazy(() => import('./pages/Contact')); const Dashboard = lazy(() => import('./pages/Dashboard')); const Settings = lazy(() => import('./pages/Settings')); const UserProfile = lazy(() => import('./pages/UserProfile')); const AdminPanel = lazy(() => import('./pages/AdminPanel')); // 加载中组件 const Loading = () => ( <div className="loading"> <div className="loading-spinner"></div> <p>Loading...</p> </div> ); // 错误边界组件 class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { hasError: false }; } static getDerivedStateFromError(error) { return { hasError: true }; } componentDidCatch(error, errorInfo) { console.error('Error:', error); console.error('Error Info:', errorInfo); } render() { if (this.state.hasError) { return <div>Something went wrong. Please try again later.</div>; } return this.props.children; } } function App() { return ( <Router> <ErrorBoundary> <Suspense fallback={<Loading />}> <Routes> <Route path="/" element={<Home />} /> <Route path="/about" element={<About />} /> <Route path="/contact" element={<Contact />} /> <Route path="/dashboard" element={<Dashboard />} /> <Route path="/settings" element={<Settings />} /> <Route path="/user-profile" element={<UserProfile />} /> <Route path="/admin" element={<AdminPanel />} /> <Route path="*" element={<Navigate to="/" replace />} /> </Routes> </Suspense> </ErrorBoundary> </Router> ); } export default App; 

基于条件的代码分割

// 基于条件懒加载组件 import React, { lazy, Suspense, useState } from 'react'; // 懒加载重型组件 const HeavyComponent = lazy(() => import('./HeavyComponent')); function App() { const [showHeavyComponent, setShowHeavyComponent] = useState(false); return ( <div> <h1>Home Page</h1> <button onClick={() => setShowHeavyComponent(true)}> Load Heavy Component </button> {showHeavyComponent && ( <Suspense fallback={<div>Loading heavy component...</div>}> <HeavyComponent /> </Suspense> )} </div> ); } export default App; 

毒舌点评

代码分割和懒加载确实能提高应用的性能,但我见过太多开发者滥用这个特性,导致应用变得更加复杂。

想象一下,当你为了分割代码而分割代码,把原本简单的应用拆分成无数个小模块,结果导致网络请求变得更多,加载时间反而增加了。这不是得不偿失吗?

还有那些过度使用懒加载的开发者,连一些轻量级的组件也懒加载,结果导致用户点击按钮后还要等待组件加载,影响用户体验。

所以,在使用代码分割和懒加载时,一定要把握好度。不要为了分割而分割,要根据实际情况来决定哪些代码需要分割,哪些不需要。

当然,对于大型应用来说,代码分割和懒加载是必不可少的。但对于小型应用,过度的代码分割反而会增加开发成本和维护难度。

最后,记住一句话:代码分割和懒加载的目的是为了提高应用的性能和用户体验,而不是为了炫技。如果你的代码分割策略导致应用变得更慢,那你就失败了。

Read more

使用 Delphi + WebView4Delphi 初步使用完整指南

WebView4Delphi 可以做什么 WebView4Delphi 是 Delphi/ C++Builder 的浏览器控件封装,基于 Microsoft Edge WebView2。简单来说,它可以在 Delphi 桌面程序里嵌入完整的 Chromium 内核浏览器,支持最新的网页标准和功能。 WebView4Delphi 不仅是一个“浏览器控件”,更是 Delphi 桌面应用与现代 Web 技术的桥梁。 你可以把它当作:内嵌网页的 UI 窗口/桌面自动化工具/脚本和插件平台 它能做的事情几乎只受你的 Delphi 与 JS 技能限制。 一.下载与安装 WebView4Delphi 从 GitHub 官方仓库下载 WebView4Delphi: 访问 https://github.com/salvadordf/

【详细精选】前端面试题(2026精选附详细解答)包含10w数据展示优化、前端核心

【详细精选】前端面试题(2026精选附详细答案)包含10w数据展示优化、前端核心 * 前端面试题详细解答 * 1. ES6新特性详解(重要10个) * 核心特性 * 其他重要特性 * 2. 什么是跨域 * 同源策略 * 跨域解决方案 * 1.CORS(跨域资源共享) * 2.JSONP * 3. 代理服务器 * 4. WebSocket * 5. Nginx反向代理 * 3. 监听数组变化 * Vue2的实现原理 * Vue3的实现原理 * 4. v-if vs v-show * 原理对比 * 差异对比表 * 源码分析 * 5. 网页加载优化 * 性能指标(Core Web Vitals) * 优化策略 * 1. 代码优化 * 2. 资源优化 * 3. 缓存策略

【前端】从零开始搭建现代前端框架:React 19、Vite、Tailwind CSS、ShadCN UI-第二章《快速开始:使用 Vite + TypeScript 初始化项目》

【前端】从零开始搭建现代前端框架:React 19、Vite、Tailwind CSS、ShadCN UI-第二章《快速开始:使用 Vite + TypeScript 初始化项目》

从零开始搭建现代前端框架:React 19、Vite、Tailwind CSS、ShadCN UI、Zustand 完整实战教程 第 2 章:快速开始 — 使用 Vite + TypeScript 初始化项目 在上一章中,我们明确了项目目标、技术栈与未来的总体架构路线。本章将正式开始动手,从零初始化一个 基于 React 19 + TypeScript + Vite 的开发环境。 本章你将完成: * 创建项目目录 * 初始化 Vite 项目(React + TS 模板) * 安装所有必要依赖 * 配置基础开发环境(ESLint / Prettier / Tailwind 前置) * 解析 package.json 结构,理解项目运行机制 完成本章后,你将拥有一个可以运行、

H.265 (HEVC) 网页播放:WebAssembly + FFmpeg 实现浏览器端的硬解/软解兼容方案

H.265 (HEVC) 网页播放:WebAssembly + FFmpeg 实现浏览器端的硬解/软解兼容方案

标签: #WebAssembly #FFmpeg #H.265 #WebCodecs #音视频开发 #前端性能 📉 前言:浏览器对 H.265 的“爱恨情仇” 为什么 <video src="video.h265.mp4"> 在 Chrome 里放不出来? 因为 H.265 的专利池太深了。只有 Safari (即使是 iOS) 和 Edge (需硬件支持) 原生支持较好。 我们的目标是构建一套混合解码方案: 1. 优先硬解 (WebCodecs):如果浏览器支持硬件加速(如 Chrome 94+ 的 WebCodecs),直接调用