资源定位和 URL

浏览器在工作的时候,需要下载网页 HTML,CSS,JavaScript,图片声音视频等等各种资源。另外,超链接元素<a>也需要指定 href 属性确定指向。资源定位错误是初学者常遇到的问题,本章将详细介绍资源的定位。

URL 简介

统一资源定位符(下文简称 URL) 即 URL,由万维网的发明人 Tim Berners-Lee 于 1994 年定义在 RFC1738,要获得完整精确的描述可以查看该 RFC 文档链接。

我们在网站概述章节中介绍了 URL (Uniform Resource Locator) 即统一资源定位符,浏览器就是根据 URL 来获取不同的资源的:

万维网上有 HTML 网页,有图片等无数资源 (Resource),这些资源的位置需要有个地址定位,就像每户人家都有自己的门牌号。有了 URL 就可以访问相应的资源了。我们经常说的网址就是 URL。例如 https://en.wikipedia.org/wiki/URL。浏览器就是根据 URL 来访问服务器下载网页的。

URL 的基本形式如下:

<scheme>:<scheme-specific-part>
<协议>:<协议专属部分>

下面是几个合法的 URL:

https://en.wikipedia.org/wiki/URL
http://google.com
file:///Users/lishi/html-example/url-demo/index.html
ftp://myname@host.dom/etc/motd
mailto:shirh.lee@gmail.com

我们这里主要关心 HTTP/HTTPS 的 URL,格式及说明如下:

