โมดูล define () ที่ไม่ระบุชื่อไม่ตรงกัน


129

ฉันได้รับข้อผิดพลาดนี้เมื่อฉันเรียกดูเว็บแอปเป็นครั้งแรก (โดยปกติจะอยู่ในเบราว์เซอร์ที่ปิดการใช้งานแคช)

ข้อผิดพลาด: ไม่ตรงกันไม่ระบุชื่อโมดูล define (): function (ต้องใช้) {

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

ใครทราบแน่ชัดว่าข้อผิดพลาดนี้หมายถึงอะไรและเหตุใดจึงเกิดขึ้น

ซอร์สไฟล์การอภิปรายสั้น ๆเกี่ยวกับมันในหน้าปัญหา github

คำตอบ:


142

เช่นเดียวกับ AlienWebguy กล่าวตามเอกสารrequire.js สามารถระเบิดได้หาก

  • คุณมีการกำหนดแบบไม่ระบุตัวตน (" โมดูลที่เรียกใช้ define () โดยไม่มีรหัสสตริง ") ในแท็กสคริปต์ของตัวเอง (ฉันคิดว่าจริง ๆ แล้วมันหมายถึงที่ใดก็ได้ในขอบเขตส่วนกลาง)
  • คุณมีโมดูลที่มีชื่อขัดแย้งกัน
  • คุณใช้ปลั๊กอินตัวโหลดหรือโมดูลที่ไม่ระบุตัวตน แต่ไม่ได้ใช้เครื่องมือเพิ่มประสิทธิภาพของ require.js ในการรวมกลุ่ม

ฉันมีปัญหานี้ในขณะที่รวมบันเดิลที่สร้างด้วย browserify ควบคู่ไปกับโมดูล require.js วิธีแก้ปัญหาคือ:

A. โหลดบันเดิลแบบสแตนด์อโลนที่ไม่ต้องใช้ js ในแท็กสคริปต์ก่อนที่จะโหลด require.js หรือ

B. โหลดโดยใช้ require.js (แทนแท็กสคริปต์)


2
ชื่อที่ขัดแย้งกันเป็นเรื่องธรรมดา
Julio Marins

1
อีกวิธีหนึ่งที่เป็นไปได้ในบางกรณีพิเศษที่มีโมดูลที่ไม่ระบุชื่อคือการเขียนทับฟังก์ชัน requirejs.onError เพื่อป้องกันข้อผิดพลาดเริ่มต้นที่เกิดจาก requirejs ซึ่งจะหยุดการทำงานของโมดูลหรือรหัสที่ประสบความสำเร็จ
xtrm

1
เพิ่งเพิ่มคำขอดึง ( github.com/requirejs/requirejs/pull/1763 ) เพื่อผ่อนคลายกรณีนั้น ๆ ฉันคิดว่ามันเป็นปัญหาที่พบบ่อยมากในทุกวันนี้
Bob S

1
ขอบคุณที่บอกให้โหลดมาก่อน! ฉันไม่รู้ว่าทำไมเคล็ดลับนี้ไม่อยู่ในเอกสารของ requirejs เอง ... นั่นคือสิ่งที่สแต็กมีประโยชน์
Tobias Feil

14

ฉันมีข้อผิดพลาดนี้เนื่องจากฉันรวมไฟล์ requirejs พร้อมกับ librairies อื่น ๆ ที่รวมอยู่ในแท็กสคริปต์โดยตรง Librairies เหล่านั้น (เช่น lodash) ใช้ฟังก์ชัน define ที่ขัดแย้งกับการกำหนดของ require ไฟล์ requirejs กำลังโหลดแบบอะซิงโครนัสดังนั้นฉันจึงสงสัยว่าการกำหนดของต้องได้รับการกำหนดหลังจากที่ไลบรารีอื่น ๆ กำหนดดังนั้นความขัดแย้ง

ในการกำจัดข้อผิดพลาดให้รวมไฟล์ js อื่น ๆ ทั้งหมดของคุณโดยใช้ requirejs


กลายเป็นว่าห้องสมุดจำนวนมากทำสิ่งนั้นหรืออย่างน้อยก็ใช้ / ส่งออกฟังก์ชันดังกล่าว ฉันจะแนะนำทุกคน - ถ้าพวกเขาใช้ต้อง - นำเข้าทุกอย่างด้วยความต้องการ :)
Andrey Popov

