From zero to deployment: realizing Mini full stack e-commerce application with Vue and express (2)

Time:2021-4-14

From zero to deployment: realizing Mini full stack e-commerce application with Vue and express (2)

Some websites and apps we usually use will save our data. When we close these websites or apps, we can still see some text and video records before us next time. In the second tutorial of the mini full stack e-commerce application practical series, we will Node.js The express framework of the platform implements the back-end API data interface and stores the data in mongodb. In this way, our website can record the products added by users, and no matter when we open it later, we can get our previous records.

Tips

Reading this article requires you to have a certain understanding of the express framework. If you are not familiar with it, you can read this tutorial to get started quickly.

Welcome to “from zero to deployment: Mini full stack e-commerce applications with Vue and express” series:

  • From zero to deployment: realizing Mini full stack e-commerce application with Vue and express (1)
  • From zero to deployment: realizing Mini full stack e-commerce application with Vue and express
  • From zero to deployment: realizing Mini full stack e-commerce application with Vue and express (3)(Coming soon
  • From zero to deployment: realizing Mini full stack e-commerce application with Vue and express (4)(Coming soon
  • From zero to deployment: realizing Mini full stack e-commerce application with Vue and express (5)(Coming soon
  • From zero to deployment: realizing Mini full stack e-commerce application with Vue and express (6)(Coming soon
  • From zero to deployment: realizing Mini full stack e-commerce application with Vue and express (7)(Coming soon
  • From zero to deployment: realizing Mini full stack e-commerce application with Vue and express (8)(Coming soon

If you think our writing is good, rememberLike + follow + commentSan Lian, encourage us to write a better tutorial

Quick start

code

You can see the final source code of this part of the tutorial in GitHub: the source code address.

Initialize project

First, let’s use the express generator scaffold to initialize our express project. Run the following command on the terminal to install:

npm install -g express-generator

Open the terminal and input the following command to test whether the installation is successful:

express --version # 4.15.5

Then enter the following command to initialize our express project:

express vue-online-shop-backend

After the project is initialized successfully, open the project with the following command:

cd vue-online-shop-backend
npm install
npm start

Then open the browser and enterhttp://localhost:3000/Check out our initial good project results.

From zero to deployment: realizing Mini full stack e-commerce application with Vue and express (2)

Discussion on scaffold code

In the project code initialized by express generator, we only need to know the following four files in the whole tutorial:

  • app.js: Express application master file
  • bin/www: script used to start the server
  • routes/index.js: route master file
  • views/index.ejs: the template file of the home page. Here we only intend to implement the API data interface, so we don’t need to care about it

Unlike previous express tutorials, scaffolding code doesn’t put all the routes in theapp.jsInstead, it is split according to different sub applications (users and index), which coincides with the nested routing of Vue router in the first tutorial of this series.

Let’s take a general lookapp.jsandroutes/index.jsThe basic knowledge of express. Let’s look at it firstapp.jsCode:

var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

var index = require('./routes/index');
var users = require('./routes/users');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', index);
app.use('/users', users);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;

Start by importing the dependent dependencies, and then call theexpress()Initialize the Express instance, and then we set the template engine toejs, and the directory where the template engine is stored, then a series of middleware is loaded and used, and finally the Express instance is exported to thebin/wwwScript and start the server.

Tips

Here we can see the two routes we importedindexandusers, is also processed like other middleware, so “everything is middleware” in express.

Let’s take another look at our routing sectionroutes/index.jsRouting is the core of our API server. When we add, delete, modify and query data, we need to access specific routing interfaces. In the whole tutorial, we almost focus on routing.

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

/* GET home page. */
router.get('/', function(req, res, next) {
  res.render('index', { title: 'Express' });
});

module.exports = router;

The above code is imported firstexpressAnd then generate a property using therouterExamples, and then defines thegetThis HTTP method is used to handle theGETMethod to access our server address/How to deal with it, and finally export ourindexroute.

In fact, our API server accesses our defined routes through various HTTP methods (post, delete, put, get, etc.), and then performs corresponding addition, deletion, and query operations on the database to obtain the expected data.

Summary

Through a simple explanationexpress-generatorWe learned the following knowledge from the above four files generated by scaffolding:

  • In express, everything is middleware. We use composite middleware to deal with the back-end logic of replication.
  • In fact, our API server defines a series of routes. When we access these routing interfaces with different HTTP methods, we can add, delete and query the data accordingly.
  • Although express can also display user interface through template engine, because the front end of our mini e-commerce application has been implemented with Vue, there is no need for template engine.

Access to mongodb database

Database is undoubtedly the most popular solution for data persistent storage, and mongodb stands out from many database products with its excellent performance, scalability and flexible data mode. Moreover, mongodb’s core function is based on bson (binary JSON), and even provides JavaScript shell, so it is very popular in node community. Mongodb can be downloaded from its official website. After downloading and installing, open a new terminal (command console), run the following command to open the database (Windows users can search mongo.exe And open:

$ mongod
2019-12-22T18:10:25.285+0800 I CONTROL  [initandlisten] MongoDB starting : pid=14475 port=27017 dbpath=/data/db 64-bit host=mRc
2019-12-22T18:10:25.285+0800 I CONTROL  [initandlisten] db version v3.6.0
2019-12-22T18:10:25.285+0800 I CONTROL  [initandlisten] git version: a57d8e71e6998a2d0afde7edc11bd23e5661c915
...

openmongodAfter that, a lot of log information will be output, and it can be accessed through thelocalhost:27017Visit. Then go back to the terminal we started before and install the NPM package mongoose

$ npm install mongoose

Mongoose is the most popular ODM (object document mapping) in mongodb, which is more convenient to use than the underlying mongodb node driver.

And then we’re in our roomapp.jsFile importmongoose, and throughmongooseThe interface provided connects to our mongodb database:

// ...
const mongoose = require('mongoose');

// ...

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

//Connect to database
mongoose.connect(`mongodb://localhost:27017/test`);


// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
// ...

Then we went throughnpm startAfter running the server, we connected to our mongodb database in express. Although we can’t see any effect yet, we will immediately write a routing operation database to test the effectiveness of the connection.

Allow cross domain access to resources

Next, we need to do a little extra operation. Although it doesn’t seem to be related to our project, it is a necessary step. That is to enable cross origin resources sharing (CORS). CORS is a solution to restrict the access of resources under this domain name. When it is closed, another domain name will be denied access to the resources of this domain name. If you want to know more about CORS, I recommend an article by Ruan Yifeng, which explains the principle of CORS in detail.

We open itapp.jsFile, add the following code:

// ...

// Database connection here
mongoose.connect(`mongodb://localhost:27017/test`);

// CORS config here
app.all('/*', function(req, res, next) {
  // CORS headers
  res.header("Access-Control-Allow-Origin", "*"); // restrict it to the required domain
  res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
  // Set custom headers for CORS
  res.header('Access-Control-Allow-Headers', 'Content-type,Accept,X-Access-Token,X-Key');
  if (req.method == 'OPTIONS') {
    res.status(200).end();
  } else {
    next();
  }
});

Generally speaking, there are many problems in the above code. We usually use NPM packagecorsTo solve this problem, of course, we use a relatively simple and crude way here.

Design schema and models of database

To interact with mongodb database through mongoose in the server, we need to defineSchemaandModel. By defining them, you can tell mongoose what data structure and corresponding data type you need.

Let’s create itmodel/index.jsDocument ourSchema

const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const model = mongoose.model.bind(mongoose);
const ObjectId = mongoose.Schema.Types.ObjectId;

const productSchema = Schema({
  id: ObjectId,
  name: String,
  image: String,
  price: Number,
  description: String,
  manufacturer: { type: ObjectId, ref: 'Manufacturer' }
});

const manufacturerSchema = Schema({
  id: ObjectId,
  name: String,
});

const Product = model('Product', productSchema);
const Manufacturer = model('Manufacturer', manufacturerSchema);

module.exports = { Product, Manufacturer };

SchemaReceive a JavaScript object to describe the data structure we need and the corresponding data type, except for the well-known objects likeStringNumberAnd other data types,ObjectIdIs a special data type. We use it to define the primary key of our single mongodb document, which is used to mark the uniqueness of stored data.

We can also see that in ourproductSchemaIn the middle,manufacturerWe define a data structurerefProperty, which is a foreign key function similar to relational database provided by mongodb. It allows us to create one to many data documentsproductSchemaOfmanufacturerThe data type corresponding to the attribute is aManufacturerrecord.

Then we went throughmodelTo create a data model for, and then export the data model we created. theremodelIs the classic MVC design patternModel

Complete API routing

Routing is the key component of express, and it is also the entry for the interaction between the client and the server. In express routing, two parameters are accepted: request and response. One is used to obtain the request of the client, and the other is used to send the response to the client server.

openapp.jsFile, add the following code:

// ...

var index = require('./routes/index');
var users = require('./routes/users');
const api = require('./routes/api');

var app = express();

// ...

app.use('/', index);
app.use('/users', users);
app.use('/api/v1', api);

// ...

As you can see, we importedapiRoute, and define the access path/api/v1. All visits/api/v1And its sub paths, such as/api/v1/xxxWill be activatedapiProcessing function, in the classic MVC design pattern,apiAlso known asControllers

Then we writeapiControllers, in which we define the routing interface for operating goods and manufacturers. Here we will use the classic restful API to write our routing interface

const express = require('express');
const router = express.Router();
const productController = require('../../controllers/product');
const manufacturerController = require('../../controllers/manufacturer');

router.get('/manufacturers', manufacturerController.all);
router.get('/manufacturers/:id', manufacturerController.byId);
router.post('/manufacturers', manufacturerController.create);
router.put('/manufacturers/:id', manufacturerController.update);
router.delete('/manufacturers/:id', manufacturerController.remove);

router.get('/products', productController.all);
router.get('/products/:id', productController.byId);
router.post('/products', productController.create);
router.put('/products/:id', productController.update);
router.delete('/products/:id', productController.remove);

module.exports = router;

As you can see, we willindexWe imported ourproductControllerandmanufacturerController. Then a series of routes are defined.

Operate heremanufacturerThe functions of the first five routes are as follows:

  • GET /manufacturersObtain all manufacturers
  • GET /manufacturers/:idGet a single manufacturer, here:idRepresents a dynamic route, used to match arbitrary strings:/manufacturers/<any-string>
  • POST /manufacturersUser creates single manufacturer
  • PUT /manufacturers/:idUsed to modify individual manufacturers
  • DELETE /manufacturers/:idUsed to delete a single manufacturer

CorrespondingproductThe five routing functions of are as follows:

  • GET /productsGet all products
  • GET /products/:idGet a single item here:idRepresents a dynamic route, used to match arbitrary strings:/products/<any-string>
  • POST /productsUser creates a single product
  • PUT /products/:idUsed to modify a single item
  • DELETE /products/:idUsed to delete a single item

Finally, we export our route.

Next, let’s take a look at the detailsmanufacturer Controller。

const Model = require('../model');
const { Manufacturer } = Model;

const manufacturerController = {
  all(req, res) {
    Manufacturer.find({})
      .exec((err, manfacturers) => res.json(manfacturers))
  },
  byId(req, res) {
    const idParams = req.params.id;

    Manufacturer
      .findOne({ _id: idParams })
      .exec((err, manufacturer) => res.json(manufacturer));
  },
  create(req, res) {
    const requestBody = req.body;
    const newManufacturer = new Manufacturer(requestBody);

    newManufacturer.save((err, saved) => {
      Manufacturer
        .findOne({ _id: newManufacturer._id })
        .exec((err, manfacturer) => res.json(manfacturer))
    })
  },
  update(req, res) {
    const idParams = req.params.id;
    let manufacturer = req.body;

    Manufacturer.updateOne({ _id: idParams }, { ...manufacturer }, (err, updated) => {
      res.json(updated);
    })
  },
  remove(req, res) {
    const idParams = req.params.id;

    Manufacturer.findOne({ _id: idParams }).remove( (err, removed) => res.json(idParams) )
  }
}

module.exports = manufacturerController;

You can see that we define amanufacturerControllerObject to organize a series of pairs of objectsmanufacturerAdd, delete, modify and query.

We started by importing what we defined earlierManufacturerModelThis is the interface that mongoose provides for us to operate the database. We can add and delete data by defining a series of operations on the model, such as find, findone, updateone, and deleteone.

Finally, it’s oursproductController, its internal operation is the same as what we mentioned abovemanufacturerThey are basically the same.

const Model = require('../model');
const { Product } = Model;

const productController = {
  all(req, res) {
    Product.find({})
      .populate('manufacturer')
      .exec((err, products) => res.json(products))
  },
  byId(req, res) {
    const idParams = req.params.id;

    Product
      .findOne({ _id: idParams })
      .populate('manufacturer')
      .exec((err, product) => res.json(product));
  },
  create(req, res) {
    const requestBody = req.body;
    const newProduct = new Product(requestBody);

    newProduct.save((err, saved) => {
      Product
        .findOne({ _id: newProduct._id })
        .populate('manufacturer')
        .exec((err, product) => res.json(product))
    })
  },
  update(req, res) {
    const idParams = req.params.id;
    const product = req.body;

    console.log('idParams', idParams);
    console.log('product', product);

    Product.updateOne({ _id: idParams }, { ...product }, (err, updated) => {
      res.json(updated);
    })
  },
  remove(req, res) {
    const idParams = req.params.id;

    Product.findOne({ _id: idParams }).remove( (err, removed) => res.json(idParams) )
  }
}

module.exports = productController;

Write the above code and save, open the terminal inputnpm startTo turn on our server.

Because our server needs to connect to the mongodb database when it is started, to ensure that the local mongodb database has been started, we can start it through the following command:

$ mongod

Well, now our API server has been built. Now let’s test whether our API is successful through the API testing tool postman.

testGET /api/v1/manufacturers

From zero to deployment: realizing Mini full stack e-commerce application with Vue and express (2)

testPOST /api/v1/manufacturers: we add mobile phone manufacturers"One plus"

From zero to deployment: realizing Mini full stack e-commerce application with Vue and express (2)

testPUT /api/v1/manufacturers/:idHere we put"One plus"Change to"One Plus"

From zero to deployment: realizing Mini full stack e-commerce application with Vue and express (2)

From zero to deployment: realizing Mini full stack e-commerce application with Vue and express (2)

testDELETE /api/v1/manufacturers/:idLet’s add the"One plus"Delete

From zero to deployment: realizing Mini full stack e-commerce application with Vue and express (2)

From zero to deployment: realizing Mini full stack e-commerce application with Vue and express (2)

Finally, test and add productsproductPOST /api/v1/productsHere we are definingproductWhen adding theManufacturerAs a foreign key, the correspondingmanufacturerProperty to be aManufacturerOfObjectIdFor example, we add new products of Xiaomi hereMix Alpha

From zero to deployment: realizing Mini full stack e-commerce application with Vue and express (2)

You can see that we addedmanufacturerby5da72eaac6ccea32f823c247Xiaomi manufacturer’s new mobile phone"Mix Alpha"

Summary

Since then, our API server has been built. In this tutorial, we have learned the following knowledge:

  • Learn about express routing and how to use mongoose to connect to mongodb database
  • Write routing, model and controllers
  • Use postman to test our API

I believe that through the study of this tutorial, you have a basic understanding of using node and express to write API back-end server. Now we know the basic knowledge of Vue and how to build back-end server. Next, we will consider how to use Vue to build large-scale applications. See you in the next tutorial!

Want to learn more wonderful practical technical courses? Come to Tuque community.

From zero to deployment: realizing Mini full stack e-commerce application with Vue and express (2)

Recommended Today

Review of SQL Sever basic command

catalogue preface Installation of virtual machine Commands and operations Basic command syntax Case sensitive SQL keyword and function name Column and Index Names alias Too long to see? Space Database connection Connection of SSMS Connection of command line Database operation establish delete constraint integrity constraint Common constraints NOT NULL UNIQUE PRIMARY KEY FOREIGN KEY DEFAULT […]