ExpressJS Bir uygulama nasıl yapılandırılır?


527

NodeJS için ExpressJS web çerçevesini kullanıyorum.

ExpressJS kullanan kişiler çevrelerini (geliştirme, üretim, test ...), rotalarını vb app.js. Bunun güzel bir yol olmadığını düşünüyorum çünkü büyük bir uygulamanız olduğunda, app.js çok büyük!

Bu dizin yapısına sahip olmak istiyorum:

| my-application
| -- app.js
| -- config/
     | -- environment.js
     | -- routes.js

İşte benim kod:

app.js

var express = require('express');
var app = module.exports = express.createServer();

require('./config/environment.js')(app, express);
require('./config/routes.js')(app);

app.listen(3000);

config / environment.js

module.exports = function(app, express){
    app.configure(function() {
    app.use(express.logger());
    });

    app.configure('development', function() {
    app.use(express.errorHandler({
        dumpExceptions: true,
        showStack: true
    }));
    });

    app.configure('production', function() {
    app.use(express.errorHandler());
    });
};

config / routes.js

module.exports = function(app) {
    app.get('/', function(req, res) {
    res.send('Hello world !');
    });
};

Kodum iyi çalışıyor ve dizinlerin yapısının güzel olduğunu düşünüyorum. Ancak, kod uyarlanması gerekiyordu ve iyi / güzel olduğundan emin değilim.

Dizinlerimin yapısını kullanmak ve kodu uyarlamak veya sadece bir dosya (app.js) kullanmak daha mı iyi?

Tavsiyeleriniz için teşekkürler!


Bunu yapmanın performans sorunları hala gizleniyor mu? Bir yerde okuduğumu hatırlıyorum (belki ekspres grup) böyle her şeyi ayırdığınızda bir ton performans kaybedersiniz. Reqs / sec gibi bir şey, sanki bir hata gibi farkedilir bir miktarda düşecektir.
AntelopeSalad

2
Express Google grubundan. Bağlantı şu şekildedir
AntelopeSalad

52
hayır bu çok yanlış
tjholowaychuk

Yanıtlar:


306

Tamam, bir süre oldu ve bu popüler bir soru, bu yüzden devam ettim ve JavaScript kodlu bir iskele github deposu ve orta boyutlu bir express.js uygulamasını nasıl yapılandırmak istediğim hakkında uzun bir README oluşturdum.

focusaurus / express_code_sttruc , bunun için en son koda sahip olan repo'dur . Çekme istekleri kabul edilir.

Stackoverflow sadece bir bağlantı yanıtlarını sevmediği için README'nin bir anlık görüntüsü. Bu, güncellemeye devam edeceğim yeni bir proje olduğu için bazı güncellemeler yapacağım, ancak sonuçta github repo bu bilgiler için güncel bir yer olacak.


Ekspres Kod Yapısı

Bu proje, orta ölçekli bir express.js web uygulamasının nasıl düzenleneceğine bir örnektir.

En azından ekspres v4.14 Aralık 2016'da geçerli

Derleme Durumu

js standardı tarzı

Başvurunuz ne kadar büyük?

Web uygulamaları aynı değildir ve bence tüm express.js uygulamalarına uygulanması gereken tek bir kod yapısı yoktur.

Uygulamanız küçükse, burada örneklendiği gibi derin bir dizin yapısına ihtiyacınız yoktur. Basit tutun ve deponuzun .jsköküne bir avuç dosya yapıştırın ve işiniz bitti. Voilà.

Uygulamanız çok büyükse, bir noktada onu farklı npm paketlerine ayırmanız gerekir. Genel olarak node.js yaklaşımı, en azından kütüphaneler için birçok küçük paketi destekliyor gibi görünüyor ve mantıklı olmaya ve ek yükü haklı çıkarmaya başlarken uygulamanızı birkaç npm paketi kullanarak oluşturmalısınız. Uygulamanız büyüdükçe ve kodun bir kısmı uygulamanızın dışında tekrar kullanılabilir hale geldikçe veya açık bir alt sistem olduğunda, onu kendi git deposuna taşıyın ve bağımsız bir npm paketine dönüştürün.

Dolayısıyla bu projenin odak noktası orta ölçekli bir uygulama için uygulanabilir bir yapı göstermektir.

Genel mimariniz nedir

Bir web uygulaması oluşturmak için birçok yaklaşım vardır, örneğin:

  • Sunucu Tarafı MVC ve Ruby on Rails
  • Tek Sayfa Uygulama stili a MongoDB / Express / Açısal / Düğüm (MEAN)
  • Bazı formlara sahip temel web sitesi
  • Modeller / İşlemler / Görüntüler / Olaylar tarzı bir MVC öldü, hareket zamanı
  • ve daha pek çoğu hem güncel hem de tarihsel

Bunların her biri farklı bir dizin yapısına iyi uyum sağlar. Bu örneğin amaçları için, sadece iskele ve tamamen çalışan bir uygulama değil, ancak aşağıdaki temel mimari noktaları varsayıyorum:

  • Sitede bazı geleneksel statik sayfalar / şablonlar var
  • Sitenin "uygulama" kısmı, Tek Sayfalı Uygulama stili olarak geliştirilmiştir
  • Uygulama, tarayıcıya bir REST / JSON stili API'si gösterir
  • Uygulama basit bir iş etki alanı modelleri, bu durumda, bir araba bayilik uygulaması

Peki Ruby on Rails?