12

ในการเริ่มต้นใช้ reactjs ฉันพบปัญหาและในฐานะผู้เริ่มต้นเอกสารอาจถูกเขียนเป็นภาษากรีกเช่นกัน

ปัญหาที่ฉันพบคือตัวอย่างเริ่มต้นส่วนใหญ่ใช้ "anonymous defines" เมื่อคุณควรใช้ "string id"

anonymous กำหนด

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


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

กำหนดด้วย id สตริง

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

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

เมื่อคุณใช้define กับ id สตริงคุณจะหลีกเลี่ยงข้อผิดพลาดนี้เมื่อคุณพยายามใช้โมดูลดังนี้:

require([ "moduleOne", "moduleTwo" ], function(moduleOne, moduleTwo) {
    moduleOne.helloWorld();
    moduleTwo.helloWorld2();
});

(เพียงบันทึกให้ลูกหลาน) มีมีข้อเสียบางอย่างเพื่อให้วิธีการนี้ได้อธิบายไว้ในเอกสาร “define () สายที่มีชื่อสำหรับโมดูลที่ ... ถูกสร้างขึ้นตามปกติโดยเครื่องมือเพิ่มประสิทธิภาพ ... น้ำ [วัน] โมดูลตัวคุณเอง ... ทำให้ โมดูลแบบพกพาน้อยกว่า…โดยปกติแล้วทางที่ดีควรหลีกเลี่ยงการเข้ารหัสในชื่อโมดูลและปล่อยให้เครื่องมือเพิ่มประสิทธิภาพเบิร์นในชื่อโมดูล” …เช่นเดียวกับในเธรด GitHubนี้ นี่น่าจะเป็นเหตุผลว่าทำไมรายชื่อจึงไม่รวมอยู่ในตัวอย่างเริ่มต้น
Mark G.

10

ตามเอกสาร :

หากคุณเขียนโค้ดแท็กสคริปต์ใน HTML ด้วยตนเองเพื่อโหลดสคริปต์ด้วยการเรียกใช้ define () แบบไม่ระบุชื่อข้อผิดพลาดนี้อาจเกิดขึ้นได้

นอกจากนี้ยังเห็นด้วยว่าคุณเขียนโค้ดแท็กสคริปต์ใน HTML ด้วยตนเองเพื่อโหลดสคริปต์ที่มีโมดูลที่มีชื่อไม่กี่โมดูล แต่จากนั้นพยายามโหลดโมดูลที่ไม่ระบุชื่อซึ่งท้ายที่สุดมีชื่อเดียวกันกับโมดูลที่มีชื่อในสคริปต์ที่โหลดด้วยตนเอง แท็กสคริปต์ที่เข้ารหัส

สุดท้ายหากคุณใช้ปลั๊กอินตัวโหลดหรือโมดูลที่ไม่ระบุชื่อ (โมดูลที่เรียกว่า define () โดยไม่มีรหัสสตริง) แต่ไม่ใช้เครื่องมือเพิ่มประสิทธิภาพ RequireJS เพื่อรวมไฟล์เข้าด้วยกันข้อผิดพลาดนี้อาจเกิดขึ้นได้ เครื่องมือเพิ่มประสิทธิภาพรู้วิธีตั้งชื่อโมดูลที่ไม่ระบุชื่ออย่างถูกต้องเพื่อให้สามารถรวมกับโมดูลอื่น ๆ ในไฟล์ที่ปรับให้เหมาะสมได้

เพื่อหลีกเลี่ยงข้อผิดพลาด:

  • อย่าลืมโหลดสคริปต์ทั้งหมดที่เรียกใช้ define () ผ่าน RequireJS API อย่าเขียนโค้ดแท็กสคริปต์ด้วยตนเองใน HTML เพื่อโหลดสคริปต์ที่มีการเรียกใช้ define ()

  • หากคุณเขียนโค้ดแท็กสคริปต์ HTML ด้วยตนเองตรวจสอบให้แน่ใจว่ามีเฉพาะโมดูลที่มีชื่อและโมดูลที่ไม่ระบุชื่อซึ่งจะมีชื่อเดียวกับโมดูลใดโมดูลหนึ่งในไฟล์นั้นจะไม่ถูกโหลด

  • หากปัญหาเกิดจากการใช้ปลั๊กอินตัวโหลดหรือโมดูลที่ไม่ระบุชื่อ แต่ไม่ได้ใช้เครื่องมือเพิ่มประสิทธิภาพ RequireJS สำหรับการรวมไฟล์ให้ใช้เครื่องมือเพิ่มประสิทธิภาพ RequireJS


