±à¼ÍƼö: |
±¾ÎÄÖ÷Òª½²½âÁ˶Ô΢ǰ¶ËµÄÀí½â¡£ÒÔ¼°ÈçºÎ¿ìËÙµÄʵÏÖÒ»¸ö»ùÓÚ
Vue.js µÄ¼òµ¥Ò×ÓõÄ΢ǰ¶Ë¡£
±¾ÎÄÀ´×ÔÓÚ²©¿ÍÔ°,ÓÉ»ðÁú¹ûÈí¼þAnna±à¼ÍƼö¡£ |
|
ÔµÆðºÎ´¦
ÎÒÃÇÍŶÓÔÚ¹«Ë¾ÄÚ²¿Ö÷ҪΪ¹úÄÚij TOP3 ½¨Öþ¹«Ë¾±àд ERP Öкǫ́ӦÓã¬ÓÉÓÚÊǽ¨ÖþÁìÓò£¬Æä ERP
ϵͳʮ·ÖÅÓÔÓ¡£ÔÚÎÒÓÚ 2018 Äêµ×Èëְʱ£¬¸Ãϵͳ¾ÍÒѱàдÁËÈýÄê¡£µ«ÊÇÓÉÓÚÐèÇó·½ÒÀÈ»ÔÚÌáÐèÇó£¬ËùÒÔÒÀÈ»ÔÚ±àдÐÂÓ¦Óã¬Î¬»¤£¬µü´úºÍÖØ¹¹¡£
ÍŶÓÄÚ²¿ºó¶Ë¼¼ÊõÕ»ºó¶ËÖ÷ÒªÊÇ Java£¬Ç°¶ËÖ÷ÒªÊÇ Vue.js£¬CI/CD ÊÇ Jenkins
+ GitLab£¬¼à¿ØÏµÍ³Ê¹Óà Sentry£¬°ü¹ÜÀíÆ÷ʹÓõÄÊÇ Nexus (Ö§³Ö npm &
maven)¡£
ÒòΪÍŶÓÖкܶà CRUD ½çÃæ¶¼ÊǺó¶Ëͬѧ×Ô¼ºÂëÁËÖ®ºóµ÷½Ó¿Ú¡£ÉõÖÁºÜ¶àͬѧÔÚʹÓõÄʱºòÁ¬ Vue.js
Îĵµ¶¼Ã»¿´¹ý¡£²»ÒªÎÊΪʲô£¬ÎʾÍÊÇ Vue.js ºÃÉÏÊÖ¡£
µ±Ê±ÍŶÓÄÚ²¿µÄǰ¶Ë±àдģʽÊÇ£¬ÔʼÏîÄ¿ A ʹÓà Vue-CLI2 ´´½¨¡£ÏÖÔÚÐèÇó·½Ìá½»ÐÂÄ£¿é B
µÄÐèÇó¸øµ½²úÆ·£¬µ±²úÆ·½»¸¶ÔÐÍͼºó£¬ÏîÄ¿ Leader ¸´ÖÆÏîÄ¿ A ¸Ä¸ÄÅäÖóÉÁËеÄÏîÄ¿ B¡£
ÓÉÓÚÔÚÎÒÃǵÄÏîÄ¿ÖдæÔÚÐí¶à²»Í¬ domain£¬±ÈÈç /notify, /workflow, /construction,
/appMgt, /form, /auth, /print, /pan, /market, /hr,
/asset µÈ¡£Ö®Ç°ÎÒÃÇʹÓà nginx ·´Ïò´úÀíʵÏÖ domain ·Ö·¢µ½¶ÔÓ¦ÏîÄ¿¡£ÔÚÓ¦Óò¼¾ÖÖж¥²¿²Ëµ¥Ö±½Ó·Ö³ÉÁË
notify.example.com£¬ workflow.example.com À´ÊµÏÖ²»Í¬ÏîÄ¿ domain
µÄ·Ö·¢¡£
Ëæ×ÅÏîĿԽÀ´Ô½¶à£¬±©Â¶µÄÎÊÌâÔ½·¢Ã÷ÏÔ£º
¼¼ÊõÕ®¶Ñ»ý
´úÂëÖØ¸´ºÍÈßÓà
ÏàͬÒÀÀµµÄ°æ±¾ÎÊÌâ
ÖØ¸´ÒÀÀµµÄ¼ÓÔØºÍÖ´ÐÐ
ÏîÄ¿¸öÊý¸úά»¤³É±¾ÕýÏà¹Ø
¹«¹²´úÂëµÄ¸üÐÂÐèÒª¸´ÖÆÕ³Ìù²¢¹¹½¨ËùÓÐÏîÄ¿
ÕÒµ½ÎÊÌ⣬½ÓÏÂÀ´¾ÍÊǽâ¾öÎÊÌâÁË¡£ÔÚ2018 ÄêÇ¡·êÆäʱµØÁ˽⵽ Micro-FrontEnds ¸ÅÄîºó£¬ÌæÎÒÃÇÖ¸Ã÷ÁË·½Ïò£¬ÎÒÃÇÒ²ÐèÒªÔÚÏîÄ¿ÖÐʵÏÖÀàËÆÎ¢Ç°¶ËµÄ¸ÅÄîÀ´½â¾öÉÏÊöÎÊÌâ¡£
ÓÚÊÇ£¬¿ªÊ¼ÔÚÉçÇøµ÷ÑС£µ±Ê±Ð´Î¢Ç°¶ËµÄÎÄÕ²¢²»¶à£¬Êµ¼ùµÄÍŶÓÒ²±È½ÏÉÙ£¬ÁôÏÂÓ¡Ïó×îÉî¿ÌµÄÊÇÕâÆªphodal/microfrontendsÎÄÕ£¬ÎÄÖÐÌáµ½ÁË΢ǰ¶ËµÄ¸÷ÖÖʵÏÖ·½Ê½¡¢ÊµÏֳɱ¾¡¢¹¤³Ì³É±¾µÈÎÊÌ⣬±È½ÏÈ«Ãæ¡£
ÕæÕýÒâÒåÉϵÄ΢ǰ¶ËÓ¦¸ÃÊÇ¿ò¼ÜÎ޹صģ¬ÏÖÔÚÉçÇøÖÐÊ×ÍÆ Single-SPA¡£µ«ÊÇÔÚ 18 ÄêµÄʱºò£¬Single-SPA
»¹Î´ÍêÈ« Production Ready£¬ÓÚÊÇÎÒÃǾö¶¨ÊµÏÖÎÒÃÇÍŶÓÄÚ²¿µÄ΢ǰ¶Ë¿ò¼Ü¡£
ÒòΪ¼¼ÊõÕ»ºÜͳһ£¬ËùÒÔÎÞÐè×öµ½¿ò¼ÜÎ޹أ¬ÎÒÃÇ×îÖÕµÄÑ¡ÔñÊÇ΢ǰ¶Ë£ºÎ¢Ó¦Óû¯¡£Ëü²»½öÍêÃÀ½â¾öÁËÉÏÊöÎÊÌ⣬ͬʱʵʩ³É±¾µÍ¡¢¼¼ÊõÄѶÈС¡¢Î¬»¤³É±¾µÍ¡£
΢ӦÓû¯
ÔÚ¶à domain ʱͨ¹ý nginx ·´Ïò´úÀíµÄÇé¿öÏ£¬Î¬»¤¹«¹²´úÂëºÜÍ´¿à¡£½«¸÷¸öÒµÎñÄ£¿é²ð³É×ÓÓ¦ÓÃºó£¬Æä¸÷¸öÒµÎñµÄ¹«¹²²¿·ÖÔò±»²ð³É¶ÀÁ¢µÄÓ¦Óá£ÉçÇø³ÆÖ®Îª»ù×ùÓ¦Ó㬻òÕßÖ÷Ó¦Óá£
ÎÒÃǽ«ËùÓÐ domain ¼´×ÓÓ¦ÓõĹ«¹²²¿·Ö·â×°µ½Ö÷Ó¦ÓÃÖУ¬µ¥¶Àά»¤£¬Í¬Ê±·¢²¼µ½ÄÚ²¿
npm ˽²Ö¡£ÒÔ¸ø×ÓÓ¦ÓÃÔÚ¿ª·¢»·¾³Öн«Æä×÷ΪÒÀÀµ°²×°¡£ÔÚÐèÒªÐ޸Ĺ«¹²´úÂë»òÕßÌṩ¹«¹²·þÎñµÄʱºò£¬Ö»ÐèÒªÖØÐ¹¹½¨ºÍ²¿ÊðÖ÷Ó¦Óü´¿É£¬½â¾öÁËÒ»´óÍ´µã¡£

ͼƬժ×Ôphodal/microfrontends
²»¹ýÎÒÃǵÄʵÏÖϸ½ÚÉÏÓÐËù²»Í¬£¬ÎÒÃǽ« URL Change ½»ÓÉ VueRouter µÄ beforeHook
´¦Àí£¬½« Ó¦ÓùÜÀí·þÎñ¡¢Loader¡¢install µÈ½»ÓÉ VueMfe ´¦Àí¡£
Ö÷Ó¦ÓÃ App

Ö÷ÔËÐÐʱ±¾ÉíÒ²ÊÇÒ»¸ö¶ÀÁ¢ÍêÕûµÄÓ¦Ó㬶ÀÁ¢ÔËÐС¢¿ª·¢ºÍ²¿Êð¡£ÎÒÃǵÄÏîÄ¿ÖУ¬Ö÷Ó¦Óðüº¬ÁËÏÂÁÐÄÚÈÝ£¨Í¨³£¶¼°üº¬ÁËÒÔÏÂÄÚÈÝ£©£º
¹«¹²ÒÀÀµ

ÔÚÎÒÃǵÄÏîÄ¿ÖÐʹÓà UMD ÒýÈ빫¹²ÒÀÀµ£¬Í¬Ê±Î¬»¤ÁËÒ»·Ý¹«¹²µÄ Webpack externals
ÅäÖã¬ÒÔ±ÜÃâÖ÷Ó¦Óú͸÷¸ö×ÓÓ¦ÓÃÔÚ´ò°üÊ±ÖØ¸´¹¹½¨¹«¹²ÒÀÀµ¡£
¹«¹²ÅäÖ㬱ÈÈ磺Webpack ÅäÖã¬Env Variables ÅäÖã¬App ÅäÖõÈ
¹«¹²²å¼þ£¬±ÈÈ磺ProgressBar, MicroFrontend, LazyLoad, Vuex,
VueRouter, Element-UI µÈ
¹«¹²·þÎñ£¬±ÈÈ磺Utils, Http, Socket, Storage µÈ
¹«¹²Êý¾Ý£¬±ÈÈ磺Auth, Config, Message µÈ Vuex modules£¬ÎÒÃÇͨ¹ý
Vuex ʵÏÖÈ«¾Ö Store ¹²Ïí£¬½èÖúÆä dynamic-module-registration
µÄÄÜÁ¦£¬ÊµÏÖ×ÓÓ¦ÓÃÖ®¼ä¹²ÏíÊý¾ÝµÄ×¢²áºÍÏú»Ù¡£
¹«¹²¼øÈ¨ºÍУÑ飬±ÈÈ磺·ÓÉȨÏÞУÑé Router before/after Hook¡¢Óû§½ÇɫУÑé
AuthManager.hasAuth(authKey) µÈ¹«¹²×´Ì¬Ð£Ñé
¹«¹²×ÊÔ´£¬±ÈÈ磺Ñùʽ¡¢×ÖÌ塢ͼ±ê¡¢Í¼Æ¬¡¢Theme ±äÁ¿
¹«¹²×é¼þ£¬±ÈÈ磺<ContentBlock />,<FilePreview />
µÈ
¹«¹²²¼¾Ö£¬±ÈÈ磺<DefaultContainer />, <DetailContrainer
/> µÈ
¹«¹²Â·ÓÉ£¬±ÈÈ磺/index, /error/401,/error/404 µÈ
×ÓÓ¦ÓÃ SubApp
ÔÚÌá³öÁËËùÓй«¹²´úÂëÖ®ºó£¬×ÓÓ¦Óñä³ÉÁË´¿ÒµÎñ´úÂëµÄÈÝÆ÷±»Ö÷Ó¦ÓÃÔÚÔËÐÐʱ¼ÓÔØÖ´ÐС£Òò´ËÔÚÆô¶¯×ÓÓ¦ÓÃ֮ǰÐèÒªÏÈÆô¶¯Ö÷Ó¦Óã¬ÒÔÓµÓÐÖ÷Ó¦ÓÃÔËÐÐʱµÄÄÜÁ¦¡£
ÔÚ¿ª·¢»·¾³Ï£¬½«×ÓÓ¦ÓõÄÈë¿ÚÉèÖÃΪÖ÷Ó¦Ó㬼æÈÝÖ÷Ó¦ÓÃµÄ Webpack ÅäÖ㬽« devServer
µÄ contentBase Ò²ÉèÖÃΪÖ÷ÔËÐÐʱµÄ public Ŀ¼£¬ÒÔ±£³ÖÖ÷Ó¦ÓÃ/×ÓÓ¦Óÿª·¢ºÍÉú²ú»·¾³ÏµÄÒ»ÖÂÐÔ¡£
vue.config.js:

×ÓÓ¦ÓÃͨ¹ýÖ÷Ó¦ÓõÄÖÐÐÄ»¯Â·ÓÉ£¬¶¯Ì¬¼ÓÔØÖ´ÐС£¶øÔÚ Vue.js ÖУ¬ÈçºÎʵÏÖÖÐÐÄ»¯Â·ÓÉÄØ£¿Vue-Router±¾ÉíÌṩÁËrouter.addRoutes(routes:
Array<RouteConfig>)µÄAPI£¬µ«ÊÇÕâ¸ö API ÓÐÒ»¸öºÜÖÂÃüµÄȱµã£¬¾ÍÊDz»Ö§³ÖǶÌ×·ÓÉ£¬¶øÔÚʵ¼ÊÒµÎñÖУ¬×ÓÓ¦ÓÃͨ³£¶¼ÊÇij¸ö
Layout ϵÄǶÌ×·ÓÉ¡£¾ßÌå¿ÉÒԲο¼Õâ¸ö ISSUE µÄÌÖÂÛ£¬Dynamically add child
routes to an existing route£¬¸ù¾Ý vuejs/rfcs Dynamic
routing £¬¹Ù·½ÍŶÓÒ²ÕýÔÚÕ÷¼¯ÉçÇøÒâ¼ûºÍʵÏÖÕâ¸ö¹¦ÄÜ¡£
ΪÁ˽â¾öÕâ¸öÎÊÌ⣬ÐèÒªÎÒÃÇ×Ô¼º´ò²¹¶¡ÔöǿһÏ VueRouter µÄ addRoutes ¹¦ÄÜ£¬ÊµÏÖÖ§³Ö¶¯Ì¬Ç¶Ì×·ÓÉ¡¢¶¯Ì¬¼ÓÔØÓ¦Óõȹ¦ÄÜ¡£Õâ±ãÊÇ
vue-mfe µÄÓÉÀ´¡£
¶¯Ì¬Ç¶Ì×·ÓÉ
vue-mfe ÄÚ²¿Î¬»¤ÁËÒ»Ì×¶ÀÁ¢µÄpathListºÍpathMap£¬ËäÈ»¶ÀÁ¢Î¬»¤£¬»áÔö¼ÓÄڴ濪Ïú³É±¾£¬ºÃ´¦ÊDz»»á¶ÔVueRouter±¾ÉíµÄ¹¦ÄÜÔì³ÉÈκÎÓ°Ïì¡£
µ±µ÷ÓÃ router.addRoutes(routes: RouteConfig[], parentPath:
string)ʱ£¬Éî¶ÈÓÅÏÈÕÒµ½ parentPath ËùÔڵľÉ·ÓÉ oldRoute£¬²¢½«Æä children
ÓëÐ嵀 routes ºÏ²¢ºóÉú³ÉеķÓÉ options: newRouterOptions¡£
ÔÙʹÓà options: newRouterOptions ÖØÐÂʵÀý»¯ new VueRouter(options:
newRouterOptions)£¬Äõ½Ð嵀 router.matcher ²¢½«Æä¸³Öµ¸øapp.$router.matcher
ÒÔ´ïµ½Ö§³Ö¶¯Ì¬Ç¶Ì×·ÓÉ¡¢¶¯Ì¬¸üÐÂÓ¦Ó÷ÓÉ×¢²á±íµÄÄ¿µÄ¡£
¶¯Ì¬¼ÓÔØÓ¦ÓÃ
ʹÓÃVueMfe.createApp(AppConfig)×¢²á΢ǰ¶ËÖ÷Ó¦ÓÃApp£¬³õʼ»¯ Router£¬Ë¢ÐÂ
VueMfe ÄÚ²¿Â·ÓÉ×¢²á±ípathListºÍpathMap¡£
×¢²á beforeEach ¹³×Ó£¬À¹½ØÂ·ÓÉtoÊÇ·ñÒÑ´æÔÚÓÚµ±Ç°Â·ÓÉÖУ¬Èô²»´æÔÚÔòÈÏΪÕâÊÇÒ»¸öÐèÒª±»¶¯Ì¬¼ÓÔØµÄ×ÓÓ¦Óá£
Ö´ÐÐgetAppPrefix(to)»ñÈ¡µ±Ç°Â·ÓɵÄ×ÓÓ¦ÓÃprefixǰ׺£¬Ö´ÐÐ install ·½·¨¡£
install»á³¢ÊÔÓÅÏÈ»ñÈ¡ SubApp ×ÔÉíµÄ resources ÅäÖà config.resources[prefix]£¬Æä´ÎÈ¡Ö÷Ó¦ÓõÄ
resources ÅäÖá£Èç¹û¶¼»ñÈ¡²»µ½£¬Ôò»áÅ׳öÎÞ·¨ÕÒµ½ prefix×ÊÔ´µÄÒì³£¡£
»ñÈ¡µ½ SubApp ×ÊÔ´ºó£¬¹ã²¥¼ÓÔØ¿ªÊ¼LOAD_STARTʼþ£¬¿ªÊ¼°²×° SubApp µÄ¾²Ì¬×ÊÔ´ºÍ·ÓÉ£¬Ö´ÐÐ
SubApp µÄ init ³õʼ»¯·½·¨£¬¼ÓÔØ³É¹¦ºó¹ã²¥¼ÓÔØ³É¹¦LOAD_SUCCESSʼþ¡£
Ö´ÐÐ next(to) Ìø×ªµ½Óû§·ÃÎʵÄ·ÓÉprefixʵÏÖÍêÕû±Õ»·¡£

¹¹½¨×ÓÓ¦ÓÃ
ÒòΪ²»Í¬µÄ App Óɲ»Í¬µÄ webpack build context ¹¹½¨£¬ÎÞ·¨¹²Ïí chunkId
ºÍ moduleId¡£ËùÒÔÐèÒª½«×ÓÓ¦Óôò°ü³É umd ¸ñʽµÄ library£¬±©Â¶ SubApp µÄÅäÖÃÏîµ½
root È«¾Ö±äÁ¿¹© VueMfe °²×°¡£¶øÇÒºóÐøÆäËû×ÊÔ´¿ØÖÆÈ¨Ôò¼ÌÐø½»ÓÉ webpack ¿ØÖÆ¡£
¶øÔÚ 19 ÄêÄ©ÓÐÁË webpack5 ÌṩµÄ module-federation £¬ÕýʽΪÁ˽â¾öÕâ¸öÎÊÌâÌá³ö£¬µ«Ä¿Ç°»¹ÊÇ
beta °æ±¾¡£ÐÂÊï¹â£¬¶øÇҺܶà´óÀÐÒѾ¿ªÊ¼ÁË̽Ë÷¡£ºóÐø£¬»á¼ÌÐø¸úÉÏ webpack5 µÄÉý¼¶¡£
¹¹½¨²½Ö裺
½«×ÓÓ¦Óôò°ü³É umd ¸ñʽµÄ library¡£
¹¹½¨µÄÈë¿Ú±ØÐëÊÇ export default VueMfe.createSubApp(SubAppConfig)µÄÎļþ£¬ÒÔ±£Ö¤
root µÄ È«¾Ö±äÁ¿ÊÇ SubAppConfig ¹© VueMfe Ö±½Ó°²×°¡£
Èç¹ûÓÐʹÓà CDN Ôò½« CDN µØÖ·ÅäÖõ½ SubApp »òÕß App µÄ resources ¼´¿É¡£
ÔÚÎÒÃÇÍŶÓÖУ¬ÔÚ¸üе½ vue-cli3 Ö®ºó£¬ÒòΪ cli3 ·â×°ÁËËùÓÐµÄ webpack ÅäÖã¬Í¨¹ý
service api ÐÎʽ±©Â¶£¬ËùÒÔдÁËÒ»¸ö²å¼þ vue-cli-plugin-mfe À´¹¹½¨×ÓÓ¦Óá£ÎÒÃÇ·Ö±ð²ð·ÖÁË
3 ¸ö command£º
build¹¹½¨ umd ¸ñʽÎļþ
uploadÉÏ´«¹¹½¨ºóµÄÎļþµ½ CDN
publish·¢²¼Ó¦ÓÃ֪ͨ¸üÐÂǰ¶Ë×ÊÔ´
build µÄÖ÷Òª´úÂëÈçÏ£º
1.ɾ³ýÁË vue-cli3 ×Ô´øµÄÏà¹Ø²å¼þ£¬ÕâЩ²å¼þ¶ÔÖ÷Ó¦ÓÃÉúЧ¼´¿É£¬×ÓÓ¦Óò¢²»ÐèÒª£º
api.chainWebpack((config)
=> {
config.plugins
.delete("html") // for cli-3.2+
.delete("html-index") // for cli-3.5+
.delete("prefetch")
.delete("prefetch-index")
.delete("preload")
.delete("preload-index")
.delete("workbox")
.delete("workbox-index")
.delete("copy")
.delete("pwa")
.end()
}) |
2.ÅäÖÃ×ÓÓ¦Óôò°ü³É umd ¸ñʽ£¬¼°ÆäÈ«¾Ö±äÁ¿Ãû³Æ
api.configureWebpack({
// ´ò°üÈë¿Ú
entry: "./src/portal.entry.js" ||
options.entry, // options.entry
devtool: args.disableSourceMap ? false : "source-map",
// disable all
output: {
path: api.resolve(args.output),
library: {
root: "__domain__app__" + camelizedName,
amd: packageName,
commonjs: packageName,
},
libraryTarget: "umd",
filename: "js/" + camelizedName +
"-[chunkhash:8].umd.js",
// libraryExport: name,
chunkLoadTimeout: 120000,
crossOriginLoading: "anonymous",
},
optimization: {
splitChunks: {
cacheGroups: {
vendors: {
name: camelizedName + "-" + "chunk-vendors",
// eslint-disable-next-line no-useless-escape
test: /[\\\/]node_modules[\\\/]/,
priority: -10,
chunks: "initial",
},
common: {
name: camelizedName + "-" + "chunk-common",
minChunks: 2,
priority: -20,
chunks: "initial",
reuseExistingChunk: true,
},
},
},
},
plugins: [
args.downloadUrl &&
new WebpackRequireFrom({
path: args.downloadUrl + args.name + "/",
}),
new WebpackManifest(),
new WebpackArchiver({
source: api.resolve(args.output),
destination: outputPath,
format: "tar",
}),
].filter(Boolean),
}) |
»Ø¹ËÀú³Ì
½ØÖ¹Ä¿Ç°ÎªÖ¹£¬ÍŶÓÄÚÒÑʹÓÃ΢ǰ¶Ë¼Ü¹¹ 1 Äê¶àÁË¡£ËäÈ»²»¹»ÍêÃÀ£¬»òÕßһЩ¸ÅÄîÔÚÈÕÐÂÔÂÒìµÄǰ¶ËÁìÓò¿ÉÄÜÒѾ¹ýʱ¡£µ«ÊÇÕâÌ×·½°¸£¬ÔÚÍŶÓÄÚ²¿ÇÐÇÐʵʵ½â¾öÁË¿ªÆªÌáµ½µÄÖÖÖÖÎÊÌâ |