Bagaimana cara menyusun aplikasi express.js?

102

Apakah ada ketentuan umum untuk memecah dan memodularisasi app.jsfile dalam aplikasi Express.js ? Atau apakah biasa menyimpan semuanya dalam satu file?

Eric si Merah
sumber
3
Ada orang yang membaginya menjadi rute. Anda juga dapat melihat sumber daya ekspres.
BRampersad
@Brandon_R sudahkah Anda mencoba sumber daya? Saya melihatnya sekilas dan berpikir itu terlihat rapi, hanya saja belum menginjak ban.
Kesempatan
1
Agak terlambat, tetapi saya baru-baru ini membuka sumber router untuk ekspres yang memungkinkan Anda untuk memecah app.js dengan baik pada pengontrol intro + tampilan, dll. Lihat: github.com/kishorenc/road
jeffreyveon

Jawaban:

82

Saya telah memecah milik saya sebagai berikut:

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

Saya menggunakan Ekspor untuk mengembalikan apa yang relevan. Misalnya, dalam model yang saya lakukan:

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

dan kemudian jika saya perlu membuat nomor telepon, sesederhana itu:

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

jika saya perlu menggunakan skema, maka PhoneNumber.schema

(yang mengasumsikan bahwa kita bekerja dari folder routes dan perlu naik 1 level ke atas lalu turun ke model)


EDIT 4

The ekspres wiki memiliki daftar kerangka yang dibangun di atasnya.

Dari semua itu, menurut saya matador Twitter terstruktur dengan cukup baik. Kami sebenarnya menggunakan pendekatan yang sangat mirip dengan cara mereka memuat bagian aplikasi.

derby.js juga terlihat sangat menarik. Ini mirip dengan meteor tanpa semua hype dan benar-benar memberikan kredit di mana kredit jatuh tempo (terutama, simpul dan ekspres).


EDIT 3

Jika Anda adalah penggemar CoffeeScript (Saya bukan) dan sangat menginginkan L&F Rails, ada juga Tower.js .


EDIT 2

Jika Anda sudah familiar dengan Rails dan tidak keberatan dengan beberapa konsep yang beredar, ada Lokomotif . Ini adalah kerangka ringan yang dibangun di Express. Ini memiliki struktur yang sangat mirip dengan RoR dan membawa beberapa konsep yang lebih mendasar (seperti perutean).

Layak untuk dicoba bahkan jika Anda tidak berencana untuk menggunakannya.


EDIT 1

nodejs-express-mongoose-demo sangat mirip dengan struktur saya. Saksikan berikut ini.

Kesempatan
sumber
2
Kemana perginya logika bisnis? Apakah Anda pernah menggunakan pembantu untuk hal-hal seperti otentikasi?
Eric the Red
@ErictheRed jika Anda terbiasa dengan Pola MVC (rel, Asp.Net mvc, dll) maka saya menganggap Routes saya sebagai pengendali saya dan segala sesuatu jatuh ke tempatnya setelah itu. Logika bisnis masuk dalam model (meskipun saya mengalami kesulitan dengan validasi dan luwak). Untuk pembantu, saya menggunakan Ekspor pada pustaka util internal sederhana yang saya kumpulkan untuk diri saya sendiri untuk hal-hal yang saya gunakan kembali.
Kesempatan
Akan sangat bagus untuk mengunggah contoh penyiapan ke github untuk kita lihat. Apa yang ada di folder / file Rute?
chovy
1
@chovy Saya menambahkan tautan ke github.com/qed42/nodejs-express-mongoose-demo yang memiliki struktur yang sangat mirip
Kesempatan
Saya sarankan untuk menghindari kerangka kerja yang membengkak yang dibangun di atas ekspres
Raynos
9

Peringatan: kode referensi yang saya retas bersama untuk node knockout, ini berfungsi tetapi jauh dari elegan atau dipoles.

Untuk lebih spesifik tentang pemisahan app.jssaya memiliki file app.js berikut

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

bootstrap(app);

Ini pada dasarnya berarti saya menempatkan semua bootstrap saya dalam file terpisah, lalu saya bootstrap server.

Jadi apa yang dilakukan bootstrap ?

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

Yah itu membagi semua pengaturan inisialisasi server dalam potongan yang bagus. Secara khusus

  • Saya memiliki bagian yang mengatur semua otentikasi OAuth jarak jauh saya menggunakan everyauth.
  • Saya memiliki bagian yang mengonfigurasi aplikasi saya (pada dasarnya memanggil app.configure)
  • Saya memiliki sedikit kode yang lebih sedikit sehingga mengkompilasi ulang apa pun yang kurang saya ke dalam css pada saat dijalankan.
  • Saya memiliki kode yang mengatur semua rute saya
  • Saya menyebutnya modul nko kecil
  • Akhirnya saya memulai server dengan mendengarkan port.

Sebagai contoh mari kita lihat file routing

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

Di sini saya memuat semua model dan rute saya sebagai array file.

Penafian: readdirSync tidak apa-apa jika dipanggil sebelum Anda memulai server http (sebelum .listen). Memanggil panggilan pemblokiran sinkron pada waktu mulai server hanya membuat kode lebih mudah dibaca (pada dasarnya ini adalah retasan)

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

Di sini saya menekan socket.io untuk benar-benar menggunakan otorisasi daripada membiarkan tom dan jack apa pun untuk berbicara ke server socket.io saya

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

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

Di sini saya memulai rute saya dengan meneruskan model yang relevan ke setiap objek rute yang dikembalikan dari file rute.

Pada dasarnya jist adalah Anda mengatur semuanya menjadi modul kecil yang bagus dan kemudian memiliki beberapa mekanisme bootstrap.

Proyek saya yang lain (blog saya) memiliki file init dengan struktur serupa .

Penafian: blog rusak dan tidak bisa dibangun, saya sedang mengerjakannya.

Raynos
sumber
0

Saya memiliki aplikasi saya yang dibangun di atas alat generator ekspres. Anda dapat menginstalnya dengan menjalankan npm install express-generator -gdan menjalankannya menggunakanexpress <APP_NAME> .

Untuk memberi Anda perspektif, salah satu struktur aplikasi saya yang lebih kecil terlihat seperti ini:

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

Satu hal keren yang saya suka tentang struktur ini yang akhirnya saya adopsi untuk aplikasi ekspres apa pun yang saya kembangkan adalah cara rute diatur. Saya tidak suka harus mewajibkan setiap file rute ke app.js dan app.use()setiap rute, terutama karena file semakin besar. Karena itu, saya merasa app.use()terbantu untuk mengelompokkan dan memusatkan semua milik saya di file ./routes/index.js.

Pada akhirnya, app.js saya akan terlihat seperti ini:

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

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

dan ./routes/index.js saya akan terlihat seperti ini:

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

Saya dapat melakukannya hanya require(./users)karena saya menulis rute pengguna menggunakan express.Router () yang memungkinkan saya untuk "mengelompokkan" beberapa rute dan kemudian mengekspornya sekaligus, dengan tujuan membuat aplikasi lebih modular.

Ini adalah contoh apa yang Anda ingin lakukan pada rute ./routers/users.js saya:


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

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

module.exports = router;

Semoga ini membantu menjawab pertanyaan Anda! Semoga berhasil!

JKleinne
sumber