vue前端项目集成emp

背景

公司有多个产品线的项目,每个项目的功能有重叠的部分,平时开发维护量大,所以考虑将共性的功能抽取出单独的base项目,其它前端项目引用base项目的公共页面,达到提高工作效率的目的。

1. 整合步骤

1.1. 创建文件emp-config.js

1.2. 将文件vue.config.js中的内容拷贝到emp-config.js并根据emp 的框架的要求调整

const FileManagerPlugin = require('filemanager-webpack-plugin');
const vue2 = require('@efox/plugin-vue-2')
const {defineConfig} = require('@efox/emp')
const {cdn} = require('./cdn')
const esm = (name, mode, version) =>
    `https://esm.sh/${name}${version ? '@' + version : ''}${mode === 'development'
        ? '?dev' : ''}`
const packageName = 'dist';
var IS_PROD = (process.env.NODE_ENV == 'CLUSTER') ? true:false
console.log("|"+process.env.NODE_ENV+"|")
console.log(IS_PROD ? '注意:当前是生产环境!!!' : '开发或测试模式')
module.exports = defineConfig(config => {
    const{mode, env} = config
// const target = 'es2018'
    const target = 'es5'
    const isESM = !['es3', 'es5'].includes(target)
    return {
        plugins: [vue2],
        appEntry: 'main.js',
        server: {port: 9003},
        html: {
            title: 'EMP Vue2 Base',
            favicon: 'src/logo.png',
            template: 'src/index.html'
        },
        build: {
            target,
//是否清空生成文件夹
            emptyOutDir: true,
//生产 环境:打包时不生成.map文件,设置为false 避免看到源码
            sourcemap: !IS_PROD,
// + 类型 `boolean` | `swc`
// + 默认 `true`
// 启用 `swc` 进行压缩 比 `terser` 速度提升 7倍,目前处于 `RC` 阶段,可以正常使用
            minify: true,
            outDir: 'dist'
        },
        debug:{
            clearLog: true,
            progress: true,
            profile: false,
            level: 'info'
        },
        empShare: {
            name: 'wsqgovViewUi',
            exposes: {
                './commonLess':'./src/styles/common.less',
                './tableCommonLess':'./src/styles/table-common.less',
                './treeCommonLess':'./src/styles/tree-common.less',
                './wsqHomeLess':'./src/styles/wsqhome.less',
                './axiosJs':'./src/libs/axios',
                './rtIndexJs':'./src/router/index',
                './rtRouterJs':'./src/router/router',
                './indexJs':'./src/api/index',
                './storeModAppJs':'./src/store/modules/app',
                './storeModDictJs':'./src/store/modules/dict',
                './storeModUserJs':'./src/store/modules/user',
                './storeIndexJs':'./src/store/index',
                './indexBackJs':'./src/api/indexBack',
            },
// shared: {
// vue: {requiredVersion: '^2.6.14'},
// 'element-ui': {requiredVersion: '^2.0.0'},
// 'vue-router': {requiredVersion: '^3.0.0'},
// 'view-design' :{requiredVersion:'^4.4.0'}
// },
            shareLib: !isESM
                ? cdn(mode)
                :
                {
                    vue: esm('vue',mode,'2.6.14'),
// 'element-ui': esm('element-ui'),
                    'view-design': esm('view-design',mode,'4.7.0')
                },
        },
        "resolve":{
            "alias": {
                "@": "src"
            },
        },
// webpack配置
        webpackChain: (chain, config) => {
            if (process.env.NODE_ENV == 'production'
                || 'buildTest' == process.env.NODE_ENV
                || 'CLUSTER' == process.env.NODE_ENV
            ) {
// 增加zip打包插件
                chain.plugin('FileManagerPlugin').use(
                    new FileManagerPlugin({
                        events: {
                            onEnd: {
                                delete: [ //首先需要删除项目根目录下的dist.zip
                                    `./${packageName}.zip`
                                ],
                                archive: [ //然后我们选择dist文件夹将之打包成dist.zip并放在根目录
                                    {source: `./${packageName}`, destination:
                                            `./${packageName}.zip`, format: 'zip'},
                                ]
                            }
                        }
                    })
                )
///
            }
        },
        optimization: {
//webpack不自动读取配置文件中的mode给process.env.NODE_ENV赋值
            nodeEnv: false
        }
/
    }
})

1.3. 将 public/index.html 移动到 src/index.html 将 public/logo.png 移动到 src/logo.png,修改引用logo.png文件的代码

