跳到主要内容

3 篇博文 含有标签「基建」

查看所有标签

错误监控

try/catch

能捕获常规运行时错误,语法错误和异步错误不行

// 常规运行时错误,可以捕获 ✅
try {
console.log(notdefined);
} catch(e) {
console.log('捕获到异常:', e);
}

// 语法错误,不能捕获 ❌
try {
const notdefined,
} catch(e) {
console.log('捕获到异常:', e);
}

// 异步错误,不能捕获 ❌
try {
setTimeout(() => {
console.log(notdefined);
}, 0)
} catch(e) {
console.log('捕获到异常:',e);
}

总结:

  1. 能捕获包裹体内的同步执行错误。
  2. 不能捕获语法错误。
  3. 不能捕获异步任务错误。
  4. 不能捕获Promise任务错误。
  5. 不能捕获资源加载错误。

window.onerror

js错误收集,window.onerror,当 JS 运行时错误发生时,window 会触发一个 ErrorEvent 接口的 error 事件

window.onerror = function(message, source, lineno, colno, error) {
console.log('捕获到异常:', {message, source, lineno, colno, error});
}

先验证下几个错误是否可以捕获

// 常规运行时错误,可以捕获 ✅
window.onerror = function(message, source, lineno, colno, error) {
console.log('捕获到异常:',{message, source, lineno, colno, error});
}
console.log(notdefined);

// 语法错误,不能捕获 ❌
window.onerror = function(message, source, lineno, colno, error) {
console.log('捕获到异常:',{message, source, lineno, colno, error});
}
const notdefined,

// 异步错误,可以捕获 ✅
window.onerror = function(message, source, lineno, colno, error) {
console.log('捕获到异常:',{message, source, lineno, colno, error});
}
setTimeout(() => {
console.log(notdefined);
}, 0)

// 资源错误,不能捕获 ❌
<script>
window.onerror = function(message, source, lineno, colno, error) {
console.log('捕获到异常:',{message, source, lineno, colno, error});
return true;
}
</script>
<img src="https://abc.cn/image/kkk.png">

需要额外注意:跨域脚本加载错误只有一个“Script error”,并不能获取到错误信息。可以通过在<script>标签上添加“crossorigin”属性来解决这个问题。

总结:

  1. 能捕获所有同步执行错误。
  2. 不能捕获语法错误。
  3. 能捕获普通异步任务错误。
  4. 不能捕获Promise任务错误。
  5. 不能捕获async任务错误。
  6. 不能捕获资源加载错误。

window.addEventListener('error')

当一项资源(如图片或脚本)加载失败,加载资源的元素会触发一个 Event 接口的 error 事件,这些 error 事件不会向上冒泡到 window,但能被捕获。而window.onerror不能监测捕获

// 图片、script、css加载错误,都能被捕获 ✅
<script>
window.addEventListener('error', (error) => {
console.log('捕获到异常:', error);
}, true)
</script>
<img src="https://yun.tuia.cn/image/kkk.png">
<script src="https://yun.tuia.cn/foundnull.js"></script>
<link href="https://yun.tuia.cn/foundnull.css" rel="stylesheet"/>

// new Image错误,不能捕获 ❌
<script>
window.addEventListener('error', (error) => {
console.log('捕获到异常:', error);
}, true)
</script>
<script>
new Image().src = 'https://yun.tuia.cn/image/lll.png'
</script>

// fetch错误,不能捕获 ❌
<script>
window.addEventListener('error', (error) => {
console.log('捕获到异常:', error);
}, true)
</script>
<script>
fetch('https://tuia.cn/test')
</script>

相比window.onerror,通过window.addEventListener的方式我们可以捕获资源加载的错误

new Image运用的比较少,可以单独自己处理自己的错误。

但通用的fetch怎么办呢,fetch返回Promise,但Promise的错误不能被捕获,怎么办呢?

window.addEventListener('unhandledrejection')

Promise被 reject 且没有 reject 处理器的时候,会触发 unhandledrejection 事件

// 全局统一处理Promise
window.addEventListener("unhandledrejection", function(e){
console.log('捕获到异常:', e);
});
fetch('https://tuia.cn/test')

Vue错误

由于Vue会捕获所有Vue单文件组件或者Vue.extend继承的代码,所以在Vue里面出现的错误,并不会直接被window.onerror捕获,而是会抛给Vue.config.errorHandler。

/**
* 全局捕获Vue错误,直接扔出给onerror处理
*/
Vue.config.errorHandler = function (err) {
setTimeout(() => {
throw err
})
}

React错误

如果渲染的子组件不可信(比如来源于第三方),怎么保证程序的正常运行?

主要通过componentDidCatch,声明一个错误边界的组件

class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}

static getDerivedStateFromError(error) {
// 更新 state 使下一次渲染能够显示降级后的 UI
return { hasError: true };
}

componentDidCatch(error, errorInfo) {
// 你同样可以将错误日志上报给服务器
logErrorToMyService(error, errorInfo);
}

render() {
if (this.state.hasError) {
// 你可以自定义降级后的 UI 并渲染
return <h1>Something went wrong.</h1>;
}

return this.props.children;
}
}

