[node.js] ExpressJS 응용 프로그램을 구성하는 방법?

NodeJS에 ExpressJS 웹 프레임 워크를 사용하고 있습니다.

ExpressJS를 사용하는 사람들은 환경 (개발, 생산, 테스트 …), 경로 등을에 배치합니다 app.js. 큰 응용 프로그램이있을 때 app.js가 너무 커서 아름다운 방법이 아니라고 생각합니다!

이 디렉토리 구조를 갖고 싶습니다.

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

내 코드는 다음과 같습니다.

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

내 코드는 잘 작동하며 디렉토리의 구조가 아름답다고 생각합니다. 그러나 코드를 수정해야했고 코드가 훌륭하고 아름답다는 것을 확신하지 못합니다.

내 디렉토리 구조를 사용하고 코드를 조정하거나 하나의 파일 (app.js)을 사용하는 것이 더 낫습니까?

당신의 조언에 감사드립니다!



답변

좋아, 그것은 오랜 시간이 지났고 이것은 인기있는 질문입니다. 그래서 JavaScript 코드와 중간 크기의 express.js 응용 프로그램을 구성하는 방법에 대한 긴 README가있는 스캐 폴딩 github 저장소를 만들었습니다.

focusaurus / express_code_structure 는 최신 코드가 포함 된 저장소입니다. 풀 요청을 환영합니다.

다음은 README의 스냅 샷입니다. 스택 오버플로는 링크 응답 만 좋아하지 않습니다. 나는 이것이 계속 업데이트 할 새로운 프로젝트이므로 업데이트 할 것이지만 궁극적으로 github repo 가이 정보의 최신 장소가 될 것입니다.


익스프레스 코드 구조

이 프로젝트는 중간 크기의 express.js 웹 애플리케이션을 구성하는 방법의 예입니다.

현재 2016 년 12 월 v4.14 이상 표현

빌드 상태

JS 표준 스타일

응용 프로그램이 얼마나 큽니까?

웹 응용 프로그램이 모두 동일하지는 않으며 모든 express.js 응용 프로그램에 적용해야 할 단일 코드 구조는 없습니다.

응용 프로그램이 작은 경우 여기에 설명 된 것과 같은 깊은 디렉토리 구조가 필요하지 않습니다. 간단하게 유지하고 .js리포지토리의 루트에 소수의 파일을 집어 넣으면 완료됩니다. Voilà.

응용 프로그램이 크면 언젠가는 별도의 npm 패키지로 분리해야합니다. 일반적으로 node.js 접근 방식은 최소한 라이브러리에는 많은 작은 패키지를 선호하는 것으로 보이며 오버 헤드를 이해하고 이해하기 시작하는 여러 npm 패키지를 사용하여 응용 프로그램을 빌드해야합니다. 따라서 응용 프로그램이 커지고 코드의 일부가 응용 프로그램 외부에서 명확하게 재사용 가능하거나 명확한 하위 시스템이됨에 따라 자체 자식 저장소로 이동하여 독립형 npm 패키지로 만듭니다.

따라서이 프로젝트의 초점은 중형 응용 프로그램의 실행 가능한 구조를 설명하는 것입니다.

전반적인 아키텍처는 무엇입니까

웹 애플리케이션을 구축하는 방법에는 여러 가지가 있습니다.

  • 서버 측 MVC a la Ruby on Rails
  • 단일 페이지 응용 프로그램 스타일 및 MongoDB / Express / Angular / Node (MEAN)
  • 일부 형태의 기본 웹 사이트
  • la MVC이 (가) 죽은 모델 / 작업 / 뷰 / 이벤트 스타일, 이제 움직일 시간입니다
  • 그리고 다른 많은 사람들은 현재와 역사적인

이들 각각은 다른 디렉토리 구조에 잘 맞습니다. 이 예제의 목적 상, 그것은 비계 일 뿐이며 완전히 작동하는 앱은 아니지만 다음과 같은 주요 아키텍처 포인트를 가정합니다.

  • 이 사이트에는 전통적인 정적 페이지 / 템플릿이 있습니다
  • 사이트의 “응용 프로그램”부분은 단일 페이지 응용 프로그램 스타일로 개발되었습니다.
  • 애플리케이션은 REST / JSON 스타일 API를 브라우저에 노출합니다.
  • 이 앱은 간단한 비즈니스 도메인을 모델링합니다.이 경우 자동차 대리점 애플리케이션입니다.

