preface

Recently I have been busy adding the Node middle layer to the project, which is finally available in this release. I’ve been asked this question many times, and in my opinion, there are several reasons:

  • Cross-domain problems are avoided
  • Make the separation of the front and back end clearer, the back end is responsible for providing data, the front end only needs to pay attention to the EFFECT of the UI layer, part of the logic can be migrated to the middle layer processing
  • The domain name of the back-end interface is also protected. After the project is started, the interface displayed in the browser is the interface that passes the middle-layer forwarding

Without further ado, let’s see the implementation

Project address: github.com/huisunyang/…

Deploy the Node project and the Vue project under the same route

Create express project

Here we use Express as the technical framework

Create a new folder nodemiddle
npm init
Copy the code

Enter all the way down

npm install express
npx express-generator
npm install
Copy the code

Follow these steps to complete the initialization of the Express project

Create a VUE project

Initialize the VUE project in the newly created Nodemiddle folder

vue create hello-world
Copy the code

Mix the two items together

Install the connect-History-API-Fallback middleware

npm install --save connect-history-api-fallback
Copy the code

Once installed, switch to the Hello-world directory

npm run build
Copy the code

Generate folder dist

Then modify app.js

var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');

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

var app = express();

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

app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

// we commented out the two lines ----------------
// app.use('/', indexRouter);
// app.use('/users', usersRouter);
//---------------------------------------------

// ---------------- these three lines are newly added to -----------
var history = require('connect-history-api-fallback');
app.use(express.static(path.join(__dirname, './hello-world/dist')));
app.use(history());
//---------------------------------------------

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  next(createError(404));
});

// 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;
Copy the code

Switch to the root directory and run the project to see the results

Express Enables the HTTPS service

Due to our project, HTTPS service must be enabled locally

Check if you have OpenSSL (if you have Git installed)

openssl version -a
Copy the code

Generating a Certificate File

#1Run the openssl genrsa -out privatekey.pem command to generate the privatekey file1024

#2Use the private key to generate the CSR certificate signature. (Some information is required and press Enter.) openSSL req -new -key privatekey.pem -out certrequest.csr

#3Openssl x509 -req - Generates a certificate file using the private key and certificate signaturein certrequest.csr -signkey privatekey.pem -out certificate.pem
Copy the code

The third command will prompt Signature OK, indicating success

Then we modify the app.js file

// Comment out this line
// module.exports = app;
// Change to the following
var options = {
  key: fs.readFileSync('./ssl/privatekey.pem'),
  cert: fs.readFileSync('./ssl/certificate.pem')}; https.createServer(options, app).listen(8443.function () {
  console.log('Https server listening on port ' + 8443);
});
Copy the code

At this point we can start the HTTPS service locally

Interface forwarding implementation

Since the graphQL interface is used in our project, I will simply implement graphQL interface forwarding. Since I have not dealt with forwarding as resetful, I made a layer of transformation here, calling graphQL interface in Express. But the Resetful interface is provided to the VUE project

First download dependencies

npm i apollo-fetch
Copy the code

Modify the app. Js

const { createApolloFetch } = require('apollo-fetch');
app.get('/graphql'.(request,response) = > {
  const fetch = createApolloFetch({
    uri: 'http://localhost:8080/graphql'}); fetch({query: '{ hello}',
  }).then(res= > {
    console.log(res)
  })
})
Copy the code

The graphQL interface provided here is a demo of my simple implementation, see github.com/huisunyang/…

Exception handling

Since forward interface, so must without exception handling, which may be embarrassing is express have no way to deal directly with the promise is unusual, usually an error UnhandledPromiseRejectionWarning here I take is to modify the routing component

const Layer = require('express/lib/router/layer');

Object.defineProperty(Layer.prototype, 'handle', {
  enumerable: true.get() {
    return this.__handle;
  },
  set(fn) {
    if (fn.length === 4) {
      this.__handle = fn;
    } else {
      this.__handle = (req, res, next) = >
        Promise.resolve()
          .then(() = >fn(req, res, next)) .catch(next); }}})Copy the code

Add the above code and you can handle the exception directly

app.get('/test'.(request,response) = > {
  axios.get('http://localhost:3000/test').then(res= > {
    response.send(res.data)
  }).catch(error= > {
    response.status(error.response.status).send(error)
  })
})
Copy the code

Write in the last

The above is what I did when I added the node middle layer to the Vue project. I am still optimizing it later. Please point out any mistakes, thank you!!