Bu proje boyunca Ruby on Rails'de yer alan fikirlerin çoğunun ve yaygın olarak kabul edilip kullanılmasına rağmen kabul ettikleri "Konfigürasyon Konvansiyonu" kararlarının aslında çok yararlı olmadığı ve bazen bu deponun tersi olduğu bir tema olacaktır. önerir.

Buradaki ana nokta, kod düzenlemenin altında yatan ilkeler olduğu ve bu ilkelere dayanarak Ruby on Rails sözleşmelerinin Ruby on Rails topluluğu için (çoğunlukla) mantıklı olduğu. Ancak, düşüncesizce bu sözleşmelerin üstesinden gelmek bu noktayı kaçırıyor. Temel ilkeleri inceledikten sonra, TÜM projeleriniz iyi organize edilmiş ve net olacaktır: kabuk komut dosyaları, oyunlar, mobil uygulamalar, kurumsal projeler, hatta ana dizininiz.

Rails topluluğu için, tek bir Rails geliştiricisinin uygulamadan uygulamaya uygulaması olmasını ve her seferinde tanıdık ve rahat olmasını isterler. 37 sinyal veya Pivotal Labs iseniz ve bunun faydaları varsa, bu çok mantıklıdır. Sunucu tarafındaki JavaScript dünyasında, genel ethos, vahşi batıdaki her şeyin gittiği yoldan çok daha fazla ve bununla ilgili bir sorunumuz yok. İşte biz buyuz. Biz buna alışkınız. Express.js içinde bile, Rails değil Sinatra'nın yakın bir akrabasıdır ve Rails'ten konvansiyon almak genellikle hiçbir şeye yardımcı olmaz. Hatta Konfigürasyon Konvansiyonu Hakkında İlkeler bile diyebilirim .

