Учебное пособие: использование Loopback 4 вместе с Next.js в одном экземпляре Heroku

Loopback 4 является отличным сервером для приложения. А Next.js отлично подходит для клиентской стороны. И они очень хорошо работают вместе.

Когда вы запустите их на отдельных серверах, у вас может вообще не возникнуть проблем с развертыванием. Но если вы хотите сэкономить некоторые ресурсы и запускать их вместе на одном экземпляре сервера, это может быть немного сложно. Сегодня я покажу вам, как это сделать. И мы будем использовать Heroku для развертывания.

Все вместе нам нужно будет выполнить следующие шаги:

  1. Настройка Loopback 4;
  2. Настройка Next.js;
  3. Настройка общего сервера;
  4. Разверните на Heroku.

Наш сервер Loopback 4 будет находиться по пути ./server, а приложение Next.js пойдет по пути./client. Итак, дерево проекта будет выглядеть так:

.
├── client
│   ├── index.js
│   ├── package.json
│   ├── pages
│   ├── server.js
│   └── ...
└── server
    ├── index.js
    ├── index.ts
    ├── package.json
    ├── src
    ├── tsconfig.json
    └── ...

1. Настройка Loopback 4

Чтобы установить Loopback 4, давайте просто следуем официальным инструкциям здесь.

Устанавливаем @loopback/cli глобально:

$ npm i -g @loopback/cli

И создаем новый проект:

$ lb4 app
? Project name: frogfish-server
? Project description: app
? Project root directory: server
? Application class name: FrogfishServerApplication
? Select features to enable in the project
 ◉ Enable tslint
 ◉ Enable prettier
 ◉ Enable mocha
 ◉ Enable loopbackBuild
 ◉ Enable vscode
 ◉ Enable repositories
 ◉ Enable services

Затем запускаем сервер и проверяем, что все хорошо:

$ cd server
$ npm start

Когда мы переходим по адресу http: // localhost: 3000 / ping, мы видим, что наше приложение работает правильно, и видим следующий ответ:

{
  greeting: "Hello from LoopBack",
  date: "2018-12-06T18:42:31.950Z",
  url: "/ping",
  headers: {...}
}

Хорошо, хорошо выглядишь. Теперь давайте настроим Next.js.

2. Настройка Next.js

Установка

То же, что и Loopback 4, давайте просто следуем официальным инструкциям отсюда.

Вне директории сервера мы запускаем это, чтобы запустить проект под директорией ./client:

$ mkdir client
$ cd client
$ npm init
package name: (client) frogfish-client
version: (1.0.0)
description:
entry point: (index.js)
test command:
git repository:
keywords:
author:
license: (ISC)

Затем устанавливаем зависимости:

$ npm install --save next react react-dom

И добавляем скрипты в наш package.json:

{
  "scripts": {
    "dev": "next",
    "build": "next build",
    "start": "next start"
  }
}

Ok. Затем создаем образец страницы на./client/pages/index.js:

export default () => <div>Welcome to next.js!</div>

Проверим, все ли работает:

$ npm run dev

И мы переходим по адресу http: // localhost: 3000 / и видим страницу-образец. Хорошо выглядеть!

Пользовательский клиентский сервер

Чтобы заставить Next.js работать с Loopback 4, нам понадобится специальный сервер для него. Давай сделаем одну. И давайте превратим его в модуль, чтобы сделать его многоразовым.

Создаем файл ./client/index.js с таким содержимым:

// ./client/index.js
const express = require('express');
const next = require('next');
module.exports = async function({
  beforeNext = () => {}, 
  dir = '.' } = {}
) {
  const dev = process.env.NODE_ENV === 'development';
  const port = process.env.PORT || 3000;
  const app = next({ dev, dir });
  const handle = app.getRequestHandler();
  const server = express();
  await app.prepare();
  await beforeNext(server);
  server.use(express.static(`${dir}/static`));
  server.get('*', (req, res) => handle(req, res));
  server.listen(port, err => {
    if (err) throw err;
    console.log(`> Ready on port: ${port}`);
  });
};

Как видите, мы создали серверный модуль, который может выполняться извне клиента. У него есть два аргумента:

  • beforeNext - функция, которая вызывалась бы до того, как Next.js обработает запрос. Здесь мы собираемся запустить наше приложение Loopback 4;
  • dir - каталог, в котором запускается проект Next.js, по умолчанию это будет ., но когда мы запустим его извне, он станет ./client.

А затем создаем бегун под ./client/server.js:

// ./client/server.js
const server = require('./');
server();

Мы меняем наш скрипт package.json dev следующим образом:

{
    "dev": "NODE_ENV=development node server.js",
}

И проверяем, что ничего не сломали:

$ npm run dev

Хорошо, пока все хорошо. Давайте склеим наш сервер с клиентом.

3. Настройте общий сервер.

Серверный скрипт

Итак, теперь у нас есть два каталога в нашем проекте. Один из них ./client, который содержит наш проект Next.js, а затем у нас есть ./server для приложения Loopback 4. И в корневом каталоге мы собираемся создать наш общий сервер, который будет обслуживать оба.

Давайте создадим файл named./index.js со следующим содержимым:

// ./index.js
const client = require('./client');
const serverApp = require('./server/dist/');
client({
  dir: 'client',
  beforeNext: async server => {
    const app = new serverApp.FrogfishServerApplication();
    await app.boot();
    server.use('/api', app.requestHandler);
  },
});

Вот как мы можем использовать оба приложения вместе на одном сервере!

Настройка package.json

Теперь мы собираемся создать общий package.json в корневом каталоге, где мы просто объединим зависимости обоих приложений:

{
  "name": "frogfish",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@loopback/boot": "^1.0.6",
    "@loopback/context": "^1.2.0",
    "@loopback/core": "^1.1.1",
    "@loopback/openapi-v3": "^1.1.3",
    "@loopback/repository": "^1.0.6",
    "@loopback/rest": "^1.4.0",
    "@loopback/rest-explorer": "^1.1.2",
    "@loopback/service-proxy": "^1.0.3",
    "express": "^4.16.4",
    "next": "^7.0.2",
    "npm-run-all": "^4.1.5",
    "react": "^16.6.3",
    "react-dom": "^16.6.3"
  },
  "devDependencies": {
    "@loopback/build": "^1.0.1",
    "@loopback/testlab": "^1.0.1",
    "@types/node": "^10.11.2"
  }
}

Затем устанавливаем зависимости:

$ npm install

Теперь давайте добавим туда скрипты для управления нашим приложением, для этого нам понадобится npm-run-all для параллельного запуска наших скриптов, мы устанавливаем его через:

$ npm install npm-run-all --save

И добавляем следующие скрипты:

{
  "scripts": {
    "dev": "NODE_ENV=development node .",
    "build": "npm-run-all --parallel build:server build:client",
    "build:client": "next build client",
    "build:server": "lb-tsc es2017 --outDir server/dist -p server",
    "start": "node .",
    "heroku-postbuild": "npm run build"
  }
}

С компиляцией TypeScript творится некое волшебство. Кроме того, все остальное просто. Также обратите внимание на сценарий heroku-postbuild. Он будет запущен после того, как наше приложение будет развернуто на heroku.

Исправление tsconfig.json

А теперь давайте сделаем последнее, давайте настроим ./server/tsconfig.json. Чтобы компиляция TypeScript работала, мы должны исправить ее extends ключ:

{
  "extends": "../node_modules/@loopback/build/config/tsconfig.common.json"
}

Мы только что добавили дополнительную точку перед /node_modules.

4. Разверните на Heroku

Развернуть на heroku просто. Мы создаем там приложение с именем frogfish. Затем разворачиваем:

git remote add origin https://git.heroku.com/frogfish.git
git push

И добавляем в нашу конфигурацию переменную HOST:

heroku config:set HOST=frogfish.herokuapp.com

Теперь приложение запущено! Yahoo

В качестве последнего шага давайте изменим ./client/pages/index.js, чтобы использовать наш новый API:

import React, { Component } from 'react';
export default class IndexPage extends Component {
  state = {
    response: {},
  };
  async componentDidMount() {
    const response = await (await fetch('/api/ping')).json();
    this.setState({ response });
  }
  render() {
    return (
      <div>
        <p>Welcome to next.js!</p>
        <p>{this.state.response.greeting}</p>
        <p>
          <pre>
            {JSON.stringify(this.state.response, undefined, 2)}
          </pre>
        </p>
      </div>
    );
  }
}

Затем мы развертываем, переходим на https://frogfish.herokuapp.com/ и ура, наше приложение Loopback 4 + Next.js запущено и работает. Мы видим приветствия с обеих сторон. Большое тебе спасибо.

Вы можете ознакомиться с исходным кодом на Github здесь.

Желаю вам приятных сеансов программирования и легкой интеграции. Увидимся в следующий раз! █