class App extends React.Component {
render() {
return (
<ErrorBoundary>
<MyWidget />
</ErrorBoundary>
)
}
}

error boundaries并不会捕捉以下错误:React事件处理,异步代码,error boundaries自己抛出的错误

错误上报

经过上述的异常处理后,我们需要将收集到的错误进行整理(可以通过一些库来解析异常),将需要的信息发送到后台

ajax进行上报

发现错误的时候上传错误到接口进行存储。

但是存在一些问题:

  • 有严格的跨域限制
  • 上报请求可能会阻塞业务
  • 请求容易丢失(被浏览器强制cancel)

image上报

使用 POST 一个 gif 对其进行上报,携带错误信息

var img = new Image();
var errorReportURL = "https://your-server.com/log_error?";
var params = "message=" + encodeURIComponent(errorMessage) +
"&url=" + encodeURIComponent(url) +
"&line=" + lineNumber +
"&column=" + columnNumber +
"&error=" + encodeURIComponent(errorObj ? errorObj.stack : '');

img.src = errorReportURL + params;

为什么使用 1 x 1 的 gif

原因是:

  1. 没有跨域问题
  2. 发POST 请求之后不需要获取和处理数据、服务器也不需要发送数据
  3. 不会携带当前域名 cookie
  4. 不会阻塞页面加载,影响用户的体验,只需 new Image 对象
  5. 相比于 BMP/PNG 体积最小,可以节约 41% / 35% 的网络资源小

Navigator.sendBeacon() - Web API | MDN (mozilla.org)

navigator.sendBeacon() 方法可用于通过HTTP POST将少量数据异步传输到 Web 服务器。

它主要用于将统计数据发送到 Web 服务器,同时避免了用传统技术(如XMLHttpRequest)发送分析数据的一些问题

详细查看MDN

参考链接

javascript - 一文搞定前端错误捕获和上报 - GrowingIO技术专栏 - SegmentFault 思否

一篇讲透自研的前端错误监控 - 掘金 (juejin.cn)


鲸落前端基建阅读需 5 分钟

前言

SEO 代表搜寻引擎最佳化/搜寻引擎优化(英文全名Search Engine Optimization,简称SEO),是指通过了解搜寻引擎的自然排名的算法逻辑,以提高目标网站在有关搜寻引擎内排名的方式。

网站的 SEO 至关重要,它可以让你的网站获得更好的排名和流量,从而提高网站知名度。对于一些盈利的网站,做好seo,还可以以低成本提高投资回报率。

本文将为你带来非常全面的SEO方案🔥🔥🔥,当然了,网站SEO是长线工作,在做好一些基础的配置之后,更重要的是后期的维护,比如定期更新网站动态文章,不断寻找优质外链资源等🤌。

本文将以三个层面展开:

  1. TDK优化
  2. 网站质量
  3. SEO手段(10种手段)

TDK优化

TDK是Title(页面标题)、Meta Description(页面描述)和Meta Keywords(页面关键词)的缩写,对网站的这三个信息的提炼是网站SEO的重要环节。

但是由于一些原因,各大主流搜索引擎基本都已经大大降低甚至移除了 <keywords> 对排名的影响

title标签-网站名片

title标签相当于网站的名片,他会直接显示在搜索结果中。一个好的标题势必可以为网站带来流量,从而提升网站排名。

注意:网站标题避免冗长

<title>鲸落的个人博客</title>

META标签-网站信息

META标签是网页head区的辅助性标签,它的作用是经过配置一些参数用以描述页面属性。目前几乎所有搜索引擎都使用网上机器人自动查找meta值来给网页分类。

meta标签如何使用

meta标签的属性有两种:namehttp- equiv

"name"属性有以下配置项:

  • Keywords(关键词,现在不再重要了):逗号分隔的关键词列表(告诉搜索引擎页面是与什么相关的)
  • description(网站内容描述,很重要):页面描述。搜索引擎会把这个描述显示在搜索结果中
  • format-detection:格式检测,比如禁止识别电话,邮箱等
  • author:作者的名字
  • Robots:用来告诉搜索机器人哪些页面需要索引,哪些页面不需要索引
  • theme-color:网站主题色
<meta name="keywords" content="掘金,稀土,Vue.js,前端面试题,Kotlin,ReactNative,Python">

<meta name="description" content="掘金是面向全球中文开发者的技术内容分享与交流平台。我们通过技术文章、沸点、课程、直播等产品和服务,打造一个激发开发者创作灵感,激励开发者沉淀分享,陪伴开发者成长的综合类技术社区。">

<meta name="format-detection" content="telephone=no">

<meta name="author" content="cece">

<Meta name="Robots" Content="Nofollow">
/**
all:文件将被检索,且页面上的链接可以被查询;
none:文件将不被检索,且页面上的链接不可以被查询;(和 "noindex, no follow" 起相同作用)
index:文件将被检索;(让robot/spider登录)
follow:页面上的链接可以被查询;
noindex:文件将不被检索,但页面上的链接可以被查询;(不让robot/spider登录)
nofollow:文件将不被检索,页面上的链接可以被查询。(不让robot/spider顺着此页的连接往下探找)
*/

