Debian 9 配置 vue 开发环境

最近开始捡起来前端 vue 的开发,这里记录一下环境搭建的过程。

安装nodejs

官网教程 适用于大部分场景了。在这里我安装当前最新的LTS版 v14.x,两个命令即可:

curl -sL https://deb.nodesource.com/setup_14.x | bash -
apt-get install -y nodejs

很不幸,在我的机器上出现了下面的错误:

The AppStream system cache was updated, but some errors were detected, which might lead to missing metadata.

image-20201125122253041

实际上我也没有头绪。随意敲了几个命令,upgrade 了几个包解决了,具体原因还是不清楚:

apt-get update
apt-get upgrade
apt autoremove

image-20201125122823911

确认版本:

node -v
npm -v

image-20201125130514125

nodejs配置

使用阿里的镜像源

npm install -g cnpm --registry=https://registry.npm.taobao.org

在 .zshrc 或 .bashrc 中添加新命令

alias cnpm="npm --registry=https://registry.npm.taobao.org \
--cache=$HOME/.npm/.cache/cnpm \
--disturl=https://npm.taobao.org/dist \
--userconfig=$HOME/.cnpmrc"

安装vue-cli

npm install -g @vue/cli

查看版本:

vue --version

@vue/cli 4.5.9

很遗憾,在这里我也遇到了问题。

大概可以看出来系统已经安装过了vue,而且是 2.x 版本的vue。在这里先进行卸载。

npm ERR! EEXIST: file already exists, symlink '../lib/node_modules/@vue/cli/bin/vue.js' -> '/usr/bin/vue'

image-20201125132803736

卸载:

npm uninstall -g vue-cli

创建demo应用

由于目前vue已经到3的版本了,3也兼容2的版本。所以这里我就直接使用 vue3 做测试了。

vue create kelu

会弹出相关的交互式问题,下面是我做的选项,把 vuex router都安排上了。

image-20201125135011676

运行

npm run serve

从原有代码中运行

npm install
npm run serve

一个简单的 gin websocket 例子

这个例子是我在开发时候写的测试demo,框架基于 Gin。

基本功能非常简单:

  • 当客户端连接上的时候,发送一个自定义的id,

  • 当收到客户端的json信息时,基于不同的返回码,打印日志。

代码包含两个文件,一个是ws的通用文件ws.go,一个是逻辑处理文件kelu.go,在这里做个记录。

依赖包

github.com/gin-gonic/gin
github.com/gorilla/websocket

ws.go


package ws

import (
  "github.com/gorilla/websocket"
  "net/http"
  "github.com/gin-gonic/gin"
  "fmt"
  "github.com/kelu.org/base/pkg/app"
)

// WebSocket 更新用
var keluWsUpgrader = websocket.Upgrader{
  ReadBufferSize:  1024,
  WriteBufferSize: 1024,
  CheckOrigin:     checkOrigin,
}

func checkOrigin(r *http.Request) bool {
  return true
}

// 路由入口
func ApiWs(c *gin.Context) {
  ws, err := keluWsUpgrader.Upgrade(c.Writer, c.Request, nil)
  if err != nil {
    return
  }

  wsid, err := KeluWsOpen(ws)
  fmt.Println("kelu open socket: ",wsid)
  if err != nil {
    return
  }

  defer ws.Close()

  for {
    //读取ws中的数据
    receivedData := app.Response{}

    // メッセージ読み込み
    err = ws.ReadJSON(&receivedData)
    if err != nil {
      fmt.Printf("KeluWs reading ws error: %v", err)
      break
    }

    switch receivedData.Code {
    case http.StatusAccepted:
      // some code ... ...
      break;
    case http.StatusOK:
      // some code ... ...
      break;

    default:
      ws.WriteJSON(KeluWsBad(wsid,receivedData.Data))
    }

  }

  KeluWsDone(wsid)
  return
}

kelu.go

