ExpressJSアプリケーションの構成方法は?


527

NodeJSにはExpressJS Webフレームワークを使用しています。

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

私のコードはうまく動作し、ディレクトリの構造は美しいと思います。ただし、コードを調整する必要があり、それが良い/美しいかどうかはわかりません。

私のディレクトリ構造を使用してコードを調整するのが良いですか、それとも単に1つのファイル(app.js)を使用するのですか?

アドバイスありがとうございます!


この方法でこれを行うことのパフォーマンスの問題はまだ潜んでいますか?私はどこか(たぶん特急グループ)を読んだことを覚えています。まるでバグであるかのように、reqs / secのようなものが、かなりの量だけ低下します。
AntelopeSalad

2
それはExpress Googleグループからのものでした。ここにリンクがあります: groups.google.com/group/express-js/browse_thread/thread/...
AntelopeSalad

52
いいえ、これは非常に
不正確です

回答:


306

さて、久しぶりですが、これはよくある質問なので、先に進んで、中規模のexpress.jsアプリケーションをどのように構築するかについて、JavaScriptコードと長いREADMEを使用して足場githubリポジトリを作成しました。

focusaurus / express_code_structureは、このための最新のコードを含むリポジトリです。プルリクエストは大歓迎です。

stackoverflowはリンクのみの回答を好まないため、ここにREADMEのスナップショットを示します。これは今後も更新する新しいプロジェクトであるため、更新を行いますが、最終的にはgithubリポジトリがこの情報の最新の場所になります。


エクスプレスコード構造

このプロジェクトは、中規模のexpress.js Webアプリケーションを編成する方法の例です。

2016年12月にv4.14を少なくとも表す最新版

ビルドステータス

js-standard-style

アプリケーションの大きさはどれくらいですか?

Webアプリケーションはすべて同じではなく、私の意見では、すべてのexpress.jsアプリケーションに適用する必要のある単一のコード構造はありません。

アプリケーションが小さい場合は、ここで例示するような深いディレクトリ構造は必要ありません。単純.jsにして、リポジトリのルートに少数のファイルを貼り付ければ完了です。ボイラ。

アプリケーションが巨大な場合、ある時点でそれを個別のnpmパッケージに分割する必要があります。一般に、node.jsアプローチは、少なくともライブラリに対しては、多くの小さなパッケージを優先するようであり、いくつかのnpmパッケージを使用してアプリケーションを構築する必要があります。そのため、アプリケーションが大きくなり、コードの一部がアプリケーションの外で明らかに再利用可能になった場合、または明確なサブシステムになった場合は、それを独自のgitリポジトリに移動し、スタンドアロンのnpmパッケージにします。

したがって、このプロジェクトの焦点は、中規模アプリケーションの実行可能な構造を示すことです。

全体的なアーキテクチャは何ですか

Webアプリケーションを構築するには、次のような多くのアプローチがあります。

  • Ruby on Railsのサーバー側MVC
  • MongoDB / Express / Angular / Node(MEAN)の単一ページアプリケーションスタイル
  • いくつかのフォームがある基本的なWebサイト
  • MVCのモデル/操作/ビュー/イベントスタイルが無効になっているため、MOVEを開始します
  • そして現在および歴史的な他の多くの

これらはそれぞれ、異なるディレクトリ構造にうまく適合します。この例では、これは足場にすぎず、完全に機能するアプリではありませんが、以下の主要なアーキテクチャポイントを想定しています。

  • サイトには、いくつかの従来の静的ページ/テンプレートがあります
  • サイトの「アプリケーション」部分は、単一ページアプリケーションスタイルとして開発されています。
  • アプリケーションがREST / JSONスタイルのAPIをブラウザーに公開する
  • アプリは単純なビジネスドメインをモデル化します。この場合は、自動車販売店アプリケーションです。

そしてRuby on Railsはどうですか?

Ruby on Railsで具体化されたアイデアの多くと、彼らが採用した「Convention over Configuration」の決定は広く受け入れられ使用されていますが、実際にはあまり役に立たず、このリポジトリとは正反対である場合があります。お勧めします。

ここでの私の主なポイントは、コードを編成するための基本的な原則があり、それらの原則に基づいて、Ruby on Railsの規則はRuby on Railsコミュニティにとって(主に)意味があるということです。しかし、それらの慣習を不注意に苦しめるだけでは要点を逃します。基本原則を理解すれば、すべてのプロジェクトがよく整理され、明確になります。シェルスクリプト、ゲーム、モバイルアプリ、エンタープライズプロジェクト、さらにはホームディレクトリまでです。