<meta name="theme-color" content="#4285f4" />

"http- equiv"属性有以下配置项:

http-equiv顾名思义,相当于http的文件头作用,它可以向浏览器传回一些有用的信息,以帮助正确和精确地显示网页内容。

<meta http-equiv="参数" content="参数变量值">

  • refresh(期限):定义文档自动刷新的时间间隔(下面content中的2是指停留2秒钟后自动刷新到URL网址)。这个属性值慎重使用,因为它会使得页面不受用户控制;
  • set-cookie:如果网页过期,那么存盘的cookie将被删除;
<meta http-equiv="refresh" content="2;URL=http://www.baidu.com">

<meta http-equiv="Set-Cookie"content="cookie value=xxx;expires=Friday,12-Jan-200118:18:18GMT;path=/">

Open Graph 协议标签

Open Graph 协议标签通过 OG Tags (OG 标签)实现的,它属于 Meta 标签的一种,可以用来标识网页类型和元素,让分享到社交网络的内容可以被有效的抓取,还可以控制分享的网站卡片呈现我们想要显示的内容。

只要看到以 og: 为前缀的 Meta 标签就可以判断该网页支持 OG 标签了,如下:

<meta property="og:title" content="设置Open Graph 标签!社交营销优化!">
<meta property="og:site_name" content="鲸落">
<meta property="og:type" content="article">
<meta property="og:description" content="Open Graph Protocol(开放图谱协议),简称 OG 协议或 OGP。">

设置og协议前后的网站分享卡片对比:

![image-20240702091744369](前端进阶:SEO 全方位解决方案.assets/image-20240702091744369.png)

网站关键词

上面也提到了,现在 keywords 关键词已经被各大搜索引擎降低了权重,所以可以设置也可以不设置,但我认为它仍然有他存在的价值。

如果你决定配置网站关键词,需要注意以下几点:

  • keywords 关键词数量控制在1-4个左右,避免关键词堆砌;
  • 合理选择长尾关键词(长尾关键词一般是2-3个词组成。例如,目标关键词是服装,其长尾关键词可以是男士服装、冬装等),长尾关键词虽然相对核心关键词的搜索量小很多,但是它带来的流量精准度非常高,后期的转化效果更好;
  • 避免使用过于专业的词汇。过于专业的词汇的搜索量较低;
  • 减少使用热门关键词,要选择合适的关键词(搜索量大、转化率高、定位精准)。

网站描述

  • Description(页面描述)的长度最好控制在120~200个字符
  • Description要让用户知道将从页面中获得什么
  • 在Description中合理使用行动号召(CTA)用语(例如“了解更多”、“立即获取”、“免费试用”等等……)
  • Description应该包含页面的核心关键字
  • 为每个页面创建独一无二的Description

网站质量

网站性能

网站性能是会影响到网站的SEO排名的,原因可想而知:

  • 网站卡顿势必会大大降低网站的用户留存率
  • 如果网站加载缓慢,搜索引擎就会认为该网站对用户不友好,从而将其排名下降
  • 影响搜索引擎蜘蛛的爬取频率
  • 等...

参考文章解析谷歌将网页加载速度快慢作为影响排名重要因素

HTML语义化

语义化是指内容的结构化(内容语义化),选择合适的标签(代码语义化)。

杜绝通篇div,HTML语义化不仅便于开发者阅读,还有利于浏览器爬虫的解析,对seo优化很有帮助。

所以我们在开发时要遵循语义化的开发规范,根据页面内容,选择合适的标签,优化代码,使得网页结构更加清晰。

下面介绍几种标签的使用:

h 标签 h标签一种有六个,分别是h1,h2...h6。h1-h6文字由大到小,权重也逐渐降低。相比其他标签而言,h标签在页面中的权重非常高,所以不要滥用h标签。要利用h标签告诉浏览器网页的核心内容!例如: h1写主标题,通常与网页title标签一致,可以在页面展示,一个页面最好只有一个h1标签。 h2写次级标题,h3-h6以此类推,细分网页结构。

strong、em 标签 <b><strong>标签都是加粗文字的标签,其二者的区别就在于:<b>是为了加粗而加粗的,<strong>是为了强调而加粗的。 同样斜体标签 <i><em> 也有着相同的区别,<em>有强调效果。 推荐使用<strong> <em>,而不是 <b> <i> 等,单纯修改加粗等样式可以用css实现。

ul ol li 标签 这三个都是列表标签,ul表示无序列表(unordered list),ol表示有序列表(oredr list), li 表示列表项(list item)。从网站优化的角度来说,在罗列多个词条的时候,最好使用列表标签,例如 使用ul li布局网站导航条对搜索引擎蜘蛛更加友好,也是影响搜索引擎排名的因素之一。

img 标签 img图片标签的 alt 属性是图片的替换文字。 alt属性可以帮助蜘蛛快速理解图片的具体内容,并且在网络故障时,仍然能够爬取到图片的内容信息。