1.4. 在src/index.html文件中注入emp shareLib 以CDN方式引入 的css与js

<!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="src/logo.png">
    <title>智慧社区管理平台</title>
    <meta name="keywords" content="">
    <meta name="description" content="">
    <!-- EMP inject css-->
    <% for (let i in htmlWebpackPlugin.options.files.css) { %>
    <link rel="stylesheet" href="<%= htmlWebpackPlugin.options.files.css[i] %>"
    /><% } %>
    <!-- EMP inject js -->
    <% for (let i in htmlWebpackPlugin.options.files.js) { %>
    <script src="<%= htmlWebpackPlugin.options.files.js[i] %>"></script><% } %>
    <!-- 部署CDN优化 -->
    <!-- <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.min.js">
    </script>
    <script src="https://cdn.jsdelivr.net/npm/vuex@3.1.2/dist/vuex.min.js">
    </script>
    <script src="https://cdn.jsdelivr.net/npm/vue-i18n@8.15.1/dist/vuei18n.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vue-router@3.1.3/dist/vuerouter.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/axios@0.19.2/dist/axios.min.js">
    </script>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/viewdesign@4.2.0/dist/styles/iview.css">
    ......

1.5. 删除文件 vue.config.js

1.6. 新建文件src/bootstrap.js

1.7. 将src/main.js文件内容复制到src/bootstrap.js

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
//import '@babel/polyfill'
import 'core-js'
import 'regenerator-runtime/runtime'
import Vue from 'vue'
import Vuex from 'vuex'
import ViewUI from 'view-design'
// import VueCompositionAPI from '@vue/composition-api'
// import { install } from 'vue-demi'
// import 'view-design/dist/styles/iview.css'
import '@/assets/font/iconfont.css' //2021-4-14新的主页 引入自定义图标
import App from './App'
import { router } from '@/router/index'
import VueRouter from 'vue-router'
import store from '@/store'
import i18n from '@/locale'
import Icon from 'vue-awesome/components/Icon'
// 按需引入awesome图标
import 'vue-awesome/icons/brands/qq'
import 'vue-awesome/icons/brands/weixin'
import 'vue-awesome/icons/brands/weibo'
import 'vue-awesome/icons/brands/github'
// 引入theme 样式
import '@/styles/theme/color.less'
import conf from '@/config/config.js';
import { getRequest, postRequest, putRequest, postBodyRequest, getNoAuthRequest,
    postNoAuthRequest } from '@/libs/axios'
import { setStore, getStore, removeStore } from '@/libs/storage'
import { format } from "date-fns";
import util from '@/libs/util'
import dictUtil from '@/libs/dictUtil'
import hasPermission from '@/libs/hasPermission'
import hasRole from '@/libs/hasRole'
import iviewArea from '@/views/my-components/iview-area';
import VueLazyload from 'vue-lazyload'
import VueClipboard from 'vue-clipboard2'
import VueApexCharts from 'vue-apexcharts'
import echarts from 'echarts' //引入echarts
Vue.prototype.$echarts = echarts
Vue.config.productionTip = false
Vue.use(VueLazyload, {
    error: require('./assets/img-error.png'),
    loading: require('./assets/loading2.gif')
})
Vue.use(ViewUI, {
    i18n: (key, value) => i18n.t(key, value)
});
import AMapLoader from '@amap/amap-jsapi-loader';
// import htmlToPdf from './views/wsqcomp/education/htmlToPdf'
// Vue.use(htmlToPdf)
Vue.use(AMapLoader)
Vue.use(Vuex)
Vue.use(VueRouter)
// Vue.use(VueCompositionAPI)
Vue.component('icon', Icon);
Vue.use(VueClipboard);
Vue.use(hasPermission);
Vue.use(hasRole);
Vue.use(iviewArea);
Vue.use(VueApexCharts);
Vue.component('apexchart', VueApexCharts);
// 挂载全局使用的方法
Vue.prototype.getRequest = getRequest;
Vue.prototype.postRequest = postRequest;
Vue.prototype.putRequest = putRequest;
Vue.prototype.postBodyRequest = postBodyRequest;
Vue.prototype.getNoAuthRequest = getNoAuthRequest;
Vue.prototype.postNoAuthRequest = postNoAuthRequest;
Vue.prototype.setStore = setStore;
Vue.prototype.getStore = getStore;
Vue.prototype.removeStore = removeStore;
Vue.prototype.format = format;
// Vue.prototype.$api = api;
Vue.prototype.$conf = conf;//全局可通过 this.$conf 访问 配置
// import ECharts from 'vue-echarts'
/* eslint-disable no-new */
new Vue({
    el: '#app',
    router,
    store,
    i18n,
    render: h => h(App),
    data: {
        currentPageName: ''
    },
    mounted() {
        this.$Message.config({
            duration: 3
        })
// 初始化菜单
        util.initRouter(this);
// 初始化全局数据字典
        dictUtil.initDictData(this);
        this.currentPageName = this.$route.name;
// 显示打开的页面的列表
        this.$store.commit('setOpenedList');
        this.$store.commit('initCachepage');
    }
})
import wangEditor from 'wangeditor'
import DPlayer from 'dplayer'
// import JsPDF from 'jspdf'
import axios from 'axios'
// import Viewer from 'viewerjs'
import XLSX from 'xlsx'
// import CountUp from 'countup.js'
// import echarts from 'echarts'
import Cookies from 'js-cookie'
import printJS from 'print-js'
// import Quill from 'quill'
import SockJS from 'sockjs-client'
import VueI18n from 'vue-i18n'
import vueSeamlessScroll from 'vue-seamless-scroll'
import vuedraggable from 'vuedraggable'
Vue.use(wangEditor)
// Vue.use(ECharts)
Vue.use(DPlayer)
// Vue.use(JsPDF)
Vue.use(axios)
// Vue.use(Viewer)
Vue.use(XLSX)
// Vue.use(echarts)
// Vue.use(CountUp)
Vue.use(Cookies)
Vue.use(printJS)
// Vue.use(Quill)
Vue.use(SockJS)
Vue.use(VueI18n)
Vue.use(vuedraggable)

