返回顶部
首页 > 资讯 > 前端开发 > JavaScript >Node CLI如何构建微信小程序脚手架
  • 746
分享到

Node CLI如何构建微信小程序脚手架

2024-04-02 19:04:59 746人浏览 八月长安
摘要

这篇文章将为大家详细讲解有关node CLI如何构建微信小程序脚手架,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。具体如下:  目的由于目前公司的 T

这篇文章将为大家详细讲解有关node CLI如何构建微信小程序脚手架,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

具体如下:

Node CLI如何构建微信小程序脚手架 

Node CLI如何构建微信小程序脚手架 

目的

由于目前公司的 TOC 产品只要是微信小程序,而且随着业务的扩展, 会有更多的需求,创建更多的小程序,为了让团队避免每次开发前花费大量时间做比如工程化的一些配置,以及保持每个项目的一致性, 所以决定做一个 Node CLI 来创建微信小程序脚手架

  • 节省开发前期的大量时间,新项目可以很快开始业务开发

  • 保证项目统一性,有利于团队间的协作及工程化

  • 提升团队基建意识,从枯燥无味的业务开发中脱离出来,尝试新的东西,即使很基础很简单

小程序选型

小程序的第三方框架有很多, 我接触过的就有 taro / wepy / mpVue ,并且都有对应上线的项目。 在尝试这些框架的过程中,对比原生小程序,有一些感想想分享出来:

  • 第三方框架语法贴近vue/React, 开发者可以根据自己的特点选择框架,学习成本相对较低

  • 原生框架在CSS预处理,多端复用,状态管理,自动构建这几块能力对比其他框架是欠缺的

  • 第三方框架额外的工具包会使打包体积变大,每次构建花费时间,同时性能不如原生

  • 第三方框架更新迭代很快,比如wepy@1.x/wepy@2, 导致旧项目的更新问题

  • 小程序的特性更新迭代速度较快, 第三方框架会相对滞后

综上所述,由于我们目前没有多端复用的要求,并且有的小程序相对简单,需要很短时间内开发完成, 最重要的是,其他的框架我都试过了,原生的还没写过,一个字,新鲜感!!:smile: ,所以最终当仁不让地选择了原生小程序,不得不说,原生大法就是妙啊! :clap::clap::clap::clap:

大体思路

这个功能是相对很基础的,但是作为一个每天搬砖的业务仔来说,是个艰难的过程,也是个很好的学习机会。

在做之前,想找找个社区比较:ox::beer:的学习(抄)一下,短暂考虑后,果断选择 taro-cli , 然后火速打开源码,一顿操作(完全蒙圈),学习了一点之后,才开始上手

