Qual è la differenza tra Require.js e la semplice creazione di un elemento <script> nel DOM? [chiuso]


138

Qual è la differenza tra l'utilizzo di Require.JS e la semplice creazione di un <script>elemento nel DOM?

La mia comprensione di Require.JS è che offre la possibilità di caricare dipendenze, ma ciò non può essere fatto semplicemente creando un <script>elemento che carica il file JS esterno necessario?

Ad esempio, supponiamo che io abbia la funzione doStuff(), che richiede la funzione needMe(). doStuff()è nel file esterno do_stuff.js, mentre needMe()è nel file esterno need_me.js.

In questo modo Require.JS:

define(['need_me'],function(){
    function doStuff(){
        //do some stuff
        needMe();
        //do some more stuff
    }
});

In questo modo semplicemente creando un elemento di script:

function doStuff(){
    var scriptElement  = document.createElement('script');
    scriptElement.src = 'need_me.js';
    scriptElement.type = 'text/javascript';
    document.getElementsByTagName('head')[0].appendChild(scriptElement);

    //do some stuff
    needMe();
    //do some more stuff
}

Entrambi funzionano. Tuttavia, la seconda versione non mi richiede di caricare tutta la libreria Require.js. Non vedo davvero alcuna differenza funzionale ...


1
che dire della memorizzazione nella cache del browser, richiedejs interferire con esso?
Muhammad Umer,

Sto riaprendo questo perché sta chiedendo la differenza tra due cose molto simili. Si può rispondere obiettivamente, e non vedo dove l'opinione si lega ad essa.
RamenChef,

Risposte:


43

Ecco il bell'articolo su ajaxian.com sul perché usarlo:

RequireJS: caricamento JavaScript asincrono

  • una sorta di # include / importa / richiede
  • capacità di caricare dipendenze nidificate
  • facilità d'uso per gli sviluppatori ma supportata da uno strumento di ottimizzazione che aiuta la distribuzione

2
Avevo letto quelli, ma ora che ci penso più mi rendo conto che l'idea delle dipendenze nidificate non può essere raggiunta semplicemente scrivendo tag <script>. Grazie.
maxedison,

37
La "facilità d'uso per gli sviluppatori" non potrebbe essere più lontana dalla verità. Ha sicuramente una ripida curva di apprendimento per te e chiunque altro verrà a lavorare in quel progetto.
Sahat Yalkabov,

3
@TwilightPony Non mi considero così brillante e requis non era davvero una cosa difficile da ottenere per me. Ti elimina la necessità di preoccuparti delle dipendenze e accelera la pagina. Il tuo codice diventa più in linea con la programmazione lato server nel modo in cui dichiari le tue dipendenze che personalmente trovo rinfrescanti e semplici. La sintassi era minima e il design era improntato alla chiusura, quindi imposta la roadmap per la produzione per combinare facilmente i tuoi script. Inoltre, il debug è proprio come le dichiarazioni statiche. Non sono sicuro di cosa sia più facile di così. Molto più difficile nell'altro modo come ho fatto nell'altro modo.
Jason Sebring,

Faccio fatica. Soprattutto con i moduli che provano ad attaccarsi agli oggetti globali. (Reagisci moduli) ...
geilt

1
I commenti su quella pagina in realtà mi hanno lasciato la sensazione che si dovrebbe scappare da e non verso necessità. Soprattutto quello vicino al fondo che collega a stevesouders.com/tests/require.php
Dave Kanter,

52

Quali vantaggi offre Require.JS rispetto alla semplice creazione di un elemento nel DOM?

Nel tuo esempio, stai creando il tag di script in modo asincrono, il che significa che la tua needMe()funzione verrebbe invocata prima che il file need_me.js finisca il caricamento. Ciò comporta eccezioni non rilevate in cui la funzione non è definita.

Invece, per far funzionare effettivamente ciò che stai suggerendo, dovresti fare qualcosa del genere:

function doStuff(){
    var scriptElement  = document.createElement('script');
    scriptElement.src = 'need_me.js';
    scriptElement.type = 'text/javascript';

    scriptElement.addEventListener("load", 
        function() { 
            console.log("script loaded - now it's safe to use it!");

            // do some stuff
            needMe();
            //do some more stuff

        }, false);

    document.getElementsByTagName('head')[0].appendChild(scriptElement);

}

Probabilmente, potrebbe essere meglio usare un gestore di pacchetti come RequireJS o utilizzare una strategia puramente JavaScript come dimostrato sopra. Sebbene l'applicazione Web possa essere caricata più rapidamente, il richiamo delle funzionalità e delle funzionalità sul sito sarebbe più lento poiché implicherebbe l'attesa del caricamento delle risorse prima che tale azione possa essere eseguita.

Se un'applicazione Web viene creata come app a pagina singola, considera che le persone non ricaricano la pagina molto spesso. In questi casi, il precaricamento di tutto contribuirebbe a rendere l'esperienza più veloce quando si utilizza effettivamente l'app. In questi casi, hai ragione, puoi semplicemente caricare tutte le risorse semplicemente includendo i tag di script nella testa o nel corpo della pagina.

Tuttavia, se si crea un sito Web o un'applicazione Web che segue il modello più tradizionale in cui si passa da una pagina all'altra, causando il ricaricamento delle risorse, un approccio a caricamento lento può aiutare ad accelerare queste transizioni.


