Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HTTPS on localhost using NextJS + Express

System Information

  • Express: 4.16.4
  • NextJS: 8.0.3
  • React: 16.8.4
  • ReactDOM: 16.8.4

Goal

Serve the web application using SSL over HTTPS on localhost

What has been done

  1. Created basic NextJS application using Create Next App
  2. Generated a certificate and key using OpenSSL and moved it into the project directory
  3. Added the Express dependency
  4. Configured the app to use express inside server.js
  5. Changed script to use the server.js inside package.json scripts.

server.js

const express = require('express');
const next = require('next');
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handle = app.getRequestHandler();
const port = 3000;

const https = require('https');
const fs = require('fs');
const httpsOptions = {
  key: fs.readFileSync('./certificates/key.pem'),
  cert: fs.readFileSync('./certificates/cert.pem')
};

app
  .prepare()
  .then(() => {
    const server = express();

    server.get('*', (req, res) => {
      return handle(req, res);
    });

    server.listen(port, err => {
      if (err) throw err;
      console.log('> Ready on http://localhost: ' + port);
    });
  })
  .catch(ex => {
    console.error(ex.stack);
    process.exit(1);
  });

Extra Information

The app currently works when initialized using yarn dev. I have tried to serve the app over https using this answer but I was unable to figure out how to apply this to my current setup using NextJS.

I spent a lot of time researching the web how to apply this solution but have not yet found a way on how to make this work.

Any help is greatly appreciated.

like image 354
Benjamin Löffel Avatar asked Mar 22 '19 16:03

Benjamin Löffel


People also ask

How do I enable https on Nextjs?

js local dev server via HTTPS (e.g., https://localhost:3000). We will be using `create-next-app ` to get a simple Next. js app set up, `mkcert` to generate a locally-trusted SSL certificate, and `local-ssl-proxy` to access our Next. js app's local dev server via HTTPS.

Can I use Nextjs with Express?

js doesn't replace Express and you can use them together. Next. js uses some Node. js features, mainly for front-end development, while ExpressJS is used only for back-end development.

Can Nextjs replace backend?

Yes. Next. js is a pre-rendered React app in the client-side that users can view and interact with and can be considered as front-end. At the same time, it also does server-side rendering and API routes which can perform server-side code and access data in the database and can be considered as back-end.


2 Answers

Other answer seemed to just drop express... Found a solution after some difficulty with both server code and certificate so hopefully can save someone else the trouble!

First of all, solid advice for creating localhost certificate here: https://letsencrypt.org/docs/certificates-for-localhost/

Secondly, simple code that offers HTTP/HTTPS with next js and express:

const next = require('next');
const express = require('express');
const http = require('http');
const https = require('https');
const fs = require('fs');

const ports = {
  http: 3080,
  https: 3443
}
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handle = app.getRequestHandler();
const server = express();  

const options = { 
  key: fs.readFileSync('localhost.key'),
  cert: fs.readFileSync('localhost.crt'), 
};

app.prepare().then(() => {           
  server.all('*', (req, res) => {
    return handle(req, res)    
  });
  http.createServer(server).listen(ports.http);
  https.createServer(options, server).listen(ports.https);
});

It is worth noting that one could omit or redirect either port.

like image 142
PJRobot Avatar answered Oct 27 '22 01:10

PJRobot


You just need to use the createServer method of https module.

const { createServer } = require('https');
const { parse } = require('url');
const { readFileSync } = require('fs');
const next = require('next');

const port = 3000;
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handle = app.getRequestHandler();

const httpsOptions = {
  key: readFileSync('./certificates/key.pem'),
  cert: readFileSync('./certificates/cert.pem')
};

app.prepare()
  .then(() => {
    createServer(httpsOptions, (req, res) => {
      const parsedUrl = parse(req.url, true);
      handle(req, res, parsedUrl);
    }).listen(port, err => {
      if (err) throw err;
      console.log(`> Ready on https://localhost:${port}`);
    })
  });
like image 21
Tibi02 Avatar answered Oct 27 '22 02:10

Tibi02