Nuxt comme serveur fullstack: serveur API frontend + backend (partie 1)

Nuxt comme serveur fullstack: serveur API frontend + backend


Les développeurs Nuxt proposent 3 méthodes d'accès à l'API:

  1. Construit dans Nuxt Server Connect et utilise le serveur
  2. Cadres intégrés ( Express, Koa, Hapi , etc.)
  3. API de serveur externe

Je vais montrer avec un exemple simple comment organiser un serveur API en utilisant serverMiddleware sur la même instance Nuxt que nous avons en frontend.

Quels sont les avantages de cette approche:

  • Démarrage rapide et la minimisation de la pile technologique, ne Nuxt est nécessaire , qui sera un serveur fullstack : rendre frontend pages et agir en tant que serveur API back - end
  • , 1 Node Nuxt, , (Nginx, php ..). - Nuxt - (MySQL, PostgreSQL, MongoDB ..)
  • , . , , .
  • Nuxt Connect, Node () 55 . , Nuxt' (Express, Koa, Hapi ..) .
  • Malgré le minimalisme, nous avons une liberté totale pour faire évoluer notre application, il est facile de déployer plusieurs serveurs Nuxt fullstack qui interagissent avec une base de données, ainsi que de déployer nginx pour équilibrer la charge entre plusieurs serveurs Nuxt fullstack . En outre, avec des modifications mineures, chaque instance Nuxt peut agir comme le seul serveur API (uniquement le serveur principal) et uniquement le serveur frontal (uniquement le serveur frontal).
  • Et un énorme bonus !!! Lorsque vous utilisez une instance pour le frontend et le backend, vous pouvez considérablement accélérer le rendu de page du serveur ( SSR ), dont je parlerai dans la partie 2

Alors, commençons.

