Nuxt配合Node在實際生產中的應用

A0150315發表於2018-08-03

上個星期,甲方說要在應用上做一個促活活動(其實就是讓使用者領OFO的騎車券),考慮到之前在我另一個應用上已經做過客戶端token驗證,想想,擼起袖子直接在之前的Node上開搞吧。

  • Nuxt

這個東西類似與React中的Next,做Vue服務端渲染在Nuxt確實挺方便的,整個目錄結構與Vue-Cli也差不多,但我覺得更清晰明瞭,而且有很豐富的配置,包括我最喜歡的頂部Loadding條啊、Layer主題模板啊、服務端渲染有益於SEO啊、自動生成Router啊等等等等。這裡我就不詳細展開了,選擇他主要是用習慣了,而且效能也很不錯。

  • Express

它就是一個Koa、egg等的一個服務端的工具,封裝很多便捷的方法。這裡也不詳細展開。

第一步 完成靜態頁面

  • 在這裡就不詳細說明HTML怎麼構建、Vue使用方法等等等不相關的問題,首先頁面效果如下圖:
    default
  • 點選確認領取後,向後端傳送請求,獲取券碼:
    1
  • 大致業務流程就是這樣子了。

第二步 基於webview完成token驗證

  • 甲方公司的token是怎麼給到使用者的呢?
    • 使用者登入客服端
    • 使用者在webview訪問相應的地址
    • 客戶端把token等資訊繫結在地址上讓服務端接受,並向服務端傳送GET請求
    • 服務端接受到Token後,根據Token資訊驗證使用者身份並返回頁面給使用者
  • 所以也就是相當於,此時我手上的Node需要完成一個Token驗證的需求,開搞:

這裡必須說一下Session這個東西,一開始當我完成了Token驗證的時候,可是發現兩個使用者同時訪問的時候,後訪問者會重新執行一次對應請求裡的方法,相當於很多資料都初始化甚至重新賦值。完全不知道怎麼把使用者分開,問了一下JAVA的同學,他們說框架自帶會分開,這就讓我很憂鬱了。其實,他們也知道Session這個東西,只是一直這樣用後習慣了也就突然說不清楚甚至想到它的存在了。
我一開始想到的是用Cookie驗證對應瀏覽器,但總覺得這種方法有點古老,不夠高大上(個人主觀看法,勿噴),儲存量也很有限。所以又探索了一天,得知有個Session這個東西可以驗證對應瀏覽器(好吧,其實也就是把Cookie當成資料索引)。知道了有這麼一回事之後也就茅塞頓開了。

// 引入一些工具
const http = require('http')
const express = require("express");
const session = require('express-session');

const nuxtapp = express(); // 建立一個express應用

// 設定SESSION配置
nuxtapp.use(session({
  secret: 'key' // 建議使用 128 個字元的隨機字串 
}));

// 處理OPTIONS請求(axios傳送POST請求時會先傳送一個OPTION請求驗證伺服器的連通情況)
nuxtapp.use(function (req, res, next) {
  if ('OPTIONS' === req.method) {
    res.sendStatus(200);
  } else {
    next();
  }
});

// 寫一個驗證Token的介面
nuxtapp.get('/getphone', (req, res) => {
    if (!req.query.token) {
      //  if else ...
      res.sendStatus(200)
      return;
    }
    // 這裡建立請求只是舉一個例子,有的Token可以本地解析,有的需要服務端向另一個服務端請求解析。(參考微信)
    const request = http.request({
      host: "api.example.com",
      headers: {
        'Content-Type': ' application/json',
        'Accept-Encoding': 'utf-8', //這裡設定返回的編碼方式 設定其他的會是亂碼
        'Accept-Language': 'zh-CN,zh;q=0.8',
        'Connection': 'keep-alive',
      },
      path: '/getTokenorSth',
      port: 'port',
      method: 'POST'
    }, response => {
      let data = ""; // 建立變數記錄資料
      response.on("data", function (chunk) {
        data += chunk
      })
      response.on("end", function () { // 設定seesion
        try {
          if (!req.session.id) {
            // set session like : req.session.id= JSON.parse(data)
          }
          res.sendStatus(200)
        } catch (err) {
          console.log(err);
          res.sendStatus(500)
        }
      })
    }).on('error', (e) => {
      console.log(`錯誤資訊: ${e.message}`);
      res.sendStatus(500)
    });
    // POST Data
    request.write(JSON.stringify({
        example:example,
        token: req.query.token
    })); // 使用者傳過來的資料 post
    request.end();
})

nuxtapp.listen(port || 80, '0.0.0.0')
console.log("已開啟伺服器,請訪問 —— localhost:" + port || 80)複製程式碼

第三步 服務端代理(這裡我也有個點不是很確定,所謂淘寶Node+JAVA是不是就是這種模式)

畢竟我還是個前端,功能方面的實現還是交給資深大JAVA吧(若是給我時間,我還真的想寫一下SQL複習一下)

  • 使用者訪問的時候還是向Node請求,這裡需要提一點的就是,假如後端提供了很多介面,你不一定每個都要寫一個app.get(‘/api’)或者什麼,express的文件上有提到類似這種寫法:
nuxtapp.all(["/api1/*","/api2/*"], requestFunction)複製程式碼

其他就跟上面token驗證差不多了

第四步 用Express執行Nuxt

  • 在Nuxt官網上其實也有部分程式碼教你如何用自己寫的Node去執行,但一直不是很完善,有點差強人意。我在這裡就補充一下我的理解,哪裡寫得不對,請儘管噴,謝謝噴我的每一個人
// nuxt
const {
  Nuxt,
  Builder
} = require('nuxt') // 引入核心構建屬性

// 判斷開發環境
const isProd = (process.env.NODE_ENV === 'production')
const port = process.env.PORT || 80

// 引入nuxt配置
const config = require('./nuxt.config.js')
config.dev = !isProd;
const nuxt = new Nuxt(config);

// 判斷生產模式 dev(開發者模式)表示重新構建 ;pro(生產模式)表示直接從yanr build的檔案直接執行
if (config.dev) {
  new Builder(nuxt).build()
    .then(listen)
    .catch((error) => {
      console.error(error)
      process.exit(1)
    })
} else {
  listen()
}複製程式碼

以上的listen就是我在第二、三步寫的相應介面的express伺服器啦。

  • 那麼nuxt其實還並沒有在程式碼中執行,new Nuxt一個Nuxt例項後返回一個nuxt方法,它其實是根據request,response去執行相應的渲染,其中我們要考慮到express()的各種介面的執行順序,假如一開始就匹配到了第二步的程式碼的get請求,那麼寫在第二步程式碼後的all方法中的各種介面是接收不到的。
  • 我考慮到的是介面不是無緣無故執行的,但使用者請求是必然發生的。那麼也就是當使用者除了故意傳送請求,全部由Nuxt接手。所以Nuxt會是放在最後讓其渲染頁面並交給使用者,為了方便驗證Token,我把驗證Token的請求放在首頁讓瀏覽器捕獲Token以及相應資訊後交給Node執行手動登陸。(其實也可以通過在nuxt渲染前判斷是否存在Token來決定是否進行token驗證,我就不在這裡再進行大量程式碼的展示了)
  • 結合以上思路,也就是在最後捕獲所有GET請求並交手給Nuxt即可:
// 最後捕獲nuxt渲染
nuxtapp.get('/*', (req, res) => {
  nuxt.render(req, res)
})複製程式碼

Demo:jasontan.cn
原文連結:github.com/A0150315/ja…

轉載請註明出處。


相關文章