Gyártásra kész Node és Express alkalmazás írása

Projekt strukturálása

Amikor elkezdtem a Node & Express alkalmazásokat építeni, nem tudtam, mennyire fontos az alkalmazás strukturálása. Az Express nem tartalmaz szigorú szabályokat vagy irányelveket a projekt struktúrájának fenntartására.

Bármely struktúrát használhat, amelyet csak akar. Amikor a kódbázisod megnő, hosszú routekezelővel rendelkezel. Ez megnehezíti a kód megértését, és lehetséges hibákat tartalmaz.

Ha egy startupnál dolgozik, akkor legtöbbször nem lesz ideje a projekt törésére vagy modulálására. Végeredményben a hibajavítás és javítás végtelen hurkja lehet.

Idővel, miközben mind a kis, mind a nagy csapatokkal dolgoztam, rájöttem, hogy milyen struktúra nőhet a projekteddel, és még mindig könnyen karbantartható.

Model View Controller

Az MVC minta segít a gyors és párhuzamos fejlődésben. Például az egyik fejlesztő dolgozhat a nézeten, míg egy másik az üzleti logika létrehozásával a vezérlőben.

Vessen egy pillantást egy egyszerű felhasználói CRUD alkalmazás példájára.

project/ controllers/ users.js util/ plugin.js middlewares/ auth.js models/ user.js routes/ user.js router.js public/ js/ css/ img/ views/ users/ index.jade tests/ users/ create-user-test.js update-user-test.js get-user-test.js .gitignore app.js package.json
  • vezérlők: Adja meg az alkalmazás útvonal-kezelőit és az üzleti logikát
  • util: Ide írja a segédprogram / segítő funkciókat, amelyeket bármely vezérlő használhat. Írhat például egy olyan függvényt, mint mergeTwoArrays(arr1, arr2).
  • middlewares: Írhat köztes eszközöket az összes beérkező kérelem értelmezéséhez, mielőtt az útvonalkezelőhöz lépne. Például,

    router.post('/login', auth, controller.login)hol authvan egy köztes függvény, amelyet itt definiáltak middlewares/auth.js.

  • modellek: egyfajta köztes szoftver is a vezérlő és az adatbázis között. Megadhat egy sémát, és elvégezhet bizonyos ellenőrzést, mielőtt az adatbázisba írna. Például használhat egy olyan ORM-et, mint a Mongoose, amely nagyszerű tulajdonságokkal és módszerekkel rendelkezik, amelyeket magában a sémában használhat
  • útvonalak: Határozza meg az alkalmazás útvonalait, HTTP módszerekkel. Például meghatározhat mindent, ami a felhasználóval kapcsolatos.
router.post('/users/create', controller.create) router.put('/users/:userId', controller.update) router.get('/users', controller.getAll)
  • public: Statikus képeket tárolhat /img, egyedi JavaScript fájlokban és CSS-ben/css
  • nézetek: A szerver által megjelenítendő sablonokat tartalmaz.
  • tesztek: Itt megírhatja az API-kiszolgáló összes egység- vagy elfogadási tesztjét.
  • app.js: A projekt fő fájljaként működik, ahol inicializálja az alkalmazást és a projekt egyéb elemeit.
  • package.json: Gondoskodik a függőségekről, a npmparanccsal futtatandó szkriptekről és a projekt verziójáról.

Kivételek és hibakezelés

Ez az egyik legfontosabb szempont, amelyre gondolni kell, ha bármilyen nyelvű projektet készít. Lássuk, hogyan kell kecsesen kezelni a hibákat és kivételeket az Express alkalmazásban.

Az ígéretek felhasználása

Az ígéretek visszahívásokkal szembeni előnyeinek egyik előnye, hogy képesek implicit vagy explicit kivételeket / hibákat kezelni az aszinkron kódblokkokban, valamint az .then()ígéret visszahívásban meghatározott szinkron kódok esetében.

Csak add hozzá .catch(next)az ígéretlánc végén. Például:

router.post('/create', (req, res, next) => { User.create(req.body) // function to store user data in db .then(result => { // do something with result return result }) .then(user => res.json(user)) .catch(next) })

Próbáld meg a fogást

A try-catch az aszinkron kódok kivételeinek elfogásának hagyományos módja.

Vessen egy pillantást egy lehetőségre a kivétel megszerzésére:

router.get('/search', (req, res) => { setImmediate(() => { const jsonStr = req.query.params try { const jsonObj = JSON.parse(jsonStr) res.send('Success') } catch (e) { res.status(400).send('Invalid JSON string') } }) })

Kerülje a szinkron kód használatát

Szinkron kód, más néven blokkoló kód, mert blokkolja a végrehajtást, amíg azok nem kerülnek végrehajtásra.

Ezért kerülje a szinkron függvények vagy módszerek használatát, amelyek milliszekundum vagy mikroszekundum lehet. Nagy forgalmú webhely esetén ez összetett és az API kérések nagy késleltetéséhez vagy válaszidejéhez vezethet.

Különösen ne használja a gyártásban :)

Sok Node.js modul mindkettővel .syncés .asyncmódszerrel együtt jár, ezért használja az aszinkront a termelésben.

De ha továbbra is szinkron API --trace-sync-io- t szeretne használni, használja a parancssori jelzőt. Figyelmeztetést és veremkövetést nyomtat, amikor az alkalmazás szinkron API-t használ.

A hibakezelés alapjairól bővebben lásd:

  • Hiba a Node.js fájlban
  • Robusztus csomópont alkalmazások építése: Hibakezelés (StrongLoop blog)
Mit kell nem tennie, hogy figyelje a uncaughtExceptionrendezvény kibocsátott egy kivétel buborékok egészen vissza az esemény hurok. Használata általában nem előnyös.

Megfelelő naplózás

A naplózás elengedhetetlen a hibakereséshez és az alkalmazás tevékenységéhez. Főleg fejlesztési célokra használják. Használjuk console.log, console.errorde ezek szinkron funkciók.

Hibakeresés céljából

Használhat olyan modult, mint a hibakeresés. Ez a modul lehetővé teszi a DEBUG környezeti változó használatát annak szabályozásához, hogy a hibakeresési üzeneteket milyen esetekben küldjük el console.err().

Alkalmazástevékenységhez

Az egyik módszer az, hogy beírja őket az adatbázisba.

Nézze meg, hogyan használtam mongúz beépülő modulokat alkalmazásom ellenőrzéséhez.

Another way is to write to a file OR use a logging library like Winston or Bunyan. For a detailed comparison of these two libraries, see the StrongLoop blog post Comparing Winston and Bunyan Node.js Logging.

require(“./../../../../../../”) mess

There are different workarounds for this problem.

If you find any module getting popular and if it has logical independence from the application, you can convert it to private npm module and use it like any other module in package.json.

OR

const path = require('path'); const HOMEDIR = path.join(__dirname,'..','..');

where __dirname is the built-in variable that names the directory that contains the current file, and .. ,..is the requisite number of steps up the directory tree to reach the root of the project.

From there it is simply:

const foo = require(path.join(HOMEDIR,'lib','foo')); const bar = require(path.join(HOMEDIR,'lib','foo','bar'));

to load an arbitrary file within the project.

Let me know in the comment below if you have better ideas :)

Set NODE_ENV to “production”

The NODE_ENV environment variable specifies the environment in which an application is running (usually, development or production). One of the simplest things you can do to improve performance is to set NODE_ENVto “production.”

Setting NODE_ENV to “production” makes Express:

  • Cache view templates.
  • Cache CSS files generated from CSS extensions.
  • Generate less verbose error messages.

Tests indicate that just doing this can improve app performance by a factor of three!

Using Process Manager

For production, you should not simply use node app.j — if your app crashes, it will be offline until you restart it.

The most popular process managers for Node are:

  • StrongLoop Process Manager
  • PM2
  • Forever

I personally use PM2.

For a feature-by-feature comparison of the three process managers, see //strong-pm.io/compare/. For a more detailed introduction to all three, see Process managers for Express apps.

Run your app in a cluster

In a multi-core system, you can increase the performance of a Node app by many times by launching a cluster of processes.

A cluster runs multiple instances of the app, ideally one instance on each CPU core. This distributes the load and tasks among the instances.

Using Node’s cluster module

Clustering is made possible with Node’s cluster module. This enables a master process to spawn worker processes. It distributes incoming connections among the workers.

However, rather than using this module directly, it’s far better to use one of the many tools out there that do it for you automatically. For example node-pm or cluster-service.

Using PM2

For pm2 you can use cluster directly through a command. For example,

# Start 4 worker processes pm2 start app.js -i 4 # Auto-detect number of available CPUs and start that many worker processes pm2 start app.js -i max 

If you encounter any problems, feel free to get in touch or comment below.

I would be happy to help :)

Don’t hesitate to clap if you considered this a worthwhile read!

References: //expressjs.com/en/advanced/best-practice-performance.html

Originally published at 101node.io on September 30, 2018.