within - Como faço para incluir um arquivo JavaScript em outro arquivo JavaScript?




load js from another js (20)

É possível gerar dinamicamente uma tag JavaScript e anexá-la ao documento HTML de outro código JavaScript. Isso carregará o arquivo JavaScript direcionado.

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

https://code.i-harness.com

Existe algo em JavaScript semelhante ao @import em CSS que permite incluir um arquivo JavaScript dentro de outro arquivo JavaScript?


A import instruções está no ECMAScript 6.

Sintaxe

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;

Acabei de escrever este código JavaScript (usando Prototype para manipulação de 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);
        }
    });
})();

Uso:

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

Gist: http://gist.github.com/284442 .


Aqui está a versão generalizada de como o Facebook faz isso por seu onipresente botão Like:

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

Se funcionar para o Facebook, funcionará para você.

A razão pela qual procuramos o primeiro elemento de script vez de head ou body é porque alguns navegadores não criam um, se estiverem faltando, mas temos a garantia de ter um elemento de script - este. Leia mais em http://www.jspatterns.com/the-ridiculous-case-of-adding-a-script-element/ .


As versões antigas do JavaScript não tinham importação, inclusão ou necessidade, portanto, muitas abordagens diferentes para esse problema foram desenvolvidas.

Mas desde 2015 (ES6), o JavaScript teve o padrão dos módulos ES6 para importar módulos no Node.js, que também é suportado pela maioria dos navegadores modernos .

Para compatibilidade com navegadores mais antigos, ferramentas de build e / ou transpilation podem ser usadas.

Módulos ES6

Módulos ECMAScript (ES6) foram suportados no Node.js desde a v8.5, com o --experimental-modules . Todos os arquivos envolvidos devem ter a extensão .mjs .

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

Módulos ECMAScript nos navegadores

Os navegadores têm suporte para o carregamento de módulos ECMAScript diretamente (sem necessidade de ferramentas como o Webpack) since Safari 10.1, Chrome 61, Firefox 60 e Edge 16. Verifique o suporte atual em 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);
}

Leia mais em: since

Importações dinâmicas em navegadores

As importações dinâmicas permitem que o script carregue outros scripts conforme necessário:

<script type="module">
  import('hello.mjs').then(module => {
      module.hello('world');
    });
</script>

Leia mais em: https://developers.google.com/web/updates/2017/11/dynamic-import

Node.js requer

O estilo antigo de importar módulos, ainda amplamente usado no Node.js, é o module.exports/require .

// mymodule.js
module.exports = {
   hello: function() {
      return "Hello";
   }
}
// server.js
const myModule = require('./mymodule');
let val = myModule.hello(); // val is "Hello"   

Existem outras maneiras de o JavaScript incluir conteúdo JavaScript externo em navegadores que não exigem pré-processamento.

AJAX Carregando

Você poderia carregar um script adicional com uma chamada AJAX e, em seguida, usar o eval para executá-lo. Essa é a maneira mais direta, mas é limitada ao seu domínio por causa do modelo de segurança do sandbox do JavaScript. O uso do eval também abre as portas para bugs, hacks e problemas de segurança.

jQuery Loading

A biblioteca jQuery fornece funcionalidade de carregamento em uma linha :

$.getScript("my_lovely_script.js", function() {
   alert("Script loaded but not necessarily executed.");
});

Carregamento de script dinâmico

Você pode adicionar uma tag de script com o URL do script no HTML. Para evitar a sobrecarga do jQuery, esta é uma solução ideal.

O script pode até residir em um servidor diferente. Além disso, o navegador avalia o código. A tag <script> pode ser injetada na tag da web <head> ou inserida logo antes da tag de fechamento </body> .

Aqui está um exemplo de como isso poderia funcionar:

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

Essa função adicionará uma nova tag <script> ao final da seção head da página, onde o atributo src é definido para a URL que é dada à função como o primeiro parâmetro.

