Is <script src="file.js"> the same as <script src="./file.js">? - javascript

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.

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.

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.

Related

How to make prefetch link work with JavaScript file?

I'm trying to use prefetching (via a link with rel="prefetch") for a JavaScript resource in an html page. In Chrome, I see the prefetch request get kicked off with a "Type" of "javascript". If I subsequently try and fetch the same JavaScript resource by inserting a script tag into the page, I'd expect this to be fetched from the browser cache, rather than a new request being fired off to fetch the resource from the CDN. However, this is not the case. I see a new request being made with the "Type" of "script". I'm assuming that the issue is related to the mismatch in type between this request and the prefetch request.
Is there a way to force the prefetch request to use a type of script or some other way to avoid the JavaScript file being fetched again?
I've tried using an "as" attribute value of "script", but that seems to have no effect.
I'm aware that rel="preload" is an alternative option. This works, but the usual advice seems to be that preloading is only appropriate for resources you're about to use and prefetching is a better choice for resources you will use after navigating elsewhere in your web page. Chrome also warns if you use preload and don't use the resource within a few seconds.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Page Title</title>
<link rel="prefetch" href="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.8/angular-cookies.js" />
<script type="text/javascript">
setTimeout(function() {
const scriptElement = document.createElement("script");
scriptElement.src = "https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.8/angular-cookies.js";
document.head.appendChild(scriptElement);
}, 2000);
</script>
</head>
<body>
</body>
</html>
See above for example repro code. I'd expect the script tag inside the setTimeout to use the already fetched resource, but instead I see a new request being fired off.
I figured this one out, finally. You're likely seeing this happen because Disable Cache is on in Chrome dev tools: Disabling Chrome cache for website development
This doesn't just disable previously-cached assets – it also means that something like this would download an asset twice:
<script src="foo.js">
<script src="foo.js">
With that checkbox unchecked, you should successfully see your asset getting cached:
That all being said, it is very important to note that in my testing, Chrome is not smart enough to realize that a prefetch and a regular download for the same resource is happening at the same time – it won't attempt to cache one for the other. So if your prefetching takes longer than your setTimeout millisecond value, you will see duplicate downloads!
This is certainly because what you and I are doing here is in some ways an abuse of prefetching. It's supposed to be a way to download resources used for the next navigation. C'est la vie!
Is there a way to force the prefetch request to use a type of script or some other way to avoid the JavaScript file being fetched again?
I've tried using an "as" attribute value of "script", but that seems to have no effect.
Just as a final note, the type differences of script and javascript are to be expected. This is Dev Tools trying to tell you that one of the files is going to be executed and the other is merely getting downloaded.

How to get the host protocol in import JSP