Temel İlkeler ve Motivasyonlar

  • Zihinsel olarak yönetilebilir olun
    • Beyin aynı anda ancak az sayıda ilgili şeyle ilgilenebilir ve düşünebilir. Bu yüzden dizin kullanıyoruz. Küçük bölümlere odaklanarak karmaşıklıkla başa çıkmamıza yardımcı olur.
  • Boyuta uygun olun
    • Sadece 3 dosya aşağı sadece 1 dosya olduğu "Konak Dizinler" oluşturmayın. Bunu, 3 dosyayı içeren 1 dizin çok daha uygun olduğunda 10'dan fazla dizin tutmak için 10'dan fazla dizin oluşturmak için küçük projeleri paylaşan Ansible Best Practices'de görebilirsiniz . Çalışmak için bir otobüs kullanmazsınız (bir otobüs şoförü değilseniz, ancak o zaman bile bir otobüs AT çalışmanız işe yaramazsa), bu nedenle içindeki gerçek dosyalar tarafından haklı gösterilmeyen dosya sistemi yapıları oluşturmayın .
  • Modüler ama pragmatik olun
    • Düğüm topluluğu genel olarak küçük modülleri tercih eder. Uygulamanızdan tamamen ayrılabilecek her şey dahili kullanım için veya npm'de herkese açık olarak yayınlanan bir modüle çıkarılmalıdır. Ancak, buradaki kapsam olan orta boyutlu uygulamalar için, bunun ek yükü, iş akışınıza orantılı değer olmadan tedium ekleyebilir. Bu nedenle, faktoring edilmiş ancak tamamen ayrı bir npm modülünü haklı çıkarmak için yeterli olmayan bir kodunuz olduğu zaman için, sadece bir boyut eşiğini geçtiği zaman çıkartılacağı beklentisiyle bir " proto-modül " olarak düşünün .
    • Gibi bazı millet @ hij1nx bile dahil app/node_modulesdizin ve sahip package.jsondosyaları proto-modül o geçişi kolaylaştırmak ve bir hatırlatma olarak hareket etmek dizinleri.
  • Kodu bulmak kolay olmalı
    • Oluşturulması gereken bir özellik veya düzeltilecek bir hata göz önüne alındığında, amacımız bir geliştiricinin ilgili kaynak dosyaları bulma konusunda hiçbir mücadelesi olmamasıdır.
    • İsimler anlamlı ve doğru
    • crufty kodu tamamen kaldırılır, bir yetim dosyasında bırakılmaz veya yorum yapılmaz
  • Arama dostu olun
    • tüm birinci taraf kaynak kodu appdizinde bulunur, böylece cdfind / grep / xargs / ag / ack / etc dosyasını çalıştırabilir ve üçüncü taraf eşleşmeleriyle dikkatinizi dağıtamazsınız
  • Basit ve açık adlandırma kullanın
    • npm artık küçük harfli paket adları gerektiriyor gibi görünüyor. Bunu çoğunlukla korkunç buluyorum, ancak sürüyü takip etmeliyim, bu yüzden kebab-caseJavaScript'te bunun için değişken adı olması gerekir camelCaseçünkü JavaScript'te -bir eksi işareti olmalıdır .
    • Değişken adı modül yolunun basename eşleşir, ancak birlikte kebab-casedönüştürülmüşcamelCase
  • Bağlantıya Göre Grupla, İşlevine Göre Değil
    • Bu Ruby on Rails toplantıdan çok önemli bir ayrımdır app/views, app/controllers, app/modelsvb
    • Özellikler tam bir yığına eklenir, bu yüzden özelliğimle ilgili olan tam bir dosya yığınına odaklanmak istiyorum. Kullanıcı modeline bir telefon numarası alanı eklerken, kullanıcı denetleyicisi dışında herhangi bir denetleyicinin umrunda değilim ve kullanıcı modeli dışında hiçbir modelin umrunda değil.
    • Bu nedenle, her biri kendi dizininde bulunan 6 dosyayı düzenlemek ve bu dizinlerdeki tonlarca başka dosyayı yok saymak yerine, bu havuz, bir özellik oluşturmak için ihtiyacım olan tüm dosyaların yerleştirileceği şekilde düzenlenmiştir.
    • MVC'nin doğası gereği, kullanıcı görünümü, kullanıcı modeline bağlanan kullanıcı denetleyicisine bağlanır. Bu nedenle, kullanıcı modelini değiştirdiğimde, bu 3 dosya genellikle birlikte değişecektir, ancak fırsatlar denetleyicisi veya müşteri denetleyicisi birbirinden ayrılmıştır ve bu nedenle dahil değildir. Aynı durum genellikle MVC olmayan tasarımlar için de geçerlidir.
    • Hangi kodun hangi modülde teşvik edildiği konusunda MVC veya MOVE stili ayrıştırma, ancak MVC dosyalarını kardeş dizinlere yaymak sadece sinir bozucu.
    • Böylece her rota dosyamda sahip olduğu yolların bir kısmı var. Raylar tarzı bir routes.rbdosya, uygulamadaki tüm rotalara genel bir bakış istiyorsanız, ancak aslında özellikler oluştururken ve hataları giderirken, yalnızca değiştirdiğiniz parça ile ilgili rotaları önemsersiniz.
  • Testleri kodun yanında saklayın
    • Bu sadece "gruplama kaplini" nin bir örneğidir, ama özellikle söylemek istedim. Testlerin "testler" adlı paralel bir dosya sistemi altında yaşadığı birçok proje yazdım ve şimdi testlerimi karşılık gelen kodlarıyla aynı dizine koymaya başladım, asla geri dönmüyorum. Bu daha modülerdir ve metin editörlerinde çalışmak çok daha kolaydır ve bir çok "../../ .." yol saçmalıklarını hafifletir. Şüpheniz varsa, birkaç projede deneyin ve kendiniz karar verin. Sizi daha iyi olduğuna ikna etmek için bunun ötesinde hiçbir şey yapmayacağım.
  • Events ile çapraz kesimi azaltın
    • "Tamam, ne zaman yeni bir Anlaşma oluşturulursa, tüm Satış Elemanlarına bir e-posta göndermek istiyorum" ve sonra sadece bu e-postaları anlaşma oluşturan rotaya göndermek için kod koymak düşünmek kolaydır.
    • Ancak, bu bağlantı sonunda uygulamanızı dev bir çamur topuna dönüştürecektir.
    • Bunun yerine, DealModel bir "create" olayı başlatmalı ve sistemin buna yanıt olarak başka neler yapabileceğinin tamamen farkında olmamalıdır.
    • Bu şekilde kod yazdığınızda app/users, kullanıcı kodu tabanının saflığını kirleten her yerde bir sıçanın birleşmiş iş mantığı yuvası olmadığından , kullanıcı ile ilgili tüm kodları koymak çok daha mümkün hale gelir .
  • Kod akışı takip edilebilir
    • Sihirli şeyler yapma. Dosyaları dosya sistemindeki sihirli dizinlerden otomatik olarak yüklemeyin. Ray olma. Uygulama başlar app/server.js:1ve kodu izleyerek yüklediği ve yürüttüğü her şeyi görebilirsiniz.
    • Rotanız için DSL yapmayın. Gerekmediğinde saçma metaprogramlama yapmayın.
    • Uygulamanızın yapıyor o kadar büyükse magicRESTRouter.route(somecontroller, {except: 'POST'})büyük bir kazançtır için baştan 3 temel app.get, app.put, app.del, çağrılar, muhtemelen etkili bir çalışmaya çok büyük bir monolitik app inşa ediyoruz. 3 basit çizgiyi 1 karmaşık çizgiye dönüştürmek için değil, BÜYÜK kazançlar için süslü olun.
  • Küçük kebap büyüklüğünde dosya adları kullanın

    • Bu biçim, platformlar arasında dosya sistemi büyük / küçük harfe duyarlılık sorunlarını önler
    • npm, yeni paket adlarında büyük harf kullanımını yasaklar ve bu,

      express.js özellikleri

  • Kullanma app.configure. Neredeyse tamamen işe yaramaz ve ihtiyacınız yok. Akılsız kopya macunu nedeniyle çok sayıda kazan plakasında.

  • EKSPRES HUSUSLARDA ORTAOKUL VE ROTALARIN SİPARİŞİ !!!
    • Stackoverflow'da gördüğüm hemen her yönlendirme sorunu sıra dışı ekspres ara katman yazılımı
    • Genel olarak, rotalarınızın birbirinden ayrılmasını ve bu kadar sıraya dayanmamasını istiyorsunuz.
    • app.useGerçekten sadece 2 yol için bu katman yazılımına ihtiyacınız varsa tüm uygulamanız için kullanmayın (Sana bakıyorum, body-parser)
    • Her şey söylendiğinde ve bittiğinde bu siparişi TAMAMEN aldığınızdan emin olun:
      1. Çok önemli, uygulama genelinde ara katman yazılımı
      2. Tüm rotalarınız ve çeşitli rota ara yazılımları
      3. THEN hata işleyicileri
  • Ne yazık ki, sinatra esinlenerek, express.js çoğunlukla tüm rotalarınızın olacağını varsayar server.jsve bunların nasıl sipariş edildiğini netleştirir. Orta ölçekli bir uygulama için, işleri ayrı rota modüllerine bölmek güzeldir, ancak sıra dışı ara katman yazılımlarının tehlikesini ortaya çıkarır

