Как включить файл JavaScript в другой файл JavaScript?

5195

Есть ли в JavaScript что-то похожее на @importCSS, что позволяет включать файл JavaScript в другой файл JavaScript?

Алек Смарт
источник
52
stackoverflow.com/questions/21294/…
Даниэль А. Уайт
82
@ Даниил, я не хочу использовать вызов AJAX.
Алек Смарт
13
Почему бы не объявить импортированный файл раньше, чем тот, который требует этого, просто используя упорядоченные scriptтеги?
Falsarella
6
@Claudiu Это не поможет импортировать что-либо, но это также должно работать. Если у вас есть JS-файл, который зависит от другого JS-файла, просто сначала объявите теги сценария для файлов зависимостей, чтобы позднее у них уже были загружены зависимости. Если у вас возникла ситуация, когда такой подход невозможен, ответы здесь должны быть полезны.
falsarella
1
В чем практическое преимущество этого? в любом случае база кода, зависящая от файла JavaScript, не будет загружаться и работать в любом случае, если она не загружена!
Ciasto piekarz

Ответы:

4473

В старых версиях JavaScript не было импорта, включения или требования, поэтому было разработано много разных подходов к этой проблеме.

Но с 2015 года (ES6) в JavaScript появился стандарт модулей ES6 для импорта модулей в Node.js, который также поддерживается большинством современных браузеров .

Для совместимости со старыми браузерами, создайте инструменты, такие как Webpack и Rollup, и / или инструменты транспиляции, такие как Babel. .

ES6 Модули

Модули ECMAScript (ES6) поддерживаются в Node.js начиная с версии 8.5 с --experimental-modulesфлагом и, по крайней мере, с версии Node.js версии 13.8.0 без флага. Чтобы включить "ESM" (по сравнению с предыдущей системой модулей CommonJS в стиле Node.js ["CJS"]), вы либо используете "type": "module"в package.jsonфайле, либо задаете расширение файла .mjs. (Аналогично, модули, написанные с помощью предыдущего модуля CJS Node.js, могут быть названы, .cjsесли по умолчанию используется ESM.)

Использование package.json:

{
    "type": "module"
}

Тогда module.js:

export function hello() {
  return "Hello";
}

Тогда main.js:

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

Используя .mjs, вы получите module.mjs:

export function hello() {
  return "Hello";
}

Тогда main.mjs:

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

Модули ECMAScript в браузерах

Браузеры поддерживают загрузку модулей ECMAScript напрямую (не требуются такие инструменты, как Webpack), начиная с Safari 10.1, Chrome 61, Firefox 60 и Edge 16. Проверьте текущую поддержку в caniuse . Нет необходимости использовать .mjsрасширение Node.js ; браузеры полностью игнорируют расширения файлов в модулях / скриптах.

<script type="module">
  import { hello } from './hello.mjs'; // Or it could be simply `hello.js`
  hello('world');
</script>
// hello.mjs -- or it could be simply `hello.js`
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 требует

Более старый стиль модуля CJS, все еще широко используемый в Node.js, это 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"   

Существуют и другие способы включения 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, обеспечивать обратную совместимость для старых браузеров, объединять файлы, минимизировать, выполнять разбиение кода и т. д.

е-удовлетворяться
источник
131
Нет, но кто-то, кто использует что-то такое продвинутое, как Rhino, иначе не задаст этот вопрос.
e-удовлетворительно
193
Проще говоря, есть третий способ: в некоторых решениях, когда вы управляете обоими файлами javascript, вы можете просто создать 1 гигантский файл javascript, который объединяет содержимое обоих файлов.
жаба
20
Не должен "document.createElement (" my_lovely_script.js ");" в примере быть "document.createElement (" script ")"?
Рассел Сильва
14
Как eval открывает двери для хаков, если вы исполняете код?
Винс Пануччо
6
Ваш ответ требует некоторой модификации для IE ( onreadystatechangeсобытие и readyStateсвойство). Кроме того, динамическая загрузка сценариев не выигрывает у сканеров с предварительной загрузкой. Рекомендовать эту статью HTML5Rocks: html5rocks.com/en/tutorials/speed/script-loading
ruhong
571

Если кто-то ищет что-то более продвинутое, попробуйте 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.

...

