How to include JS file to another JS file?

Tine JavaScript tutorial on a sophisticated topic with code examples
30 August 2017   165121

Hype.codes team made a research and found several ways to solve this issue.

The old versions of JavaScript had no import, include, or require, so many different approaches to this problem have been developed.

But recent versions of JavaScript have standards like ES6 modules to import modules, although this is not supported yet by most browsers. Many people using modules with browser applications use build and/or transpilation tools to make it practical to use new syntax with features like modules.

ES6 Modules

Note that currently, browser support for ES6 Modules is not particularly great, but it is on it's way. They are supported (but behind flags) in Chrome 60, Firefox 54 and MS Edge 15, with only Safari 10.1 providing support without flags.

Thus, you will currently still need to use build and/or transpilation tools to valid JavaScript that will run in without any requirement for the user to use those browser versions or enable any flags.

Once ES6 Modules are commonplace, here is how you would go about using them:

// module.js
export function hello() {
  return "Hello";
}

// main.js
import {hello} from 'module'; // or './module'
let val = hello(); // val is "Hello";

Node.js

Node.js is currently using a module.exports/require system. You can use babel to transpile if you want the import syntax.

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

AJAX Loading

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.

jQuery Loading

The jQuery library provides loading functionality in one line:

$.getScript("my_lovely_script.js", function(){

   alert("Script loaded but not necessarily executed.");

});

Dynamic Script Loading

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"); //Make a script DOM node
    script.src = url; //Set it's 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 end of the head section of the page, where the srcattribute 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.

How to detect executed script?

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! 

Bytecode Alliance Launched to Promote WebAssembly

The purpose of the Alliance is the development of runtime and compilers, allowing WebAssembly to be used not only in web browsers
13 November 2019   129

Mozilla, Fastly, Intel, and Red Hat have teamed up to develop technologies that make WebAssembly a universal platform for safely executing code on any infrastructure, operating system, and device. For the joint development of runtime and compilers, allowing WebAssembly to be used not only in web browsers, the Bytecode Alliance community has been formed.

To create portable programs delivered in WebAssembly format that can be run outside the browser, it is proposed to use the WASI API (WebAssembly System Interface), which provides program interfaces for direct interaction with the operating system (POSIX API for working with files, sockets, etc.). A distinctive feature of the execution model of applications using WASI is the launch in a sandbox environment to isolate from the main system and the use of a security mechanism based on capability management - for actions with each of the resources (files, directories, sockets, system calls, etc.) the application must be given the appropriate authority (only access to the declared functionality is provided).

One of the goals of the created alliance is to solve the problem of the spread of modern modular applications with a large number of dependencies. In such applications, each dependency can be a potential source of vulnerabilities or attacks. Obtaining dependency control allows you to gain control over all applications associated with it. Confidence in the application automatically implies the existence of trust in all dependencies, but dependencies are often developed and accompanied by extraneous teams whose activities cannot be controlled. Bytecode Alliance members intend to prepare a complete solution for the safe execution of WebAssembly applications that are not initially trustworthy.

For protection, it is proposed to use the concept of nanoprocesses, in which each dependency module is separated into a separately isolated WebAssembly module, whose authority is set to bind only to this module (for example, a library for processing strings cannot open a network socket or file). Unlike process separation, WebAssembly handlers are lightweight and require almost no additional resources - the interaction between the handlers is not much slower than calling ordinary functions. Separation can be made not only at the level of individual modules, but also at the level of groups of modules, which, for example, need to work with common areas of memory

Requested permissions can be defined both at the level of dependencies themselves and delegated to dependencies in a chain by parent modules (resources in WASI are associated with a special type of file descriptors - capability). For example, the module can be delegated the ability to access a specific directory and system calls, and if the development infrastructure of the module is compromised or a vulnerability is identified, access will be limited only by these resources. Declaring resources by the creators of modules can become an indicator of suspicious activity, for example, when a text processing module requests permission to open a network connection. Initially, the set permissions are checked, and if they change, the dependency load is rejected until the local module signature is updated.

For joint development, several projects related to WebAssembly, previously separately developed by the founding companies of the alliance, were transferred under the Bytecode Alliance wing:

  • Wasmtime, a small and efficient runtime for WebAssembly & WASI
  • Lucet, an ahead-of-time compiler and runti
  • me for WebAssembly & WASI focused on low-latency, high-concurrency applications
  • WebAssembly Micro Runtime (WAMR), an interpreter-based WebAssembly runtime for embedded devices
  • Cranelift, a cross-platform code generator with a focus on security and performance, written in Rust

WebAssembly is much like Asm.js, but differs in that it is a binary format that is not dependent on JavaScript and allows you to execute low-level intermediate code in a browser compiled from various programming languages.