微前端的选型,暂不考虑,qiankun作为微前端的一种融合方式,目前也比较成熟,但是由于各类开发技术选型非常繁多,导致了在项目中配置不同,解决别人的问题,不一定能解决自己的问题。例如:
- 使用的js框架的不同或版本的不同:vue/react 等,vue2/vue3 等
- ui组件库版本的不同,以element为例,大版本上可分为element-ui/element-plus,小版本就更多了。
- 打包工具的不同,比如常用的 webpack/vite等
- 各类插件版本的不同,比如,node的版本,webpack的版本,vite的版本,node-sass/sass-loader的版本等
本文仅记录项目开发过程中遇到的一些坑,和如何解决的。希望能在你迷茫的时候有所帮助。同时也呼吁小伙伴们,也能养成记录的习惯。 宁滥毋缺
。好了,说了很多废话,下面回归正题。
场景一 主应用和子应用使用了不同版本的组件库
1. 版本库
1. 主应用依赖包版本
"dependencies": {
"axios": "^1.3.2",
"element-plus": "^2.2.30",
"qiankun": "^2.10.2",
"vue": "^3.2.13",
},
"devDependencies": {
"postcss": "^7.0.0",
"postcss-change-css-prefix": "^1.0.4",
"postcss-loader": "^7.3.0",
"sass": "^1.32.7",
"sass-loader": "^12.0.0",
"sass-resources-loader": "^2.2.5",
"typescript": "~4.5.5",
"webpack-dev-server": "^4.0.0-beta.0"
}
2. 子应用依赖包版本
// todo
2. 基于qinkun的样式隔离
qiankun针对样式隔离主要通过沙箱的方式,参考官方api说明。
通过这种方式,在不引用组件库的情况下,看似很完美,实则也挑不出什么毛病,但是引用了组件库后。组件库有些组件是通过jsx语法生成并插入到body节点后,例如(Popover、内置了popover的select/datapicker等组件)便会出现主应用全局样式会影响到子应用。
3. 组件库的命名空间
为了解决主应用对子应用的样式覆盖和影响,组件库引入命名空间。下面提供了webpack 和 vite的两种配置方式,官网配置提供了vite的完整配置。针对webpack的配置提供了一种思路,需要自己查阅文档进行配置,下面提供完整配置
- 添加全局配置:
namespace
增加了主应用的命名空间,替换了所有的组件样式,但是通过js生成的组件,例如:el-message、el-message-box、el-loading,没有生效,需要在引入element-plus时,配置namespace,参考 github.com/element-plu…
<!-- main.ts -->
import App from './App.vue';
import ElementPlus from 'element-plus';
const app = createApp(App);
app.use(ElementPlus, {
locale: zhCn,
namespace: 'main-el'
})
- 使用
ElConfigProvider
包装您的根组件。
<!-- App.vue -->
<template>
<el-config-provider namespace="ep">
<!-- ... -->
</el-config-provider>
</template>
- 设置 SCSS 和 CSS 变量
创建
styles/element/index.scss
:
// styles/element/index.scss
// we can add this to custom namespace, default is 'el'
@forward 'element-plus/theme-chalk/src/mixins/config.scss' with (
$namespace: 'ep'
);
// 配置主题色,根据项目需要。
@forward 'element-plus/theme-chalk/src/common/var.scss' with (
$colors: (
'primary': (
'base': #009982,
),
),
);
注意:引入路径不同,对应不同的配置,这里我还配置了主题色
#009982
,forward的一个变量地址。
- vite构建方式,需要修改
vite.config.ts
文件,在vite.config.ts
中导入styles/element/index.scss
:
import { defineConfig } from 'vite'
// https://vitejs.dev/config/
export default defineConfig({
// ...
css: {
preprocessorOptions: {
scss: {
additionalData: `@use "~/styles/element/index.scss" as *;`,
},
},
},
// ...
})
- webpack构建方式,需要修改
vue.config.js
文件,在vue.config.js
中导入styles/element/index.scss
:
const { defineConfig } = require('@vue/cli-service');
// https://cli.vuejs.org/zh/config/#css-modules
module.exports = defineConfig({
// ...
css: {
loaderOptions: {
sass: {
additionalData: `@import "./src/styles/element/index.scss";`,
// Note: this option is named as "prependData" in sass-loader v8
// prependData: `@import "./src/styles/element/index.scss";`,
},
},
},
// ...
})
注意:
- 根据sass-lodader的版本,需要选择不同的属性
additionalData
、prependData
- 根据sass-lodader的版本,需要选择不同的引入方式(
@import
/@use
)- 根据预编译处理器选择对应的
sass
或者scss
配置
4. 主应用全局组件的样式添加
<!-- main.ts -->
import App from './App.vue';
import ElementPlus from 'element-plus';
const app = createApp(App);
app.use(ElementPlus, {
locale: zhCn,
namespace: 'main-el'
})
场景二 主应用和子应用使用相同版本的组件库
// todo
参考文档
1. qiankun官网
2. element-plus 自定义命名空间
3. vue Cli 配置文档
4. vite配置(官网)
5. webpack配置(官网)