Photo by Lee Campbell on Unsplash

Technology stack & Tools

The effect of the project: http://47.92.228.193:8990/

The front end

  • Vue.js

The back-end

  • Express
  • PM2

tool

  • Nodejs
  • VScode
  • Map JSSDK

The development of preparation

  • One Linux server (centos)
  • Set up based onnodejsServer environment
    1. usenvmmanagementnodejsEnvironment (curl – o -Raw.githubusercontent.com/nvm-sh/nvm/… | bash)
    2. The installationpm2Used fornodejsProcess management of programs (NPM i-g pm2)
  • Set up based onVueFront-end environment
    1. use@vue/cliNPM install -g@vue /cli
    2. [Optional] Use Travis + Github Action for project CI management

function

  • Get location information accurate to the city level
  • Visual display of location information map

The source code parsing

Back-end core logic

The source IP is obtained based on the request obtained by Express, and the location information is obtained by invoking a third-party API

app.get('/api/loc'.(req, res) = > {
  let ip = req.ip || req.ips[0]
  if (ip.indexOf(":") > -1) {
    ip = ip.split(':') [3]}if (ip) {
    const url = `http://api.ipapi.com/${ip}? access_key=xxx`
    http.get(url, httpRes= > {
      let chunkData = ' ';
      httpRes.on('data'.chunk= > {
        chunkData += chunk;
      })
      httpRes.on('end'.() = > {
        const jsonObj = JSON.parse(chunkData)
        res.status(200)
        res.json({
          errno: 0.data: jsonObj
        })
      })
    })
  } else {
    res.status(400)
    res.json({
      errno: 400.errmsg: 'No IP obtained'})}})Copy the code

Front-end core logic

Interface request and data processing

getLoc() {
  let url = ` / /${account.api}/api/loc`;
  axios
    .get(url)
    .then(res= > res.data)
    .then(res= > {
      if (+res.errno === 0) {
        const obj = res.data;
        if (obj.latitude) {
          this.lat = obj.latitude * 1
          this.lng = obj.longitude * 1
        }
        this.rows = Object.keys(obj)
          .filter(key= > Object.keys(this.dataMap).includes(key))
          .map(key= > {
            return key === 'location' ? {
              label: 'flag'.value: obj[key]['country_flag_emoji'}, {label: this.dataMap[key],
              value: obj[key] }; }); }}); },Copy the code

Map SDK loading

function baiduMap(ak) {
  return new Promise((resolve, reject) = > {
    window.baiduMap = function() {
      resolve()
    }
    let script = document.createElement('script')
    script.type = 'text/javascript'
    script.src = ` http://api.map.baidu.com/api?type=webgl&v=3.0&ak=${ak}&callback=baiduMap`
    script.onerror = reject
    document.head.appendChild(script)
  })
}
Copy the code

Map component

<template>
  <div class="map-wrap">
    <div id='container'></div>
  </div>
</template>
<script>
import { baiduMap } from ".. /.. /common/js/utils";
import { account } from ".. /.. /.. /account";
export default {
  props: {
    lat: Number.lng: Number
  },
  data() {
    return {
      ak: account.ak,
      zoomSize: 16.map: null.clickedAddr: ""
    };
  },
  watch: {
    lat() {
      this.renderMap(); }},mounted() {
    if (this.lat && window.BMapGL) {
      this.initMap(); }},methods: {
    renderMap() {
      const that = this;
      this.$nextTick(() = > {
        baiduMap(this.ak).then(() = > {
          that.initMap();
        });
      });
    },
    initMap() {
      const map = new BMapGL.Map("container");
      this.locationByLatLng(map);
      this.commonSet(map);
      this.showLoactionControl(map);
      this.observeMapClick(map);
      this.getAddress();
      this.locationByBrowser(map);
      this.locateByOriginBrowser(); }}};</script>
<style lang="scss" scoped>
.map-wrap {
  margin: 20px;
  position: relative;
}
#container {
  height: 300px;
}
</style>
Copy the code

Engineering infrastructure

vConsole

Load the vConsole implicitly, invoking the vConsole panel with a hotkey

clickTitle() {
  this.clickCount = this.clickCount + 1
  if (this.clickCount === 5) {
    if (!this.consoleShow) {
      this.consoleShow = true
      this.showVConsole()
    }
  }
  setTimeout(() = > {
    this.clickCount = 0
  }, 2000)}Copy the code

PM2

When the back-end service is started, the –time parameter is added to add the log time

Use pM2 logs to view back-end service logs

Project deployment

The back-end service

pm2 start api.js --name me
Copy the code

The front-end service

npm run build
Copy the code

Drag dist to the server machine that vscode remote accesses

architecture

Server fixed single port Deployed front-end service and back-end service for different routes

The front-end service

app.use(express.static(path.join(__dirname, '.. /dist')))
app.get('/'.(req, res) = > {
  res.sendFile(path.join(__dirname, '.. /dist/'.'index.html'))})Copy the code

The back-end service

app.get('/api/loc'.(req, res) = > {
  res.status(400)
  res.json({
    errno: 200.data: {}})}Copy the code