Next. Js is a great lightweight React isomorphic framework that allows you to quickly develop server-side renderings of React applications. On the next. Js website, it is recommended to deploy the application using Now, but for domestic users or users with special needs, deploying to a custom server is probably what most people want. By taking advantage of the recent revision of the company’s official website, I would like to share my experience from development to deployment.

I still remember that the first time I used Next-js was last year (2017). At that time, I used Next-js version 2.x and React version 15. A year later, React has developed to version 16 and Next-js has developed to version 6.0. In the process of using the new version is also encountered many pits.

The technology used

To start with what technologies were used this time, here is a list of the main technologies or tool libraries used in the project.

  • Koa 2

A next-generation Web framework developed by the original Express team to provide Web services.

  • nginx

Is a high performance HTTP and reverse proxy server, as well as an IMAP/POP3/SMTP server (from Baidu Baike), developed by the Russians. Used to provide static file services, HTTPS certificates, proxy services.

  • 16.3 the react

A javascript UI library

  • Next, js 6.0.1

A lightweight React isomorphic application framework

  • ant design

React is a set of background product component library developed by Ant Financial

  • react-motion

React based animation solution

  • react-waypoint

Determine whether the react component is in the current viewable area

  • pm2

Process manager for a Node application with load balancing

  • isomorphic-fetch

Isomorphic WHATWG Fetch API

The development phase

Having said so much, let’s enter the development phase, and the first step is to build the project architecture. Here we share our own project structure:

📁 .vscode

Vscode configuration file

📁 component

The react components

📁 common

In the public part, I put the navigation bar information, global variables, global styles, and so on

📁 pages

All page entry files of the project are also next. Js page entry files

📁 static

Static files

📁 styles

Individual page style sheets

🗄 index. Js

Node startup file

🗄 .babelrc

Babel configuration file

🗄 .gitignore

Git configuration files

🗄 ecosystem. Config. Js

Pm2 configuration file

🗄 next. Config. Js

Next. Js configuration file

🗄 postcss. Config. Js

Postcss configuration file

🗄 nginx. Conf

Nginx configuration file

🗄 package. Json

NPM configuration file

After configuring the project structure, assuming you have saved all the dependencies we need in package.json, let’s try typing YARN to install the dependencies. Assuming all goes well with the installation, let’s continue our development journey.

First, I created a new index.js file under the Pages file, where I randomly extracted some code from my real project and used it as a normal.

export default class HomePage extends React.Component {
  static async getInitialProps({ req, pathname }) {
    const data = await fetch(`${ctx}/api/projects/common/list`).then(res= > res.json())
    .then(dt= > dt)
    .catch(err= > {
      return {
        success: false.message: err.message
      }
    })
    return { pathname,data };
  }

  render() {
    const { pathname, data } = this.props;
    return (
      <div>
         <Head>
          <title>Home page - Ekejie (Wuhan) Ecological Technology Co., LTD</title>
        </Head>
        <div>Welcome to next.js!</div>{/* omit code here */}</div>); }}Copy the code

If you don’t have the next startup script configured in your package.json, go to Setup to do so. Let’s run NPM run dev on the console. If all goes well, open your browser and you’ll see Welcome to next.

Developing the experience in next.js is almost the same as react, but the WebPack configuration may require some work. Common plugins such as Sass, CSS, and next.js are already available, but you can also use community open source plugins to complete your development journey. For details, please visit the website of next.js.

The deployment of

After going through the development phase, testing, and so on, it’s finally time for deployment. In next. Js, you only need to run NPM run build. It is officially recommended not to change the folder name of the package (formerly called.next), but I recommend to change it to build or dist. After the packaging is complete, we need to write the nodeJS startup entry file. Here is the example code:

const Koa = require('koa')
const next = require('next')
const Router = require('koa-router')

const port = parseInt(process.env.PORT, 10) | |3000
constdev = process.env.NODE_ENV ! = ='production'
const app = next({ dev })
const handle = app.getRequestHandler()

app.prepare()
  .then((a)= > {
    const server = new Koa()
    const router = new Router()
	/ / home page
    router.get('/'.async ctx => {
      await app.render(ctx.req, ctx.res, '/', ctx.query)
      ctx.respond = false
    })
	/ / about
    router.get('/about'.async ctx => {
      await app.render(ctx.req, ctx.res, '/about', ctx.query)
      ctx.respond = false
    })
	/ / product
    router.get('/products/:id'.async ctx => {
      const {id} = ctx.params
      await app.render(ctx.req, ctx.res, `/products/${id}`, ctx.query)
      ctx.respond = false
    })
	/ / case
    router.get('/case'.async ctx => {
      await app.render(ctx.req, ctx.res, '/case', ctx.query)
      ctx.respond = false
    })
	// Contact us
    router.get('/contact'.async ctx => {
      await app.render(ctx.req, ctx.res, '/contact', ctx.query)
      ctx.respond = false
    })
	/ / details
    router.get('/view/:type/:id'.async ctx => {
      const {id, type} = ctx.params
      await app.render(ctx.req, ctx.res, `/view`, {id, type})
      ctx.respond = false
    })
    // If nginx is not configured to do static file service, the following code must be enabled
   /* router.get('*', async ctx => { await handle(ctx.req, ctx.res) ctx.respond = false })*/
    // Prevent console error 404
    server.use(async (ctx, next) => {
      ctx.res.statusCode = 200
      await next()
    })
    server.use(router.routes())
    server.listen(port, () => {
      console.log(`> Ready on http://localhost:${port}`)})})Copy the code

