Modul mendefinisikan () anonim tidak cocok

129

Saya mendapatkan kesalahan ini saat menelusuri webapp untuk pertama kalinya (biasanya di browser dengan cache yang dinonaktifkan).

Kesalahan: Modul anonim define () tidak cocok: fungsi (memerlukan) {

HTML :

<html>
   .
   .
   .
   <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
   <script> var require = { urlArgs: "v=0.4.1.32" }; </script>
   <script data-main="assets/js/main" src="assets/js/libs/require.js"></script>
   <script src="assets/js/ace/ace.js?v=0.4.1.32"></script>
   </body>
</html>

JS :

$(function () {
    define(function (require) {
        // do something
    });
});

Adakah yang tahu persis apa arti kesalahan ini dan mengapa itu terjadi?

file sumber , diskusi singkat tentang hal itu di halaman masalah github

Adonis K. Kakoulidis
sumber

Jawaban:

142

Seperti yang dikatakan AlienWebguy, per dokumen, memerlukan.js dapat meledak jika

  • Anda memiliki define anonim (" modul yang memanggil define () tanpa ID string ") dalam tag skripnya sendiri (saya asumsikan sebenarnya maksudnya di mana saja dalam lingkup global)
  • Anda memiliki modul yang memiliki nama yang bertentangan
  • Anda menggunakan plugin loader atau modul anonim tetapi tidak menggunakan optimizer need.js untuk membundelnya

Saya punya masalah ini sementara termasuk bundel yang dibangun dengan browserify bersama modul needs.js. Solusinya adalah:

A. memuat bundel mandiri non-require.js dalam tag skrip sebelum require.js dimuat, atau

B. memuatnya menggunakan require.js (bukan tag skrip)

BT
sumber
2
nama yang saling bertentangan adalah yang umum
Julio Marins
1
Solusi lain yang mungkin, dalam beberapa kasus khusus dengan modul anonim adalah untuk menimpa fungsi requirejs.onError untuk mencegah pengecualian kesalahan default yang dilemparkan oleh requirejs yang menghentikan modul atau kode yang berhasil dijalankan.
xtrm
1
Baru saja menambahkan permintaan tarik ( github.com/requirejs/requirejs/pull/1763 ) untuk mengendurkan casing yang tepat. Saya pikir ini masalah yang sangat umum akhir-akhir ini.
Bob S
1
Terima kasih telah memberi tahu saya untuk memuatnya sebelumnya! Saya tidak tahu mengapa tip ini tidak ada dalam dokumentasi requirejs sendiri ... Di situlah tumpukan berguna
Tobias Feil
14

Saya mengalami kesalahan ini karena saya menyertakan file requirejs bersama dengan librairies lain yang disertakan secara langsung dalam tag script. Librairies (seperti lodash) menggunakan fungsi define yang bertentangan dengan define yang harus. File Requirejs memuat secara tidak sinkron, jadi saya curiga bahwa define yang diperlukan didefinisikan setelah perpustakaan lain mendefinisikan, maka konflik.

Untuk menghilangkan kesalahan, sertakan semua file js Anda yang lain dengan menggunakan requireejs.

eloone
sumber
Ternyata banyak perpustakaan melakukan hal seperti itu, atau setidaknya menggunakan / mengekspor fungsi seperti itu. Saya akan menyarankan semua orang - jika mereka menggunakan mengharuskan - impor semuanya dengan membutuhkan :)
Andrey Popov
12

Dalam memulai dengan reactjs saya mengalami masalah dan sebagai pemula dokumen mungkin juga ditulis dalam bahasa Yunani.

Masalah yang saya temui adalah bahwa sebagian besar contoh pemula menggunakan "definisi anonim" ketika Anda harus menggunakan "string id".

mendefinisikan anonim

define(function() {
        return { helloWorld: function() { console.log('hello world!') } };
 })


define(function() {
        return { helloWorld2: function() { console.log('hello world again!') } };
 })

tentukan dengan string id

define('moduleOne',function() {
    return { helloWorld: function() { console.log('hello world!') } };
})

 define('moduleTwo', function() {
      return { helloWorld2: function() { console.log('hello world again!') } };
})

Ketika Anda menggunakan define dengan id string maka Anda akan menghindari kesalahan ini ketika Anda mencoba menggunakan modul seperti:

require([ "moduleOne", "moduleTwo" ], function(moduleOne, moduleTwo) {
    moduleOne.helloWorld();
    moduleTwo.helloWorld2();
});
P.Brian.Mackey
sumber
(Hanya sebuah catatan untuk anak cucu) Ada yang beberapa kelemahan pendekatan ini, dijelaskan dalam dokumentasi : “define () panggilan yang mencakup nama untuk modul ... biasanya dihasilkan oleh alat optimasi ... nam [ing] modul sendiri ... membuat modul kurang portabel ... Biasanya yang terbaik adalah menghindari pengkodean dalam nama untuk modul dan biarkan alat optimisasi terbakar dalam nama modul. " ... juga di utas GitHub ini . Ini tampaknya menjadi alasan mengapa daftar nama dikecualikan dalam contoh pemula.
Mark G.
10

