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

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

Комментарии к вопросу (6)
Решение

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

Но с 2015 года (ES6) JavaScript имеет стандарт ES6 modules для импорта модулей в Node.js, который также поддерживается [большинством современных браузеров] ( https ://caniuse.com/#feat=es6-модуль).

Для совместимости со старыми браузерами можно использовать инструменты build и / или transpilation.

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

Динамический импорт в браузерах

Динамический импорт позволяет сценарию загружать другие сценарии по мере необходимости:

<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 включить внешнее содержимое 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.");
});

Динамический скрипт Загрузка

Вы можете добавить тег сценария с 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 < / kbd >. И это работает! Смущает...

Так что с этим делать ?

Ну, вы можете использовать взлом, который автор предлагает в ссылке, которую я вам дал. Таким образом, для людей, которые спешат, он использует событие для запуска функции обратного вызова при загрузке сценария. Таким образом, вы можете поместить весь код с помощью удаленной библиотеки в функцию обратного вызова. Например:

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

Затем вы пишете код, который хотите использовать ПОСЛЕ загрузки скрипта в функцию lambda:

var myPrettyCode = function() {
   // Here, do whatever you want
};

Тогда вы запускаете все это:

loadScript("my_lovely_script.js", myPrettyCode);

Обратите внимание, что скрипт может выполняться после загрузки DOM или до этого, в зависимости от браузера и от того, включили ли вы строку script.async = false;. Есть отличная статья о загрузке Javascript в целом, в которой обсуждается это.

Исходный код слияния / предварительной обработки

Как упомянуто в верхней части этого ответа, многие разработчики используют в своих проектах инструменты сборки / переплета, такие как Parcel, Webpack или Babel, что позволяет им использовать предстоящий синтаксис JavaScript, обеспечивает обратную совместимость для старых браузеров, объединяет файлы, измельчает, выполнить разделение кода и т. д.

Комментарии (31)

Если кто-то ищет что-то более продвинутое, попробуйте RequireJS. Вы получите дополнительные преимущества, такие как управление зависимостями, лучший параллелизм и избегание дублирования (то есть извлечение сценария более одного раза).

Вы можете написать свои файлы JavaScript в «модулях», а затем ссылаться на них как на зависимости в других скриптах. Или вы можете использовать RequireJS как простое решение «перейти к этому сценарию».

Пример:

Определите зависимости как модули:

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

implementation.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, а также более определенные модули. Он оптимизирован для использования в браузере, в том числе в Интернете Рабочий, но его можно использовать в других средах JavaScript, например Носорог и узел. Он реализует API асинхронных модулей

RequireJS использует простые теги сценариев для загрузки модулей / файлов, так что это должно быть позволяют легко отлаживать. Его можно использовать просто для загрузки существующих Файлы JavaScript, так что вы можете добавить его в свой существующий проект без необходимость переписать ваши файлы JavaScript.

...

Комментарии (7)

На самом деле is способ загрузить файл JavaScript not асинхронно, чтобы вы могли использовать функции, включенные в ваш недавно загруженный файл, сразу после его загрузки, и я думаю, что он работает во всех браузерах.

Вам необходимо использовать jQuery.append () в элементе < head >, который:

$("head").append('<script type="text/javascript" src="' + script + '"></script>');

Однако, у этого метода также есть проблема: если в импортированном файле JavaScript произошла ошибка, ,[Firebug]1] ,(а также Firefox Error Console и [Инструменты разработчика Chrome]2] также) сообщит о своем месте неправильно, это большая проблема, если вы используете 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-satis).

Комментарии (7)

Другой способ, который, на мой взгляд, намного чище, - это сделать синхронный запрос Ajax вместо использования тега < script >. Так же и [Node.js][1] включает в себя маркеры.

Вот пример использования jQuery:


function require(script) {
    $.ajax({
        url: script,
        dataType: "script",
        async: false,           // 
Комментарии (13)

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

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

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

Обратитесь к:

[3]: http://wiki.ecmascript.org/doku.php?id = гармония: module_loaders

Комментарии (11)

Можно динамически генерировать тег 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");
Комментарии (13)

Заявление 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;
Комментарии (4)

Может быть, вы можете использовать эту функцию, которую я нашел на этой странице [Как включить файл JavaScript в файл JavaScript?][1] :

function include(filename)
{
    var head = document.getElementsByTagName('head')[0];

    var script = document.createElement('script');
    script.src = filename;
    script.type = 'text/javascript';

    head.appendChild(script)
}

[1]: http://forums.digitalpoint.com/showthread.php?t = 146094

Комментарии (7)

Вот синхронная версия без jQuery :


function myRequire( url ) {
    var ajax = new XMLHttpRequest();
    ajax.open( 'GET', url, false ); // 
Комментарии (7)

Я только что написал этот код JavaScript (используя Прототип для манипуляции 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.

Комментарии (2)

Вот обобщенная версия того, как Facebook делает это для своей вездесущей кнопки «Мне нравится»

& Лт;!- начать фрагмент: js скрыть: false - >

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

Комментарии (2)

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

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

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

$.getScript("another_script.js");
Комментарии (1)

Вы также можете собрать свои сценарии, используя 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
Комментарии (2)

Большинство решений, показанных здесь, подразумевают динамическую нагрузку. Вместо этого я искал компилятор, который собирал все зависающие файлы в один выходной файл. Так же, как препроцессоры 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");
  • src / Form / Input / Tel.js *
function() {
    return {
          prop: "",
          method: function(){}
    }
}

Теперь мы можем запустить компилятор:

node jsic.js src/main.js build/mail.js

И получите объединенный файл

build / main.js

var foo = function() {
    return {
          prop: "",
          method: function(){}
    }
};
Комментарии (1)

Если вы хотите загрузить файл 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. Заказ должен быть как ниже:


  <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>
Комментарии (0)

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

xhr = new XMLHttpRequest();
xhr.open("GET", "/soap/ajax/11.0/connection.js", false);
xhr.send();
eval(xhr.responseText);
Комментарии (6)

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

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

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

Комментарии (1)

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

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

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

Комментарии (0)

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

Мне пришлось использовать переменную (myVar1), определенную в одном файле JavaScript (myvariables.js) в другом файле JavaScript (main.js).

Для этого я сделал, как ниже:

Загрузил код JavaScript в файле HTML, в правильном порядке, сначала mystariables.js, затем main.js:




        <script src="myvariables.js" > </script>
        <script src="main.js" > </script>



Файл: 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 автоматически.

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

Комментарии (5)

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

Из документации по смеси в файлах .mix:

Файлы Mix - это просто файлы .js или .css с .mix. в имени файла. A файл 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, кроме как использовать его в качестве внешнего инструмента разработки. Я столкнулся с этим вопросом, увидев файл JavaScript .mix в действии (в одной из котельных смесей) и немного смутившись этим («вы можете сделать это?"Я думал про себя). Тогда я понял, что это был тип файла для конкретного приложения (несколько разочаровывающий, согласованный). Тем не менее, понял, что знания могут быть полезны для других.

ОБНОВЛЕНИЕ : Смесь теперь бесплатная (офлайн).

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

Комментарии (2)