Uygulama symlink hilesi

Topluluk tarafından büyük özde Node.js için daha iyi yerel gereksinim () yollarında özetlenen ve tartışılan birçok yaklaşım vardır . Yakında ya "sadece ../../../ .." bir sürü anlaşma tercih ya da requirFrom modlue kullanmaya karar verebilir. Ancak, şu anda aşağıda ayrıntıları verilen symlink numarasını kullanıyorum.

Proje içi rahatsızlıktan kaçınmanın bir yolu require("../../../config"), aşağıdaki gibi hileli rahatsız edici yollar gerektirir :

  • uygulamanız için node_modules altında bir sembolik bağlantı oluşturun
    • cd node_modules && ln -nsf ../app
  • git'e node_modules klasörünün tamamını değil, yalnızca node_modules / app symlink'in kendisini ekleyin
    • git add -f node_modules / app
    • Evet, yine de .gitignoredosyanızda "node_modules" olmalıdır
    • Hayır, git deponuza "node_modules" koymamalısınız. Bazı insanlar bunu yapmanızı tavsiye eder. Yanlış.
  • Artık bu öneki kullanarak proje içi modüllere ihtiyaç duyabilirsiniz
    • var config = require("app/config");
    • var DealModel = require("app/deals/deal-model");
  • Temel olarak, bu proje içi gerektirir harici npm modülleri için çok benzer çalışma gerektirir.
  • Maalesef, Windows kullanıcıları, üst dizine ilişkin yollara bağlı kalmalısınız.

Yapılandırma

Genellikle modülleri ve sınıfları yalnızca temel bir JavaScript optionsnesnesinin geçmesini beklemek üzere kodlayın . Yalnızca modülü app/server.jsyüklemelidir app/config.js. Oradan options, alt sistemleri gerektiği gibi yapılandırmak için küçük nesneleri sentezleyebilir , ancak her alt sistemi fazladan bilgi içeren büyük bir global yapılandırma modülüne bağlamak kötü bağlantıdır.

DB bağlantılarının oluşturulmasını merkezileştirmeye çalışın ve bunları bağlantı parametrelerini geçmekten ve alt sistemlerin giden bağlantıları kendileri yapmasının aksine alt sistemlere geçirmeye çalışın.

NODE_ENV

Bu, Rails'ten taşınan bir başka cazip ama korkunç fikir. Uygulamanızda ortam değişkenine app/config.jsbakan tam olarak 1 yer olmalıdır NODE_ENV. Diğer her şey bir sınıf yapıcı argümanı veya modül yapılandırma parametresi olarak açık bir seçenek almalıdır.

