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

5194

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

Alec Smart
fonte
82
@ Daniel, eu não quero usar uma chamada AJAX.
Alec inteligente
13
Por que não declarar o arquivo importado antes do outro que o exige, simplesmente usando scripttags ordenadas ?
Falsarella
6
@ Claudiu Isso não ajudaria a importar nada, mas deveria funcionar também. Se você tiver um arquivo JS que depende de outro arquivo JS, apenas declare as tags de script dos arquivos de dependência primeiro, para que o posterior já tenha suas dependências carregadas. Se você tiver uma situação em que não seja possível, as respostas aqui devem ser úteis.
Falsarella
1
qual é a vantagem prática de fazer isso? de qualquer forma, a base de código dependente do arquivo javascript não será carregada e começará a funcionar em qualquer caso, não será carregada!
Ciasto piekarz

Respostas:

4472

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

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

Para compatibilidade com navegadores antigos, crie ferramentas como Webpack e Rollup e / ou ferramentas de transpilação como Babel .

Módulos ES6

Os módulos ECMAScript (ES6) são suportados no Node.js. desde a v8.5, com o --experimental-modulessinalizador, e desde pelo menos Node.js. v13.8.0, sem o sinalizador. Para ativar "ESM" (vs. sistema de módulos commonjs de estilo anterior Node.js [ "CJS"]) que você quer para uso "type": "module"em package.jsonou dar os arquivos a extensão .mjs. (Da mesma forma, os módulos gravados com o módulo CJS anterior do Node.js. podem ser nomeados .cjsse o padrão for ESM.)

Usando package.json:

{
    "type": "module"
}

Então module.js:

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

Então main.js:

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

Usando .mjs, você teria module.mjs:

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

Então main.mjs:

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

Módulos ECMAScript em navegadores

Os navegadores têm suporte para carregar módulos ECMAScript diretamente (não são necessárias ferramentas como o Webpack) desde o Safari 10.1, Chrome 61, Firefox 60 e Edge 16. Verifique o suporte atual no caniuse . Não há necessidade de usar a .mjsextensão do Node.js. Os navegadores ignoram completamente as extensões de arquivo nos módulos / scripts.

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

Leia mais em https://jakearchibald.com/2017/es-modules-in-browsers/

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

O Node.js requer

O estilo mais antigo do módulo CJS, ainda amplamente usado no Node.js, é o 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"   

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

Carregamento AJAX

Você pode carregar um script adicional com uma chamada AJAX e depois usá eval-lo para executá-lo. Essa é a maneira mais direta, mas está limitada ao seu domínio devido ao modelo de segurança da sandbox JavaScript. O uso evaltambém abre as portas para bugs, hacks e problemas de segurança.

Obter carregamento

