Taro Next Cli

—— 一个Taro 脚手架

前言

这段时间用Taro开发微信小程序,有了一些架构设计、适配、错误兼容等方案,每一次新开一个项目都要将之前的代码copy一份并重新配置,这个过程是机械且繁琐的,所以想构建一个脚手架来帮我们快速进行配置。

除此之外,还希望能讲Layout(布局组件)、LayoutHeader(自定义头部导航栏)、LayoutTabbar(自定义底部导航栏)、DragList(下拉刷新下拉加载)优化后单独拎成UI组件库,将此UI组件库完善并集成到脚手架中。让用脚手架创建的项目做到“只关心业务”的能力。

正文

Flag

本次的脚手架需要做的事:

完成 ———> 未开始

🌝🌖🌗🌘🌑

  1. 配置阶段
    • 项目信息基本配置 🌝
    • css扩展语言选择 🌑
    • 项目模板选择 🌓
  2. 开发阶段
    • 本地mock server 🌑
    • 代码热更新
  3. 测试阶段
    • 执行测试脚本 🌑
    • 生成测试报告 🌑
  4. 部署阶段
    • 自动化部署

配合本次脚手架构建要做的事:

  1. Taro3.x 架构设计
  2. Taro2.x 组件升级到Taro3.x并优化
  3. npm发布

脚手架

本节仅以简单的构建流程为例,大家可以以此入门

主流程

1
配置脚手架入口 => 配置“创建项目”命令 => 人机交互设置项目基本配置 => 拉取相关基础项目 => 更新package.json => 安装相关依赖
1
2
3
4
5
6
7
8
9
10
11
// 项目文件结构
├── bin
| └── cli.js 脚手架入口文件
├── lib
| ├── download.js 项目下载相关操作
| ├── exec.js 进程执行相关操作
| ├── file.js 文件相关操作
| ├── install.js 安装相关操作
| └── utils.js 工具包
├── package.json
└── README.md

配置脚手架入口

1
2
3
4
5
6
7
// package.json
{
"bin": {
"biu": "./bin/cli.js"
},
...
}

配置 “创建项目” 命令

这里要借助commander.js

1
2
3
4
5
// cli.js
const program = require("commander");
// command注册命令
program.command("init <projectName>")./* 中间操作 */.action();
// 当在命令行中输入 biu init myapp 便会执行相关命令,并将 "myapp" 赋值给projectName

人机交互设置项目基本配置

这里要借助 inquirer.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// cli.js
const program = require("commander");

const QUESTIONS = [
{
type: "input",
name: "author",
message: "请输入作者的名称:",
},
{
type: "list",
name: "style",
message: "样式预处理语言:",
choices: [
{ name: "scss", value: 1 },
{ name: "less", value: 2 },
],
},
{
type: "confirm",
name: "isOk",
message: "请确认输入是否ok?",
},
]
program.command("init <projectName>")./* 中间操作 */.action(() => {
inquirer.prompt(QUESTIONS).then(({author,style,isOk})=>{
// 再次做出相应操作

// 1.拉取相关基础项目
// 2.更新package.json
// 3.安装依赖
console.log(author,style,isOk);
})
});

拉取相关基础项目

这里要借助 download-git-repo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// download.js
const { promisify } = require("util");

/**
* 从git仓库上下载项目到本地
* @param {String} repo git仓库地址
* @param {String} desc 本地的路径
*/
const clone = function (repo, desc) {
const download = promisify(require("download-git-repo"));
download(repo, desc);
};

module.exports = {
clone
};
1
2
3
4
// cli.js
await clone("github.com:Howlcn1997/taro-next-base", projectName);

// 注意这里仓库的地址要去除 git@ 或 http://

更新package.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// file.js
const fs = require("fs-extra");