10

Alcuni altri motivi molto evidenti per cui ha senso usare RequireJS:

  1. La gestione delle proprie dipendenze cade rapidamente a pezzi per progetti considerevoli.
  2. Puoi avere tutti i file di piccole dimensioni che desideri e non devi preoccuparti di tenere traccia delle dipendenze o dell'ordine di caricamento.
  3. RequireJS consente di scrivere un'intera app modulare senza toccare l'oggetto finestra.

Tratto dai commenti di rmurphey qui in questo Gist .

Gli strati di astrazione possono essere un incubo per imparare e adattarsi, ma quando serve uno scopo e lo fa bene, ha senso.


9
Devi ancora gestire tutti questi requisiti e definire istruzioni, file di configurazione, collisioni con altri sistemi e librerie che non hanno implementato la specifica AMD, ecc. Ho provato a utilizzare Require.JS in un progetto nodo-webkit e Require.JS mi ha combattuto ad ogni passo ... Contrasto che con il semplice ordinamento di script in un certo modo ... Certo, si ottiene un caricamento lento con Require.JS, motivo per cui ho provato a farlo funzionare. :)
jmort253,

Sono totalmente d'accordo con @ jmort253, all'inizio è stata una lotta, ma ora mi piace molto. Tutti e tre i punti sono corretti! E AMDificare una libreria non dovrebbe essere così difficile ... o usare lo spessore.
Leggende

0

Ecco un esempio più concreto.

Sto lavorando a un progetto con 60 file. Abbiamo 2 diverse modalità di esecuzione.

  1. Carica una versione concatenata, 1 file di grandi dimensioni. (Produzione)

  2. Carica tutti i 60 file (sviluppo)

Stiamo usando un caricatore, quindi abbiamo solo uno script nella pagina web

<script src="loader.js"></script>

L'impostazione predefinita è la modalità n. 1 (caricamento di un file concatenato di grandi dimensioni). Per eseguire la modalità in # 2 (file separati) impostiamo alcuni flag. Potrebbe essere qualsiasi cosa. Una chiave nella stringa di query. In questo esempio lo facciamo e basta

<script>useDebugVersion = true;</script>
<script src="loader.js"></script>

loader.js è simile a questo

if (useDebugVersion) {
   injectScript("app.js");
   injectScript("somelib.js");
   injectScript("someotherlib.js");
   injectScript("anotherlib.js");
   ... repeat for 60 files ...
} else {
   injectScript("large-concatinated.js");
}

Lo script di compilazione è solo un file .sh che assomiglia a questo

cat > large-concantinated.js app.js somelib.js someotherlib.js anotherlib.js

eccetera...

Se viene aggiunto un nuovo file, probabilmente useremo la modalità # 2 poiché stiamo facendo lo sviluppo, dobbiamo aggiungere una injectScript("somenewfile.js")riga a loader.js

Successivamente, per la produzione, dobbiamo anche aggiungere somenewfile.js al nostro script di build. Un passaggio che spesso dimentichiamo e quindi riceviamo messaggi di errore.

Passando ad AMD non è necessario modificare 2 file. Il problema di mantenere sincronizzati loader.js e lo script di compilazione scompare. Utilizzando r.jso webpacksi può semplicemente leggere il codice per crearelarge-concantinated.js

Può anche gestire le dipendenze, ad esempio abbiamo caricato 2 file lib1.js e lib2.js in questo modo

injectScript("lib1.js");
injectScript("lib2.js");

lib2 ha bisogno di lib1. Ha un codice all'interno che fa qualcosa di simile

lib1Api.installPlugin(...);

Ma poiché gli script iniettati vengono caricati in modo asincrono, non vi è alcuna garanzia che vengano caricati nell'ordine corretto. Questi 2 script non sono script AMD, ma utilizzando Requis.js possiamo dirgli le loro dipendenze

require.config({
    paths: {
        lib1: './path/to/lib1',
        lib2: './path/to/lib2',
    },
    shim: {
        lib1: {
            "exports": 'lib1Api',
        },
        lib2: {
            "deps": ["lib1"],
        },
    }
});

Nel nostro modulo che usa lib1 lo facciamo

define(['lib1'], function(lib1Api) {
   lib1Api.doSomething(...);
});

Ora request.js inietterà gli script per noi e non inietterà lib2 fino a quando non sarà caricato lib1 poiché gli abbiamo detto che lib2 dipende da lib1. Inoltre non avvierà il nostro modulo che utilizza lib1 fino a quando non sono stati caricati sia lib2 che lib1.

Questo rende piacevole lo sviluppo (nessuna fase di compilazione, nessuna preoccupazione per l'ordine di caricamento) e rende piacevole la produzione (non è necessario aggiornare uno script di compilazione per ogni script aggiunto).

Come bonus aggiuntivo possiamo usare il plug-in babel di webpack per eseguire babel sul codice per i browser più vecchi e anche in questo caso non è necessario mantenere lo script di build.

Se Chrome (il nostro browser preferito) inizia a supportare importdavvero, probabilmente passeremmo a quello per lo sviluppo, ma ciò non cambierebbe nulla. Potremmo ancora usare il webpack per creare un file concatenato e potremmo usarlo eseguendo babel sul codice per tutti i browser.

Tutto ciò si ottiene non usando i tag di script e usando AMD

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.