Джон Стриклер
источник
1
@aaaidan: причина MattDmo плюс это полагается на внешнюю библиотеку, которая в свою очередь полагается на принятый ответ.
Дэвид Малдер
1
Для преодоления require.js самым последним был бы угловой js, который более стабилен и прост в использовании наряду с другими обязательными и богатыми функциями HTML.
Зеешан
5
-1: эти абстракции - "some_dependency" - действительно плохие, с индексами, добавляющими путаницу. Я изо всех сил пытаюсь понять, как выглядит пример рабочего кода. Если автор предоставит рабочий пример, почти любой сможет адаптировать и обобщить его для своих нужд.
Тегири Ненаши
1
плохо работает с MVC и связыванием сценариев с автоматической минификацией
Triynko
1
'добавить .. без необходимости переписывать ваши файлы JavaScript'; круто, но как именно? Cur. В ответ предлагается добавить такой «require» (не «requirejs»?) в основной скрипт + такой «define» для каждого зависимого файла, да? Но это переписать, так что не переписать? -реста кода, поскольку RequireJS позволяет файлу делать глобальные определения как обычно? -Является ли? Я только что попробовал, + (забыли?) <Script src = " requirejs.org/docs/release/2.2.0/comments/require.js "> </ script>, затем 'requirejs ([' GoogleDrive.com/host /..',..],function(a,b) {mycode}) ': Firebug говорит каждому загруженному зависимому, НО свои определения, не определенные в mycode & after.
Судьба Архитектор
196

На самом деле есть способ загрузить файл 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).

Kipras
источник
Я пытаюсь этот метод, но у меня не работает, элемент просто не появляется в теге head.
сайты
16
@juanpastas - используйте jQuery.getScript, чтобы вам не пришлось беспокоиться о написании плагина ...
MattDMo
6
Хм, в соответствии с этой статьей , добавление scriptэлемента в headзаставит его работать асинхронно, если для asyncнего специально не установлено значение false.
Flimm
1
Разве в переменной скрипта не должны быть закодированы HTML-объекты? Если ссылка содержит ", код сломается
RedClover
1
@Flimm дорогой сэр, я и моя команда благодарны за ваш комментарий, и я лично должен вам
Алекс
155

Другой способ, который, на мой взгляд, намного чище, - это сделать синхронный 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(); 
Ariel
источник
1
Хорошее решение, голова, к сожалению, асинхронная, решение ajax работает.
Маттео Конта
17
Как уже упоминал кто-то другой, requirejs.org делает это, а также имеет прекомпилятор, который объединяет js-файлы, чтобы они быстрее загружались. Вы можете проверить это.
Ариэль
2
Обнаружил, что я мог бы сделать отладку, добавив эту директиву внизу файла для Chrome: // @ sourceURL = view_index.js
Тодд Вэнс
11
К сожалению, async: false теперь не поддерживается в jQuery. Может сломаться в будущем, поэтому я бы избегал.
13
3
@katsh Мы здесь не используем объекты jqXHR. Похоже, ваша цитата не подкрепляет ваш предыдущий комментарий о том, что он async: falseпредположительно устарел. Не то! Как говорится в вашей цитате, только материал, связанный с jqXHR.
Ноль3
101

Есть хорошие новости для вас. Очень скоро вы сможете легко загрузить код JavaScript. Это станет стандартным способом импорта модулей кода JavaScript и станет частью самого ядра JavaScript.

Вам просто нужно написать, import cond from 'cond.js';чтобы загрузить макрос condиз файла cond.js.

Таким образом, вам не нужно полагаться на какую-либо инфраструктуру JavaScript и не делать явных вызовов Ajax .

Ссылаться на:

Имдад
источник
12
Требовать / импортировать в jsfile было слишком долго в будущем. (ИМО).
rwheadon
6
@ rwheadon да, кажется ужасным, что это не часть языка! То, как люди делают что-либо, - вне меня! Я новичок в этом, и это кажется худшим (из многих) кусочков безумия
JonnyRaa
@ jonny-leeds Даже без встроенной загрузки модулей JavaScript в браузере достаточно гибок, чтобы мы могли реализовать такую ​​библиотеку, как RequireJS, для управления нашими модулями.
Кин
8
середина 2015 г. - по-прежнему не реализована ни в одном браузере, developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
сценарий
Да, ты прав. теперь я начинаю чувствовать себя плохо из-за этого :(. Однажды реализованный во всех браузерах, это будет отличная функция, встроенная в javascript.
Imdad
97

Можно динамически генерировать тег 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");
Светлана Максимчук
источник
8
@ e-Satin - На самом деле это преимущество, сценарий синхронизации будет блокировать. Лошади на курсы, но 9 раз из 10 вам нужен неблокирующий вариант.
Annakata
@Svitlana - элементы скрипта, созданные таким образом, являются асинхронными. В настоящее время это можно рассматривать как использование лазейки, так что это не может быть доказательством на будущее, я не видел ничего ни в одном стандарте, который бы это разъяснил.
Annakata
На самом деле, я забираю это назад, я заметил, что вы добавляете тело, а не голову.
Annakata
@annakata: Какая разница? Кстати, Yahoo предлагает добавить теги скрипта в конец тела, так что при динамическом добавлении ничего не должно быть с этим не так.
Светлана Максимчук
7
@ e-удовлетворительно асинхронный - это хорошо, потому что он не замораживает вашу страницу. Используйте обратный вызов, чтобы получать уведомления, когда это будет сделаноjs.onload = callback;
Vitim.us
74

Заявление 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;
draupnie
источник
... но пока не поддерживается ни одним браузером, согласно таблице совместимости на странице, на которую вы ссылаетесь.
Zero3
6
Теперь вы можете написать код ES6 и скомпилировать его с Babel.js ( babeljs.io ) в любую предпочитаемую вами текущую модульную систему (CommonJS / AMD / UMD): babeljs.io/docs/usage/modules
Jeremy Harris
@ Zero3 Судя по всему, новый IE (Edge) - единственный
Джулиан Авар
в 2019 году IE до сих пор не поддерживает это в любой форме. Почему Microsoft должна быть против юзабилити?
GreySage
61

Может быть, вы можете использовать эту функцию, которую я нашел на этой странице Как мне включить файл 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)
}
Арно Гудер де Борегар
источник
5
Должно быть полезно добавитьscript.onload = callback;
Vitim.us
@SvitlanaMaksymchuk так что, если я не буду использовать var, переменная будет глобальной?
Франциско Корралес Моралес
@FranciscoCorrales да.
Кристофер Чич
Это заканчивается в глобальном с или без вар :)
Ведран Маричевич.
54

Вот синхронная версия без 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заголовок в своем ответе.

