Apa perbedaan antara Require.js dan cukup membuat elemen <script> di DOM? [Tutup]

138

Apa perbedaan antara menggunakan Require.JS dan hanya membuat <script>elemen di DOM?

Pemahaman saya tentang Require.JS adalah bahwa ia menawarkan kemampuan untuk memuat dependensi, tetapi dapatkah ini tidak dilakukan dengan membuat <script>elemen yang memuat file JS eksternal yang diperlukan?

Misalnya, mari kita asumsikan saya memiliki fungsi doStuff(), yang membutuhkan fungsi needMe(). doStuff()ada di file eksternal do_stuff.js, sedangkan needMe()di file eksternal need_me.js.

Melakukan ini dengan cara Require.JS:

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

Melakukan ini hanya dengan membuat elemen skrip:

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
}

Keduanya bekerja. Namun, versi kedua tidak mengharuskan saya untuk memuat semua perpustakaan Require.js. Saya tidak benar-benar melihat perbedaan fungsional ...

maxedison
sumber
1
bagaimana dengan caching browser, apakah needsejs mengganggu?
Muhammad Umer
Saya membuka kembali ini karena meminta perbedaan antara dua hal yang sangat mirip. Itu bisa dijawab secara objektif, dan tbh saya tidak tahu di mana pendapat itu ada hubungannya.
RamenChef

Jawaban:

43

Inilah artikel bagus di ajaxian.com tentang mengapa menggunakannya:

RequireJS: Asynchronous JavaScript loading

  • semacam # include / import / butuhkan
  • kemampuan memuat dependensi bersarang
  • kemudahan penggunaan untuk pengembang tetapi kemudian didukung oleh alat optimisasi yang membantu penyebaran
Sarfraz
sumber
2
Saya telah membaca itu, tetapi sekarang setelah saya memikirkannya lebih saya menyadari bahwa gagasan dependensi bersarang tidak dapat dicapai dengan hanya menulis tag <script>. Terima kasih.
maxedison
37
"kemudahan penggunaan untuk pengembang" tidak bisa lebih jauh dari kebenaran. Ini pasti memiliki kurva belajar yang curam untuk Anda dan siapa pun yang akan datang untuk bekerja di proyek itu.
Sahat Yalkabov
3
@ TightightPony Saya menganggap diri saya tidak secerah itu dan tidak terlalu sulit untuk saya dapatkan. Ini menghilangkan Anda harus khawatir tentang ketergantungan dan mempercepat halaman. Kode Anda menjadi lebih sejalan dengan pemrograman sisi server dalam cara Anda mendeklarasikan ketergantungan Anda yang menurut saya pribadi menyegarkan dan sederhana. Sintaksnya minimal dan ditutup dengan desain kemudian menetapkan roadmap untuk produksi untuk dengan mudah menggabungkan skrip Anda. Selain itu debugging seperti deklarasi statis. Tidak yakin apa yang lebih mudah dari itu. Jauh lebih sulit dengan cara lain seperti yang saya lakukan dengan cara lain.
Jason Sebring
Saya berjuang. Terutama dengan modul yang mencoba melampirkan diri ke objek global. (Bereaksi modul) ...
geilt
1
Komentar pada halaman itu benar-benar membuat saya merasa bahwa seseorang harus melarikan diri dan tidak ke arah keharusan. Terutama yang di dekat bagian bawah yang terhubung ke stevesouders.com/tests/require.php
Dave Kanter
52

Apa keuntungan yang ditawarkan Require.JS dibandingkan dengan hanya membuat elemen di DOM?

Dalam contoh Anda, Anda membuat tag skrip secara asinkron, yang artinya needMe()fungsi Anda akan dipanggil sebelum file need_me.js selesai memuat. Ini menghasilkan pengecualian tanpa tertangkap di mana fungsi Anda tidak didefinisikan.

Alih-alih, untuk membuat apa yang Anda sarankan benar-benar berfungsi, Anda harus melakukan sesuatu seperti ini:

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

}

Dapat diperdebatkan, mungkin atau mungkin tidak terbaik untuk menggunakan manajer paket seperti RequireJS atau untuk menggunakan strategi murni JavaScript seperti yang ditunjukkan di atas. Meskipun aplikasi Web Anda dapat memuat lebih cepat, menjalankan fungsi dan fitur di situs akan lebih lambat karena melibatkan menunggu sumber daya dimuat sebelum tindakan itu dapat dilakukan.

Jika aplikasi Web dibangun sebagai aplikasi satu halaman, maka pertimbangkan bahwa orang tidak akan benar-benar memuat ulang halaman tersebut terlalu sering. Dalam kasus ini, preloading semuanya akan membantu membuat pengalaman tampak lebih cepat ketika benar - benar menggunakan aplikasi. Dalam kasus ini, Anda benar, seseorang hanya dapat memuat semua sumber daya hanya dengan memasukkan tag skrip di kepala atau badan halaman.

Namun, jika membangun situs web atau aplikasi Web yang mengikuti model yang lebih tradisional di mana satu transisi dari halaman ke halaman, menyebabkan sumber daya dimuat ulang, pendekatan lazy-loading dapat membantu mempercepat transisi ini.

