VUE动态加载模块,热插拔。
vue模块化加载功能1 如何按照不同的模块进行打包?2如何动态加载?3 生产环境下如何加载子模块4 根据后台传回来的值,加载指定的模块5如何只要一个主模块,子模块后台传输过来注:我的请求后台方法不是用的此项目的方法。改了一丢丢。。。别直接复制。某大叔项目地址:https://gitee.com/itdashu/flick最近有一个新需求:就是插件化模块。按不同模块打包,如user模块,role模块
vue模块化加载功能
最近有一个新需求:就是插件化模块。按不同模块打包,如user模块,role模块,打包成不同的main.js,然后在nginx部署一个主模块,按照后台传来的需要加载的模块和js文件,进行加载对应的模块。
在尝试中遇到几个问题:
1 如何按照不同的模块进行打包?
因为不熟悉,百度了一下,参考某大叔项目 https://gitee.com/itdashu/flick对项目模块化打包,加载已经进行了处理。
因为对yargs不熟悉,花费了一段时间。。。有点傻。。。
在package.json 进行了添加命令
webpack --config config/webpack.module.js --mode production --module=user
打包User模块。
而这里大叔 对命令传入的参数,在webpack.module.js文件中,对参数进行识别,打包resolve,生成在dist目录下。
mode: "production",
: resolve(`src/${moduleName}/main.js`),
output: {
publicPath: `/manage/${moduleName}/`,
filename: 'main.js',
path: resolve(`dist/${moduleName}`),
chunkFilename: "module.[hash].js",
library: {
root: `flick${ucModuleName}`
},
libraryTarget: 'umd'
},
2如何动态加载?
在App.vue里面 通过created方法加载不同的组件
let moduleList =[{name:'user'},[name:'test']];
for (let module of moduleList) {
//加载js,并返加载的router对象
loadModule(module.name,module.path).then(moduleExport => {
console.log('加载',moduleExport)
// 注册路由
if(moduleExport.hasOwnProperty('routes')){
this.$router.options.routes.push(moduleExport.routes);
//因为此处addRoutes,没有用,我就用了上面
this.$router.addRoutes(moduleExport.routes)
}
// 注册vuex
if(moduleExport.hasOwnProperty('store')){
this.$store.registerModule(module.name, moduleExport.store)
}
}).catch(err => {
console.log(`${module.name}加载失败`)
console.log(err)
})
}
export default async (module,path) => {
const customImport = await import("./loadModule/load_" + process.env.NODE_ENV);
let customModule = await customImport.default(module,path)
return customModule.default
}
export default (module) => import(`@/${module}/main.js`);
loadModule方式是通过import加载模块,让用户模块,测试模块加载到主模块(load_development.js)。
addRouterr(我这里无效,用上一行方法代替的),添加子模块路由到主模块。
3 生产环境下如何加载子模块
生产环境不同与开发环境,不可以直接导入main.js?这就一个问题,大叔用loadJs和Promise对象解决了(load_production.js)
加载module下面的对应的模块
let basePath = '/manage'
return new Promise((resolve, reject) => {
loadJs(`${basePath}/${module}/main.js`, {
success: () => {
resolve({
default: window[umdModuleName].default
})
},
error: err => {
console.log("这里报错")
reject(err)
}
})
})
4 根据后台传回来的值,加载指定的模块
这个其实简单,就是moduleList 的值用后台传就是了。
我
await this.$post(`/api/file/test`).then(res=>{
if (res.code==="001000"){
if (res.data.length<=0){
console.log("没有模块加载");
}
let moduleList =res.data;
for (let module of moduleList) {
loadModule(module.name,module.path).then(moduleExport => {
console.log('加载',moduleExport)
// 注册路由
if(moduleExport.hasOwnProperty('routes')){
this.$router.options.routes.push(moduleExport.routes);
this.$router.addRoutes(moduleExport.routes)
}
// 注册vuex
if(moduleExport.hasOwnProperty('store')){
this.$store.registerModule(module.name, moduleExport.store)
}
}).catch(err => {
console.log(`${module.name}加载失败`)
console.log(err)
})
}
}else {
console.log("无法改变")
}
})
5如何只要一个主模块,子模块后台传输过来
上面我已经对loadModule方法进行了改造,多了一个path。
这个path就是请求后台对应的js文件用的路径,用于后台文件服务器进行传输js文件。
前端用blob对象接收js文件,然后创建虚拟路径。然后load。就可以了
await fileDownload(`/api/file/test/download?path=${path}`).then(res => {
let blob = new Blob([res], {type: "application/x-javascript"});
url = window.URL.createObjectURL(blob);
//不可在这返回数据,因为此处返回是返回该方法
})
return new Promise((resolve, reject) => {
loadJs(url, {
success: () => {
resolve({
default: window[umdModuleName].default
})
},
error: err => {
console.log("这里报错")
reject(err)
}
})
});
注:我的请求后台方法不是用的此项目的方法。改了一丢丢。。。别直接复制。
某大叔项目地址:https://gitee.com/itdashu/flick
更多推荐
所有评论(0)