GithubHelp home page GithubHelp logo

blog's Introduction

blog's People

Contributors

bjkb avatar

Stargazers

 avatar  avatar

Watchers

 avatar

blog's Issues

小程序与Taro

小程序的前世今生

小程序的前世

  • 小程序并非凭空冒出来的一个概念。当微信中的 WebView 逐渐成为移动 Web 的一个重要入口时,微信就有相关的 JS API 了。也就是微信提供的 WeixinJSBridgeJS SDK
    • 比如说在微信的浏览器里提供一些原生的能力,诸如 微信分享调用原生相册 之类的原生功能
    • 但是这跟其它的混合APP应用并没有区别,复杂的页面会白屏,页面切换的生硬以及用户体验的不足。这些种种缺点,使微信迫切的想要一个解决方案,去优化这些问题。

小程序的诞生

传统的混合APP
传统的混合APP,主要依赖于端上内置的JS运行容器,在其上运行混合APP代码,其本质仍然属于传统的JavaScript运行机制,也就是单线程运行的,并且JS引擎线程会跟GUI渲染线程互斥,导致执行长时间的JS操作的时候,页面会失去响应,动画掉帧等,影响用户体验,这也是混合APP最大的一个弊端

小程序的底层架构
小程序的实现逻辑是双线程架构
image

小程序的运行环境

运行环境 逻辑层 渲染层
iOS JavaScriptCore WKWebView
安卓 V8 chromium定制内核
小程序开发者工具 NWJS Chrome WebView

视图层和逻辑层通过系统层的JSBridage进行通信,逻辑层把数据变化通知到视图层,触发视图层页面更新,视图层把触发的事件通知到逻辑层进行业务处理。这就解决了混合APP最大的一个问题

image

小程序与传统编写的区别

  • 由于种种的考虑(主要是管控性跟安全性,惨遭阉割的小程序也只能走微信审核上线了),小程序搞出了这有点扯淡的实现,还自己搞了一套模板语法,用于区别开传统的 HTML+CSS+JS的方式
  • 小程序由3个文件组成一个小的组件 WXML+WXSS+JS,然后偷偷摸摸的编译一下,本质还是HTML+CSS+JS

WXML
image

WXSS
image

依赖于微信平台的Native组件
由于依赖于微信平台,所以在小程序里面,能使用微信提供的原生组件,也就是Native层绘制的组件,Native层绘制的组件会在WebView层之上

image

所以 微信小程序的本质是由WebViewNative两者组合渲染完成的

小程序的优势

image

小程序的问题

  • 小程序的逻辑层和渲染层是分开的,逻辑层运行在 JSCore 中,并没有一个完整浏览器对象,因而缺少相关的DOM API和BOM API。
  • 这一区别导致了前端开发非常熟悉的一些库,例如 jQuery、 Zepto 等,在小程序中是无法运行的。
  • 同时 JSCore 的环境同 NodeJS 环境也是不尽相同,所以一些 NPM 的包在小程序中也是无法运行的。

为什么选择使用框架taro

小程序编写方面的不足

虽然小程序为业务提供了一种新的展示形式,但对于开发者来说,开发体验则显得并不那么友好。在前端工程化深入人心的今天,小程序那落后的三件套编写模式,大大的浪费时间。

  • 没有自定义文件预处理,无法直接使用 Sass、Less 以及较新的 ES.Next 语法;
  • 字符串模板太过孱弱,小程序的字符串模板仿的是 Vue,但是没有提供 Vue 那么多的语法糖,当实现一些比较复杂的处理时,写起来就非常麻烦,虽然提供了 wxs 作为补充,但是使用体验还是非常糟糕;
  • 缺乏测试套件,无法编写测试代码来保证项目质量,也就不能进行持续集成,自动化打包。

小程序框架对比

列表渲染
image

点击组件响应速度
image

社区对比
image

taro的特点

Taro 采用了 React 语法来作为自己的语法标准,配合前端工程化的**,为小程序开发打造了更加优雅的开发体验。

  • React 是一个非常流行的框架,也有广大的受众,使用它也能降低小程序开发的学习成本;
  • 小程序的数据驱动模板更新的**与实现机制,与 React 类似;
  • React 采用 JSX 作为自身模板,JSX 相比字符串模板来说更自由,更自然,更具表现力,不需要依赖字符串模板的各种语法糖,也能完成复杂的处理
  • React 本身有跨端的实现方案 - React Native,并且非常成熟,社区活跃,对于 Taro 来说有更多的多端开发可能性。

