📜 ⬆️ ⬇️

Making a project on Node.js using Mongoose, Express, Cluster. Part 1

Introduction


Good afternoon, dear% username%! Today we will describe the creation of a framework application like MVC on Node.js using clusters , Express.js and mongoose .


The task is to raise a server that has several features.



The article is written by a newbie for newbies. I would welcome any comments!


Where to begin? Install Node.js (which comes with npm). Install MongoDB (+ Add to PATH).


Now the creation of NPM project in order not to drag all the dependencies in our git!


$ npm init 

You have to answer a few questions (you can skip everything just by pressing Enter). Sometimes npm buggy and writing package.json does not complete.


Farther! Let's write our index.js


 // Project/bin/index.js process.stdout.isTTY = true; //   node.js    git bash  ! //  https://github.com/nodejs/node/issues/3006 var cluster = require('cluster'); //   if(cluster.isMaster) { //   <<master>>       require('./master'); } else { //   <<worker>>      worker-a require('./worker'); } 

A little about clusters.


What is a cluster? A cluster is a system of applications where there are two roles: the main role (master) and the working role (worker). There is one master to which all requests come, and the n-th number of workers (in the CPUCount code).


If a request comes to the server, then the master decides which worker to give this request. When creating a working node, a process is born that runs the same code that is currently running and creates an IPC . When a TCP / IP connection occurs, the wizard sends the Socket one of the workers for a specific policy (more details here ) via IPC.


Let's go back to the code. What happened to the master and worker? Master Code:


 //Project/bin/master.js var cluster = require('cluster'); //    cluster var CPUCount = require("os").cpus().length; //     //      .     8    Nodemon-     . //      CPUCount  1      .... cluster.on('disconnect', (worker, code, signal) => { //    IPC    (     ) console.log(`Worker ${worker.id} died`); //     ,     . cluster.fork(); //   }); cluster.on('online', (worker) => { //        ! console.log(`Worker ${worker.id} running`); }); //     CPUCount for(var i = 0; i < CPUCount; ++i) { cluster.fork(); //  ! :) } 

Pro arrow function , online , disconnect , template lines


What's next? Next work! Here we will write one code. Then I will say that we missed it and add it :) BUT before that, first download the dependencies from npm!


 $ npm i express apidoc bluebird body-parser busboy connect-mongo cookie-parser express-session image-type mongoose mongoose-unique-validator nodemon passport passport-local request request-promise --save 

Why do we need each module?



So? Let's write a script to launch nodemon. Add to package.json (replace if there is such a field)


 "scripts":{ "start":"nodemon bin/index.js" } 

To run, we will now use


 $ npm start 

In the future, we will add tests, documentation.


Now back to Worker. To get started, run Express!


 var express = require('express'); //  express var app = express(); //    app.get('/',(req,res,next)=>{ //  handler     `/` res.send('Hello, World!'); //   ! }); //     3000      . //  Worker-        app.listen(3000,function(err){ if(err) console.error(err); //       //   ..   handler- else console.log(`Running server at port 3000!`) //         //      }); 

It's all? Not. In fact, there are a few things that we have forgotten about setting up Express. Fix it. Do we need files for the front part? (Front-end). So add their support! Create a public folder whose entire contents will be available at /public . We have two options. Put NGINX and not put it. The easiest option is not to put it. We will use what is built into express.


An alternative option is to use NGINX as a master, who will also take responsibility for static files. Let's leave it for a while, although it will help with performance and scaling.


Before app.get('/') . Add the following:


 //.... var path = require('path'); // app = express();    //   //    project/public      /public app.use('/public',express.static(path.join(__dirname,'../public'))); //... 

It's all? AGAIN NO! Now to the input data. How will we get the input?


 var bodyParser = require('body-parser'); //.. /// app.use(express.static(.........)); // JSON  :) app.use(bodyParser.json({ limit:"10kb" })); //... 

Now to the cookie


 // JSON  // ... //  ! app.use(require('cookie-parser')()); // ... 

But that's not all! Next we need to get the Mongoose to work, for we will work with the sessions! Run the MongoDB command


 $ mkdir database $ mongod --dbpath database --smallfiles 

What is going on here? We create the database folder where the server data will be stored. Do not forget to add the folder to .gitignore . Then we run MongoDB pointing to the database folder as storage. And so that the files are small, we pass the parameter --smallfiles , although even in this case, MongoDB will store logs of 200MB in the ./database/journal folder


Also in the second part there will be a tutorial on how to increase the bandwidth of MongoDB, and install it as a service in systemd under Ubuntu.


Now to the code. In the file worker.js, at the beginning of the file immediately after the module loads, insert the following


 require('./dbinit'); //   