Como as importações dinâmicas, você pode carregar um ou vários scripts com uma fetchchamada usando promessas para controlar a ordem de execução das dependências de script usando a biblioteca 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)}`)
})

Carregamento de jQuery

A biblioteca jQuery fornece a 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 a 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 <script>tag pode ser injetada na página da Web <head>ou inserida imediatamente antes da </body>tag de fechamento .

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

Esta função adicionará uma nova <script>tag ao final da seção principal da página, onde o srcatributo é definido como o URL que é atribuído à 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ê carrega remotamente o código . Navegadores modernos carregam o arquivo e continuam executando o script atual, porque carregam tudo de forma assíncrona para melhorar o desempenho. (Isso se aplica ao método jQuery e ao método de carregamento de script dinâmico manual.)

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 ainda estará carregando.

Por exemplo: my_lovely_script.jsconté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 acessando F5. E funciona! Confuso ...

Então o que fazer sobre isso ?

Bem, você pode usar o hack que o autor sugere no link que eu lhe dei. Em resumo, para pessoas com pressa, ele usa um evento para executar uma função de retorno de chamada quando o script é carregado. Assim, 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.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);
}

Em seguida, você escreve o código que deseja usar APÓS o script ser carregado em uma função lambda :

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

Então você executa tudo isso:

loadScript("my_lovely_script.js", myPrettyCode);

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

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

Como mencionado na parte superior desta resposta, muitos desenvolvedores usam ferramentas de compilação / transpilação como Parcel, Webpack ou Babel em seus projetos, permitindo que eles usem a próxima sintaxe JavaScript, forneçam compatibilidade com versões anteriores para navegadores antigos, combinem arquivos, minifiquem, executar divisão de código etc.

e-satis
fonte
130
Não, mas alguém que usa algo tão avançado quanto o Rhino ou então não faria essa pergunta.
e-satis
192
Para concluir, existe uma terceira maneira: em certas soluções, quando você controla os dois arquivos javascript, você pode criar apenas um arquivo javascript gigante, que combina o conteúdo dos dois arquivos.
sapo
20
Não deve "document.createElement (" my_lovely_script.js ");" no exemplo seja "document.createElement (" script ")"?
Russell Silva
14
Como eval abre a porta para hacks, se é o seu código que você está executando?
Vince Panuccio
6
Sua resposta requer alguma modificação para o IE ( onreadystatechangeevento e a readyStatepropriedade). Além disso, o carregamento dinâmico de scripts não se beneficia dos scanners de pré-carregamento do Bros. Recomende este artigo do HTML5Rocks: html5rocks.com/en/tutorials/speed/script-loading
ruhong
570

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

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

Exemplo:

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

deployment.js é o seu arquivo JavaScript "principal" que depende de some-dependency.js

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

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

Trecho do arquivo README do GitHub :

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

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

...

John Strickler
fonte
1
@aaaidan: O motivo do MattDmo, mais ele se baseia em uma biblioteca externa que, em troca, depende da resposta aceita.
David Mulder
1
Para superar o require.js, o mais recente seria o js angular, mais estável e fácil de usar, além de outros recursos avançados de ligação e HTML.
zeeshan
5
-1: essas abstrações - "alguma_dependência" - são realmente ruins, com índices aumentando a confusão. Eu luto para entender como é um exemplo de código funcional. Se o autor fornecesse um exemplo prático, quase qualquer um seria capaz de adaptá-lo e generalizá-lo às suas necessidades.
Tegiri Nenashi
1
não funciona bem com MVC e roteiro agregação com minification automática
Triynko
1
'add .. sem ter que reescrever seus arquivos JavaScript'; legal, mas como exatamente? Cur. A resposta sugere adicionar esse 'require' (não 'requirejs'?) ao script principal + tal 'define' a cada arquivo dependente, sim? Mas isso é reescrito, então o que não foi reescrito? -restante de código desde que o RequireJS permite que um arquivo faça defs globais normalmente? -é verdade? Eu apenas tentei isso, + (esquecido?) <Script src = " requirejs.org/docs/release/2.2.0/comments/require.js "> </script>, depois 'requirejs ([' GoogleDrive.com/host /..',..],function(a,b) {} mycode) ': Firebug diz que cada dependente carregado, mas suas instruções def não definido no mycode e depois.
Arquiteto de Destiny
195

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

Você precisa usar jQuery.append()no <head>elemento 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 o Chrome Developer Tools ) informarão seu lugar incorretamente, o que é um grande problema se você usar o Firebug para rastrear Erros de JavaScript caem muito (sim). O Firebug simplesmente não sabe sobre o arquivo recém-carregado por algum motivo; portanto, se ocorrer um erro nesse arquivo, ele informa que ocorreu no seu HTML principal arquivo e você terá problemas para descobrir a verdadeira razão do erro.

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

Na verdade, eu 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);

Portanto, tudo que você precisa fazer para importar o JavaScript é:

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

Também fiz um teste simples para isso no Exemplo .

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

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

E logo após a inclusão included.js, a hello()função é chamada e você recebe o alerta.

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

Kipras
fonte
Estou tentando esse método, mas não está funcionando para mim, o elemento simplesmente não aparece na tag head.
sites
16
@juanpastas - uso jQuery.getScript, dessa forma você não precisa se preocupar em escrever o plugin ...
MattDMo
6
Hmm, de acordo com este artigo , anexar um scriptelemento ao headfará com que ele seja executado de forma assíncrona, a menos que asyncesteja definido especificamente como false.
Flimm
1
A variável de script não deve ter entidades HTML codificadas? Se o link contém o ", código vai quebrar
RedClover
1
@Flimm caro senhor, eu e minha equipe agradecer por seu comentário e eu, pessoalmente, devo-lhe uma cerveja de dinheiro, mesmo se alguma vez encontrar-se pessoalmente
Alex
155

Outra maneira, que na minha opinião é muito mais limpa, é fazer uma solicitação síncrona do Ajax em vez de usar uma <script>tag. Também é assim que o Node.js lida com inclui.

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

Em seguida, você pode usá-lo em seu código, como normalmente usaria uma inclusão:

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

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

subscript.doSomethingCool(); 
Ariel
fonte
1
Boa solução, a inclusão da cabeça é assíncrona, infelizmente, a solução ajax funciona.
Matteo Conta
17
Como outra pessoa mencionou, o requirejs.org faz isso e também possui um pré-compilador que reúne os arquivos js para que eles sejam carregados mais rapidamente. Você pode querer conferir.
Ariel #
2
Descobri que podia fazer depurá-lo adicionando esta directiva na parte inferior do arquivo para o Chrome: // @ SourceURL = view_index.js
Todd Vance
11
infelizmente, async: false agora está obsoleto no jQuery. Pode quebrar no futuro, então eu evitaria.
Sqram
3
@katsh Não estamos usando objetos jqXHR aqui. Sua cotação não parece fazer backup de seu comentário anterior afirmando que async: falsesupostamente está obsoleto. Não é! Como sua cotação indica, apenas o material relacionado ao jqXHR é.
Zero3
101

Há uma boa notícia para você. Em breve, você poderá carregar o código JavaScript facilmente. Ele se tornará uma maneira padrão de importar módulos de código JavaScript e fará parte do próprio JavaScript principal.

Você simplesmente precisa escrever import cond from 'cond.js';para carregar uma macro chamada condde um arquivo cond.js.

Portanto, você não precisa confiar em nenhuma estrutura JavaScript nem precisa fazer explicitamente chamadas para o Ajax .

Referir-se:

Imdad
fonte
12
O require / import no jsfile demorou muito tempo a chegar. (OMI)
Rwheadon
6
@rwheadon sim parece chocante que isso não faça parte do idioma! Como as pessoas fazem algo está além de mim! Im novo para ele e isso parece piores (de muitos) bits de loucura
JonnyRaa
@ jonny-leeds Mesmo sem o carregamento interno do módulo, o JavaScript no navegador é flexível o suficiente para que possamos implementar uma biblioteca como o RequireJS para o gerenciamento do módulo.
Keen
8
mid 2015- Ainda não implementado em qualquer navegador, developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
scape
sim você está certo. agora eu estou começando a me sentir mal por isso :( thouh, uma vez implementado em todos os navegadores que este será um grande recurso embutido para javascript..
Imdad
97

É 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");
Svitlana Maksymchuk
fonte
8
@ e-satis - Na verdade, isso é uma vantagem, um script de sincronização estaria bloqueando. Cavalos para percursos, mas 9 vezes em 10 você deseja a opção sem bloqueio.
Annakata 4/06/2009
@Svitlana - os elementos de script criados assim são assíncronos. Atualmente, isso pode ser visto como explorar uma brecha, para que não seja uma prova futura. Não vi nada em nenhum padrão que esclareça isso.
Annakata 4/06/2009
Na verdade, eu retiro, notei que você está anexando ao corpo, e não à cabeça.
Annakata 4/06/2009
@annakata: Qual é a diferença? BTW, o yahoo sugere adicionar tags de script ao final do corpo, para que nada deva dar errado ao anexar dinamicamente.
Svitlana Maksymchuk
7
@ e-satis assíncrono é bom porque não congela sua página. Use callback para ser notificado quando ele é feitojs.onload = callback;
Vitim.us
74

Declaração import 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;
draupnie
fonte
... mas não é suportado por nenhum navegador até o momento, de acordo com a tabela de compatibilidade na página à qual você vinculou.
precisa saber é
6
Agora você pode escrever código ES6 e compilá-lo com Babel.js ( babeljs.io ) para o que o seu sistema de módulo atual preferido é (commonjs / AMD / UMD): babeljs.io/docs/usage/modules
Jeremy Harris
@ Zero3 Aparentemente, o novo IE (Edge) é o único #
Julian Avar
em 2019, o IE ainda não suporta isso de nenhuma forma. Por que a Microsoft deve ser tão contra a usabilidade?
GreySage 5/09/19
61

Talvez você possa usar esta função que encontrei nesta página. Como incluo um arquivo JavaScript em um arquivo 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)
}
Arnaud Gouder de Beauregard
fonte
5
Deveria ser útil adicionarscript.onload = callback;
Vitim.us
@SvitlanaMaksymchuk então, se eu não usar var, a variável será global?
Francisco Corrales Morales
@FranciscoCorrales yes.
Christopher Chiche
Ele acaba no global com ou sem o var :)
Vedran Maricevic.
Isso falhará se a página não tiverhead .
Dan Dascalescu
54

Aqui está uma versão síncrona sem 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);
}

Observe que, para obter esse domínio entre domínios, o servidor precisará definir o allow-origincabeçalho em sua resposta.

heinob
fonte
Excellent function! Carrega o JavaScript antes que qualquer JS adicional seja gravado após o corpo. Muito importante ao carregar vários scripts.
tfont 28/02
3
@heinob: O que posso fazer para que ele funcione em vários domínios? (script de carregamento de http://web.archive.org/web/20140905044059/http://www.howtocreate.co.uk/operaStuff/userjs/aagmfunctions.js)
user2284570
@ user2284570: Se você é o proprietário do domínio estrangeiro: defina o cabeçalho `allow-origin 'na resposta do servidor. Se você não é o proprietário: nada. Desculpa! Essa é a política de origem cruzada.
heinob
2
@ user2284570: Entendo seu comentário dessa maneira, que você não é o proprietário do domínio do qual deseja carregar o script. Nesse caso, você só pode carregar um script por meio de uma <script>tag inserida , não por XMLHttpRequest.
heinob 14/09/14
2
Para aqueles que planejam usar isso no Firefox (por exemplo, para scripts imacros), adicione esta linha ao topo do arquivo:const XMLHttpRequest = Components.Constructor("@mozilla.org/xmlextras/xmlhttprequest;1");
Kwestion 16/16
49

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 .