1.8. 修改src/main.js文件内容

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
//import '@babel/polyfill'
import('./bootstrap.js')

1.9. 在package.json中添加emp相关依赖

添加@efox开头的依赖

删除以下依赖

@vue/cli-service

@vue/cli-plugin-babel

less

less-loader

"devDependencies": {
"@efox/emp": "^2.4.3",
"@efox/eslint-config-vue": "^2.0.1",
"@efox/plugin-vue-2": "^1.1.2",
"@types/node": "^18.6.3",
"@vue/cli-plugin-router": "^4.1.0",
"@vue/cli-plugin-vuex": "^4.1.0",
"compression-webpack-plugin": "^3.0.0",
"cross-env": "^7.0.3",
"exports-loader": "^1.1.0",
"filemanager-webpack-plugin": "^3.1.1",
"imports-loader": "^1.1.0",
"luckyexcel": "^1.0.1",
"three": "^0.118.3",
"vue-template-compiler": "^2.6.10",
"webpack": "^5.74.0"
}

1.10. 将第三方组件以cdn方式引入

1.10.1. 新建 /cdn.js

const envLib = {
development: {
'vue': 'Vue@https://www.wsq666.com/datapublic/cdn/vue@2.6.14/dist/vue.min.js',
'view-design': [
'iview@https://www.wsq666.com/data-public/cdn/viewdesign@4.7.0/dist/iview.min.js',
`https://www.wsq666.com/data-public/cdn/viewdesign@4.7.0/dist/iview.css`,
'zhCnLocale@https://www.wsq666.com/data-public/cdn/viewdesign@4.7.0/dist/locale/zh-CN.js',
'enUsLocale@https://www.wsq666.com/data-public/cdn/viewdesign@4.7.0/dist/locale/en-US.js'
],
'stompjs':'Stomp@https://cdn.bootcdn.net/ajax/libs/stomp.js/2.1.0-
next/stomp.js',
'html2canvas':'https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2ca
nvas.min.js',
'vuex':'Vuex@https://unpkg.com/vuex@3.1.2/dist/vuex.js',
vue-router':'VueRouter@https://unpkg.com/vue-router@3.3.1/dist/vuerouter.js',
// 'vue-echarts':'ECharts@https://lf6-cdn-tos.bytecdntp.com/cdn/expire1-M/vue-echarts/6.0.0-rc.5/index.umd.js',
'wangeditor':'wangEditor@https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-
M/wangEditor/3.1.1/wangEditor.min.js',
'dplayer':'DPlayer@https://lf9-cdn-tos.bytecdntp.com/cdn/expire-1-
M/dplayer/1.25.1/DPlayer.min.js',
// 'jspdf':'JsPDF@https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-
M/jspdf/2.5.0/jspdf.umd.min.js',
'axios':'axios@https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-
M/axios/0.19.2/axios.min.js',
/* 'viewerjs':[
'Viewer@https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-
M/viewerjs/1.5.0/viewer.min.js',
`https://lf9-cdn-tos.bytecdntp.com/cdn/expire-1-
M/viewerjs/1.10.4/viewer.css`
], */
'xlsx':'XLSX@https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-
M/xlsx/0.15.1/xlsx.min.js',
// 'echarts':'echarts@https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-
M/echarts/4.9.0-rc.1/echarts.min.js',
// 'countup.js':'CountUp@https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-
M/countup.js/2.0.4/countUp.min.js',
'js-cookie':'Cookies@https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-
M/js-cookie/2.2.1/js.cookie.min.js',
'core-js':'https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/corejs/3.5.0/minified.min.js',
'print-js':'printJS@https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-
M/print-js/1.0.63/print.min.js',
/* 'quill':[
'Quill@https://lf9-cdn-tos.bytecdntp.com/cdn/expire-1-
M/quill/1.3.7/quill.min.js',
`https://lf9-cdn-tos.bytecdntp.com/cdn/expire-1-
M/quill/1.3.7/quill.snow.css`
], */
'sockjs-client':'SockJS@https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-
M/sockjs-client/1.4.0/sockjs.min.js',
'videojs-contrib-hls':'https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-
M/videojs-contrib-hls/5.15.0/videojs-contrib-hls.min.js',
'vue-clipboard2':'VueClipboard@https://lf26-cdntos.bytecdntp.com/cdn/expire-1-M/vue-clipboard2/0.3.0/vue-clipboard.min.js',
'vue-i18n':'VueI18n@https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-
M/vue-i18n/8.15.1/vue-i18n.min.js',
'vue-lazyload':'VueLazyload@https://lf9-cdntos.bytecdntp.com/cdn/expire-1-M/vue-lazyload/1.3.3/vue-lazyload.js',
'vue-seamlessscroll':'vueSeamlessScroll@https://cdn.jsdelivr.net/npm/vue-seamlessscroll@latest/dist/vue-seamless-scroll.min.js',
'vuedraggable':'vuedraggable@https://cdnjs.cloudflare.com/ajax/libs/Vue.Draggab
le/2.23.2/vuedraggable.umd.min.js',
},
production: {
},
}
const lib = {
// 'react-router-dom': 'ReactRouterDOM@https://cdn.jsdelivr.net/npm/reactrouter-dom@5.3.0/umd/react-router-dom.min.js',
}
module.exports = {
cdn: mode => {
return {
...envLib[mode],
// ...lib,
}
},
}

