36 Answers
36

JavaScript has no import, include, or require. There are other ways for JavaScript to include external JavaScript contents, though.

Ajax Loading

Load an additional script with an Ajax call and then use eval. This is the most straightforward way, but it is limited to your domain because of the JavaScript sandbox security model. Using eval also opens the door to bugs and hacks.

jQuery Loading

Dynamic Script Loading

Add a script tag with the script URL in the HTML. To avoid the overhead of jQuery, this is an ideal solution.

The script can even reside on a different server. Furthermore, the browser evaluates the code. The <script /> tag can be injected into either the web page <head>, or inserted just before the closing </body> tag.

Now, there is a big issue you must know about. Doing that implies that you remotely load the code. Modern web browsers will load the file and keep executing your current script because they load everything asynchronously to improve performance.

It means that if you use these tricks directly, you won't be able to use your newly loaded code the next line after you asked it to be loaded, because it will be still loading.

Well, you can use the hack the author suggests in the link I gave you. In summary, for people in a hurry, he uses en event to run a callback function when the script is loaded. So you can put all the code using the remote library in the callback function. For example:

not all javascript files are executed in a browser.
–
Michael PaulukonisJul 14 '10 at 17:42

41

Nope but somebody that uses something as advanced as Rhino or else wouldn't ask this question.
–
e-satisJul 15 '10 at 3:53

77

Just to be complete, there is a third way: In certain solutions when you control both javascript files, you can just make 1 giant javascript file which combines the content of both files.
–
ToadSep 7 '12 at 8:36

As a side note, if you use the jQuery one-liner, you will not be able to debug the code because its in VM and will not be visible. If you use the second method, you will have to load your scripts Synchronously, because the first callback will break asynchronous loads. $.when( loadscript('/some/file.js'), loadscript('/some/file2.js') ).done( /*second file is pending, fail.*/ );
–
Talvi WatiaJun 7 '13 at 16:18

If anyone is looking for something more advanced, try out RequireJS. You'll get added benefits such as dependency management, better concurrency, and avoid duplication (that is, retrieving a script more than once).

You can write your JavaScript files in "modules" and then reference them as dependencies in other scripts. Or you can use RequireJS as a simple "go get this script" solution.

RequireJS loads plain JavaScript files as well as more defined
modules. It is optimized for in-browser use, including in a Web
Worker, but it can be used in other JavaScript environments, like
Rhino and Node. It implements the Asynchronous Module API.

RequireJS uses plain script tags to load modules/files, so it should
allow for easy debugging. It can be used simply to load existing
JavaScript files, so you can add it to your existing project without
having to re-write your JavaScript files.

However, this method also has a problem: if an error happens in the imported JavaScript file, Firebug (and also Firefox Error Console and Chrome Developer Tools as well) will report its place incorrectly, which is a big problem if you use Firebug to track JavaScript errors down a lot (I do). Firebug simply doesn't know about the newly loaded file for some reason, so if an error occurs in that file, it reports that it occurred in your main HTML file, and you will have trouble finding out the real reason for the error.

But if that is not a problem for you, then this method should work.

I have actually written a jQuery plugin called *$.import_js()* which uses this method:

There is a good news for you. Very soon you will be able to load JavaScript code easily. It will become a standard way of importing modules of JavaScript code and will be part of core JavaScript itself.

You simply have to write import cond from 'cond.js'; to load a macro named cond from a file cond.js.

So you don't have to rely upon any JavaScript framework nor do you have to explicitly make Ajax calls.

require/import on the jsfile has been way too long in the coming. (IMO).
–
rwheadonApr 10 '13 at 16:12

8

more than a year later - still doesn't exist. =/
–
katshOct 17 '13 at 1:47

1

@rwheadon yeah seems appalling that this isnt part of the language! How js people get anything done is beyond me! Im new to it and this seems the worst (of many) bits of madness
–
Jonny LeedsFeb 7 '14 at 12:04

Or rather than including at run time, use a script to concatenate prior to upload.

I use Sprockets (I don't know if there are others). You build your JavaScript code in separate files and include comments that are processed by the Sprockets engine as includes. For development you can include files sequentially, then for production to merge them...

This is perhaps the biggest weakness of JavaScript in my opinion. It's caused me no end of problems over the years with dependency tracing. Anyhow, it does appear that the only practical solution is to use script includes in the HTML file and thus horribly making your JavaScript code dependent upon the user including the source you need and making reuse unfriendly.

Sorry if this comes across as a lecture ;) It's a bad habit of mine, but I want to make a point.