nornagon
fonte
7
jrburke escreveu isso como RequireJS. Github: requirejs.org/docs/requirements.html
Mike Caron
Não é isso que coloca o script carregado fora do escopo em que require () é chamado? Parece que eval () é a única maneira de fazê-lo dentro do escopo. Ou existe outra maneira?
trusktr
44

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

<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 scriptelemento em vez de headou bodyé porque alguns navegadores não criam um se estiverem ausentes, mas garantimos que temos um scriptelemento - este. Leia mais em http://www.jspatterns.com/the-ridiculous-case-of-adding-a-script-element/ .

Dan Dascalescu
fonte
3
Muito bom! Alguns dos métodos aqui também funcionam, mas em uma configuração dinâmica isso funciona melhor.
tfont
estendi seu script para eliminar a publicação
Kamil Dąbrowski
39

Se você deseja JavaScript puro, pode usar document.write.

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

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

$.getScript("another_script.js");
Venu immadi
fonte
8
document.write não removeria todo o resto?
Eisa Adil
30

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
Calmarius
fonte
16
Parece que o ponto é manter tudo isso em javascript na extremidade dianteira
Ariel
1
Obrigado por lembrar isso. Você também pode ter tags <script> PHP write no seu cabeçalho HTML, para que os arquivos js necessários (e somente aqueles) sejam carregados.
Rolf
29