其他标签

  • nav 标签定义导航链接的部分;
  • aside 标签定义侧边栏内容、引述内容;
  • header 标签定义网站头部,介绍信息。它通常是一组介绍性描述 (搜索框 / logo / …),网络爬虫知道诸如与之类的部分后可以非常简单的跳过它们,更好的定位网页内容;
  • article 标签定义网站的内容部分。搜索引擎通过这个标签可以正确知道页面中哪些是正文内容;
  • section 标签定义文档中的节(section、区段)。比如章节、页眉、页脚或文档中的其他部分;
  • footer 标签定义文档或节的页脚。它对网站首页的排名将会增加,而对于内页来说搜索引擎将有可能会视而不见。不建议每个web的footer信息都是独立的,这或许意味着新的黑帽手段将会出现。

其他注意点

  • SEO的禁忌之一就是用JS输出重要的内容。爬虫不会读取JS格式的内容,所以重要的内容必须是HTML格式,这也就是为什么现在流行的spa框架都不利于seo的原因之一
  • 尽量不使用iFrame。因为搜索引擎不会抓取iframe内的内容,所以重要内容绝对不能放在iframe中
  • 如果需要截取文字,尽量用css实现,保证文字可以完整呈现给搜索引擎

SEO手段

各搜索引擎提交站点收录

在各个搜索引擎的站点平台提交网站收录可以缩短爬虫发现网站链接时间,加快爬虫抓取速度。

百度搜索资源平台_共创共享鲜活搜索 (baidu.com)

Google 搜索中心(前身为“Google 网站站长”)| 网站 SEO 资源 | Search Central | Google for Developers

Bing - 网站管理员工具

头条搜索站长平台 (toutiao.com)

sitemap站点地图

Sitemap,即站点地图,它是一个网站的全部URL列表,同时可以列出每个网址的其他元数据(上次更新的时间、更改的频率以及相对于网站上其他网址的重要程度为何等)。它可以为搜索引擎的蜘蛛进行导航,更快的找到全站中的所有链接,更全面的获取网站信息。为了保证链接的全面性和准确性,应该自动不定期更新sitemap站点地图。

一般网站的sitemap文件都会有以下两种格式:

sitemap.xml,这是大部分搜索引擎所使用的用于提交网站网址的XML文件

sitemap.html,这是可直接放在网站上用于用户访问或搜索引擎快速找到全站链接的页面(每页最多500条,自动分页)

sitemap.xml 文件内容格式大致如下:

<?xml version="1.0" encoding="UTF-8"?>
<urlset
xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9
http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd"
>

<url>
<loc>https://www.cece.com/</loc>
<priority>0.3</priority>
<lastmod>2023-05-17</lastmod>
<changefreq>weekly</changefreq>
</url>

</urlset>

网上有很多生成sitemap文件的站长工具,例如:

sitemap网站地图站点地图_在线生成

免费Sitemap在线生成器,网站地图在线生成工具 - 在线工具 (bugscaner.com)

生成的sitemap文件一般放在项目根目录下,然后可以在各个搜索引擎的站点平台提交sitemap.xml文件。

robots文件

蜘蛛在访问一个网站时,会首先会检查该网站的根域下是否有一个叫做 robots.txt的纯文本文件,这个文件用于指定spider在您网站上的抓取范围。

如果你有哪些页面不想被蜘蛛访问,则可以通过robots文件告诉蜘蛛不想被搜索引擎收录的部分或者指定搜索引擎只收录特定的部分。

robots文件内容语法: 此文件主要由两种键值对组成:

  1. User-agent: 该项的值用于描述搜索引擎蜘蛛的名字。如果该项的值设为*,则该协议对任何机器人均有效。
  2. Disallow: 该项的值用于描述不希望被访问到的一个URL,一个目录或者整个网站。以Disallow 开头的URL 均不会被搜索引擎蜘蛛访问到。任何一条Disallow 记录为空,说明该网站的所有部分都允许被访问。

参考:掘金的robots文件

*网站目录下所有文件均能被所有搜索引擎蜘蛛访问*
User-agent: *
Disallow:

*禁止所有搜索引擎蜘蛛访问网站的任何部分*
User-agent: *
Disallow: /

*禁止所有的搜索引擎蜘蛛访问网站的几个目录*
User-agent: *
Disallow: /a/
Disallow: /b/

*只允许某个搜索引擎蜘蛛访问*
User-agent: Googlebot
Disallow:

使用场景举例:

  • 将一些不重要的页面配置在robots 文件中,集中蜘蛛爬取的权重;
  • 虽然 robots 文件是用于通知蜘蛛忽略哪些文件的爬取的,但是每当用户试图访问某个不存在的URL时,服务器都会在日志中记录404错误(无法找到文件)。每当搜索蜘蛛来寻找并不存在的robots.txt文件时,服务器也将在日志中记录一条404错误,所以建议还是添加一个robots.txt。
  • 避免服务器上的一些文件被蜘蛛访问,例如后台管理文件、程序脚本、附件、数据库文件、编码文件、样式表文件、模板文件、导航图片和背景图片等等,例如设置Disallow: /data/ 数据库文件
  • 避免访问时出错,例如不能让用户直接进入购物车页面,否则会报错,所以要用 robots 文件告诉蜘蛛,阻止这个页面被搜索引擎收录;
  • 如果你的网站是动态网页,并且你为这些动态网页创建了静态副本,以供搜索蜘蛛更容易抓取。那么你需要在robots.txt文件里设置避免动态网页被蜘蛛索引,以保证这些网页不会被视为含重复内容。
  • 将sitemap站点地图配置在robots文件中允许蜘蛛访问。这样站长就不需要在每个搜索引擎的站长平台去提交网站的sitemap 文件,搜索引擎的蜘蛛自己就会抓取robots.txt文件,读取其中的sitemap路径,接着抓取其中链接的网页。但是目前国内的搜索引擎基本都不支持此配置。