Railsコミュニティの場合、Rails開発者が1人でアプリを切り替えられるようにし、毎回それに慣れ親しんでいる必要があります。これは、37の信号またはPivotal Labsである場合に非常に意味があり、利点があります。サーバー側のJavaScriptの世界では、全体的な精神は、何が起こってもまったくよりワイルドウエストであり、実際には問題はありません。それが私たちが転がる方法です。私たちはそれに慣れています。express.js内でも、これはRailsではなくSinatraの近縁であり、Railsから規則を採用しても通常は何の助けにもなりません。設定よりも規約に関する原則も言います

根本的な原則と動機

  • 精神的に管理できる
    • 脳は、同時に少数の関連する事柄のみを扱い、考えることができます。そのため、ディレクトリを使用します。小さな部分に焦点を当てることで、複雑さに対処するのに役立ちます。
  • サイズが適切であること
    • 「Mansion Directories」を作成しないでください。1つのファイルだけが3つ下のディレクトリにあるだけです。これは、3つのファイルを持つ1つのディレクトリの方がはるかに適切な場合に、小さなプロジェクトが10以上のディレクトリを作成して10以上のファイルを保持するように恥ずかしがるAnsible Best Practicesで発生しています。バスを運転して動作しない(バスドライバーでない限り、バスを運転しても動作しない)ので、内部の実際のファイルによって正当化されていないファイルシステム構造を作成しないでください。
  • モジュール式で実用的
    • ノードコミュニティは全体的に小さなモジュールを好みます。アプリから完全に分離できるものはすべて、内部使用のためにモジュールに抽出するか、npmで公開する必要があります。ただし、ここでのスコープである中規模のアプリケーションの場合、これのオーバーヘッドにより、相応の価値がなければワークフローに退屈さが追加される可能性があります。したがって、除外されているが完全に独立したnpmモジュールを正当化するのに十分ではないコードがある場合は、「proto-module」であると考えてください。あるサイズのしきい値を超えると、それが抽出されることを期待しています。
    • @ hij1nxなどの一部の人々は、app/node_modulesディレクトリを組み込みpackage.jsonproto-moduleディレクトリにファイルを用意して、移行を容易にし、リマインダーとして機能します。
  • コードを見つけやすい
    • ビルドする機能または修正するバグを考えると、開発者が関係するソースファイルを見つけるのに苦労しないことが目標です。
    • 名前は意味があり正確です
    • 不正なコードは完全に削除され、孤立ファイルに残されたり、コメントアウトされたりすることはありません
  • 検索に対応する
    • すべてのファーストパーティソースコードがappディレクトリにあるため、cdfind / grep / xargs / ag / ack / etcを実行して、サードパーティの一致に気を取られないようにすることができます
  • シンプルでわかりやすい名前を使用する
    • npmは、すべて小文字のパッケージ名を要求するようになりました。これはほとんどひどいですが、群れを追跡する必要があります。したがってkebab-case、JavaScriptでの変数名はJavaScript のマイナス記号であるcamelCaseため、ファイル名は使用する必要があり-ます。
    • 変数名は、モジュールパスのベース名と一致しますが、とkebab-caseに変換しますcamelCase
  • 機能ではなくカップリングでグループ化
    • これは、のルビーon Railsの慣例からの主要な出発でapp/viewsapp/controllersapp/models、など
    • 機能は完全なスタックに追加されるので、自分の機能に関連するファイルの完全なスタックに焦点を当てたいと思います。ユーザーモデルに電話番号フィールドを追加するときは、ユーザーコントローラー以外のコントローラーは気にせず、ユーザーモデル以外のモデルも気にしません。
    • したがって、それぞれ独自のディレクトリにある6つのファイルを編集して、それらのディレクトリにある他の多数のファイルを無視する代わりに、このリポジトリは、機能の構築に必要なすべてのファイルが同じ場所に配置されるように編成されています
    • MVCの性質上、ユーザービューは、ユーザーモデルに結合されたユーザーコントローラーに結合されます。したがって、ユーザーモデルを変更すると、これらの3つのファイルが一緒に変更されることがよくありますが、取引コントローラーまたは顧客コントローラーは分離されているため、関与しません。通常、MVC以外の設計にも同じことが当てはまります。
    • どのコードがどのモジュールに入るのかという点でMVCまたはMOVEスタイルのデカップリングが推奨されますが、MVCファイルを兄弟ディレクトリーに広げるのは面倒です。
    • したがって、私の各ルートファイルには、それが所有するルートの一部が含まれています。Railsスタイルのroutes.rbファイルは、アプリ内のすべてのルートの概要が必要な場合に便利ですが、実際に機能を構築してバグを修正するときは、変更する部分に関連するルートのみを気にします。
  • コードの横にテストを保存する
    • これは単なる「グループバイカップリング」のインスタンスですが、具体的に呼びたかったのです。「tests」と呼ばれる並列ファイルシステムの下にテストが存在する多くのプロジェクトを書いており、対応するコードと同じディレクトリにテストを配置し始めたので、戻ることはありません。これはよりモジュール化されており、テキストエディタでの作業がはるかに簡単であり、多くの "../../ .."パスのナンセンスを軽減します。疑問がある場合は、いくつかのプロジェクトで試して、自分で決めてください。私はあなたにそれがより良いことを納得させるためにこれ以上のことをするつもりはありません。
  • イベントとの横断的な結合を減らす
    • 「OK、新しい取引が作成されたときはいつでも、すべての営業担当者にメールを送信したい」と考えて、取引を作成するルートにそれらのメールを送信するコードを置くだけです。
    • ただし、この結合により、最終的にアプリが巨大な泥の塊に変わります。
    • 代わりに、DealModelは「作成」イベントを起動するだけで、それに応答してシステムが他に何をする可能性があるかを完全に認識しません。
    • この方法でコーディングするapp/usersと、ユーザーコードベースの純粋さを汚染する場所全体に、結合されたビジネスロジックのネズミの巣がないため、すべてのユーザー関連コードを配置することがはるかに可能になります。
  • コードフローはフォロー可能です
    • 魔法のようなことはしないでください。ファイルシステムの魔法のディレクトリからファイルを自動ロードしないでください。Railsにならないでください。アプリは次の場所から始まりapp/server.js:1、コードに従うことで、アプリが読み込んで実行するものすべてを確認できます。
    • ルート用にDSLを作成しないでください。それが求められていないときは、ばかげたメタプログラミングを行わないでください。
    • あなたのアプリがやっていることをとても大きい場合はmagicRESTRouter.route(somecontroller, {except: 'POST'})大きな勝利であるため、あなたの上に3つの基本的なapp.getapp.putapp.del、呼び出し、あなたはおそらく効果的に取り組むには大きすぎるモノリシックアプリを構築しています。3つの単純なラインを1つの複雑なラインに変換するためではなく、BIGの勝利を手に入れましょう。
  • ケバブ小文字のファイル名を使用する

    • このフォーマットは、プラットフォーム間でのファイルシステムの大文字と小文字の区別の問題を回避します
    • npmは新しいパッケージ名の大文字を禁止し、これはこれでうまく機能します

      express.jsの詳細

  • 使用しないでくださいapp.configure。それはほとんど完全に役に立たず、あなたはそれを必要としません。マインドレスなコピーパスタのため、定型文がたくさんあります。

  • エクスプレスの重要事項におけるミドルウェアとルートの順序!!!
    • stackoverflowで見られるほとんどすべてのルーティングの問題は、順不同のExpressミドルウェアです
    • 一般的に、ルートを分離し、順序にそれほど依存しないようにします
    • app.use2つのルートにミドルウェアが本当に必要なだけの場合は、アプリケーション全体に使用しないでください(私はあなたを見ていますbody-parser
    • すべての発言が完了したら、次の順序が正しいことを確認してください。
      1. 非常に重要なアプリケーション全体のミドルウェア
      2. すべてのルートと各種ルートミドルウェア
      3. THENエラーハンドラ
  • 悲しいことに、sinatraにインスパイアされたexpress.jsは、ほとんどすべてのルートが含まれることを想定しており、ルートのserver.js順序が明確になります。中規模のアプリケーションの場合、物事を別々のルートモジュールに分割するのは良いことですが、順序が狂っているミドルウェアの危険が伴います。

アプリのsymlinkトリック

Node.jsの優れたローカルローカルrequire()パスには、コミュニティによって概要が説明され、議論されている多くのアプローチがあります。私はすぐに「たくさんの../../../ ..を扱う」か、requireFromモジュールを使用することを好むかもしれません。ただし、現時点では、以下に説明するシンボリックリンクトリックを使用しています。

したがって、プロジェクト内を回避するための1つの方法require("../../../config")は、次のようなトリックを使用することです。

  • アプリのnode_modulesの下にシンボリックリンクを作成します
    • cd node_modules && ln -nsf ../app
  • 追加アプリ自体をシンボリックリンク/ちょうどnode_modulesを、全体ではなくnode_modulesはgitのには、フォルダ
    • 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ユーザーは親ディレクトリの相対パスを使用する必要があります。

構成

通常、モジュールとクラスは、options渡される基本的なJavaScript オブジェクトのみを想定するようにコーディングします。モジュールのみapp/server.jsをロードする必要がありapp/config.jsます。そこから小さなoptionsオブジェクトを合成して必要に応じてサブシステムを構成できますが、すべてのサブシステムを追加情報でいっぱいの大きなグローバル構成モジュールに結合するのは不適切な結合です。

接続パラメータを渡してサブシステム自体に発信接続を行わせるのではなく、DB接続の作成を一元化してサブシステムに渡そうとします。

NODE_ENV

これは、Railsから引き継がれたもう1つの魅力的ですが恐ろしいアイデアです。アプリにapp/config.jsは、NODE_ENV環境変数を調べる場所が1つだけあるはずです。その他はすべて、クラスコンストラクターの引数またはモジュール構成パラメーターとして明示的なオプションを取る必要があります。

電子メールモジュールに電子メールの配信方法に関するオプション(SMTP、標準出力へのログ、キューに入れるなど)がある場合、次のようなオプションを使用する必要があります{deliver: 'stdout'}が、絶対にチェックしないでくださいNODE_ENV

テスト

テストファイルを対応するコードと同じディレクトリに保存し、ファイル名拡張子の命名規則を使用してテストと製品コードを区別しています。

  • foo.js モジュール「foo」のコードがあります
  • foo.tape.js fooのノードベースのテストがあり、同じディレクトリにあります
  • foo.btape.js ブラウザ環境で実行する必要があるテストに使用できます

find . -name '*.tape.js'必要に応じて、ファイルシステムグロブとコマンドを使用して、すべてのテストにアクセスします。

.jsモジュールファイル内のコードを整理する方法

このプロジェクトのスコープは主にファイルとディレクトリがどこにあるかに関するものであり、他のスコープをあまり追加したくありませんが、コードを3つの異なるセクションに編成することだけを述べます。

  1. CommonJSのオープニングブロックには、状態の依存関係への呼び出しが必要です
  2. pure-JavaScriptのメインコードブロック。ここにはCommonJS汚染はありません。exports、module、またはrequireを参照しないでください。
  3. CommonJSのブロックを閉じてエクスポートをセットアップする

1
bodyParserを使用するルートが少ない場合、bodyParserの代わりに何を使用すればよいですか?
Ilan Frumer 2014年

3
私はここで探していたものが見つかりました:stackoverflow.com/questions/12418372/...
宜蘭Frumer

1
チェックアウト@wlingke gist.github.com/branneman/8048520を、その問題への利用可能なアプローチの徹底的な議論のために。
Peter Lyons

@peterLyons共有していただきありがとうございます。読み終えたら、起動スクリプトを作成すると思います。ありがとう!
wlingke 2014

2
アプリのシンボリックリンクのトリック、があります。このすべての問題が離れて行かせる小さなモジュールは
ヘイココーユン

157

アップデート(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.coffeecoffeescriptファイルでは、次のようにします。

[
  '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マークダウンファイルを配置します。

NPMのgit repoルートにセマンティックバージョン番号を含むpackage.jsonファイルを置きます。


1
ねえピーター!私はこのアプローチが本当に好きです。私はエクスプレスプロジェクトの構築に取り組んでおり、実際にハックして配置するだけではなく、正しい方法でやりたいと思っています。githubにサンプルリポジトリやブログ投稿がある場合は、すばらしいでしょう。
suVasH ..... 2012

4
このリポジトリには、参照として使用できる多数
Peter Lyons

75
コーヒースクリプトはこれを読みにくくします:/バニラJS編集を取得する機会はありますか?ありがとう
toasted_flakes 2013年

1
この回答をありがとう。私はただ、私の心を包み込もうとしています。他のコントローラ内に他のコントローラにアクセスするにはどうすればよいですか(上記のようなセットアップ機能など)app.put route, api.needId
chmanie

@PeterLyons:やあ、私はあなたのソースコードを見ましたが、ビルドモードを実行する方法がわかりません、私はすでにインストールGoしてbinファイルを構造に含めています。そのgoファイルをどのように実行しますbinか?
user2002495 2014

51

以下は、Peter Lyonsの回答を逐語的に示したもので、他の何人かからの要求に応じてCoffeescriptからvanilla JSに移植されました。ピーターの答えは非常に有能であり、私の答えに投票する人は誰でも彼にも投票する必要があります。


構成

あなたがやっていることは結構です。このように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.jsjavascriptファイルで私はします:

[
  '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マークダウンファイルを配置します。

NPMのgit repoルートにセマンティックバージョン番号を含むpackage.jsonファイルを置きます。


43

私の質問は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アプリケーションをブートストラップすることです。これは、構成モジュール、ロガーモジュールをロードし、データベース接続を待機し、...、高速サーバーを実行します。

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

ルート/

ルートディレクトリには 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);
};

各ルートモジュールはスタンドアロンです。


ジェネレータを使用してこの構造を作成していますか?
アシッシュ2017年

18

関数などをエクスポートするのではなく、グローバルな「アプリ」を使用したい


私はクリエーターからアドバイスを受けることを選びます:)ところで、あなたは私たちにいくつかのコードを提供していただけませんか?
2013年

そのとおり。このアプリでは、github.com
visionmedia

17

それを行うには素晴らしい方法だと思います。表現に限定されませんが、githubで同じことを実行しているnode.jsプロジェクトのかなりの数を見てきました。それらは、構成パラメーターを取り出します+小さいモジュール(場合によってはすべてのURI)は、個別のファイルに因数分解されます。

アイデアを得るために、GitHubでExpress固有のプロジェクトを実行することをお勧めします。IMOのやり方は正しいです。


16

現在は2015年末で、3年間、小規模および大規模プロジェクトで私の構造を開発した後です。結論?

1つの大きなMVCを実行せず、モジュールで分離する

そう...

どうして?

  • 通常、1つは1つのモジュール(製品など)で動作し、個別に変更できます。

  • モジュールを再利用できます

  • あなたはそれを別々にテストすることができます

  • あなたはそれを別々に交換することができます

  • 彼らは明確な(安定した)インターフェースを持っています

    -少なくとも、複数の開発者が作業している場合、モジュールの分離が役立ちます

nodebootstrapのプロジェクトは、私の最終的な構造に類似のアプローチがあります。(github

この構造はどのように見えますか?

  1. それぞれが個別のMVCを備えた小型のカプセル化モジュール

  2. 各モジュールにはpackage.jsonがあります

  3. 構造の一部としてのテスト(各モジュール内)

  4. グローバル構成、ライブラリ、サービス

  5. 統合されたDocker、クラスター、永遠に

Folderoverview(モジュールについてはlibフォルダーを参照):

nodebootstrap構造


3
個々のモジュールも展開した状態でフォルダーの概要の図を更新できれば、それらをどのように構成するかの例として役立つでしょう。
youngrrrr

8

MVCスタイルのフォルダ構造を提供しています。以下をご覧ください。

大中規模のWebアプリケーションには、以下のフォルダー構造を使用しました。

 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

エクスプレスmvcフォルダー構造を生成するためのnpmモジュールを1つ作成しました。

以下のhttps://www.npmjs.com/package/express-mvc-generatorを見つけて ください

このモジュールを生成して使用するための簡単な手順。

i)モジュールをインストールする npm install express-mvc-generator -g

ii)チェックオプション express -h

