6380

How do I include a JavaScript file inside another JavaScript file, similar to @import in CSS?

1

72 Answers 72

1 2
3
1

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

  • support promise-await-async including error-handling
  • support load-once caching, including reloading
  • support load in head, body, or current script-element
  • support load css, js, mjs modules or other script-types
  • support other tag attrs, like nonce, crossorigin, etc
static 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); } 
Sign up to request clarification or add additional context in comments.

Comments

1

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

Comments

1

It’s this simple:

var js = document.createElement("script"); js.type = "text/javascript"; js.src = jsFilePath; document.body.appendChild(js); 

Comments

1

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.

Comments

0

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.

1 Comment

Notice1: You might need to run an additional npm run dev as well in case it doesn't start the server for you automatically. Notice2: Of course Vite.js is more than just a bundler, refer to their website if you want to know more: vitejs.dev. Notice3: I was the 5959th upvote on this question, it's pointless, but it's funny :D
0

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

Comments

0

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':

File jsMod.js

JSMODOBJ = {}; JSMODOBJ.valueAddition = function(/* element value 1 */ val1, /* element value 2 */ val2) { return val1 + val2; } 

File jsView.js

JSVIEWOBJ = {}; JSVIEWOBJ.elementColour = function(/* element id to change colour */ id, /* css colour classname */ col) { document.getElementById(id).className = col; } 

File jsContr.js

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.

Comments

0

You can also use gulp, gulp-concat, gulp-typescript with /// <reference path= includes:

File packages.json

{ "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" } } 

File src/someimport.ts

class SomeClass { delay: number; } 

File src/main.ts

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

  1. Triple-Slash Directives
  2. When do I need a triple slash reference?

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.

File gulpfile.js

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/")); }); 

Pure javascript version

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:

File gulpfile.js

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/")); }); 

File packages.json

{ "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:

File build/main.js

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:

  1. TypeScript: Gulp
  2. Can I use TypeScript without RequireJS?
  3. Simple concatenation of main file that requires another JavaScript file using Gulp.js
  4. Client on Node.js: Uncaught ReferenceError: require is not defined
  5. How can TypeScript browser Node.js modules be compiled with Gulp.js?
  6. Concatenate files using babel
  7. How can I 'require' CommonJS modules in the browser?
  8. Is there an alternative to Browserify?

Comments

0

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"; 

Comments

0

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> */ 

Comments

-1

You can import the file via the following code:

const require = (module) => fetch(module).then(res => res.text()).then(eval); require('./main.js'); ... 

Comments

-2

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; } 

3 Comments

This function does not even exist, tested in latest Chrome: Uncaught ReferenceError: require is not defined
This only works on Node.JS.
This works actually pretty good when using Node.JS anyways. But you have to add a module.exports = { add }; in the end of the second (required) file. Here is a in detail explantation: linkstanleyulili.com/node/…
1 2
3

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.