我们目前这边所使用的前端框架也就是 React,基本只需要很少的学习,就能无缝切换到小程序的开发当中去。

Taro原理以及机制

taro诞生的本质**跟编译原理有点类似,就是通过编译的方式,将taro代码,通过一系列的操作,转换成目标代码
image

Taro的优势

  • 由于taro的这种实现策略,导致其也能编译成其它环境的代码
  • 目前 Taro 代码可以支持转换到 微信/百度/支付宝/字节跳动/QQ小程序 、快应用、 H5 端 以及 移动端(React Native)。
    image
    image

但是这对于多端开发是远远不够的,因为每一个平台都有自己的特性,比如小程序跟WEB
image

taro运行机制
image

编译转换核心
Taro 的核心部分就是将代码编译成其他端(H5、小程序、React Native 等)代码。一般来说,将一种结构化语言的代码编译成另一种类似的结构化语言的代码包括以下几个步骤:

image

具体的操作
假设我们需要更改 foo的名字 为 bar

jsonStr.replace(/(?<=")foo(?="\s*:)/i, 'bar')

这就是具体的操作了,实现parse的部分是整个框架的核心,肯定不可能这么简单了,但是自己去实现一个parse也是工作量非常巨大的,还好业界有非常著名的 babel

  • 利用Babylon(@babel/parser) 将代码转换成AST
import * as babylon from "babylon";

const code = `n * n`;

babylon.parse(code);

转换成这样
image

然后通过 Babel-traverse (@babel/traverse) 可以遍历生成的树,实现添加,删除,替换的操作。

taro运行时
image
image

Taro 组件的 setState 行为最终会对应到小程序的 setData。Taro 引入了如 nextTick ,编译时识别模板中用到的数据,在 setData 前进行数据差异比较等方式来提高 setState 的性能。

taro的不足

  • 受限于模板转译的机制,不可能完全支持React的一些新特性,某些方法的使用也遭到了阉割
  • 编译代码必然会导致包体积的增加
  • 性能相比小程序原生语法,有些许下降

小结

这里只简单介绍了一下小程序的历史以及taro主要的架构,在开发过程中依然有无数的坑在等着你,这个只有等具体实践的时候,再逐步积累了。

参考文章:
微信小程序架构,工作原理解析
Taro多端开发原理与实战
小程序开发框架对比

正则表达式总结

自己对正则表达式的使用,还停留在校验手机号、身份证这种级别,趁着中秋假期,梳理一波正则表达式的使用。

正则表达式基础

这里列举一些基本的,完整的查看正则表达式MDN

字符 含义
\ 表示下一个字符不是特殊字符,常用来做转义
^ 表示以什么开头,必须要在开头的位置才行,eating,用这个匹配 a 肯定没效果
$ 表示以什么结尾,必须要在结尾的位置才行,跟上面同理
. 表示换行符之外的任意单个字符
* 表示匹配 0 - 多次,类似 {0,}
+ 表示匹配 1- 多次,类似{1,}
? 表示匹配 0-1次,类似{0,1}
(x) 会记住匹配项 x
(?:x) 不会记住匹配项x
x(?=y) 匹配x,只有当x后面是y的时候,先行断言
(?<=y)x 匹配x,只有当x前面是y的时候,后行断言
x(?!y) 匹配x,只有当x后面不是y的时候,正向否定查找
(?<!y)x 匹配x,只有当x前面不是y的时候,反向否定查找
x|y 匹配x或者y

常见的正则表达式题目

通过这些题目,对使用正则做一个综合性的测试
题目来源:
手写题:9道字符串类高频面试题(掘金)

解析URL params为对象

var url = 'http://www.domain.com/?user=anonymous&id=123&id=456&city=%E5%8C%97%E4%BA%AC&enabled';
parseParam(url)
/* 结果
{ user: 'anonymous',
  id: [ 123, 456 ], // 重复出现的 key 要组装成数组,能被转成数字的就转成数字类型
  city: '北京', // 中文需解码
  enabled: true, // 未指定值得 key 约定为 true
}
*/
解法:
function parseParam(url){
  let obj = {};
  if(!url) return obj;
  let searchParams = url.match(/(?<=\?).*/g)[0]; // 匹配 ?号之后的内容
  searchParams.split('&').forEach((item)=>{
    let [key, value ] = item.split('=');
    if(value){
      value = /^\d+$/.test(value)?parseFloat(value): decodeURIComponent(value); // 判断是否是数字以及解码
    }else{ 
      value = true
    }
    if(obj[key]){  // 判断是否已经存在了这个key,存在就得推入数组里
      obj[key] = Array.isArray(obj[key])? obj[key].push(value): obj[key] = [obj[key],value];
      return;
    }
    obj[key] = value;
  }) 
  return obj;
}

