CommonJS, AMD ve RequireJS arasındaki ilişki?


840

Çok okuduktan sonra bile CommonJS, AMD ve RequireJS hakkında çok kafam karıştı .

CommonJS (eski adıyla ServerJS ), dil tarayıcı dışında kullanıldığında bazı JavaScript özelliklerini (yani modülleri) tanımlamak için bir grup olduğunu biliyorum . CommonJS modülleri belirtiminde Node.js veya RingoJS gibi bazı uygulamalar var , değil mi?

CommonJS , Asenkron Modül Tanımı (AMD) ve RequireJS arasındaki ilişki nedir ?

RequireJS , CommonJS modülü tanımının bir uygulaması mıdır ? Evet ise, AMD nedir?


31
Requirjs.org/docs/whyamd.html okumak, hepsinden bahsedildiği için çok açıklığa kavuşacaktır . (Ben bu tam bir cevap olarak düşünmüyor gibi yorum olarak gönderme).
mmutilva

5
Daha fazla soru sorabilir veya ekleyebilir miyim; ES2015 içe aktarma ifadeleri bunların hepsine nasıl veya nerede sığar; örneğin Ember'i 'kor' dan içe aktarın;
testndtv

Ayrıca, desteklenen JS modülü biçimlerini (CommonJS, UMD, AMD, ES6) yükleyen bir sistem sistemi de vardır.
Andy

Yanıtlar:


770

RequireJS , AMD API'sini (kaynak) uygular .

CommonJS , exportsmodül içeriğini tanımlayan bir nesne yardımıyla modülleri tanımlamanın bir yoludur . Basitçe söylemek gerekirse, bir CommonJS uygulaması şu şekilde çalışabilir:

// someModule.js
exports.doSomething = function() { return "foo"; };

//otherModule.js
var someModule = require('someModule'); // in the vein of node    
exports.doSomethingElse = function() { return someModule.doSomething() + "bar"; };

Temel olarak, CommonJS, require()bağımlılıkları getirmek için bir işleve, exportsmodül içeriğini dışa aktarmak için bir değişkene ve bağımlılıkları ( kaynak olarak söz konusu modülle ilgili söz konusu modülün konumunu açıklayan) bir modül tanımlayıcısına ( kaynaka ihtiyaç duyduğunu) belirtmeniz gerektiğini belirtir. ). CommonJS, bahsettiğiniz Node.js de dahil olmak üzere çeşitli uygulamalara sahiptir .

CommonJS özellikle tarayıcılar göz önünde bulundurularak tasarlanmadı, bu yüzden tarayıcı ortamına çok iyi uymuyor ( bunun için hiçbir kaynağım yok - sadece RequireJS sitesi de dahil olmak üzere her yerde söylüyor . ) Görünüşe göre, bunun bir şeyleri var eşzamansız yükleme vb. ile yapın.

Öte yandan, RequireJS, tarayıcı ortamına ( kaynak ) uyacak şekilde tasarlanmış AMD'yi uygular . Görünüşe göre AMD, CommonJS Transport formatının bir parçası olarak başladı ve kendi modül tanımı API'sine dönüştü. Bu yüzden ikisi arasındaki benzerlikler. AMD'nin yeni özelliği define(), modülün yüklenmeden önce bağımlılıklarını bildirmesine izin veren işlevdir. Örneğin, tanım şunlar olabilir:

define('module/id/string', ['module', 'dependency', 'array'], 
function(module, factory function) {
  return ModuleContents;  
});

Bu nedenle, CommonJS ve AMD, farklı uygulamaları olan JavaScript modülü tanımlama API'larıdır, ancak her ikisi de aynı kökenlidir.

  • AMD tarayıcı için daha uygundur, çünkü modül bağımlılıklarının eşzamansız yüklenmesini destekler.
  • RequireJS , AMD'nin bir uygulamasıdır , aynı zamanda CommonJS'in ruhunu korumaya çalışır (esas olarak modül tanımlayıcılarında).

Sizi daha da karıştırmak için, bir AMD uygulaması olarak RequireJS, bir CommonJS sarmalayıcısı sunar, böylece CommonJS modülleri neredeyse doğrudan RequireJS ile kullanılmak üzere içe aktarılabilir.

define(function(require, exports, module) {
  var someModule = require('someModule'); // in the vein of node    
  exports.doSomethingElse = function() { return someModule.doSomething() + "bar"; };
});

Umarım bu bir şeyleri netleştirmeye yardımcı olur!


7
2 formattaki boşlukları köprüleyen uRequire.org projesine göz atın - ya (ya da her ikisini birden) yazın, iki ya da basit <script> 'den herhangi birine konuşlandırın
Angelos Pikoulas

51
FYI Browserify artık tarayıcıda CommonJS kullanmanıza izin verecek.
Eruant

9
@Eruant Ancak, AMD ile hala eşzamansız bir doğaya sahip değil.
İnanç Gümüş

8
CommonJS'nin RequireJS belgelerinde belirtildiği gibi tarayıcıya sığmamasının nedeni - "CommonJS gerektirir () eşzamanlı bir çağrıdır, modülü hemen geri döndürmesi beklenir. Bu, tarayıcıda iyi çalışmıyor" . Daha fazla bilgi burada .
msn

4
@aaaaaa kullanıcı isteğine bağlı olarak bazı özellikleri etkinleştirmek isteyebilirsiniz; bu nedenle AMD'nin zaman uyumsuz yapısı kullanışlı olabilir.
İnanç Gumus

199

CommonJS bundan daha fazlasıdır - JavaScript için ortak bir API ve ekosistem tanımlamak için bir projedir. CommonJS'nin bir kısmı Modül belirtimidir. Node.js ve RingoJS sunucu tarafı JavaScript çalışma zamanlarıdır ve evet, her ikisi de CommonJS Module spesifikasyonlarına göre modüller uygular.

AMD (Asenkron Modül Tanımı) modüller için başka bir özelliktir. RequireJS muhtemelen AMD'nin en popüler uygulamasıdır. CommonJS'den önemli bir fark, AMD'nin modüllerin eşzamansız olarak yüklendiğini belirtmesidir - bu, bir yükün bitmesini bekleyerek yürütmeyi engellemenin aksine modüllerin paralel olarak yüklendiği anlamına gelir.

AMD genellikle bu nedenle istemci tarafı (tarayıcı içi) JavaScript geliştirmede daha çok kullanılır ve CommonJS Modülleri genellikle sunucu tarafında kullanılır. Ancak, her iki ortamda da modül özelliklerini kullanabilirsiniz - örneğin, RequireJS Node.js'de çalıştırmak için yönergeler sunar ve browserify , tarayıcıda çalışabilen bir CommonJS Modülü uygulamasıdır.


20
Neden CommonJS ana sayfası bu kadar korkunç ... Sadece resmi spesifikasyonu görmeye çalışıyorum. Sözdizimi hataları, eksik belgeler var ve wiki sayfası çözülmüyor.
taco

7
Modülleri eşzamansız olarak yüklemenin anlamı bu değildir. Dinamik / tembel yüklemeden bahsediyor olabilirsiniz. Zaman uyumsuz olarak, yüklenecek bir dosya önerirsiniz ve daha sonra bir süre sonra yükleme tamamlandığında geri arar. Senkronizasyon ile yüklenecek bir dosya önerirsiniz ve daha sonra bu dosyanın yüklenmesi bitene kadar tüm iş parçacığı bloke edilir; dosya yüklenene kadar başka kod yürütülmez. Birincisi öngörülemezlik pahasına daha iyi performans verebilirken, ikincisi her seferinde aynı sonuçları verebilir ve bu nedenle daha tahmin edilebilir. Bu tuhaflıkların çeşitli optimizasyonlar kullanılarak azaltılabileceğini unutmayın.
perry

Cevap için teşekkürler. Artık modüller ES2015 ile JS'de resmi olduğuna göre, bu AMD veya ortak JS'den daha fazla tercih edildikleri anlamına mı geliyor?
Akhoy

Bu onların tercih edildiği anlamına gelmez. Her şey geliştirici ihtiyaçlarına bağlıdır. Hiçbir seçenek bırakmadan ES6 modüllerine gitmenin özellikle iyi bir fikir olduğunu düşünmüyorum. Ancak iyi UMD kullanarak bu sorunla mücadele edebilirsiniz. AMD ile senkronize edilen CommonJS paketlerini yüklemek genel olarak iyi (en iyi) bir fikirdir (performans iyiliği iyileştirmeleri için). Açıkçası daha fazla kontrole sahip olmanız gerektiğini düşünüyorsanız. Ve yapmalısın.
Maciej Sitko

187

Kısa cevap:

CommonJS ve AMD , modüllerin ve bağımlılıklarının javascript uygulamalarında nasıl bildirilmesi gerektiğine ilişkin spesifikasyonlardır (veya formatlardır).

RequireJS , AMD uyumlu bir script yükleyici kütüphanesidir, curljs başka bir örnektir.

CommonJS uyumlu:

Alındığı Addy Osmani adlı kitabında .

// package/lib is a dependency we require
var lib = require( "package/lib" );

// behavior for our module
function foo(){
    lib.log( "hello world!" );
}

// export (expose) foo to other modules as foobar
exports.foobar = foo;

AMD uyumlu:

// package/lib is a dependency we require
define(["package/lib"], function (lib) {

    // behavior for our module
    function foo() {
        lib.log( "hello world!" );
    }

    // export (expose) foo to other modules as foobar
    return {
        foobar: foo
    }
});

Modül başka bir yerde kullanılabilir:

require(["package/myModule"], function(myModule) {
    myModule.foobar();
});

Bazı bilgiler:

Aslında, CommonJS bir API bildiriminden çok daha fazlasıdır ve yalnızca bir kısmı bununla ilgilenir. AMD, CommonJS listesindeki modül formatı için taslak şartname olarak başladı, ancak tam konsensüse ulaşılmadı ve formatın daha da geliştirilmesi amdjs grubuna taşındı . Hangi biçimin daha iyi olduğu konusundaki argümanlar, CommonJS'nin daha geniş bir dizi endişeyi kapsamaya çalıştığını ve senkronize doğası göz önüne alındığında sunucu tarafı gelişimi için daha uygun olduğunu ve AMD'nin asenkron yapısı ve bunun kökleri Dojo'nun modül beyanı uygulamasındadır.

Kaynaklar:


1
Açıklamalar yerine kodu görmek yardımcı olur! :) AMD compliantaslında RequireJS, değil mi?
Asim KT

Bir şey mi kaçırıyorum yoksa yanlış yazılmış bir şey var mı? "Package / lib" tanımlıyorsunuz ancak "package / myModule" gerekiyor.
RullDawg

Her zaman bir şeyin neden böyle olduğu hakkında biraz okumak isterim! Bu arka planı sağladığınız için teşekkürler!
Andru

@RullDawg Hayır, “package / lib” burada tanımlanmamıştır, burada kullanılan bir 3. taraf bağımlılığıdır .
Robert Siemer

28

Alıntı yapmak

AMD :

  • İlk tarayıcı yaklaşımı
  • Zaman uyumsuz davranışı ve basitleştirilmiş geriye dönük uyumluluğu seçme
  • Herhangi bir Dosya G / Ç konsepti yoktur.
  • Nesneleri, işlevleri, yapıcıları, dizeleri, JSON ve diğer birçok modül türünü destekler.

CommonJS :

  • İlk sunucu yaklaşımı
  • Eşzamanlı davranış varsayımı
  • G / Ç, Dosya sistemi, Vaatler ve daha fazlası gibi daha geniş bir endişeyi kapsar.
  • Sarılmamış modülleri destekler, ES.next/Harmony spesifikasyonlarına biraz daha yakın hissedebilir ve sizi AMDzorlayan define () sargısını serbest bırakır .
  • Nesneleri yalnızca modül olarak destekleyin.

17

JavaScript programını modüler olarak birkaç dosya halinde düzenlemek child-modulesve main js module.

Aslında JavaScript bunu sağlamaz. Bugün bile Chrome ve FF'nin en son tarayıcı sürümlerinde değil.

Ancak, JavaScript'te başka bir JavaScript modülünü çağırmak için herhangi bir anahtar kelime var mı?

Bu soru birçokları için dünyanın tamamen çökmesi olabilir, çünkü cevap Hayır .


ES5'te (2009'da piyasaya sürüldü) JavaScript'in içe aktarma , dahil etme veya gereksinim gibi anahtar kelimeleri yoktu .

ES6, içe aktarma anahtar sözcüğünü ( https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/import ) önererek günü (2015 yılında piyasaya sürüldü) kaydeder , ancak bunu tarayıcı uygulamaz.

Babel 6.18.0 kullanıyorsanız ve yalnızca ES2015 seçeneğiyle aktarıyorsanız

import myDefault from "my-module";

requiretekrar alacaksın .

"use strict";
var _myModule = require("my-module");
var _myModule2 = _interopRequireDefault(_myModule);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

Bunun nedeni requiremodülün Node.js'den yükleneceği anlamına gelir. Node.js, sistem düzeyinde dosya okumadan sarma işlevlerine modüle kadar her şeyi işleyecektir.

Çünkü JavaScript işlevlerinde modülleri temsil eden tek sarmalayıcılar vardır.

CommonJS ve AMD hakkında çok kafam karıştı mı?

Hem CommonJS hem de AMD, modülleri akıllı yüklemek için JavaScript "kusurunun" üstesinden gelmek için sadece iki farklı tekniktir.


3
Cevabınızı güncellemelisiniz, çünkü şimdi tüm modern tarayıcılar destekliyor import
vsync

@vsync, evet, bu segmenti bir süredir takip etmediğim için cevabımı düzenlemekte çekinmeyin.
prosti
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.