乐闻世界logo
搜索文章和话题

面试题手册

Chrome 打开一个页面需要启动多少进程?分别有哪些进程?

在谷歌Chrome浏览器中,当您打开一个新的网页时,Chrome通常会启动几个进程。这是因为Chrome采用了多进程架构来提升性能和安全性。具体需要启动的进程数量可能会根据您的浏览器设置、扩展插件、打开的标签页数量以及Chrome的版本不同而有所变化。以下是Chrome打开一个新页面时可能会启动的主要进程类型:浏览器进程(Browser Process):这是主要的控制进程,管理Chrome用户界面的所有方面,包括地址栏、书签、前进和后退按钮等。它也负责文件的下载和安全策略。渲染进程(Renderer Process):每个标签页通常有自己的渲染进程(在默认情况下)。渲染进程负责一个网页的渲染,包括HTML、CSS、JavaScript的执行等。这种隔离机制可以确保如果一个网页崩溃,它不会影响到其他标签页。插件进程(Plugin Process):如果页面使用了插件(如Adobe Flash Player,虽然现在已经逐渐弃用),每个插件可能有其自己的进程。GPU进程(GPU Process):Chrome有一个专门的GPU进程,用来处理GPU加速的任务,例如3D CSS效果、WebGL内容等。扩展进程(Extension Process):如果您安装了Chrome扩展,每一个活动的扩展通常都会有自己的进程。例如,假设您打开了一个新的Chrome窗口,并在其中打开了一个包含多媒体内容且有多个扩展活动的复杂网页,那么您可能至少会看到如下的几个进程:一个浏览器进程一个渲染进程多个扩展进程(根据活动的扩展数量)一个GPU进程所以在这个假设中,打开这个页面至少需要4种类型的进程,具体进程数取决于活动扩展的数量。此外,从Chrome 67版本开始,Chrome推出了一种名为“Site Isolation”的安全特性,这会导致更多的进程生成,因为它会为来自不同站点的渲染器分别创建不同的进程,以加强站点之间的隔离。这意味着即使是单个标签页也可能因为加载了来自不同域的iframe而产生多个渲染进程。
阅读 28·2024年6月24日 16:43

HTTP 有哪些常用的状态码?

HTTP状态码是服务器用来告知客户端关于请求的处理结果的一组标准代码。以下是一些常用的HTTP状态码及其含义:1xx - 信息响应100 Continue:客户端应继续其请求101 Switching Protocols:服务器根据客户端的请求切换协议2xx - 成功200 OK:请求成功,通常用于GET与POST请求201 Created:请求成功并且服务器创建了新的资源202 Accepted:服务器已接受请求,但尚未处理204 No Content:请求成功,但没有内容要返回3xx - 重定向301 Moved Permanently:请求的页面已永久移至新位置302 Found(之前是Moved Temporarily):请求的页面临时移至其他位置304 Not Modified:自从上次请求后,请求的页面未修改过4xx - 客户端错误400 Bad Request:服务器无法理解请求的格式401 Unauthorized:请求没有进行身份验证或验证未通过403 Forbidden:客户端没有权限访问该请求的内容404 Not Found:服务器找不到请求的资源405 Method Not Allowed:不允许使用请求中指定的方法408 Request Timeout:服务器等待客户端发送的请求时间过长,超时429 Too Many Requests:用户在给定的时间内发送了太多请求(“限速”)5xx - 服务器错误500 Internal Server Error:服务器遇到了使其无法处理请求的情况501 Not Implemented:服务器不支持请求的功能,无法完成请求502 Bad Gateway:服务器作为网关或代理,从上游服务器收到无效响应503 Service Unavailable:服务器目前无法使用(由于超载或停机维护)504 Gateway Timeout:服务器作为网关或代理,但没有及时从上游服务器收到请求例如,如果您开发的Web应用程序中有一段代码负责处理用户登录请求,当用户成功登录时,您的服务器应该返回200 OK状态码。如果用户尝试访问需要特定权限的资源而他们未经授权,则应返回403 Forbidden。而如果用户请求一个不存在的页面,如一个未定义的路由或资源,服务器应当返回404 Not Found状态码。
阅读 89·2024年6月24日 16:43

webpack 的热更新原理是什么?详细聊聊热更新的流程