实现一个编译模板

let template = '我是{{name}},年龄{{age}},性别{{sex}}';
let data = {
  name: '姓名',
  age: 18
}
compile(template, data); // 我是姓名,年龄18,性别undefined
解法一:

// 正则替换{{}}里面的内容
function compile(template,data){
  return template.replace(/{{\w+}}/g,item=>data[item.match(/\w+/)]);
}

上面的方法有个问题是,只能替换简单key,复杂一点的,比如 {{obj.name}},就GG了
题目有个变种:
let template =  compile(template);
template({name:'姓名',age:18});

// 可以将字符串写成字符串表达式,类似下面这样
let template = '我是'+obj.name+',年龄'+obj.age+',性别'+obj.sex+'';

解法二:
// 要使用这种方式,得借助一下 new Function(),创建一个新的函数

function compile(template){
   // 将 template 替换成 '我是'+obj.name+',年龄'+obj.age+',性别'+obj.sex+'';
   let str = template.replace(/{{\w+}}/g,item=>`'+obj.${item.match(/\w+/)}+'`);
   let newFn = new Function('obj',`return '${str}'`); // 第一个参数,第二个 return 返回值
  /*
   function anonymous(obj){
     return '我是'+obj.name+',年龄'+obj.age+',性别'+obj.sex+'';
  }
 */
   return newFn;
}

转化为驼峰命名

let str = "get-element-by-id"
// 转化为 getElementById

解法:
// 匹配 -跟后面的单个字符,再利用 replace 替换掉
str  = str.replace(/-\w/g,x=>x.slice(1).toUpperCase())

查找字符串中出现最多的字符跟次数

例: abbcccddddd -> 字符最多的是d,出现了5次
let str = "abcabcabcbbccccc";
let num = 0;
let char = '';

 // 使其按照一定的次序排列
str = str.split('').sort().join('');
// "aaabbbbbcccccccc"

// 定义正则表达式
let re = /(\w)\1+/g; // 匹配单字符,并记住它

replace具体方法参数可以参考 String.prototype.replace

参数 含义
match 匹配的子串
p1,p2,... 匹配括号中的内容,依次推
offset 偏移量
string 原字符串
str.replace(re,(match,p1) => { 
    if(num < match.length){
        num = match.length;
        char = p1;        
    }
});
console.log(`字符最多的是${char},出现了${num}次`);

字符串查找

a='34';b='1234567'; // 返回 2
a='35';b='1234567'; // 返回 -1
a='355';b='12354355'; // 返回 5
isInclude(a,b);

function isInclude(a,b){
  const result = b.match(new RegExp(a));
  return result === null ? -1 : result.index;
}

实现千位分隔符

parseToMoney(123456789); // return '123,456,789'

function parseToMoney(num){
  let str = '';
  let [integer,decimal] = String.prototype.split.call(num,'.');
  str = integer.replace(/(?<=\d)(?=(\d{3})+$)/g,','); // 以数字开头,3个数字为一组,匹配多次
  return decimal?str+'.'+decimal:str;
}

结语

通过这一次的正则做题,让自己对正则有了一个清晰的认识,也巩固了以往正则的基础,收获非常大。

VSCode 扩展插件开发(一键创建模板文件)记录

故事的起源

将几个组件提取到公共组件之后, 开发效率从2小时开发一个基本的后台CRUD模块,提高到了不到 1 小时就能完成。于是,日常的开发就变成了 复制,粘贴,修改表单 fields,增加Router,增加对应菜单的权限key。然后一套写下来差不多 30,40分钟的样子,在暗自窃喜自己又提高了开发效率的一周后,突然感觉到了一阵的空虚,索然无味。重复的创建相同的文件夹,重复的修改文件name,重复的写相似的Router,简直让我感觉到崩溃
这重复的劳动,能不能一键就生成了,我只关注于业务代码的逻辑跟质量,行否?
这念头一起,瞬间四肢百骸 涌起一阵阵的波动,这,这,这,难道便是新的境界?

想法

背景

  • 现存有几个后台系统都在开发维护中,这几个后台系统因为历史的一些原因,模板文件根本无法统一,所以还不如在本地保存一个当前项目的模板文件夹。

