最近有一个新需求:就是插件化模块。按不同模块打包,如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

Logo

前往低代码交流专区

更多推荐