Как включить файл JavaScript в другой файл JavaScript?
Есть ли в JavaScript что-то похожее на @import
в CSS, что позволяет включить файл JavaScript в другой файл JavaScript?
74 ответа
В старых версиях JavaScript не было импорта, включения или требования, поэтому было разработано много разных подходов к этой проблеме.
Но с 2015 года (ES6) в JavaScript появился стандарт модулей ES6 для импорта модулей в Node.js, который также поддерживается большинством современных браузеров.
Для совместимости со старыми браузерами можно использовать инструменты сборки и / или переноса.
ES6 Модули
Модули ECMAScript (ES6) поддерживаются в Node.js начиная с версии 8.5, с --experimental-modules
флаг. Все файлы должны иметь .mjs
расширение.
// module.mjs
export function hello() {
return "Hello";
}
// main.mjs
import { hello } from 'module'; // or './module'
let val = hello(); // val is "Hello";
Модули ECMAScript в браузерах
Браузеры поддерживают загрузку модулей ECMAScript напрямую (не требуются такие инструменты, как Webpack) начиная с Safari 10.1, Chrome 61, Firefox 60 и Edge 16. Проверьте текущую поддержку в caniuse.
<script type="module">
import { hello } from './hello.mjs';
hello('world');
</script>
// hello.mjs
export function hello(text) {
const div = document.createElement('div');
div.textContent = `Hello ${text}`;
document.body.appendChild(div);
}
Узнайте больше на https://jakearchibald.com/2017/es-modules-in-browsers/
Динамический импорт в браузерах
Динамический импорт позволяет скрипту загружать другие скрипты по мере необходимости:
<script type="module">
import('hello.mjs').then(module => {
module.hello('world');
});
</script>
Подробнее читайте на https://developers.google.com/web/updates/2017/11/dynamic-import
Node.js требует
Старый стиль импорта модулей, все еще широко используемый в Node.js, это система module.exports/require.
// mymodule.js
module.exports = {
hello: function() {
return "Hello";
}
}
// server.js
const myModule = require('./mymodule');
let val = myModule.hello(); // val is "Hello"
Существуют и другие способы включения JavaScript внешнего содержимого в браузерах, которые не требуют предварительной обработки.
AJAX Загрузка
Вы можете загрузить дополнительный скрипт с помощью вызова AJAX, а затем использовать eval
запустить его. Это самый простой способ, но он ограничен вашим доменом из-за модели безопасности песочницы JavaScript. С помощью eval
также открывает дверь к ошибкам, взломам и проблемам безопасности.
Загрузка Загрузка
Как и Dynamic Imports, вы можете загрузить один или несколько сценариев с fetch
вызовите с помощью обещаний для контроля порядка выполнения зависимостей скрипта с помощью библиотеки Fetch Inject:
fetchInject([
'https://cdn.jsdelivr.net/momentjs/2.17.1/moment.min.js'
]).then(() => {
console.log(`Finish in less than ${moment().endOf('year').fromNow(true)}`)
})
Загрузка jQuery
Библиотека jQuery обеспечивает загрузку в одну строку:
$.getScript("my_lovely_script.js", function() {
alert("Script loaded but not necessarily executed.");
});
Динамическая загрузка скриптов
Вы можете добавить тег HTML с URL скрипта в HTML. Чтобы избежать накладных расходов jQuery, это идеальное решение.
Скрипт может даже находиться на другом сервере. Кроме того, браузер оценивает код. <script>
тег может быть введен в любую веб-страницу <head>
или вставлен непосредственно перед закрытием </body>
тег.
Вот пример того, как это может работать:
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)
}
Эта функция добавит новый <script>
тег до конца раздела заголовка страницы, где src
атрибут установлен на URL, который задан функции в качестве первого параметра.
Оба эти решения обсуждаются и иллюстрируются в JavaScript Madness: динамическая загрузка скриптов.
Обнаружение, когда скрипт был выполнен
Теперь есть большая проблема, о которой вы должны знать. Это подразумевает, что вы загружаете код удаленно. Современные веб-браузеры загружают файл и продолжают выполнять ваш текущий скрипт, потому что они загружают все асинхронно для повышения производительности. (Это относится как к методу jQuery, так и к методу ручной динамической загрузки скрипта.)
Это означает, что если вы будете использовать эти приемы напрямую, вы не сможете использовать свой недавно загруженный код на следующей строке после того, как вы попросили его загрузить, потому что он все еще будет загружаться.
Например: my_lovely_script.js
содержит 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
Затем вы перезагрузите страницу, нажав F5. И это работает! Смешение...
Так что с этим делать?
Ну, вы можете использовать взлом, который предлагает автор, по ссылке, которую я вам дал. Таким образом, для спешащих людей он использует событие для запуска функции обратного вызова при загрузке скрипта. Таким образом, вы можете поместить весь код с помощью удаленной библиотеки в функцию обратного вызова. Например:
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);
}
Затем вы пишете код, который хотите использовать ПОСЛЕ того, как скрипт загружается в лямбда-функцию:
var myPrettyCode = function() {
// Here, do whatever you want
};
Затем вы запускаете все это:
loadScript("my_lovely_script.js", myPrettyCode);
Обратите внимание, что скрипт может выполняться после загрузки DOM или раньше, в зависимости от браузера и от того, включена ли строка script.async = false;
, В общем, есть отличная статья о загрузке Javascript, которая обсуждает это.
Слияние / предварительная обработка исходного кода
Как упоминалось в верхней части этого ответа, многие разработчики используют в своих проектах инструменты сборки / переноса, такие как Parcel, Webpack или Babel, что позволяет им использовать предстоящий синтаксис JavaScript, обеспечивать обратную совместимость для старых браузеров, объединять файлы, минимизировать, выполнять разбиение кода и т. д.
Если кто-то ищет что-то более продвинутое, попробуйте RequireJS. Вы получите дополнительные преимущества, такие как управление зависимостями, улучшенный параллелизм и избежание дублирования (то есть получение сценария более одного раза).
Вы можете записать свои файлы JavaScript в "модули", а затем ссылаться на них как на зависимости в других скриптах. Или вы можете использовать RequireJS как простое решение "иди и получи этот скрипт".
Пример:
Определите зависимости как модули:
некоторые-dependency.js
define(['lib/dependency1', 'lib/dependency2'], function (d1, d2) {
//Your actual script goes here.
//The dependent scripts will be fetched if necessary.
return libraryObject; //For example, jQuery object
});
creation.js - это ваш "основной" файл JavaScript, который зависит от some-dependency.js
require(['some-dependency'], function(dependency) {
//Your script goes here
//some-dependency.js is fetched.
//Then your script is executed
});
Выдержка из GitHub README:
RequireJS загружает простые файлы JavaScript, а также более определенные модули. Он оптимизирован для использования в браузере, в том числе в Web Worker, но может использоваться в других средах JavaScript, таких как Rhino и Node. Он реализует API асинхронного модуля.
RequireJS использует простые теги сценариев для загрузки модулей / файлов, поэтому он должен обеспечивать легкую отладку. Его можно использовать просто для загрузки существующих файлов JavaScript, поэтому вы можете добавить его в существующий проект без необходимости переписывать файлы JavaScript.
...
На самом деле есть способ загрузить файл JavaScript не асинхронно, так что вы можете использовать функции, включенные в ваш недавно загруженный файл, сразу после загрузки, и я думаю, что он работает во всех браузерах.
Вам нужно использовать jQuery.append()
на <head>
элемент вашей страницы, то есть:
$("head").append('<script type="text/javascript" src="' + script + '"></script>');
Однако этот метод также имеет проблему: если в импортированном файле JavaScript возникает ошибка, Firebug (а также Firefox Error Console и Chrome Developer Tools также сообщат о своем месте неверно, что является большой проблемой, если вы используете Firebug для отслеживания Ошибки JavaScript много (я делаю). Firebug по какой-то причине просто не знает о недавно загруженном файле, поэтому, если в этом файле происходит ошибка, он сообщает, что она произошла в вашем основном HTML- файле, и у вас будут проблемы с поиском истинной причины ошибки.
Но если это не проблема для вас, тогда этот метод должен работать.
На самом деле я написал плагин jQuery с именем $.import_js(), который использует этот метод:
(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 type="text/javascript" src="' + script + '"></script>');
import_js_imported.push(script);
}
}
});
})(jQuery);
Поэтому все, что вам нужно сделать для импорта JavaScript, это:
$.import_js('/path_to_project/scripts/somefunctions.js');
Я также сделал простой тест для этого в Примере.
Включает в себя main.js
файл в основном HTML, а затем скрипт в main.js
использования $.import_js()
импортировать дополнительный файл с именем included.js
, который определяет эту функцию:
function hello()
{
alert("Hello world!");
}
И сразу после включения included.js
, hello()
Функция вызывается, и вы получаете предупреждение.
(Этот ответ является ответом на комментарий e-sat).
Другой способ, который, на мой взгляд, намного чище, - это сделать синхронный Ajax-запрос вместо использования <script>
тег. К тому же, как обрабатывает Node.js.
Вот пример использования jQuery:
function require(script) {
$.ajax({
url: script,
dataType: "script",
async: false, // <-- This is the key
success: function () {
// all good...
},
error: function () {
throw new Error("Could not load script " + script);
}
});
}
Затем вы можете использовать его в своем коде, как если бы вы обычно использовали include:
require("/scripts/subscript.js");
И сможете вызвать функцию из необходимого скрипта в следующей строке:
subscript.doSomethingCool();
Можно динамически генерировать тег JavaScript и добавлять его в документ HTML из другого кода JavaScript. Это загрузит целевой файл JavaScript.
function includeJs(jsFilePath) {
var js = document.createElement("script");
js.type = "text/javascript";
js.src = jsFilePath;
document.body.appendChild(js);
}
includeJs("/path/to/some/file.js");
Для вас есть хорошие новости. Очень скоро вы сможете легко загрузить код JavaScript. Это станет стандартным способом импорта модулей кода JavaScript и станет частью самого ядра JavaScript.
Вы просто должны написать import cond from 'cond.js';
загрузить макрос с именем cond
из файла cond.js
,
Таким образом, вам не нужно полагаться на какую-либо инфраструктуру JavaScript и не нужно явно делать вызовы Ajax.
Ссылаться на:
Утверждение import
находится в ECMAScript 6.
Синтаксис
import name from "module-name";
import { member } from "module-name";
import { member as alias } from "module-name";
import { member1 , member2 } from "module-name";
import { member1 , member2 as alias2 , [...] } from "module-name";
import name , { member [ , [...] ] } from "module-name";
import "module-name" as name;
Может быть, вы можете использовать эту функцию, которую я нашел на этой странице Как мне включить файл JavaScript в файл JavaScript?:
function include(filename)
{
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.src = filename;
script.type = 'text/javascript';
head.appendChild(script)
}
Вот синхронная версия без jQuery:
function myRequire( url ) {
var ajax = new XMLHttpRequest();
ajax.open( 'GET', url, false ); // <-- the 'false' makes it synchronous
ajax.onreadystatechange = function () {
var script = ajax.response || ajax.responseText;
if (ajax.readyState === 4) {
switch( ajax.status) {
case 200:
eval.apply( window, [script] );
console.log("script loaded: ", url);
break;
default:
console.log("ERROR: script not loaded: ", url);
}
}
};
ajax.send(null);
}
Обратите внимание, что для получения этого рабочего междомена серверу необходимо установить allow-origin
Заголовок в своем ответе.
Я только что написал этот код JavaScript (используя Prototype для манипулирования DOM):
var require = (function() {
var _required = {};
return (function(url, callback) {
if (typeof url == 'object') {
// We've (hopefully) got an array: time to chain!
if (url.length > 1) {
// Load the nth file as soon as everything up to the
// n-1th one is done.
require(url.slice(0, url.length - 1), function() {
require(url[url.length - 1], callback);
});
} else if (url.length == 1) {
require(url[0], callback);
}
return;
}
if (typeof _required[url] == 'undefined') {
// Haven't loaded this URL yet; gogogo!
_required[url] = [];
var script = new Element('script', {
src: url,
type: 'text/javascript'
});
script.observe('load', function() {
console.log("script " + url + " loaded.");
_required[url].each(function(cb) {
cb.call(); // TODO: does this execute in the right context?
});
_required[url] = true;
});
$$('head')[0].insert(script);
} else if (typeof _required[url] == 'boolean') {
// We already loaded the thing, so go ahead.
if (callback) {
callback.call();
}
return;
}
if (callback) {
_required[url].push(callback);
}
});
})();
Использование:
<script src="prototype.js"></script>
<script src="require.js"></script>
<script>
require(['foo.js','bar.js'], function () {
/* Use foo.js and bar.js here */
});
</script>
Если вы хотите в чистом JavaScript, вы можете использовать document.write
,
document.write('<script src="myscript.js" type="text/javascript"></script>');
Если вы используете библиотеку jQuery, вы можете использовать $.getScript
метод.
$.getScript("another_script.js");
Вот обобщенная версия того, как Facebook делает это для их вездесущей кнопки "Нравится":
<script>
var firstScript = document.getElementsByTagName('script')[0],
js = document.createElement('script');
js.src = 'https://cdnjs.cloudflare.com/ajax/libs/Snowstorm/20131208/snowstorm-min.js';
js.onload = function () {
// do stuff with your dynamically loaded script
snowStorm.snowColor = '#99ccff';
};
firstScript.parentNode.insertBefore(js, firstScript);
</script>
Если это работает для Facebook, это будет работать для вас.
Причина, почему мы ищем первое script
элемент вместо head
или же body
потому что некоторые браузеры не создают один, если его не хватает, но мы гарантированно script
Элемент - этот. Узнайте больше на http://www.jspatterns.com/the-ridiculous-case-of-adding-a-script-element/.
Вы также можете собрать свои скрипты, используя PHP:
файл main.js.php
:
<?php
header('Content-type:text/javascript; charset=utf-8');
include_once("foo.js.php");
include_once("bar.js.php");
?>
// Main JavaScript code goes here
Большинство представленных здесь решений предполагают динамическую загрузку. Вместо этого я искал компилятор, который собирает все зависимые файлы в один выходной файл. Так же, как препроцессоры Less/ Sass работают с CSS @import
в властвуй. Так как я не нашел ничего приличного в этом роде, я написал простой инструмент для решения проблемы.
Итак, вот компилятор, https://github.com/dsheiko/jsic, который заменяет $import("file-path")
с запрошенным содержимым файла надежно. Вот соответствующий плагин Grunt: https://github.com/dsheiko/grunt-jsic.
В основной ветви jQuery они просто объединяют атомарные исходные файлы в один, начиная с intro.js
и заканчивая outtro.js
, Это меня не устраивает, так как не обеспечивает гибкости при разработке исходного кода. Проверьте, как это работает с JSIC:
SRC /main.js
var foo = $import("./Form/Input/Tel");
ЦСИ / Форма / вход / Tel.js
function() {
return {
prop: "",
method: function(){}
}
}
Теперь мы можем запустить компилятор:
node jsic.js src/main.js build/mail.js
И получите объединенный файл
строить /main.js
var foo = function() {
return {
prop: "",
method: function(){}
}
};
Если ваше намерение загрузить файл JavaScript использует функции из импортированного / включенного файла, вы также можете определить глобальный объект и установить функции в качестве элементов объекта. Например:
global.js
A = {};
file1.js
A.func1 = function() {
console.log("func1");
}
file2.js
A.func2 = function() {
console.log("func2");
}
main.js
A.func1();
A.func2();
Вам просто нужно быть осторожным, когда вы включаете скрипты в HTML-файл. Порядок должен быть таким, как показано ниже:
<head>
<script type="text/javascript" src="global.js"></script>
<script type="text/javascript" src="file1.js"></script>
<script type="text/javascript" src="file2.js"></script>
<script type="text/javascript" src="main.js"></script>
</head>
Или вместо включения во время выполнения используйте сценарий для объединения перед загрузкой.
Я использую Звездочки (я не знаю, есть ли другие). Вы строите свой код JavaScript в отдельных файлах и включаете комментарии, которые обрабатываются механизмом Sprockets, как и включенные. Для разработки вы можете включить файлы последовательно, а затем для производства, чтобы объединить их...
Смотрите также:
Это должно сделать:
xhr = new XMLHttpRequest();
xhr.open("GET", "/soap/ajax/11.0/connection.js", false);
xhr.send();
eval(xhr.responseText);
У меня была простая проблема, но я был озадачен ответами на этот вопрос.
Мне пришлось использовать переменную (myVar1), определенную в одном файле JavaScript (myvariables.js) в другом файле JavaScript (main.js).
Для этого я сделал, как показано ниже:
Загрузил код JavaScript в HTML-файле в правильном порядке, сначала myvariables.js, затем main.js:
<html>
<body onload="bodyReady();" >
<script src="myvariables.js" > </script>
<script src="main.js" > </script>
<!-- Some other code -->
</body>
</html>
Файл: myvariables.js
var myVar1 = "I am variable from myvariables.js";
Файл: main.js
// ...
function bodyReady() {
// ...
alert (myVar1); // This shows "I am variable from myvariables.js", which I needed
// ...
}
// ...
Как вы видели, я использовал переменную в одном файле JavaScript в другом файле JavaScript, но мне не нужно было включать одну в другую. Мне просто нужно было убедиться, что первый файл JavaScript загружен до второго файла JavaScript, а переменные первого файла JavaScript доступны во втором файле JavaScript автоматически.
Это спасло мой день. Надеюсь, это поможет.
ES6: ДА использовать type="module" в теге script ( поддержка)
<script type="module" src="script.js"></script>
И в script.js
файл включает в себя еще один файл, как это:
import { hello } from './module.js';
...
// alert(hello());
В 'module.js' вы должны экспортировать функцию / класс, который вы будете импортировать
export function hello() {
return "Hello World";
}
Рабочий пример здесь.
@import
Синтаксис для достижения CSS-подобного импорта JavaScript возможен с помощью таких инструментов, как Mixture, через специальные .mix
тип файла (см. здесь). Я предполагаю, что приложение просто использует один из вышеупомянутых методов, хотя я не знаю.
Из документации смеси на .mix
файлы:
Файлы микширования - это просто файлы.js или.css с.mix. в имени файла. Файл микширования просто расширяет функциональность обычного файла стиля или скрипта и позволяет импортировать и комбинировать.
Вот пример .mix
файл, который объединяет несколько .js
файлы в один:
// 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";
Смесь выводит это как scripts-global.js
а также как минимизированная версия (scripts-global.min.js
).
Примечание: я никоим образом не связан с Mixture, за исключением того, что использую его как интерфейсный инструмент разработки. Я столкнулся с этим вопросом, увидев .mix
Файл JavaScript в действии (в одном из шаблонов Mixture) и немного смущен этим ("Вы можете сделать это?" - подумал я про себя). Затем я понял, что это тип файла для приложения (несколько разочаровывающий, согласился). Тем не менее, полагал, что знания могут быть полезны для других.
ОБНОВЛЕНИЕ: Mixture теперь бесплатна (не в сети).
ОБНОВЛЕНИЕ: Смесь теперь прекращена. Старые релизы смеси все еще доступны
На современном языке это было бы
function loadJs( url ){
return new Promise( resolve => {
const script = document.createElement( "script" );
script.src = url;
script.onload = resolve;
document.head.appendChild( script );
});
}
Хотя эти ответы и хороши, существует простое "решение", существующее с момента загрузки скрипта, и оно охватит 99,999% случаев использования большинства людей. Просто включите сценарий, который вам нужен, прежде чем сценарий, который требует этого. Для большинства проектов не требуется много времени, чтобы определить, какие сценарии нужны и в каком порядке.
<!DOCTYPE HTML>
<html>
<head>
<script src="script1.js"></script>
<script src="script2.js"></script>
</head>
<body></body>
</html>
Если script2 требует script1, это действительно самый простой способ сделать что-то подобное. Я очень удивлен, что никто не поднял этот вопрос, так как это самый очевидный и самый простой ответ, который применим почти в каждом отдельном случае.
Если вы используете Web Workers и хотите включить дополнительные сценарии в область работника, другие ответы о добавлении сценариев в head
тег и т. д. не будут работать для вас.
К счастью, веб-работники имеют свои собственные importScripts
функция, которая является глобальной функцией в области веб-работника, родной для самого браузера, поскольку она является частью спецификации.
Кроме того, в качестве второго наиболее высоко оцененного ответа на ваш вопрос, RequireJS может также обрабатывать включение сценариев внутри Web Worker (вероятно, вызывающий importScripts
сам, но с несколькими другими полезными функциями).
var js = document.createElement("script");
js.type = "text/javascript";
js.src = jsFilePath;
document.body.appendChild(js);
Мой обычный метод:
var require = function (src, cb) {
cb = cb || function () {};
var newScriptTag = document.createElement('script'),
firstScriptTag = document.getElementsByTagName('script')[0];
newScriptTag.src = src;
newScriptTag.async = true;
newScriptTag.onload = newScriptTag.onreadystatechange = function () {
(!this.readyState || this.readyState === 'loaded' || this.readyState === 'complete') && (cb());
};
firstScriptTag.parentNode.insertBefore(newScriptTag, firstScriptTag);
}
Это прекрасно работает и не использует перезагрузки страницы для меня. Я попробовал метод AJAX (один из других ответов), но, похоже, он мне не подходит.
Вот объяснение того, как работает код для любопытных: по сути, он создает новый тег сценария (после первого) URL-адреса. Он устанавливает его в асинхронный режим, чтобы не блокировать остальную часть кода, а вызывает обратный вызов, когда readyState (состояние загружаемого содержимого) меняется на "загружен".
Этот скрипт добавит файл JavaScript в начало любого другого <script>
тег:
(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);
})();
Я написал простой модуль, который автоматизирует работу по импорту / включению скриптов модуля в JavaScript. Для подробного объяснения кода, обратитесь к сообщению в блоге JavaScript require / import / include modules.
// ----- USAGE -----
require('ivar.util.string');
require('ivar.net.*');
require('ivar/util/array.js');
require('http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js');
ready(function(){
//Do something when required scripts are loaded
});
//--------------------
var _rmod = _rmod || {}; //Require module namespace
_rmod.LOADED = false;
_rmod.on_ready_fn_stack = [];
_rmod.libpath = '';
_rmod.imported = {};
_rmod.loading = {
scripts: {},
length: 0
};
_rmod.findScriptPath = function(script_name) {
var script_elems = document.getElementsByTagName('script');
for (var i = 0; i < script_elems.length; i++) {
if (script_elems[i].src.endsWith(script_name)) {
var href = window.location.href;
href = href.substring(0, href.lastIndexOf('/'));
var url = script_elems[i].src.substring(0, script_elems[i].length - script_name.length);
return url.substring(href.length+1, url.length);
}
}
return '';
};
_rmod.libpath = _rmod.findScriptPath('script.js'); //Path of your main script used to mark
//the root directory of your library, any library.
_rmod.injectScript = function(script_name, uri, callback, prepare) {
if(!prepare)
prepare(script_name, uri);
var script_elem = document.createElement('script');
script_elem.type = 'text/javascript';
script_elem.title = script_name;
script_elem.src = uri;
script_elem.async = true;
script_elem.defer = false;
if(!callback)
script_elem.onload = function() {
callback(script_name, uri);
};
document.getElementsByTagName('head')[0].appendChild(script_elem);
};
_rmod.requirePrepare = function(script_name, uri) {
_rmod.loading.scripts[script_name] = uri;
_rmod.loading.length++;
};
_rmod.requireCallback = function(script_name, uri) {
_rmod.loading.length--;
delete _rmod.loading.scripts[script_name];
_rmod.imported[script_name] = uri;
if(_rmod.loading.length == 0)
_rmod.onReady();
};
_rmod.onReady = function() {
if (!_rmod.LOADED) {
for (var i = 0; i < _rmod.on_ready_fn_stack.length; i++){
_rmod.on_ready_fn_stack[i]();
});
_rmod.LOADED = true;
}
};
_.rmod = namespaceToUri = function(script_name, url) {
var np = script_name.split('.');
if (np.getLast() === '*') {
np.pop();
np.push('_all');
}
if(!url)
url = '';
script_name = np.join('.');
return url + np.join('/')+'.js';
};
//You can rename based on your liking. I chose require, but it
//can be called include or anything else that is easy for you
//to remember or write, except "import", because it is reserved
//for future use.
var require = function(script_name) {
var uri = '';
if (script_name.indexOf('/') > -1) {
uri = script_name;
var lastSlash = uri.lastIndexOf('/');
script_name = uri.substring(lastSlash+1, uri.length);
}
else {
uri = _rmod.namespaceToUri(script_name, ivar._private.libpath);
}
if (!_rmod.loading.scripts.hasOwnProperty(script_name)
&& !_rmod.imported.hasOwnProperty(script_name)) {
_rmod.injectScript(script_name, uri,
_rmod.requireCallback,
_rmod.requirePrepare);
}
};
var ready = function(fn) {
_rmod.on_ready_fn_stack.push(fn);
};
Делайте это красиво, коротко, просто и легко!:]
// 3rd 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]);
}
}
Этот код является просто кратким функциональным примером, который может потребовать дополнительных функциональных возможностей для полной поддержки на любой (или данной) платформе.
Существует несколько способов реализации модулей в Javascript. Вот два наиболее популярных из них:
ES6 Модули
Браузеры пока не поддерживают эту систему модуляции, поэтому для использования этого синтаксиса вы должны использовать такой пакет, как webpack. В любом случае лучше использовать упаковщик, потому что он может объединить все ваши разные файлы в один (или пару связанных) файлов. Это позволит быстрее передавать файлы с сервера на клиент, поскольку с каждым HTTP-запросом связаны некоторые накладные расходы. Таким образом, уменьшая общий HTTP-запрос, мы улучшаем производительность. Вот пример модулей ES6:
// main.js file
export function add (a, b) {
return a + b;
}
export default function multiply (a, b) {
return a * b;
}
// test.js file
import {add}, multiply from './main'; // for named exports between curly braces {export1, export2}
// for default exports without {}
console.log(multiply(2, 2)); // logs 4
console.log(add(1, 2)); // logs 3
CommonJS (используется в NodeJS)
Эта система модуляции используется в NodeJS. Вы в основном добавляете свои экспорты к объекту, который называется module.exports
, Затем вы можете получить доступ к этому объекту через require('modulePath')
, Здесь важно понимать, что эти модули кэшируются, так что если вы require()
определенный модуль дважды вернет уже созданный модуль.
// main.js file
function add (a, b) {
return a + b;
}
module.exports = add; // here we add our add function to the exports object
// test.js file
const add = require('./main');
console.log(add(1,2)); // logs 3
Да, есть...
Продолжайте читать, в ES6, мы можем export
а также import
часть или весь файл javascript в другой...
Но подождите, ES6 поддерживается не во всех браузерах, так что вам нужно его перенести с помощью babel.js
например...
Итак, вы создаете класс, как показано ниже:
class Person {
constructor(name) {
this.name = name;
}
build() {
return new Person(this);
}
}
module.exports = Person;
в другом файле JavaScript выполните импорт следующим образом:
import { Person } from 'Person';
Вы также можете потребовать файл как:
const Person = require('./Person');
Если вы используете более старую версию JavaScript, вы можете использовать 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".
});
Если вы хотите придерживаться более старых версий таких вещей, как jQuery, вы также можете использовать что-то вроде getScript:
jQuery.getScript('./another-script.js', function() {
// Call back after another-script loaded
});
И последнее, но не менее важное: не забывайте, что вы можете сделать традиционный способ объединения сценариев, используя <script>
тег...
<script src="./first-script.js"></script>
<script src="./second-script.js"></script>
<script src="./third-script.js"></script>
Есть также атрибут async и defer, о котором я должен упомянуть здесь...
Примечание. Существует несколько способов выполнения внешнего скрипта:
- Если присутствует асинхронность: сценарий выполняется асинхронно с остальной частью страницы (сценарий будет выполняться, пока страница продолжает анализ)
- Если async отсутствует, а defer присутствует: скрипт выполняется после завершения анализа страницы
- Если нет ни асинхронного, ни отсроченного: скрипт извлекается и выполняется немедленно, прежде чем браузер продолжит синтаксический анализ страницы.