그리고 Ruby on Rails는 어떻습니까?

이 프로젝트 전체에 걸쳐 주제가 될 것입니다. Ruby on Rails에서 구현 된 많은 아이디어와 그들이 채택한 “컨벤션 오버 컨벤션”결정은 실제로 널리 사용되지는 않았지만 실제로는 그다지 도움이되지 않으며 때로는이 리포지토리와 반대입니다. 추천합니다.

필자의 주요 요점은 코드 구성에 기본 원칙이 있으며, 이러한 원칙을 기반으로 Ruby on Rails 규칙은 Ruby on Rails 커뮤니티에 적합하다는 것입니다. 그러나 이러한 관습을 신중하게 숙지하는 것은 요점을 놓치게됩니다. 기본 원칙을 고수하면 셸 스크립트, 게임, 모바일 앱, 엔터프라이즈 프로젝트, 홈 디렉토리까지 모든 프로젝트가 잘 구성되고 명확 해집니다.

Rails 커뮤니티의 경우 단일 Rails 개발자가 앱에서 앱으로 전환하고 매번 익숙하고 편안하게 사용할 수 있기를 원합니다. 37 개의 신호 또는 Pivotal Labs에 적합하며 이점이 있습니다. 서버 측 JavaScript 세계에서 전반적인 정신은 훨씬 더 서구 적이며 실제로 문제가 없습니다. 그것이 우리가 굴리는 방식입니다. 우리는 그것에 익숙합니다. express.js에서도 Rails가 아닌 Sinatra와 밀접한 관계가 있으며 Rails에서 컨벤션을 취하는 것은 일반적으로 도움이되지 않습니다. 컨벤션에 대한 컨벤션에 대한 원칙 조차 말하고 싶습니다 .