Webpack 的热更新,也被称作热替换(Hot Module Replacement,HMR),是一个在应用程序运行时更新、添加或删除模块,而无需完全刷新页面的过程。这一功能对于前端开发非常有用,因为它可以显著提高开发效率,让开发者看到代码变更的实时效果。以下是其工作原理和流程的概述: 热更新原理1. 服务器和客户端通过WebSocket通信HMR 功能依赖于 WebSocket,这允许服务器向客户端推送实时更新。当你的应用正在运行时,Webpack dev server 会启动一个 WebSocket 服务器,用于监听文件的变化。2. 模块热替换插件Webpack 使用 HotModuleReplacementPlugin 插件来实现模块的热替换。这个插件在编译过程中会注入 HMR runtime 代码。3. Manifest 文件当构建过程结束时,Webpack 会产生一个 manifest 文件,用来记录每个模块的最新版本号。这个文件会告诉 HMR runtime 哪些文件发生了变化。4. 更新生命周期HMR 有一套生命周期事件,允许开发者控制如何处理热替换,例如 module.hot.accept, module.hot.decline 和 module.hot.dispose 等。热更新流程1. 文件修改开发者修改一个或多个文件,Webpack 监听到文件变化并将其重新编译。2. 编译构建Webpack 重新构建改动的模块,并生成新的 manifest 文件和更新后的模块代码。3. 文件变更通知Webpack dev server 通过 WebSocket 向客户端发送一个或多个更新的信号(通常包含变更模块的哈希值)。4. 接收更新客户端收到更新信号后,通过 HMR runtime 请求更新信息(即新的 manifest 文件)。5. 请求更新文件客户端根据 manifest 文件获取最新的模块代码,通常是通过 JSONP 请求。6. 替换模块HMR runtime 根据更新信息(manifest)解析需要更新的模块,并且对其进行替换。如果设置了模块的热替换处理函数(例如通过 module.hot.accept),则会先执行这些函数来处理模块的替换逻辑。7. 更新反映到视图一旦模块更新完毕,如果是组件或样式等,变更会立即反映在应用程序的 UI 上,而无需全页刷新。示例例如,当开发者修改了一个 React 组件的代码并保存时,Webpack 会重新编译这个模块,并推送更新到客户端。客户端接收更新后,通过 React Hot Loader 这样的库,实现 React 组件的无缝替换,使得开发者能够即时看到变更效果。这就是热更新的基本原理和流程。在日常开发中,这样的功能极大减少了重复的加载时间,提升了开发体验和效率。
阅读 20·2024年6月24日 16:43

GET和POST的区别,何时使用POST?

GET和POST都是HTTP协议中用来发送请求的方法,它们之间有几个主要的区别:数据传输位置:GET方法通过URL传递信息,一般用于请求服务器发送资源,比如网页、图片、视频等。参数通过URL的查询字符串(query string)部分传递,形如?key1=value1&key2=value2。POST方法通常用于提交数据给服务器,比如表单数据。数据不会通过URL传递,而是放在HTTP请求的正文(body)中。数据大小限制:GET请求因为数据在URL中,所以大小受到URL长度的限制,不同的浏览器和服务器对URL长度的限制不同,但一般限制在2048字符之内。POST请求将数据存放在请求体中,理论上没有大小限制,适合传递大量数据。安全性:GET请求由于参数在URL中,所以安全性相对较低。敏感信息如密码不应该通过GET方法发送,因为这样的信息可以在浏览器历史、服务器日志等地方被轻易看到。POST请求更为安全,因为数据不会在URL中显示,相对GET而言,较难被截获。可缓存:GET请求可以被缓存,可以被书签保存,也可以在浏览器历史中回溯。POST请求不会被缓存,不会保存在浏览器历史中,通常用于更新服务器上的信息。幂等性:GET请求应该是幂等的,意味着多次执行同一个GET请求,服务器上的资源状态不会发生变化。POST请求不是幂等的,它用于创建或修改资源,所以多次执行同一个POST请求可能会多次创建或修改数据。何时使用POST?POST通常用于以下情况:发送用户填写的表单数据到服务器,尤其是包含敏感信息(如密码)时。上传文件或大量数据到服务器。需要创建或更新资源时,比如在数据库中新增一条记录。执行需要对资源状态产生影响的操作,比如订单提交。例如,如果运行一个电商网站,当用户填写了结账信息并点击“确认订单”按钮时,你应该使用POST请求来提交表单数据,因为这涉及到创建新的订单记录在服务器上,同时可能包含用户的敏感信息。
阅读 58·2024年6月24日 16:43

什么是BFC吗?BFC有哪些使用场景?