A maioria das soluções mostradas aqui implica carregamento dinâmico. Eu estava procurando um compilador que reunisse todos os arquivos dependentes em um único arquivo de saída. O mesmo que os pré-processadores Less / Sass lidam com a @importregra geral do CSS . Como não achei nada decente desse tipo, escrevi uma ferramenta simples para resolver o problema.

Então, aqui está o compilador, https://github.com/dsheiko/jsic , que substitui $import("file-path")com segurança o conteúdo do arquivo solicitado. Aqui está o plug-in Grunt correspondente : https://github.com/dsheiko/grunt-jsic .

No ramo mestre do jQuery, eles simplesmente concatenam os arquivos de origem atômica em um único começando intro.jse terminando com outtro.js. Isso não combina comigo, pois não oferece flexibilidade no design do código-fonte. Confira como ele funciona com o jsic:

src / main.js

var foo = $import("./Form/Input/Tel");

src / Form / Input / Tel.js

function() {
    return {
          prop: "",
          method: function(){}
    }
}

Agora podemos executar o compilador:

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

E obtenha o arquivo combinado

build / main.js

var foo = function() {
    return {
          prop: "",
          method: function(){}
    }
};
Dmitry Sheiko
fonte
2
Desde este post, eu vim com uma solução muito melhor - compilador de módulo CommonJS - github.com/dsheiko/cjsc. Então você pode simplesmente escrever módulos CommonJs ou NodeJs e acessar um ao outro, mantendo-os em escopos isolados. Os benefícios: Não há necessidade de várias solicitações HTTP que afetam o desempenho. Você não precisa agrupar manualmente o código do módulo - é responsabilidade do compilador (melhor legibilidade do código-fonte). Você não precisa de bibliotecas externas. É compatível com UMD- e módulos NodeJS (por exemplo, você pode abordar jQuery, Backbone como módulos sem tocar o seu código)
Dmitry Sheiko
26