iii)エクスプレスmvc構造を生成する express myapp

iv)依存関係をインストールしますnpm install::

v)config / database.jsを開き、mongo dbを設定してください。

vi)アプリケーションを実行するnode appか、nodemon app

vii)URL http:// localhost:8042 / signupまたはhttp:// yourip:8042 / signupを確認してください


7

この質問への最後の回答から久しぶりに、Expressがバージョン4を最近リリースしました。これにより、アプリの構造を整理するための便利な機能がいくつか追加されました。

以下は、Expressアプリを構造化する方法のベストプラクティスに関する長い最新のブログ投稿です。 http://www.terlici.com/2014/08/25/best-practices-express-structure.html

記事のアドバイスを適用するGitHubリポジトリもあります。Expressバージョンは常に最新です。
https://github.com/terlici/base-express


7

configにルートを追加するのは良い方法ではないと思います。より良い構造は次のようなものです:

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...

したがって、products.jsとusers.jsには、すべてのルートが含まれ、その中にすべてのロジックが含まれます。


6

さて、ルートをjsonファイルとして置き、最初にそれを読み、app.jsのforループにルートを設定しました。route.jsonには、呼び出すビューと、ルートに送信される値のキーが含まれています。
これは多くの単純なケースで機能しますが、特別なケースではいくつかのルートを手動で作成する必要がありました。