什么是BFCBFC (Block Formatting Context) 是 Web 页面的可视化 CSS 渲染的一部分,它是块级盒布局发生的区域,也是浮动元素与其他元素的交互限定区域。 如何创建 BFC在 CSS 中,以下几种方式可以创建 BFC:根元素或其它包含它的元素浮动元素 (元素的 float 不是 none)绝对定位元素(元素的 position 为 absolute 或 fixed)内联块(元素的 display 为 inline-block)表格单元格 (元素的 display 为 table-cell,HTML 表格单元格默认为 table-cell)表格标题(元素的 display 为 table-caption,HTML 表格标题默认为 table-caption)匿名表格单元格元素(元素的 display 为 table、table-row、table-row-group、table-header-group、table-footer-group 或 table-cell且是匿名的)overflow 值不为 visible 的块级元素弹性元素(display 为 flex 或 inline-flex 元素的直接子元素)网格元素(display 为 grid 或 inline-grid 元素的直接子元素)contain 值为 layout、paint 或 size 的元素多列容器(元素的 column-count 或 column-width 不为 auto,包括 column-count 为 1)column-span 为 all 的元素总是会创建一个新的 BFC,这样使得元素能跨越多列。14. BFC 有哪些规则BFC遵循一些特殊的规则,主要包括:内部的 Box 会在垂直方向一个接一个地放置。也就是说,在 BFC 中,块级盒子都是紧贴在一起的。垂直方向的距离由 margin 决定,两个相邻 Box 的 margin 会发生重叠。Box 垂直方向的距离由 margin 决定。属于同一个 BFC 的两个相邻 Box 的 margin 会发生重叠。每个元素的左边,与包含块(Containing Block)的左边相接触。这句话的意思是:在 BFC 中,每一个 Box 的左边都贴紧包含块的左边。BFC的区域不会与 float box 重叠。BFC 是浮动元素和其它元素交互的界限,BFC 与浮动盒子不会重叠。计算 BFC 的高度时,浮动元素也参与计算。也就是说,如果 BFC 内部有浮动的元素,那么 BFC 的高度会扩大,以包含这个浮动元素,也就是说 BFC 是可以包含浮动元素的。6. BFC 的应用场景通过掌握 BFC,我们可以解决一些常见的 CSS 布局问题,如以下几种场景:避免外边距折叠在 BFC 中,处于同一 BFC 中的两个块元素的垂直外边距会发生折叠。如果你不想让这两个外边距折叠,你可以将元素放在不同的 BFC 中。清除浮动由于 BFC 可以包含浮动,我们可以用 BFC 来清除内部浮动,避免造成父元素高度塌陷。当父元素内部的子元素全部浮动后,它们脱离了正常的文档流,父元素就会失去高度,这个现象通常被称为高度塌陷。如果把父元素变为一个 BFC,那么它可以“感知”到浮动元素,从而包裹住浮动元素。这是因为 BFC 在生成时,会计算内部的浮动元素。为了将父元素变为一个 BFC,我们通常会使用 overflow 属性,如:overflow:auto 或者 overflow:hidden。.container { overflow: auto;}制作自适应两栏布局BFC 也可以用于构建布局。比如,常见的两栏布局,左栏固定宽度,右栏自适应:HTML 结构如下:<div class="container"> <div class="left"></div> <div class="right"></div></div>CSS 样式如下:.container { width: 100%;}.left { float: left; width: 200px; height: 200px; background-color: red;}.right { overflow: hidden; height: 200px; background-color: green;}在这个例子中,left 元素设置了浮动,然后 right 元素设置 overflow:hidden,这样 right 就基于 BFC,从而填充剩下的空间。综上,BFC 在处理一些布局问题和元素间的关系时非常有用,它是 CSS 中的一个重要概念,理解和掌握它可以帮助我们更好地应对布局难题。
阅读 59·2024年6月24日 16:43

webpack 的 loader 的作用是什么?如何自定义一个loader?