Create the dbinit.js file in the bin folder. In which we insert the following code:


 //  ! //  mongoose var mongoose = require('mongoose'); //    (Promise)      mongoose (mpromise) mongoose.Promise = require('bluebird'); //  Bluebird //    MongoDB //         mongoose.connect("mongodb://127.0.0.1/armleo-test",{ server:{ poolSize: 10 //      // 10     . //      ... } }); //        mongoose.connection.on('error',(err)=> { console.error("Database Connection Error: " + err); //     MongoDB  :) console.error('  MongoDB !'); process.exit(2); }); //         mongoose.connection.on('connected',()=> { //   console.info("Succesfully connected to MongoDB Database"); //       . }); 

Now we will tie the session to the database. In bin/worker.js add the following. Top of loading modules:


 var session = require('express-session'); //  var MongoStore = require('connect-mongo')(session); //     

And after parser cookies:


 //   //     app.use(session({ secret: ' ', //     resave: false, //      saveUninitialized: true, //    store: new MongoStore({ mongooseConnection: require('mongoose').connection }) //    })); 

A few explanations about the sequence of connections. express.static('/public') . Sits right at the beginning. Browsers send requests for files in parallel and they will send requests with empty sessions and we will create them in thousands.


Cookies parser and sessions are needed at the beginning. in the future they will use for authorization. Then the parsers of the request body go. NOTE: The last two can be swapped. Authorization service. It should go after parsers and sessions because uses them, but before the controllers because they use user information. Next are the controllers, we will return to them later.


Now error handler. He must go last. Express documentation is written like this :)


In the file bin/worker.js add before app.listen(.....); following


 //   app.use(require('./errorHandler')); 

Now create errorHandler.js file


 //      4 ,      module.exports = function(err,req,res,next) { // err    Express.js       ,       ; console.error(err); //        ,      . res.status(503).send(err.stack || err.message); //    next()      . //      503   }; 

Practically finished work with Worker. But we still need to customize the models and their loading.
Create a models folder where our models will be stored. In the future, we will have more migrations with the help of which we will migrate from one version of the database to the new one.


Create files index.js AND user.js in the models folder. Thus, in index.js we will record the loading of all models and their Export, and the user.js file will contain a model from Mongoose with some methods and functions attached to the model. You can read about the models on the Mongoose website or in the documentation .
In index.js write:


 module.exports = { //    () //  *nix-      User:require('./User') }; //     ! 

And in user.js write:


 //  mongoose ..          var mongoose = require('mongoose'); //   ! var userSchema = new mongoose.Schema({ //  username:{ type:String, // : String required:[true,"usernameRequired"], //   .        usernameRequired maxlength:[32,"tooLong"], //   32   (Unicode symbol != byte) minlength:[6,"tooShort"], //   ! match:[/^[a-z0-9]+$/,"usernameIncorrect"], //   !   ! unique:true //     }, //  password:{ type:String, //  String //       maxlength:[32,"tooLong"], minlength:[8, "tooShort"], match:[/^[A-Za-z0-9]+$/,"passwordIncorrect"], required:[true,"passwordRequired"] //      }, //     ,       ! }); //    ( ) //     module.exports = mongoose.model('User',userSchema); 

Now we will deal with the images (Attempt to translate the view ) and controllers. Create two folders: controllers and views . Now we select the library we need for rendering (drawing, drawing, compiling, filling) images. For me, was extremely simple mustache . But in order to make it easy to change the rendering engine, I use consolidate.


 $ npm i consolidate mustache --save 

Consolate requires the engines used by the project to be installed, so don’t forget after you change the engine to install it. Now we app.get('/'); replace the entire app.get('/'); on


 var cons = require('consolidate'); //    app.engine('html', cons.mustache); //    app.set('view engine', 'html'); //    app.set('views', __dirname + '/../views'); app.get('/',(req,res,next)=>{ //  handler     `/` res.render('index',{title:"Hello, world!"}); //      index }); 

Now in the views folder we add our index.html where we write


 {{title}} 

Go to 127.0.0.1:3000 and see Hello, World! . Let's go to the controllers! Remove the app.get lines app.get(.................) . Now we have to load the controllers. (Which are in the controllers folder). Instead of our remote code insert the following.


 app.use(require('./../controllers')); //  ! 

In the file controllers/index.js write


 var app = require('express')(); app.use(require('./home')); module.exports = app; 

And in the file controllers/home.js write:


 var app = require('express')(); app.get('/',(req,res,next)=>{ //  handler     `/` res.render('index',{title:"Hello, world!"}); //      index }); module.exports = app; 

At the end of the first part! Thanks for attention. Much remained without our attention, and it will be necessary to fix it in the second part. There are many controversial points. There are also many mistakes that will be fixed in the second part. The code will be posted a bit later on github. The essence of the project is explained in the second part.


')

Source: https://habr.com/ru/post/314394/


All Articles