I am having two JSP files in my main application whereas one is MAIN.jsp and another one is CSS & JS import.jsp file.
MAIN.jsp is the main page of main application.The import.jsp file will import the CSS and JS of partner application in MAIN.jsp file which is used for support the few functionality with main application as partner.
But all the application (Main and Partner) are deployed in same server. So basically the host name of both the application will not change but context root alone will get change.
i have used jsp import tag to import the import.jsp in MAIN.jsp like mentioned below code.
MAIN.jsp
<html>
<head>
<c:import url="resourceImport/import.jsp">
</head>
<body>
</body>
</html>
import.jsp
<html>
<head>
<link url="http://hostName/DifferentContext/example.css" rel="stylesheet" type="test/css">
<script type="text/javascript" src="http://hostName/DifferentContext/sample.js" > </script>
</head>
<body>
</body>
</html>
Currently i have hard coded the partner HTTP URL in import.jsp for load all the resource in MAIN.jsp file. But moving forward we are planing to run the application in HTTP and HTTPS environment.
So how can i make it dynamic way of getting protocol in import.jsp file. I have tried following methods to get the protocol dynamically but its not working.
Method 1:
Removing Protocol and make it relative URL
<head>
<link url="//hostName/DifferentContext/example.css" rel="stylesheet" type="test/css">
<script type="text/javascript" src="//hostName/DifferentContext/sample.js" > </script>
</head>
Method 2
Removing Protocol and Host name and make it relative URL
<head>
<link url="//DifferentContext/example.css" rel="stylesheet" type="test/css">
<script type="text/javascript" src="//DifferentContext/sample.js" > </script>
</head>
So could you please anyone help me to get resolve this issue.
If there is anything that makes it worth to use https (and these days there is), I'd opt for less hassle and just go https everywhere.
No more worries, no accidental information leak and protocol change. Easier maintenance and no later update will inadvertently bring back a wrong protocol link.
Check HSTS as an option to force compliant browsers to not bother with any http connection attempt in the future.
That being said, relative links are another way to stay in the same protocol and probably beneficial: You rarely want to hard code domain names into your applications - Depending on the programming style that you're using in your app, you might want to use page-relative links (../DifferentContext/example.css) or server-relative (/DifferentContext/example.css). Protocol relative is fine as well, but hardcodes the domain name.
Yet another option is to make that location completely configurable. This way you can decide later (provided that you've changed all occurrences to the configured value): ${config.theOtherAppBaseUrl}/example.css. With this, you can try out all the different options yourself and within 10 minutes. And change your mind later, when you come to the conclusion that it's worth to go https everywhere.
(Note: You have an issue in your question's code: The last link refers to //DifferentContext...., which would assume that DifferentContext is a hostname - this is a protocol relative URL)

Include a JavaScript library in a JSP file

I'm trying to use JavaScript functions from the a JavaScript library in my JSP file to display the result on a web-browser page, but it seems like the inclusion didn't work.
I actually put the .js file corresponding to the library in the WEB-INF folder and added the following line in the JSP file to include it in it :
<script type="text/javascript" src="./jsgl.min.js"></script>
I successfully managed to use the library in a simple HTML file, that's why I don't understand why this doesn't work.
EDIT :
TLDR
Put the JS file in a folder under web content (but not WEB-INF) like [WebContent]/js/jsgl.min.js, and use the following in the JSP:
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jsgl.min.js"></script>
Explanation
JSP files are compiled by the server, then processed to send data (typically HTML) back to the web browser. A <script> tag is a HTML tag that gets interpreted by the browser, not by the servlet container. So the browser sees that in the HTML then makes a new request to the server for the JavaScript file in the src attribute.
The src attribute is relative to the URL that the browser asked for, not to the path of the JSP on the server.
So as an example, let's say:
The browser asks for a page at http://example.com/SomeWebApp/some-resource
The servlet container internally forwards the request to a JSP at /WEB-INF/jsp/somepage.jsp
The response sent to the browser contains the script tag <script type="text/javascript" src="./jsgl.min.js"></script> (as in your question)
The browser sees the URL ./jsgl.min.js and resolves it relative to the URL it has asked the server for (which in this case was http://example.com/SomeWebApp/some-resource - note there is no trailing '/') so the browser will request the JS file from http://example.com/SomeWebApp/jsgl.min.js*. This is because the relative URL in the script tag's src attribute starts with a '.'.
Another answer suggested putting the JS file in a 'js' folder and changing the script tag to <script type="text/javascript" src="/js/jsgl.min.js"></script>. Using the same original page URL as in the example above, the browser would translate this src URL to http://example.com/js/jsgl.min.js. Note that this is missing the "/SomeWebApp" context path.
The best solution therefore is indeed to put the JS file in a static folder like /js/jsgl.min.js, but to use the following in the JSP script tag:
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jsgl.min.js"></script>
The JSP will translate the ${pageContext.request.contextPath} bit into the current context path, making the code portable (if you redeploy the webapp with a different context path, it will still work). So the HTML response received by the browser will be (again, sticking with our example above):
<script type="text/javascript" src="/SomeWebApp/js/jsgl.min.js"></script>
The browser will now resolve that relative URL to the correct target.
__
*If the original URL had a trailing slash = i.e., was http://example.com/SomeWebApp/some-resource/, the JS URL would be http://example.com/SomeWebApp/some-resource/jsgl.min.js
Static resources should be put outside the WEB-INF folder (as you would typically not allow web access to its content).
You could put the file under webapp/js/, then change your script import to:
<script type="text/javascript" src="/js/jsgl.min.js"></script>
In addition to being good practice, this is good as it is not relative to the location of the JSP file.
Files in WEB-INF are inaccessible.
You may put them under webapp and try accessing as mentioned above.

javascript file not loading

Trying to import my js file from my page.
My page is in webcontent/mydomain/templates/page.xhtml
My js is in webcontent/mydomain/test/scripts
In page.xhtml
<script type="text/javascript" src="../test/scripts/test.js"></script>
But still the script is not getting picked.
Can anyone tell how I need to give the path in src.
Try this:
<script src="/test/scripts/test.js"></script>
Provided that webcontent is the root of public web content and thus /mydomain is also a public folder and thus your JavaScript is standalone available by http://localhost:8080/context/mydomain/test/scripts/test.js, assuming a domain of http://localhost:8080 and a context path of /context, then the following should do:
<script src="#{request.contextPath}/mydomain/test/scripts/test.js"></script>
This will generate a domain-relative URL with a dynamically inlined context path, which is much more robust than fiddling with ../ which would make the URI relative to the current request URI (as you see in browser's address bar) and not to the physical location of the template file as many starters incorrectly assume.

Edit external JavaScript file after breakpoint is hit

In the VS2010 IDE when a breakpoint (or an error) is hit, it opens a read-only [dynamic] version of the external JavaScript file I referenced. My workflow would be vastly improved if I could immediately edit this file, and refresh the browser. That is as opposed to digging up the original JS file opening it, finding the correct line and editing there.
I only know that this is possible because I was able to do this on my old work computer configuration, but for the life of me I can't duplicate it at home.
Has anyone made this work? Perhaps an extension? or maybe it has to with the way the files are referenced, or my basehref tag, or url rewriting.
This happens when the base href specifies a domain other than localhost. My issue was that to enable a local environment for Facebook JS, I need my domain in the url. So I set up my host file to remap localhost.mydomain.com to localhost.
When the Visual Studio IDE encounters a file reference which is something other than localhost, it does not attempt to grab the local file since it assumes (correctly in most cases) that it is being served from another site. In these cases it loads a file as [dynamic] and readonly.
Here is the test case:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<base href="http://localhost.mydomain.com/virtual-directory/" />
<script type="text/javascript" src="test.js"></script>
</head>
<body>
</html>
Any breakpoint within test.js will result in opening a readonly dynamic file.
how are you referencing your files? whenever a script block is written inside the html or is dynamically inserted the debugger will open the instance of the page where the code stops. If you reference the script using tags vs should open the original script file (at least that's what it does on my machine). could you upload an example of your current structure?

Categories

Resources