robots 文件使用方法: 使用方法非常简单,只需要将 robots.txt 文件上传到网站根目录就行了,注意文件名一定要全小写。当成功上传后,通常在浏览器中访问域名/robots.txt就可以查看到文件。

内链|外链

在搜索引擎优化领域,有着内链为王、外链为皇的说法,它们都能对提升网站排名有所帮助,尤其是外链的建设。 先来区分下网站内链和外链:

内链:从自己网站的一个页面指向另外一个页面。通过内链让网站内部形成网状结构,让蜘蛛的广度和深度达到最大化。

外链:在别的网站导入自己网站的链接。通过外链提升网站权重,提高网站流量。外链有以下几个好处:

  • 提升网站权重
  • 能够吸引蜘蛛来抓取网站
  • 提升关键词排名
  • 提升网址或品牌的曝光度
  • 给网站带来流量

外链能够为我们的网站带来流量,所以外链数量越多越好是必然的。但是,一定要注意外链的质量,例如对方网站没有被搜索引擎收录,对方网站性能过差,死链等,这些低质量的外链反而会影响到本站的排名。

另外,在添加内链外链的过程中,要注意在 a 标签中对 nofollowexternal 属性的使用。

<a> 标签的 rel 属性用于指定当前文档与被链接文档的关系。

rel=nofollow使用说明

<a rel="nofollow" href="http://www.baidu.com/">百度</a>

带有rel=nofollow 属性的链接会告诉搜索引擎忽略这个链接。阻止搜索引擎对该页面进行追踪。从而避免权重分散。这个属性只对搜索引擎有效,这是一个纯粹的SEO优化标签。

使用场景:

  • 屏蔽一些垃圾链接,比如网站上面评论里面的站外链接,论坛里面用户留下的链接等;

  • 外链的内容与本站无关时,建议使用nofollow

    ![image.png](前端进阶:SEO 全方位解决方案.assets/622d19f927724a13a0c28711a8ffe13etplv-k3u1fbpfcp-jj-mark3024000q75.webp)

  • 外链站点不稳定,性能较差时,建议使用nofollow

  • 友链一般作为网站交换链接,互惠互利,是不会设置nofollow的,所以在交换友链之前,一定要对对方的网站质量进行审核;

  • 内部链接密度过大,页面重要性不高时,可以使用nofoolw,例如很多网站常有的“关于我们”页面,比如掘金的:

    ![image.png](前端进阶:SEO 全方位解决方案.assets/88c020e9f9d74d5ab6d3e71fc22a26bctplv-k3u1fbpfcp-jj-mark3024000q75.webp)

  • 并不是内容无关的外链都要加nofollow。适当的添加高质量的外链,对于SEO是没有坏处的,还会产生正向影响,所以关键就在于外链的质量和数量上。例如掘金的友链:

    ![image.png](前端进阶:SEO 全方位解决方案.assets/12bec0e2e322452d90def4d1e66faeaatplv-k3u1fbpfcp-jj-mark3024000q75.webp)

rel=external使用说明 >>>

<a rel="external" href="http://www.baidu.com/">百度</a>

external字面意思是“外部的”,a 标签加上这个属性代表这个链接是外部链接,非本站链接,点击时会在新窗口中打开,它和target="_blank"效果一样。external 可以告诉搜索引擎这是一个外部链接,非本站的链接

Canonical URL(网址规范化)

什么是网址规范化?简单举个例子:

juejin.cn

www.juejin.cn

www.juejin.cn/index.html

这几个网址虽然url不同,搜索引擎也确实把他当作不同的网址,但是其实这些网址返回的都是同一个页面,这就是不规范网址。

网页规范化的两个好处:

  • 解决网站由于网站url链接不一样,但网页内容是一样而造成搜索引擎重复收录的问题;
  • 有利于URL权重集中。

解决方法: 在页面的head 标签中,加入以下canonical标签,指定规范化网址。

<head>
<link rel="canonical" href="href="https://juejin.cn"/>
</head>

例如掘金的规范化网址:

![image.png](前端进阶:SEO 全方位解决方案.assets/27346b16daba4994a4093fdf08c57773tplv-k3u1fbpfcp-jj-mark3024000q75.webp)

网站301重定向

301/302重定向是 SEO优化中一种重要的自动转向技术。301重定向是当搜索引擎向网站服务器发出访问请求时,服务返回的HTTP数据流中头信息(header)部分状态码的一种,表示本网址永久性转移到另一个地址。302重定向则表示暂时转移。

