ความแตกต่างระหว่าง Require.js และเพียงแค่สร้างองค์ประกอบ <script> ใน DOM คืออะไร [ปิด]


138

อะไรคือความแตกต่างระหว่างการใช้ Require.JS และเพียงแค่สร้าง<script>องค์ประกอบใน DOM

ความเข้าใจใน Require.JS ของฉันคือมันมีความสามารถในการโหลดการพึ่งพา แต่สิ่งนี้ไม่สามารถทำได้โดยการสร้าง<script>องค์ประกอบที่โหลดไฟล์ JS ภายนอกที่จำเป็นหรือไม่

เช่นให้ถือว่าผมมีฟังก์ชั่นที่ต้องใช้ฟังก์ชั่นdoStuff() อยู่ในแฟ้มภายนอกในขณะที่อยู่ในแฟ้มภายนอกneedMe()doStuff()do_stuff.jsneedMe()need_me.js

การทำเช่นนี้ Require.JS วิธี:

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

การทำสิ่งนี้โดยการสร้างองค์ประกอบสคริปต์:

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
}

ทั้งสองงานนี้ อย่างไรก็ตามรุ่นที่สองไม่ต้องการให้ฉันโหลดไลบรารี่ Require.js ทั้งหมด ฉันไม่เห็นความแตกต่างในการทำงาน ...


1
เบราว์เซอร์แคชเกี่ยวข้องกับอะไร
มูฮัมหมัดอูเมอร์

ฉันเปิดใหม่เพราะมันขอความแตกต่างระหว่างสองสิ่งที่คล้ายกันมาก มันสามารถจะตอบอย่างเป็นกลางและ TBH ฉันไม่เห็นความสัมพันธ์ที่มีความคิดเห็นเป็นมัน
RamenChef

คำตอบ:


43

นี่คือบทความที่ดีใน ajaxian.com ว่าทำไมใช้มัน:

RequireJS: การโหลด JavaScript แบบอะซิงโครนัส

  • # include / import / needs บางประเภท
  • ความสามารถในการโหลดการอ้างอิงที่ซ้อนกัน
  • ใช้งานง่ายสำหรับนักพัฒนาซอฟต์แวร์ แต่ได้รับการสนับสนุนจากเครื่องมือเพิ่มประสิทธิภาพที่ช่วยในการปรับใช้

2
ฉันได้อ่านสิ่งเหล่านี้แล้ว แต่ตอนนี้ฉันคิดอีกแล้วฉันก็ตระหนักว่าแนวคิดเรื่องการพึ่งพาที่ซ้อนกันไม่สามารถทำได้โดยการเขียนแท็ก <script> ขอบคุณ
maxedison

37
"ความสะดวกในการใช้งานสำหรับนักพัฒนาซอฟต์แวร์" ไม่สามารถทำได้ไกลจากความจริง มันมีช่วงการเรียนรู้ที่สูงชันสำหรับคุณและคนอื่น ๆ ที่จะมาทำงานในโครงการนั้น
Sahat Yalkabov

3
@ TwilightPony ฉันคิดว่าตัวเองไม่สดใสและต้องมีอะไรที่ยากสำหรับฉันที่จะได้รับ มันลบคุณต้องกังวลเกี่ยวกับการพึ่งพาและเพิ่มความเร็วในหน้า โค้ดของคุณสอดคล้องกับการเขียนโปรแกรมฝั่งเซิร์ฟเวอร์มากขึ้นในวิธีที่คุณประกาศการพึ่งพาซึ่งฉันพบว่าสดชื่นและเรียบง่าย ไวยากรณ์น้อยที่สุดและถูกปิดโดยการออกแบบจากนั้นตั้งค่าแผนงานสำหรับการผลิตเพื่อรวมสคริปต์ของคุณได้อย่างง่ายดาย ด้านบนของการดีบักนั้นเหมือนกับการประกาศคงที่ ไม่แน่ใจว่าอะไรจะง่ายไปกว่านั้น วิธีอื่นที่ยากกว่ามากอย่างที่ฉันได้ทำไปแล้ว
Jason Sebring