Per dokumen :

Jika Anda secara manual memberi kode pada tag skrip dalam HTML untuk memuat skrip dengan panggilan define () anonim, kesalahan ini dapat terjadi.

Juga terlihat jika Anda secara manual kode tag skrip dalam HTML untuk memuat skrip yang memiliki beberapa modul bernama, tetapi kemudian mencoba memuat modul anonim yang akhirnya memiliki nama yang sama dengan salah satu modul bernama dalam skrip dimuat oleh manual tag skrip kode.

Akhirnya, jika Anda menggunakan plugin loader atau modul anonim (modul yang memanggil define () tanpa ID string) tetapi tidak menggunakan pengoptimal RequireJS untuk menggabungkan file bersama, kesalahan ini dapat terjadi. Pengoptimal tahu cara memberi nama modul anonim dengan benar sehingga mereka dapat digabungkan dengan modul lain dalam file yang dioptimalkan.

Untuk menghindari kesalahan:

  • Pastikan untuk memuat semua skrip yang panggilan define () melalui API RequireJS. Jangan kode tag skrip secara manual dalam HTML untuk memuat skrip yang memiliki panggilan () di dalamnya.

  • Jika Anda secara manual memberi kode pada tag skrip HTML, pastikan hanya berisi modul yang dinamai, dan bahwa modul anonim yang akan memiliki nama yang sama dengan salah satu modul dalam file itu tidak dimuat.

  • Jika masalahnya adalah penggunaan plugin loader atau modul anonim tetapi pengoptimal RequireJS tidak digunakan untuk bundling file, gunakan pengoptimal RequireJS.

AlienWebguy
sumber
3
Apakah ini modul yang didefinisikan secara anonim? github.com/requirejs/example-multipage/blob/master/www/js/app/…
lampu jalan
5

Perlu diketahui bahwa beberapa ekstensi browser dapat menambahkan kode ke halaman. Dalam kasus saya, saya memiliki plugin "Emmet in all textareas" yang mengacaukan kebutuhan saya. Pastikan tidak ada kode tambahan yang ditambahkan beign ke dokumen Anda dengan memeriksanya di browser.

Vektor
sumber
5

Jawaban yang ada menjelaskan masalah dengan baik, tetapi jika menyertakan file skrip Anda menggunakan atau sebelum needJS bukan pilihan yang mudah karena kode warisan solusi yang sedikit membingungkan adalah untuk menghapus keharusan dari lingkup jendela sebelum tag skrip Anda dan kemudian mengembalikannya setelah kata sandi. Dalam proyek kami ini dibungkus dengan panggilan fungsi sisi server tetapi secara efektif browser melihat yang berikut:

    <script>
        window.__define = window.define;
        window.__require = window.require;
        window.define = undefined;
        window.require = undefined;
    </script>
    <script src="your-script-file.js"></script>        
    <script>
        window.define = window.__define;
        window.require = window.__require;
        window.__define = undefined;
        window.__require = undefined;
    </script>

Bukan yang paling rapi tetapi tampaknya berfungsi dan telah menyelamatkan banyak refractoring.

jcbdrn
sumber
5
Sebenarnya jangan pernah melakukan ini. Itu tidak berfungsi dengan baik di IE.
jcbdrn
2
Terkadang di IE skrip yang disertakan dengan requireJS akan mendefinisikan hilang dari lingkup jendela mereka bahkan ketika perintah memerlukan datang setelah variabel-variabel tersebut dipulihkan. Kami tidak pernah berhasil mencari tahu mengapa hal ini terjadi sehingga kami mengabaikan solusi peretasan ini.
jcbdrn
2
@ jcbdrn Ini bukan hanya di IE. Saya pernah melihatnya terjadi di platform lain. Alasannya adalah bahwa spesifikasi HTML memang menawarkan jaminan mengenai urutan pelaksanaan skrip sinkron tetapi hanya relatif terhadap skrip sinkron lainnya . Itu tidak menjamin eksekusi skrip asinkron relatif terhadap yang sinkron (atau sebaliknya). Jadi dalam kode yang ditunjukkan pada jawaban di sini, dimungkinkan untuk menjalankan skrip asinkron antara dua scriptelemen.
Louis
Jika Anda memiliki kemampuan untuk mengedit bundel js yang Anda impor, Anda dapat membungkus semuanya seperti ini:(function(){ var define = undefined; // the UMD registration code won't find the global 'define' anymore! // generated content goes here })()
Pete Thorne
2

Atau Anda bisa menggunakan pendekatan ini.

  • Tambahkan require.js di basis kode Anda
  • lalu muat skrip Anda melalui kode itu

<script data-main="js/app.js" src="js/require.js"></script>

Apa yang akan dilakukan itu akan memuat skrip Anda setelah memuat require.js .

Umar Asghar
sumber