express.js 애플리케이션을 구성하는 방법은 무엇입니까?


102

Express.js 애플리케이션 app.js에서 파일 을 분할하고 모듈화하는 일반적인 규칙이 있습니까? 아니면 모든 것을 하나의 파일에 보관하는 것이 일반적입니까?


3
사람들이 그들을 경로로 나누었습니다. 또한 익스프레스 리소스를 살펴볼 수 있습니다.
BRampersad

@Brandon_R 리소스를 사용해 보셨습니까? 나는 그것을 흘끗 보았고 그것이 깔끔해 보인다고 생각했고, 단지 아직 타이어를 걷어 차지 않았다.
Chance

1
조금 늦었지만 최근에 app.js 인트로 컨트롤러 + 뷰 등을 멋지게 분할 할 수있는 express 용 라우터를 오픈 소스했습니다. 참조 : github.com/kishorenc/road
jeffreyveon

답변:


82

나는 다음과 같이 분해했다.

~/app
|~controllers
| |-monkey.js
| |-zoo.js
|~models
| |-monkey.js
| |-zoo.js
|~views
| |~zoos
|   |-new.jade
|   |-_form.jade
|~test
|  |~controllers
|    |-zoo.js
|  |~models
|    |-zoo.js
|-index.js

나는 수출을 사용하여 관련된 것을 반환합니다. 예를 들어, 내가하는 모델에서 :

module.exports = mongoose.model('PhoneNumber', PhoneNumberSchema);

전화 번호를 만들어야하는 경우 다음과 같이 간단합니다.

var PhoneNumber = require('../models/phoneNumber');
var phoneNumber = new PhoneNumber();

스키마를 사용해야하는 경우 PhoneNumber.schema

(이는 경로 폴더에서 작업하고 있으며 한 수준 위로 이동 한 다음 모델로 내려 가야한다고 가정)


4 편집

명시 위키는 그것의 상단에 내장 프레임 워크의 목록이 있습니다.

그중 트위터의 투우사 는 꽤 잘 구성되어 있다고 생각 합니다. 실제로 앱의 일부를로드하는 방법과 매우 유사한 접근 방식을 사용했습니다.

derby.js 도 매우 흥미로워 보입니다. 모든 과대 광고가없는 유성 과 비슷하며 실제로 신용이 필요한 곳에 신용을 부여합니다 (특히 노드 및 표현).


3 편집

CoffeeScript의 팬이고 (나는 아닙니다) Rails의 L & F를 원하신다면 Tower.js있습니다 .


2 편집

Rails에 익숙하고 일부 개념의 블리드 오버에 신경 쓰지 않는다면 Locomotive가 있습니다. Express를 기반으로하는 경량 프레임 워크입니다. RoR과 매우 유사한 구조를 가지고 있으며 좀 더 기본적인 개념 (예 : 라우팅)을 전달합니다.

사용할 계획이 없더라도 확인해 볼 가치가 있습니다.


1 편집

nodejs-express-mongoose-demo 는 내가 구조화 한 방식과 매우 유사합니다. 확인 해봐.


2
비즈니스 로직은 어디에 있습니까? 인증과 같은 일에 헬퍼를 사용한 적이 있습니까?
Eric the Red

@ErictheRed MVC 패턴 (rails, Asp.Net mvc 등)에 익숙하다면 내 경로를 내 컨트롤러로 간주하고 그 이후에 모든 종류가 제자리에 있습니다. 비즈니스 로직은 모델에 포함됩니다 (하지만 유효성 검사 및 몽구스에는 어려움이 있습니다). 도우미의 경우 재사용을 위해 직접 모아 놓은 간단한 내부 유틸리티 라이브러리에서 내보내기를 사용합니다.
Chance

우리가 살펴볼 수 있도록 샘플 설정을 github에 업로드하는 것이 좋습니다. Routes 폴더 / 파일에는 무엇이 들어가나요?
chovy

1
@chovy 매우 유사한 구조를 가진 github.com/qed42/nodejs-express-mongoose-demo 링크를 추가했습니다
Chance

Express를 기반으로 구축 된
비대해진

9

경고 : 노드 녹아웃을 위해 함께 해킹 한 코드를 참조하면 작동하지만 우아하거나 세련되지는 않습니다.

분할에 대해 더 구체적으로 설명하기 app.js위해 다음 app.js 파일이 있습니다.

var express = require('express'),
    bootstrap = require('./init/bootstrap.js'),
    app = module.exports = express.createServer();

bootstrap(app);

이것은 기본적으로 모든 부트 스트랩을 별도의 파일에 배치 한 다음 서버를 부트 스트랩한다는 것을 의미합니다.

그렇다면 부트 스트랩 은 무엇을합니까?

var configure = require("./app-configure.js"),
    less = require("./watch-less.js"),
    everyauth = require("./config-everyauth.js"),
    routes = require("./start-routes.js"),
    tools = require("buffertools"),
    nko = require("nko"),
    sessionStore = new (require("express").session.MemoryStore)()