기본 원칙과 동기

  • 정신적으로 관리 가능
    • 뇌는 한 번에 적은 수의 관련된 것들만 다루고 생각할 수 있습니다. 우리가 디렉토리를 사용하는 이유입니다. 작은 부분에 집중함으로써 복잡성을 처리하는 데 도움이됩니다.
  • 적절한 크기
    • 하나의 파일 만있는 3 개의 디렉토리가있는 “맨션 디렉토리”를 작성하지 마십시오. 3 개의 파일이있는 1 개의 디렉토리가 훨씬 더 적합 할 때 작은 프로젝트가 10 개 이상의 디렉토리를 작성하여 10 개 이상의 파일을 보유하도록 하는 Ansible Best Practices 에서 이러한 일이 발생하는 것을 볼 수 있습니다 . 버스를 운전하지 말고 버스 운전을하지 않는 한 버스를 운전하지 마십시오. 실제 파일로 정당화되지 않는 파일 시스템 구조를 만들지 마십시오. .
  • 모듈 식이지만 실용적 임
    • 노드 커뮤니티는 전반적으로 작은 모듈을 선호합니다. 앱에서 완전히 분리 할 수있는 것은 모두 내부 용 또는 npm에 공개적으로 게시 할 수있는 모듈로 추출해야합니다. 그러나 여기에 해당하는 중간 규모의 응용 프로그램의 경우 오버 헤드로 인해 적절한 가치없이 워크 플로에 지루한 요소가 추가 될 수 있습니다. 따라서 완전히 분리 된 npm 모듈을 정당화하기에 충분하지 않은 일부 코드가 있는 경우에는 일부 크기 임계 값을 초과 할 때 추출 될 것으로 예상 되는 ” 프로토 모듈 “을 고려하십시오 .
    • @ hij1nx 와 같은 일부 사람들 은 app/node_modules디렉토리를 포함 package.json하고 프로토 모듈 디렉토리에 파일을 가지고 있어 전환을 촉진하고 미리 알림으로 작동합니다.
  • 코드를 쉽게 찾을 수 있습니다
    • 빌드 할 기능이나 수정해야 할 버그가 있다면 개발자가 관련 소스 파일을 찾는 데 어려움을 겪지 않는 것이 목표입니다.
    • 이름은 의미 있고 정확합니다
    • crufty 코드가 완전히 제거되어 고아 파일에 남아 있거나 주석 처리되지 않았습니다.
  • 검색 친화적
    • 모든 자사 소스 코드가 app디렉토리에 있으므로 cdfind / grep / xargs / ag / ack / etc를 실행하고 타사 매치에 의해 방해받지 않을 수 있습니다
  • 간단하고 명백한 이름 사용
    • npm은 이제 모두 소문자 패키지 이름을 요구하는 것 같습니다. 나는 이것이 끔찍한 것을 발견하지만 무리를 따라야하므로 kebab-caseJavaScript의 변수 이름이 JavaScript 의 빼기 기호 camelCase이기 때문에 파일 이름을 사용해야 합니다 -.
    • 변수 이름은 모듈로의 기본 이름과 일치하지만,과은 kebab-case으로 변환camelCase
  • 기능별이 아닌 커플 링별 그룹화
    • 이의 루비 온 레일스 대회에서 중요한 출발이다 app/views, app/controllers, app/models, 등
    • 기능이 전체 스택에 추가되므로 기능과 관련된 전체 파일 스택에 중점을두고 싶습니다. 전화 번호 필드를 사용자 모델에 추가 할 때 사용자 컨트롤러 이외의 다른 컨트롤러는 신경 쓰지 않으며 사용자 모델 이외의 다른 모델은 신경 쓰지 않습니다.
    • 따라서 각각 자체 디렉토리에있는 6 개의 파일을 편집하고 해당 디렉토리에있는 수많은 다른 파일을 무시하는 대신이 저장소는 기능을 빌드하는 데 필요한 모든 파일이 함께 배치되도록 구성됩니다.
    • MVC의 특성상, 사용자 뷰는 사용자 모델에 연결된 사용자 컨트롤러에 연결된다. 따라서 사용자 모델을 변경하면이 3 개의 파일이 함께 변경되는 경우가 많지만 거래 컨트롤러 또는 고객 컨트롤러는 분리되어 관련되지 않습니다. 비 MVC 설계에도 동일하게 적용됩니다.
    • 어떤 코드가 어떤 모듈에 권장되는지에 대한 MVC 또는 MOVE 스타일 디커플링은 여전히 ​​MVC 파일을 형제 디렉토리에 퍼뜨리는 것은 성가신 일입니다.
    • 따라서 내 각 라우트 파일에는 자신이 소유 한 라우트의 일부가 있습니다. 레일 스타일 routes.rb파일은 앱의 모든 경로에 대한 개요를 원할 경우 편리하지만 실제로 기능을 빌드하고 버그를 수정하는 경우 변경하는 부분과 관련된 경로 만 신경 써야합니다.
  • 코드 옆에 테스트 저장
    • 이것은 “group by coupling”의 인스턴스 일 뿐이지 만, 구체적으로 설명하고 싶었습니다. 테스트가 “tests”라는 병렬 파일 시스템 하에서 진행되는 많은 프로젝트를 작성했으며 이제는 해당 코드와 동일한 디렉토리에 테스트를 시작 했으므로 결코 되돌아 가지 않을 것입니다. 이것은 텍스트 편집기에서보다 모듈화되고 작업하기가 훨씬 쉬우 며 많은 “../../ ..”경로 넌센스를 완화합니다. 확실치 않은 경우 몇 가지 프로젝트를 시도해보고 스스로 결정하십시오. 나는 그것이 더 낫다는 것을 확신시키기 위해 이것 이외의 어떤 것도하지 않을 것입니다.
  • 이벤트와 교차 절단 커플 링 감소
    • “새 거래가 생성 될 때마다 모든 영업 사원에게 전자 메일을 보내려고합니다”라고 생각한 다음 거래를 생성하는 경로에 해당 전자 메일을 보내는 코드 만 넣으면됩니다.
    • 그러나이 커플 링은 결국 앱을 거대한 진흙 공으로 바꿉니다.
    • 대신, DealModel은 “만들기”이벤트를 발생시키고 시스템이 그에 대한 응답으로 시스템이 수행 할 수있는 작업을 완전히 인식하지 않아야합니다.
    • 이 방법으로 코딩 app/users하면 사용자 코드 기반의 순도를 오염시키는 모든 장소에 연결된 비즈니스 로직의 랫트가 없기 때문에 모든 사용자 관련 코드를 넣을 수 있습니다 .
  • 코드 흐름에 따름
    • 마법적인 일을하지 마십시오. 파일 시스템의 매직 디렉토리에서 파일을 자동로드하지 마십시오. Rails가되지 마십시오. 앱이 시작되고 app/server.js:1코드를 따라로드 및 실행되는 모든 것을 볼 수 있습니다.
    • 경로에 DSL을 만들지 마십시오. 부적절하게 메타 프로그래밍을하지 마십시오.
    • 앱이 일을 너무 큰 경우 magicRESTRouter.route(somecontroller, {except: 'POST'})큰 승리를위한 이상 3 기본 app.get, app.put, app.del, 전화, 당신은 아마 효율적으로 작업 할 너무 커서 모 놀리 식 응용 프로그램을 구축하고 있습니다. 3 개의 간단한 라인을 1 개의 복잡한 라인으로 변환하는 것이 아니라 BIG의 승리를 위해 공감하십시오.
  • 케밥 소문자 파일 이름 사용

    • 이 형식은 플랫폼에서 파일 시스템 대소 문자 구분 문제를 방지합니다
    • npm은 새 패키지 이름에서 대문자를 금지하며 이는 잘 작동합니다.

      express.js 사양

  • 를 사용하지 마십시오 app.configure. 거의 완전히 쓸모가 없으며 필요하지 않습니다. 마음이없는 카피 파스타로 인해 많은 상용구에 있습니다.

  • 미들웨어 주문 및 특급 사안의 경로 !!!
    • stackoverflow에서 볼 수있는 거의 모든 라우팅 문제는 고장난 표현 미들웨어입니다.
    • 일반적으로 경로를 분리하고 순서에 의존하지 않기를 원합니다.
    • app.use2 개의 경로에 해당 미들웨어 만 필요한 경우 전체 애플리케이션에 사용하지 마십시오 (내가보고 있습니다 body-parser).
    • 모든 내용을 말하고 완료했는지 확인하십시오.
      1. 매우 중요한 애플리케이션 전체 미들웨어
      2. 모든 경로 및 여러 경로 미들웨어
      3. THEN 오류 처리기
  • 슬프게도, sinatra에서 영감을 얻은 express.js는 대부분 모든 경로가있을 것으로 가정하고 server.js주문 방식이 명확합니다. 중간 규모의 응용 프로그램의 경우 별도의 경로 모듈로 분류하는 것이 좋지만 고장난 미들웨어의 위험을 초래합니다.