目标

  • 输入一个文件夹的名字,一键生成模板文件。
  • 替换 Page 文件中的PageName
  • 替换 model文件 中的 namespace
  • 在项目 Page 目录下的 index.js 文件中 export 创建的文件
  • 在项目 configs 文件中,新增对应的权限 key
  • 在项目 Layout 目录下新增对应的 Router

调研VSCode插件扩展

官方文档

在充分了解了各个项目的情况之后,选择使用VSCode 插件扩展的方式,去实现这一次的功能。

官方的文档对开发扩展有详细的文档说明,所以下面就大概提一下

环境安装

npm i -g yo generator-code  // 官方插件开发脚手架
yo code // 执行脚手架命令

根据步骤创建一个New Extension

这边选的是JavaScript,所以下文都是JavaScript

image

这个新建的Hello Word扩展,点击调试,就能运行了,这里需要注意的是 package.jsonvscode的版本
image

打包成.vsix文件

npm i -g vsce
vsce vscode-plugin-demo

如果没有vscodeAccess Token需要申请一个 vscode 推送准备

Node.js开发准备

由于 VSCode 的扩展里面,内置了 Node.js ,所以 fs 模块就能直接用了

遇到的问题,以及解决

  • 本来想直接使用 inquirer 这个交互式工具去完成的,结果直接写 命令调用是没用的,需要通过 VSCode 提供的 vscode.window.createTerminal 的命令去创建一个终端,执行自己的 shell 代码。在查看API的过程中,发现可以直接利用input弹框获取输入值,所以就用弹框的形式了

  • 在创建文件夹的时候,需要获取 项目的根路径 ,当时还折腾了下,都不太满意,没想到VSCode里面就直接有命令可以使用获取到。

  • Page/index.js文件内容进行添加操作的时候,需要获取对应的行数,进行添加。思考了下,将fs.readFile 读取出来的字符串以\r\n的方式进行数组分割,再匹配最后一个 export的位置,然后进行插入

大概的操作

  • 使用 shelljs 命令,cp 模板文件,放到对应的文件路径下面,判断文件是否存在,给出提示。
  • 使用 Node.jsfs模块,去读写文件。然后修改文件名,增加对应的语句等...

结语

  • VSCode 开发扩展极其的方便,几乎是0学习成本
  • 本来以为很复杂的东西,3天就完成了,一键就可以生成模板。
  • 现在写一个基本的后台 CRUD 模块,复制,粘贴修改文件的5-10分钟统统省略掉了,又提高了一截开发效率。
  • 后续准备将更多的便利性操作集成到 VSCode扩展里。比如扩展公共组件的 参数提示之类的。

图片上传,裁剪项目总结

项目简介

公司需要一个便捷的方式获取员工的照片以制作工牌,靠人力收集的话,则无法保证图片的效果以及标准,浪费人力时间。制作成H5,方便大家上传规范的图片。


技术选型

公司技术栈

公司推荐使用的技术栈有:ReactJqueryES6,这里考虑到这个项目比较轻量,没有过多的DOM操作,直接选择了原生的ES6开撸

需要实现的功能

  • 判断图片的大小(大于1MB,小于等于10MB)
  • 上传、预览图片
  • 图片可支持放大,缩小,裁剪,旋转
  • 产品希望在裁剪的过程时,遇到无网络情况也能保存,下次进来直接预览

实现的难点在于 放大,缩小,裁剪,旋转这一项功能。

当时查看组件库中无此组件,项目周期只有一周(前端开发只有2天),根本不够撸一个稳定版组件。只能退而求其次,选择第三方组件,最后经过,issuesstarpkgSize操作性四个方面的考量,选择了cropperjs


项目的基本架构(前端的部分)

image

项目难点以及遇到的坑

项目难点

项目还是比较简单的,这里略过不提。

遇到的坑以及解决方法

裁剪的图片过大,使用localstorage无法保存

需要保存是因为需要满足 裁剪之后,虽然没有上传,但是也不用重新选择照片再次裁剪的功能

具体问题

  • 裁剪图片时可能大于5MB的图片,本地存储无法存储(chrome最大限制为5MB),只能通过IndexedDB的方式进行存储,但是这个API对低版本的IOSAndroid不支持。

