现如今,前端开发基本离不开模块化了,那么多项目的组件共用就会变成一个比较头疼的问题,很多人都习惯ctrl c和ctrl v,这样容易导致项目中后期维护困难,我们当然也不能这么low,早期在项目开发中我也探索了几个组件共用的方案。
解决方案
方案一 cdn/服务器
使用cdn引入组件的方案应该是减少打包时间以及访问时间最显著的方案了,但是缺点也非常明显,就是组件频繁更新时,需要频繁刷新cdn。
将打包好的组件文件放在服务器上同理,更新频繁的时候也是需要频繁更新服务器上的文件,不方便。
方案二 发布至npm
我最早的时候也是把很多组件文件发布至npm上,这样组员可以很方便的获取组件资源,但是问题亦非常明显,首先,npm的访问速度不稳定,很多时候需要借助某些上网手段,其次,频繁更新npm,也会带来一长串的版本号,发布的时候也非常的麻烦;而使用国内镜像源,又需要等待镜像同步,也比较耗时;至于发布至npm私服,我估计大部分中小公司都没有建立npm私服。
方案三 使用git submodule
git可以使用git submodule直接将一个git仓库当做子模块放在项目中,只需要
git submodule add <url> <path>
其中,url为子模块的路径,path为该子模块存储的目录路径。 该方法的一大问题是git submodule使用起来异常的繁琐,比如删除,甚至没有一个专门的命令,必须借助一系列操作才能完成,最后考虑到项目组成员接受度的问题,放弃了这个方案。
方案四 在package.json依赖中使用git地址
这个方案是我目前依然在使用的最好的方案,没有额外的学习成本,封装好后使用方便,下面将详细介绍次方案。
以vue-cli项目为例(react项目原理一模一样,自己套用即可)
文件结构
vue项目的主要文件结构如以下所示
├─src
| └─components
| └─IframeCom
| └─index.vue
├─package.json
├─script.js
├─vue.config.js
其中,components是放置于src文件夹下的组件文件夹,IframeCom是其中的一个组件文件夹,里面的index.vue即为暴露出的IframeCom的组件文件。
生成导出入口的脚本
script.js文件为写入导出文件的脚本文件,其内容如下:
const fs = require('fs');
const path = require('path');
// 生成导出文件
fs.readdir(path.join(__dirname, './src/components'), function (err, files) {
if (err) {
console.log('目录不存在')
return
}
// 设置时间以提交git
let content = `/*${new Date()}*/`
let ex = []
// 处理导出代码
files.forEach(item => {
// 读取目录名
content = content + `import ${item} from './components/${item}';`
ex.push(item)
})
ex = ex.join(",")
content = content + `export { ${ex} }; `
fs.writeFile(path.join(__dirname, './src/index.js'), content, 'utf8', (err) => {
if (err) throw err;
});
})
执行
node script.js
即可在src的目录下生成一个index.js文件,此文件即为导出组件的入口,内容如下(写入时间注释是为了确保git commit一定有东西提交):
/*Tue Jun 09 2020 14:07:43 GMT+0800 (GMT+08:00)*/import IframeCom from './components/IframeCom';export { IframeCom };
vue.config.js设置
因为组件一般样式比较少,所以直接打包进js中,在vue.config.js中写入
module.exports = {
css: { extract: false }
};
package.json设置
之后在package.json文件中写好打包命令:
{
"name": "compoment-demo",
"version": "0.1.2",
"private": false,
"main": "lib/pikaz-compoment.umd.min.js",
"scripts": {
"lib": "vue-cli-service build --target lib --name pikaz-compoment --dest lib src/index.js",
"serve": "vue-cli-service serve",
"push": "node script.js && npm run lib && git add . && git commit -m 'commit' && git push"
}
}
其中的lib命令
"vue-cli-service build --target lib --name compoment-demo --dest lib src/index.js"
为打包库的命令,--name后面跟着的compoment-demo是库的名称,随便填写,最后的src/index.js为项目入口,指定为src目录下的index.js文件即可。
再写一个上传git仓库的命令(需之前已连接远程仓库)
"push": "node script.js && npm run lib && git add . && git commit -m 'commit' && git push"
即先执行script.js文件生成库入口index.js文件,再执行打包库的命令,最后上传至git,一步到位,简化操作。
主项目的package.json设置
{
"name": "project-demo",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "npm install compoment-demo && vue-cli-service build"
},
"dependencies": {
"compoment-demo": "git+https://github.com/pikaz-18/compoment-demo.git",
"core-js": "^3.6.5",
"vue": "^2.6.11"
}
}
在dependencies依赖中写入组件库的地址,格式为git+git仓库地址,之后只需执行npm install compoment-demo即可安装与更新项目依赖,并将此命令写入打包命令中,确保每一次打包使用的组件库依赖都为最新的。
主项目中组件的使用
<template>
<div class="demo">
<iframe-com></iframe-com>
</div>
</template>
<script>
import { IframeCom } from 'compoment-demo'
export default {
name: 'App',
components: {
IframeCom
}
}
</script>
和普通的组件一样的使用方法
项目demo地址
优点
最大的优点便是使用便捷,组件项目执行一个命令即可完成打包上传,不需要进行额外操作,主项目在打包的时候也可以实时更新组件库,使用时完全无感知,并且大部分公司都有搭建gitlab等,再不济也可以使用码云,使用成本可以说是非常低,更新速度也非常快。
最后
这仅仅是一个简易的组件共用demo,大家可以根据自己的项目需求去完善。你甚至可以把整个项目当做库导出,将每个页面当做基本组件,从而将多个项目的页面自由组合成一个saas系统,而且该方案并没有太大的侵入性,改造旧项目也是轻而易举,再也不用担心老板想要一个项目加入其他项目已有的功能而烦恼了,彻底扔掉无脑cv吧。
不过如果项目过大时,此方案也会带来打包时间过长,项目臃肿等问题,这个时候可能就需要使用微前端了。
如果觉得对你有帮助的话,不妨点个赞吧。