├── README.md
├── build 编译相关代码
├── docs 文档
├── package.json
├── packages 主要内容
│ ├── __mocks__
│ ├── components 组件
│ ├── directives 指令
│ ├── element-plus
│ ├── hooks
│ ├── locale
│ ├── test-utils
│ ├── theme-chalk 样式
│ ├── tokens
│ └── utils 工具包
├── play 测试demo
├── pnpm-workspace.yaml
├── scripts 脚本
├── tsconfig.json
└── typings .d.ts 全局声明
-
monorepo
简介- monorepo 全称 monolithic repository (巨型仓库) 是一种管理项目代码的方式,指在一个项目中管理多个模块/包(package)
├── packages 其他模块放置在该目录下 | ├── pkg1 | | ├── package.json | ├── pkg2 | | ├── package.json ├── package.json 第一层内容
- 使用 monorepo 好处:多模块在一个项目下,方便开发调试(依赖的模块不需要单独下载repo,依赖多模块时可以统一调试,发版, 方便管理)
- 弊端:repo 体积可能会很大, 因为每个 package 理论上是独立的,因此都有自己的 dependencies, 这时,不同的模块可能安装了相同的依赖, install 时会出现重复安装,导致 node_module 膨胀
- 管理工具 lerna (处理发版问题 统一的工作流),yarn 的 workspaces (处理依赖问题, 以 semver 的约定来分析 dependencies,, 相同的提到 repo 根目录下)
- 参考文章
-
使用
pnpm
作为包管理工具- 全称
performant npm
高性能的npm - pnpm 会在全局生成一个 store 目录用来存放 node_modules 下文件的 hard link, 查找项目中 node_modules 下的包时,会通过软链找到 .pnpm 下的文件目录, 然后在通过hard link在全局 store 中查找
- 解决了npm 的两个痛点:
- 幽灵依赖 (npm v3 版本之后,yarn 中也存在) - 即在 package.json 中不存在的依赖,项目中也能引用到 (foo 中依赖了bar, 安装时node_modules会被打平处理,即foo与bar的依赖会出现在同一层级, 那能引入foo,也能引入bar)
- npm 包重复安装
- 全称
# node_modules 软链到 node_modules 下的 .pnpm 目录下的真实依赖, 真实依赖通过 hard link 存储到全局 store 中
└── bar // symlink to .pnpm/bar@1.0.0/node_modules/bar
└── foo // symlink to .pnpm/foo@1.0.0/node_modules/foo
└── .pnpm
├── bar@1.0.0
│ └── node_modules
│ └── bar -> <store>/bar
│ ├── index.js
│ └── package.json
└── foo@1.0.0
└── node_modules
└── foo -> <store>/foo
├── index.js
└── package.json
- 在项目根目录下建立
pnpm-workspace.yaml
配置文件
npm install pnpm -g
pnpm init -y
pnpm install vue@next typescript -D # 安装 vue ts
npx tsc --init # 初始化ts配置文件
# tsconfig.json 文件配置 ts 编译格式,可以根据配置文件编译成相对应的 js 文件
mkdir play && cd play
pnpm init
pnpm install vite @vitejs/plugin-vue # 安装vite及插件
- play 下 创建 vite.config.js 配置 vite 文档
- root 下对 vue 模块进行 declare 声明
packages
├─components # 存放所有的组件
├─utils # 存放工具方法
└─theme-chalk # 存放对应的样式
- 模块初始化
cd components && pnpm init # @c-plus/components
cd utils && pnpm init # @c-plus/utils
cd theme-chalk && pnpm init # @c-plus/theme-chalk
- 根目录下添加依赖项
pnpm install @c-plus/components -w
pnpm install @c-plus/theme-chalk -w
pnpm install @c-plus/utils -w
- 组件编写
- 组件导出
- 导出的时候需要包裹 install 方法
app.use(CIcon)
- 导出的时候需要包裹 install 方法
theme-chalk
│ └─src
│ ├─fonts # 存放字体
│ └─mixins
│ └─config.scss # BEM规范命名
- scss 相关语法
- 组件样式导出
- glup 流程控制,做代码转化处理 文档
- 安装
# pnpm install gulp @types/gulp sucrase -w -D (sucrase -> babel平替,速度比babel快)
"scripts": {
"build": "gulp -f build/gulpfile.ts" # gulp --gulpfile 手动设置 gulpfile 路径
}
-
gulpfile.ts
配置文件 -
执行
pnpm build
执行打包流程
# 依赖包安装
pnpm install sass gulp-sass gulp-clean-css gulp-autoprefixer @types/gulp-sass @types/sass @types/gulp-autoprefixer @types/gulp-clean-css
- 执行
buildPackages
任务, 会对应执行 packages 下每个子模块的打包流程
theme-chalk/gulpfile.ts
- 用 gulp-sass 相关插件处理 sass 文件, 将处理的文件拷贝到 root 的dist目录下
utils/gulpfile.ts
pnpm install gulp-typescript -w -D # 处理 ts 编译工作流的插件
-
创建组件库入口
index.ts
-
创建打包组件库的入口
mkdir c-plus && cd c-plus
pnpm init
# 入口文件 index.ts 代码编写
- 新增组件库打包命令
- 新增
buildFullComponent
命令
- 新增
pnpm install rollup @rollup/plugin-node-resolve @rollup/plugin-commonjs rollup-plugin-typescript2 rollup-plugin-vue -D -w
- 打包
umd
和es
模块
- 找到
components
文件下所有组件依次进行打包
pnpm install fast-glob -w -D # nodejs glob库,能快速遍历文件系统
- 给每个组件添加类型声明
pnpm i ts-morph -w -D # 为每个组件添加 ts 声明文件, 根据tsconfig.json 生成ts文件
- components 组件打包
- c-plus 打包
- 打包package/c-plus入口文件输出作为dist文件下 es / lib 的入口
- 打包package/components/index 输出到dist文件下 es / lib下作为入口文件
- 生成 .d.ts 声明文件入口(找到packages/c-plus/index 生成.d.ts文件拷贝到es/lib下)
"main": "lib/index.js", // npm包的入口文件, 浏览器与node环境均可使用
"module": "es/index.js", // 定义 npm 包的 ESM 规范的入口文件,browser 环境和 node 环境均可使用
umd 通用的模块化系统(是amd与commonjs的结合体), 与 amd CommonJS 兼容
- CommonJS 模块输出的是值的拷贝,ES6 模块输出的是值的引用
- CommonJS 模块是运行时加载,ES6 模块是编译时输出接口
- CommonJS 模块导出的是一个对象(module.exports 属性),该对象只在脚本运行完才会生成。
- ES6 的模块机制是 JS 引擎对脚本进行静态分析的时候,遇到模块加载命令 import,就会生成一个只读引用,等到脚本真正执行时,再根据这个只读引用到被加载的模块中取值
- 先判断是否支持 Node.js 模块格式(exports 是否存在),存在则使用 Node.js 模块格式
- 再判断是否支持 AMD 模块格式(define 是否存在),存在则使用 AMD 模块格式
- 前2个都不存在则将模块公开到全局(window 或 global)