module.exports = function(app) {
    everyauth(app);
    configure(app, sessionStore);
    less();
    routes(app, sessionStore);
    nko('/9Ehs3Dwu0bSByCS');


    app.listen(process.env.PORT);
    console.log("server listening on port xxxx");
};

모든 서버 초기화 설정을 멋진 덩어리로 나눕니다. 구체적으로 특별히

  • everyauth를 사용하여 모든 원격 OAuth 인증을 설정하는 청크가 있습니다.
  • 내 응용 프로그램을 구성하는 청크가 있습니다 (기본적으로 호출 app.configure)
  • 덜 펀치하는 코드가 약간 있으므로 런타임에 내 적은 것을 CSS로 다시 컴파일합니다.
  • 내 모든 경로를 설정하는 코드가 있습니다.
  • 나는 이것을 작은 nko 모듈이라고 부릅니다.
  • 마지막으로 포트를 수신하여 서버를 시작합니다.

예를 들어 라우팅 파일을 살펴 보겠습니다.

var fs = require("fs"),
    parseCookie = require('connect').utils.parseCookie;

module.exports = function(app, sessionStore) {
    var modelUrl = __dirname + "/../model/",
        models = fs.readdirSync(modelUrl),
        routeUrl = __dirname + "/../route/"
        routes = fs.readdirSync(routeUrl);

여기에서는 모든 모델과 경로를 파일 배열로로드합니다.

면책 조항 : http 서버를 시작하기 전에readdirSync 호출 할 때만 괜찮습니다 (이전 ). 서버 시작시 동기화 차단 호출을 호출하면 코드를 더 쉽게 읽을 수 있습니다 (기본적으로 해킹)..listen

    var io = require("socket.io").listen(app);

    io.set("authorization", function(data, accept) {
        if (data.headers.cookie) {
            data.cookie = parseCookie(data.headers.cookie);

            data.sessionId = data.cookie['express.sid'];

            sessionStore.get(data.sessionId, function(err, session) {

                if (err) {
                    return accept(err.message, false);
                } else if (!(session && session.auth)) {
                    return accept("not authorized", false)
                }
                data.session = session;
                accept(null, true);
            });
        } else {
            return accept('No cookie', false);
        }
    });

여기에서는 어떤 탐과 잭이 내 socket.io 서버와 통신하도록하는 대신 실제로 인증을 사용하기 위해 socket.io를 펀치합니다.

    routes.forEach(function(file) {
        var route = require(routeUrl + file),
            model = require(modelUrl + file);

        route(app, model, io);
    });
};

여기서는 관련 모델을 경로 파일에서 반환 된 각 경로 객체에 전달하여 경로를 시작합니다.

기본적으로 요점은 모든 것을 멋진 작은 모듈로 구성한 다음 부트 스트랩 메커니즘을 갖는 것입니다.

내 다른 프로젝트 (내 블로그) 에는 유사한 구조의 init 파일이 있습니다.

면책 조항 : 블로그가 깨져서 구축되지 않습니다. 작업 중입니다.



0

익스프레스 생성기 도구 위에 내 앱을 빌드했습니다. 을 npm install express-generator -g사용하여 실행 하고 실행할 수 있습니다 express <APP_NAME>.

관점을 제공하기 위해 내 작은 응용 프로그램의 구조 중 하나는 다음과 같습니다.

~/
|~bin
| |-www
|
|~config
| |-config.json
|
|~database
| |-database.js
|
|~middlewares
| |-authentication.js
| |-logger.js
|
|~models
| |-Bank.js
| |-User.js
|
|~routes
| |-index.js
| |-banks.js
| |-users.js
|
|~utilities
| |-fiat-converersion.js
|
|-app.js
|-package.json
|-package-lock.json

내가 개발하는 모든 급행 애플리케이션에 채택하게되는이 구조에 대해 내가 좋아하는 한 가지 멋진 점은 경로가 구성되는 방식입니다. app.use()특히 파일이 커짐 에 따라 각 경로 파일을 app.js와 각 경로 에 요구할 필요가 없었 습니다. 따라서 app.use()./routes/index.js 파일에서 모든 것을 그룹화하고 중앙 집중화하는 것이 도움이된다는 것을 알았습니다 .

결국 내 app.js는 다음과 같이 보일 것입니다.

...
const express = require('express');
const app = express();

...
require('./routes/index')(app);

내 ./routes/index.js는 다음과 같습니다.

module.exports = (app) => {
  app.use('/users', require('./users'));
  app.use('/banks', require('./banks'));
};

단순히 수 있어요 require(./users)내가 "그룹"여러 경로로 나를 수 express.Router를 (사용하여 사용자의 경로를) 작성하기 때문에 다음 응용 프로그램이 더 모듈화 만드는 것을 목표로, 한 번에 내보낼 수 있습니다.

이것은 내 ./routers/users.js 경로에서 괜찮을 것의 예입니다.


const router = require('express').Router();

router.post('/signup', async (req, res) => {
    // Signup code here
});

module.exports = router;

이것이 귀하의 질문에 대한 답변이 되었기를 바랍니다. 행운을 빕니다!

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.