앱 심볼릭 트릭

Node.js에 대한 더 나은 local require () 경로 에서 커뮤니티가 길게 설명하고 논의한 많은 접근 방식이 있습니다 . 나는 곧 “많은 ../../../ .. 다루기”를 원하거나 requireFrom 모듈을 사용하기로 결정할 수도있다. 그러나 현재는 아래에 설명 된 symlink 트릭을 사용하고 있습니다.

따라서 프로젝트 내에서 요구하는 성가신 상대 경로를 피하는 한 가지 방법 require("../../../config")은 다음 트릭을 사용하는 것입니다.

  • 앱의 node_modules 아래에 심볼릭 링크를 만듭니다
    • cd node_modules && ln -nsf ../app
  • git에 전체 node_modules 폴더가 아닌

    node_modules / app symlink 자체를 추가하십시오.

    • git add -f node_modules / app
    • 예, 여전히 .gitignore파일 에 “node_modules”가 있어야 합니다
    • 아니요, “node_modules”를 git 저장소에 넣지 마십시오. 어떤 사람들은 이것을 권장합니다. 잘못되었습니다.
  • 이제이 접두사를 사용하여 프로젝트 내 모듈을 요구할 수 있습니다
    • var config = require("app/config");
    • var DealModel = require("app/deals/deal-model");
  • 기본적으로 이것은 프로젝트 내부 요구 사항을 외부 npm 모듈 요구 사항과 매우 유사하게 만듭니다.
  • 죄송합니다. Windows 사용자는 상위 디렉토리 상대 경로를 사용해야합니다.

구성