301重定向与上一点所说的网址规范化有着类似的作用,与此同时,它还具有以下作用:

  • 集中域名权重,301 网址跳转其实是对域名权重进行转移,比如 www.juejin.cn 重定向到 juejin.cn,其实是把 www.juejin.cn 的权重转移到了 juejin.cn,从而增加 juejin.cn 域名的权重;
  • 避免重复收录;
  • 网页PR(PageRank-网页级别)是用来评估一个网站页面相对于网站其他页面重要性的一个算法,301定向跳转有利于网站PR的传递;
  • 优化用户体验,网址规范化可以让用户更好地记住我们的网站,可以将域名统一重定向到某一个域名,增加网站的记忆度,获取更好的用户体验。

虽然canonical标签可以规范化网址,但是以下四种情况必须配置301重定向:

  1. 网站替换域名后,通过301永久重定向旧域名重定向到新域名,弥补流量损失和SEO
  2. 如果删除掉网站中的一些页面,但是这个页面有一定的流量和权重,可以利用301重定向到合适的页面避免流量流失
  3. 网站改版或因为其他原因导致页面地址发生变化,为避免出现死链接,可以通过 301 重定向来解决
  4. 如果您有多个空闲的域名需要指向相同的站点,则可以使用301永久重定向

如何验证301重定向是否生效: 可以使用站长工具HTTP状态查询查看返回的状态码是否为301

网站设置伪静态页面

伪静态页面是指动态网页通过重写URL的方法实现去掉动态网页的参数,但在实际的网页目录中并没有必要实现存在重写的页面。

动态页面通常是php或者asp等语言结合数据库,通过代码调用数据来实现页面展示。

伪静态化就是将动态页面的url转换成以 .html 等结尾的静态页面url,以增强搜索引擎的友好性(符合搜索引擎的抓取规则),同时方便用户输入和记忆。

举个例子: 比如有个asp动态页面:http://127.0.0.1/test.asp?id=1234

在伪静态化后,就可以通过类似的url访问这个页面: http://127.0.0.1/test_1234.html

一般实现手段是在 nginx/apache 等服务器配置rewrite重写规则,将动态url转变为静态url

使用HTTPS

谷歌曾发公告表示,使用安全加密协议(HTTPS),是搜索引擎排名的一项参考因素。

所以,在域名相同情况下,HTTPS站点比HTTP站点,能获得更好的排名。

SSR服务端渲染( Server-Side Rendering)

当下SPA应用盛行,虽然它有用户体验好,服务器压力小等优点,但是同时也暴露出很多问题。例如首屏加载较慢,不利于SEO等(因为这些spa应用内容是由js动态更新的,蜘蛛无法爬取网页内容)。

而ssr的出现,很好的解决了seo的问题。因为服务端渲染是指指客户端向服务器发出请求,然后运行时动态生成 html 内容并返回给客户端。所以客户端可以获取到完整的页面内容。

目前流行的 Vue/React 前端框架,都有SSR的解决方案:Vue的nuxt和React的next

预渲染prerender-spa-plugin

如果你只想改善部分页面的SEO,可以不采用 SSR 的解决方案,毕竟无论是next.js,还是nuxt.js,都是有一定学习成本的。那么你可以使用 prerender-spa-plugin 等插件来实现预渲染页面,在构建时就针对特定的路有生成静态的 html 文件。

了解更多:Vue使用prerender-spa-plugin进行网页预渲染 - 掘金 (juejin.cn)

参考链接

⛳前端进阶:SEO 全方位解决方案 - 掘金 (juejin.cn)


鲸落前端基建阅读需 20 分钟

前言

前端优化大概可以有以下几个方向:

  • 网络优化
  • 页面渲染优化
  • JS优化
  • 图片优化
  • webpack打包优化
  • React优化
  • Vue优化

网络优化

DNS预解析

link标签的rel属性设置dns-prefetch,提前获取域名对应的IP地址

使用缓存

减轻服务端压力,快速得到数据(如强缓存协商缓存等)

使用 CDN(内容分发网络)

用户与服务器的物理距离对响应时间也有影响。

内容分发网络(CDN)是一组分散在不同地理位置的 web 服务器,用来给用户更高效地发送内容。典型地,选择用来发送内容的服务器是基于网络距离的衡量标准的。例如:选跳数(hop)最少的或者响应时间最快的服务器。

压缩响应

压缩组件通过减少 HTTP 请求产生的响应包的大小,从而降低传输时间的方式来提高性能。从 HTTP1.1 开始,Web 客户端可以通过 HTTP 请求中的 Accept-Encoding 头来标识对压缩的支持(这个请求头会列出一系列的压缩方法)

如果 Web 服务器看到请求中的这个头,就会使用客户端列出的方法中的一种来压缩响应。Web 服务器通过响应中的 Content-Encoding 头来告知 Web 客户端使用哪种方法进行的压缩

目前许多网站通常会压缩 HTML 文档,脚本和样式表的压缩也是值得的(包括 XML 和 JSON 在内的任何文本响应理论上都值得被压缩)。但是,图片和 PDF 文件不应该被压缩,因为它们本来已经被压缩了。

使用多个域名

