2

I read various d3js tutorials and nobody is explained why to use d3 you need to start a web server (whether in Python or Node, ...).

So, why is it necessary?

  • 4
    This has nothing to do with D3: modern browsers don't allow reading local files. If you create a D3 code with hardcoded data it will work just fine without a server. – Gerardo Furtado May 29 '18 at 11:58
  • Ok so the problem arises when I want to load an external file like a csv, json, etc? –  May 29 '18 at 12:04
  • 2
    Exactly. Again, nothing to do with D3, that's a browser's feature. – Gerardo Furtado May 29 '18 at 12:10
  • 1
    Good question! I think this issue comes up frequently enough that it warrants an attempt to write a formal answer to link to in the future. – Steve May 29 '18 at 17:50
  • @Steve the problem is that this has been asked/answered dozens of times. That's why I didn't answer it in the first place, I avoid answering clearly duplicated questions. – Gerardo Furtado May 29 '18 at 23:00
  • @GerardoFurtado Good point; I did notice that questions about d3 local files have been asked (and answered) a few times just in the last week. However, I have yet to see or find a comprehensive answer. For instance, many answers omit that Firefox does seem to work for async requests, and I rarely see any references to schemeless urls that sometimes occur in d3 examples. This question might serve as a good collection as to all of the issues that can arise with dealing with local files, since the question itself is pretty general. – Steve May 29 '18 at 23:17
  • @Steve yes, indeed. But since this has nothing to do with D3, if you look at general JS questions about the issue (i.e., without the d3.js tag), you'll find several good answers... those are the dupe targets I'm talking about. – Gerardo Furtado May 29 '18 at 23:18
  • @GerardoFurtado definitely makes sense-- I certainly didn't mean for my initial comment to be criticism about your comment, but as a justification for my answer below. My preliminary searches didn't turn up a comprehensive answer about JS pitfalls with local files (I'm probably not using the right search terms), and since it seems to come up so often, I thought it'd be good to try to answer as completely as I could, and use this question as a reference for the future. – Steve May 29 '18 at 23:50

1 Answers1

2

Sometimes it's not necessary. But in general, it's a good idea to replicate the environment that your code will be viewed in so you don't run into unforeseen issues when you publish or unnecessary frustrations due to using an environment not intended for your technology.

d3 is intended to run in the browser, with some parts of it requiring to be run on a web page for certain browsers. In my experience, the issues that arise from opening a d3 page directly in browser using the file URI, i.e. file://, are split into two categories: security and schemeless urls.

Security Limitations

The file:// protocol often has additional limitations. Particularly relevant to d3 is the restrictions of using XMLHttpRequest (used in d3v4 and below) and fetch (used in d3v5), which form the basis for loading data files (e.g. using d3.csv).

Chrome, and other browsers, does not normally allow XMLHttpRequest or fetch requests to local files. You may get an error that says something like:

Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https

You can read more about how to enable asynchronous reading from local files and the reasoning behind disabling it by default from this answer: https://stackoverflow.com/a/18137280/6184972

Firefox, however, does not seem to have this restriction.

Schemeless Urls

Some d3 examples, particularly older ones, include d3 using this convention:

<script src="//d3js.org/d3.v3.min.js"></script>

The //d3js.org is a Schemeless Url (also known as Protocol-Relative Urls) which means that the browser can decide what protocol to use. That means it will use https://d3js.org if the loading page uses https, and (maybe) http://d3js.org if the loading page uses http.

Unfortunately when loading a file through the file:// protocol, this means that the aforementioned URL will refer to file://d3js.org/d3.v3.min.js, which usually isn't what is intended. In this case you may get an error like:

GET file://d3js.org/d3.v3.min.js net::ERR_FILE_NOT_FOUND

Uncaught ReferenceError: d3 is not defined

Using Schemeless Urls has fallen out of favor, in lieu of always using https:// instead. See: https://stackoverflow.com/a/31100809/6184972

If this is the only issue that you're running into, it may be solvable by including the protocol (i.e. changing src="//d3js.org/d3.v3.min.js" to src="https://d3js.org/d3.v3.min.js"

Additional references:

https://developer.mozilla.org/en-US/docs/Learn/Common_questions/set_up_a_local_testing_server#The_problem_with_testing_local_files

Steve
  • 10,435
  • 15
  • 21