commit
37b63f1c0e
18 changed files with 7377 additions and 0 deletions
Split View
Diff Options
-
3.browserslistrc
-
21.gitignore
-
41README.md
-
23package.json
-
BINpublic/favicon.ico
-
17public/index.html
-
32src/App.vue
-
10src/api/index.js
-
BINsrc/assets/logo.png
-
57src/components/HelloWorld.vue
-
95src/main.js
-
5src/public-path.js
-
25src/router/index.js
-
76src/utils/request.js
-
5src/views/About.vue
-
22src/views/Home.vue
-
52vue.config.js
-
6893yarn.lock
@ -0,0 +1,3 @@ |
|||
> 1% |
|||
last 2 versions |
|||
not dead |
|||
@ -0,0 +1,21 @@ |
|||
.DS_Store |
|||
node_modules |
|||
/dist |
|||
|
|||
# local env files |
|||
.env.local |
|||
.env.*.local |
|||
|
|||
# Log files |
|||
npm-debug.log* |
|||
yarn-debug.log* |
|||
yarn-error.log* |
|||
|
|||
# Editor directories and files |
|||
.idea |
|||
.vscode |
|||
*.suo |
|||
*.ntvs* |
|||
*.njsproj |
|||
*.sln |
|||
*.sw? |
|||
@ -0,0 +1,41 @@ |
|||
# 微前端、微应用 |
|||
|
|||
## 作为单独项目开始 |
|||
|
|||
```bash |
|||
yarn serve |
|||
``` |
|||
|
|||
## 接入主服务 |
|||
|
|||
将下面的路由接入主服务中: |
|||
|
|||
```js |
|||
import { RouteView } from '@/layouts' |
|||
// 测试微前端 |
|||
export default { |
|||
path: '/testMicro/index', |
|||
component: RouteView, |
|||
name: 'testMicro', |
|||
redirect: '/testMicro', |
|||
meta: { title: '测试微前端', keepAlive: false }, |
|||
children: [ |
|||
{ |
|||
path: '/testMicro', |
|||
name: 'testMicroHome', |
|||
meta: { title: '测试微前端home', keepAlive: true, icon: 'home', hiddenHeaderContent: true } |
|||
}, |
|||
{ |
|||
path: '/testMicro/about', |
|||
name: 'testMicroAbout', |
|||
meta: { title: '测试微前端about', keepAlive: true, icon: 'home', hiddenHeaderContent: true } |
|||
}, |
|||
] |
|||
} |
|||
``` |
|||
|
|||
## 编译 |
|||
|
|||
```bash |
|||
yarn build |
|||
``` |
|||
@ -0,0 +1,23 @@ |
|||
{ |
|||
"name": "test-micro", |
|||
"version": "0.1.0", |
|||
"private": true, |
|||
"scripts": { |
|||
"serve": "vue-cli-service serve", |
|||
"build": "vue-cli-service build" |
|||
}, |
|||
"dependencies": { |
|||
"ant-design-vue": "^1.5.6", |
|||
"axios": "^0.19.2", |
|||
"utils": "^1.5.0", |
|||
"vue": "^2.6.11", |
|||
"vue-router": "^3.1.6" |
|||
}, |
|||
"devDependencies": { |
|||
"@vue/cli-plugin-router": "~4.3.0", |
|||
"@vue/cli-service": "~4.3.0", |
|||
"less": "^3.0.4", |
|||
"less-loader": "^5.0.0", |
|||
"vue-template-compiler": "^2.6.11" |
|||
} |
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
<!DOCTYPE html> |
|||
<html lang="en"> |
|||
<head> |
|||
<meta charset="utf-8"> |
|||
<meta http-equiv="X-UA-Compatible" content="IE=edge"> |
|||
<meta name="viewport" content="width=device-width,initial-scale=1.0"> |
|||
<link rel="icon" href="<%= BASE_URL %>favicon.ico"> |
|||
<title><%= htmlWebpackPlugin.options.title %></title> |
|||
</head> |
|||
<body> |
|||
<noscript> |
|||
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong> |
|||
</noscript> |
|||
<div id="app"></div> |
|||
<!-- built files will be auto injected --> |
|||
</body> |
|||
</html> |
|||
@ -0,0 +1,32 @@ |
|||
<template> |
|||
<div id="app"> |
|||
<!-- <div id="nav"> |
|||
<router-link to="/">Home</router-link> | |
|||
<router-link to="/about">About</router-link> |
|||
</div> --> |
|||
<router-view :key="(new Date()).getTime()" /> |
|||
</div> |
|||
</template> |
|||
|
|||
<style scoped lang="less"> |
|||
#app { |
|||
font-family: Avenir, Helvetica, Arial, sans-serif; |
|||
-webkit-font-smoothing: antialiased; |
|||
-moz-osx-font-smoothing: grayscale; |
|||
text-align: center; |
|||
color: #2c3e50; |
|||
} |
|||
|
|||
#nav { |
|||
padding: 30px; |
|||
|
|||
a { |
|||
font-weight: bold; |
|||
color: #2c3e50; |
|||
|
|||
&.router-link-exact-active { |
|||
color: #42b983; |
|||
} |
|||
} |
|||
} |
|||
</style> |
|||
@ -0,0 +1,10 @@ |
|||
import { axios } from '@/utils/request' |
|||
|
|||
// 测试接口
|
|||
export function test (parameter) { |
|||
return axios({ |
|||
url: '/department/getDepartmentList', |
|||
method: 'get', |
|||
params: parameter |
|||
}) |
|||
} |
|||
@ -0,0 +1,57 @@ |
|||
<template> |
|||
<div class="hello"> |
|||
<h1>{{ msg }}</h1> |
|||
<p> |
|||
For a guide and recipes on how to configure / customize this project,<br> |
|||
check out the |
|||
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>. |
|||
</p> |
|||
<h3>Installed CLI Plugins</h3> |
|||
<ul> |
|||
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-router" target="_blank" rel="noopener">router</a></li> |
|||
</ul> |
|||
<h3>Essential Links</h3> |
|||
<ul> |
|||
<li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li> |
|||
<li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li> |
|||
<li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li> |
|||
<li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li> |
|||
<li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li> |
|||
</ul> |
|||
<h3>Ecosystem</h3> |
|||
<ul> |
|||
<li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li> |
|||
<li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li> |
|||
<li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li> |
|||
<li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li> |
|||
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li> |
|||
</ul> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
name: 'HelloWorld', |
|||
props: { |
|||
msg: String |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<!-- Add "scoped" attribute to limit CSS to this component only --> |
|||
<style scoped lang="less"> |
|||
h3 { |
|||
margin: 40px 0 0; |
|||
} |
|||
ul { |
|||
list-style-type: none; |
|||
padding: 0; |
|||
} |
|||
li { |
|||
display: inline-block; |
|||
margin: 0 10px; |
|||
} |
|||
a { |
|||
color: #42b983; |
|||
} |
|||
</style> |
|||
@ -0,0 +1,95 @@ |
|||
import Vue from 'vue' |
|||
|
|||
import "./public-path"; |
|||
|
|||
import VueRouter from 'vue-router' |
|||
import App from './App.vue' |
|||
import routes from './router' |
|||
|
|||
Vue.use(VueRouter) |
|||
Vue.config.productionTip = false |
|||
|
|||
let instance = null; |
|||
let router = null; |
|||
|
|||
/** |
|||
* 渲染函数 |
|||
* 两种情况:主应用生命周期钩子中运行 / 微应用单独启动时运行 |
|||
*/ |
|||
function render(props = {}) { |
|||
const { container } = props; |
|||
|
|||
// 在 render 中创建 VueRouter,可以保证在卸载微应用时,移除 location 事件监听,防止事件污染
|
|||
router = new VueRouter({ |
|||
// 运行在主应用中时,添加路由命名空间 /vue
|
|||
base: window.__POWERED_BY_QIANKUN__ ? "/testMicro" : process.env.BASE_URL, |
|||
mode: "history", |
|||
routes, |
|||
}); |
|||
|
|||
// 挂载应用
|
|||
instance = new Vue({ |
|||
router, |
|||
render: h => h(App), |
|||
}).$mount(container ? container.querySelector('#app') : '#app'); |
|||
} |
|||
|
|||
// 独立运行时,直接挂载应用
|
|||
if (!window.__POWERED_BY_QIANKUN__) { |
|||
render() |
|||
} |
|||
|
|||
function storeTest(props) { |
|||
props.onGlobalStateChange && |
|||
props.onGlobalStateChange( |
|||
(value, prev) => { |
|||
console.log(`[qiankun testMicro]: [onGlobalStateChange - ${props.name}]:`, value, prev) |
|||
localStorage.setItem('pro__Access-Token', JSON.stringify((value || {}).token || {})) |
|||
}, |
|||
true, |
|||
); |
|||
// props.setGlobalState &&
|
|||
// props.setGlobalState({
|
|||
// ignore: props.name,
|
|||
// user: {
|
|||
// name: props.name,
|
|||
// },
|
|||
// });
|
|||
} |
|||
|
|||
/** |
|||
* bootstrap 只会在微应用初始化的时候调用一次,下次微应用重新进入时会直接调用 mount 钩子,不会再重复触发 bootstrap。 |
|||
* 通常我们可以在这里做一些全局变量的初始化,比如不会在 unmount 阶段被销毁的应用级别的缓存等。 |
|||
*/ |
|||
export async function bootstrap() { |
|||
console.log('[qiankun testMicro]: vue app bootstraped'); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 应用每次进入都会调用 mount 方法,通常我们在这里触发应用的渲染方法 |
|||
*/ |
|||
export async function mount(props) { |
|||
console.log('[qiankun testMicro]: props from main framework', props); |
|||
|
|||
props.onGlobalStateChange((state, prev) => { |
|||
// state: 变更后的状态; prev 变更前的状态
|
|||
console.log("[qiankun testMicro]: [onGlobalStateChange]", state, prev); |
|||
}); |
|||
|
|||
// props.setGlobalState(state);
|
|||
|
|||
storeTest(props); |
|||
render(props); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 应用每次 切出/卸载 会调用的方法,通常在这里我们会卸载微应用的应用实例 |
|||
*/ |
|||
export async function unmount() { |
|||
console.log("[qiankun testMicro]: vue app unmount"); |
|||
instance.$destroy(); |
|||
instance = null; |
|||
router = null; |
|||
} |
|||
@ -0,0 +1,5 @@ |
|||
if (window.__POWERED_BY_QIANKUN__) { |
|||
// 动态设置 webpack publicPath,防止资源加载出错
|
|||
// eslint-disable-next-line no-undef
|
|||
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__; |
|||
} |
|||
@ -0,0 +1,25 @@ |
|||
|
|||
import Home from '../views/Home.vue' |
|||
|
|||
|
|||
const routes = [ |
|||
{ |
|||
path: '/', |
|||
name: 'Home', |
|||
component: Home |
|||
}, |
|||
{ |
|||
path: '/about', |
|||
name: 'About', |
|||
// route level code-splitting
|
|||
// this generates a separate chunk (about.[hash].js) for this route
|
|||
// which is lazy-loaded when the route is visited.
|
|||
component: function () { |
|||
// /* webpackChunkName: "about" */
|
|||
return import('../views/About.vue') |
|||
} |
|||
} |
|||
] |
|||
|
|||
|
|||
export default routes |
|||
@ -0,0 +1,76 @@ |
|||
import Vue from 'vue' |
|||
import axios from 'axios' |
|||
import notification from 'ant-design-vue/es/notification' |
|||
import { VueAxios } from 'utils' |
|||
// import { ACCESS_TOKEN } from '@/store/mutation-types'
|
|||
|
|||
// 创建 axios 实例
|
|||
const service = axios.create({ |
|||
baseURL: process.env.NODE_ENV === 'production' ? 'http://api-test.qniao.cn/user-centre' : 'http://47.106.79.88:9000/user-centre', |
|||
timeout: 15000 // 请求超时时间
|
|||
}) |
|||
|
|||
const err = (error) => { |
|||
console.log(error) |
|||
if (error.response) { |
|||
const data = error.response |
|||
// const token = Vue.ls.get(ACCESS_TOKEN)
|
|||
// const token = JSON.parse(localStorage.getItem('pro__Access-Token') || '{}').value
|
|||
const token = localStorage.getItem('pro__Access-Token') |
|||
console.log('token get from testmicro: ', token) |
|||
if (error.response.status === 403) { |
|||
notification.error({ |
|||
message: '您暂时没有权限!', |
|||
description: data.message |
|||
}) |
|||
} |
|||
if (error.response.status === 500) { |
|||
notification.error({ |
|||
message: '服务器错误!', |
|||
description: data.message |
|||
}) |
|||
} |
|||
if (error.response.status === 401 && !(data.result && data.code === 666)) { |
|||
notification.error({ |
|||
message: '登录已失效', |
|||
description: '会话失效,请重新登录!' |
|||
}) |
|||
if (token) { |
|||
// Vue.ls.remove(ACCESS_TOKEN)
|
|||
localStorage.removeItem('pro__Access-Token') |
|||
window.location = service.baseURL |
|||
} |
|||
} |
|||
} |
|||
return Promise.reject(error) |
|||
} |
|||
|
|||
// request interceptor
|
|||
service.interceptors.request.use(config => { |
|||
// const token = Vue.ls.get(ACCESS_TOKEN)
|
|||
// const token = JSON.parse(localStorage.getItem('pro__Access-Token') || '{}').value
|
|||
const token = localStorage.getItem('pro__Access-Token') |
|||
console.log('token get from testmicro: ', token) |
|||
const _token = (JSON.parse(token) || {}).value |
|||
if (_token) { |
|||
config.headers['user-token'] = _token // 让每个请求携带自定义 token 请根据实际情况自行修改
|
|||
} |
|||
return config |
|||
}, err) |
|||
|
|||
// response interceptor
|
|||
service.interceptors.response.use((response) => { |
|||
return response.data |
|||
}, err) |
|||
|
|||
const installer = { |
|||
vm: {}, |
|||
install (Vue) { |
|||
Vue.use(VueAxios, service) |
|||
} |
|||
} |
|||
|
|||
export { |
|||
installer as VueAxios, |
|||
service as axios |
|||
} |
|||
@ -0,0 +1,5 @@ |
|||
<template> |
|||
<div class="about"> |
|||
<h1>This is an about page</h1> |
|||
</div> |
|||
</template> |
|||
@ -0,0 +1,22 @@ |
|||
<template> |
|||
<div class="home"> |
|||
<img alt="Vue logo" src="../assets/logo.png"> |
|||
<HelloWorld msg="Welcome to Your Vue.js App"/> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
// @ is an alias to /src |
|||
import HelloWorld from '@/components/HelloWorld.vue' |
|||
import { test } from '@/api' |
|||
|
|||
export default { |
|||
name: 'Home', |
|||
components: { |
|||
HelloWorld |
|||
}, |
|||
created() { |
|||
test() |
|||
} |
|||
} |
|||
</script> |
|||
@ -0,0 +1,52 @@ |
|||
const path = require('path'); |
|||
const { name } = require('./package'); |
|||
|
|||
function resolve(dir) { |
|||
return path.join(__dirname, dir); |
|||
} |
|||
|
|||
const port = 7101; // dev port
|
|||
|
|||
|
|||
module.exports = { |
|||
/** |
|||
* You will need to set publicPath if you plan to deploy your site under a sub path, |
|||
* for example GitHub Pages. If you plan to deploy your site to https://foo.github.io/bar/,
|
|||
* then publicPath should be set to "/bar/". |
|||
* In most cases please use '/' !!! |
|||
* Detail: https://cli.vuejs.org/config/#publicpath
|
|||
*/ |
|||
outputDir: 'dist', |
|||
assetsDir: 'static', |
|||
filenameHashing: true, |
|||
// tweak internal webpack configuration.
|
|||
// see https://github.com/vuejs/vue-cli/blob/dev/docs/webpack.md
|
|||
devServer: { |
|||
// host: '0.0.0.0',
|
|||
hot: true, |
|||
disableHostCheck: true, |
|||
port, |
|||
overlay: { |
|||
warnings: false, |
|||
errors: true, |
|||
}, |
|||
headers: { |
|||
'Access-Control-Allow-Origin': '*', |
|||
}, |
|||
}, |
|||
// 自定义webpack配置
|
|||
configureWebpack: { |
|||
devtool: 'source-map', |
|||
resolve: { |
|||
alias: { |
|||
'@': resolve('src'), |
|||
}, |
|||
}, |
|||
output: { |
|||
// 把子应用打包成 umd 库格式
|
|||
library: `${name}-[name]`, |
|||
libraryTarget: 'umd', |
|||
jsonpFunction: `webpackJsonp_${name}`, |
|||
}, |
|||
}, |
|||
}; |
|||
6893
yarn.lock
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
Write
Preview
Loading…
Cancel
Save