Se sua intenção de carregar o arquivo JavaScript estiver usando as funções do arquivo importado / incluído , você também poderá definir um objeto global e definir as funções como itens de objeto. Por exemplo:

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

Você só precisa ter cuidado ao incluir scripts em um arquivo HTML. O pedido deve ser como abaixo:

<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>
Adem İlhan
fonte
22

Isso deve fazer:

xhr = new XMLHttpRequest();
xhr.open("GET", "/soap/ajax/11.0/connection.js", false);
xhr.send();
eval(xhr.responseText);
tggagne
fonte
5
o evalque há de errado com isso. De Crockford , " evalé ruim. A evalfunção é o recurso mais mal utilizado do JavaScript. Evite-o. evalPossui aliases. Não use o Functionconstrutor. Não passe as strings para setTimeoutou setInterval". Se você ainda não leu o "JavaScript: The Good Parts", faça o mesmo agora. Você não vai se arrepender.
precisa saber é o seguinte
13
@MattDMo "Alguém disse que era ruim" não é realmente um argumento.
Casey
4
@emodendroket Presumo que você não esteja ciente de quem é Douglas Crockford .
precisa saber é o seguinte
13
@MattDMo Estou plenamente ciente de quem ele é, mas ele é um ser humano, não um deus.
Casey
2
@tggagne: O que posso fazer para que ele funcione em vários domínios? (script de carregamento de http://web.archive.org/web/20140905044059/http://www.howtocreate.co.uk/operaStuff/userjs/aagmfunctions.js)
user2284570
21

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

Eu uso rodas dentadas (não sei se existem outros). Você constrói seu código JavaScript em arquivos separados e inclui comentários que são processados ​​pelo mecanismo Sprockets como inclui. Para o desenvolvimento, você pode incluir arquivos seqüencialmente e, em seguida, para a produção mesclá-los ...

Veja também:

JMawer
fonte
O Browserify é muito mais popular que o Sprockets.
Dan Dascalescu
18

Eu tinha 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, primeiro myvariables.js, 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 usava uma variável em um arquivo JavaScript em outro arquivo JavaScript, mas não precisava incluir uma em outro. Eu só precisava garantir que o primeiro arquivo JavaScript carregado antes do segundo arquivo JavaScript e as variáveis ​​do primeiro arquivo JavaScript estivessem acessíveis no segundo arquivo JavaScript automaticamente.

Isso salvou meu dia. Eu espero que isso ajude.

Manohar Reddy Poreddy
fonte
O problema com esta resposta é que não é algo parecido import. Você precisa de um arquivo HTML para obter coisas de um arquivo js para outro.
Cannicide
Muito verdadeiro. É isso que algumas outras respostas estão tendo como soluções. No entanto, eu tinha dois arquivos JS, um deve usar outras variáveis ​​de JS. Nenhum node.js, next.js, express.js, etc., portanto, importar ou exigir não funcionará, apenas tinha arquivos .js simples.
Manohar Reddy Poreddy 17/10/19
Compreensível, no entanto, a questão é realmente importar um arquivo javascript para outro arquivo, não apenas acessar suas variáveis ​​usando um arquivo HTML. Por exemplo, suponha que você esteja criando funcionalidade para um botão e use três arquivos js diferentes, um para manipulação de cliques, um para manipulação instantânea, um para os retornos de chamada de cada um dos outros dois. Seria útil importar os outros dois js no terceiro js e ter apenas uma <script>tag. Isso pode ajudar na organização. Essa resposta simplesmente não é o que a pergunta estava pedindo e não é ideal nesse contexto.
Cannicide
Quando procurei a solução para o meu problema, procurei da maneira certa; no entanto, o Google acha que essa é a página correta, então cheguei aqui. Por isso escrevi minha resposta aqui. Parece que, eu fiz certo, devido a 15 votos acima. Para não desperdiçar o tempo de outras pessoas, coloquei um começo claro sobre qual é o meu cenário - coloquei o código HTML primeiro - que parece ter ajudado, já que você respondeu e disse que o html não é o seu cenário. Espero que tenha esclarecido.
Manohar Reddy Poreddy 19/10/19
Sim - de fato, parece que algumas pessoas procuraram por um problema ligeiramente diferente, para o qual essa é uma solução, e encontraram isso. Embora essa não seja necessariamente a resposta para essa pergunta, definitivamente é a resposta para outra pergunta semelhante. Como tal, é bom ter esta resposta aqui, pois ajuda aqueles que estavam procurando por essa resposta. Obrigado por essa resposta, que a esclareceu.
Cannicide 19/10/19
16

Caso você esteja usando Trabalhadores da Web e queira incluir scripts adicionais no escopo do trabalhador, as outras respostas fornecidas sobre a adição de scripts aohead tag 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 destaca a segunda resposta mais votada para sua pergunta , o RequireJS também pode lidar com a inclusão de scripts dentro de um Web Worker (provavelmente se chamando importScripts, mas com alguns outros recursos úteis).

Turnerj
fonte
16

Na linguagem moderna, com a verificação se o script já foi carregado, seria:

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

Uso (assíncrono / aguardar):

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

ou

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

Uso (Promessa):

loadJs("https://.../script.js").then(res => {}).catch(err => {})
Dmitry Sheiko
fonte
Agradável. Boa solução.
Naftali tcp Neal
Conciso e precisa apenas do ES5 e evita formalmente uma ligação. Obrigado Dmitry!
Eureka
Uau, funciona no navegador sem servidor. pi.js = simplesmente var pi = 3.14. chamar a função loadJS () vialoadJs("pi.js").then(function(){ console.log(pi); });
zipzit 7/17/17
14

A @importsintaxe para obter a importação de JavaScript do tipo CSS é possível usando uma ferramenta como o Mixture por meio de seu .mixtipo de arquivo especial (veja aqui ). Eu imagino que o aplicativo simplesmente use um dos métodos mencionados acima de forma interativa, embora eu não saiba.

Na documentação do Mixture em .mixarquivos:

Os arquivos de mistura são simplesmente arquivos .js ou .css com .mix. no nome do arquivo. Um arquivo mix simplesmente amplia a funcionalidade de um estilo normal ou arquivo de script e permite importar e combinar.

Aqui está um .mixarquivo de exemplo que combina vários .jsarquivos em um:

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

A mistura produz isso como scripts-global.jse também como uma versão minificada (scripts-global.min.js ).

Nota: Eu não sou afiliado de maneira alguma ao Mixture, além de usá-lo como uma ferramenta de desenvolvimento front-end. Me deparei com esta questão ao ver um.mix arquivo JavaScript em ação (em um dos clichês do Mixture) e ficar um pouco confuso com ele ("você pode fazer isso?", Pensei comigo mesmo). Então percebi que era um tipo de arquivo específico do aplicativo (um pouco decepcionante, concordou). No entanto, percebi que o conhecimento pode ser útil para outras pessoas.

ATUALIZAÇÃO : A mistura agora é gratuita (offline).

ATUALIZAÇÃO : A mistura está descontinuada. Versões antigas de mistura ainda estão disponíveis

Isaac Gregson
fonte
Isso seria incrível se fosse um módulo de nó.
b01
@ b01 Parece um desafio;) Se ao menos eu tivesse tempo ... talvez alguém o faça?
Isaac Gregson
13
var js = document.createElement("script");