1.10.2. 在 emp-config.js 中引入cdn.js

......
const {cdn} = require('./cdn')
......
shareLib: !isESM
? cdn(mode)
:
{
vue: esm('vue',mode,'2.6.14'),
// 'element-ui': esm('element-ui'),
'view-design': esm('view-design',mode,'4.7.0')
},
......

1.10.3. 在 src/bootstrap.js 中引入通过CDN方式注入的组件

......
import SockJS from 'sockjs-client'
Vue.use(SockJS)
......

1.11. emp项目启动

yarn dev

emp dev

1.12. 引用其它项目的样式文件

wsqcomp前端项目引用wsqgov政府端前端的样式方式

将wsqcmop集成emp框架

将wsqgov项目的样式文件通过 empShare 的方式暴露出去

以 /src/styles/common.less 为例

/emp-config.js

......
empShare: {
name: 'wsqgovViewUi',
exposes: {
'./commonLess':'./src/styles/common.less',
'./tableCommonLess':'./src/styles/table-common.less',
'./treeCommonLess':'./src/styles/tree-common.less',
'./wsqHomeLess':'./src/styles/wsqhome.less',
'./axiosJs':'./src/libs/axios',
'./rtIndexJs':'./src/router/index',
'./rtRouterJs':'./src/router/router',
'./indexJs':'./src/api/index',
'./storeModAppJs':'./src/store/modules/app',
'./storeModDictJs':'./src/store/modules/dict',
'./storeModUserJs':'./src/store/modules/user',
'./storeIndexJs':'./src/store/index',
'./indexBackJs':'./src/api/indexBack',
},
......

wsqcomp项目中通过 remotes 方式引用 wsqgov 暴露的组件

emp-config.js

......
empShare: {
name: 'wsqcompViewUi',
remotes: {
'@govViewUi': 'wsqgovViewUi@http://192.168.124.66:9003/emp.js',
},
......

修改wsqcomp项目中引用样式文件的方式

\src\views\home\home.vue

import commonLess from '@govViewUi/commonLess';

<style lang="less">
@import "./home.less";
// @import "../../styles/common.less";
</style>
<template>
  <div>
    <div v-show="currNav=='home'" class="home">
      <dashboard2 />
    </div>
  </div>
</template>
<script>
// import wsqHomeLess from '@govViewUi/wsqHomeLess';
import commonLess from '@govViewUi/commonLess';
import { ipInfo, getNotice } from "@/api/index";
// import axiosJs from '@govViewUi/axiosJs';
//import rtIndexJs from '@govViewUi/rtIndexJs';
//import indexBackJs from '@govViewUi/indexBackJs';
import visitVolume from "./components/visitVolume.vue";
import visitSeparation from "./components/visitSeparation.vue";
import infoCard from "./components/infoCard.vue";
import show from "./show.vue";
import dashboard2 from "../kr-charts/dashboard2/dashboard2.vue";
import Cookies from "js-cookie";
import "gitalk/dist/gitalk.css";
import Gitalk from "gitalk";
......

1.13. 导出公用函数 wsqcomp

引用 wsqgov 暴露的公用函数

需要导出的函数中,若包含多个 export const 函数,需要修改成通过 export default 导出 测试文件 \src\api\indexBack.js

// 统一请求路径前缀在libs/axios.js中修改
import {
getRequest,
getNoAuthRequest
} from '@/libs/axios';
import conf from '@/config/config.js';
export const indexBackJs = {
vaptchaID: "121133243434343434",
uploadFile: conf.baseUrl + "/upload/file",
uploadFilePh: conf.baseUrlPh + "/upload/file",
uploadFileWyc: conf.baseUrlWyc + "/upload/file",
uploadFileKy: conf.baseUrlKy + "/upload/file",
drawCodeImage: conf.baseUrl + "/common/captcha/draw/",
getMenuList: conf.baseUrl + "/permission/getMenuList",
getDictData: conf.baseUrl + "/dictData/getByType/",
ws: conf.baseWs, // "http://127.0.0.1:4888/wsqcomp_system/ws"
// IP天气信息
ipInfo(params) {
return getRequest('/common/ip/info', params)
},
// 获取公告
getNotice(params) {
return getNoAuthRequest('/setting/notice', params)
}
}
export default indexBackJs

wsqgov 项目在 /emp-config.js 文件中暴露出公用函数文件

以 /src/api/indexBack.js 文件为例

......
empShare: {
name: 'wsqgovViewUi',
exposes: {
'./commonLess':'./src/styles/common.less',
'./tableCommonLess':'./src/styles/table-common.less',
'./treeCommonLess':'./src/styles/tree-common.less',
'./wsqHomeLess':'./src/styles/wsqhome.less',
'./axiosJs':'./src/libs/axios',
'./rtIndexJs':'./src/router/index',
'./rtRouterJs':'./src/router/router',
'./indexJs':'./src/api/index',
'./storeModAppJs':'./src/store/modules/app',
'./storeModDictJs':'./src/store/modules/dict',
'./storeModUserJs':'./src/store/modules/user',
'./storeIndexJs':'./src/store/index',
'./indexBackJs':'./src/api/indexBack',
},
......

wsqcomp 项目在 emp-config.js 中通过 empShare 的 remotes 属性 引用 wsqgov 项目暴露的公 用函数

......
empShare: {
name: 'wsqcompViewUi',
remotes: {
'@govViewUi': 'wsqgovViewUi@http://192.168.124.66:9003/emp.js',
},
......

wsqcomp 项目在 /src/bootstrap.js 中引入 wsqgov 暴露的组件

......
import storeModDictJs from '@govViewUi/storeModDictJs';
import storeModUserJs from '@govViewUi/storeModUserJs';
import storeModAppJs from '@govViewUi/storeModAppJs';
import storeIndexJs from '@govViewUi/storeIndexJs';
import rtRouterJs from '@govViewUi/rtRouterJs';
import rtIndexJs from '@govViewUi/rtIndexJs';
import axiosJs from '@govViewUi/axiosJs';
import indexBackJs from '@govViewUi/indexBackJs';
console.log('storeModDictJs', storeModDictJs)
console.log('storeModUserJs', storeModUserJs)
console.log('storeModAppJs', storeModAppJs)
console.log('storeIndexJs', storeIndexJs)
console.log('rtRouterJs', rtRouterJs)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

营赢盈英

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值