ฉันกำลังดิ้นรน โดยเฉพาะอย่างยิ่งกับโมดูลที่พยายามแนบตัวเองเข้ากับวัตถุระดับโลก (
ตอบโต้

1
ความคิดเห็นในหน้านั้นทำให้ฉันรู้สึกว่าควรหนีจากและไม่ได้ต้องการ โดยเฉพาะที่อยู่ใกล้ด้านล่างซึ่งเชื่อมโยงไปยังstevesouders.com/tests/require.php
Dave Kanter

52

Require.JS มีข้อได้เปรียบอะไรบ้างเมื่อเปรียบเทียบกับการสร้างองค์ประกอบใน DOM

ในตัวอย่างของคุณคุณกำลังสร้างแท็กสคริปต์แบบอะซิงโครนัสซึ่งหมายความว่าneedMe()ฟังก์ชันของคุณจะถูกเรียกใช้ก่อนที่ไฟล์ need_me.js จะเสร็จสิ้นการโหลด สิ่งนี้ส่งผลให้เกิดข้อยกเว้นที่ไม่ได้ตรวจสอบซึ่งฟังก์ชันของคุณไม่ได้ถูกกำหนดไว้

แต่เพื่อให้สิ่งที่คุณแนะนำใช้งานได้จริงคุณต้องทำสิ่งนี้:

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

}

อาจจะดีกว่าหรือไม่ที่จะใช้ตัวจัดการแพ็คเกจเช่น RequireJS หรือใช้กลยุทธ์ pure-JavaScript ดังที่แสดงไว้ด้านบน ในขณะที่เว็บแอปพลิเคชันของคุณอาจโหลดเร็วขึ้นการเรียกใช้ฟังก์ชันการทำงานและฟีเจอร์ต่าง ๆ บนไซต์จะช้าลงเนื่องจากมันจะเกี่ยวข้องกับการรอให้ทรัพยากรโหลดก่อนที่การกระทำนั้นจะสามารถทำได้

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

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


10

เหตุผลที่ชัดเจนบางประการว่าทำไมการใช้ RequireJS จึงสมเหตุสมผล:

  1. การจัดการการพึ่งพาของคุณเองอย่างรวดเร็วแตกต่างสำหรับโครงการขนาดใหญ่
  2. คุณสามารถมีไฟล์ขนาดเล็กได้มากเท่าที่คุณต้องการและไม่ต้องกังวลกับการติดตามการขึ้นต่อกันหรือลำดับการโหลด
  3. RequireJS ทำให้สามารถเขียนแอพแบบโมดูลาร์ทั้งหมดได้โดยไม่ต้องสัมผัสวัตถุในหน้าต่าง

นำมาจากความเห็นของ rmurphey ที่นี่ในส่วนสำคัญนี้

เลเยอร์ของสิ่งที่เป็นนามธรรมอาจเป็นฝันร้ายที่จะเรียนรู้และปรับตัวเข้ากับ แต่เมื่อมันทำหน้าที่ตามวัตถุประสงค์และทำได้ดีมันก็สมเหตุสมผลแล้ว


9
คุณยังต้องจัดการทั้งหมดที่จำเป็นและกำหนดคำสั่งไฟล์การกำหนดค่าการชนกับระบบและไลบรารีอื่น ๆ ที่ไม่ได้ใช้ข้อมูลจำเพาะของ AMD ฯลฯ ฉันลองใช้ Require.JS ในโครงการ node-webkit และ Require.JS สู้กับฉันในทุกขั้นตอน ... เปรียบเทียบว่าด้วยการสั่งสคริปต์ในลักษณะที่แน่นอน ... แน่นอนคุณได้รับขี้เกียจด้วย Require.JS ซึ่งเป็นเหตุผลที่ฉันพยายามทำให้มันทำงานได้ :)
jmort253

ฉันเห็นด้วยกับ @ jmort253 ทั้งหมดมันเป็นการต่อสู้ที่จุดเริ่มต้น แต่ตอนนี้ฉันชอบมันมาก ทั้งสามคะแนนถูกต้อง! และการทำให้ไลบรารีของ AMD เป็นเรื่องที่ไม่ยาก ... หรือใช้ shim
ตำนาน