js.type = "text/javascript";
js.src = jsFilePath;

document.body.appendChild(js);
Sam4Code
fonte
2
Este é o código mais simples, mas falhará em alguns casos extremos quando bodyainda não existe ou não pode ser modificado. Além disso, ajuda a explicar as respostas.
Dan Dascalescu
13

Meu método usual é:

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

Ele funciona muito bem e não usa recargas de página para mim. Eu tentei o método AJAX (uma das outras respostas), mas ele não parece funcionar tão bem para mim.

Aqui está uma explicação de como o código funciona para aqueles que são curiosos: essencialmente, ele cria uma nova tag de script (após a primeira) da URL. Ele define o modo assíncrono para não bloquear o restante do código, mas chama um retorno de chamada quando o readyState (o estado do conteúdo a ser carregado) muda para 'carregado'.

Christopher Dumas
fonte
13

Embora essas respostas sejam ótimas, existe uma "solução" simples que existe desde o carregamento do script, e cobrirá 99,999% dos casos de uso da maioria das pessoas. Basta incluir o script necessário antes do script que o requer. Para a maioria dos projetos, não demora muito para determinar quais scripts são necessários e em que ordem.

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

Se script2 requer script1, essa é realmente a maneira mais fácil de fazer algo assim. Estou muito surpreso que ninguém tenha levantado isso, pois é a resposta mais óbvia e mais simples que será aplicada em quase todos os casos.