Chrome 等现代化浏览器,都会有同域名限制并发下载数的情况,不同的浏览器及版本都不一样,使用不同的域名可以最大化下载线程,但注意保持在 2~4 个域名内,以避免 DNS 查询损耗。

避免图片src为空

虽然 src 属性为空字符串,但浏览器仍然会向服务器发起一个 HTTP 请求:

IE 向页面所在的目录发送请求; Safari、Chrome、Firefox 向页面本身发送请求; Opera 不执行任何操作。

页面渲染优化

避免css阻塞

css影响renderTree的构建,会阻塞页面的渲染,因此应该尽早(将 CSS 放在 head 标签里)和尽快(启用 CDN 实现静态资源加载速度的优化)的将css资源加载

降低css选择器的复杂度

浏览器读取选择器,遵循的原则是从选择器的右边到左边读取。

  • 减少嵌套:最多不要超过三层,并且后代选择器的开销较高,慎重使用
  • 避免使用通配符,对用到的元素进行匹配即可
  • 利用继承,避免重复匹配和定义
  • 正确使用类选择器和id选择器

避免使用CSS 表达式

css 表达式会被频繁地计算。

避免js阻塞

js可以修改CSSOM和DOM,因此js会阻塞页面的解析和渲染,并且会等待css资源的加载。也就是说js会抢走渲染引擎的控制权。所以我们需要给js资源添加defer或者async,延迟js脚本的执行。

使用外链式的js和css

在现实环境中使用外部文件通常会产生较快的页面,因为 JavaScript 和 CSS 有机会被浏览器缓存起来。对于内联的情况,由于 HTML 文档通常不会被配置为可以进行缓存的,所以每次请求 HTML 文档都要下载 JavaScript 和 CSS。所以,如果 JavaScript 和 CSS 在外部文件中,浏览器可以缓存它们,HTML 文档的大小会被减少而不必增加 HTTP 请求数量。

使用字体图标 iconfont 代替图片图标

  • 图片会增加网络请求次数,从而拖慢页面加载时间
  • iconfont可以很好的缩放并且不会添加额外的请求

首屏加载优化

  • 使用骨架屏或者动画优化用户体验
  • 资源按需加载,首页不需要的资源延迟加载

减少重绘和回流

  • 增加多个节点使用documentFragment:不是真实dom的部分,不会引起重绘和回流

  • 用 translate 代替 top ,因为 top 会触发回流,但是translate不会。所以translate会比top节省了一个layout的时间

  • 使用 visibility 替换 display: none ,因为前者只会引起重绘,后者会引发回流(改变了布局);opacity 代替 visiabilityvisiability会触发重绘(paint),但opacity不会。

  • 把 DOM 离线后修改,比如:先把 DOM 给 display:none (有一次 Reflow),然后你修改 100 次,然后再把它显示出来

  • 不要把 DOM 结点的属性值放在一个循环里当成循环里的变量

    javascript复制代码for (let i = 0; i < 1000; i++) {
    // 获取 offsetTop 会导致回流,因为需要去获取正确的值
    console.log(document.querySelector('.test').style.offsetTop)
    }
  • 尽量少用table布局,table布局的话,每次有单元格布局改变,都会进行整个tabel回流重绘;

  • 最好别频繁去操作DOM节点,最好把需要操作的样式,提前写成class,之后需要修改。只需要修改一次,需要修改的时候,直接修改className,做成一次性更新多条css DOM属性,一次回流重绘总比多次回流重绘要付出的成本低得多;

  • 动画实现的速度的选择,动画速度越快,回流次数越多,也可以选择使用 requestAnimationFrame

  • 每次访问DOM的偏移量属性的时候,例如获取一个元素的scrollTop、scrollLeft、scrollWidth、offsetTop、offsetLeft、offsetWidth、offsetHeight之类的属性,浏览器为了保证值的正确也会回流取得最新的值,所以如果你要多次操作,最取完做个缓存。更加不要for循环中访问DOM偏移量属性,而且使用的时候,最好定义一个变量,把要需要的值赋值进去,进行值缓存,把回流重绘的次数减少;

  • 将频繁运行的动画变为图层,图层能够阻止该节点回流影响别的元素。比如对于 video 标签,浏览器会自动将该节点变为图层。

JS中的性能优化

使用事件委托

防抖和节流

尽量不要使用JS动画

css3动画和canvas动画都比JS动画性能好

多线程

复杂的计算开启webWorker进行计算,避免页面假死

计算结果缓存

减少运算次数,比如vue中的computed、react中的useMemo

图片的优化

雪碧图

借助减少http请求次数来进行优化

图片懒加载

在图片即将进入可视区域的时候进行加载

使用CSS3代替图片

有很多图片使用 CSS 效果(渐变、阴影等)就能画出来,这种情况选择 CSS3 效果更好

图片压缩

压缩方法有两种,一是通过在线网站进行压缩,二是通过 webpack 插件 image-webpack-loader

使用渐进式jpeg

使用渐进式jpeg,会提高用户体验 参考文章

使用 webp 格式的图片

webp 是一种新的图片文件格式,它提供了有损压缩和无损压缩两种方式。在相同图片质量下,webp 的体积比 png 和 jpg 更小。

webpack打包优化

抽离css

