Web Basics — Working Locally - odigity/academy GitHub Wiki
There are two ways to use your browser to view HTML documents on your computer while working on them:
- open as a file
- run a web server locally (recommended)
The differences are subtle, and will be covered below.
The best way to work is to run a web server on your desktop and access the the site from your browser using an HTTP URL. That most closely simulates real-world conditions, with a web browser connecting to a web server and speaking HTTP. (The browser behaves slightly differently when you simply open a file directly. See Open as a File for details.)
Since you should have Node.js installed on your desktop for dev purposes anyway, the easiest way to run a web server is install the serve NPM package:
Windows
> npm install -g serve
Linux, Mac OSX
$ sudo npm install -g serve
This will install the serve
command, which you can run in any directory to serve the files in that directory:
$ serve
Running on http://localhost:3000
The output will conveniently show you the URL you can use to reach the web server.
The root path (/
) will load the index.html file in the directory you ran the serve
command, or if none exists, will show a directory listing.
The command will "bind" to port 3000 by default, which is a common convention when developing locally.
You can change that with the -p
parameter:
$ serve -p 5000
Running on http://localhost:5000
The localhost domain is a special domain that browsers and operating systems recognize as meaning "this computer".
Technically, it translates to the IP address 127.0.0.1, which is a special IP address that means "this computer".
You could use the IP address directly (http://127.0.0.1/
), but some things work differently with IP address URLs, such as cookies which are tied to the domain.
Best to just use localhost.
Alternatively, you can view a file in your browser by opening it directly, either by using File -> Open File and navigating to the file on your computer, or simply dragging the file onto the browser window.
Either one will result in a URL that uses the file://
protocol instead of http://
, which will look something like this:
Chrome: file:///C:/Users/Jon/Documents/Mosaic/Grid%20Game/index.html
Firefox: file:///C:/Users/Jon/Documents/Mosaic/Grid%20Game/index.html
IE: C:\Users\Jon\Documents\Mosaic\Grid Game\index.html (HORRIBLE!)
However, I don't recommend this. Let's discuss why.
All tests performed on Firefox and Chrome on Ubuntu.
The most obvious different is that DOM properties and methods having to do with the domain will not work as expected. Here is an example:
document.domain
The document.domain
property returns the domain portion of the URL.
Let's see what happens:
URL document.domain
---------------------------- ---------------------------
http://www.google.com/ -> www.google.com
http://localhost:3000/ -> localhost
file:///home/ofer/index.html -> file://home/ofer/index.html
The space between the second and third slash is for the host, including for file://
URLs.
If left blank, it defaults to localhost.
You can make it explicit, in which case document.domain
will return a good value:
URL document.domain
------------------------------------- ---------------------------
file://localhost/home/ofer/index.html -> localhost
But you'll have to manually add the 'localhost' part every time you open a new file.
It is best to use relative links when creating your web pages, like foo.html
, subdir/bar.css
, and ../sibling/baz.js
.
This allows for maximum flexibility during deployment — you can host your website on any domain and under any path (like http://example.com/apps/myapp/
, and it will work fine.
However, sometimes it's convenient or necessary to use a "rooted path", like /path/to/file.css
, that is relative to the root path of the domain.
Unfortunately, these links will break when you open the page as a file.
Let's say you have the following two files on your computer:
/home/ofer/myapp/index.html
/home/ofer/myapp/other.html
And you want to link from index.html to other.html:
# index.html
<html><body><a href="/other.html">other path</a></body></html>
If you run the serve
command in /home/ofer/myapp and go to http://localhost:3000/
, it will work fine.
The link will take you to http://localhost:3000/other.html
.
However, if you open the index.html as a file (file:///home/ofer/myapp/index.html
) and click on the link, it will take you to file:///other.html
, which will look in the root directory of your computer — which is, of course, the wrong place.
The Same-Origin Policy restricts how a document or script loaded from one origin can interact with a resource from another origin. Two pages have the same origin if the protocol, port, and host are the same for both pages.
The details are complicated, so click the above link if you want to know more. The two most affected features are cookies and localStorage.
localStorage
Access to data stored in the browser such as localStorage and IndexedDB are separated by origin. Each origin gets its own separate storage, and JavaScript in one origin cannot read from or write to the storage belonging to another origin.
Cookies
Cookies use a separate definition of origins.
A page can set a cookie for its own domain or any parent domain, as long as the parent domain is not a public suffix. The browser will make a cookie available to the given domain including any sub-domains, no matter which protocol (http/https) or port is used.
When you set a cookie, you can limit its availability using the Domain, Path, Secure and Http-Only flags.
File URI Differences
According to MDN:
"A file can read another file only if the parent directory of the originating file is an ancestor directory of the target file."
and
"For cross-window DOM access, each file is treated as a separate origin."
When I tested this using my localStorage Explorer app, I got the following results:
- In both browsers, an app loaded from
localhost:3001
was allocated a separate localStorage area than an app loaded fromlocalhost:3000
. - In Chrome, all file URIs share the same localStorage area, but writes do not trigger
storage
events in other tabs. - In Firefox, the same file URI loaded in two different tabs share a localStorage area and trigger `storage events in the other, but each distinct file URI is allocated a separate localStorage area.
Just another reason to avoid file://
URIs.
For fun: