UNPKG

egg-born-front

Version:
297 lines (292 loc) 9.97 kB
import mparse from 'egg-born-mparse'; import modulesRepo from '../../__runtime/modules.js'; import nprogressFn from './nprogress.js'; export default function (Vue) { const loadingQueue = { _queue: {}, push(relativeName, cb) { if (!this._queue[relativeName]) this._queue[relativeName] = []; this._queue[relativeName].push(cb); return this._queue[relativeName].length === 1; }, pop(relativeName, module, err) { if (!this._queue[relativeName]) return; for (const cb of this._queue[relativeName]) { cb(module, err); } delete this._queue[relativeName]; }, }; const nprogress = nprogressFn(Vue); const module = { _get(relativeName) { return Vue.prototype.$meta.modules[relativeName || 'main']; }, get(relativeName) { const module = this._get(relativeName); if (module) return module; // try sync module try { this._require(relativeName); return this._get(relativeName); } catch (err) { return null; } }, set(relativeName, module) { Vue.prototype.$meta.modules[relativeName] = module; if (module.info.monkey) { Vue.prototype.$meta.modulesMonkey[relativeName] = module; } }, // use // relativeName / relativeName-sync use(moduleName, cb) { if (cb) { const moduleInfo = typeof moduleName === 'string' ? mparse.parseInfo(moduleName) : moduleName; if (!moduleInfo) { const message = Vue.prototype.$text('InvalidModuleName'); throw new Error(`${message}: ${moduleName}`); } const relativeName = moduleInfo.relativeName; const module = this._get(relativeName); if (module) return cb(module); const moduleRepo = modulesRepo.modules[relativeName]; if (!moduleRepo) { const message = Vue.prototype.$text('ModuleNotExists'); throw new Error(`${message}: ${relativeName}`); } if (loadingQueue.push(relativeName, cb)) { try { if (moduleRepo.info.sync) { this._require(relativeName, module => loadingQueue.pop(relativeName, module)); } else { this._import(relativeName) .then(module => loadingQueue.pop(relativeName, module)) .catch(err => { loadingQueue.pop(relativeName, null, err); }); } } catch (err) { loadingQueue.pop(relativeName, null, err); } } } else { return new Promise((resolve, reject) => { try { this.use(moduleName, (module, err) => { if (err) return reject(err); resolve(module); }); } catch (err) { reject(err); } }); } }, async tryUse(moduleName) { try { const module = await this.use(moduleName); return module; } catch (err) { return null; } }, loadWaitings() { for (const key in Vue.prototype.$meta.modulesWaiting) { this._registerRoutes(Vue.prototype.$meta.modulesWaiting[key]); } }, monkeyModule(monkeyName, monkeyData) { for (const key in Vue.prototype.$meta.modulesMonkey) { const moduleMonkey = Vue.prototype.$meta.modulesMonkey[key]; if (moduleMonkey.options.monkey && moduleMonkey.options.monkey[monkeyName]) { moduleMonkey.options.monkey[monkeyName](monkeyData); } } }, install(instance, moduleInfo, cb) { // callback const callback = options => { // module const module = { name: moduleInfo.relativeName, info: moduleInfo, instance, options, }; // set this.set(moduleInfo.relativeName, module); // monkey this.monkeyModule('moduleLoaded', { module }); // routes if (!Vue.prototype.$f7) { Vue.prototype.$meta.modulesWaiting[moduleInfo.relativeName] = module; } else { this._registerRoutes(module); } // register resources this._registerResources(module); // invoke onLoaded if (module.options.onLoaded) { module.options.onLoaded(); } // ready return cb && cb(module); }; // install Vue.use(instance.default, callback, { moduleInfo }); }, async _import(relativeName) { return new Promise((resolve, reject) => { const moduleRepo = modulesRepo.modules[relativeName]; if (!moduleRepo) { return reject(new Error(`Module ${relativeName} not exists`)); } nprogress.start(); moduleRepo .instance() .then(instance => { nprogress.done(); if (!instance || !instance.default || !instance.default.install) { instance = window[relativeName]; } this.install(instance, moduleRepo.info, module => { resolve(module); }); }) .catch(err => { nprogress.done(); reject(err); }); }); }, requireAllMonkeys() { for (const relativeName in modulesRepo.modulesMonkey) { const moduleRepo = modulesRepo.modules[relativeName]; this._requireJS(moduleRepo); } }, requireAllSyncs() { for (const relativeName in modulesRepo.modulesSync) { const moduleRepo = modulesRepo.modules[relativeName]; this._requireJS(moduleRepo); } }, _require(relativeName, cb) { const moduleRepo = modulesRepo.modules[relativeName]; if (!moduleRepo) throw new Error(`Module ${relativeName} not exists`); this._requireJS(moduleRepo, cb); }, _requireJS(moduleRepo, cb) { // instance let instance = moduleRepo.instance; if (!instance.default) { instance = window[moduleRepo.info.relativeName]; } // install this.install(instance, moduleRepo.info, module => { // ok cb && cb(module); }); }, _registerRoutes(module) { if (!module.options.routes) return null; const routes = module.options.routes.map(route => { Vue.prototype.$meta.util._setComponentModule(route.component, route.module || module); // path route.path = `/${module.info.pid}/${module.info.name}/${route.path}`; // meta.modal if (route.meta && route.meta.modal) { route[route.meta.modal] = { component: route.component, }; route.component = null; } // meta.auth if (route.meta && route.meta.auth) { route.async = function (routeTo, routeFrom, resolve, reject) { if (Vue.prototype.$meta.store.state.auth.loggedIn) { const _component = {}; if (route.meta.modal) { _component[route.meta.modal] = route.async[route.meta.modal]; } else { _component.component = route.async.component; } resolve(_component); } else { // login Vue.prototype.$meta.vueLayout.openLogin({ view: this.view, url: routeTo, }); reject(); } }; if (route.meta.modal) { route.async[route.meta.modal] = route[route.meta.modal]; route[route.meta.modal] = null; } else { route.async.component = route.component; route.component = null; } } return route; }); Vue.prototype.$f7.routes = Vue.prototype.$f7.routes.concat(routes); }, _registerResources(module) { module.options.components && this._registerComponents(module); module.options.store && this._registerStore(module); module.options.config && this._registerConfig(module); module.options.locales && this._registerLocales(module); }, _registerComponents(module) { for (const key in module.options.components) { const component = module.options.components[key]; Vue.prototype.$meta.util._setComponentModule(component, component.module || module); Vue.prototype.$meta.util._setComponentGlobal(component); } }, _registerStore(module) { if (!Vue.prototype.$meta.store._modulesNamespaceMap[`${module.info.pid}/`]) { Vue.prototype.$meta.store.registerModule(module.info.pid, { namespaced: true, }); } module.options.store.namespaced = true; Vue.prototype.$meta.store.registerModule([module.info.pid, module.info.name], module.options.store); }, _registerConfig(module) { if (module.name === 'main') { // scene module.options.config.scene = process.env.SCENE; // env module.options.config.env = process.env.NODE_ENV; // extend Vue.prototype.$utils.extend(Vue.prototype.$meta._configOriginal, module.options.config); // baseURL if (Vue.prototype.$meta.config.api.baseURL) { Vue.prototype.$meta.axios.defaults.baseURL = Vue.prototype.$meta.config.api.baseURL; Vue.prototype.$meta.axios.defaults.withCredentials = true; } } else { Vue.prototype.$meta._configOriginal.modules[module.info.relativeName] = Vue.prototype.$utils.extend( {}, module.options.config, Vue.prototype.$meta._configOriginal.modules[module.info.relativeName] ); } }, _registerLocales(module) { Object.keys(module.options.locales).forEach(key => { Vue.prototype.$meta.locales[key] = Vue.prototype.$utils.extend( {}, module.options.locales[key], Vue.prototype.$meta.locales[key] ); }); }, }; return module; }