借助mini-css-extract-plugin:本插件会将 CSS 提取到单独的文件中,为每个包含 CSS 的 JS 文件创建一个 CSS 文件,并且支持 CSS 和 SourceMaps 的按需加载。

const MiniCssExtractPlugin = require("mini-css-extract-plugin");
{
test: /\.less$/,
use: [
// "style-loader", // 不再需要style-loader,⽤MiniCssExtractPlugin.loader代替
MiniCssExtractPlugin.loader,
"css-loader", // 编译css
"postcss-loader",
"less-loader" // 编译less
]
},
plugins: [
new MiniCssExtractPlugin({
filename: "css/[name]_[contenthash:6].css",
chunkFilename: "[id].css"
})
]

代码压缩

  • JS代码压缩:mode:production,使用的是terser-webpack-plugin

    module.exports = {
       // ...
       optimization: {
           minimize: true,
           minimizer: [
               new TerserPlugin({}),
          ]
      }
    }
  • CSS代码压缩:css-minimizer-webpack-plugin

    module.exports = {
       // ...
       optimization: {
           minimize: true,
           minimizer: [
               new CssMinimizerPlugin({})
          ]
      }
    }
  • HTML代码压缩:设置了minify,实际会使用另一个插件html-minifier-terser

    module.exports = {
       ...
       plugin:[
           new HtmlwebpackPlugin({
               ...
               minify:{
                   minifyCSS:false, // 是否压缩css
                   collapseWhitespace:false, // 是否折叠空格
                   removeComments:true // 是否移除注释
              }
          })
      ]
    }
  • 文件大小压缩:对文件的大小进行压缩,减少http传输过程中宽带的损耗

    new ComepressionPlugin({
       test:/.(css|js)$/,  // 哪些文件需要压缩
       threshold:500, // 设置文件多大开始压缩
       minRatio:0.7, // 至少压缩的比例
       algorithm:"gzip", // 采用的压缩算法
    })
  • 图片压缩

    module: {
     rules: [
      {
         test: /.(png|jpg|gif)$/,
         use: [
          {
             loader: 'file-loader',
             options: {
               name: '[name]_[hash].[ext]',
               outputPath: 'images/',
            }
          },
          {
             loader: 'image-webpack-loader',
             options: {
               // 压缩 jpeg 的配置
               mozjpeg: {
                 progressive: true,
                 quality: 65
              },
               // 使用 imagemin**-optipng 压缩 png,enable: false 为关闭
               optipng: {
                 enabled: false,
              },
               // 使用 imagemin-pngquant 压缩 png
               pngquant: {
                 quality: '65-90',
                 speed: 4
              },
               // 压缩 gif 的配置
               gifsicle: {
                 interlaced: false,
              },
               // 开启 webp,会把 jpg 和 png 图片压缩为 webp 格式
               webp: {
                 quality: 75
              }
            }
          }
        ]
      },
    ]
    }

Tree shaking 去除死代码

Tree Shaking 是一个术语,在计算机中表示消除死代码,依赖于ES Module的静态语法分析(不执行任何的代码,可以明确知道模块的依赖关系)

webpack实现Tree shaking有两种不同的方案:

  • usedExports:通过标记某些函数是否被使用,之后通过Terser来进行优化的
  • sideEffects:跳过整个模块/文件,直接查看该文件是否有副作用

css也可以进行tree shaking优化:安装PurgeCss插件

减少ES6转化ES5的冗余

Babel 插件会在将 ES6 代码转换成 ES5 代码时会注入一些辅助函数。在默认情况下, Babel 会在每个输出文件中内嵌这些依赖的辅助函数代码,如果多个源代码文件都依赖这些辅助函数,那么这些辅助函数的代码将会出现很多次,造成代码冗余。为了不让这些辅助函数的代码重复出现,可以在依赖它们时通过 require('babel-runtime/helpers/createClass') 的方式导入,这样就能做到只让它们出现一次。babel-plugin-transform-runtime 插件就是用来实现这个作用的,将相关辅助函数进行替换成导入语句,从而减小 babel 编译出来的代码的文件大小。

代码分离

将代码分离到不同的bundle中,之后我们可以按需加载,或者并行加载这些文件

默认情况下,所有的JavaScript代码(业务代码、第三方依赖、暂时没有用到的模块)在首页全部都加载,就会影响首页的加载速度

代码分离可以分出更小的bundle,以及控制资源加载优先级,提供代码的加载性能

可以通过splitChunksPlugin来实现,该插件webpack已经默认安装和集成,只需要配置即可

VUE

  • v-for添加key
  • 路由懒加载
  • 第三方插件按需引入
  • 合理使用computed和watch
  • v-for的同时避免使用v-if
  • destory时销毁事件:比如addEventListener添加的事件、setTimeout、setInterval、bus.$on绑定的监听事件等

React

  • map循环展示添加key
  • 路由懒加载
  • 第三方插件按需引入
  • 使用scu,memo或者pureComponent避免不必要的渲染
  • 合理使用useMemo、memo、useCallback

参考链接

当面试官问我前端可以做的性能优化有哪些 - 掘金 (juejin.cn)


鲸落前端基建阅读需 11 分钟