Ambas as soluções são discutidas e ilustradas em JavaScript Madness: Dynamic Script Loading .

Detectando quando o script foi executado

Agora, há um grande problema que você deve conhecer. Isso implica que você carregue remotamente o código . Os navegadores da Web modernos carregam o arquivo e continuam executando seu script atual porque carregam tudo de forma assíncrona para melhorar o desempenho. (Isso se aplica tanto ao método jQuery quanto ao método de carregamento manual de script dinâmico.)

Isso significa que, se você usar esses truques diretamente, não poderá usar o código recém-carregado na próxima linha depois de solicitar que ele seja carregado , porque ele ainda estará sendo carregado.

Por exemplo: my_lovely_script.js contém 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

Então você recarrega a página atingindo F5 . E isso funciona! Confuso ...

Então o que fazer sobre isso ?

Bem, você pode usar o hack que o autor sugere no link que eu te dei. Em resumo, para pessoas com pressa, ele usa um evento para executar uma função de retorno de chamada quando o script é carregado. Então você pode colocar todo o código usando a biblioteca remota na função de retorno de chamada. Por exemplo:

function loadScript(url, callback)
{
    // Adding the script tag to the head as suggested before
    var head = document.getElementsByTagName('head')[0];
    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);
}

Então você escreve o código que você quer usar depois que o script é carregado em uma função lambda :

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

Então você corre tudo isso:

loadScript("my_lovely_script.js", myPrettyCode);

Observe que o script pode ser executado depois que o DOM foi carregado ou antes, dependendo do navegador e se você incluiu a linha script.async = false; . Há um ótimo artigo sobre o carregamento de JavaScript em geral, que discute isso.

Mesclagem / pré-processamento de código-fonte

Como mencionado no início desta resposta, muitos desenvolvedores usam ferramentas de compilação / transpilação como Parcel, Webpack ou Babel em seus projetos, permitindo que usem a próxima sintaxe JavaScript, forneçam compatibilidade retroativa para navegadores mais antigos, combinem arquivos, minifiquem, executar o código de divisão etc.


Há uma boa notícia para você. Muito em breve você poderá carregar o código JavaScript com facilidade. Ela se tornará uma maneira padrão de importar módulos de código JavaScript e fará parte do próprio JavaScript principal.

Você simplesmente tem que escrever import cond from 'cond.js'; para carregar uma macro nomeada cond de um arquivo cond.js

Portanto, você não precisa depender de nenhuma estrutura JavaScript nem de fazer explicitamente chamadas Ajax .

Referir-se:


Na verdade, existe uma maneira de carregar um arquivo JavaScript não de forma assíncrona, para que você possa usar as funções incluídas em seu arquivo recém-carregado logo após carregá-lo, e acho que ele funciona em todos os navegadores.

Você precisa usar jQuery.append() no elemento <head> da sua página, ou seja:

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

No entanto, esse método também tem um problema: se ocorrer um erro no arquivo JavaScript importado, o Firebug (e também o Firefox Error Console e as Chrome Developer Tools ) informará seu local incorretamente, o que é um grande problema se você usar o Firebug para rastrear Erros de JavaScript para baixo muito (eu faço). O Firebug simplesmente não sabe sobre o arquivo recém-carregado por algum motivo, portanto, se ocorrer um erro nesse arquivo, ele informará que ocorreu no arquivo HTML principal e você terá problemas para descobrir o motivo real do erro.

Mas se isso não é um problema para você, então este método deve funcionar.

Eu realmente escrevi um plugin jQuery chamado $ .import_js () que usa este método:

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

Então tudo o que você precisa fazer para importar JavaScript é:

$.import_js('/path_to_project/scripts/somefunctions.js');

Eu também fiz um teste simples para isso no Example .

Ele inclui um arquivo main.js no HTML principal e, em seguida, o script em main.js usa $.import_js() para importar um arquivo adicional chamado included.js , que define esta função:

function hello()
{
    alert("Hello world!");
}

E logo depois de incluir o included.js , a função hello() é chamada e você recebe o alerta.

(Esta resposta é em resposta ao comentário do e-satis).


Outra maneira, que na minha opinião é muito mais limpa, é fazer um pedido Ajax síncrono em vez de usar uma tag <script> . Qual é também como as manipulações do Node.js incluem.

Aqui está um exemplo usando 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);
        }
    });
}

Você pode então usá-lo em seu código como usaria normalmente um include:

require("/scripts/subscript.js");

E ser capaz de chamar uma função do script necessário na próxima linha:

subscript.doSomethingCool(); 

Se alguém estiver procurando por algo mais avançado, experimente o RequireJS . Você obterá benefícios adicionais, como gerenciamento de dependência, melhor concorrência e evitar duplicação (ou seja, recuperar um script mais de uma vez).

Você pode escrever seus arquivos JavaScript em "módulos" e, em seguida, referenciá-los como dependências em outros scripts. Ou você pode usar o RequireJS como uma solução simples "vá buscar este script".

Exemplo:

Definir dependências como módulos:

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 é o seu arquivo JavaScript "principal" que depende do some-dependency.js

require(['some-dependency'], function(dependency) {

    //Your script goes here
    //some-dependency.js is fetched.   
    //Then your script is executed
});

Trecho do README do GitHub :

O RequireJS carrega arquivos JavaScript simples, assim como módulos mais definidos. Ele é otimizado para uso no navegador, inclusive em um Web Worker, mas pode ser usado em outros ambientes JavaScript, como Rhino e Node. Implementa a API do módulo assíncrono.

O RequireJS usa tags de script simples para carregar módulos / arquivos, portanto, deve permitir uma depuração fácil. Ele pode ser usado simplesmente para carregar arquivos JavaScript existentes, para que você possa adicioná-lo ao seu projeto existente sem ter que reescrever seus arquivos JavaScript.

...


Se você quiser em JavaScript puro, você pode usar document.write .

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

Se você usar a biblioteca jQuery, poderá usar o método $.getScript .

$.getScript("another_script.js");

Você também pode montar seus scripts usando PHP :

Arquivo 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

Eu tive um problema simples, mas fiquei perplexo com as respostas a essa pergunta.

Eu tive que usar uma variável (myVar1) definida em um arquivo JavaScript (myvariables.js) em outro arquivo JavaScript (main.js).

Para isso fiz o seguinte:

Carregou o código JavaScript no arquivo HTML, na ordem correta, myvariables.js primeiro, depois main.js:

<html>
    <body onload="bodyReady();" >

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

        <!-- Some other code -->
    </body>
</html>

Arquivo: myvariables.js

var myVar1 = "I am variable from myvariables.js";

Arquivo: main.js

// ...
function bodyReady() {
    // ...
    alert (myVar1);    // This shows "I am variable from myvariables.js", which I needed
    // ...
}
// ...

Como você viu, eu usei uma variável em um arquivo JavaScript em outro arquivo JavaScript, mas não precisei incluir um no outro. Eu só precisava garantir que o primeiro arquivo JavaScript carregado antes do segundo arquivo JavaScript e as primeiras variáveis ​​do arquivo JavaScript estivessem acessíveis no segundo arquivo JavaScript, automaticamente.

Isso salvou meu dia. Eu espero que isso ajude.


Na linguagem moderna, seria

function loadJs( url ){
  return new Promise( resolve => {
    const script = document.createElement( "script" );
    script.src = url;
    script.onload = resolve;
    document.head.appendChild( script );
  });
}

Ou, em vez de incluir no tempo de execução, use um script para concatenar antes do upload.

Eu uso Sprockets (não sei se existem outros). Você cria seu código JavaScript em arquivos separados e inclui comentários que são processados ​​pelo mecanismo do Sprockets como inclusões. Para desenvolvimento, você pode incluir arquivos sequencialmente e, em seguida, para a produção mesclá-los ...

