Skip to content

miniapp-upload 小程序本地上传发布工具

小程序开发会经历几个阶段:

  • 本地开发
  • 上传开发版(设置体验版)测试
  • 提交审核
  • 发布

本文档主要聚焦在第二步: 上传代码。众所周知。小程序上传代码可以通过微信开发者工具(以下简称开发工具)中的上传功能将代码上传至微信公众平台中。大部分时候这完全没问题。那么本篇文章到此为止(才怪)。

有些经验的开发者会发现这种模式有那么一丢丢问题。就是每次上传都需要打开微信开发者工具(好像没什么问题?)
那如果现在有一种方式。我的构建上传并不需要打开微信开发者工具。只需要通过命令行发布呢?

没错。微信官方通过开发工具提供了一个CLI工具来实现这个。

前置条件

在使用这个特性前。你需要自查一下本机环境

  • 安装微信开发者工具,并完成扫码登录

  • 微信开发者工具开启端口。【开发工具】-【设置】-【安全设置】-【服务端口】 E0565E820D2B

  • [可选]如果你是Windows用户.在项目根目录创建pub-weapp.config.private.json,并填入cli路径

    bash
    { 
    "windowsWeiXinCliPath": "C:\\Program Files (x86)\\Tencent\\微信web开发者工具\\cli.bat" 
    }

    注意:这里填写你电脑上实际的工具位置

添加命令配置

添加依赖

bash
pnpm add -wD inquirer@^8.0.0 shelljs@^0.8.5

在项目根目录packages.json中。新建打包命令

json
"scripts": {
    // 其他命令...
    "mini:uat": "node scripts/pub-weapp --target uat",
    "mini:prd": "node scripts/pub-weapp --target prd",
  },

在项目根目录创建上传脚本scripts/pub-weapp.js

输入以下命令

js
const os = require('os')
const path = require('path')
const fs = require('fs')
const shelljs = require('shelljs')
// const chalk = require('chalk')
const inquirer = require('inquirer')
const argv = require('minimist')(process.argv.slice(2))

const target = argv.target || 'uat'
const isMac = os.type() === 'Darwin'
const isWindows = os.type() === 'Windows_NT'
const isSupportSystem = isMac || isWindows

const configFileName = 'pub-weapp.config.private.json'

const uploadVersion = {
  uat: argv.v || '1.0.0',
  stg: argv.v || '1.0.0',
  prd: argv.v
}[target]

const packageOptions = [
  {
    name: 'taro-shop-component',
  },

]

const chalk = {
  red: (text = '') => `\x1B[31m${text}\x1B[0m`,
  green: (text = '') => `\x1B[32m${text}\x1B[0m`,
  yellow: (text = '') => `\x1B[33m${text}\x1B[0m`
}

// 配置文件不存在则手动创建
if (isWindows && !fs.existsSync(path.join(__dirname, '../', configFileName))) {
  console.log(
    ` ${chalk.yellow(
      '警告'
    )}: 由于 Windows 首次使用发布命令,将为您创建配置文件,请在工程根目录 ${configFileName} 中填入您的【微信开发工具安装路径】,填写完成后再重新执行命令即可`
  )
  fs.writeFileSync(path.join(__dirname, '../', configFileName), `{ "windowsWeiXinCliPath": "这是示例示例    D:/软件/微信web开发者工具/cli.bat" }`)
  return
}