KthProg
fonte
1
Acho que para muitas pessoas, inclusive eu, precisamos de um nome de arquivo dinâmico.
Stuart McIntyre
1
@StuartMcIntyre, nesse caso, defina o atributo src da tag de script em tempo de execução e aguarde o evento onload (é claro que existem soluções melhores nesse caso em 2019).
KthProg 17/07/19
12

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

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);
})();
Vicky Gonsalves
fonte
10

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

Ale
fonte
10

Existem muitas respostas possíveis para essa pergunta. Minha resposta é obviamente baseada em várias delas. Foi isso que acabei depois de ler todas as respostas.

O problema $.getScripte realmente qualquer outra solução que exija retorno de chamada quando o carregamento estiver concluído é que, se você tiver vários arquivos que o utilizam e dependem um do outro, não terá mais como saber quando todos os scripts foram carregados (uma vez aninhados em vários arquivos).

Exemplo:

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

Você está certo quando diz que pode especificar o Ajax para executar de forma síncrona ou usar XMLHttpRequest , mas a tendência atual parece ser descontinuar solicitações síncronas, portanto, talvez você não obtenha suporte total ao navegador agora ou no futuro.

Você pode tentar usar $.whenpara verificar uma matriz de objetos adiados, mas agora está fazendo isso em todos os arquivos e o arquivo2 será considerado carregado assim que $.whennão for executado quando o retorno de chamada for executado, portanto, o arquivo1 ainda continuará a execução antes do carregamento do arquivo3 . Isso realmente ainda tem o mesmo problema.

Decidi voltar ao invés de avançar. Obrigado document.writeln. Eu sei que é um tabu, mas contanto que seja usado corretamente, isso funcionará bem. Você acaba com um código que pode ser depurado facilmente, exibido corretamente no DOM e pode garantir a ordem em que as dependências são carregadas corretamente.

Obviamente, você pode usar $ ("body"). Append (), mas não poderá mais depurar corretamente.

NOTA: Você deve usá-lo apenas enquanto a página estiver carregando, caso contrário, você verá uma tela em branco. Em outras palavras, sempre coloque-o antes / fora do documento.ready . Eu não testei usando isso depois que a página foi carregada em um evento de clique ou algo assim, mas tenho certeza que ela falhará.

Gostei da idéia de estender o jQuery, mas obviamente você não precisa.

Antes de chamar document.writeln, ele verifica se o script ainda não foi carregado, avaliando todos os elementos do script.

Presumo que um script não seja totalmente executado até que seu document.readyevento seja executado. (Eu sei que o uso document.readynão é obrigatório, mas muitas pessoas o usam, e lidar com isso é uma salvaguarda.)