webpack 的 loader 的作用是什么?webpack 的 loader 有着非常关键的作用。在 webpack 打包过程中,loader 负责处理源代码文件,并且将其转换成 webpack 能够处理的模块。由于 webpack 本身只理解 JavaScript,所以当我们需要在 JavaScript 代码中导入 CSS、图片或者其他非 JavaScript 文件时,就需要用到 loader。例如,如果我们想在 JavaScript 中导入一个 CSS 文件,我们会使用 style-loader 和 css-loader。这两个 loader 分别做两件事情:css-loader 会处理 import 和 url() 等,就像 JavaScript 模块一样处理 CSS 文件。style-loader 会将计算后的 CSS 注入到页面的 <style> 标签中。其他常用的 loader 还包括:babel-loader:将 ES6+ 代码转换成兼容性更好的 JavaScript 代码。file-loader:处理文件导入,将文件输出到输出目录,并返回文件的 URL。url-loader:像 file-loader 但在文件大小低于指定的限制时会返回 Data URL。sass-loader:将 SASS/SCSS 文件编译成 CSS。等等。Loader 可以链式调用,每个 loader 将上一个处理的结果传递给下一个 loader,直到最后输出 webpack 能够处理的 JavaScript 模块。如何自定义一个 loader?自定义一个 loader 需要遵循一定的步骤:创建一个 JavaScript 函数:这个函数将接收源文件的内容作为参数。函数内部,可以使用任何 JavaScript 代码来处理输入的内容。函数最后需要返回处理后的内容,或者使用 this.callback 方法异步返回处理结果和可能的 map。遵守 loader 的规则:接收源文件的内容作为参数。不修改原始内容,返回一个新的字符串或者 Buffer。在需要时,可以通过 this.async 返回一个异步函数。使用 this.cacheable 标记 loader 的结果是否可缓存。通过 this.loaders 访问配置中的其他 loaders。导出这个函数:使用 module.exports 导出这个 loader 函数。在 webpack 配置中使用你的 loader:在 module.rules 中添加一个规则来使用你的 loader。例子:假设我们要创建一个简单的 markdown loader,将 markdown 转换为 HTML。const marked = require('marked');module.exports = function (markdown) { // 将 markdown 转换成 HTML const html = marked(markdown); // 返回 HTML 字符串 return `module.exports = ${JSON.stringify(html)}`;};然后在 webpack 配置文件中使用这个 loader:module.exports = { // ... module: { rules: [ { test: /\.md$/, use: [ { loader: 'html-loader' }, { loader: path.resolve('./path/to/your/custom-markdown-loader.js') } ] } ] } // ...};注意,这里我们使用了 html-loader 来处理我们自定义 loader 输出的 HTML 字符串,这样做可以确保 HTML 字符串也遵循 webpack 的模块系统。通过这种方式,开发者可以根据项目需求创建特定功能的 loader,以适应各种类型的文件处理场景。
阅读 29·2024年6月24日 16:43

React 中 useRef 的使用方式和使用场景有哪些?

在React中,useRef是一个非常有用的Hook,它主要被用来访问DOM元素和保存跨渲染周期持久的可变数据。useRef返回一个可变的ref对象,其 .current属性被初始化为传递给 useRef的参数(initialValue)。返回的对象在组件的整个生命周期内保持不变。 使用方式首先,我们需要在组件内部导入 useRef:import React, { useRef } from 'react';然后可以使用 useRef来创建一个ref对象:const myRef = useRef(initialValue);其中 initialValue是ref对象 .current属性的初始值。使用 myRef.current可以访问或者修改这个值。使用场景有几种常见的场景适合使用 useRef:1. 访问DOM元素当你需要直接操作DOM节点时,比如获取输入框的值或者设置焦点,可以使用 useRef。function TextInputWithFocusButton() { const inputEl = useRef(null); const onButtonClick = () => { // 直接访问DOM元素来设置焦点 inputEl.current.focus(); }; return ( <> <input ref={inputEl} type="text" /> <button onClick={onButtonClick}>Set focus</button> </> );}2. 保存任意可变值另一个使用场景是当你想要保存一个在组件的整个生命周期中都保持不变的值,这个值不会触发组件的重新渲染。function Timer() { const intervalRef = useRef(); useEffect(() => { const id = setInterval(() => { // 执行一些操作 }, 1000); intervalRef.current = id; return () => { clearInterval(intervalRef.current); }; }, []); // ...}在这个例子中,intervalRef被用来保存一个间隔定时器的ID,虽然这个ID会在不同的渲染周期间发生变化,但我们不希望这种变化触发组件的重新渲染。3. 跟踪上一个值useRef也可以被用来跟踪组件中的变量或状态的旧值。function Counter() { const [count, setCount] = useState(0); const prevCountRef = useRef(); useEffect(() => { prevCountRef.current = count; }); const prevCount = prevCountRef.current; // 在渲染时获取旧的值 // ...}这里 prevCountRef用于存储每次渲染后的 count值,可以在任何时候访问前一个状态的值,而不会触发组件的重新渲染。
阅读 54·2024年6月24日 16:43

React 中 useContext 的使用方式和使用场景有哪些?

React 中的 useContext 钩子是一个用于让组件能够访问 React 上下文(Context)的工具。这个上下文设计用于共享那些对于一个组件树而言是“全局”的数据,如当前认证的用户、主题或首选语言等。 使用方式:首先,你需要创建一个 Context 对象。这可以通过 React.createContext() 完成,并且通常会在组件树的较高层级上完成。import React from 'react';// 创建 Context 对象const MyContext = React.createContext(defaultValue);一旦你有了一个 Context 对象,就可以使用 Context.Provider 组件包裹你的组件树的一部分,以在其下所有的组件中提供上下文数据。<MyContext.Provider value={/* 某些值 */}> {/* 组件树 */}</MyContext.Provider>然后,在组件树中的任何层级上,你都可以使用 useContext 钩子来访问该上下文。import React, { useContext } from 'react';function MyComponent() { // 使用 useContext 钩子获取上下文值 const contextValue = useContext(MyContext); return <div>{/* 使用 contextValue 做些什么 */}</div>;}通过使用 useContext 钩子,你不需要通过组件的 props 手动传递数据,可以直接访问上层组件通过 Context.Provider 提供的数据。使用场景:主题切换:当你想要在应用程序中切换主题时,你可以使用上下文来保持当前主题的状态,并在整个应用程序中轻松访问它。用户认证:在需要知道当前用户是否已经登录的多个组件中,你可以使用上下文来共享用户的登录状态和用户信息。国际化:你可以使用上下文来存储当前的语言设置,并在组件树中的任何地方访问它,以便于国际化。状态管理:在某些简单的情况下,你可以使用上下文来代替其他状态管理库(如 Redux),来存储和管理全局状态。示例:假设我们有一个需要在多个组件之间共享的用户认证状态,可以这样使用 useContext:// AuthContext.jsimport React, { createContext, useState } from 'react';// 创建上下文对象,初始值为 nullexport const AuthContext = createContext(null);// 创建一个提供者组件export const AuthProvider = ({ children }) => { const [authUser, setAuthUser] = useState(null); // 登录逻辑 const signIn = (username, password) => { // 假设验证逻辑在这里 const user = { name: 'Mock User', username }; setAuthUser(user); }; // 登出逻辑 const signOut = () => { setAuthUser(null); }; return ( <AuthContext.Provider value={{ authUser, signIn, signOut }}> {children} </AuthContext.Provider> );};// App.jsimport React from 'react';import { AuthProvider } from './AuthContext';import MyComponent from './MyComponent';function App() { return ( <AuthProvider> <MyComponent /> </AuthProvider> );}// MyComponent.jsimport React, { useContext } from 'react';import { AuthContext } from './AuthContext';function MyComponent() { const { authUser, signIn, signOut } = useContext(AuthContext); return ( <div> {authUser ? ( <div> <p>Welcome, {authUser.name}!</p> <button onClick={signOut}>Sign out</button> </div> ) : ( <button onClick={() => signIn('user', 'password')}> Sign in </button> )} </div> );}
阅读 198·2024年6月24日 16:43

如何基于 Promise.all 实现Ajax请求的串行和并行?

Ajax请求的串行实现对于串行执行多个Ajax请求,我们通常需要确保一个请求完全完成后,再执行下一个请求。这可以通过链式调用then方法来实现,也就是在每个Promise对象的then方法中启动下一个Ajax请求。function ajaxRequest(url) { return new Promise((resolve, reject) => { // 这里是Ajax请求的代码,成功时调用resolve,失败时调用reject const xhr = new XMLHttpRequest(); xhr.open('GET', url); xhr.onload = () => resolve(xhr.responseText); xhr.onerror = () => reject(xhr.statusText); xhr.send(); });}const urls = ['/url1', '/url2', '/url3']; // 假设我们有多个请求需要串行处理let promiseChain = Promise.resolve(); // 初始化一个已完成的Promiseurls.forEach(url => { promiseChain = promiseChain.then(() => ajaxRequest(url)).then(response => { console.log('请求完成:', response); // 这里可以处理每个请求的响应 });});// 最后可以在所有请求都完成后执行一些操作promiseChain.then(() => { console.log('所有请求都已串行完成。');});在这个例子中,每个请求仅在前一个请求的then方法中被调用,这确保了请求的串行执行。Ajax请求的并行实现要并行执行多个Ajax请求,可以使用Promise.all方法。Promise.all接收一个Promise对象数组,等待所有的Promise对象都成功完成后,它将返回一个新的Promise,这个新Promise将解析为一个结果数组,数组中的每个结果对应于原Promise数组中的每个请求。function ajaxRequest(url) { return new Promise((resolve, reject) => { // 这里是Ajax请求的代码,成功时调用resolve,失败时调用reject const xhr = new XMLHttpRequest(); xhr.open('GET', url); xhr.onload = () => resolve(xhr.responseText); xhr.onerror = () => reject(xhr.statusText); xhr.send(); });}const urls = ['/url1', '/url2', '/url3']; // 假设我们有多个请求需要并行处理const promises = urls.map(ajaxRequest); // 创建一个包含所有请求的Promise数组Promise.all(promises).then(responses => { console.log('所有请求都已并行完成。'); responses.forEach(response => { console.log('请求完成:', response); // 这里可以处理每个请求的响应 });}).catch(error => { // 如果任何一个请求失败,这里会捕获到错误 console.error('请求失败:', error);});在这个例子中,Promise.all并行地处理所有的Ajax请求,并在所有请求成功完成后,按照请求的顺序输出响应结果。如果任何一个请求失败,Promise.all会立即拒绝,并返回第一个遇到的错误。这两种方法是处理多个Ajax请求时常用的串行和并行模式。根据实际需求选择合适的方式。在实际面试中,可以根据面试官的要求提供更详细的代码实例或解释。
阅读 45·2024年6月24日 16:43

基于 HTTP 网络层,前端能可以做哪些性能优化?

基于HTTP网络层的前端性能优化主要关注的是资源的加载和传输效率。以下是一些前端可以采取的性能优化措施:1. 减少HTTP请求次数合并文件:将多个CSS或JavaScript文件合并成单个文件以减少请求数量。精灵图(Sprite Maps):将多个小图标合并到一张图片中,通过CSS背景定位显示所需图标。内联图片(Data URIs):将小图像直接内嵌到HTML或CSS中,减少图片请求。2. 使用CDN(内容分发网络)分布式节点:CDN将静态资源缓存在全球的多个节点,使用户能从就近的服务器下载,降低延迟。缓存效率:CDN通常会对资源进行优化缓存,提高再次访问的速度。3. 缓存优化强缓存:通过设置HTTP头中的Cache-Control和Expires标识,使资源在客户端本地缓存,直到缓存过期。协商缓存:利用ETag和Last-Modified标识,仅当资源更新时才重新下载。4. 延迟加载和按需加载懒加载:对于非首屏图片、视频等资源进行懒加载,即滚动到可视区域后才加载。代码分割(Code Splitting):通过工具如Webpack实现模块的按需加载,避免单页应用加载过多不必要的JavaScript代码。5. 优化请求头和响应头压缩请求头:减少Cookie的大小和使用的数量,以及其他不必要的HTTP头部信息。Gzip/Brotli压缩:对文本资源进行Gzip或Brotli压缩,减少传输大小。6. HTTP/2和HTTP/3的使用多路复用:HTTP/2允许在同一个连接上并行传输多个请求响应,消除了队头阻塞问题。服务器推送:HTTP/2的Server Push可以提前发送资源,减少等待时间。QUIC协议:HTTP/3使用QUIC协议,减少连接建立时间,提升传输效率。7. 优化TLS/SSL握手TLS 1.3:使用更新的TLS版本可以减少握手过程中的往返次数。OCSP Stapling:通过服务器代替客户端查询证书状态,减少TLS握手的延迟。8. 优化资源的加载顺序关键请求优先:确保关键资源(如HTML、CSS、关键JavaScript函数)最先加载。异步加载:使用async和defer属性对非关键JavaScript脚本进行异步加载。9. WebP格式使用WebP:相比传统的JPEG或PNG格式,WebP格式在同等质量下具有更小的文件大小。10. Service Workers离线体验:Service Workers可以帮助缓存资源,并在无网络状态下提供访问。背景同步:Service Workers可以在后台进行数据同步或推送通知。举例来说,对于一个电商网站,我之前优化过的一个项目中,通过使用图片懒加载和WebP格式,网站首页的加载时间减少了约30%。利用HTTP/2的多路复用特性,也显著提高了资源加载的并行度,进一步减少了页面的完
阅读 52·2024年6月24日 16:43