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.

Run a Web Server

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.)

serve NPM Package

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

localhost

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.

Open as a File

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.

Domain and Base URL

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.

Rooted Paths

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.

Same-Origin Policy

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 from localhost: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:

https://blogs.msdn.microsoft.com/freeassociations/2005/05/19/the-bizarre-and-unhappy-story-of-file-urls/

⚠️ **GitHub.com Fallback** ⚠️