Quando os arquivos adicionais são carregados, os document.readyretornos de chamada são executados na ordem errada. Para resolver isso quando um script é realmente carregado, o script que o importou é reimportado e a execução é interrompida. Isso faz com que o arquivo de origem agora tenha seu document.readyretorno de chamada executado após qualquer um dos scripts importados.

Em vez dessa abordagem, você poderia tentar modificar o jQuery readyList, mas essa parecia uma solução pior.

Solução:

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

Uso:

Arquivo3:

var f3obj = "file3";

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

Arquivo2:

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

Arquivo1:

$.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
fonte
É exatamente o que a resposta atualmente aceita afirma: apenas não é suficiente.
Cannicide 2/02
A principal diferença é que, se houver uma dependência ausente, a tag de script será adicionada para a dependência, também a tag de script para o arquivo de chamada e lançará um erro que interrompe a execução. Isso faz com que os scripts sejam processados ​​e executados na ordem correta e elimina a necessidade de retornos de chamada. Portanto, o script dependente será carregado e executado antes do script de chamada enquanto suporta o aninhamento.
Curlyhairedgenius
Quanto a "a tendência atual parece depreciar solicitações síncronas", isso é verdade apenas porque muitos desenvolvedores as usaram incorretamente e fizeram os usuários esperar desnecessariamente. No entanto, se a solicitação for naturalmente síncrona, como uma instrução Include, o Ajax síncrono simples é adequado. Criei uma função geral de extensão JavaScript que executa de forma síncrona funções como a leitura de um arquivo que não faz parte do JavaScript executando um arquivo "servidor" PHP e acho muito útil ao escrever aplicativos usando JavaScript. Nenhum servidor da web local é necessário para esse Ajax.
David Spector
10

Existem várias maneiras de implementar módulos em Javascript. Aqui estão as 2 mais populares:

Módulos ES6

Os navegadores ainda não oferecem suporte a esse sistema de modulação. Para usar essa sintaxe, você deve usar um bundler como o webpack. O uso de um bundler é melhor de qualquer maneira, pois isso pode combinar todos os seus arquivos diferentes em um único arquivo (ou em dois). Isso servirá os arquivos do servidor para o cliente mais rapidamente, pois cada solicitação HTTP possui alguma sobrecarga associada. Assim, ao reduzir a solicitação HTTP geral, melhoramos o desempenho. Aqui está um exemplo dos módulos 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 (usado no NodeJS)

Este sistema de modulação é usado no NodeJS. Você basicamente adiciona suas exportações a um objeto chamado module.exports. Você pode acessar esse objeto através de um require('modulePath'). Importante aqui é perceber que esses módulos estão sendo armazenados em cache; portanto, se você tiver require()um determinado módulo duas vezes, ele retornará o módulo já criado.

// 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
Willem van der Veen
fonte
9

Cheguei a essa pergunta porque estava procurando uma maneira simples de manter uma coleção de plugins JavaScript úteis. Depois de ver algumas das soluções aqui, eu vim com isso:

  1. Configure um arquivo chamado "plugins.js" (ou extensions.js ou o que você quiser). Mantenha seus arquivos de plug-in junto com esse único arquivo mestre.

  2. plugins.js terá uma matriz chamada na pluginNames[]qual iremos iterar e each(), em seguida, anexar uma <script>tag na cabeça de cada plug-in

//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. Chame manualmente apenas o arquivo em sua cabeça:
    <script src="js/plugins/plugins.js"></script>

MAS:

Embora todos os plugins sejam inseridos na tag head da maneira que deveriam, eles nem sempre são executados pelo navegador quando você clica na página ou atualiza.

Descobri que é mais confiável escrever apenas as tags de script em um PHP include. Você só precisa escrevê-lo uma vez e isso funciona tanto quanto chamar o plugin usando JavaScript.

rgb_life
fonte
@ Will, sua solução parece muito mais limpa que a minha e estou preocupada com alguns erros se usar a minha, pois utiliza .append (). Então, para usar isso, você pode chamar essa função apenas uma vez para cada arquivo de plug-in que deseja incluir?
Rgb_life 01/12/11