解决方案

  • 裁剪三张不同质量的图片,一张用于预览(localStorage),一张用于备用(localStorage),一张用于上传(IndexedDB)。
  • 如果用户裁剪完成离线之后,再回来上传,则通过判断是否支持IndexedDB,不支持就降级,选择备用的图片(localStorage
  • 为啥不直接用备用的?不用IndexedDB呢,因为产品要求,她想要最好的...
  • 为啥不上传到服务器,再下载回来呢?因为考虑到用户可能会多次裁剪,每次裁剪就上传,太浪费了,而且请求下来的图片也很慢。

Canvas.toDataURL 有时候得到的base64图片是白色的

具体问题

  • 多次裁剪之后,有时候会得到白色的预览图

解决方案

  • 图片未加载,img.onload未完成就转换,将其简单修改
  • 跨域图片,加上图片属性crossorigin或者日期属性

上传base64的图片数据,网络请求一直无响应,页面崩溃

具体问题

  • 有时候上传大于6MB的base64图片,会让浏览器卡死

解决方案

  • 推测是因为base64的字符串太长,上传的时候造成浏览器的内存增加,然后服务器没响应,就卡死了
  • base64的图片转换成file(blob)文件上传

项目总结

  • 通过这次不大的项目,学到了很多东西,也是对自己的一个综合性的考量
  • 这个项目里面,肯定也存在一些不合理的地方,以后遇到类似的问题,就会有更优的选择了

使用 lerna 管理项目中的业务组件

方案的起源

单仓库管理多个包

在进行业务开发的时候,往往能抽离出很多相似的模块跟组件。自己负责的项目一般也不止一个,如果只是将其手动复制到不同的项目当中,组件跟模块往后的更新与迭代将会很困难。

大多数人都会这么干,那就是将公共的组件、模块、工具方法、发布到 npm私有仓库上进行统一的管理跟迭代...

遇到的问题

  • 由于大家都是高自我要求的前端开发者,踊跃的抽离项目中的公共模块,发布到 npm 仓库当中,所以就造成了 npm 公共组件仓库体积的急剧增加。
  • 不仅如此,由于公共方法也被放到这个仓库当中,造成了一个很尴尬的情况,自己只是修改了公共方法当中的导出操作,不得不发布了整个仓库。

提出的解决方案(多仓库管理多个包)

最开始的解决方案,将公共操作方法,公共组件,公共模块弄成了三个仓库单独发布
自从这样实行以来,上面的问题得到了初步的解决,本以为满心欢喜,结果却遇到了更棘手的情况。

遇到的问题

  • 在使用公共操作方法时,细心的小明发现了公共操作方法当中的某个缺陷,提出了改进的意见,于是提了一个 pull request ,负责管理公共仓库的小华,review 以后觉得相当的不错,于是打上了 tag 更新了版本。
  • 某日,小明在使用公共模块时,发现自己改进的操作方法,在这个模块当中没有更改,于是在查看源码之后,发现公共模块依赖的公共操作方法的版本没有升级...

简单的总结

  • 使用单独的仓库进行管理多个包,更改一个,必须发布整个仓库,文件目录过多,阅读体验差。
  • 使用多仓库管理多个包,难以梳理其中的依赖情况,不便于管理,维护多个仓库浪费时间。

那能不能一个仓库管理多个包,但是这些包相对于这个仓库,又是独立的呢?

答案是可以的,在调研之后,发现业界早已存在解决方案,那就是 monorepo 管理方案,本文基于monorepo 方案的开源框架 lerna 进行简单的讲解。


lerna 的简单使用

Lerna 是一个管理多个 npm 模块的工具,是 Babel 自己用来维护自己的 Monorepo 并开源出的一个项目。优化维护多包的工作流,解决多个包互相依赖,且发布需要手动维护多个包的问题。

简单的安装

npm i -g lerna

git init lernaExample

cd lernaExample

lerna init

然后根据提示,项目当中生成的 package.jsonlerna.json 如下

// package.json
{
  "name": "root",
  "private": true, // 私有的,不会被发布,是管理整个项目,与要发布到npm的解耦
  "devDependencies": {
    "lerna": "^3.15.0"
  }
}
 
// lerna.json
{
  "packages": [
    "packages/*"
  ],
  "version": "0.0.0" // 仓库的版本
}

创建 npm

这里有个注意点是,lerna 中的仓库名 @lernaExample 必须一致

lerna create @lernaExample/utils

lerna create @lernaExample/components

lerna create @lernaExample/decorator

文件目录

image

增加依赖

lerna add react // 为所有 package 增加 react 模块 (像这种公共的包可以使用 lerna bootstrap --hoist 提升到项目的工程目录)

lerna add classnames--scope @lernaExample/components // 为 @lernaExample/components 增加 classnames 模块 

lerna add @lernaExample/utils--scope @lernaExample/components // 增加内部模块之间的依赖

// 想删除某个依赖项
lerna clean

更多的命令可以查看 lerna

image

发布

lerna publish 
// 按照提示发布就行
// 如果发布报错,可能是没有相对于仓库的权限

lerna 完整示例

在上文中,只是简单的了解 lerna 的基本使用,在项目当中使用的话还存在下面的几个问题。

  • 包中的文件没有经过编译,如果是直接书写的 es6 文件,则很有可能浏览器中不能兼容
  • 没有对文件进行基本的 eslint 格式校验
  • 没有对发布进行约束,比如 commit 校验,changlog 文件生成等

环境搭建

babel 环境

需要下载的 babel

  "dependencies": {
    "@babel/runtime": "^7.6.2",
    "@lernaExample/utils": "^0.0.0",
    "classnames": "^2.2.5",
    "react": "^16.8.0"
  },
  "devDependencies": {
    "@babel/cli": "^7.6.0",
    "@babel/core": "^7.6.0",
    "@babel/plugin-proposal-class-properties": "^7.5.5",
    "@babel/plugin-proposal-decorators": "^7.6.0",
    "@babel/plugin-transform-regenerator": "^7.4.5",
    "@babel/plugin-transform-runtime": "^7.6.0",
    "@babel/preset-env": "^7.6.0",
    "@babel/preset-react": "^7.0.0",
    "babel-plugin-import": "^1.12.2"
  },

.babelrc 文件配置

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "modules": false // 模块使用 es modules ,不使用 commonJS 规范
      }
    ],
    "@babel/preset-react"
  ],
  "plugins": [
    [
      "@babel/plugin-proposal-decorators",
      {
        "legacy": true
      }
    ],
    ["@babel/plugin-transform-regenerator"],
    ["@babel/plugin-proposal-class-properties"],
    [
      "@babel/plugin-transform-runtime",
      {
        "corejs": false, // 默认值,可以不写
        "helpers": true, // 默认,可以不写
        "regenerator": true, // 通过 preset-env 已经使用了全局的 regeneratorRuntime, 不再需要 transform-runtime 提供的 不污染全局的 regeneratorRuntime
        "useESModules": true // 使用 es modules helpers, 减少 commonJS 语法代码
      }
    ],
    [
      "import",
      {
        "libraryName": "antd"
      }
    ] // 通过手动引入antd样式
  ]
}