General static files, gzip compression do not need to be handed over to NodeJS to do, I have always considered professional things to professional people. If you do not use Nginx to do static file services, please enable it. Otherwise, js, CSS, image files, etc. packaged with next.js will be 404.

In the packaging stage of next. Js production, the js file request path contains the version number, while the real packaged folder does not have the actual corresponding directory, that is, the packaged folder is a virtual directory, which needs special attention when using nginx. Next. Js provides configuration items to change the build ID. Here’s my actual code:

// next.config.js
module.exports = {
  generateBuildId: async() = > {// For example get the latest git commit hash here
    return 'v1'}}Copy the code

The resulting virtual path is roughly _next/v1/page/xxx.js, which is slightly different if you use the CDN prefix, but the version number is still there.

Another pitfall is that next. Js is packaged with three folders: bundles, dist, and static. For those who don’t know the source code, there is no way to know which folder the actual requested files are in. So I looked at the source code of next. Js and found that I was actually looking for page in the bundle file, source location: L214

So you need to use aliases when configuring nginx. Here is my actual nginx configuration code:

		# site root directory file
        location ~ ^/(robots.txt|humans.txt|favicon.ico|sw.js|baidu_verify_7Kj6tQjI3v.html) {
            root /home/website/eco_website_pc/static/;
            if ($request_filename ~* sw.js){
                    expires -1s;
                }
            expires 10m;

	    }
        # static file
        location^ ~ /static/ {
            alias /home/website/eco_website_pc/static/;
            if ($request_filename ~* sw.js){
                    expires -1s;
                }
            expires 10m;

	    }
        # next Pages script
        location ~ ^/(/_next/v1/) {
            alias /home/website/eco_website_pc/build/bundles/;
            if ($request_filename ~* sw.js){
                    expires -1s;
                }
            expires 10m;

	    }
        # next static file
        location ~ ^/(/_next/static/) {
            root /home/website/eco_website_pc/build;
            if ($request_filename ~* sw.js){
                    expires -1s;
                }
            expires 10m;

	    }
Copy the code

After the static file is configured, HTTPS certificate needs to be configured. Because this project is on the official website of our company, I got a certificate for free, and I used the Asian integrity certificate provided by FreessL here. After applying for the SSL certificate, I need to configure the TXT record from the domain name provider. I am using Ali Cloud here. After completing the verification, FreessL will download the certificate, and after getting the certificate, I need to configure the Nginx SSL certificate.

server {
        listen       80;
        listen       443 ssl;
        server_name  wh-eco.com;
        charset utf-8;
        ssl_certificate /home/website/ssl/www/full_chain.pem;
        ssl_certificate_key /home/website/ssl/www/private.key;
        fastcgi_param   HTTPS               on;
        fastcgi_param   HTTP_SCHEME         https;

        if ($scheme = http ) {
          return 301 https://$host$request_uri;
        }
        access_log      /var/log/nginx/www.wh-eco.com.access.log;
        error_log       /var/log/nginx/www.wh-eco.com.error.log;
        location / {
            proxy_pass http://127.0.0.1:xxxx; Secret # 0.0
            proxy_set_header Host $host;
            #proxy_redirect off;
            proxy_set_header    REMOTE-HOST $remote_addr;
        	Websites may use the Websocket special upgrade request protocol in the future
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
	        proxy_connect_timeout 60;
            proxy_read_timeout 600;
            proxy_send_timeout 600;
        }
        # site root directory file
        location ~ ^/(robots.txt|humans.txt|favicon.ico|sw.js|baidu_verify_7Kj6tQjI3v.html) {
            root /home/website/eco_website_pc/static/;
            if ($request_filename ~* sw.js){
                    expires -1s;
                }
            expires 10m;

	    }
        # static file
        location^ ~ /static/ {
            alias /home/website/eco_website_pc/static/;
            if ($request_filename ~* sw.js){
                    expires -1s;
                }
            expires 10m;

	    }
        # next Pages script
        location ~ ^/(/_next/v1/) {
            alias /home/website/eco_website_pc/build/bundles/;
            if ($request_filename ~* sw.js){
                    expires -1s;
                }
            expires 10m;

	    }
        # next static file
        location ~ ^/(/_next/static/) {
            root /home/website/eco_website_pc/build;
            if ($request_filename ~* sw.js){
                    expires -1s;
                }
            expires 10m;

	    }
        error_page   500 502 503 504 = /error.html;
        error_page  404 = /notfound.html;
        location = /error.html {
                root   /home;
            }
        location = /notfound.html{
            root/home; }}Copy the code

As for gzip, you can configure it according to your requirements. Here is my sample configuration:

 	gzip  on;
    gzip_comp_level 6;
    gzip_vary on;
    gzip_types
        application/atom+xml
        application/javascript
        application/json
        application/rss+xml
        application/vnd.ms-fontobject
        application/x-font-ttf
        application/x-web-app-manifest+json
        application/xhtml+xml
        application/xml
        font/opentype
        image/svg+xml
        image/x-icon
        image/jpeg 
        image/gif 
        image/png
        text/css
        text/plain
        text/x-component;
Copy the code

All you need to do after configuring Nginx is launch the entire application in PM2 mode

pm2 start ecosystem.config.js
Copy the code

After running the above command, if all goes well, you can enter the domain name to access your application (assuming you have resolved the domain name).

conclusion

As deep as the sea at the front


Making | blog