jmort253
sumber
10

Beberapa alasan penting lainnya mengapa menggunakan RequireJS masuk akal:

  1. Mengelola dependensi Anda sendiri dengan cepat berantakan untuk proyek-proyek yang cukup besar.
  2. Anda dapat memiliki file kecil sebanyak yang Anda inginkan, dan tidak perlu khawatir tentang melacak dependensi atau memuat pesanan.
  3. RequireJS memungkinkan untuk menulis seluruh aplikasi modular tanpa menyentuh objek jendela.

Diambil dari komentar rmurphey di sini di Gist ini .

Lapisan abstraksi bisa menjadi mimpi buruk untuk dipelajari dan disesuaikan, tetapi ketika itu melayani tujuan dan melakukannya dengan baik, itu masuk akal.

girls_can_code_too
sumber
9
Anda masih harus mengelola semua yang memerlukan dan menentukan pernyataan, file konfigurasi, tabrakan dengan sistem dan perpustakaan lain yang belum menerapkan spesifikasi AMD, dll. Saya mencoba menggunakan Require.JS dalam proyek node-webkit, dan Require.JS melawan saya di setiap langkah ... Kontras dengan hanya memesan skrip dengan cara tertentu ... Tentu saja, Anda mendapatkan pemuatan malas dengan Require.JS, itulah sebabnya saya mencoba membuatnya bekerja. :)
jmort253
Saya sangat setuju dengan @ jmort253, itu adalah perjuangan di awal, tapi sekarang saya sangat menyukainya. Ketiga poin itu benar! Dan mengesahkan perpustakaan seharusnya tidak sesulit itu ... atau gunakan shim.
Legenda
0

Inilah contoh yang lebih konkret.

Saya sedang mengerjakan proyek dengan 60 file. Kami memiliki 2 mode berbeda untuk menjalankannya.

  1. Muat versi yang disatukan, 1 file besar. (Produksi)

  2. Memuat semua 60 file (pengembangan)

Kami menggunakan loader sehingga kami hanya memiliki satu skrip di halaman web

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

Itu default ke mode # 1 (memuat satu file besar bersatu). Untuk menjalankan dalam mode # 2 (file terpisah) kami menetapkan beberapa flag. Itu bisa apa saja. Kunci dalam string kueri. Dalam contoh ini kita hanya melakukan ini

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

loader.js terlihat seperti ini

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

Skrip build hanyalah file .sh yang terlihat seperti ini

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

dll ...

Jika file baru ditambahkan, kami kemungkinan akan menggunakan mode # 2 karena kami sedang melakukan pengembangan, kami harus menambahkan injectScript("somenewfile.js") baris ke loader.js

Kemudian untuk produksi kami juga harus menambahkan somenewfile.js ke skrip build kami. Sebuah langkah yang sering kita lupakan dan kemudian mendapat pesan kesalahan.

Dengan beralih ke AMD kita tidak perlu mengedit 2 file. Masalah menjaga loader.js dan skrip build dalam sinkronisasi hilang. Menggunakan r.jsatau webpackhanya dapat membaca kode yang akan dibuatlarge-concantinated.js

Itu juga dapat menangani dependensi, misalnya kita memiliki 2 file lib1.js dan lib2.js dimuat seperti ini

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

lib2 membutuhkan lib1. Ada kode di dalamnya yang berfungsi seperti itu

lib1Api.installPlugin(...);

Tetapi karena skrip yang disuntikkan dimuat secara asinkron, tidak ada jaminan mereka akan memuat dalam urutan yang benar. 2 skrip ini bukan skrip AMD tetapi dengan menggunakan require.js kita dapat mengatakan dependensi mereka

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

Saya modul kami yang menggunakan lib1 kami melakukan ini

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

Sekarang memerlukan.js akan menyuntikkan skrip untuk kami dan itu tidak akan menyuntikkan lib2 sampai lib1 telah dimuat karena kami mengatakan lib2 tergantung pada lib1. Itu juga tidak akan memulai modul kami yang menggunakan lib1 sampai lib2 dan lib1 dimuat.

Ini membuat pengembangan bagus (tidak ada langkah pembangunan, tidak perlu khawatir tentang memuat pesanan) dan itu membuat produksi menyenangkan (tidak perlu memperbarui skrip pembuatan untuk setiap skrip yang ditambahkan).

Sebagai bonus tambahan, kita dapat menggunakan plugin babel webpack untuk menjalankan babel di atas kode untuk browser yang lebih lama dan sekali lagi kita tidak harus mempertahankan script build itu.

Perhatikan bahwa jika Chrome (browser pilihan kami) mulai mendukung import nyata, kami mungkin akan beralih ke itu untuk pengembangan tetapi itu tidak akan benar-benar mengubah apa pun. Kami masih bisa menggunakan webpack untuk membuat file gabungan dan kami bisa menggunakannya menjalankan babel atas kode untuk semua browser.

Semua ini diperoleh dengan tidak menggunakan tag skrip dan menggunakan AMD

gman
sumber