The problem comes back to the same as everything else with the web, the history of JavaScript. It really wasn't designed to be used in the widespread manner it's used in today. Netscape made a language that would allow you to control a few things, but they didn't envisage its widespread use for so many things as it is put to now and for one reason or another it's expanded from there, without addressing some of the fundamental weaknesses of he original strategy.

It's not alone of course. HTML wasn't designed for the modern webpage; it was designed to be a way of expressing the logic of a document, so that readers (browsers in the modern world) could display this in an applicable form that was within the capabilities of the system, and it took years for a solution (other than the hacks of MS and Netscape) to come along. CSS solves this problem, but it was a long time coming and even longer to get people to use it rather than the established BAD techniques. It happened though, praise be.

Hopefully JavaScript (especially now it's part of the standard) will develop to take on board the concept of proper modularity (as well as some other things) as every other (extant) programming language in the world does and this stupidity will go away. Until then you just have to not like it and lump it, I'm afraid.

Most of solutions shown here imply dynamical loading. I was searching instead for a compiler which assemble all the depended files into a single output file. The same as Less/Sass preprocessors deal with the CSS @import at-rule. Since I didn't find anything decent of this sort, I wrote a simple tool solving the issue.

On the jQuery master branch, they simply concatenate atomic source files into a single one starting with intro.js and ending with outtro.js. That doesn't suits me as it provides no flexibility on the source code design. Check out how it works with jsic:

Since this post I came up with much better solution - CommonJS module compiler - github.com/dsheiko/cjsc So you can simply write CommonJs or NodeJs modules and access each other yet keeping them in isolated scopes. The benefits: No need of multiple HTTP requests that affect performance You don't need manually wrapping you module code - it is responsibility of the compiler (so better source code readability) You don't need any external libraries It is compatible with UMD- and NodeJs modules (e.g. you can address jQuery, Backbone as modules without touching their code)
–
Dmitry SheikoMar 7 '14 at 16:07

the eval is what's wrong with it. From Crockford, "eval is evil. The eval function is the most misused feature of JavaScript. Avoid it. eval has aliases. Do not use the Function constructor. Do not pass strings to setTimeout or setInterval." If you haven't read his "JavaScript: The Good Parts" then go out and do it right now. You will not regret it.
–
MattDMoJun 1 '13 at 17:56

2

@MattDMo "Someone said it was bad" isn't really an argument.
–
emodendroketSep 3 '14 at 19:05

I have created a function that will allow you to use similar verbiage to C#/Java to include a JavaScript file. I've tested it a little bit even from inside of another JavaScript file and it seems to work. It does require jQuery though for a bit of "magic" at the end.

I put this code in a file at the root of my script directory (I named it global.js, but you can use whatever you want. Unless I'm mistaken this and jQuery should be the only required scripts on a given page. Keep in mind this is largely untested beyond some basic usage, so there may or may not be any issues with the way I've done it; use at your own risk yadda yadda I am not responsible if you screw anything up yadda yadda:

The @import syntax for achieving CSS-like JavaScript importing is possible using a tool such as Mixture via their special .mix file type (see here). I imagine the application simply uses one of the aforementioned methods "under the hood," though I don't know.

From the Mixture documentation on .mix files:

Mix files are simply .js or .css files with .mix. in the file name. A
mix file simply extends the functionality of a normal style or
script file and allows you to import and combine.

Mixture outputs this as scripts-global.js and also as a minified version (scripts-global.min.js).

Note: I'm not in any way affiliated with Mixture, other than using it as a front-end development tool. I came across this question upon seeing a .mix JavaScript file in action (in one of the Mixture boilerplates) and being a bit confused by it ("you can do this?" I thought to myself). Then I realized that it was an application-specific file type (somewhat disappointing, agreed). Nevertheless, figured the knowledge might be helpful for others.

Unfortunately, it's not really under development any more, and there's no guarantee that some future browser or JS engine or language version won't break it. You should try to be as up-to-date as possible with JS, although there is something to be said for stability. Even though this could be a good option for somebody, I'd much rather steer them toward RequireJS or jQuery.getScript(), both of which are stable and under constant development.
–
MattDMoJun 1 '13 at 18:02

Now, I may be totally misguided, but here's what I've recently started doing...
Start and end your JavaScript files with a carriage return, place in the PHP script, followed by one more carriage return.
The JavaScript comment "//" is ignored by PHP so the inclusion happens anyway. The purpose for the carriage returns is so that the first line of your included JavaScript isn't commented out.

Technically, you don't need the comment, but it posts errors in Dreamweaver that annoy me. If you're scripting in an IDE that doesn't post errors, you shouldn't need the comment or the carriage returns.