网址前面加不加www,到底哪个对?

2,968字
13–19 分钟
in

上网冲浪时有没有发现一个怪现象:有的网站敲example.com直接蹦出来,有的却强制跳转到www.example.com。两边阵营吵了好多年,Google、Instagram站队带www派,GitHub、DuckDuckGo偏要反着来。这事儿没有绝对对错,但背后藏着不少门道,搞清楚了能给网站省下一堆麻烦。

目录

www是啥来头

这三个W全称“万维网”(World Wide Web),上世纪80年代末的产物。当年人们喜欢按服务类型给子域名起名:网页服务器用www,文件传输用ftp,聊天服务用irc。说白了,www就是一个子域名,跟blog.example.com里的blog一个性质。只不过这老大哥名声太大,搞得很多人以为网址天生就得带它。

裸域有啥坑

Cookie偷跑那些事
老早以前有人发现,在IE浏览器里,example.com设置的Cookie居然能被subdomain.example.com读到。这要是搞网站托管的服务商,客户子站就能偷主站的登录凭证,够吓人。不过后来RFC 6265标准一巴掌拍死了这个行为,明说IE那种做法是错的。现在只要别手贱给Cookie加上Domain=example.com属性,子域名根本摸不到主域的饼干。看下面这张表就门清了:

Cookie设置主域访问子域访问
secret=data允许拒绝
加Domain参数允许允许

DNS绕不过的坎
裸域(不带www的域名)想用CNAME记录?难搞。按照RFC 1912规定,CNAME不能跟其他记录共存。比方说example.com既要做网站又收邮件,那它得同时有A记录和MX记录。一旦把example.com设成CNAME指向某CDN域名.com,MX记录就废了,@example.com的邮件全得扑街。还好现在Cloudflare这类服务商搞出“CNAME压平”技术:后台配的是CNAME,但DNS服务器直接吐出A记录的IP。相当于抄了近道,绕开了规则限制。

带www有啥爽

新顶级域名救命
.miami.club这种新花样域名,普通人看到example.miami可能愣一下——这是网址还是啥?换成www.example.miami,那三道杠瞬间暴露身份:“我是网页!”当然,老牌.com就没这焦虑。

性能蹭点羊毛
每个HTTP请求少传4个字节(www.),对Facebook这种流量巨兽能省下不少带宽。虽然现在带宽白菜价,但苍蝇腿也是肉。

实操开干:二选一加全套配置

不管站哪边,核心就一条:定一个主场,另一个做永久重定向。下面按两套方案掰开揉碎讲。

方案A:让www.example.com当老大

第一步 改DNS记录
登录域名管理后台,把example.com的A记录指向服务器IP。再给www.example.com也配一条A记录,或者配CNAME指向example.com。注意:裸域那条A记录必须存在,因为CNAME不能用在裸域上。配好后等几分钟生效。

第二步 配301永久重定向
让所有访问http://example.comhttps://example.com的请求,统统跳转到https://www.example.com。拿Nginx举个栗子,在配置文件里写:

server {
    listen 80;
    server_name example.com;
    return 301 https://www.example.com$request_uri;
}
server {
    listen 443 ssl;
    server_name example.com;
    # 证书路径省略...
    return 301 https://www.example.com$request_uri;
}

Apache的.htaccess写法:

RewriteEngine On
RewriteCond %{HTTP_HOST} ^example.com [NC]
RewriteRule ^(.*)$ https://www.example.com/$1 [L,R=301]

第三步 加canonical标签防Google犯浑
搜索引擎会把带www和不带的当成两个独立站点,容易判定成重复内容。挑www.example.com做标准版本,在每个页面的<head>里塞这么一行:

<link href="https://www.example.com/当前页面路径" rel="canonical">

注意路径要写全,别漏了https://。动态网站可以在模板里用变量拼接,静态页面就手动改或者用构建脚本批量加。

第四步 检查Cookie是否乱窜
千万别在设置Cookie时写上Domain=example.com。大部分后端框架默认只对当前域名生效,比如Python的Flask用response.set_cookie('key','value')就不会带Domain参数。如果用了domain='.example.com'这种写法,赶紧删掉。

方案B:让example.com(裸域)当老大

第一步 同样改DNS
example.com配A记录到服务器IP。www.example.com可以删掉,或者也配A记录指向同一IP——但最后会做重定向,所以无所谓。注意:如果用了CDN,大部分CDN要求CNAME方式接入,而裸域不能用CNAME,这时候要么换A记录直连源站,要么找支持CNAME压平的DNS服务商。

第二步 配重定向(反向操作)
把所有www.example.com请求301跳转到example.com。Nginx配置:

server {
    listen 80;
    server_name www.example.com;
    return 301 https://example.com$request_uri;
}

第三步 canonical标签指向裸域
页头改成:

<link href="https://example.com/当前页面路径" rel="canonical">

第四步 小心子域名Cookie泄漏
裸域场景下,如果站点有子域名(比如blog.example.com),且子域名也跑着服务,那example.com设置的Cookie默认不会传给子域,这反而是好事。但反过来,子域要是想读主域的登录态,那就得显式设置Domain=.example.com,这又可能带来跨子域风险。所以尽量保持Cookie作用域收窄,别贪方便全开。

两个都想要?别作死

理论上可以同时支持example.comwww.example.com并存不跳转。但实操坑死人:网站内部链接必须全用相对路径(比如/about而不是https://www.example.com/about),否则用户从裸域点进带www的链接就换域名了。Google那边还得同时给两个版本标canonical,搞不好排名直接分裂。更别提流量统计工具会把两个域名分开计数,看报表时脑壳疼。除非有自虐倾向,否则老老实实选一个做重定向。

搬站点时别用错状态码

想从带www切到不带www,或者反过来,务必用HTTP 301(永久移动)。302(临时重定向)不会传递SEO权重,搞了白搞。命令行检查方法:

curl -I https://example.com

看返回头里有没有HTTP/1.1 301 Moved Permanently以及Location字段。如果出来302,赶紧改配置。