一次项目合并经历

我所在的组有很多项目,其中一个是对外供用户使用的以下简称项目A,还有一个是对内进行资源管理提高效率的以下简称项目B。项目Acss解析用postcss,ui组件用element ui,项目B css解析用less,ui组件使用内部开发的一套ui库。

接到一个需求:同事辛辛苦苦做的在A项目中的某个功能(六七个页面)能不能一股脑的嵌入B项目呢?最好不用开发,你们前端不都是Vue 组件么?复用一下噻?

刚接到需求的时候大脑里跑过了千万匹🐴,但是遇到困难不能躲啊。冷静思考一下,先iframe被排除了,因为iframe只能整体的嵌入,而我们想要的可能只是页面中的一部分。第一次尝试把A整个项目手动copy到B项目中,通过相对路径来引用。最开始的报错是postcss解析报错,费了半天劲解决后就是,js重名,css覆盖,字体冲突。总结一下遇到的问题list 如下:

  1. postcss loader配置失败
  2. 嵌入A后A全局样式污染B全局样式
  3. B中嵌入的ui库和A的element组件冲突 (e.g. v-loading)
  4. 登录状态如何保持
  5. webpack alias重名,都叫utils,都叫components
  6. A引入B后样式丢失
  7. 自定义的组件覆盖了el样式
  8. B中的字体库和element中的冲突了(content: “\e69a”显示了不同的图标)
  9. build failed

解决方法

  1. vue-loader的设置不熟悉,按照官网的配置不生效。原来vue文件在解析的时候会根据language解析成不同后缀名的文件。只需要 { test: /\.postcss$/, use : cssLoaders('postcss') } 即可。
  2. 如我们所知A中有很多全局样式,引入部分页面缺了这部分全局样式又没法正常渲染,借助postcss-plugin-namespace可以给postcss的文件加一个前缀,确保不因小失大,污染整个B。
  3. 因为element中的组件比内部开发的组件库健壮的多,大部分都是element覆盖之。
  4. A中页面要想正常工作首先是以登录为前提的。还有一条路就是在api上带上某个特定标识,由此也引发了一个小问题。需要改变location search,url会replace,刷新页面。还可以优化。
  5. A中的webpack alias我不敢改,我只能委曲求全改B中的,改成不重名的。
  6. A依赖了好多全局样式,一个一个引入。有些B中的样式跟A中的确实是冲突,确实影响到了。只好自己调整调整,但是需要调整的量很小,就两三处。
  7. 有同事把element的源码拿到项目中使用。而且还稍加改动了css。删掉就好了。
  8. 要想让A中页面正常渲染图标也必不可少,但是element中的字体是font-family: element-icons!important;非常强暴的把所有的图标都用自己的这套字体库。没办法,只好也把我们自己的字体库也加上了!important。
  9. 最终以submodule的方式引入A。A中的.postcssrc.js 和B全局的冲突了。按照官方的options配置,但是还是没成功,只好在gitlab hook中删掉submodule中的.postcssrc.js。这样不好,但是能work。(https://github.com/postcss/postcss/issues/1295)

思考

最终不是太完美的上线了,还有一些地方可以优化。
虽然嵌入的Acss样式不会影响B全局,但是B全局的样式还是会影响嵌入的A样式。
js方法最好能互不影响。

微前端的材料看了不少,但还是没找到小成本能实现的方式,可能需要在规划两个或多个项目时就已经想好了实现的方式,有主项目,有include项目等等。对于两个已经成熟的项目如何互相include,甚至不同框架的项目怎么融合,啊~啊~啊~,这个题超纲了。

参考资料

https://tech.meituan.com/2018/09/06/fe-tiny-spa.html

https://forum.vuejs.org/t/advice-to-organize-multiple-vue-projects/15078