1: Nuxt as API Server


  1. /api/ , API
  2. API Server :

    /serverMiddleware/api-server.js
    export default async (req, res, next) => {
      let url = req._parsedUrl.pathname.replace(/^\/+|\/+$|\.+/g, "");
      url = url.split("/");
      let method = url.pop();
      let controller = url.slice(1).join("/");
      let api = require("../api/" + controller);
      let result = await api[method](req.params);
      res.end(JSON.stringify(result));
    };
    
  3. API Server Nuxt serverMiddleware

    /nuxt.config.js
      serverMiddleware: [
        { path: "/api", handler: require("body-parser").json() },
        {
          path: "/api",
          handler: (req, res, next) => {
            const url = require("url");
            req.query = url.parse(req.url, true).query;
            req.params = { ...req.query, ...req.body };
            next();
          }
        },
        { path: "/api", handler: "~/serverMiddleware/api-server.js" }
      ],
    

    http://<server_name>/api/controller_name/method_name /api/ controller_name.js, method_name
  4. users

    /api/users.js
    // we can get data from any DB
    async function getDataFromDB() {
      return (await require("axios").get(`https://reqres.in/api/users?page=1`))
        .data;
    }
    
    async function index() {
      let res = await getDataFromDB();
    
      // some business logic
      let ret = res.data.map(el => {
        return {
          id: el.id,
          full_name: el.first_name + " " + el.last_name,
          highlight: el.first_name.charAt(0) === "J"
        };
      });
      ret = ret.sort(() => 0.5 - Math.random());
    
      return ret;
    }
    
    export { index };
    

    ,

    3gzhl.sse.codesandbox.io/api/users/index
    [
      {
        "id": 3,
        "full_name": "Emma Wong",
        "highlight": false
      },
      {
        "id": 5,
        "full_name": "Charles Morris",
        "highlight": false
      },
      {
        "id": 1,
        "full_name": "George Bluth",
        "highlight": false
      },
      {
        "id": 2,
        "full_name": "Janet Weaver",
        "highlight": true
      },
      {
        "id": 4,
        "full_name": "Eve Holt",
        "highlight": false
      },
      {
        "id": 6,
        "full_name": "Tracey Ramos",
        "highlight": false
      }
    ]
    
  5. index.vue API

    /pages/index.vue
    <template>
      <div>
        <h1 class="title">NUXT as API Server</h1>
        <h2 class="subtitle">Users</h2>
        <button type="button" @click="$fetch">Refresh</button>
        <ol>
          <li
            v-for="user in users"
            :class="{'highlight': user.highlight}"
            :key="user.id"
          >{{ user.full_name }}</li>
        </ol>
      </div>
    </template>
    
    <script>
    export default {
      data() {
        return {
          users: []
        };
      },
      async fetch() {
        try {
          this.users = await this.$axios.$get("/api/users/index");
        } catch (e) {
          console.error(e);
          throw e;
        }
      }
    };
    </script>
    
    <style scoped>
    .highlight {
      color: green;
      font-weight: bold;
    }
    </style>
    

    3gzhl.sse.codesandbox.io



    fetch , HTTP (https://3gzhl.sse.codesandbox.io/api/users/index), API json, .

    Refresh, http API .
  6. :

    API users (/api/users.js)

    ...
    async function show({ id }) {
      let res = await getDataFromDB();
    
      return res.data.filter(el => el.id == id)[0];
    }
    
    export { index, show };
    

    users

    /pages/index.vue
    <template>
      <div>
        <h1 class="title">NUXT as API Server</h1>
        <h2 class="subtitle">Users</h2>
        <button type="button" @click="$fetch">Refresh</button>
        <ol>
          <li
            v-for="user in users"
            :class="{'highlight': user.highlight}"
            :key="user.id"
            @click="getUserInfo(user.id)"
          >{{ user.full_name }}</li>
        </ol>
        <div v-if="userInfo">
          <hr>
          <h3>{{ userInfo.first_name }} {{ userInfo.last_name }}</h3>
          <div>Email: {{ userInfo.email }}</div>
          <img :src="userInfo.avatar" alt="avatar">
        </div>
      </div>
    </template>
    
    <script>
    export default {
      data() {
        return {
          users: [],
          userInfo: null
        };
      },
      async fetch() {
        try {
          this.users = await this.$axios.$get("/api/users/index");
        } catch (e) {
          console.error(e);
          throw e;
        }
      },
      methods: {
        async getUserInfo(id) {
          try {
            this.userInfo = await this.$axios.$post("/api/users/show", {
              id: id
            });
          } catch (e) {
            console.error(e);
            throw e;
          }
        }
      }
    };
    </script>
    
    <style scoped>
    li {
      cursor: pointer;
    }
    .highlight {
      color: green;
      font-weight: bold;
    }
    </style>
    

    Users, HTTP 3gzhl.sse.codesandbox.io/api/users/show?id=4

    {"id":4,"email":"eve.holt@reqres.in","first_name":"Eve","last_name":"Holt","avatar":"https://s3.amazonaws.com/uifaces/faces/twitter/marcoramires/128.jpg"}
    


  7. .. API, . API

    /plugins/api-context.js
    export default (context, inject) => {
        inject('api', async (controller, method, params) => {
            try {
                return await context.$axios['$' + (params ? 'post' : 'get')]('/api/' + controller + '/' + method, params);
            } catch (e) {
                console.error(e);
                throw e;
            }
        })
    }
    



    nuxt.config.js
    export default {
      ...
      plugins: ["~/plugins/api-context.js"]
    }
    

    ( ) :

    /pages/index.vue
    ...
    <script>
    export default {
      ...
      async fetch() {
        this.users = await this.$api("users", "index");
      },
      methods: {
        async getUserInfo(id) {
          this.userInfo = await this.$api("users", "show", {id: id});
        }
      }
    };
    </script>
    


1


Nous avons obtenu Nuxt avec un serveur API complet.

  • nos contrôleurs de serveur sont dans le dossier / api /
  • la logique de traitement des demandes d'API par le serveur se trouve
    /serverMiddleware/api-server.js
  • nous pouvons facilement étendre les fonctionnalités de l'API du serveur en ajoutant un nouveau middleware à / serverMiddleware / et en les connectant à nuxt.config.js

→ La version finale de cet exemple peut être consultée ici
→ Sandbox ici

All Articles