这个具体的实现思路我想到两个

  • git clone 远程仓库作为模版下载到本地,再根据用户输入配置修改 .JSON 文件(比如 appId )

  • template 就放在当前目录中,直接`copy``, 之后的事等同

权衡之后,打算使用 lerna 作为管理工具, 其中模版也作为一个 npm 包 ,用到的时候去 npm 下载,这么做我是为了方便管理,统一 push / publish , 就是为了省事 :smile:。

最终思路:

暴露命令 —> 用户交互输入配置 -> 集合配置下载模版 -> 根据配置修改 .json -> git init + 安装依赖

开发 Node CLI

Lerna 项目搭建

知道 monorepo 的同学不需要我多说,其实就是把代码放在一个仓库里,结果包之间回想以来,发布繁琐等问题, 这里我们就用到了 lerna 这个神器帮助我们做包的统一管理

// 创建项目
mkdir modoo-mini-program
cd modoo-mini-program

// 初始化
lerna init

cd packages
mkdir modoo-script
mkdir modoo-template-mini
mkdir modoo-mini // 安装 modoo-script 依赖用于测试,无其他实际用处

lerna bootstrap // 安装依赖 + npm link

安装依赖

为了实现功能,我们需要安装一些依赖包

  • commander 命令行工具,用于读取命令参数,作对应操作

  • node-fs-extra 在 node.js 的 fs 基础上增加了一些新的方法,更好用,还可以拷贝模板。

  • chalk 可以用于控制终端输出字符串的样式, 调整颜色啥的

  • inquirer 用户命令行交互,获取用户的交互配置数据,就像个提问板

  • ora 实现加载中的状态是一个 Loading 加前面转起来的小圈圈,成功了是一个 Success 加前面一个小钩钩。

  • log-symbols 日志彩色符号,用来显示√ 或 × 等的图标

获取命令

首先第一步,要在用户全局安装之后,暴露出命令接口,需要在 packages.json 文件中加入如下内容

"bin": {
  "modoo-script": "./bin/modoo-script.js"
},

之后在根目录下创建 bin 文件夹 + bin/modoo-script.js

#!/usr/bin/env node
const { program } = require("commander");

program
 .version(require("../package").version) // modoo-script --version
 .usage("<command> [options]")
 // init 命令,床架项目
 .command("init [projectName]", "Init a project with default templete")
 .parse(process.argv); // 解析命令参数

然后需要注意的是, commander 支持 Git 风格的子命令处理,可以根据子命令自动引导到以特定格式命名的命令执行文件,文件名的格式是 [command]-[subcommand] ,例如:

modoo-script init => modoo-script-init
modoo-script build => modoo-script-build

所以为了实现 init 命令,可以直接在 bin 文件目录下添加 modoo-script-init.js

#!/usr/bin/env node

const { program } = require("commander");

program
 .option("--name [name]", "项目名称")
 .option("--description [description]", "项目介绍")
 .option("--framework", "脚手架框架")
 .parse(process.argv);

const args = program.args;
// 获取命令参数
const { name, description, framework } = program;

const projectName = args[0] || name;

......

用户交互

获取了命令参数后,根据参数转到用户交互界面,这里使用的是 inquirer 来处理命令行交互, 用法很简单

const inquirer = require('inquirer')

if (typeof conf.description !== 'string') {
   prompts.push({
    type: 'input',
    name: 'description',
    message: '请输入项目介绍!'
   })
}

......

inquirer.prompt(prompts).then(answers => {
  // 整合配置
  this.conf = Object.assign(this.conf, answers);
})

远程模块

这里较为折腾,一开始说了,我把模版作为 npm包 ,具体查找,下载的过程如下

  • npm search 查找相应的模版 npm 包

  • 在用户选择框架后对应所需的包,获取它的详细信息,主要是 tarball

  • 用户输入完后,下载 tarball 到项目目录,并修改 .json 文件配置

部分代码如图所示

// 一 npm search 查找相应的模版 npm 包
const { execSync } = require("child_process");

module.exports = () => {
 let list = [];
 try {
  const listJSON = execSync(
   "npm search --json --reGIStry Http://registry.npmjs.org/ @modoo/modoo-template"
  );
  list = JSON.parse(listJSON);
 } catch (error) {}

 return Promise.resolve(list);
};
// 二 返回 npm 数据
const pkg = require("package-json");
const chalk = require("chalk");
const logSymbols = require("log-symbols");

exports.getBoilerplateMeta = framework => {
 log(
  logSymbols.info,
  chalk.cyan(`您已选择 ${framework} 远程模版, 正在查询该模版...`)
 );

 return pkg(framework, {
  fullMetadata: true
 }).then(metadata => {
  const {
   dist: { tarball },
   version,
   name,
   keyWords
  } = metadata;
  log(
   logSymbols.success,
   chalk.green(`已为您找到 ${framework} 远程模版, 请输入配置信息`)
  );

  return {
   tarball,
   version,
   keywords,
   name
  };
 });
};
// 三 下载 npm 包
const Got = require("got");
const tar = require("tar");
const ora = require("ora");

const spinner = ora(
  chalk.cyan(`正在下载 ${framework} 远程模板仓库...`)
).start();

const stream = await got.stream(tarball);

fs.mkdirSync(proPath);

const tarOpts = {
 strip: 1,
 C: proPath
};

// 管道流传输下载文件到当前目录
stream.pipe(tar.x(tarOpts)).on("close", () => {
  spinner.succeed(chalk.green("下载远程模块完成!"));
  ......
})
// 四 遍历文件修改配置
const fs = require("fs-extra");

readFiles(
  proPath,
  {
   ignore: [
    ".{pandora,git,idea,vscode,DS_Store}*",
    "{scripts,dist,node_modules}*",
    "****", options);
 files.forEach(file => {
  done({
   path: file,
   content: fs.readFileSync(file, { encoding: "utf8" })
  });
 });
};

// 配置替换
exports.template = (content = "", inject) => {
 return content.replace(/@{([^}]+)}/gi, (m, key) => {
  return inject[key.trim()];
 });
};

下载依赖

下载完毕并且修改完配置后, 默认执行 git init + 根据环境( yarn / npm / cnpm )安装依赖,这个就很简单了

const { exec } = require("child_process");
const ora = require("ora");
const chalk = require("chalk");

// proPath 项目目录
process.chdir(proPath);

// git init
const gitInitSpinner = ora(
 `cd ${chalk.cyan.bold(projectName)}, 执行 ${chalk.cyan.bold("git init")}`
).start();

const gitInit = exec("git init");
gitInit.on("close", code => {
 if (code === 0) {
  gitInitSpinner.color = "green";
  gitInitSpinner.succeed(gitInit.stdout.read());
 } else {
  gitInitSpinner.color = "red";
  gitInitSpinner.fail(gitInit.stderr.read());
 }
});

// install
let command = "";
if (shouldUseYarn()) {
 command = "yarn";
} else if (shouldUseCnpm()) {
 command = "cnpm install";
} else {
 command = "npm install";
}

log(" ".padEnd(2, "\n"));
const installSpinner = ora(
 `执行安装项目依赖 ${chalk.cyan.bold(command)}, 需要一会儿...`
).start();

exec(command, (error, stdout, stderr) => {
  if (error) {
   installSpinner.color = "red";
   installSpinner.fail(chalk.red("安装项目依赖失败,请自行重新安装!"));
   console.log(error);
  } else {
   installSpinner.color = "green";
   installSpinner.succeed("安装成功");
   log(`${stderr}${stdout}`);
  }
});

主要的代码就是这些,其实只要知道思路,这些东西都很简单,虽然我写的有点 ️:chicken:,但是主要的逻辑还是能理清楚的一些的。更加详细的可以去:eyes:我发的源码,多谢指教。:pray::pray::pray:

开发脚手架

因为这是小程序的脚手架,它不像其他 WEB 框架一样需要很多 webpack 的配置,所以相对简单很多。

对于这个脚手架,相比于开发者工具创建的默认项目,我弥补了它的一些问题

  1. 默认项目太过简单,只适合自己折腾,对于团队或者企业,缺乏相应的代码约定/规范,没有强制的约定会导致团队协作间的困难,提升code review的难度,所以我在原来的基础上加入了eslint,stylelint,prettier,commitlint等配置,以及git hook 在 pre-commit 时,执行校验,确保提交的代码尽量规范

  2. 由于对 css 预处理的钟爱,另外加入了对 less 的支持,并且解决小程序背景图不支持本地图片的问题

  3. 由于以上基本都是文件处理,所以选择 gulp 作为构建工具,这里是 v4, 与v3 写法上有一定的区别,不过关系不大

在根目录下创建 gulpfile.js

const gulp = require('gulp');
const chalk = require('chalk');
const rename = require('gulp-rename');

// 支持 less
gulp.task('less', () => {
 return gulp
  .src('./miniprogram*.less')
  .pipe(less())
  .pipe(postcss()) // 配置在 post.config.js
  .pipe(
   rename((path) => {
    path.extname = '.wxss';
   })
  )
  .pipe(
   gulp.dest((file) => {
    return file.base; // 原目录
   })
  );
});

// 开发环境监听 less
if (env === 'development') {
 gulp.watch(['./miniprogram*.less'], gulp.series('less')).on('change', (path) => {
  log(chalk.greenBright(`File ${path} was changed`));
 });
}


// 一下代码注释掉了,依赖包下载太慢了,这主要负责图片的压缩
const imagemin = require('gulp-imagemin');
const cache = require('gulp-cache'); // 使用缓存

gulp.task('miniimage', () => {
 return gulp
  .src('./miniprogram*.{png,jpe?g,gif,svg}')
  .pipe(
   cache(
    imagemin([
     imagemin.gifsicle({ interlaced: true }),
     imagemin.mozjpeg({ quality: 75, progressive: true }),
     imagemin.optipng({ optimizationLevel: 5 }),
     imagemin.svgo({
      plugins: [{ removeViewBox: true }, { cleanupIDs: false }],
     }),
    ])
   )
  )
  .pipe(
   gulp.dest((file) => {
    return file.base; // 原目录
   })
  );
});

关于“Node CLI如何构建微信小程序脚手架”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

--结束END--

本文标题: Node CLI如何构建微信小程序脚手架

本文链接: https://lsjlt.com/news/67848.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Node CLI如何构建微信小程序脚手架
    这篇文章将为大家详细讲解有关Node CLI如何构建微信小程序脚手架,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。具体如下:  目的由于目前公司的 T...
    99+
    2024-04-02
  • 如何搭建微信小程序
    今天小编给大家分享一下如何搭建微信小程序的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。  准备域名和证书  任务时间:20m...
    99+
    2023-06-26
  • 使用Vue怎么创建一个vue-cli脚手架程序
    使用Vue怎么创建一个vue-cli脚手架程序?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。1. Vue--第一个vue-cli程序Vue的开发都是要基于Nod...
    99+
    2023-06-15
  • Vue新手指南之创建第一个vue-cli脚手架程序
    1. Vue--第一个vue-cli程序 Vue的开发都是要基于NodeJS,实际开发采用Vue-cli脚手架开发,vue-router路由,vuex做状态管理;Vue UI,界面我...
    99+
    2024-04-02
  • 微信小程序如何实现骨架屏
    这篇文章主要介绍微信小程序如何实现骨架屏,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!一、演示二、说明:实现思路:需要默认数据,这样才能完美应对list,wx:if的情况,及flex...
    99+
    2024-04-02
  • 微信小程序后端如何搭建
    要搭建微信小程序的后端,可以选择以下几种方式:1. 使用云开发:微信小程序提供了云开发能力,可以直接在小程序中使用云数据库、云函数等...
    99+
    2023-09-20
    微信小程序
  • 微信门店小程序如何创建
    今天小编给大家分享一下微信门店小程序如何创建的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。    门店小...
    99+
    2023-06-26
  • 微信小程序如何判断手机号
    这篇文章主要介绍微信小程序如何判断手机号,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!JS实现代码: validatemobile: function ...
    99+
    2024-04-02
  • 微信小程序中线程架构的示例分析
    这篇文章主要介绍了微信小程序中线程架构的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。小程序的线程架构每个小程序包含一个描述整体程序...
    99+
    2024-04-02
  • 【小程序】微信小程序如何获取微信公众号openid?
    一图总览 大家可以先看看下面的流程图,来了解笔者想实现的功能,简单来说就是两个不同主体间的小程序与公众号该如何产生关联。 注:为什么这里要强调不同主体呢,因为同主体的小程序与公众号是可以通过unionId来进行关联绑定。 ...
    99+
    2023-08-19
    微信小程序 小程序 微信
  • 微信小程序如何实现手写签名
    这篇文章主要介绍了微信小程序如何实现手写签名的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇微信小程序如何实现手写签名文章都会有所收获,下面我们一起来看看吧。效果wxml<view class=&...
    99+
    2023-07-02
  • 微信小程序中如何实现swiper组件构建轮播图
    小编给大家分享一下微信小程序中如何实现swiper组件构建轮播图,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!实现效果图:wxm...
    99+
    2024-04-02
  • 微信小程序checkbox如何变小
    这篇“微信小程序checkbox如何变小”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“微信小程序checkbox如何变小”文...
    99+
    2023-06-26
  • 微信小程序基本架构与组件是什么
    微信小程序基本架构由三部分组成:逻辑层、视图层和微信客户端。 逻辑层:逻辑层主要负责处理小程序的逻辑,包括数据处理、页面跳转、事...
    99+
    2024-04-09
    微信小程序
  • 微信积分商城小程序如何搭建
    这篇文章主要为大家展示了“微信积分商城小程序如何搭建”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“微信积分商城小程序如何搭建”这篇文章吧。1,要制作积分商城小程序可以用到微信人家平台,微信第三方...
    99+
    2023-06-27
  • 如何创建微信小程序线性渐变
    这篇文章主要介绍了如何创建微信小程序线性渐变的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇如何创建微信小程序线性渐变文章都会有所收获,下面我们一起来看看吧。canvasContext.createLinearG...
    99+
    2023-06-26
  • 如何创建微信小程序圆形渐变
    这篇“如何创建微信小程序圆形渐变”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“如何创建微信小程序圆形渐变”文章吧。canva...
    99+
    2023-06-26
  • 微信小程序如何实现手机号登录
    这篇文章主要讲解了“微信小程序如何实现手机号登录”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“微信小程序如何实现手机号登录”吧!wxml<form bindsubmit=&q...
    99+
    2023-07-02
  • 如何优化微信小程序
    小编给大家分享一下如何优化微信小程序,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!避免使用本地大图片、大资源文件请避免在小程序的...
    99+
    2024-04-02
  • 微信小程序如何推广
    小程序推广的方法:开启附近的小程序功能附近小程序的功能,可以获取门店附近五公里的客流,用户只需打开“附近的小程序”就可以看到小程序的信息。公众号+小程序推广将小程序放在公众号的底部菜单栏,将小程序跳转链接插入公众号的推文中,既可以将公众号粉...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作