How to include js file in another js file? [duplicate]
How can I include a js file into another js file , so as to stick to the DRY principle and avoid duplication of code.
You can only include a script file in an HTML page, not in another script file. That said, you can write JavaScript which loads your "included" script into the same page:
var imported = document.createElement('script');
imported.src = '/path/to/imported/script';
document.head.appendChild(imported);
There's a good chance your code depends on your "included" script, however, in which case it may fail because the browser will load the "imported" script asynchronously. Your best bet will be to simply use a third-party library like jQuery or YUI, which solves this problem for you.
// jQuery
$.getScript('/path/to/imported/script.js', function()
{
// script is now loaded and executed.
// put your dependent JS here.
});
I disagree with the document.write
technique (see suggestion of Vahan Margaryan). I like document.getElementsByTagName('head')[0].appendChild(...)
(see suggestion of Matt Ball), but there is one important issue: the script execution order.
Recently, I have spent a lot of time reproducing one similar issue, and even the well-known jQuery plugin uses the same technique (see src here) to load the files, but others have also reported the issue. Imagine you have JavaScript library which consists of many scripts, and one loader.js
loads all the parts. Some parts are dependent on one another. Imagine you include another main.js
script per <script>
which uses the objects from loader.js
immediately after the loader.js
. The issue was that sometimes main.js
is executed before all the scripts are loaded by loader.js
. The usage of $(document).ready(function () {/*code here*/});
inside of main.js
script does not help. The usage of cascading onload
event handler in the loader.js
will make the script loading sequential instead of parallel, and will make it difficult to use main.js
script, which should just be an include somewhere after loader.js
.
By reproducing the issue in my environment, I can see that **the order of execution of the scripts in Internet Explorer 8 can differ in the inclusion of the JavaScript*. It is a very difficult issue if you need include scripts that are dependent on one another. The issue is described in Loading Javascript files in parallel, and the suggested workaround is to use document.writeln
:
document.writeln("<script type='text/javascript' src='Script1.js'></script>");
document.writeln("<script type='text/javascript' src='Script2.js'></script>");
So in the case of "the scripts are downloaded in parallel but executed in the order they're written to the page", after changing from document.getElementsByTagName('head')[0].appendChild(...)
technique to document.writeln
, I had not seen the issue anymore.
So I recommend that you use document.writeln
.
UPDATED: If somebody is interested, they can try to load (and reload) the page in Internet Explorer (the page uses the document.getElementsByTagName('head')[0].appendChild(...)
technique), and then compare with the fixed version used document.writeln
. (The code of the page is relatively dirty and is not from me, but it can be used to reproduce the issue).
You need to write a document.write object:
document.write('<script type="text/javascript" src="file.js" ></script>');
and place it in your main javascript file
It is not possible directly. You may as well write some preprocessor which can handle that.
If I understand it correctly then below are the things that can be helpful to achieve that:
Use a pre-processor which will run through your JS files for example looking for patterns like "@import somefile.js" and replace them with the content of the actual file. Nicholas Zakas(Yahoo) wrote one such library in Java which you can use (http://www.nczonline.net/blog/2009/09/22/introducing-combiner-a-javascriptcss-concatenation-tool/)
If you are using Ruby on Rails then you can give Jammit asset packaging a try, it uses assets.yml configuration file where you can define your packages which can contain multiple files and then refer them in your actual webpage by the package name.
Try using a module loader like RequireJS or a script loader like LabJs with the ability to control the loading sequence as well as taking advantage of parallel downloading.
JavaScript currently does not provide a "native" way of including a JavaScript file into another like CSS ( @import ), but all the above mentioned tools/ways can be helpful to achieve the DRY principle you mentioned. I can understand that it may not feel intuitive if you are from a Server-side background but this is the way things are. For front-end developers this problem is typically a "deployment and packaging issue".
Hope it helps.