6

私はこの問題について正確に投稿しました。基本的には、その関数を呼び出すrouteRegistrarフォルダー内のファイルを反復処理するa を使用/controllersしますinit。関数initは、エクスプレスapp変数をパラメーターとして受け取るため、ルートを希望どおりに登録できます。

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プロジェクトのファイルシステムは次のようになります。

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

app.js-グローバルアプリコンテナー

2)モジュールのメインファイル(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)メインのapp.jsのConnectモジュール

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

4)サンプルロジック

lib/login
lib/db
lib/config
lib/users
lib/verify
lib/
   /api/ 
   ...
lib/
   /admin/
      /users/
      /settings/
      /groups/
...
  • テストに最適
  • 規模に最適
  • モジュールごとに異なります
  • 機能(またはモジュール)によるルートのグループ化

tjは、Vimeoの興味深いアイデアについて、Expressアプリケーション(Node.jsとExpressを使用したモジュール式Webアプリケーション)をモジュール化する方法について語ってい ます。強力でシンプル。


4

http://locomotivejs.org/は、Node.jsとExpressで構築されたアプリを構築する方法を提供します。

ウェブサイトから:

「LocomotiveはNode.jsのウェブフレームワークです。LocomotiveはMVCパターン、RESTfulルート、構成上の規約をサポートすると同時に、データベースやテンプレートエンジンとシームレスに統合します。LocomotiveはExpressをベースに構築されており、期待どおりのパワーとシンプルさを維持しています。ノードから。」


