Require.js ile DOM'da yalnızca bir <script> öğesi oluşturma arasındaki fark nedir? [kapalı]


138

Require.JS amd kullanarak DOM'da bir <script>öğe oluşturmak arasındaki fark nedir ?

Require.JS anlayışım, bağımlılıkları yükleme yeteneği sunuyor, ancak bu sadece <script>gerekli harici JS dosyasını yükleyen bir öğe oluşturarak yapılamaz mı?

Örneğin, işlevi doStuff()gerektiren bir işleve sahip olduğumu varsayalım needMe(). doStuff()harici dosyada do_stuff.js, needMe()harici dosyada need_me.js.

Bunu Require.JS yöntemini kullanarak:

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

Bunu bir komut dosyası öğesi oluşturarak yapın:

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
}

Her ikisi de çalışıyor. Ancak, ikinci sürüm tüm Require.js kitaplığını yüklememi gerektirmez. İşlevsel bir fark görmüyorum ...


1
tarayıcı önbelleğe alma hakkında ne, requirjs buna müdahale ediyor mu?
Muhammed Umer

Bunu tekrar açıyorum çünkü çok benzer iki şey arasındaki farkı istiyor. Bu olabilir objektif olarak cevaplanması ve tbh ben onun içine nereye görüşü bağları görmüyorum.
RamenChef

Yanıtlar:


43

İşte ajaxian.com'da neden kullanıldığına dair güzel makale:

RequireJS: Eşzamansız JavaScript yükleme

  • bir çeşit # dahil / ithalat / gerektirir
  • iç içe bağımlılıkları yükleme yeteneği
  • geliştirici için kullanım kolaylığı, ancak daha sonra konuşlandırmaya yardımcı olan bir optimizasyon aracı ile desteklenir

2
Bunları okumuştum, ama şimdi daha çok düşündüğüm için, iç içe bağımlılık fikrinin sadece <script> etiketleri yazarak elde edilemeyeceğini anlıyorum. Teşekkürler.
maxedison

37
"geliştirici için kullanım kolaylığı" gerçeğinden uzak olamazdı. Sizin ve bu projede çalışmaya gelecek olan herkes için kesinlikle dik bir öğrenme eğrisi var.
Sahat Yalkabov

3
@ TwilightPony Kendimi o kadar parlak değil sanıyorum ve requirjs benim için zor bir şey değildi. Bağımlılıklar konusunda endişelenmenize gerek kalmaz ve sayfayı hızlandırır. Kodunuz, kişisel olarak canlandırıcı ve basit bulduğum bağımlılıklarınızı nasıl beyan ettiğiniz konusunda sunucu tarafı programlamayla daha fazla satır içi hale gelir. Sözdizimi minimaldir ve tasarımla kapatılmıştır, daha sonra komut dosyalarınızı kolayca birleştirmek için üretim için yol haritasını belirler. Bunun yanı sıra hata ayıklama statik bildirimler gibidir. Bundan daha kolay ne olduğundan emin değilim. Diğer şekilde yaptığım gibi çok daha zor.
Jason Sebring

Çabalıyorum. Özellikle küresel nesnelere bağlanmaya çalışan modüller ile. (Reaksiyon modülleri) ...
15'te geilt

1
Bu sayfadaki yorumlar aslında bana ihtiyaçtan kaçınmak ve kaçmak gerektiğini hissettirdi. Özellikle alt kısımda bulunan ve stevesouders.com/tests/require.php adresine
Dave Kanter

52

Require.JS, DOM'de bir öğe oluşturmaya kıyasla ne gibi avantajlar sunar?

Örneğinizde , komut dosyası etiketini eşzamansız olarak oluşturuyorsunuz. Bu , need_me.js dosyasının yüklenmesi bitmedenneedMe() işlevinizin çağrılması anlamına gelir . Bu, işlevinizin tanımlanmadığı durumlarda yakalanmamış istisnalarla sonuçlanır.

Bunun yerine, önerdiğiniz şeyin gerçekte çalışmasını sağlamak için şöyle bir şey yapmanız gerekir:

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

}

Muhtemelen, RequireJS gibi bir paket yöneticisi kullanmak veya yukarıda gösterildiği gibi saf JavaScript stratejisini kullanmak en iyisi olabilir veya olmayabilir. Web uygulamanız daha hızlı yüklenebilir, ancak bu eylem gerçekleştirilmeden önce kaynakların yüklenmesini beklemeyi içereceğinden, sitedeki işlevsellik ve özelliklerin çağrılması daha yavaş olacaktır.

Bir Web uygulaması tek sayfalık bir uygulama olarak oluşturulmuşsa, insanların sayfayı çok sık yeniden yüklemeyeceklerini düşünün. Bu durumlarda, her şeyi önceden yüklemek , uygulamayı kullanırken deneyimin daha hızlı görünmesine yardımcı olur . Bu gibi durumlarda haklısınız, sadece komut dosyası etiketlerini sayfanın başına veya gövdesine ekleyerek yalnızca tüm kaynakları yükleyebilirsiniz.

Ancak, bir sayfanın sayfadan geçiş yaptığı ve kaynakların yeniden yüklenmesine neden olduğu daha geleneksel bir modeli izleyen bir web sitesi veya Web uygulaması oluşturmak, tembel yükleme yaklaşımı bu geçişleri hızlandırmaya yardımcı olabilir.