inquirer
  .prompt([
    {
      type: 'checkbox',
      message: `即将打包 ${target} 环境,回车选择 package`,
      name: 'packageNameList',
      choices: packageOptions.map((item) => item.name)
    }
  ])
  .then(
    ({
      /** 本次打包的 包名 */
      packageNameList
    }) => {
      const successList = []
      const failList = []

      packageNameList.forEach((packageName) => {
        const option = packageOptions.find((item) => item.name === packageName)

        run(packageName, option, () => {
          successList.push(packageName)
        })
      })

      // 全部发布完成后,检查哪些没发布成功
      packageNameList.forEach((packageName) => {
        const isSuccess = successList.indexOf(packageName) !== -1
        !isSuccess && failList.push(packageName)
      })

      console.log(' ')
      console.log(' ')
      console.log(` ${chalk.green('批量发布完成')}: ${new Date().toLocaleTimeString()}`)
      console.log(` 发布:${packageNameList.length} ${packageNameList.join('、')}`)
      console.log(` 成功:${chalk.green(successList.length)} ${successList.join('、')}`)
      console.log(` 失败:${chalk.red(failList.length)} ${failList.join('、')}`)

      function run(packageName = '', option = {}, onSuccessCallback) {
        /** 小程序包目录 */
        const weappDir = `packages/${packageName}`

        /** 打包命令 */
        const buildCmd = `pnpm build:${target}:weapp`

        /** 用于发布的 打包输出目录 */
        // const outputDir = projectConfigJson.miniprogramRoot.replace(/\//g, '')
        const pubDir = 'dist/weapp'
        const pubFullDir = path.join(process.cwd(), 'packages', packageName, pubDir)

        // 自定义命令语句
        if (option.cmd) {
          shelljs.exec(option.cmd, { cwd: process.cwd() })

          onSuccessCallback()

          return
        }

        /** 微信开发工具命令行所在路径 */
        let cli = ''

        if (isMac) {
          cli = '/Applications/wechatwebdevtools.app/Contents/MacOS/cli'
        } else {
          const pubWeappConfig = require('../pub-weapp.config.private.json')
          cli = validateWeiXinCliPath(pubWeappConfig.windowsWeiXinCliPath)
        }

        if (!isSupportSystem) {
          return console.log(`${chalk.red('【错误】')} 该命令仅支持 Mac 与 Windows 使用,不支持 ${os.type()}`)
        }

        if (!cli) {
          return console.log(`${chalk.red('【错误】')} 请根据 docs/开始.md 在根目录配置 ${scriptConfigFileName} 文件,或检查配置文件中指向的 cli 文件是否存在`)
        }

        if (target === 'prod' && !uploadVersion) {
          return console.log(`${chalk.red('【错误】')} 生产环境,请输入版本号参数 【--v=x.x.x】`)
        }

        shelljs.exec(buildCmd, {
          cwd: path.join(process.cwd(), weappDir)
        })

        console.log(' ')
        console.log(' ')
        console.log(` ${chalk.green('打包完成,开始上传')}`)
        console.log(' ')

        console.log(' ')
        console.log(` 发布参数 ====================================================`)
        console.log(' ')
        console.log(` ${chalk.green('cli')}: ${cli}`)
        console.log(` ${chalk.green('发布源文件')}: ${pubFullDir}`)
        console.log(` ${chalk.green('uploadVersion')}: ${uploadVersion}`)
        console.log(` ${chalk.green('desc')}: ${target}`)
        console.log(' ')

        cliLogin(cli)

        shellExec(cli, `upload --project ${pubFullDir} -v ${uploadVersion} -d '${target}'`)

        console.log(` ${chalk.green('发布完成')}: ${packageName} ${new Date().toLocaleTimeString()}`)

        onSuccessCallback()
      }
    }
  )

/** 校验微信开发者工具安装路径 */
function validateWeiXinCliPath(cliPath = '') {
  if (!cliPath) {
    throw Error('请在项目根目录 package.json [windowsWeiXinCliPath] 填入你的 windows 电脑【微信开发者工具】的完整安装路径')
  }

  const exist = fs.existsSync(cliPath)

  if (!exist) {
    throw Error(`${cliPath} 文件不存在`)
  }

  if (!/cli\.bat/.test(cliPath)) {
    throw Error('weiXinCliPath 字段不合法,应为 <完整安装路径>/cli.bat')
  }

  return cliPath
}

function cliLogin(cli) {
  try {
    // 修复文件夹包含中文
    if (isWindows) {
      shelljs.exec(`chcp 65001`)
    }

    const res = shellExec(cli, 'islogin').stdout
    const isLogin = JSON.parse(res).login

    if (!isLogin) {
      console.log(` ${chalk.yellow('警告')}: 尚未登录微信开发工具,请扫码登录`)
      shellExec(cli, 'login')
    }
  } catch (error) {
    console.log(` ${chalk.red('警告')}: 登录微信开发工具失败,请打开新的微信开发工具登录后重试,或联系发布脚本的开发人员`)
    console.error(error)
    process.exit(1)
  }
}

function shellExec(cliPath, command) {
  const innerCommand = isWindows ? `cli.bat ${command}` : `${cliPath} ${command}`
  return shelljs.exec(
    innerCommand,
    isWindows
      ? {
        cwd: path.dirname(cliPath)
      }
      : {}
  )
}

打包上传

运行打包命令. 会执行上传操作。

bash
pnpm mini:prd

如果配置成功。会执行成功。如果失败。请查看具体报错信息。或联系架构部解决