我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第1篇文章,点击查看活动详情
序
之前有一段时间使用过qiankun微前端,每个子项目都有同样的api
请求模块和可复用的组件,想要抽离出来公用,却没有想到比较好的方法。
了解了pnpm的workplace和Lerna,还有monorepo,所以想着又又又搭建一个Vue3项目的monorepo仓库。
旧的做法
在没有使用monorepo的情况下,选择了多代码库(multirepos),其实就是每个子项目单独一个git仓库,而公共api模块和公共组件模块也是一个git仓库,使用npm的file方式引入。
如package.json代码所示,使用npm install ../common/
就可以引入。
// package.json
{
"name": "project-name",
"version": "0.1.0",
"dependencies": {
"common": "file:../common"
}
//...
}
但十分难受的是,如果修改了common模块的代码,需要再跑一次npm install
,而且可能需要把子项目node_modules
下的common文件夹删了再安装才行,或许是需要修改common模块的版本version才行吧。
每次修改common模块的代码都要安装一次,真的太麻烦了。而且因为common模块为独立的git仓库,会存在其他同事代码未提交,导致其他子项目报错的问题。并且每完成一个完整的功能,多个仓库也需要分别提交代码,也是相对麻烦的。
开始搭建
创建根目录项目
Vue3新的官方文档上线之后,才知道可以用npm init vue@3
创建项目,基本可以vue-cli
一样,都是可选各类配置。
这里选择了vue-router
、pinia
、eslint
,没有选ts
,大家可以根据需要自选。
项目初始化之后,需要打开终端执行pnpm i
,然后按照pnpm官网的说法,新建pnpm-workspace.yaml
文件
packages:
# 子项目模块
- 'packages/*'
# 全局组件模块
- 'components/**'
# api请求模块
- 'apis/**'
# 公共方法模块
- 'utils/**'
# exclude packages that are inside test directories
- '!**/test/**'
在项目根目录新建packages
文件夹,packages/*
是子项目模块的文件夹,里面放子项目的代码,后续依旧是使用npm init vue@3
初始化。
'components/**'
,'apis/**'
,'utils/**'
这三个模块可以使用vite
初始化
使用vite
初始化模块
可以使用vite
创建单纯的js
项目,相对简约一些。
api请求模块
打开终端,使用pnpm create vite
创建apis模块,项目名称是apis
,接着选择Vanilla
和JavaScript
✔ Project name: … apis
✔ Select a framework: › Vanilla
✔ Select a variant: › JavaScript
然后对项目进行删减,把不需要的文件删除,然后新建index.js
、request.js
文件和modules
文件夹。
在apis文件夹打开终端安装axios
,pnpm i axios -S
二次封装axios
的文章太多了,这里就简单地做请求拦截和响应拦截就完了,大家可以在掘金找到合适的封装方式,或者了解开源项目的封装方式,实现自己的需求。
request.js
代码如下
import axios from "axios";
const http = axios.create({
baseURL: "",
timeout: 1000 * 60,
withCredentials: true
});
// 请求拦截
http.interceptors.request.use((config) => {
// 防止缓存,GET请求默认带_t参数
if (config.method === "get") {
config.params = {
...config.params,
...{ _t: new Date().getTime() },
};
}
return config;
},
(error) => {
return Promise.reject(error);
}
);
// 响应拦截
http.interceptors.response.use((response) => {
if (response.data.code === 401 || response.data.code === 10001) {
return Promise.reject(response.data.msg);
}
return response;
},
(error) => {
return Promise.reject(error);
}
);
export default http;
在modules文件夹下创建用户模块的请求,新建users.js
文件,代码如下
import http from '../request'
export const findAll = (params) => {
return http({
url: '/api/users/findAll',
method: 'get',
params
})
}
最后在index.js
文件中引入并导出users模块,代码如下
import * as users from './modules/users'
export default {
users
}
在项目中引入使用
可以使用pnpm add apis
的方式引入,但尝试后发现会安装到npm社区的包,所以建议修改apis中package.json
文件的name。
比如修改为@project/apis
,再引入pnpm add @project/apis
就可以了.
可以看到根目录的package.json
中多了"@project/apis": "workspace:^0.0.1",
,附带了apis模块的版本号,也可以修改为"@project/apis": "workspace:*",
这时候可以新建vue
文件,在onMounted
的时候调用请求,在控制台有请求发出,那就已经成功了。
可以配合我之前的NestJS文章,搭建简单的后端测试效果
全局组件模块
和上面一样,依旧是vite
创建项目,选择vue
的模板
npm create vite
Need to install the following packages:
create-vite
Ok to proceed? (y)
✔ Project name: … components
✔ Select a framework: › Vue
✔ Select a variant: › JavaScript
这里选择使用element-plus
,根目录项目和用到组件模块的项目都建议安装。接着删减不需要的文件和目录,并在src
目录下新建vue
组件。
依旧是需要在index.js
文件中进行导出,可以看到这里加了一个name
属性,是作为全组注册组件的名称使用,也可以使用文件名称,export
出去的模块有个__name
属性可以作为组件名称使用。
import TestBtn from "./src/testBtn/index.vue";
TestBtn.name = "testBtn";
export default { TestBtn };
export {
TestBtn
}
自动注册全局组件
Vue项目中的实用技巧记录 - 掘金 (juejin.cn),这篇文章中有webpack
和vite
,如何在vue项目中自动注册全局组件的案例,并且使用到ts。
使用之前需要安装组件模块,和上面的api模块一样,需要修改package.json
文件的name,然后pnpm add @project/components
,如果是按需引入,在vue
组件中import { TestBtn } from '@project/components'
即可。
下面是全局注册的做法,在项目根目录中新建autoRegistCompontents.js
,引入所有组件并全局注册,代码如下。
import gobalComponents from '@project/components'
import { defineComponent } from "vue";
const autoRegist = {
install(app) {
for (const key in gobalComponents) {
const component = gobalComponents[key]
const name = component.name
app.component(name, defineComponent(component));
}
}
}
export default autoRegist
最后在mian.js
中调用autoRegist
的注册方法。
import autoRegist from "./autoRegistCompontents";
app.use(autoRegist)
在项目中使用
直接调用即可
<test-btn></test-btn>
utils模块
和api模块类似,这里就不赘述了,可以直接看git的代码
子项目搭建
子项目需要在packages文件夹下初始化,作为独立项目开发使用,需要把上面的模块通通引入。
pnpm add @project/components
pnpm add @project/apis
pnpm add @project/utils
复制autoRegistCompontents.js
到项目中,并在main.js
中使用。
子项目代码如下
packages/system · Elvis/monorepo-workplace - 码云 - 开源中国 (gitee.com)
总结
monorepo解决了微前端或多个前端项目可以在一个git仓库管理的问题,提取各项目的公用部分成为单独模块,减少了多个项目组件模块,api请求模块代码大量重复问题。不仅适用于微前端,若是有多个项目有大量公用代码重复,且又是独立的git仓库管理,可考虑改用monorepo的git管理方式。
完整代码如下
monorepo-workplace: pnpm的workplace项目 (gitee.com)
文章推荐
Nestjs入门,使用nest-cli创建项目并新建接口 - 掘金 (juejin.cn)