/**
* 更新文件内容.
* @param {String} filePath
* @param {Object} contents
*/
const updateFile = (filePath, contents) => {
if (fs.existsSync(filePath)) {
const fileContent = Object.assign({}, require(filePath), contents);
fs.writeJSONSync(filePath, fileContent, { spaces: "\t" });
} else {
throw new Error(`无法找到此路径: ${filePath}`);
}
};

module.exports = {
updateFile
};
1
2
3
4
5
6
7
// cli.js
updateFile(packageJson, {
name: projectName,
author,
version: version,
description: description,
});

安装相关依赖

这里要借助 which.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// exec.js
const childProcess = require("child_process");

/**
* 开启子进程来执行命令
* @param {String} cmd 待执行的命令
* @param {Array} args 命令执行时的参数.
* @param {Function} fn 执行完成时的回调.
*/
function exec(cmd, args = [], cb) {
const runner = childProcess.spawn(cmd, args, {
stdio: "inherit",
});

runner.on("close", function (code) {
cb && cb(code);
});
}

module.exports = {
exec,
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// utils.js
const which = require("which");
/**
* 查找系统中用于安装依赖包的命令
*/
function findNpm() {
const npms = ["tnpm", "cnpm", "npm"];
for (let i = 0; i < npms.length; i++) {
try {
// 查找环境变量下指定的可执行文件的第一个实例
which.sync(npms[i]);
return npms[i];
} catch (e) {}
}
throw new Error("请先安装 npm");
}

module.exports = {
findNpm,
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// install.js
const which = require("which");
const { exec } = require("./exec");
const { findNpm } = require("./utils");

/**
* 执行npm install命令, 安装项目依赖.
*/
const install = (cb) => {
const npm = findNpm();
console.log("开始安装依赖...");
exec(which.sync(npm), ["install"], function () {
console.log("安装成功!");
cb && cb();
});
};

module.exports = {
install,
};
1
2
3
4
5
6
7
// cli.js

// 将node工作目录更改成构建的项目根目录下
const projectPath = path.resolve(projectName);
process.chdir(projectPath);
// 执行安装命令
install();

验证

1
2
3
// 命令行
npm link
biu init demo

额外的库

1
2
ora.js  // 控制台加载动画
chalk.js // 控制台打印美化

基础模板项目

项目文件结构

1
2
3
4
5
6
7
8
9
10
11
12
13
├── config                 配置目录
| ├── dev.js 开发时配置
| ├── index.js 默认配置
| └── prod.js 打包时配置
├── src 源码目录
| ├── pages 页面文件目录
| | └── index index 页面目录
| | ├── index.js index 页面逻辑
| | └── index.css index 页面样式
| ├── styles 公共通用样式
| ├── app.css 项目总通用样式
| └── app.js 项目入口文件
└── package.json

关于 Layout等组件、session缓存、初始页面分发方案不在此赘述

Taro2.x 升级

从旧版本迁移到 Taro Next

注意:若不使用了Nervjs,就不要引入

npm发布脚手架

  1. 先注册一个npm账号并登录

  2. 去除脚手架项目中多余的依赖配置

  3. 确认package.json中name在npm中无重名

    1
    简单方法:打开npm,直接搜索此name,若无结果,则无重名
  4. 写好readme.md

  5. 切换源至npm

    1
    2
    nrm ls // 查看所有源
    nrm use 源名 // 切换源
  6. 登录

    1
    npm login
  7. 发布

    1
    npm publish
  8. 测试

    1
    2
    3
    4
    5
    6
    7
    npm i taro-next-cli -g
    ----------------------
    biu init firstDemo
    ----------------------
    cd firstDemo
    ----------------------
    npm run dev:weapp

后期

暂时只是有一些基础功能

模板也只有一套,组件还没抽离成单独的包,还有若干需要优化的点。Nodejs暂时还没系统性学习。暂时的应急版本只是相应业务上的需求。之后会持续将集成方案补全到基础项目中。

最后更新: 2020年08月25日 00:20

原始链接: https://HowlCN1997.github.io/2020/08/15/Taro Next Cli/

× 请我吃糖~
打赏二维码