func KeluWsOpen(ws *websocket.Conn) (int64, error) {
  wsid := time.Now().UnixNano()
  welcome := app.Response{http.StatusAccepted, "ok", "ok", map[string]interface{}{"wsid": wsid}}
  err := ws.WriteJSON(welcome)
  if err != nil {
    fmt.Printf("open websocket error while writing message to client: %v", err)
    ws.Close()
    return 0, err
  }

  return wsid, nil
}

func KeluWsBad(wsid int64, data interface{}) *app.Response {
  resultData := app.Response{http.StatusBadRequest, strconv.FormatInt(wsid, 10), "", data}
  return &resultData
}

func KeluWsDone(wsid int64){
  // some code ... ...
}

golang jwt 解析过期信息

golang 下解析 jwt 信息,基本上都用的这个包. https://github.com/dgrijalva/jwt-go

官方的 GitHub 案例,也提供了简单的解析方法:

import "github.com/dgrijalva/jwt-go"

func ParseToken(token string) (*Claims, error) {
  tokenClaims, err := jwt.ParseWithClaims(token, &Claims{}, func(token *jwt.Token) (interface{}, error) {
    return jwtSecret, nil
  })

  if tokenClaims != nil {
    if claims, ok := tokenClaims.Claims.(*Claims); ok && tokenClaims.Valid {
      return claims, nil
    }
  }

  return nil, err
}

ParseWithClaims方 法里会对token做验证,只有验证通过的才会进行后续的逻辑。

但对于已经过期的信息,验证显然是不能通过的,使用这个方法会抛出 get claim is nil 的错误。这时候应该使用 ParseUnverified 方法 跳过验证.

func GetUsernameFromToken(cookie string) (string, error) {
  token, _, err := new(jwt.Parser).ParseUnverified(cookie, jwt.MapClaims{})
  if err != nil {
    return "", err
  }

  if claims, ok := token.Claims.(jwt.MapClaims); ok {
    jwtToken := KeluJwtToken{}
    tmp, err := json.Marshal(claims)
    if err != nil {
      return "", err
    }

    err = json.Unmarshal(tmp, &jwtToken)
    if err != nil {
      return "", err
    }
    return jwtToken.Username, nil
  }

  return "", errors.New("cannot parase cookie")
}

参考资料


golang 解析 map[string]interface{} 和 json 到 struct

从 json 转成 strcut 可以算是go开发中的常事了。这里记录两个窍门。

通过 json 自动生成 struct 声明

一般来说如果只有三四个字段,还是比较轻松的,如果有50个以上的字段,光是定义结构体,都要累死一拨人了~

这时候这个网站 https://app.quicktype.io/ 真是个神器一般的存在,可以根据 json 定义go struct。

image-20201215165155521

猜测json的内部数据类型

进行开发,解析json数据时,我先写了以下的测试代码,用于判断数据的格式。不得不说,强类型的语言就是有这种不方便。

同时要注意下面几个事项:

  • 解析出来的 int 类型会变成 float64 类型
  • 要注意和前端的交互,某些情形下前端解析 int64 会有精度问题,如果涉及前端的交互,尽量避免使用int64,或先转成string再与前端交互。
func GuessType(k string, v interface{})  {
  switch value := v.(type) {
  case nil:
    fmt.Println(k, "is nil", "null")
  case string:
    fmt.Println(k, "is string", value)
  case int:
    fmt.Println(k, "is int", value)
  case float64:
    fmt.Println(k, "is float64", value)
  case []interface{}:
    fmt.Println(k, "is an array:")
    for i, u := range value {
      fmt.Println(i, u)
    }
  case map[string]interface{}:
    fmt.Println(k, "is an map:")
  default:
    fmt.Println(k, "is unknown type", fmt.Sprintf("%T", v))
  }

}

func GuessTypeFromMapStringInterface(m map[string]interface{}){
  for k, v := range m {
    GuessType(k,v)
  }
}

将 map[string]interface{} 和 json 转成struct

由上一个步骤接着往下走,使用 encoding/json 库中的格式化命令,先将 json 格式化,再反格式化成 struct:

import "encoding/json"

  tmpJson, err := json.Marshal(data)
  if err != nil {
    return nil, err
  }
  create := KeluTest{}
  json.Unmarshal(tmpJson, &create)

参考资料