Reputation: 95950
How do I include a JavaScript file inside another JavaScript file, similar to @import
in CSS?
Upvotes: 6366
Views: 4490583
Reputation: 19
You can import the file via the following code:
const require = (module) => fetch(module).then(res => res.text()).then(eval);
require('./main.js');
...
Upvotes: -1
Reputation: 1092
A little extension to the library from Dan Dascalescu's answer taken from the Facebook idea.
(function() {
var __ = {};
this._ = function(name, callback) {
if(__[name]==undefined) {
__[name] = true;
var firstScript = document.getElementsByTagName('script')[0],
js = document.createElement('script');
js.src = name;
js.onload = callback;
firstScript.parentNode.insertBefore(js, firstScript);
}
}
})();
(new _('https://cdnjs.cloudflare.com/ajax/libs/Snowstorm/20131208/snowstorm-min.js', function() {
snowStorm.snowColor = '#99ccff';
}));
Upvotes: 4
Reputation: 191
include js internal url path
function createElement(urlPath) {
let s = document.createElement("script");
s.url = urlPath
document.body.appendChild(s);
}
function includeMoreJsPath(jsFilePath) {
for(let path of jsFilePath){
createElement(path)
}
}
includeMoreJsPath(["/path/to/some/file.js","/path/to/some/file2.js"]);
/*
<script src="/path/to/some/file.js"></script>
<script src="/path/to/some/file2.js"></script>
*/
include the external js url path
or you can eval
directly from text code
function createElement(code) {
let s = document.createElement("script");
s.appendChild(document.createTextNode(code));
document.body.appendChild(s);
}
async function includeMoreJsPath(jsFilePath) {
for(let path of jsFilePath){
let code = await(await fetch(path)).text()
createElement(code)
}
}
includeMoreJsPath(["'https://cdn.jsdelivr.net/momentjs/2.17.1/moment.min.js'"]);
/*
<script> ...code... </script>
*/
Upvotes: 0
Reputation: 1766
I will assume you are importing a file from the same directory, if not, you can update the path to fit the path.
To import another JavaScript file in the same directory, you can use the ES6 import
statement. Assuming you have two files, main.js
and helper.js
, both located in the same directory, you can import helper.js
in main.js
as follows:
export function helperFunction() {
// helper function code
}
import { helperFunction } from './helper.js';
// use helper function
helperFunction();
The import statement is followed by the name of the function or variable you want to import, and the path to the file, starting with ./
to indicate that it's in the current directory.
Note that the file extension .js is usually omitted in the import statement, but you can include it if you prefer.
Make sure to include the appropriate script tags in your HTML file to load both main.js and helper.js.
Upvotes: 4
Reputation: 259
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...
See also:
Upvotes: 25
Reputation: 1992
If you want to have a single link to all your javascript functions which are located in different files, you can do something like this using php:
Create a php file that will store all your javascript functions/triggers javascript.php
and make sure its a .php
file:
in your <head>
section
<script src="/directory/javascript.php"></script>
Let say you have a folder called /functions
where all the javascript files are located. Within your javascript.php
, create a header with content type application/javascript
, and use php glob
to include all the javascript files/scripts like so:
javascript.php
<?php
header("content-type:application/javascript");
foreach(glob("/functions/*.js") as $filename){include($filename);}
?>
Now you can just create separate javascript files and add them to your /functions
folder, or whatever you may call it. Those will be automatically included into the javascript.php
file that is actually a functioning js file which you can link in your <head>
section.
Upvotes: 1
Reputation: 92627
Yes, use type="module" in a script tag (support):
<script type="module" src="script.js"></script>
And in a script.js
file include another file like this:
import { hello } from './module.js';
...
// alert(hello());
In 'module.js' you must export the function/class that you will import:
export function hello() {
return "Hello World";
}
A working example is here.
Upvotes: 27
Reputation: 71
To import another script in JavaScript use the import
keyword:
import '/src/js/example.js';
// both types of quotes work
import "/src/js/example2.js";
Upvotes: 0
Reputation: 597261
The old versions of JavaScript had no import, include, or require, so many different approaches to this problem have been developed.
But since 2015 (ES6), JavaScript has had the ES6 modules standard to import modules in Node.js, which is also supported by most modern browsers.
For compatibility with older browsers, build tools like Webpack and Rollup and/or transpilation tools like Babel can be used.
ECMAScript (ES6) modules have been supported in Node.js since v8.5, with the --experimental-modules
flag, and since at least Node.js v13.8.0 without the flag. To enable "ESM" (vs. Node.js's previous CommonJS-style module system ["CJS"]) you either use "type": "module"
in package.json
or give the files the extension .mjs
. (Similarly, modules written with Node.js's previous CJS module can be named .cjs
if your default is ESM.)
Using package.json
:
{
"type": "module"
}
Then module.js
:
export function hello() {
return "Hello";
}
Then main.js
:
import { hello } from './module.js';
let val = hello(); // val is "Hello";
Using .mjs
, you'd have module.mjs
:
export function hello() {
return "Hello";
}
Then main.mjs
:
import { hello } from './module.mjs';
let val = hello(); // val is "Hello";
Browsers have had support for loading ECMAScript modules directly (no tools like Webpack required) since Safari 10.1, Chrome 61, Firefox 60, and Edge 16. Check the current support at caniuse. There is no need to use Node.js' .mjs
extension; browsers completely ignore file extensions on modules/scripts.
<script type="module">
import { hello } from './hello.mjs'; // Or the extension could be just `.js`
hello('world');
</script>
// hello.mjs -- or the extension could be just `.js`
export function hello(text) {
const div = document.createElement('div');
div.textContent = `Hello ${text}`;
document.body.appendChild(div);
}
Read more at https://jakearchibald.com/2017/es-modules-in-browsers/
Dynamic imports let the script load other scripts as needed:
<script type="module">
import('hello.mjs').then(module => {
module.hello('world');
});
</script>
Read more at https://developers.google.com/web/updates/2017/11/dynamic-import
The older CJS module style, still widely used in Node.js, is the module.exports
/require
system.
// mymodule.js
module.exports = {
hello: function() {
return "Hello";
}
}
// server.js
const myModule = require('./mymodule');
let val = myModule.hello(); // val is "Hello"
There are other ways for JavaScript to include external JavaScript contents in browsers that do not require preprocessing.
You could load an additional script with an AJAX call and then use eval
to run it. 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, hacks and security issues.
Like Dynamic Imports you can load one or many scripts with a fetch
call using promises to control order of execution for script dependencies using the Fetch Inject library:
fetchInject([
'https://cdn.jsdelivr.net/momentjs/2.17.1/moment.min.js'
]).then(() => {
console.log(`Finish in less than ${moment().endOf('year').fromNow(true)}`)
})
The jQuery library provides loading functionality in one line:
$.getScript("my_lovely_script.js", function() {
alert("Script loaded but not necessarily executed.");
});
You could add a script tag with the script URL into 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.
Here is an example of how this could work:
function dynamicallyLoadScript(url) {
var script = document.createElement("script"); // create a script DOM node
script.src = url; // set its src to the provided URL
document.head.appendChild(script); // add it to the end of the head section of the page (could change 'head' to 'body' to add it to the end of the body section instead)
}
This function will add a new <script>
tag to the end of the head section of the page, where the src
attribute is set to the URL which is given to the function as the first parameter.
Both of these solutions are discussed and illustrated in JavaScript Madness: Dynamic Script Loading.
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. (This applies to both the jQuery method and the manual dynamic script loading method.)
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.
For example: my_lovely_script.js
contains MySuperObject
:
var js = document.createElement("script");
js.type = "text/javascript";
js.src = jsFilePath;
document.body.appendChild(js);
var s = new MySuperObject();
Error : MySuperObject is undefined
Then you reload the page hitting F5. And it works! Confusing...
So what to do about it ?
Well, you can use the hack the author suggests in the link I gave you. In summary, for people in a hurry, he uses an 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:
function loadScript(url, callback)
{
// Adding the script tag to the head as suggested before
var head = document.head;
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = url;
// Then bind the event to the callback function.
// There are several events for cross browser compatibility.
script.onreadystatechange = callback;
script.onload = callback;
// Fire the loading
head.appendChild(script);
}
Then you write the code you want to use AFTER the script is loaded in a lambda function:
var myPrettyCode = function() {
// Here, do whatever you want
};
Then you run all that:
loadScript("my_lovely_script.js", myPrettyCode);
Note that the script may execute after the DOM has loaded, or before, depending on the browser and whether you included the line script.async = false;
. There's a great article on Javascript loading in general which discusses this.
As mentioned at the top of this answer, many developers use build/transpilation tool(s) like Parcel, Webpack, or Babel in their projects, allowing them to use upcoming JavaScript syntax, provide backward compatibility for older browsers, combine files, minify, perform code splitting etc.
Upvotes: 5476
Reputation: 9475
You can also use gulp
, gulp-concat
, gulp-typescript
with /// <reference path=
includes:
{
"scripts": {
"gulp": "gulp main"
},
"dependencies": {
"@types/gulp": "^4.0.6",
"@types/gulp-concat",
"@types/gulp-typescript",
"gulp": "^4.0.2",
"gulp-concat": "^2.6.1",
"gulp-resolve-dependencies": "^3.0.1",
"gulp-typescript": "^6.0.0-alpha.1",
"typescript": "^3.7.3"
}
}
class SomeClass {
delay: number;
}
/// <reference path="./someimport.ts" />
someclass = new SomeClass();
someclass.delay = 1;
This main
Gulp.js task (on gulpfile.js
) targets only the src/main.js
file, resolving all its /// <reference path=...
include references. These includes are know as Triple-Slash Directives
, and they are used only for transpilers tools to combine files. In our case, they are used explicitly by .pipe(resolveDependencies({
and by TypeScript itself when checking the file for missing types, variables, etc.
Refer to gulp-typescript if you would like to customize the var tsProject = ts.createProject
call and not use a tsconfig.json
file or override its parameters.
var gulp = require("gulp");
var concat = require('gulp-concat');
var resolveDependencies = require('gulp-resolve-dependencies');
var ts = require("gulp-typescript");
var tsProject = ts.createProject("tsconfig.json");
gulp.task("main", function() {
return gulp
.src(["src/main.ts"])
.pipe(resolveDependencies({
pattern: /^\s*\/\/\/\s*<\s*reference\s*path\s*=\s*(?:"|')([^'"\n]+)/gm
}))
.on('error', function(err) {
console.log(err.message);
})
.pipe(tsProject())
.pipe(concat('main.js'))
.pipe(gulp.dest("build/"));
});
If you would like to target all your TypeScript project files instead of only src/main.ts
, you can replace this:
return gulp
.src(["src/main.ts"])
.pipe(resolveDependencies({
...
// -->
return tsProject
.src()
.pipe(resolveDependencies({
...
If you do not want to use TypeScript, you can use this simplified gulpfile.js
and remove all TypeScript includes from package.json
:
var gulp = require("gulp");
var concat = require('gulp-concat');
var resolveDependencies = require('gulp-resolve-dependencies');
gulp.task("main", function() {
return gulp
.src(["src/main.js"])
.pipe(resolveDependencies({
pattern: /^\s*\/\/\/\s*<\s*reference\s*path\s*=\s*(?:"|')([^'"\n]+)/gm
}))
.on('error', function(err) {
console.log(err.message);
})
.pipe(concat('main.js'))
.pipe(gulp.dest("build/"));
});
{
"scripts": {
"gulp": "gulp main"
},
"dependencies": {
"gulp": "^4.0.2",
"gulp-concat": "^2.6.1",
"gulp-resolve-dependencies": "^3.0.1"
}
}
Then, after running the command npm run gulp
, the file build/main.js
is created with the following as its contents:
class SomeClass {
}
/// <reference path="./someimport.ts" />
someclass = new SomeClass();
someclass.delay = 1;
Which allows me to include it in the browser with the script
tag, after serving the build
directory files:
<html>
<head>
<script src="main.js"></script>
</head>
<body>
<script type="text/javascript">
console.log(someclass.delay);
</script>
</body>
</html>
Related questions:
Upvotes: 0
Reputation: 23500
So this is a edge case. But if you need to load the JavaScript from a remote source, most modern browsers might block your cross-site requests due to CORS or something similar. So normal
<script src="https://another-domain.com/example.js"></script>
Won't work. And doing the document.createElement('script').src = '...'
won't cut it either. Instead, what you could do is load the JavaScript code as a resource via standard GET
request, and do this:
<script type="text/javascript">
var script = document.createElement('script');
script.type = 'text/javascript';
let xhr = new XMLHttpRequest();
xhr.open("GET", 'https://raw.githubusercontent.com/Torxed/slimWebSocket/master/slimWebSocket.js', true);
xhr.onreadystatechange = function() {
if (this.readyState === XMLHttpRequest.DONE && this.status === 200) {
script.innerHTML = this.responseText; // <-- This one
document.head.appendChild(script);
}
}
xhr.send();
</script>
By grabbing the content yourself, the browser won't notice malicious intents and allow you go do the request. Then you add it in <script>
's innerHTML
instead. This still causes the browser (at least tested in Chrome) to parse/execute the script.
Again, this is a edge case use case. And you'll have no backwards compatibility or browser compliance probably. But fun/useful thing to know about.
Upvotes: 3
Reputation: 1913
I did not see an answer whereby you create an object of all functions and variables in a file and then make that object an argument to refer to it in another file.
E.g., you have files called 'jsMod.js', 'jsView' and 'jsContr.js':
JSMODOBJ = {};
JSMODOBJ.valueAddition = function(/* element value 1 */ val1, /* element value 2 */ val2) {
return val1 + val2;
}
JSVIEWOBJ = {};
JSVIEWOBJ.elementColour = function(/* element id to change colour */ id, /* css colour classname */ col) {
document.getElementById(id).className = col;
}
JSCONTROBJ = {};
var jsMod = JSMODOBJ;
var jsView = JSVIEWOBJ;
JSCONTROBJ.changeColourByValue = function (val1, val2, id, clss) {
if (jsMod.valueAddition(val1,val2) !== 0) {
jsView.elementColour(id, clss);
}
}
Then you can set the .js files dynamically by echoeing the scripts
into your .html or .php file:
<?php
echo "<script src = './js/dleafView.js'></script>
<script src = './js/dleafModule.js'></script>
<script src = './js/dleafContr.js'></script>";
?>
Then just call the control function within a <script type="text/javascript"></script>
tag. Of course, this will take a lot of time in the beginning to set up, but it saves you time in the long run.
I use this in a slightly different way, but this way also works.
Upvotes: 0
Reputation: 643
On the back-end, you can use CommonJS modules. For example:
//a.js
function func () {
var result = "OK Bro";
return result;
}
module.exports = { func };
//b.js
var a = require('./a.js');
console.log(a.func);
Upvotes: -1
Reputation: 196
It’s this simple:
var js = document.createElement("script");
js.type = "text/javascript";
js.src = jsFilePath;
document.body.appendChild(js);
Upvotes: 1
Reputation: 4074
This is the easiest solution. Use a bundler like Vite.js and then simply do:
import "./path/to/js/file";
That's it! The OP has asked for something like "@import
in CSS" and this is exactly like that. It is also not as rocket science complex as some of the old methods. It is at least undoubtedly the most beginner-friendly method, but I'm sure non-beginners do like it as well.
To get started with Vite for a vanilla JavaScript project, just have Node.js and [NPM3 installed, and then do:
npm create vite@latest <your-vanilla-js-app-name> --template vanilla
E.g.:
npm create vite@latest my-js-app --template vanilla
Now add imports like mentioned at the beginning of this answer and call it a day.
Just as a side note: Also another thing that might pop into your mind is namespacing issues, e.g., what if a name you have used in a file you're including is similar to a name you already have in your current file? But that's the nature of JavaScript, right? It's not an issue specific to this method.
So you'll need to devise strategies for handling that separately. There's a comprehensive article on Addy Osmani's blog in case you want to learn more about that: Design Patterns for Handling the Global Namespace in JavaScript.
Upvotes: -1
Reputation: 599
Don't forget to check out LAB.js!
<script type="text/javascript">
$LAB.script("jquery-1.8.3.js").wait().script("scripts/clientscript.js");
</script>
Upvotes: 5
Reputation: 3381
The above function works fine if you are loading only one script or you don't care about the loading order of multiple scripts. If you have some scripts that depends on others, you need to use Promise to specify the order of loading. The reason behind this is Javascript loads resources like scripts and images asynchronously. The loading sequence does not depends on the sequence of asynchronous calls, meaning script1 will not be guaranteed to load before script2 even if you call dynamicallyLoadScript("scrip1")
before calling dynamicallyLoadScript("scrip2")
So here's another version of dynamicallyLoadScript that guarantees loading order:
// Based on: https://javascript.info/promise-basics#example-loadscript
function dynamicallyLoadScript(url) {
return new Promise(function(resolve, reject) {
var script = document.createElement("script");
script.src = url;
script.onload = resolve;
script.onerror = () => reject(new Error(`Error when loading ${url}!`));
document.body.appendChild(script);
});
}
For more on Promises, see this excellent page.
The usage of this new dynamicallyLoadScript is very simple:
dynamicallyLoadScript("script1.js")
.then(() => dynamicallyLoadScript("script2.js"))
.then(() => dynamicallyLoadScript("script3.js"))
.then(() => dynamicallyLoadScript("script4.js"))
.then(() => dynamicallyLoadScript("script5.js"))
//...
Now the scripts are loaded in the order of script1.js, script2.js, script3.js, etc.
In addition, you can immediately run code that uses the scripts after they are loaded. Just add another .then
after the loading the script:
dynamicallyLoadScript("script1.js")
.then(() => dynamicallyLoadScript("script2.js"))
.then(() => foo()) // foo can be a function defined in either script1, script2
.then(() => dynamicallyLoadScript("script3.js"))
.then(() => {
if (var1){ // var1 can be a global variable defined in either script1, script2, or script3
bar(var1); // bar can be a function defined in either script1, script2, or script3
} else {
foo(var1);
}
})
//more .then chains...
To display unhandled promise rejections (errors loading scripts, etc), put this unhandledrejection
event listener at the top of your code:
// Based on: https://javascript.info/promise-error-handling#unhandled-rejections
window.addEventListener('unhandledrejection', function(event) {
// the event object has two special properties:
console.error(event.promise);// the promise that generated the error
console.error(event.reason); // the unhandled error object
});
Now you will be notified of any script loading errors.
If you are loading a lot of scripts without executing code immediately after loading, this shorthand function may come in handy:
function dynamicallyLoadScripts(urls) {
if (urls.length === 0)
return;
let promise = dynamicallyLoadScript(urls[0]);
urls.slice(1).forEach(url => {
promise = promise.then(() => dynamicallyLoadScript(url));
});
}
To use it, just pass in an array of script urls like this:
const scriptURLs = ["dist/script1.js", "dist/script2.js", "dist/script3.js"];
dynamicallyLoadScripts(scriptURLs);
The scripts will be loaded in the order they appear in the array.
Upvotes: 3
Reputation: 10711
If you find there are two or more scripts occupying the same function when they are called, and we cannot be include them at the same time, we need to do it dynamically by user selection.
Including another file in jQuery using $.getScript
works since the script will not be cached by default. So we are safe to call other scripts. The calls can be arranged like this:
HTML
<select class="choice">
<option value="script1" selected>Script-1</option>
<option value="script2">Script-2</option>
</select>
JavaScript
$(".choice").change(on_change);
var url = "https://example.com";
$.url1 = url + "/script1.js";
$.url2 = url + "/script2.js";
function on_change() {
if ($(".choice").val()=="script1") {
script1();
} else {
script2();
}
}
// script1
function script1() {
$.getScript($.url1, function( data, textStatus, jqxhr ) {
// Execute here
});
}
// script2
function script2() {
$.getScript($.url2, function( data, textStatus, jqxhr ) {
// Execute here
});
}
Upvotes: 2
Reputation: 63
You can just use the require(); tag.
For example, if I had a addition.js module that I wanted to add to math.js, I would do this:
//this is math.js
//vars
let a = 1;
let b = 3;
//start of code
const additionfile = require('addition.js');
window.alert("You added " + a + " and " + b + " together, to get " + additionfile.add(a,b) + "!");
if you wanted the addition.js file, it would look something like this
function add(a,b) {
const sum = a + b;
return sum;
}
Upvotes: -2
Reputation: 196
So if you want it quick, and easy... Try this:
function include(filename)
{
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.src = filename;
script.type = 'text/javascript';
head.appendChild(script)
}
Upvotes: 1
Reputation: 730
My general solution taken from the efekt.js.st
library from EdgeS (which I authored).
shameless plug alert - I am on other stackexchange network sites. This is a relink of
https://codereview.stackexchange.com/questions/263764/dynamic-load-css-or-script
.
What code or design would you use to support dynamic-loading of css
and scripts
?
Requirements
head
, body
, or current script-element
css
, js
, mjs
modules or other script-typesnonce
, crossorigin
, etcstatic loadScriptOrStyle(url, options) {
// provenance :<# **Smallscript EdgeS efekt** `efekt.js.st` github libraries #>
// returns :<Promise#onload;onerror>
// options :<# `fIgnoreCache`, `fAppendToHead`, `fUrlIsStyle`, `attrs:{}` #>
const head = document.head; let node = options?.fAppendToBody ? document.body : head;
const url_loader_cache = document.head.url_loader_cache
? head.url_loader_cache
: (head.url_loader_cache = {script:{},link:{}})
const kind = (options?.fUrlIsStyle || /\.css(?:(?:\?|#).*)?$/i.test(url))
? 'link' : 'script';
// check already-loaded cache
if(url_loader_cache[kind][url]) {
const el = url_loader_cache[kind][url];
// support `fIgnoreCache` reload-option; should not use on `head`
if(options?.fIgnoreCache)
el.remove();
else
return(new CustomEvent('cache',{detail:el}));
}
// (re)create and record it
const self = document.currentScript;
const el = url_loader_cache[kind][url] = document.createElement(kind);
const append = (!self || options?.fAppendToHead || options?.fAppendToBody)
? el => node.appendChild(el)
: el => self.parentNode.insertBefore(el, self);
const load = new Promise((resolve, reject) => {
el.onload = e => {e.detail = el;resolve(e)};
el.onerror = e => {e.detail = el;reject(e)};
// `onload` or `onerror` possibly alter `cache` value
// throw(new URIError(`The ${url} didn't load correctly.`))
});
// configure `module` attr, as appropriate
if(/\.mjs(?:(?:\?|#).*)?$/i.test(url))
el.type = 'module'
// configure other attrs as appropriate (referrer, nonce, etc)
for(const key in options?.attrs) {el[key] = attrs[key]}
// trigger it
if(kind === 'link') el.rel = 'stylesheet', el.href = url; else el.src = url;
append(el);
return(load);
}
Upvotes: 1
Reputation: 2704
There actually is a way to load a JavaScript file not asynchronously, so you could use the functions included in your newly loaded file right after loading it, and I think it works in all browsers.
You need to use jQuery.append()
on the <head>
element of your page, that is:
$("head").append($("<script></script>").attr("src", url));
/* Note that following line of code is incorrect because it doesn't escape the
* HTML attribute src correctly and will fail if `url` contains special characters:
* $("head").append('<script src="' + url + '"></script>');
*/
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:
(function($)
{
/*
* $.import_js() helper (for JavaScript importing within JavaScript code).
*/
var import_js_imported = [];
$.extend(true,
{
import_js : function(script)
{
var found = false;
for (var i = 0; i < import_js_imported.length; i++)
if (import_js_imported[i] == script) {
found = true;
break;
}
if (found == false) {
$("head").append($('<script></script').attr('src', script));
import_js_imported.push(script);
}
}
});
})(jQuery);
So all you would need to do to import JavaScript is:
$.import_js('/path_to_project/scripts/somefunctions.js');
I also made a simple test for this at Example.
It includes a main.js
file in the main HTML and then the script in main.js
uses $.import_js()
to import an additional file called included.js
, which defines this function:
function hello()
{
alert("Hello world!");
}
And right after including included.js
, the hello()
function is called, and you get the alert.
(This answer is in response to e-satis' comment).
Upvotes: 241
Reputation: 2075
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 assume the application does this via one of above-mentioned methods.
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.
Here's an example .mix
file that combines multiple .js
files into one:
// scripts-global.mix.js
// Plugins - Global
@import "global-plugins/headroom.js";
@import "global-plugins/retina-1.1.0.js";
@import "global-plugins/isotope.js";
@import "global-plugins/jquery.fitvids.js";
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.
Note: Mixture was discontinued on 2016/07/26 (after being open sourced on 2015/04/12).
Upvotes: 19
Reputation: 11253
Keep it nice, short, simple, and maintainable! :]
// Third-party plugins / script (don't forget the full path is necessary)
var FULL_PATH = '', s =
[
FULL_PATH + 'plugins/script.js' // Script example
FULL_PATH + 'plugins/jquery.1.2.js', // jQuery Library
FULL_PATH + 'plugins/crypto-js/hmac-sha1.js', // CryptoJS
FULL_PATH + 'plugins/crypto-js/enc-base64-min.js' // CryptoJS
];
function load(url)
{
var ajax = new XMLHttpRequest();
ajax.open('GET', url, false);
ajax.onreadystatechange = function ()
{
var script = ajax.response || ajax.responseText;
if (ajax.readyState === 4)
{
switch(ajax.status)
{
case 200:
eval.apply( window, [script] );
console.log("library loaded: ", url);
break;
default:
console.log("ERROR: library not loaded: ", url);
}
}
};
ajax.send(null);
}
// Initialize a single load
load('plugins/script.js');
// Initialize a full load of scripts
if (s.length > 0)
{
for (i = 0; i < s.length; i++)
{
load(s[i]);
}
}
This code is simply a short functional example that could require additional feature functionality for full support on any (or given) platform.
Upvotes: 13
Reputation: 1605
If you want it in pure JavaScript, you can use document.write
.
document.write('<script src="myscript.js" type="text/javascript"></script>');
If you use the jQuery library, you can use the $.getScript
method.
$.getScript("another_script.js");
Upvotes: 53
Reputation: 11717
This script will add a JavaScript file to the top of any other <script>
tag:
(function () {
var li = document.createElement('script');
li.type = 'text/javascript';
li.src = "http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js";
li.async = true;
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(li, s);
})();
Upvotes: 13
Reputation: 3727
Please note that we usually use static scripts. So we want to be taken from the cache as much as possible.
This saves network traffic and speeds up landing.
Usage
$.cachedScript( "ajax/test.js" ).done(function( script, textStatus ) {
console.log( textStatus );
});
The cache: true option has been added to the Ajax method.
Upvotes: 2
Reputation: 104870
Yes, there is...
Keep reading. In ES6, we can export
and import
part or whole JavaScript file into another one...
But wait, ES6 is not supported in all the browsers, so you need to transpile it using babel.js
for example...
So you create a class like below:
class Person {
constructor(name) {
this.name = name;
}
build() {
return new Person(this);
}
}
module.exports = Person;
In another JavaScript file, do the import like:
import { Person } from 'Person';
You also can require the file like:
const Person = require('./Person');
If you are using an older JavaScript version you can use requirejs:
requirejs(["helper/util"], function(util) {
// This function is called when scripts/helper/util.js is loaded.
// If util.js calls define(), then this function is not fired until
// util's dependencies have loaded, and the util argument will hold
// the module value for "helper/util".
});
If you want to stick to older version of stuff, like jQuery, you can also use something like getScript:
jQuery.getScript('./another-script.js', function() {
// Call back after another-script loaded
});
Last, but not the least, don't forget you can do the traditional way of putting a script together using the <script>
tag...
<script src="./first-script.js"></script>
<script src="./second-script.js"></script>
<script src="./third-script.js"></script>
There are also the async and defer attributes which I should mention here...
Note: There are several ways an external script can be executed:
- If async is present: The script is executed asynchronously with the rest of the page (the script will be executed while the page continues the parsing)
- If async is not present and defer is present: The script is executed when the page has finished parsing
- If neither async or defer is present: The script is fetched and executed immediately, before the browser continues parsing the page
Upvotes: 12
Reputation: 22354
For Node.js only, this worked for me the best!
I've tried most solutions here, but none helped me about just being able to load another file without changing scope. Finally I used this. Which preserves the scope and everything. It is as good as your code is in that point.
const fs = require('fs');
eval(fs.readFileSync('file.js') + '');
Upvotes: 10