3
นี่เป็นโมดูลที่กำหนดโดยไม่ระบุตัวตนหรือไม่ github.com/requirejs/example-multipage/blob/master/www/js/app/…
ไฟถนน

5

โปรดทราบว่าส่วนขยายของเบราว์เซอร์บางตัวสามารถเพิ่มโค้ดลงในเพจได้ ในกรณีของฉันฉันมีปลั๊กอิน "Emmet in all textareas" ที่ยุ่งกับ requireJs ของฉัน ตรวจสอบให้แน่ใจว่าไม่มีการเพิ่มรหัสพิเศษลงในเอกสารของคุณโดยการตรวจสอบในเบราว์เซอร์


5

คำตอบที่มีอยู่อธิบายปัญหาได้ดี แต่หากรวมไฟล์สคริปต์ของคุณโดยใช้หรือก่อนหน้านี้ requireJS ไม่ใช่ตัวเลือกที่ง่ายเนื่องจากรหัสเดิมวิธีแก้ปัญหาที่แฮ็กเล็กน้อยคือการลบความต้องการออกจากขอบเขตหน้าต่างก่อนแท็กสคริปต์ของคุณจากนั้นจึงคืนสถานะให้เป็นคำหลัง ในโครงการของเราสิ่งนี้ถูกห่อหุ้มไว้หลังการเรียกใช้ฟังก์ชันฝั่งเซิร์ฟเวอร์ แต่เบราว์เซอร์จะเห็นสิ่งต่อไปนี้:

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

ไม่ใช่สิ่งที่สะอาดที่สุด แต่ดูเหมือนจะใช้ได้ผลและช่วยประหยัดการหักเหของแสงได้มาก


5
ที่จริงไม่เคยทำเช่นนี้ มันทำงานไม่ถูกต้องใน IE
jcbdrn

2
เป็นระยะ ๆ ใน IE สคริปต์ที่มาพร้อมกับ requireJS จะกำหนดว่าขาดหายไปจากขอบเขตหน้าต่างแม้ว่าคำสั่ง require จะมาหลังจากที่เรียกคืนตัวแปรเหล่านั้นแล้วก็ตาม เราไม่เคยคิดได้ว่าเหตุใดจึงเกิดขึ้นเราจึงละทิ้งโซลูชันที่แฮ็กนี้
jcbdrn

2
@jcbdrn ไม่ใช่แค่บน IE ฉันเคยเห็นมันเกิดขึ้นบนแพลตฟอร์มอื่น เหตุผลก็คือข้อมูลจำเพาะของ HTML ให้การรับประกันเกี่ยวกับลำดับการทำงานของสคริปต์ซิงโครนัสแต่สัมพันธ์กับสคริปต์ซิงโครนัสอื่น ๆเท่านั้น ไม่รับประกันการทำงานของสคริปต์อะซิงโครนัสที่สัมพันธ์กับซิงโครนัสหนึ่ง (หรือในทางกลับกัน) ดังนั้นในโค้ดที่แสดงในคำตอบที่นี่จึงเป็นไปได้ที่จะมีสคริปต์อะซิงโครนัสรันระหว่างสองscriptองค์ประกอบใด ๆ
หลุยส์

หากคุณมีความสามารถในการแก้ไขบันเดิล js ที่คุณกำลังนำเข้าคุณก็สามารถรวมสิ่งต่างๆได้ดังนี้(function(){ var define = undefined; // the UMD registration code won't find the global 'define' anymore! // generated content goes here })()
Pete Thorne

2

หรือคุณสามารถใช้แนวทางนี้

  • เพิ่ม require.js ในฐานรหัสของคุณ
  • จากนั้นโหลดสคริปต์ของคุณผ่านรหัสนั้น

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

สิ่งที่จะทำมันจะโหลดสคริปต์ของคุณหลังจาก require.js

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.