0

นี่เป็นตัวอย่างที่ชัดเจนมากขึ้น

ฉันกำลังทำงานในโครงการที่มี 60 ไฟล์ เรามีโหมดการทำงานที่แตกต่างกัน 2 โหมด

  1. โหลดรุ่นต่อเนื่องขนาดใหญ่ 1 ไฟล์ (การผลิต)

  2. โหลดทั้งหมด 60 ไฟล์ (การพัฒนา)

เรากำลังใช้ตัวโหลดดังนั้นเราจึงมีเพียงหนึ่งสคริปต์ในหน้าเว็บ

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

ค่าเริ่มต้นคือโหมด # 1 (โหลดไฟล์ที่ต่อกันขนาดใหญ่หนึ่งไฟล์) ในการรันในโหมด # 2 (ไฟล์แยก) เราได้ตั้งค่าสถานะบางอย่าง มันอาจเป็นอะไรก็ได้ คีย์ในสายอักขระแบบสอบถาม ในตัวอย่างนี้เราเพิ่งทำสิ่งนี้

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

loader.js มีลักษณะเช่นนี้

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

สคริปต์การสร้างเป็นเพียงไฟล์. sh ที่มีลักษณะเช่นนี้

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

ฯลฯ ...

หากมีการเพิ่มไฟล์ใหม่เราน่าจะใช้โหมด # 2 เนื่องจากเรากำลังทำการพัฒนาเราต้องเพิ่มinjectScript("somenewfile.js")บรรทัดลงใน loader.js

หลังจากนั้นสำหรับการผลิตเรายังต้องเพิ่ม somenewfile.js ไปยังสคริปต์สร้างของเรา ขั้นตอนที่เรามักจะลืมแล้วได้รับข้อความแสดงข้อผิดพลาด

เมื่อเปลี่ยนเป็น AMD เราไม่จำเป็นต้องแก้ไข 2 ไฟล์ ปัญหาของการเก็บ loader.js และสคริปต์การสร้างในการซิงค์หายไป การใช้r.jsหรือwebpackเพียงแค่อ่านรหัสเพื่อสร้างlarge-concantinated.js

นอกจากนี้ยังสามารถจัดการกับการพึ่งพาเช่นเราโหลด 2 ไฟล์ lib1.js และ lib2.js เช่นนี้

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

lib2 ต้องการ lib1 มันมีโค้ดข้างในที่ทำอะไรบางอย่าง

lib1Api.installPlugin(...);

แต่เนื่องจากสคริปต์ฉีดถูกโหลดแบบอะซิงโครนัสจึงไม่รับประกันว่าจะโหลดตามลำดับที่ถูกต้อง 2 สคริปต์เหล่านี้ไม่ใช่สคริปต์ของ AMD แต่การใช้ require.js เราสามารถบอกได้ว่ามันขึ้นกับอะไร

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

ฉันโมดูลของเราที่ใช้ lib1 เราทำเช่นนี้

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

ตอนนี้ require.js จะฉีดสคริปต์ให้เราและจะไม่ส่ง lib2 จนกว่าจะโหลด lib1 เนื่องจากเราบอกว่า lib2 ขึ้นอยู่กับ lib1 และจะไม่เริ่มโมดูลของเราที่ใช้ lib1 จนกว่าทั้ง lib2 และ lib1 จะโหลดแล้ว

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

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

โปรดทราบว่าหาก Chrome (เบราว์เซอร์ที่เราเลือก) เริ่มสนับสนุนimportจริงเราอาจเปลี่ยนไปใช้เพื่อการพัฒนา แต่นั่นจะไม่เปลี่ยนแปลงอะไรเลย เรายังคงสามารถใช้ webpack เพื่อสร้างไฟล์ที่ต่อกันกันและเราสามารถใช้มันเพื่อเรียกใช้ babel บนโค้ดสำหรับเบราว์เซอร์ทั้งหมด

ทั้งหมดนี้ได้มาจากการไม่ใช้แท็กสคริปต์และการใช้ AMD

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