일반적으로 기본 JavaScript options객체 만 전달 되도록 모듈 및 클래스를 코딩하십시오. 모듈 만 app/server.js로드해야 app/config.js합니다. 거기에서 options필요에 따라 작은 오브젝트를 합성 하여 서브 시스템을 구성 할 수 있지만, 모든 서브 시스템을 추가 정보로 가득 찬 큰 전역 구성 모듈에 결합하는 것은 나쁜 결합입니다.

연결 매개 변수를 전달하고 서브 시스템이 나가는 연결을 작성하는 것과 달리 DB 연결 작성을 중앙 집중화하여 서브 시스템으로 전달하십시오.

NODE_ENV

이것은 Rails에서 가져온 또 다른 유혹이지만 끔찍한 아이디어입니다. 앱에 정확히 1 개의 위치가 있어야하며 app/config.js, NODE_ENV환경 변수 를 살펴 봅니다 . 그 밖의 모든 것에는 클래스 생성자 인수 또는 모듈 구성 매개 변수로 명시적인 옵션을 사용해야합니다.

이메일 모듈에 이메일 전달 방법 (SMTP, stdout에 로그, 대기열에 넣는 방법 등)에 대한 옵션이있는 경우에는 옵션을 선택 {deliver: 'stdout'}해야하지만 반드시 확인해서는 안됩니다 NODE_ENV.

테스트

이제 테스트 파일을 해당 코드와 동일한 디렉토리에 유지하고 파일 이름 확장명 명명 규칙을 사용하여 테스트와 프로덕션 코드를 구분합니다.

  • foo.js “foo”모듈 코드가 있습니다
  • foo.tape.js foo에 대한 노드 기반 테스트가 있으며 동일한 디렉토리에 있습니다.
  • foo.btape.js 브라우저 환경에서 실행해야하는 테스트에 사용할 수 있습니다.

파일 시스템 글로브와 find . -name '*.tape.js'명령을 사용하여 필요에 따라 모든 테스트에 액세스합니다.

.js모듈 파일 내에서 코드를 구성하는 방법

이 프로젝트의 범위는 주로 파일과 디렉토리의 위치에 관한 것이며 다른 범위를 추가하고 싶지는 않지만 코드를 3 개의 개별 섹션으로 구성한다고 언급합니다.

  1. CommonJS의 시작 블록은 상태 종속성에 대한 호출이 필요합니다.
  2. 순수 자바 스크립트의 메인 코드 블록. 여기에 CommonJS 오염이 없습니다. 내보내기, 모듈 또는 필요를 참조하지 마십시오.
  3. 내보내기를 설정하기위한 CommonJS의 닫기 블록

답변

업데이트 (2013-10-29) : 인기있는 요구에 따라 CoffeeScript 대신 JavaScript가 있고 상용구 github 저장소 및이 주제에 대한 최신 권장 사항을 자세히 설명하는 광범위한 README가있는 다른 대답도 참조하십시오.

구성

당신이하는 일은 괜찮습니다. 내 자신의 구성 네임 스페이스를 config.coffee중첩 네임 스페이스가있는 최상위 파일 에 설정하고 싶습니다.

#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}"

이것은 sysadmin 편집에 친숙합니다. 그런 다음 DB 연결 정보와 같은 것이 필요할 때

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

경로 / 컨트롤러

나는 내 경로를 컨트롤러와 함께두고 app/controllers하위 디렉토리에 구성하는 것을 좋아합니다 . 그런 다음로드하여 필요한 경로를 추가 할 수 있습니다.

app/server.coffee커피 스크립트 파일에서 나는 :

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

그래서 다음과 같은 파일이 있습니다.

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

예를 들어 내 도메인 컨트롤러에는 setup다음과 같은 기능이 있습니다.

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

견해

뷰를 넣는 app/views것이 관습적인 장소가되고 있습니다. 나는 이것을 이렇게 배치했습니다.

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

정적 파일

public서브 디렉토리로 이동하십시오 .

Github / Semver / NPM

github의 git repo 루트에 README.md 마크 다운 파일을 넣으십시오.

시맨틱 버전 번호가 있는 package.json 파일 을 NPM의 git repo 루트에 넣으십시오 .


답변

다음은 다른 사람들의 요청에 따라 Coffeescript의 바닐라 JS로 포팅 된 Peter Lyons의 대답입니다. Peter의 답변은 매우 유능하며 내 답변에 투표하는 사람은 누구나 투표해야합니다.


구성