image

package.json 文件中增加编译命令

"main": "lib/index.js", // 文件入口
"scripts": {
    "compile": "babel src --out-dir lib",
     ...
 },

使用方式  npm run compile

eslint 环境

我这边直接使用的 vscode 扩展的 eslint 工具,如果团队内部对 eslint 有自己的定义,可以单独下载 eslint 包,对其文件进行配置。


commit 以及 changelog 环境

自动校验commit规范

使用 husky 包,相关依赖项

"devDependencies": {
    "@commitlint/cli": "^7.0.0",
    "@commitlint/config-conventional": "^7.0.1",
    "husky": "^0.14.3",
 }

创建 commitlint.config.js 文件

module.exports = {
  extends: ['@commitlint/config-conventional'],
  rules: {
    'type-enum': [
      2,
      'always',
      [
        'feat',
        'fix',
        'bug',
        'docs',
        'style',
        'refactor',
        'test',
        'chore',
        'version',
        'build',
        'ci',
        'perf',
        'revert',
      ]
    ],
    'scope-case': [2, 'always', ['lower-case', 'snake-case', 'upper-case', 'kebab-case']],
    'subject-case': [0]
  }
};

自动生成changelog记录

npm i cz-lerna-changelog 下载 lerna 专用的 changelog

image


使用

  • 更改了文件之后,执行npm run compile
  • 写上 commit 内容,如果内容不符合,会自动打回
  • 如果不用发布版本,则直接执行 lerna version,打上tag 生成 changlog 记录
  • 需要发布版本
    • 只发布一个,可以先执行 lerna updated,然后执行 lerna publish
    • 全部发布, 执行 lerna publish
  • 如果不想生成版本记录,以及不发布版本,则直接执行 git push

总结

  • 以往的仓库管理方式的不足之处
  • 使用 lerna 之后,package 之间存在互相的依赖项,lerna 会自动对其管理,不需要手动更新 package.json 中依赖项的版本号。
  • 一个基本完整的 lerna 使用介绍

参考文章:lerna+yarn workspace+monorepo项目的最佳实践(掘金)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.