4

In an HTML file, are the following two script includes functionally equivalent?

index.html

  <script src="file.js"></script>

and

  <script src="./file.js"></script>

From what I remember, when files are resolved:

(1) The current directory of the HTML file is used by default for resolving relative paths,

(2) So "file.js" and "./file.js" are resolved using the path/directory of the HTML file.

When I experiment with this, they work the same in my test browser/server, but when it's behind an nginx load balancer with a route it is failing. But I think this is a different issue which would be an entirely different question.

EDIT: The value of the PATH environment variable and the rules for executable files lookup are unrelated to the way that HTML <script src="file.js"> is handled.

5
  • 3
    They should be the same unless you have an exotic nginx configuration ... I would look first in the nginx logs to see what errors are being emitted. Commented Apr 14, 2021 at 20:54
  • Not the same. First implies same directory. Second is a root relative path. So they would effectively be the same if the html file is in root only Commented Apr 14, 2021 at 20:59
  • 3
    @charlietfl Are you sure? The second one starts with a ./, which should mean the current directory. Commented Apr 14, 2021 at 21:34
  • 2
    Your browser should normalize both URLs to (the same) absolute URL before doing the request. Your server should not see any difference. Note that URLs are not relative to the HTML file's directory, but to the document's baseURL which can be changed in some circumstances (e.g when using a <base> element). Commented Apr 15, 2021 at 1:27
  • @Kaiido Post that as the answer. Commented Apr 15, 2021 at 16:53

2 Answers 2

1

While the MDN docs for script are not helpful, this article http://brianvanderplaats.com/2017/01/16/understanding-relative-urls/ covers the issue and explains how relative paths are handled.

How it works

The way a script is handled is not determined by the server but is instead determined by the browser. The browser parses the element and makes an HTTP GET request to ask for the javascript file.

For example, if the following browser page were opened http://host.com/app/dir1/index.html and the following script element was found:

    <script src="file.js"></script>

When examined in Chrome's devtools I see that an HTTP GET for the file being sent to the server.

http://host.com/app/dir1/file.js

What the standard says

The HTML standard in 4.3.1 The script element says:

If the element has a src attribute, then the value of that attribute must be resolved relative to the element, and if that is successful, the specified resource must then be fetched, from the origin of the element's Document.

This means relative to the index.html file and then requested via the document's origin which is document.location.origin. NOTE: Technically, the element refers to DOM element but I'm keeping it simple.

If we change the index.html file to include a dot, then we see the same HTML GET is issued. So this:

    <script src="./file.js"></script>

Also results to the same HTTP GET being issued:

http://host.com/app/dir1/file.js

Hopefully this clearly that src="file.js" is functionally the same as src="./file.js".

Current is changed when <base> element is used

It is worth noting that if the <base> element exists, then it will be used instead of the current location. For example,

<html>
  <head>
    <base href="https://just-a-test/dir1/">
    <script src="./file33.js"></script>
  </head>
  <body>... rest not shown

Then the browser will issue an HTTP GET for

https://just-a-test/dir1/file33.js

Another interesting case is when a relative path uses a sub-directory, or dot-dot syntax to get to a parent directory ../images/img1.png.

In both cases, the browser resolves the name and issues and HTTP GET Request for the resource it believes is the correct name. So

<html>
  <head>
    <base href="https://just-a-test/dir1/">
  </head>
  <body>
    <img src="../images/img1.png"></script>
  </body>
</html>

results in an HTTP GET request to the following file.

 https://just-a-test.com/images/img1.png

<base> can include filename

Lastly, the <base> element can include a filename such as:

<html>
  <head>
    <base href="https://just-a-test/dir1/index.html">
  </head>
  <body>
    <img src="img44.png"></script>
  </body>
</html>

When this happens, the filename is dropped and only the remaining path is used so in this case an HTTP GET request is made for this file.

 https://just-a-test.com/dir1/img44.png

And not the file https://just-a-test.com/dir1/index.html/img44.png.

I bring this case up because a common bug is to leave off the trailing slash and wonder why things are not working. For example,

<html>
  <head>
    <base href="https://just-a-test/dir1">
  </head>
  <body>
    <img src="img44.png"></script>
  </body>
</html>

Results in an HTTP GET Request to

https://just-a-test.com/img44.png

Which might make you think it wasn't working. This happens because dir1 is viewed just like index.html in the previous example and ignored for the purposes of issuing the HTTP GET requests.

Documentation on <base>

The MDN documentation for base is here and the HTML5 standard for <base> is here. My hightlights are:

  • If the document has no elements, then the browser uses location.href. A base can include a filename.

  • If multiple elements are used, only the first href and first target are obeyed — all others are ignored.

  • A base element must have either an href attribute, a target attribute, or both.

  • The base element has to be put in the <head> element.

  • The base element does not have a closing tag.

Sign up to request clarification or add additional context in comments.

1 Comment

The origin has little to play here, it only sets the Origin HTTP header that the server could check to see if it's willing to share this resource, but that doesn't influence the URL. What does is the base URL of the element's Document. W3C's HTML specs are outdated, the true HTML standards are at whatwg. There, at step 26.4, they ask to Parse src relative to the element's node document.
0

There is no difference between the two from web browser perspective.

However, on *nix systems, for example in shell, file.js would be searched in $PATH, while ./file.js will be searched in current directory.

2 Comments

The statements on $PATH are unrelated to the problem and IMO confusing your answer. For example, whether you have the current directory on your path or not (e.g., PATH=.:$PATH ), the file file.js will be found in the current directory where current is defined as the directory relative to the HTML file that is including the file.
I don't know what nginx load balancer does or how it does it, but it was my hypothesis that it might be parsing the html and searching the file on the system, which could be using $PATH

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.