Nuxt sebagai server fullstack: frontend + backend API Server (Bagian 1)

Nuxt sebagai server fullstack: frontend + backend API Server


Pengembang Nuxt menawarkan 3 metode mengakses API:

  1. Dibangun di Nuxt Server Connect dan gunakan serverMiddleware
  2. Kerangka kerja terintegrasi ( Express, Koa, Hapi , dll.)
  3. API server eksternal

Saya akan menunjukkan dengan contoh sederhana bagaimana mengatur server API menggunakan serverMiddleware pada contoh Nuxt yang sama yang kita miliki di frontend.

Apa manfaat dari pendekatan ini:

  • Mulai cepat dan meminimalkan tumpukan teknologi, hanya Nuxt yang diperlukan , yang akan menjadi server fullstack : render halaman frontend dan bertindak sebagai server API backend
  • , 1 Node Nuxt, , (Nginx, php ..). - Nuxt - (MySQL, PostgreSQL, MongoDB ..)
  • , . , , .
  • Nuxt Connect, Node () 55 . , Nuxt' (Express, Koa, Hapi ..) .
  • Terlepas dari minimalis, kami memiliki kebebasan penuh untuk mengukur aplikasi kami, mudah untuk menggunakan beberapa server Nuxt fullstack yang berinteraksi dengan satu database, ditambah menggunakan nginx untuk menyeimbangkan beban antara beberapa server Nuxt fullstack . Juga, dengan modifikasi kecil, setiap instance Nuxt dapat bertindak sebagai satu-satunya server API (hanya server backend), dan hanya server frontend (hanya server frontend).
  • Dan bonus besar !!! Saat menggunakan satu instance untuk frontend dan backend, Anda dapat secara signifikan mempercepat rendering halaman server ( SSR ), yang akan saya bahas di Bagian 2

Jadi mari kita mulai.

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


Kami mendapat Nuxt dengan server API lengkap.

  • pengendali server kami ada di folder / api /
  • logika untuk memproses permintaan API oleh server terletak
    /serverMiddleware/api-server.js
  • kita dapat dengan mudah memperluas fungsionalitas server API dengan menambahkan middleware baru ke / serverMiddleware / dan menghubungkannya ke nuxt.config.js

→ Versi terakhir dari contoh ini dapat dilihat di sini
→ Sandbox di sini

All Articles