Veja também:


Caso você esteja usando Web Workers e queira incluir scripts adicionais no escopo do worker, as outras respostas fornecidas sobre a adição de scripts à headtag, etc. não funcionarão para você.

Felizmente, os Web Workers têm sua própria importScriptsfunção, que é uma função global no escopo do Web Worker, nativa do próprio navegador, pois faz parte da especificação .

Como alternativa, como a segunda resposta mais votada para os destaques de sua pergunta , o RequireJS também pode manipular a inclusão de scripts dentro de um Web Worker (provavelmente chamando a importScriptssi mesmo, mas com alguns outros recursos úteis).


Este script adicionará um arquivo JavaScript ao topo de qualquer outra <script>tag:

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

Eu criei uma função que permitirá que você use verbosidade semelhante ao C # / Java para incluir um arquivo JavaScript. Eu testei um pouco até de dentro de outro arquivo JavaScript e parece funcionar. Ele requer jQuery embora por um pouco de "magia" no final.

Eu coloquei este código em um arquivo na raiz do meu diretório de script (eu o nomeei global.js, mas você pode usar o que quiser. A menos que eu esteja enganado, o jQuery deve ser o único script necessário em uma determinada página. Lembre-se disso é em grande parte não testado além de algum uso básico, por isso pode ou não haver quaisquer problemas com a maneira que eu fiz isso, use a seu próprio risco yadda yadda Eu não sou responsável se você estragar tudo yadda yadda:

/**
* @fileoverview This file stores global functions that are required by other libraries.
*/

if (typeof(jQuery) === 'undefined') {
    throw 'jQuery is required.';
}

/** Defines the base script directory that all .js files are assumed to be organized under. */
var BASE_DIR = 'js/';

/**
* Loads the specified file, outputting it to the <head> HTMLElement.
*
* This method mimics the use of using in C# or import in Java, allowing
* JavaScript files to "load" other JavaScript files that they depend on
* using a familiar syntax.
*
* This method assumes all scripts are under a directory at the root and will
* append the .js file extension automatically.
*
* @param {string} file A file path to load using C#/Java "dot" syntax.
*
* Example Usage:
* imports('core.utils.extensions');
* This will output: <script type="text/javascript" src="/js/core/utils/extensions.js"></script>
*/
function imports(file) {
    var fileName = file.substr(file.lastIndexOf('.') + 1, file.length);

    // Convert PascalCase name to underscore_separated_name
    var regex = new RegExp(/([A-Z])/g);
    if (regex.test(fileName)) {
        var separated = fileName.replace(regex, ",$1").replace(',', '');
        fileName = separated.replace(/[,]/g, '_');
    }

    // Remove the original JavaScript file name to replace with underscore version
    file = file.substr(0, file.lastIndexOf('.'));

    // Convert the dot syntax to directory syntax to actually load the file
    if (file.indexOf('.') > 0) {
        file = file.replace(/[.]/g, '/');
    }

    var src = BASE_DIR + file + '/' + fileName.toLowerCase() + '.js';
    var script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = src;

    $('head').find('script:last').append(script);
}

Eu escrevi um módulo simples que automatiza o trabalho de importar / incluir scripts de módulo em JavaScript. Para uma explicação detalhada do código, consulte a postagem do blog 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);
};

Há também Head.js . É muito fácil lidar com:

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

Como você vê, é mais fácil do que o Require.js e tão conveniente quanto o $.getScriptmétodo do jQuery . Ele também possui alguns recursos avançados, como carregamento condicional, detecção de recursos e muito mais .


Melhor usar o modo jQuery . Para atrasar o evento pronto, primeiro ligue $.holdReady(true). Exemplo ( source ):

$.holdReady(true);
$.getScript("myplugin.js", function() {
    $.holdReady(false);
});




include