heinob
источник
Отличная функция! Загружает JavaScript прежде, чем любой дополнительный JS будет написан после тела. Очень важно при загрузке нескольких скриптов.
TFont
3
@heinob: Что я могу сделать, чтобы заставить его работать для междоменных? (загрузка скрипта из http://web.archive.org/web/20140905044059/http://www.howtocreate.co.uk/operaStuff/userjs/aagmfunctions.js)
user2284570
@ user2284570: Если вы являетесь владельцем чужого домена: установите заголовок `allow-origin 'в ответе сервера. Если вы не владелец: ничего. Сожалею! Это перекрестная политика происхождения.
Хейноб
2
@ user2284570: Я так понимаю, ваш комментарий о том, что вы не являетесь владельцем домена, из которого вы хотите загрузить скрипт. В этом случае вы можете загрузить скрипт только через вставленный <script>тег, а не через XMLHttpRequest.
Хейноб
2
Для тех, кто планирует использовать это в Firefox (скажем, для сценариев imacros), добавьте эту строку в начало файла:const XMLHttpRequest = Components.Constructor("@mozilla.org/xmlextras/xmlhttprequest;1");
Kwestion
49

Я только что написал этот код 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>

Суть: http://gist.github.com/284442 .

nornagon
источник
7
Джербурк написал это как RequireJS. Github: requirejs.org/docs/requirements.html
Майк Карон,
Разве это не помещает загруженный скрипт за пределы области, где вызывается require ()? Похоже, eval () - единственный способ сделать это в рамках видимости. Или есть другой способ?
trusktr
44

Вот обобщенная версия того, как 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/ .

Дан Дакалеску
источник
3
Чертовски приятно! Некоторые из методов здесь также работают, но при динамической настройке это работает лучше всего.
tfont
я расширил ваш сценарий, чтобы исключить дублирование
Камиль Домбровски
39

Если вы хотите в чистом JavaScript, вы можете использовать document.write.

document.write('<script src="myscript.js" type="text/javascript"></script>');

Если вы используете библиотеку jQuery, вы можете использовать $.getScriptметод.

$.getScript("another_script.js");
Вену Иммади
источник
8
не document.write удалить все остальное?
Эйса Адиль
30

Вы также можете собрать свои скрипты, используя 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
Calmarius
источник
16
Похоже, смысл в том, чтобы сохранить все это в javascript на переднем крае
Ариэль,
1
Спасибо за напоминание об этом. Вы также можете иметь PHP-теги <script> в своем HTML-заголовке, чтобы загружать нужные вам js-файлы (и только те).
Рольф
29

Большинство представленных здесь решений предполагают динамическую загрузку. Вместо этого я искал компилятор, который собирает все зависимые файлы в один выходной файл. Так же, как препроцессоры 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(){}
    }
};
Дмитрий Шейко
источник
2
Начиная с этого поста, я придумал гораздо лучшее решение - компилятор модулей CommonJS - github.com/dsheiko/cjsc. Таким образом, вы можете просто писать модули CommonJs или NodeJs и получать доступ друг к другу, сохраняя их в изолированных областях. Преимущества: нет необходимости в нескольких HTTP-запросах, которые влияют на производительность. Вам не нужно вручную оборачивать свой код модуля - это ответственность компилятора (поэтому улучшается читаемость исходного кода). Вам не нужны внешние библиотеки. Он совместим с UMD- и модули NodeJs (например, вы можете обращаться к jQuery, Backbone как к модулям, не касаясь их кода)
Дмитрий Шейко,
26

Если ваше намерение загрузить файл 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>
Адем Ильхан
источник
22

Это должно сделать:

xhr = new XMLHttpRequest();
xhr.open("GET", "/soap/ajax/11.0/connection.js", false);
xhr.send();
eval(xhr.responseText);
tggagne
источник
5
evalто , что случилось с ним. По словам Крокфорда , « evalэто зло. Эта evalфункция - наиболее часто используемая функция JavaScript. Избегайте ее. evalИмеет псевдонимы. Не используйте Functionконструктор. Не передавайте строки в setTimeoutили setInterval». Если вы еще не читали его «JavaScript: Хорошие части», то выходите и делайте это прямо сейчас. Вы будете не пожалеете об этом.
MattDMo
13
@MattDMo «Кто-то сказал, что это плохо», на самом деле не аргумент.
Кейси
4
@emodendroket Я так понимаю, ты не знаешь, кто такой Дуглас Крокфорд .
MattDMo
13
@MattDMo Я полностью осознаю, кто он, но он человек, а не бог.
Кейси
2
@tggagne: Что я могу сделать, чтобы это работало для междоменных доменов? (загрузка скрипта из http://web.archive.org/web/20140905044059/http://www.howtocreate.co.uk/operaStuff/userjs/aagmfunctions.js)
user2284570
21

Или вместо включения во время выполнения используйте сценарий для объединения перед загрузкой.

Я использую звездочки (я не знаю, есть ли другие). Вы строите свой код JavaScript в отдельных файлах и включаете комментарии, которые обрабатываются механизмом Sprockets, как и включенные. Для разработки вы можете включить файлы последовательно, а затем для производства, чтобы объединить их ...

Смотрите также:

JMawer
источник
Browserify гораздо популярнее, чем Sprockets.
Дан Даскалеску
18

У меня была простая проблема, но я был озадачен ответами на этот вопрос.

Мне пришлось использовать переменную (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 автоматически.

Это спасло мой день. Надеюсь, это поможет.

Манохар Редди Поредди
источник
Проблема с этим ответом состоит в том, что это не что-то подобное import. Вам нужен файл HTML, чтобы получить материал из одного файла JS в другой.
Cannicide
Очень верно. Это то, что некоторые другие ответы имеют в качестве решения. Однако у меня было два файла JS, один должен использовать другие переменные JS. Нет node.js, next.js, express.js и т. Д., Поэтому импорт ИЛИ require не будет работать, просто были простые .js файлы.
Манохар Редди Поредди
Понятно, однако, что на самом деле вопрос заключается в том, чтобы импортировать файл javascript в другой файл, а не просто обращаться к его переменным с помощью файла HTML. Например, предположим, что вы создаете функциональность для кнопки и используете три разных js-файла, один для обработки щелчков, один для обработки при наведении, один для обратных вызовов для каждого из двух других. Было бы полезно импортировать два других js в сам третий js и иметь только один <script>тег. Это может помочь с организацией. Этот ответ просто не тот, о котором спрашивал вопрос, и не идеален в этом контексте.
Cannicide
Когда я искал решение для своей проблемы, я искал правильный путь, однако Google считает, что это правильная страница, поэтому я попал сюда. Вот почему я написал свой ответ здесь. Похоже, я сделал правильно, из-за 15 голосов выше. Чтобы не тратить время других людей, я четко определил, в чем заключается мой сценарий - поставил HTML-код первым - что выглядит как помогло, поскольку вы ответили и сказали, что html - это не ваш сценарий. Надеюсь, что разъяснил.
Манохар Редди Поредди
Да, действительно, похоже, что некоторые люди искали немного другую проблему, для которой это решение, и нашли это. Хотя это не обязательно ответ на этот вопрос, это, безусловно, ответ на другой, похожий вопрос. Таким образом, это нормально иметь этот ответ здесь, поскольку он помогает тем, кто искал этот ответ. Спасибо за этот ответ, который прояснил это.
Cannicide
16

Если вы используете Web Workers и хотите включить дополнительные сценарии в область действия работника, другие ответы о добавлении сценариев вhead тег и т. Д. Не будут работать для вас.

К счастью, у Web Workers есть своя собственная importScriptsфункция, которая является глобальной функцией в области Web Worker, встроенной в сам браузер, поскольку является частью спецификации. .

Кроме того, в качестве второго наиболее высоко оцененного ответа на ваш вопрос , RequireJS может также обрабатывать включение сценариев внутри Web Worker (вероятно, вызывающего importScriptsсебя, но с несколькими другими полезными функциями).

Turnerj
источник
16

На современном языке с проверкой, если скрипт уже загружен, это будет:

function loadJs(url){
  return new Promise( (resolve, reject) => {
    if (document.querySelector(`head > script[src="${src}"]`) !== null) return resolve()
    const script = document.createElement("script")
    script.src = url
    script.onload = resolve
    script.onerror = reject
    document.head.appendChild(script)
  });
}

Использование (async / await):

try { await loadJs("https://.../script.js") } 
catch(error) {console.log(error)}

или

await loadJs("https://.../script.js").catch(err => {})

Использование (обещание):

loadJs("https://.../script.js").then(res => {}).catch(err => {})
Дмитрий Шейко
источник
Ницца. Хорошее решение
Нафтали, он же Нил,
Краткий и требует только ES5, и элегантно избегает формально перезвонить. Спасибо Дмитрий!
Эврика
Ух, работает в браузере без сервера. pi.js = просто var pi = 3.14. вызовите функцию loadJS () черезloadJs("pi.js").then(function(){ console.log(pi); });
zipzit
14

@importСинтаксис для достижения CSS-подобный JavaScript импортирования можно с помощью такого инструмента, как смеси через их особый .mixтип файла (см здесь ). Я предполагаю, что приложение просто использует один из вышеупомянутых методов, хотя я не знаю.

Из документации Mixture по .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";

Mixture выводит это как, scripts-global.jsа также как уменьшенную версию ( scripts-global.min.js).

Примечание: я никоим образом не связан с Mixture, кроме того, что использую его в качестве внешнего инструмента разработки. Я столкнулся с этим вопросом, увидев.mix файл JavaScript в действии (в одном из шаблонов Mixture) и будучи немного смущенным этим («Вы можете сделать это?» - подумал я про себя). Затем я понял, что это был тип файла приложения (несколько разочаровывающий, согласился). Тем не менее, полагал, что знания могут быть полезны для других.

ОБНОВЛЕНИЕ : Mixture теперь бесплатна (не в сети).

ОБНОВЛЕНИЕ : Смесь теперь прекращена. Старые релизы смеси все еще доступны

Исаак Грегсон
источник
Это было бы здорово, если бы это был модуль узла.
b01
@ b01 Звучит как вызов;) Если бы у меня было время ... может, кто-то еще?
Исаак Грегсон
13

Мой обычный метод:

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 (состояние загружаемого содержимого) меняется на «загружен».

Кристофер Дюма
источник
13

Хотя эти ответы великолепны, существует простое «решение», существующее с момента загрузки скрипта, и оно охватит 99,999% случаев использования большинства людей. Просто включите сценарий, который вам нужен, прежде чем сценарий, который требует этого. Для большинства проектов не требуется много времени, чтобы определить, какие сценарии нужны и в каком порядке.

<!DOCTYPE HTML>
<html>
    <head>
        <script src="script1.js"></script>
        <script src="script2.js"></script>
    </head>
    <body></body>
</html>

Если script2 требует script1, это действительно самый простой способ сделать что-то подобное. Я очень удивлен, что никто не поднял этот вопрос, так как это самый очевидный и самый простой ответ, который применим почти в каждом отдельном случае.

KthProg
источник
1
Я предполагаю, что для многих людей, включая меня, нам нужно динамическое имя файла.
Стюарт Макинтайр
1
@StuartMcIntyre в этом случае установите атрибут src тега script во время выполнения и дождитесь события onload (конечно, в этом случае есть лучшие решения в 2019 году).
KthProg
12

Я написал простой модуль, который автоматизирует работу по импорту / включению скриптов модуля в 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);
};
Стамат
источник
10

Этот скрипт добавит файл 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);
})();
Вики Гонсалвес
источник
10

Существует также Head.js . Это очень легко иметь дело с:

head.load("js/jquery.min.js",
          "js/jquery.someplugin.js",
          "js/jquery.someplugin.css", function() {
  alert("Everything is ok!");
});

Как видите, это проще, чем Require.js и так же удобно, как $.getScriptметод jQuery . Он также имеет некоторые расширенные функции, такие как условная загрузка, обнаружение функций и многое другое .

эль
источник
10

Есть много потенциальных ответов на этот вопрос. Мой ответ, очевидно, основан на ряде из них. Это то, чем я закончил, прочитав все ответы.

Проблема с $.getScriptлюбым другим решением, которое требует обратного вызова при завершении загрузки, заключается в том, что если у вас есть несколько файлов, которые используют его и зависят друг от друга, у вас больше не будет способа узнать, когда все сценарии были загружены (после того, как они вложены). в нескольких файлах).

Пример:

file3.js

var f3obj = "file3";

// Define other stuff

file2.js:

var f2obj = "file2";
$.getScript("file3.js", function(){

    alert(f3obj);

    // Use anything defined in file3.
});

file1.js:

$.getScript("file2.js", function(){
    alert(f3obj); //This will probably fail because file3 is only guaranteed to have loaded inside the callback in file2.
    alert(f2obj);

    // Use anything defined in the loaded script...
});

Вы правы, когда говорите, что можете указать синхронный запуск Ajax или использовать XMLHttpRequest , но в настоящее время наблюдается тенденция отклонять синхронные запросы, поэтому вы можете не получить полную поддержку браузера сейчас или в будущем.

Вы можете попытаться использовать $.whenдля проверки массив отложенных объектов, но теперь вы делаете это в каждом файле, и file2 будет считаться загруженным, как только $.whenвыполняется, а не при выполнении обратного вызова, поэтому file1 все еще продолжает выполнение до загрузки file3 , Это действительно до сих пор та же проблема.

Я решил идти назад, а не вперед. Спасибо document.writeln. Я знаю, что это табу, но при правильном использовании это работает хорошо. В итоге вы получите код, который можно легко отладить, правильно отобразить в DOM и убедиться, что зависимости загружены правильно.

Конечно, вы можете использовать $ ("body"). Append (), но тогда вы больше не сможете корректно отлаживать.

ПРИМЕЧАНИЕ. Вы должны использовать это только во время загрузки страницы, иначе вы получите пустой экран. Другими словами, всегда размещайте это перед / за пределами document.ready . Я не проверял использование этого после загрузки страницы в событии щелчка или чем-то подобном, но я почти уверен, что это не удастся.

Мне понравилась идея расширения jQuery, но, очевидно, вам не нужно.

Перед вызовом document.writelnон проверяет, что скрипт еще не загружался, оценивая все элементы скрипта.

Я предполагаю, что сценарий не выполняется полностью, пока не выполнено его document.readyсобытие. (Я знаю, что использование document.readyне требуется, но многие люди используют его, и обращение с ним является гарантией.)

Когда дополнительные файлы загружены, document.readyобратные вызовы будут выполняться в неправильном порядке. Чтобы решить эту проблему, когда скрипт действительно загружен, импортированный скрипт снова импортируется, и выполнение останавливается. Это заставляет исходный файл теперь document.readyвыполнять обратный вызов после любого из любых сценариев, которые он импортирует.

Вместо этого вы можете попытаться изменить jQuery readyList, но это выглядит как худшее решение.

Решение:

$.extend(true,
{
    import_js : function(scriptpath, reAddLast)
    {
        if (typeof reAddLast === "undefined" || reAddLast === null)
        {
            reAddLast = true; // Default this value to true. It is not used by the end user, only to facilitate recursion correctly.
        }

        var found = false;
        if (reAddLast == true) // If we are re-adding the originating script we do not care if it has already been added.
        {
            found = $('script').filter(function () {
                return ($(this).attr('src') == scriptpath);
            }).length != 0; // jQuery to check if the script already exists. (replace it with straight JavaScript if you don't like jQuery.
        }

        if (found == false) {

            var callingScriptPath = $('script').last().attr("src"); // Get the script that is currently loading. Again this creates a limitation where this should not be used in a button, and only before document.ready.

            document.writeln("<script type='text/javascript' src='" + scriptpath + "'></script>"); // Add the script to the document using writeln

            if (reAddLast)
            {
                $.import_js(callingScriptPath, false); // Call itself with the originating script to fix the order.
                throw 'Readding script to correct order: ' + scriptpath + ' < ' + callingScriptPath; // This halts execution of the originating script since it is getting reloaded. If you put a try / catch around the call to $.import_js you results will vary.
            }
            return true;
        }
        return false;
    }
});

Применение:

file3:

var f3obj = "file3";

// Define other stuff
$(function(){
    f3obj = "file3docready";
});

File2:

$.import_js('js/file3.js');
var f2obj = "file2";
$(function(){
    f2obj = "file2docready";
});

File1:

$.import_js('js/file2.js');

// Use objects from file2 or file3
alert(f3obj); // "file3"
alert(f2obj); // "file2"

$(function(){
    // Use objects from file2 or file3 some more.
    alert(f3obj); //"file3docready"
    alert(f2obj); //"file2docready"
});
curlyhairedgenius
источник
Это именно то, что говорится в принятом в настоящее время ответе: просто недостаточно.
Cannicide
Основное отличие состоит в том, что если отсутствует зависимость, он добавляет тег сценария для зависимости, затем также добавляет тег сценария для вызывающего файла и выдает ошибку, которая останавливает выполнение. Это приводит к тому, что сценарии обрабатываются и запускаются в правильном порядке, и устраняет необходимость в обратных вызовах. Таким образом, зависимый скрипт будет загружен и выполнен перед вызывающим скриптом, поддерживая вложение.
curlyhairedgenius
Что касается «похоже, что текущая тенденция заключается в отказе от синхронных запросов», то это верно только потому, что многие разработчики злоупотребили ими и заставили пользователей ждать без необходимости. Однако, если запрос является естественно синхронным, как оператор Include, тогда простой синхронный Ajax вполне подойдет. Я создал общую функцию расширения JavaScript, которая синхронно выполняет функции, такие как чтение файла, не являющегося частью JavaScript, путем запуска PHP-файла «server», и нашел его очень полезным при написании приложений с использованием JavaScript. Для такого Ajax локальный веб-сервер не требуется.
Дэвид Спектор
10

Есть несколько способов реализовать модули в Javascript, вот 2 самых популярных:

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
Виллем ван дер Веен
источник
9

Я пришел к этому вопросу, потому что искал простой способ поддерживать коллекцию полезных плагинов JavaScript. Увидев некоторые решения здесь, я придумал это:

  1. Настройте файл с именем «plugins.js» (или extensions.js или все, что вы хотите). Храните ваши файлы плагинов вместе с этим одним основным файлом.

  2. У plugins.js будет массив, pluginNames[]который мы будем перебирать each(), а затем добавляем <script>тег к заголовку для каждого плагина.

//set array to be updated when we add or remove plugin files
var pluginNames = ["lettering", "fittext", "butterjam", etc.];

//one script tag for each plugin
$.each(pluginNames, function(){
    $('head').append('<script src="js/plugins/' + this + '.js"></script>');
});
  1. Вручную вызовите только один файл в вашей голове:
    <script src="js/plugins/plugins.js"></script>

НО:

Несмотря на то, что все плагины вставляются в тег head так, как они должны, они не всегда запускаются браузером при нажатии на страницу или обновлении.

Я обнаружил, что более надежно просто писать теги сценария в PHP include. Вы должны написать это только один раз, и это такая же работа, как вызов плагина с использованием JavaScript.

rgb_life
источник
@ Будет, ваше решение выглядит намного чище, чем мое, и я волнуюсь, у меня могут быть некоторые ошибки, если я использую мое, так как оно использует .append (). Таким образом, чтобы использовать это, вы можете просто вызвать эту функцию один раз для каждого файла плагина, который вы хотите включить?
rgb_life