原副标题:从0到1构筑如前所述另一方面销售业务的后端辅助工具库
作者 | 天猫云合作开发人员-天猫零售业 博尔希夫卡
序言
在前述工程项目合作开发中不论 M 端、PC 端,多多少少都有两个 utils 二百一十三去管理工程项目中加进的许多常见的辅助工具方式,比如:时间处置、价格处置、导出 url 模块、读取JAVA等,其中许多是多次重复、基础、或如前所述这种销售业务情景的辅助工具,存在工程项目间输入输出的关键点以及辅助工具方式规范化不统一的问题。
在前述合作开发过程中,经常使用许多开放源码辅助工具库,如 lodash,以方便、快捷的进行工程项目合作开发。但是当 npm 上没有他们科榧或符合另一方面销售业务的辅助工具时,他们不得不他们亲自动手,此时拥有他们的、如前所述销售业务的辅助工具库就显得至关重要。 他们所津津乐道的 Vue、React 等众多著名后端架构,或公司提供更多的许多C#,它们是怎样合作开发、构筑、装箱出的,责任编辑将率领你了解到怎样从 0 到 1 构筑如前所述另一方面销售业务的后端辅助工具库。构筑辅助工具库非主流方案 1. WEBPACKwebpack 提供更多了构筑和装箱不同组件化准则的库,而已须要他们去构筑合作开发下层构架。 vue-cli,如前所述 webpack , vue-cli 钢架辅助工具能快速调用两个 vue 应用领域,它也能调用两个构筑库。2. ROLLUProllup 是两个专门特别针对 Java 组件装箱器,能将应用领域或库的大块标识符载入更复杂的机能标识符。 Vue、React 等许多盛行后端架构的构筑和装箱都能看到 rollup 的踪迹。为什么采用 ROLLUP 而不是 WEBPACKwebpack 主要就职责是合作开发应用领域,而 rollup 主要就特别针对的就是 js 库的合作开发,假如你要开发 js 库,那 webpack 的繁杂配置和装箱后的文档表面积就不太适用于了,通过 webpack 装箱构筑出的源标识符增加了许多辅助工具表达式之外的组件倚赖标识符。 rollup 而已把销售业务标识符音频文档成目标 js ,轻巧且小巧。rollup 对于标识符的 Tree-shaking 和 ES6 组件有着演算法优势上的全力支持,假如只想构筑两个简单的库,并且是如前所述 ES6 合作开发的,加上其简约的 API,rollup 得到更多合作开发人员的追捧。辅助工具库下层构架设计构筑辅助工具库下层构架大概须要什么样机能的全力支持:
构架倚赖需知
在对下层构架设计的基础上,首先须要把加进的倚赖库简单熟悉一下:
rollup 全家桶
• rollup(辅助工具库装箱构筑核心包)
• rollup-plugin-livereload(rollup 插件,热更新,方便本地 debugger 合作开发)
• rollup-plugin-serve(rollup 插件,本地服务代理,方便在本地 html 中调试辅助工具)
• rollup-plugin-terser(rollup 插件,标识符压缩混淆)
• rollup-plugin-visualizer(rollup 插件,可视化并分析 Rollup bundle,以查看组件占用)
• @rollup/plugin-babel(rollup 插件,rollup 的 babel 插件,ES6 转 ES5)
• @rollup/plugin-commonjs(rollup 插件,用来将 CommonJS 组件转换为 ES6,这样它们就能包含在 Rollup 包中)
• @rollup/plugin-json(rollup 插件,它将.json 文档转换为 ES6 组件)
• @rollup/plugin-node-resolve(rollup 插件,它使用节点导出演算法定位组件,用于在节点组件中使用第三方 node_modules 包)
• @rollup/plugin-type(rollup 插件,对 type 的全力支持,将 type 进行 tsc 转为 js)
type 相关
• type(使用 ts 合作开发辅助工具库)
• tslib(Type 的运行库,它包含了 Type 所有的帮助表达式)
• @type-eslint/eslint-plugin(Type 的 eslint 插件,约束 ts 书写规范化)
• @type-eslint/parser(ESLint 导出器,它利用 Type ESTree 来允许 ESLint 检测 Type 源标识符)
文档相关
• typedoc(Type 工程项目的文档生成器)
• gulp(使用 gulp 构筑文档系统)
• gulp-typedoc(Gulp 插件来执行 TypeDoc 辅助工具)
• browser-sync(文档系统热更新)
单元测试相关
• jest(一款优雅、简约的 Java 测试架构)
• @types/jest(Jest 的类型定义)
• ts-jest(两个全力支持源映射的 Jest 转换器,允许您使用 Jest 来测试用 Type 编写的工程项目)
• @babel/preset-type(Type 的 Babel 预设)
其他倚赖
• eslint(标识符规范化约束)
• @babel/core(@rollup/plugin-babel 倚赖的 babel 导出插件)
• @babel/plugin-transform-runtime(babel 转译倚赖)
• @babel/preset-env(babel 转译倚赖)
• chalk(控制台字符样式)
• rimraf(UNIX 命令 rm -rf 用于 node)
• cross-env(跨平台设置 node 环境变量)
下层构架构筑1. 调用工程项目
新建两个文档夹 utils-demo,执行 npm init,过程会询问构筑工程项目的基本信息,按需填写即可:
npminit2. 组织辅助工具库销售业务合作开发 SRC 目录结构
创建辅助工具库销售业务合作开发 src 二百一十三,明确怎样规划辅助工具库包,里面放置的是辅助工具库合作开发须要的销售业务标识符:
3. 安装工程项目倚赖
要对 type 标识符进行导出全力支持须要安装对 ts 全力支持的倚赖,以及对合作开发的辅助工具的许多倚赖包:
yarn add type tslib rollup rollup-plugin-livereload rollup-plugin-serve rollup-plugin-terser rollup-plugin-visualizer
@rollup/plugin-babel @rollup/plugin-commonjs @rollup/plugin-json @rollup/plugin-node-resolve @rollup/plugin-type
@babel/core @babel/plugin-transform-runtime @babel/preset-env rimraf lodash chalk@^4. 1.2-D
这里遇到两个坑,关于最新 chalk5.0.0 不全力支持在 nodejs 中 require 导入,所以锁定包版本 chalk@^4.1.2
要对 type 进行导出和编译还须要配置 tsconfig.json,该文档中指定了用来编译这个工程项目的根文档和编译选项,在工程项目根目录,使用 tsc –init 命令快速生成 tsconfig.json 文档(前提全局安装 type)
npmi type -g
tsc–init
调用 tsconfig 完成之后,根目录自动生成 tsconfig.json 文档,须要对其进行简单的配置,以适用于于 ts 工程项目,其中具体含义能参考tsconfig.json 官网
4. 组织工程项目装箱构筑 S 目录结构
1) 根目录创建工程项目装箱构筑 s JAVA二百一十三,里面放置的是有关于工程项目装箱构筑须要的文档:
生成 rollup 配置项表达式核心标识符:
constmoduleName = camelCase(name)// 当format为iife和umd时必须提供更多,将作为全局变量挂在window下:window.moduleName=…
constbanner = generateBanner // 包说明文案
// 生成rollup配置文档表达式
constgenerateConfigs = ( options) => {
const{ input, outputFile } = options
console.log(chalk.greenBright(${input}` ))
constresult = []
constpushPlugins = ( { format, plugins, ext }) =>{
result.push({
input, // 装箱入口文档
external: [], // 假如装箱出的文档有工程项目倚赖,能在这里配置是否将工程项目倚赖一起打到包里面还是作为外部倚赖
// 装箱出口文件
output: {
file: ` ${outputFile}${ext}` , // 出口文档名称
sourcemap: true, // // 是否生成sourcemap
format, // 装箱的组件化格式
name: moduleName,// 当format为iife和umd时必须提供更多,将作为全局变量挂在window下:window.moduleName=…
exports: named/** Disable warning for default imports */,
banner, // 装箱出的文档在最顶部的说明文案
globals: {} // 假如external设置了装箱忽略的工程项目倚赖,在此配置,工程项目倚赖的全局变量
},
plugins // rollup插件
})
}
buildType.forEach( ( { format, ext }) => {
letplugins = […defaultPlugins]
// 生产环境加入包分析以及标识符压缩
plugins = [
…plugins,
visualizer({
gzipSize: true,
brotliSize: true
}),
terser
]
pushPlugins({ format, plugins, ext })
})
returnresult
}
2) rollup 在装箱构筑的过程中须要进行 babel 的转译,须要在根目录添加.babelrc 文件告知 babel:
{
“presets”: [
[
“@babel/preset-env”
]
],
“plugins”: [ “@babel/plugin-transform-runtime”]
}
3) 此时距离装箱构筑辅助工具库只差一步之遥,配置装箱JAVA命令,在 package.json 中配置命令:
“s”: {
“build”: “rimraf lib && rollup -c ./s/rollup.config.js”// rollup装箱
},
4) 执行 yarn build,根目录会构筑出两个 lib 文档夹,里面有装箱构筑的文档,还多了两个 stats.html,这个是可视化并分析 Rollup bundle,用来查看辅助工具组件占用空间:
构架构筑优化
工程项目构筑到这里,不知机智的你能否发现问题:
1) 只要添加了两个辅助工具,就要在入口文档导出须要装箱构筑的辅助工具,在多人合作开发提交标识符的时候将引来冲突的产生:
2) 使用辅助工具库的时候,按需引用的颗粒度太细了,不能满足许多要求颗粒度粗的朋友,比如:
•我想使用该包里面 date 相关辅助工具,要这样吗?
import{ dateA, dateB, dateC } from“utils-demo”
能不能这样?
import { date} from “utils-demo”
date.dateA
date.dateB
date.dateC
•在许多使用 JAVA引入的情景下,就仅仅须要 date 相关的辅助工具,要这样吗?
< src= “https://xxx/main.min.js”>
能不能这样?
< src= “https://xxx/date.min.js”>
这样仅仅使用 date 里面的辅助工具,就没有必要将所有的辅助工具都引入了
解决方案:
1) 特别针对第两个标识符冲突的问题,能根据 src > modules 下目录结构自动生成入口文档 index.ts
自动构筑入口文档核心标识符:
constfs = require( fs) // node fs组件
constchalk = require( chalk) // 自定义输出样式
const{ resolveFile, getEntries } = require(./utils)
letsrcIndexContent = `
// tips:此文档是自动生成的,无需手动添加
`
getEntries(resolveFile( src/modules/*)).forEach(( { baseName, entry }) => {
letmoduleIndexContent = `
// tips:此文档是自动生成的,无需手动添加
`
try{
// 判断是否文档夹
conststats = fs.statSync(entry)
if(stats.isDirectory) {
getEntries( ` ${entry}/*.ts` ).forEach( ( { baseName }) => {
baseName = baseName.split(.)[ 0]
if(baseName.indexOf( index) === -1) {
moduleIndexContent += `
export * from ./${baseName}
`
}
})
fs.writeFileSync( ` ${entry}/index.ts` , moduleIndexContent, utf-8)
srcIndexContent += `
export * from ./modules/${baseName}
export * as ${baseName}from ./modules/ ${baseName}
`
} else{
srcIndexContent +=`
export * from ./modules/ ${baseName.split( .)[ 0]}
`
}
} catch(e) {
console.error(e)
}
})
fs.writeFileSync(resolveFile(src/index.ts), srcIndexContent, utf-8)
2) 特别针对颗粒度的问题,能将 modules 下各种类型辅助工具文档夹下面也自动生成入口文档,除了全部导出,再追加 import * as 组件类名称 类型的导出
至此,基本上解决了辅助工具库装箱的问题,但是构架中还缺少本地合作开发调试的环境,下面为大家介绍怎样构架中添加本地合作开发调试的系统。
本地合作开发调试系统
首先要明确要加入本地合作开发调试系统的全力支持,须要做到以下:
•跨平台(window 不全力支持 NODE_ENV=xxx)设置环境变量,根据环境配置不同的 rollup 配置项
•引入本地合作开发须要的 html 静态服务器环境,并能做到热更新
1) 跨平台设置环境变量很简单,使用 cross-env 指定 node 的环境
yarnadd cross-env -D
2) 配置 package.json 命令
“s”: {
“entry”: “node ./s/build-entry.js”,
“dev”: “rimraf lib && yarn entry && cross-env NODE_ENV=development rollup -w -c ./s/rollup.config.js”, // -w 表示监听的辅助工具组件的修改
“build”: “rimraf lib && yarn entry && cross-env NODE_ENV=production rollup -c ./s/rollup.config.js”
},
3) 根据最开始构架设计的组件,在工程项目根目录新建 debugger 文档夹,里面存放的是辅助工具调试的 html 静态页面
4) 接下来就是配置 s > rollup.config.js ,将 NODE_ENV=development 环境加入 rollup 配置,修改生成 rollup 配置项函数核心标识符:
(isProd ? buildType : devType).forEach( ( { format, ext }) => {
letplugins = […defaultPlugins]
if(isProd) {
// 生产环境加入包分析以及标识符压缩
plugins = […plugins, visualizer({
gzipSize: true,
brotliSize: true
}), terser]
} else{
// 非生产环境加入热更新和本地服务插件,方便本地debugger
plugins = […plugins, …[
// 热更新
rollUpLiveLoad({
watch: [ debugger, lib],
delay: 300
}),
// 本地服务代理
rollupServe({
open: true,
// resolveFile()代理根目录原因是为了在ts标识符里debugger时能方便看到调试信息
contentBase: [resolveFile( debugger), resolveFile( lib), resolveFile( )]
})
]]
}
pushPlugins({ format, plugins, ext })
})
5) 执行 yarn dev 之后浏览器会新打开窗口,输入刚添加的辅助工具链接,并且它是热更新的:
辅助工具库文档系统
两个完备的辅助工具库须要有两个文档来展示合作开发的辅助工具函数,它可能须要具备以下几点全力支持:
•全力支持辅助工具库中方式的可视化预览
•全力支持修改辅助工具的时候,具备热更新机制
typedoc (Type 工程项目的文档生成器)能完美全力支持 type 合作开发辅助工具库的文档生成器的全力支持,它的核心原理就是读取源标识符,根据辅助工具的注释、ts 的类型规范化等,自动生成文档页面
关于热更新机制的全力支持,第两个自然想到 browser-sync (文档系统热更新)
由于文档系统的预览机能有许多插件组合来实现的,可以借助 gulp (如前所述流的自动化构筑辅助工具),typedoc 正好有对应的gulp-typedocGulp 插件来执行 TypeDoc 辅助工具插件
构筑完成后打开文档系统,并且它是热更新的,修改辅助工具方式后自动更新文档:
单元测试
为确保用户使用的辅助工具标识符的安全性、正确性以及可靠性,辅助工具库的单元测试必不可少。单元测试选用的是 Facebook 出品的 Jest 测试架构,它对于 Type 有很好的全力支持。
1. 环境构筑
1) 首先全局安装 jest 使用 init 来调用 jest 配置项
npm jest -g
jest –init
下面是本人设置的jest的配置项
✔ Would you like to useJestwhenrunning “test” in“package.json”? … yes
✔ Would you liketouseType forthe configuration file? … yes
✔ Choosethe testenvironment that will be used fortesting › jsdom (browser- like)
✔ Doyou want Jest toaddcoverage reports? … yes
✔ Which provider should be used toinstrument code forcoverage? › babel
✔ Automaticallyclearmock calls, instances andresults beforeevery test? … yes
执行完之后根目录会自动生成 jest.config.ts 文档,里面设置了单元测试的配置准则,package.json 里面也多了两个 指令 test。
2) 关于 jest.config.js 文档配置项具体含义能查看官网,要想完成 jest 对于 Type 的测试,还须要安装一些倚赖:
yarnaddjestts-jest@ babel/ preset– type@types/jest -D
3) jest 还须要借助 .babelrc 去导出 Type 文档,再进行测试,编辑 .babelrc 文档,添加倚赖包 @babel/preset-type:
{
“presets”: [
“@babel/preset-type”,
[
“@babel/preset-env”
]
],
“plugins”: [ “@babel/plugin-transform-runtime”]
}
2. 单元测试文档的编写
1) 通过以上环节,jest 单元测试环境基本构筑完毕,接下来在__tests__下编写测试用例
2) 执行 yarn test
能看到关于 debounce 防抖辅助工具表达式的测试情况显示在了控制台:
•stmts 是语句覆盖率(statement coverage):是不是每个语句都执行了?
•Branch 分支覆盖率(branch coverage):是不是每个 if 标识符块都执行了?
•Funcs 表达式覆盖率(function coverage):是不是每个表达式都调用了?
•Lines 行覆盖率(line coverage):是不是每一行都执行了?
3) 同时还会发现工程项目根目录多了两个 coverage 文档夹,里面就是 jest 生成的测试报告:
3. 单元测试文档的编写引发的思考
每次修改单元测试都要执行 yarn test 去查看测试结果,怎么解决?
jest 提供更多了 watch 指令,只须要配置 s JAVA就能做到,单元测试的热更新。
“s”: {
“test”: “jest –watchAll”
},
以后会写许多辅助工具的测试用例,每次 test 都将所有辅助工具都进行了测试,能否只测试他们写的辅助工具?
jest 也提供更多了测试单个文档的方式,这样 jest 只会对防抖表达式进行测试(前提全局安装了 jest)。
jestdebounce.test.ts–watch
辅助工具库包的发布
至此辅助工具库距离合作开发人员使用仅一步之遥,就是发布到 npm 上,发包前须要在 package.json 中声明库的许多入口,关键词等信息。
“main”: “lib/main.js”, //告知引用该包组件化方式的默认文档路径
“module”: “lib/main.esm.js”, //告知引用该包组件化方式的文档路径
“types”: “lib/types/index.d.ts”, //告知引用该包的类型声明文档路径
“sideEffects”: false, //false为了告诉 webpack 我这个 npm 包里的所有文档标识符都是没有副作用的
“files”: [ //合作开发人员引用该包后node_modules包里面的文档
“lib”,
“README.md”
],
“keywords”: [
“type”,
“utils-demo”,
“utils”
],
“s”: {
“pub”: “npm publish”
},
登陆 npm ,你会看到他们的 packages 里面有了刚刚发布的辅助工具库包:
写在最后
以上就是作者整理的从 0 到 1 构筑如前所述另一方面销售业务的后端辅助工具库的全过程,希望能给阅读责任编辑的合作开发人员带来许多新的想法与尝试。
在此基础上已经成功在天猫 npm 源发布了应用领域于天猫汽车后端的辅助工具库 @jdcar/car-utils ,并在各个销售业务线及系统得到落地。
当然,构架优化之路也还远未结束,比如:装箱构筑的速度、本地合作开发按需构筑、辅助工具库钢架化等,后续他们也会如前所述另一方面销售业务以及许多新技术,持续深入优化,在性能上进一步提升,在机能上进一步丰富。责任编辑或存在许多浅显不足之处,也欢迎大家评论指点。
参考资料
[1] rollup 英文文档(https://rollupjs.org/guide/en/#quick-start )
[2] rollup 中文文档(https://rollupjs.org/guide/zh/#introduction)
[3] Rollup.js 实战学习笔记(https://chenshenhai.github.io/rollupjs-note/)
[4] Rollup 装箱辅助工具的使用(https://juejin.cn/post/6844904058394771470 )
[5] Type、Rollup 构筑辅助工具库(https://juejin.cn/post/6844904035309322254)
[6] 使用 rollup.js 封装各工程项目共用的辅助工具包(https://juejin.cn/post/6993720790046736420)
[7] 怎样合作开发两个如前所述 Type 的辅助工具库并自动生成文档(https://juejin.cn/post/6844903881030238221 )
[8] 一款优雅、简约的 Java 测试架构(https://jestjs.io/zh-Hans/)
微软Bing“开战”谷歌:争夺Firefox的默认搜索引擎
后端架构Svelte放弃Type,JS赢!
开放源码软件:甲骨文和苹果最爱
🌟 活动推荐
2023 年 5 月 27-28 日,GOTC 2023 全球开放源码技术峰会将在上海张 江科学会堂隆重举行。
为期 2 天的开放源码行业盛会,将以行业展览、主题发言、特别论坛、分论坛、快闪演讲的形式来诠释此次大会主题 ——“Open Source, Into the Future”。与会者将一起探讨元宇宙、3D 与游戏、eBPF、Web3.0、区块链等热门技术主题,以及 OSPO、汽车软件、AIGC、开放源码教育培训、云原生等热门话题,探讨开放源码未来,助力开放源码发展。