import { registerMicroApps, start, initGlobalState } from 'qiankun';
let propsData = {
}
const actions = initGlobalState(propsData);
// 主项目项目监听和修改(在项目中任何需要监听的地方进行监听)
actions.onGlobalStateChange((state, prev) => {
// state: 变更后的状态; prev 变更前的状态
console.log('改变前的值 ', prev);
console.log('改变后的值 ', state);
});
// 将actions对象绑到Vue原型上,为了项目中其他地方使用方便
Vue.prototype.$actions = actions;
const apps = [
{
name: 'webuiApp', // 应用的名字
entry: 'https://localhost:997/index.html?remote=https://10.119.167.102#/index/overall_monitoring', // 默认会加载这个html 解析里面的js 动态的执行 (子应用必须支持跨域)fetch
container: '#webui', // 容器名
activeRule: '/main/webui', // 激活的路径
props: propsData,
},
{
name: 'easydeployApp',
entry: 'http://127.0.0.1:3100', // 默认会加载这个html 解析里面的js 动态的执行 (子应用必须支持跨域)fetch
container: '#easy',
activeRule: '/main/easydeploy',
props: propsData,
},
{
name: 'vueApp',
entry: 'https://localhost:8080', // 默认会加载这个html 解析里面的js 动态的执行 (子应用必须支持跨域)fetch
container: '#vue',
activeRule: '/main/vue',
props: propsData,
}
]
//注册子应用,在子应用激活时,创建运行沙箱,不同阶段调用不同的生命周期函数
//bootstrap - 初始化子应用,mount - 挂载子应用,unmount - 卸载子应用
registerMicroApps(apps, {
// qiankun 生命周期钩子 - 微应用加载前
beforeLoad: (app) => {
// 加载微应用前,加载进度条
NProgress.start();
console.log("before load", app.name);
return Promise.resolve();
},
// qiankun 生命周期钩子 - 微应用挂载后
afterMount: (app) => {
// 加载微应用前,进度条加载完成
NProgress.done();
console.log("after mount", app.name);
return Promise.resolve();
},
}); // 注册应用
//预加载需要全局监听,在挂载第一个应用后预加载其他子应用的资源
//window.__POWERED_BY_QIANKUN__ 为true,在子应用判断是否运行在主应用容器中
start({
prefetch: false // 取消预加载
});// 开启
<el-container>
<!-- 左侧导航 -->
<el-aside>
<el-menu
default-active="1"
class="el-menu-vertical-demo"
background-color="#545c64"
text-color="#fff"
:router="true"
>
<el-menu-item index="/main/webui">
<i class="el-icon-document"></i>
<span slot="title">深信服SD-WAN安全智能路由器</span>
</el-menu-item>
<el-menu-item index="/main/easydeploy">
<i class="el-icon-setting"></i>
<span slot="title">云端易部署</span>
</el-menu-item>
<el-menu-item index="/main/vue">
<i class="el-icon-setting"></i>
<span slot="title">Vue2测试页面</span>
</el-menu-item>
</el-menu>
</el-aside>
<el-container>
<!-- 内容 -->
<el-main>
<router-view></router-view>
<div id="webui"></div>
<div id="easy"></div>
<div id="vue"></div>
</el-main>
</el-container>
</el-container>
路由
import Main from '../views/Main';
Vue.use(VueRouter)
const routes = [
{
path: '/main/*',
name: 'Main',
component: Main,
}
]
const router = new VueRouter({
mode: 'history',
// base: process.env.BASE_URL,
base: '',
routes
})
export default router
lerna.json lerna配置
{
“packages”: [“packages/"],
“npmClient”: “yarn”,
“useWorkspaces”: true,
“version”: “0.0.1”,
“ignoreChanges”: ["**/.md”],
“bootstrap”: {
“npmClientArgs”: ["–no-package-lock", “–force-local”]
}
}
package.json
```typescript
{
"name": "SDWR",
"private": true,
"scripts": {
"add-dep": "lerna add",
"add-dep:webui": "lerna add --scope=@sdwr/webui",
"init:dep": "yarn install && lerna bootstrap && yarn build && yarn dev:webui",
"clean:dep": "yarn clean:sub-dep && rm -rf node_modules",
"clean:sub-dep": "lerna clean -y",
"reinstall:dep": "yarn clean:dep && yarn init:dep",
"dev": "cross-env JOINT_DEBUGGING=1 yarn dev:webui",
"dev:webui": "yarn kill-ports 997 && yarn cp-dep:webui && yarn run-script dev --scope=@sdwr/webui",
"build": "yarn build:util && yarn build:common && yarn build:components && yarn build:idb && yarn build:webui",
"build:components": "yarn cp-dep:components && yarn run-script build --scope=@sdwr/webui-component",
"build:webui": "yarn cp-dep:webui && yarn run-script build --scope=@sdwr/webui",
"build:util": "yarn cp-dep:components && yarn run-script build --scope=@sdwr/webui-util",
"build:common": "yarn cp-dep:common && yarn run-script build --scope=@sdwr/webui-common",
"build:idb": "yarn run-script build --scope=@sdwr/idb",
"cp-dep": "yarn cp-dep:webui",
"cp-dep:webui": "cp -rn node_modules/less-loader/ packages/webui_base/node_modules/",
"cp-dep:components": "cp -rn node_modules/less-loader/ packages/webui_component/node_modules/",
"cp-dep:util": "cp -rn node_modules/less-loader/ packages/webui_util/node_modules/",
"cp-dep:common": "cp -rn node_modules/less-loader/ packages/webui_common/node_modules/",
"run-script": "lerna run --stream --no-prefix",
"run-script:serial": "yarn run-script --concurrency 1",
"run-script:serial-only-change": "yarn run-script:serial --since HEAD --exclude-dependents",
"kill-ports": "kill-port --port",
"test": "jest",
"eslint": "yarn run-script eslint",
"eslint-fix": "yarn run-script eslint-fix",
"stylelint": "yarn run-script stylelint",
"stylelint-fix": "yarn run-script stylelint-fix",
"pre-commit": "npx ls-lint && yarn run-script:serial-only-change pre-commit"
},
"dependencies": {
"babel-runtime": "^6.26.0",
"@sxf/i18n": "1.0.12",
"@sxf/intl-polyfill": "~1.2.0",
"@sxf/sf-theme": "~0.1.17",
"@sxf/vue-intl": "~1.9.1",
"axios": "~0.20.0",
"js-sha256": "~0.9.0",
"jsrsasign": "~10.3.0",
"lodash-es": "4.17.11",
"uuid": "~8.3.2",
"vue": "2.6.12",
"vue-class-component": "~7.1.0",
"vue-property-decorator": "~9.0.0",
"@vue/babel-helper-vue-jsx-merge-props": "~1.2.1",
"@vue/babel-preset-jsx": "~1.2.4",
"core-js": "~3.12.0",
"@sxf/sf-vue-component": "~2.20.12",
"@types/clone": "^0.1.30",
"clone": "^2.1.2",
"copy": "^0.3.2",
"path-browserify": "^1.0.1",
"shelljs": "^0.8.3"
},
"devDependencies": {
"@babel/core": "~7.4.5",
"@babel/plugin-proposal-nullish-coalescing-operator": "~7.14.5",
"@babel/plugin-proposal-optional-chaining": "~7.14.5",
"@babel/preset-env": "~7.12.7",
"@babel/preset-typescript": "~7.12.7",
"@babel/plugin-syntax-jsx": "^7.0.0",
"babel-eslint": "^10.0.1",
"babel-helper-vue-jsx-merge-props": "^2.0.3",
"babel-plugin-syntax-jsx": "^7.0.0-beta.3",
"@commitlint/cli": "~12.1.4",
"@commitlint/config-conventional": "~12.1.4",
"@jest/types": "~27.0.6",
"@ls-lint/ls-lint": "~1.9.0",
"@sxf/eslint-config-idux": "~0.0.12",
"@sxf/eslint-plugin-i18n": "~0.0.5",
"@sxf/eslint-plugin-i18n-next": "~0.3.1",
"@types/jest": "~26.0.24",
"@types/jsrsasign": "^8.0.1",
"@types/node": "~16.3.2",
"@types/uuid": "^8.3.1",
"@typescript-eslint/eslint-plugin": "~4.28.3",
"@typescript-eslint/parser": "~4.28.3",
"@uedc/api-utils": "~0.14.0",
packages
webui_base
{
"name": "@sdwr/webui",
"private": true,
"version": "1.0.0",
"description": "",
"main": "index.js",
"repository": {
"type": "git",
"url": "[email protected]:13594/learn.git"
},
"scripts": {
"build": "npm run update:url-map && npm run eslint && sfx2 build",
"dev": "sfx2 dev",
"test": "node --max-old-space-size=8192 ./node_modules/jest/bin/jest --maxWorkers=50% --all --passWithNoTests --detectOpenHandles",
"test:change": "node --max-old-space-size=8192 ./node_modules/jest/bin/jest --maxWorkers=50% -o --passWithNoTests --detectOpenHandles",
"test:ci": "node --max-old-space-size=8192 ./node_modules/jest/bin/jest --runInBand --all --passWithNoTests --silent --ci --detectOpenHandles",
"test:dev": "node --max-old-space-size=8192 ./node_modules/jest/bin/jest --maxWorkers=25% --passWithNoTests --detectOpenHandles --watch",
"eslint": "eslint --ext .vue,.js,.ts src",
"fix": "eslint --ext .vue,.js,.ts src --fix",
"count_component_usage_frequency": "node ./build/scanning_component_usage_frequency.js sf-,sdwr- ../dist/static/js ../usage_frequency.json",
"update:url-map": "node ./build/auto_create_url_map.js"
},
"devDependencies": {
"@babel/helper-module-imports": "~7.0.0",
"@babel/plugin-syntax-dynamic-import": "~7.2.0",
"@babel/plugin-syntax-jsx": "~7.0.0",
"@babel/plugin-transform-runtime": "~7.4.4",
"@babel/runtime": "~7.4.5",
"@babel/runtime-corejs2": "~7.4.5",
"@sxf/tpl-loader": "~1.1.1",
"@types/echarts": "~4.6.5",
"@types/jest": "~26.0.23",
"@types/store": "~2.0.2",
"autoprefixer": "~9.6.0",
"babel-plugin-transform-es2015-modules-commonjs": "~6.26.2",
"babel-plugin-transform-strict-mode": "6.24.1",
"babel-polyfill": "~6.26.0",
"babel-preset-es2015": "6.24.1",
"babel-preset-stage-0": "6.24.1",
"css-loader": "~4.2.2",
"fake-indexeddb": "~3.1.2",
"file-loader": "~6.1.0",
"jest-canvas-mock": "~2.3.1",
"jsdom": "~16.4.0",
"jsdom-global": "~3.0.2",
"parse-comments": "~1.0.0",
"prettier": "~2.3.1",
"style-loader": "~1.2.1",
"sugarss": "~2.0.0",
"url-loader": "~4.1.0",
"vue-hot-reload-api": "2.3.4",
"vue-template-compiler": "2.6.12"
},
"dependencies": {
"@babel/plugin-proposal-class-properties": "~7.5.5",
"@babel/plugin-proposal-decorators": "~7.4.4",
"@babel/plugin-proposal-object-rest-spread": "~7.5.4",
"@sdwr/webui-common": "~0.0.1",
"@sdwr/webui-component": "~0.0.1",
"@sdwr/webui-util": "~0.0.1",
"@sxf/pineapple": "~2.7.10",
"@uedc/login": "1.0.6",
"axios": "~0.20.0",
"echarts": "~4.6.0",
"highcharts": "5.0.6",
"idb": "~6.1.2",
"store": "~2.0.12",
"ts-loader": "~8.0.3",
"typescript": "~4.1.5",
"v-viewer": "~1.4.0",
"vue-loader": "~15.9.0",
"vue-router": "~3.0.6",
"vuex": "~3.6.2",
"webpack": "~4.41.5",
"wind-dom": "0.0.3"
},
"keywords": [],
"author": "",
"license": "ISC",
"husky": {
"hooks": {
"pre-commit": "ls-lint && lint-staged && npm run eslint && yarn test:change",
"commit-msg": "npx --no-install commitlint --edit \"$1\""
}
},
"lint-staged": {
"*.{json}": [
"prettier --write"
],
"*.{js,ts,vue}": [
"eslint --fix"
]
},
"vetur": {
"tags": "./build/global_components/tags.json",
"attributes": "./build/global_components/attributes.json"
}
}
业务中应用
import { openDB } from ‘…/…/…/webui_idb/dist/index.js’;
webui_common
公共的过滤函数,全局变量等
webui_component
webui的自身组件库
拥有install方法。Vue.component 全局注册
webui_idb
支持ie11 的idb库
webui_util
util函数
# 副业务应用(vue3)
支持vue3 需要一个插件vite_plugin_qiankun
```typescript
'use strict';
var cheerio = require('cheerio');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var cheerio__default = /*#__PURE__*/_interopDefaultLegacy(cheerio);
var createQiankunHelper = function (qiankunName) { return "\n const createDeffer = (hookName) => {\n const d = new Promise((resolve, reject) => {\n window.proxy && (window.proxy[`vite${hookName}`] = resolve)\n })\n return props => d.then(fn => fn(props));\n }\n const bootstrap = createDeffer('bootstrap');\n const mount = createDeffer('mount');\n const unmount = createDeffer('unmount');\n\n ;(global => {\n global.qiankunName = '" + qiankunName + "';\n global['" + qiankunName + "'] = {\n bootstrap,\n mount,\n unmount,\n };\n })(window);\n"; };
var createImportFinallyResolve = function (qiankunName) {
return "\n const qiankunLifeCycle = window.moudleQiankunAppLifeCycles && window.moudleQiankunAppLifeCycles['" + qiankunName + "'];\n if (qiankunLifeCycle) {\n window.proxy.vitemount((props) => qiankunLifeCycle.mount(props));\n window.proxy.viteunmount((props) => qiankunLifeCycle.unmount(props));\n window.proxy.vitebootstrap(() => qiankunLifeCycle.bootstrap());\n }\n ";
};
var htmlPlugin = function (qiankunName) {
var isProduction;
return {
// enforce: 'post',
name: 'qiankun-html-transform',
configResolved: function (config) {
isProduction = config.command === 'build' || config.isProduction;
"http://127.0.0.1:" + (config.server.port || 3000) + config.base;
},
transformIndexHtml: function (html) {
var $ = cheerio__default['default'].load(html);
var moduleTags = $('script[type=module]');
if (!moduleTags || !moduleTags.length) {
return;
}
moduleTags.each(function (i, moduleTag) {
var script$ = $(moduleTag);
var moduleSrc = script$.attr('src');
if (isProduction) {
script$.removeAttr('src');
script$.removeAttr('type');
script$.html("import('" + moduleSrc + "').finally(() => {\n " + createImportFinallyResolve(qiankunName) + "\n })");
return;
}
});
$('body').append("");
var output = $.html();
return output;
},
};
};
module.exports = htmlPlugin;
即可支持
ViteQiankunPlugin(‘easydeployApp’)