https  : // www.example.com :3000 /path/resource ?id=123&name=test #section-id
  1. 协议 - 定义了如何获取资源
  2. 层级URL标记符号 - (为 // ,固定不变)
  3. 域名 - 也可以是 IP 地址,例子中是一个二级域名
  4. 端口 - 可以省略。如果省略了,HTTP 是 80 端口,HTTPS 是 443 端口。
  5. 路径 - 希望访问资源的路径
  6. 查询参数 - 以?开始,&分隔,=连接键值(key value)
  7. 片段ID - 以 # 开始的字符,一般对应页面中某个元素的 id 属性

下面是一个真实的例子,可以访问 http://example.simon1987.com/url-demo/index.html 查看页面:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>URL 资源举例</title>
        <script src="//code.jquery.com/jquery-3.3.1.js" ></script>
        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.2/css/bulma.css">
        <link rel="stylesheet" href="make-h1-yellow.css">
        <link rel="stylesheet" href="bg/add-background-image.css">
        <link rel="stylesheet" href="../css/make-h2-pink.css">
        <link rel="stylesheet" href="/make-h3-green.css">
    </head>
    <body>
        <h1>黄色标题</h1>
        <h2>粉红标题</h2>
        <h3>绿色标题</h3>
        <img src="../images/spiderman.jpg">
        <p>
            <a href="//code.jquery.com/jquery-3.3.1.js">jquery-3.3.1.js</a><br>
            <a href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.2/css/bulma.css">bulma.css</a><br>
            <a href="make-h1-yellow.css">make-h1-yellow.css</a><br>
            <a href="bg/add-background-image.css">add-background-image.css</a><br>
            <a href="../css/make-h2-pink.css">make-h2-pink.css</a><br>
            <a href="/make-h3-green.css">make-h3-green.css</a><br>
            <a href="mailto:shirh.lee@gmail.com">mailto 链接</a><br>
        </p>
    </body>
</html>

在上面的 HTML 中,在<head>标签里引用到了多个资源,有的通过绝对 URL,有的通过相对 URL。浏览器在打开这个页面的时候,会根据<script>标签的 src 属性值,<link>标签的 href属性值获取相应资源,包括 CSS, JavaScript。下面会对其中的 URL 一一解释。

绝对 URL (absolute URLs)

绝对 URL 地址,即符合完整 URL 定义的地址,例如:

  • 该页面的网址:http://example.simon1987.com/url-demo/index.html
  • 上文例子中的 <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.2/css/bulma.css">
  • 上文例子中的 <a href="mailto:shirh.lee@gmail.com">mailto 链接</a>

相对 URL (absolute URLs)

所谓相对 URL 是不指定完整目标的 URL,而根据当前页面的 URL (即 Base URL,<base>标签可以改变 Base URL,见下文) 和相对路径,来访问目标资源。相对 URL 有 4 个规则:

  • 不同层级的路径,用“/”隔开。
  • 当前页面同一层的资源。直接写资源的名称,或者用./加资源的名称,表示同一层。
  • 当前页面上一层的资源。用“../”来表示上一层,可以同时有多个“../”。
  • 可以相对根路径访问资源。用“/”开始,表示相对根路径。根路径指紧接着域名的路径,比如 http://example.simon1987.com/ 是根路径。

例如当前页面为 http://example.simon1987.com/url-demo/index.html,值得注意的是这个url 与 http://example.simon1987.com/url-demo/属于同一层,但是与http://example.simon1987.com/url-demo不同,虽然在这个例子中,访问后者的时候,会跳转至http://example.simon1987.com/url-demo/,这个跳转是 Web Server 控制的 (通过返回浏览器 HTTP 301 重定向):

  • 上文例子中的<link rel="stylesheet" href="make-h1-yellow.css"><a href="make-h1-yellow.css">make-h1-yellow.css</a>是同一层的资源。根据当前页面路径,确定目标 URL 为 http://example.simon1987.com/url-demo/make-h1-yellow.css
  • 上文例子中的 <link rel="stylesheet" href="bg/add-background-image.css"><a href="bg/add-background-image.css">add-background-image.css</a> 是同一层路径 bg 的下一层。根据当前页面路径确定目标 URL 为 http://example.simon1987.com/url-demo/bg/add-background-image.css
  • 上文例子中的 <link rel="stylesheet" href="../css/make-h2-pink.css"><a href="../css/make-h2-pink.css">make-h2-pink.css</a>因为以“../”开头,所以是当前页面的上一层的资源。根据单前页面的路径,确定目标 URL 为http://example.simon1987.com/make-h2-pink.css 。同样的<img src="../images/spiderman.jpg">的目标路径为http://example.simon1987.com/images/spiderman.jpg
  • 上文例子中的<link rel="stylesheet" href="/make-h3-green.css"><a href="/make-h3-green.css">make-h3-green.css</a>因为以“/”开头,所以是相对于根目录的路径,根据根目录 http://example.simon1987.com/ ,确定目标 URL 为 http://example.simon1987.com/make-h3-green.css

下面的表格有更多例子:

当前页面 URL (Base URL) 相对路径 完整 URL
http://example.com/a/b/c.html

http://example.com/a/b/

http://example.com/a/b/d.html
photo.jpg 或 ./photo.jpg http://example.com/a/b/photo.jpg
css/reset.css 或 ./css/reset.css http://example.com/a/b/css/reset.css
../x.html http://example.com/a/x.html
../../y.html http://example.com/y.html
/y.html http://example.com/y.html
/a/b/c.html http://example.com/a/b/c.html

另外,可以在 HTML 中使用<base>标签改变所有相对路径的基本路径,可以参考这个 MDN 文档

协议相关 URL (Protocol-relative URLs)

协议相关 URL 是省略掉协议部分以及协议后面的分号的 URL,浏览器在访问时,会根据当前页面的协议解析目标资源。即如果当前页面是 HTTP 目标也用 HTTP,如果当前页面是 HTTPS 的,目标也用 HTTPS。例如:

  • 上文例子中的<script src="//code.jquery.com/jquery-3.3.1.js" ></script>
  • 上文例子中的<a href="//code.jquery.com/jquery-3.3.1.js">jquery-3.3.1.js</a>

CSS 中的 URL 资源

CSS 中也可以引用资源,例如设置图片背景,设置 font-face。这个时候相对路径的参照是 css 文件的 URL 而不是相关页面的 URL。例如,上文例子中的 <link rel="stylesheet" href="bg/add-background-image.css">,这个 css 的内容如下:

body {
  background-image: url('../../images/shanghai-unsplash.jpg');
  height: 100vh;
}

浏览器首先根据当前页面的 URL 确定 CSS 的 URL 为:http://example.simon1987.com/url-demo/bg/add-background-image.css,再根据这个路径,和图片相对路径'../../images/shanghai-unsplash.jpg'确定图片的 URL 为 http://example.simon1987.com/images/shanghai-unsplash.jpg

注意事项

  • 在开发时通常是在本地(自己的电脑)上进行的,文件的相对路径与部署到服务器的相对路径可能不一样(比如相对于根路径;比如用../访问上一层的资源,在服务器上不一定有权限),尽管大部分情况是一致的。
  • 本地文件的 URL 是 file 协议的,而部署到服务器以后,在HTTP(S)协议的网页中,是无法访问 file 协议的资源的。如果网页的 URL 是 HTTPS 的,引入的资源是 HTTP 的,这个资源也大概率会被浏览器阻止访问。都是因为安全上的考量。
  • 在本地开发中可以在本地部署服务器访问,而不是通过浏览器直接打开文件,这样可以避免很多开发与部署不一致的问题。服务器的部署在第x章有介绍。

参考文档

  • RFC 1738: https://tools.ietf.org/html/rfc1738
  • <base>标签:https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/base