10

RequireJS kullanımının mantıklı olmasının bazı başka sivri nedenleri:

  1. Kendi bağımlılıklarınızı yönetmek, büyük projeler için hızla ayrılıyor.
  2. İstediğiniz kadar küçük dosyaya sahip olabilirsiniz ve bağımlılıkları veya yükleme sırasını takip etme konusunda endişelenmenize gerek yoktur.
  3. RequireJS, pencere nesnesine dokunmadan tüm modüler bir uygulamanın yazılmasını mümkün kılar.

Alındığı bu Gist burada rmurphey yorumlarından .

Soyutlama katmanları öğrenmek ve uyum sağlamak için bir kabus olabilir, ancak bir amaca hizmet edip iyi yaptığında, mantıklıdır.


9
Tüm bu gereksinimleri yönetmeniz ve tanımlamaları, yapılandırma dosyalarını, AMD belirtimini uygulamayan diğer sistem ve kitaplıklarla çakışmaları vb. Yönetmeniz gerekir. Bir düğüm-webkit projesinde Require.JS ve Require.JS kullanmayı denedim. Bana yolun her adımında savaştı ... Bunu basitçe komut dosyaları sipariş ederek belirli bir şekilde tezatlayın ... Tabii ki Require.JS ile tembel yükleme kazanıyorsunuz, bu yüzden onu çalıştırmayı denedim. :)
jmort253

@ Jmort253 ile tamamen katılıyorum, başlangıçta bir mücadeleydi, ama şimdi çok beğendim. Her üç nokta da doğrudur! Ve bir kütüphaneyi AMD etmek o kadar da zor olmamalı ... ya da şimi kullanmamalı.
Efsaneler

0

İşte daha somut bir örnek.

60 dosyadan oluşan bir projede çalışıyorum. Çalıştırmak için 2 farklı modumuz var.

  1. Birleştirilmiş bir sürüm, 1 büyük dosya yükleyin. (Üretim)

  2. 60 dosyanın tümünü yükle (geliştirme)

Bir yükleyici kullanıyoruz, böylece web sayfasında sadece bir komut dosyası var

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

Bu, varsayılan olarak # 1 (büyük bir birleştirilmiş dosyayı yükleyerek) moduna geçer. # 2 modunda (ayrı dosyalar) çalıştırmak için bazı bayraklar ayarladık. Herhangi bir şey olabilir. Sorgu dizesinde bir anahtar. Bu örnekte sadece bunu yapıyoruz

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

loader.js şöyle görünüyor

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

Derleme betiği sadece şuna benzer bir .sh dosyasıdır

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

vb...

Yeni bir dosya eklenirse, geliştirme yaptığımızdan # 2 modunu injectScript("somenewfile.js")kullanacağız. Loader.js'ye bir satır eklemeliyiz

Sonra üretim için daha sonra derleme betiğimize somenewfile.js'yi eklemeliyiz. Sıklıkla unuttuğumuz ve daha sonra hata mesajları aldığımız bir adım.

AMD'ye geçerek 2 dosyayı düzenlememiz gerekmiyor. Loader.js ve oluşturma komut dosyasını senkronize tutma sorunu ortadan kalkar. Kullanarak r.jsveya webpacksadece oluşturmak için kodu okuyabilirlarge-concantinated.js

Ayrıca bağımlılıklarla da başa çıkabilir, örneğin lib1.js ve lib2.js gibi 2 dosya yükledik

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

lib2'nin lib1'e ihtiyacı var. İçinde gibi bir şey yapan bir kod var

lib1Api.installPlugin(...);

Ancak, enjekte edilen komut dosyaları eşzamansız olarak yüklendiğinden, doğru sırada yükleneceklerinin garantisi yoktur. Bu 2 komut dosyası AMD komut dosyaları değildir ancak requir.js kullanarak bağımlılıklarını söyleyebiliriz

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

Ben lib1 kullanan modülümüz bunu yapıyoruz

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

Şimdi requir.js bizim için komut dosyaları enjekte edecek ve lib2 yüklenene kadar lib2 yüklenmeyecek çünkü lib2'nin lib1'e bağlı olduğunu söylemiştik. Hem lib2 hem de lib1 yüklenene kadar lib1 kullanan modülümüzü başlatmaz.

Bu geliştirmeyi güzelleştirir (derleme adımı yok, yükleme sırası hakkında endişelenmeyin) ve üretimi güzelleştirir (eklenen her komut dosyası için bir derleme komut dosyasını güncellemeye gerek yoktur).

Ek bir bonus olarak, eski tarayıcılar için kod üzerinden babil çalıştırmak için webpack'in babel eklentisini kullanabiliriz ve yine bu yapı komut dosyasını da korumak zorunda değiliz.

Chrome (tercih edilen tarayıcımız) importgerçek anlamda desteklemeye başlarsa, muhtemelen geliştirme için buna geçeceğimizi, ancak bunun gerçekten hiçbir şey değiştirmeyeceğini unutmayın. Birleştirilmiş bir dosya yapmak için web paketini kullanmaya devam edebiliriz ve tüm tarayıcılar için kod üzerinden babel çalıştırmak için kullanabiliriz.

Tüm bunlar komut dosyası etiketleri kullanılmadan ve AMD kullanılarak elde edilir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.