당신이하는 일은 괜찮습니다. 내 자신의 구성 네임 스페이스를 config.js중첩 네임 스페이스가있는 최상위 파일 에 설정하고 싶습니다.

// 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}"
};

이것은 sysadmin 편집에 친숙합니다. 그런 다음 DB 연결 정보와 같은 것이 필요할 때

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

경로 / 컨트롤러

나는 내 경로를 컨트롤러와 함께두고 app/controllers하위 디렉토리에 구성하는 것을 좋아합니다 . 그런 다음로드하여 필요한 경로를 추가 할 수 있습니다.

app/server.js자바 스크립트 파일에서 나는 :

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

그래서 다음과 같은 파일이 있습니다.

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

예를 들어 내 도메인 컨트롤러에는 setup다음과 같은 기능이 있습니다.

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

견해

뷰를 넣는 app/views것이 관습적인 장소가되고 있습니다. 나는 이것을 이렇게 배치했습니다.

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

정적 파일

public서브 디렉토리로 이동하십시오 .

Github / Semver / NPM

github의 git repo 루트에 README.md 마크 다운 파일을 넣으십시오.

시맨틱 버전 번호가 있는 package.json 파일 을 NPM의 git repo 루트에 넣으십시오 .


답변

내 질문은 2011 년 4 월에 소개되었으며 조용합니다. 이 기간 동안 Express.js에 대한 경험과이 라이브러리를 사용하여 작성된 응용 프로그램을 아키텍처 화하는 방법을 향상시킬 수있었습니다. 그래서 나는 여기 내 경험을 공유합니다.

내 디렉토리 구조는 다음과 같습니다.

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

app.js파일 의 목표 는 expressjs 애플리케이션을 부트 스트랩하는 것입니다. 구성 모듈, 로거 모듈을로드하고 데이터베이스 연결을 기다립니다 … 및 Express 서버를 실행합니다.

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

노선 /

routes 디렉토리에 index.js파일이 있습니다. 그것의 목표는 routes/디렉토리에 다른 모든 파일을로드하는 일종의 마술을 도입하는 것입니다 . 구현은 다음과 같습니다.

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

이 모듈을 사용하면 새로운 경로 정의 및 구현을 만드는 것이 정말 쉽습니다. 예를 들면 다음과 hello.js같습니다.

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

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

각 경로 모듈은 독립형 입니다.


답변

함수 등을 내보내는 대신 전역 “앱”을 사용하고 싶습니다.


답변

나는 그것을하는 좋은 방법이라고 생각합니다. 표현에 국한되지는 않지만 github에서 꽤 많은 node.js 프로젝트가 동일한 작업을 수행하는 것을 보았습니다. 그들은 구성 매개 변수를 취합니다 + 작은 모듈 (경우에 따라 모든 URI)은 별도의 파일에 포함됩니다.

아이디어를 얻으려면 github에서 특정 프로젝트를 진행하는 것이 좋습니다. IMO는 당신이하고있는 방식이 맞습니다.


답변

이제 2015 년 말 이며 3 년 동안 크고 작은 프로젝트에서 내 구조를 개발 한 후입니다. 결론?

하나의 큰 MVC를 수행하지 말고 모듈로 분리하십시오.

그래서…

왜?

  • 일반적으로 하나의 모듈 (예 : 제품)에서 작동하며 독립적으로 변경할 수 있습니다.

  • 모듈을 재사용 할 수 있습니다

  • 별도로 테스트 할 수 있습니다

  • 별도로 교체 할 수 있습니다

  • 그들은 명확한 (안정한) 인터페이스를 가지고 있습니다

    -최근에 여러 개발자가 작업하고 있다면 모듈 분리가 도움이됩니다.

nodebootstrap의 프로젝트 내 최종 구조와 유사한 접근 방식을 가지고있다. ( github )

이 구조는 어떻게 생겼습니까?

  1. 각각 별도의 MVC가있는 소형 캡슐화 된 모듈

  2. 각 모듈 에는 패키지가 있습니다.

  3. 구조의 일부로 테스트 (각 모듈에서)

  4. 글로벌 구성 , 라이브러리 및 서비스

  5. 통합 도커, 클러스터, 영원히

폴더 개요 (모듈은 lib 폴더 참조) :

nodebootstrap 구조