【umi插件開發】控制檯二維碼

前言

在進行移動端webapp開發時,你是否會想要在真機上調試項目。 下面分析一下本地運行項目時,真機調試須要的步驟和麻煩的點。前端

  1. 你須要將手機和運行項目的電腦鏈接到同一局域網(鏈接同一個WiFi便可)。
  2. 查看電腦在局域網內的ip地址(windows在命令行輸入ipconfig)。
  3. 手機瀏覽器中輸入ip和端口打開項目。

然而局域網內的ip地址不是固定的,項目運行的端口也有可能因爲端口占用致使端口不固定,因此存書籤可能會失效,輸入長串的ip地址和端口會比較繁瑣,若是要在多臺手機調試兼容問題就更讓人生無可戀了。這天然就產生了需求:在運行項目時,在控制檯輸出二維碼,掃碼訪問項目地址。node

webpack插件

慣例,在造輪子以前去GitHub搜索一下有沒有已經造好的輪子。果真,我不是第一個有這種需求的人。 devserver-qrcode-webpack-plugin是一個基於webpack的插件。但我平時開發項目使用的umi腳手架,可是咱們都知道umi封裝的是webpack,因此webpack插件也是可使用的,那咱們就試試看行不行。webpack

umi使用chain-webpack自定義webpack配置,安裝插件後,在.umirc.js添加以下配置便可git

import qrcode from 'qrcode-webpack-plugin'

export default {
  chainWebpack(config, { webpack }) {
    config.plugin('qrcode')
      .use(qrcode)
  }
}
複製代碼

讓咱們運行試一下 github

umistart

沒有咱們想要的二維碼輸出,看來該插件並不兼容umi,緣由是什麼呢,咱們查看插件源碼web

apply(compiler) {
    const devServer = compiler.options.devServer

    if (!devServer) {
      console.warn('webpack-server-qrcode: needs to start webpack-dev-server')
      return
    }

    const protocol = devServer.https ? 'https' : 'http'
    const port = devServer.port
    const _ip = this.getIPAdress()[0]
    const url = `${protocol}://${_ip}:${port}`
    this.printQRcode(url)
  }
複製代碼

插件是從webpack的編譯器實例中的options中讀取DevServer的信息的,然而umiwebpackDevServer的啓動方式與直接使用webpack有很大的不一樣,因此compiler實例中並無DevServer的信息,因此該插件沒法正常使用。小程序

那麼,下面就正式開始造輪子之路吧!windows

先拆解問題,要實現咱們想要的效果,只須要重要的兩步:微信小程序

  1. 獲取項目運行的地址。
  2. 輸出包含ip地址和端口的二維碼。

獲取ip和端口

ip地址可使用node的內置模塊os模塊獲取,os模塊中的networkInterfaces方法能夠獲取設備網卡的相關信息,包括IP地址和mac地址等。api

// getIp.js
const os = require('os');

module.exports = () => {
  const interfaces = os.networkInterfaces();
  
  for (let interface of Object.values(interfaces)) {
    for(let items of interface) {
      if (items.family === 'IPv4' && !items.internal) {
        // TODO: 能夠完善的判斷條件,兼容多網卡和不一樣平臺設備
        return items.address;
      }
    }
  }
}
複製代碼

對於項目運行的端口,使用過umi的都知道,直接從配置中或者環境變量process.env.PORT中獲取是不許確的,由於umi有一套端口選擇機制,當指定的端口被佔用時,會自動選擇其餘的的端口運行。umi內部使用detect-port檢查端口,detect-port的原理很簡單,使用node內置net模塊嘗試監聽指定的端口,當端口被佔用時嘗試監聽其餘端口,在監聽成功後立刻取消監聽,並將端口號返回。

在外部沒有好的檢查方案,好在umi在今年5月的一個更新中,在afterDevServer事件中提供了devServerPort,這爲插件獲取端口號提供了簡便的接口,具體可查看issue#2386

插件中獲取port的基礎邏輯以下:

export default api => {
   api.afterDevServer(({ server, devServerPort }) => {
    console.log(devServerPort)
  });
}
複製代碼

控制檯輸出二維碼

控制檯輸出二維碼可使用qrcode-terminal,該庫的主要邏輯爲:根據字符串生成二維碼每一個位置的顏色信息二維數組。用字符'\u2588'表示縱向兩個白色,'\u2580'表示先白後黑,'\u2584'表示先黑後白,對於二維碼大圖,使用的是'\033[40m \033[0m''\033[47m \033[0m'。 想要了解細節的能夠去查看其源碼github

使用它輸出二維碼的代碼以下:

import qrcode from 'qrcode-terminal';

qrcode.generate(`http://${ip}:${port}`, { small });
複製代碼

umi-plugin-qrcode

整合上面兩步,umi-plugin-qrcode插件天然就成型了。獲取ip地址其實也不用本身寫,有許多js庫都有這個功能,實現思路都大同小異,而且考慮了其餘邊界狀況。

import address from 'address';
import qrcode from 'qrcode-terminal';

export default (api, { small = true, once = true } = {}) => {
  let port;
  let ip = address.ip();

  api.afterDevServer(({ server, devServerPort }) => {
    port = devServerPort;
  });

  api.onDevCompileDone(({ isFirstCompile }) => {
    once
      ? isFirstCompile && qrcode.generate(`http://${ip}:${port}`, { small })
      : qrcode.generate(`http://${ip}:${port}`, { small })
  })
}

複製代碼

umi中如何使用umi插件呢?(不是webpack插件)

  1. 安裝插件
yarn add umi-plugin-qrcode --dev
複製代碼
  1. .umirc.js中配置插件
// .umirc.js
export default {
  plugins: [
    ['umi-plugin-qrcode', {
      small: false, // 二維碼大小,默認small=true
      once: false // 第一次編譯完成輸出(默認)或者每次編譯完成輸出
    }]
  ]
}
複製代碼

因爲上文所說的緣由,插件支持的umi版本爲2.7.0+。 運行效果以下:

template

原文連接 歡迎 star & issue

做者簡介】:葉茂,蘆葦科技web前端開發工程師,表明做品:口紅挑戰網紅小遊戲、服務端渲染官網、微信小程序粒子系統。擅長網站建設、公衆號開發、微信小程序開發、小遊戲、公衆號開發,專一於前端領域框架、交互設計、圖像繪製、數據分析等研究。 一塊兒並肩做戰: yemao@talkmoney.cn 訪問 www.talkmoney.cn 瞭解更多。

相關文章
相關標籤/搜索