E-posta modülünde e-postaların nasıl gönderileceği seçeneği varsa (SMTP, stdout'a giriş, sıraya koyma vb.), Bunun gibi bir seçenek almalıdır, {deliver: 'stdout'}ancak kesinlikle kontrol etmemelidir NODE_ENV.

Testler

Şimdi test dosyalarımı karşılık gelen kodlarıyla aynı dizinde tutuyorum ve testleri üretim kodundan ayırmak için dosya adı uzantısı adlandırma kurallarını kullanıyorum.

  • foo.js modül "foo" koduna sahip
  • foo.tape.js foo için düğüm tabanlı testlere sahip ve aynı direkte yaşıyor
  • foo.btape.js tarayıcı ortamında yürütülmesi gereken testler için kullanılabilir

find . -name '*.tape.js'Gerektiğinde tüm testlerime erişmek için dosya sistemi glob'larını ve komutunu kullanıyorum.

Her .jsmodül dosyası içindeki kod nasıl düzenlenir

Bu projenin kapsamı çoğunlukla dosyaların ve dizinlerin nereye gittiği ile ilgilidir ve başka bir kapsam eklemek istemiyorum, ancak kodumu 3 ayrı bölüm halinde organize ettiğimi söyleyeceğim.

  1. CommonJS'nin açılış bloğu, eyalet bağımlılıklarına çağrı yapılmasını gerektirir
  2. Saf JavaScript'in ana kod bloğu. Burada CommonJS kirliliği yok. Dışa aktarma, modül veya gereksinimlere referans vermeyin.
  3. İhracat kurmak için CommonJS'nin kapanış bloğu

1
BodyParser yerine ne kullanmalıyım? Bunu kullanan yalnızca birkaç yolum varsa?
Ilan Frumer

3
Burada aradığımı buldum: stackoverflow.com/questions/12418372/…
Ilan Frumer

1
@wlingke bu soruna yönelik mevcut yaklaşımların kapsamlı bir tartışması için gist.github.com/branneman/8048520 adresine bakın.
Peter Lyons

@peterLyons Bunu paylaştığınız için teşekkürler. Okuduktan sonra sanırım bir başlangıç ​​senaryosu yazacağım. Teşekkürler!
wlingke

2
açısından uygulama Sembolik bağ hile , orada bu tüm sorunlar gitmek yapar küçük modül
Hayko Koryun

157

GÜNCELLEME (2013-10-29) : Lütfen popüler talebe göre CoffeeScript yerine JavaScript'in yanı sıra bir kazan plakası github repo ve bu konudaki en son önerilerimi detaylandıran kapsamlı bir README olan diğer cevabımı da görün.

Yapılandırma

Yaptığın iyi. Kendi yapılandırma ad config.coffeealanımın böyle bir yuvalanmış ad alanı olan üst düzey bir dosyada ayarlanmasını seviyorum.

#Set the current environment to true in the env object
currentEnv = process.env.NODE_ENV or 'development'
exports.appName = "MyApp"
exports.env =
  production: false
  staging: false
  test: false
  development: false
exports.env[currentEnv] = true
exports.log =
  path: __dirname + "/var/log/app_#{currentEnv}.log"
exports.server =
  port: 9600
  #In staging and production, listen loopback. nginx listens on the network.
  ip: '127.0.0.1'
if currentEnv not in ['production', 'staging']
  exports.enableTests = true
  #Listen on all IPs in dev/test (for testing from other machines)
  exports.server.ip = '0.0.0.0'
exports.db =
  URL: "mongodb://localhost:27017/#{exports.appName.toLowerCase()}_#{currentEnv}"

Bu sistem yöneticisi düzenleme için uygundur. Sonra DB bağlantı bilgisi gibi bir şeye ihtiyacım olduğunda,

require('./config').db.URL

Rotalar / Kontrolörler

Rotalarımı kontrolörlerimle bırakıp bir app/controllersalt dizinde organize etmeyi seviyorum . Sonra onları yükleyebilir ve ihtiyaç duydukları her yolu eklemelerine izin verebilirim.

Benim içinde app/server.coffeeCoffeeScript dosyası yapmam:

[
  'api'
  'authorization'
  'authentication'
  'domains'
  'users'
  'stylesheets'
  'javascripts'
  'tests'
  'sales'
].map (controllerName) ->
  controller = require './controllers/' + controllerName
  controller.setup app

Yani gibi dosyaları var:

app/controllers/api.coffee
app/controllers/authorization.coffee
app/controllers/authentication.coffee
app/controllers/domains.coffee

Örneğin, etki alanı denetleyicimde böyle bir setupişlevim var .

exports.setup = (app) ->
  controller = new exports.DomainController
  route = '/domains'
  app.post route, controller.create
  app.put route, api.needId
  app.delete route, api.needId
  route = '/domains/:id'
  app.put route, controller.loadDomain, controller.update
  app.del route, controller.loadDomain, exports.delete
  app.get route, controller.loadDomain, (req, res) ->
    res.sendJSON req.domain, status.OK

Görüntüleme

Görünüm koymak app/views, alışılmış bir yer haline geliyor. Ben böyle yerleştirdim.

app/views/layout.jade
app/views/about.jade
app/views/user/EditUser.jade
app/views/domain/EditDomain.jade

Statik Dosyalar

Bir publicalt dizine gidin.

Github / Semver / NPM

Github için git repo köküne bir README.md markdown dosyası koyun.

NPM için git repo köküne anlamsal sürüm numarası içeren bir package.json dosyası koyun .


1
Hey Peter! Bu yaklaşımı gerçekten seviyorum. Ekspres bir proje üzerinde çalışıyorum ve işleri doğru şekilde yapmak ve onu kesmek ve yerleştirmek yerine gerçekten doğru şekilde yapmak istiyorum. Eğer github üzerinde örnek bir repo ve / veya üzerinde bir blog yazısı olsaydı mükemmel olurdu.
suVasH .....

4
Bu repo referans olarak kullanabileceğiniz bir sürü desen var: github.com/focusaurus/peterlyons.com
Peter Lyons

75
Kahve betiği bu okumayı zorlaştırır: / Vanilya JS düzenleme şansı var mı? Teşekkürler
toasted_flakes

1
Bu cevap için teşekkürler. Sadece zihnimi etrafına sarmaya çalışıyorum. Bir başkasının içindeki diğer denetleyicilere nasıl erişirsiniz (örn. Yukarıdaki gibi kurulum işlevindeapp.put route, api.needId
chmanie

@PeterLyons: hey adam, ben kaynak kodunu gördün ama nasıl inşa modu yapmak için hiçbir fikrim yok, ben zaten yüklü Gove binyapıya dosyayı dahil ettik . Bu godosyayı nasıl çalıştırıyorsunuz bin?
user2002495

51

Aşağıda, diğerlerinin talep ettiği gibi, Coffeescript'ten vanilya JS'ye gönderilen Peter Lyons'ın cevabı kelimesi kelimesine yazılmıştır. Peter'ın cevabı çok yeteneklidir ve cevabımı oylayan herkes de ona oy vermelidir.


Yapılandırma

Yaptığın iyi. Kendi yapılandırma ad config.jsalanımın böyle bir yuvalanmış ad alanı olan üst düzey bir dosyada ayarlanmasını seviyorum.

// Set the current environment to true in the env object
var currentEnv = process.env.NODE_ENV || 'development';
exports.appName = "MyApp";
exports.env = {
  production: false,
  staging: false,
  test: false,
  development: false
};  
exports.env[currentEnv] = true;
exports.log = {
  path: __dirname + "/var/log/app_#{currentEnv}.log"
};  
exports.server = {
  port: 9600,
  // In staging and production, listen loopback. nginx listens on the network.
  ip: '127.0.0.1'
};  
if (currentEnv != 'production' && currentEnv != 'staging') {
  exports.enableTests = true;
  // Listen on all IPs in dev/test (for testing from other machines)
  exports.server.ip = '0.0.0.0';
};
exports.db {
  URL: "mongodb://localhost:27017/#{exports.appName.toLowerCase()}_#{currentEnv}"
};

Bu sistem yöneticisi düzenleme için uygundur. Sonra DB bağlantı bilgisi gibi bir şeye ihtiyacım olduğunda,

require('./config').db.URL

Rotalar / Kontrolörler

Rotalarımı kontrolörlerimle bırakıp bir app/controllersalt dizinde organize etmeyi seviyorum . Sonra onları yükleyebilir ve ihtiyaç duydukları her yolu eklemelerine izin verebilirim.

Benim içinde app/server.jsJavascript dosyasında yapmam:

[
  'api',
  'authorization',
  'authentication',
  'domains',
  'users',
  'stylesheets',
  'javascripts',
  'tests',
  'sales'
].map(function(controllerName){
  var controller = require('./controllers/' + controllerName);
  controller.setup(app);
});

Yani gibi dosyaları var:

app/controllers/api.js
app/controllers/authorization.js
app/controllers/authentication.js
app/controllers/domains.js

Örneğin, etki alanı denetleyicimde böyle bir setupişlevim var .

exports.setup = function(app) {
  var controller = new exports.DomainController();
  var route = '/domains';
  app.post(route, controller.create);
  app.put(route, api.needId);
  app.delete(route, api.needId);
  route = '/domains/:id';
  app.put(route, controller.loadDomain, controller.update);
  app.del(route, controller.loadDomain, function(req, res){
    res.sendJSON(req.domain, status.OK);
  });
}

Görüntüleme

Görünüm koymak app/views, alışılmış bir yer haline geliyor. Ben böyle yerleştirdim.

app/views/layout.jade
app/views/about.jade
app/views/user/EditUser.jade
app/views/domain/EditDomain.jade

Statik Dosyalar

Bir publicalt dizine gidin.

Github / Semver / NPM

Github için git repo köküne bir README.md markdown dosyası koyun.

NPM için git repo köküne anlamsal sürüm numarası içeren bir package.json dosyası koyun .


43

Sorum Nisan 2011'de tanıtıldı, sessiz eski. Bu süre zarfında, Express.js ile olan deneyimimi ve bu kitaplığı kullanarak yazılmış bir uygulamanın nasıl mimarileceğini geliştirebilirim. Burada deneyimimi paylaşıyorum.

İşte benim dizin yapısı:

├── app.js   // main entry
├── config   // The configuration of my applications (logger, global config, ...)
├── models   // The model data (e.g. Mongoose model)
├── public   // The public directory (client-side code)
├── routes   // The route definitions and implementations
├── services // The standalone services (Database service, Email service, ...)
└── views    // The view rendered by the server to the client (e.g. Jade, EJS, ...)

App.js

Hedefi app.jsdosyası expressjs uygulamasını bootstrap etmektir. Konfigürasyon modülünü, logger modülünü yükler, veritabanı bağlantısını bekleyin, ... ve ekspres sunucuyu çalıştırın.

'use strict';
require('./config');
var database = require('./services/database');
var express = require('express');
var app = express();
module.exports = app;

function main() {
  var http = require('http');

  // Configure the application.
  app.configure(function () {
    // ... ... ...
  });
  app.configure('production', function () {
    // ... ... ...
  });
  app.configure('development', function () {
    // ... ... ...
  });

  var server = http.createServer(app);

  // Load all routes.
  require('./routes')(app);

  // Listen on http port.
  server.listen(3000);
}

database.connect(function (err) {
  if (err) { 
    // ...
  }
  main();
});

yolları /

Route dizini bir index.jsdosyaya sahiptir. Amacı, routes/dizindeki diğer tüm dosyaları yüklemek için bir tür sihir tanıtmaktır . İşte uygulama:

/**
 * This module loads dynamically all routes modules located in the routes/
 * directory.
 */
'use strict';
var fs = require('fs');
var path = require('path');

module.exports = function (app) {
  fs.readdirSync('./routes').forEach(function (file) {
    // Avoid to read this current file.
    if (file === path.basename(__filename)) { return; }

    // Load the route file.
    require('./' + file)(app);
  });
};

Bu modül ile yeni bir rota tanımı ve uygulaması oluşturmak gerçekten çok kolay. Örnekler için hello.js:

function hello(req, res) {
  res.send('Hello world');
}

module.exports = function (app) {
  app.get('/api/hello_world', hello);
};

Her bir rota modülü bağımsızdır .


Bu yapıyı oluşturmak için bir jeneratör kullanıyor musunuz?
Ashish


17

Bence bunu yapmanın harika bir yolu. İfade etmekle sınırlı değil ama aynı şeyi yapan github'da oldukça fazla sayıda node.js projesi gördüm. Konfigürasyon parametrelerini + daha küçük modülleri (bazı durumlarda her URI) ayrı dosyalarda hesaba katarlar.

Bir fikir edinmek için github'daki ekspres spesifik projelere bakmanızı tavsiye ederim. IMO yaptığınız yol doğrudur.


16

şu anda 2015 sonu ve 3 yıl boyunca yapımı geliştirdikten sonra küçük ve büyük projelerde. Sonuç?

Büyük bir MVC yapmayın, ancak modüller halinde ayırın

Yani...

Neden?

  • Genellikle bir modül bağımsız olarak değiştirebileceğiniz bir modül (örn. Ürünler) üzerinde çalışır.

  • Modülleri tekrar kullanabilirsiniz

  • Ayrı ayrı test edebilirsiniz

  • Ayrı olarak değiştirebilirsiniz

  • Net (kararlı) arayüzleri var

    -En sonunda, birden fazla geliştirici çalışıyorsa, modül ayırma yardımcı olur

Nodebootstrap proje benim son yapıya benzer bir yaklaşım vardır. ( github )

Bu yapı nasıl görünüyor?

  1. Her biri ayrı MVC'ye sahip küçük, kapsüllü modüller

  2. Her modülün bir paketi vardır. Json

  3. Yapının bir parçası olarak test etme (her modülde)

  4. Global yapılandırma , kütüphaneler ve Hizmetler

  5. Entegre Docker, Küme, sonsuza kadar

Folderoverview (modüller için lib klasörüne bakınız):

nodebootstrap yapısı


3
Klasöre genel bakış resmini, genişletilmiş ayrı modüller ile de güncelleyebilmeniz yararlı olabilir, ayrıca bunları nasıl yapılandıracağınıza bir örnek olarak.
16:20

8

MVC tarzı klasör yapısı veriyorum feryat bulabilirsiniz.

Büyük ve orta büyüklükteki web uygulamalarımız için feryat klasör yapısını kullandık.

 myapp   
|
|
|____app
|      |____controllers
|      |    |____home.js
|      |
|      |____models
|      |     |___home.js
|      |
|      |____views
|           |___404.ejs
|           |___error.ejs
|           |___index.ejs
|           |___login.ejs
|           |___signup.ejs
|   
|
|_____config
|     |___auth.js
|     |___constants.js
|     |___database.js
|     |___passport.js
|     |___routes.js
|
|
|____lib
|    |___email.js
|
|____node_modules
|
|
|____public.js
|    |____css
|    |    |__style.css
|    |    
|    |____js
|    |    |__script.js
|    |
|    |____img
|    |    |__img.jpg
|    |
|    |
|    |____uploads
|         |__img.jpg
|      
|   
|
|_____app.js
|
|
|
|_____package.json

Ben nesil ekspres mvc klasör yapılandırıcı için bir npm modülü oluşturduk.

Lütfen aşağıdaki https://www.npmjs.com/package/express-mvc-generator adresini bulun

Bu modülleri oluşturmak ve kullanmak için basit adımlar.

i) kurulum modülü npm install express-mvc-generator -g

ii) kontrol seçenekleri express -h

iii) Hızlı mvc yapısı oluşturmak express myapp

iv) Kurulum bağımlılıkları npm install::

v) config / database.js dosyasını açın, Lütfen mongo db'nizi yapılandırın.

vi) Uygulamayı çalıştırın node appveyanodemon app

vii) URL'yi kontrol edin http: // localhost: 8042 / kayıt VEYA http: // yourip: 8042 / kayıt


7

Bu sorunun son cevabından bu yana epey zaman geçti ve Express son zamanlarda uygulama yapınızı düzenlemek için birkaç yararlı şey ekleyen sürüm 4'ü yayınladı.

Aşağıda, Express uygulamanızı nasıl yapılandıracağınızla ilgili en iyi uygulamalar hakkında uzun bir blog yazısı bulunmaktadır. http://www.terlici.com/2014/08/25/best-practices-express-structure.html

Makalede tavsiyeyi uygulayan bir GitHub deposu da var. Her zaman en son Express sürümü ile günceldir.
https://github.com/terlici/base-express


7

Yapılandırmaya rota eklemenin iyi bir yaklaşım olduğunu düşünmüyorum. Daha iyi bir yapı şöyle olabilir:

application/
| - app.js
| - config.js
| - public/ (assets - js, css, images)
| - views/ (all your views files)
| - libraries/ (you can also call it modules/ or routes/)
    | - users.js
    | - products.js
    | - etc...

Yani products.js ve users.js içerisindeki tüm rotalarınızı içerecektir.


6

Yollarımı bir json dosyası olarak koydum, başlangıçta okudum ve app.js'de bir for-loop'ta rotaları kurdum. Route.json, hangi görünümün çağrılması gerektiğini ve rotaya gönderilecek değerlerin anahtarını içerir.
Bu birçok basit durum için işe yarar, ancak özel durumlar için manuel olarak bazı yollar oluşturmak zorunda kaldım.


6

Bu konuda tam olarak bir yazı yazdım. Temelde işlevini çağıran routeRegistrarklasördeki dosyalar üzerinden yinelenen bir kullanır . İşlev , express değişkenini parametre olarak alır, böylece rotalarınızı istediğiniz şekilde kaydedebilirsiniz./controllersinitinitapp

var fs = require("fs");
var express = require("express");
var app = express();

var controllersFolderPath = __dirname + "/controllers/";
fs.readdirSync(controllersFolderPath).forEach(function(controllerName){
    if(controllerName.indexOf("Controller.js") !== -1){
        var controller = require(controllersFolderPath + controllerName);
        controller.init(app);
    }
});

app.listen(3000);


4

1) Express proje dosya sisteminiz aşağıdaki gibi olabilir:

/ ...
/lib
/node_modules
/public
/views
      app.js
      config.json
      package.json

app.js - küresel uygulama kapsayıcısı siz

2) Modül ana dosyası (lib / mymodule / index.js):

var express = require('express');    
var app = module.exports = express();
// and load module dependencies ...  

// this place to set module settings
app.set('view engine', 'jade');
app.set('views', __dirname + '/views');

// then do module staff    
app.get('/mymodule/route/',function(req,res){ res.send('module works!') });

3) Ana app.js'deki modülü bağlayın

...
var mymodule = require('mymodule');
app.use(mymodule);

4) Örnek mantık

lib/login
lib/db
lib/config
lib/users
lib/verify
lib/
   /api/ 
   ...
lib/
   /admin/
      /users/
      /settings/
      /groups/
...
  • Test için en iyisi
  • Ölçek için en iyisi
  • Ayrı modüle bağlıdır
  • Rotayı işleve (veya modüllere) göre gruplama

tj , Vimeo'da ekspres uygulamayı nasıl modülerleştirdiğini ilginç bir şekilde söylüyor / göster - Node.js ve Express ile modüler web uygulamaları . Güçlü ve basit.


4

http://locomotivejs.org/ , Node.js ve Express ile oluşturulan bir uygulamayı yapılandırmanın bir yolunu sunar.

Web sitesinden:

"Lokomotif, Node.js için bir web çerçevesidir. Lokomotif, herhangi bir veritabanı ve şablon motoruyla sorunsuz bir şekilde bütünleşirken MVC kalıplarını, RESTful rotaları ve konfigürasyon üzerinde konvansiyonu destekler. Düğümden. "


3

Son zamanlarda modülleri bağımsız mini uygulamalar olarak benimsedim.

|-- src
  |--module1
  |--module2
     |--www
       |--img
       |--js
       |--css
     |--#.js
     |--index.ejs
  |--module3
  |--www
     |--bower_components
     |--img
     |--js
     |--css
  |--#.js
  |--header.ejs
  |--index.ejs
  |--footer.ejs

Şimdi herhangi bir modül yönlendirmesi (# .js) için görünümler (* .ejs), js, css ve varlıklar yan yana. alt modül yönlendirmesi üst # .js'de iki ek satırla kurulur

router.use('/module2', opt_middleware_check, require('./module2/#'));
router.use(express.static(path.join(__dirname, 'www')));

Bu şekilde sub-submodüller bile mümkündür.

Görünümü src dizinine ayarlamayı unutmayın

app.set('views', path.join(__dirname, 'src'));

Github'a, yolların, görüşlerin ve modellerin nasıl yüklendiğini görmekle ilgilenen böyle bir yapıya sahip herhangi bir bağlantı
Muhammad Umer

Her şeyin açıklandığını düşünüyorum. Güzergahlar sadece klasik ekspres güzergahlardır. Görünümlerin modül adları ile ön ekine yüklenmesi, modellerin ilgili yola referansla yüklenmesi gerekir.
zevero

Son satırımda, görünümü src dizinine ayarladım. Böylece buradan tüm görünümlere src dizinine göre erişilebilir. Hiçbir şey fantezi.
zevero

1

Ekspres proje dizin yapımın çoğu böyle görünüyor.

Genellikle express dirnameprojeyi başlatmak, tembellikimi affetmek için bir şey yaparım , ancak çok esnek ve uzatılabilir. PS - bunun için almanız gerekiyor express-generator(arayanlar için sudo npm install -g express-generatorsudo, çünkü küresel olarak kuruyorsunuz)

|-- bin
    |-- www //what we start with "forever"
|-- bower_components
|-- models
    |-- database.js
    |-- model1.js //not this exact name ofcourse.
    |-- .
|-- node_modules
|-- public
    |-- images
    |-- javascripts
        |-- controllers
        |-- directives
        |-- services
        |-- app.js
        |-- init.js //contains config and used for initializing everything, I work with angular a lot.
    |-- stylesheets
|-- routes
    |-- some
    |-- hierarchy
    .
    .
|-- views
    |-- partials
    |-- content
|-- .env
|-- .env.template
|-- app.js
|-- README.md

Neden .env dosyalarını merak ediyor olmalısınız? Çünkü çalışıyorlar! dotenvProjelerimde modül kullanıyorum (çok yakın zamanda) ve işe yarıyor! Bu 2 ifadeyi app.jsveyawww

var dotenv = require('dotenv');
dotenv.config({path: path.join(__dirname + "/.env")});

Ve /bower_componentskaynak altında statik içerik sunmak için hızlı bir şekilde ayarlanacak başka bir satır/ext

app.use('/ext', express.static(path.join(__dirname, 'bower_components')));

Muhtemelen Express ve Angular'ı birlikte kullanmak isteyen veya javascriptselbette bu hiyerarşi olmadan ifade eden insanlar için uygun olabilir .


1

Yapım ekspres 4. https://github.com/odirleiborgert/borgert-express-boilerplate

Paketler

View engine: twig
Security: helmet
Flash: express-flash
Session: express-session
Encrypt: bcryptjs
Modules: express-load
Database: MongoDB
    ORM: Mongoose
    Mongoose Paginate
    Mongoose Validator
Logs: winston + winston-daily-rotate-file
Nodemon
CSS: stylus
Eslint + Husky

yapı

|-- app
    |-- controllers
    |-- helpers
    |-- middlewares
    |-- models
    |-- routes
    |-- services
|-- bin
|-- logs
|-- node_modules
|-- public
    |-- components
    |-- images
    |-- javascripts
    |-- stylesheets
|-- views
|-- .env
|-- .env-example
|-- app.js
|-- README.md

0

Ur express uygulamasını yapılandırmak için basit bir yol:

  • Main index.js dosyasında aşağıdaki sıra korunmalıdır.

    tüm app.set ilk olmalıdır.

    tüm app.use ikinci olmalıdır.

    ardından diğer apislerin işlevleri ile birlikte veya diğer dosyalarda rota devam et

    Exapmle

    app.use ("/ password", passwordApi);

    app.use ("/ kullanıcı", userApi);

    app.post ("/ token", passport.createToken);

    app.post ("/ oturum kapatma", pasaport.logout)


0

Gidon ve Passportjs ile ExpressJs Projesi için MVC Yapısına En İyi Yol

- app
      -config 
        -passport-setup.js
      -controllers
      -middleware
      -models
      -routes
      -service
    -bin
      -www
      -configuration.js
      -passport.js
    -node_modules
    -views
     -handlebars page
    -env
    -.gitignore
    -package.json
    -package-lock.json

@ sandro-munda lütfen kontrol edin
Manishkumar Bhavnani
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.