3

私は最近、独立したミニアプリとしてモジュールを採用しました。

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

これで、モジュールルーティング(#.js)、ビュー(* .ejs)、js、css、およびアセットが互いに隣接しています。サブモジュールのルーティングは、2つの追加行を含む親#.jsで設定されます

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

このように、サブサブモジュールも可能です。

ビューをsrcディレクトリに設定することを忘れないでください

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

ルート、ビュー、モデルがどのようにロードされているかを確認することに関心がある、そのような構造を持つgithubへのリンク
Muhammad Umer

すべてが説明されていると思います。ルートは、従来の高速ルートです。ビューはモジュール名を前に付けてロードする必要があり、モデルは相対パスを参照してロードする必要があります。
zevero

最後の行では、ビューをsrcディレクトリに設定しました。したがって、これ以降、すべてのビューはsrcディレクトリを基準にしてアクセスできます。派手なものは何もありません。
zevero 2018

1

これが私のExpressプロジェクトのディレクトリ構造のほとんどです。

私は通常express dirname、プロジェクトを初期化して怠惰を許すためにを行いますが、それは非常に柔軟で拡張可能です。PS-あなたはそれを手に入れる必要がありますexpress-generator(それを探している人のためにsudo npm install -g express-generator、あなたはそれをグローバルにインストールしているのでsudo)

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

なぜ.envファイルなのか不思議に思う必要がありますか?彼らが働くので!私dotenvは自分のプロジェクトでモジュールを使用しています(最近の多く)、それは機能します!app.jsまたはでこれら2つのステートメントをポップwww

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

そして/bower_components、リソースの下で静的コンテンツを提供するようにすばやく設定する別の行/ext

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

それはおそらくExpressとAngularを一緒に使用したい人やjavascripts、もちろんその階層なしで表現したい人に適しているでしょう。


1

私の構造は4を表現し ます。https://github.com/odirleiborgert/borgert-express-boilerplate

パッケージ

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

構造

|-- 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アプリを構築する簡単な方法:

  • メインのindex.jsでは、次の順序を維持する必要があります。

    すべてのapp.setを最初にする必要があります。

    すべてのapp.useは2番目でなければなりません。

    続いて、他のAPIとその機能、または他のファイルのroute-continue

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

    app.use( "/ user"、userApi);

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

    app.post( "/ logout"、passport.logout)


0

ハンドルバーとPassportjsを備えたExpressJsプロジェクトのMVC構造への最良の方法

- 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を確認してください
Manishkumar Bhavnani
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.