将随机React应用程序转换为微前端的5个步骤
时间:2023-03-14 22:19:33
科技观察
什么是微前端方法?微前端一词最早出现在2016年11月的ThoughtTechRadar中。它将微服务的概念扩展到前端开发。该方法是通过分解应用程序功能将基于浏览器的代码拆分为微前端。通过使代码库更小并以功能为中心,我们实现了解耦软件开发的目标。尽管代码库是分离的,但用户体验是连贯的。此外,每个代码库都可以独立实施、升级、更新和部署。这是微前端的天堂。无论框架和版本如何,javascript应用程序都是由容器启动的。这些应用程序,无论是旧的还是新的,都可以无缝地协同工作,并且类似于一个应用程序。在我们的示例中,我们将处理更简单的React微前端的情况。前端工作是构建一个启动React应用程序的微型前端容器。这个容器需要能够在不知道很多细节的情况下启动一个随机的React应用程序。此外,由于微前端的概念,这一层需要很薄,只有很少的业务逻辑。幸运的是,CamJackson发布了他的微前端作品供我们采用。他的作品位于:容器:微前端演示和容器应用程序的入口点。用于浏览餐厅的微前端:Browse。用于从餐厅订购食物的微前端:RestaurantOrdering。内容服务器:为微前端演示存储静态内容的地方。下面是微前端工作的工作流程:启动内容服务器。在特定端口上启动浏览和餐厅订购应用程序。基于URL,容器将路由到微前端之一。选中的微前端去特定端口获取应用的资产清单.JSON。从此JSON文件中,包含的main.js被放置在脚本标记中并加载。清单文件包含所有资产文件名与其相应输出文件的映射,因此无需解析index.html即可选择它。该容器的核心是以下Microfrontend.js:importReactfrom'react';classMicroFrontendextendsReact.Component{componentDidMount(){const{name,host,document}=this.props;constscriptId=`micro-frontend-script-${name}`;if(document.getElementById(scriptId)){this.renderMicroFrontend();return;}fetch(`${host}/asset-manifest.json`).then(res=>res.json()).then(manifest=>{constscript=document.createElement('script');script.id=scriptId;script.crossOrigin='';script.src=`${host}${manifest['main.js']}`;script.onload=this.renderMicroFrontend;document.head.appendChild(script);});}componentWillUnmount(){const{name,window}=this.props;window[`unmount${name}`](`${name}-container`);}renderMicroFrontend=()=>{const{name,window,history}=this.props;window[`render${name}`](`${name}-container`,history);};render(){return;}}MicroFrontend.defaultProps={document,window,};exportdefaultMicroFrontend;第13到22行包要启动微型前端的代码。通常,微前端之间没有通信,容器和微前端之间的通信有限。总的来说,这是一种从容器到微前端的方式。在这里,第34行传递ContainerID和历史记录,因为它是要呈现的微前端,如下所示:ReactDOM.render(,document.getElementById(containerId));第18行将脚本的Crondorigin值设置为Empty,相当于匿名。这意味着对元素的请求将其模式设置为CORS,并将其凭据模式设置为同一来源。我们在实际代码中修改了Came的示例。无论如何,这是我们使用的基础。基于此,我们可以向您展示如何将您的应用程序转换为微前端。将随机React应用程序转换为微前端的5个步骤我们对随机React应用程序的选择是创建一个React应用程序。将它变成一个微前端是一个五步过程。关于创建React应用程序的10个有趣事实中描述了有关Facebook皇冠上的珠宝应用程序的许多原则。在本文中,我们强调这些原则的应用。第1步:修改package.json以设置端口并使用“React-App-Rewifire”{"name":"my-app","version":"0.1.0","private":true,"dependencies":{"@testing-library/jest-dom":"^4.2.4","@testing-library/react":"^9.4.0","@testing-library/user-event":"^7.2.1","re??act":"^16.12.0","re??act-dom":"^16.12.0","re??act-scripts":"3.4.0","re??act-app-rewired":"2.1.5"},"scripts":{"start":"PORT=4000react-app-rewiredstart","build":"react-app-rewiredbuild","test":"react-app-rewiredtest","eject":"react-scriptseject"},"eslintConfig":{"extends":"react-app"},"browserslist":{"production":[">0.2%","notdead","notop_miniall"],“ddevelopment":["last1chromeversion","last1firefoxversion","last1safariversion"]}}在第12行,添加react-app-rewired作为依赖项,这允许在第15行自定义应用程序而不弹出它,应用程序的启动端口有已从默认端口3000更改为选定的4000-这避免了端口冲突,因为容器本身在端口3000上运行。从第15行到第17行,react脚本由Reft-App-Rewifired替换执行。使用新的端口,创建一个React应用程序来显示如下所示的UI。(我们作弊了一点。使用React-App-Rewired需要在应用程序运行之前更改第2步。)第2步:使用config-overrides.js默认禁用代码拆分,codesplittingenabled.应用程序被分成多个块,可以在页面上独立加载.http://localhost:4000/asset-manifest.json清楚地表明应用程序是捆绑的。这种加载优化可能会导致问题安装和卸载微型前端河我们需要通过创建或编辑config-overrides.js来禁用该块,如下所示:{默认:false,},};returnconfig;},};之后,http://localhost:4000/asset-manifest.json显示没有任何块。如果您没有从CreateReactapp生成Reactapp,您可以通过修改WebPack配置来完成步骤1和2。如果您使用我们改进的MicroFrontend.js,您不必在步骤1中使用React-App-Rewifirew,并且步骤2可以完全跳过。第5步减少到3.5。详细信息在“您不必失去微前端的优化”中进行了描述。此保存在此repo的ChunkOptimization分支中捕获。第3步:更改src/index.js以定义渲染和卸载函数让我们看一下微前端的src/index.js:import'react-app-polyfill/ie11';importReactfrom'反应';importReactDOMfrom'react-dom';importAppfrom'./App';import{unregister}from'./registerServiceWorker';window.renderBrowse=(containerId,history)=>{ReactDOM.render(,document.getElementById(containerId),);unregister();};window.unmountBrowse=containerId=>{ReactDOM.unmountComponentAtNode(document.getElementById(containerId));};window.RenderBrowse和window.unmountBrowse定义。这些方法由容器的Microfrontend.js调用。需要为CreateReact应用程序的src/index.js定义一个类似的方法。importReactfrom'react';importReactDOMfrom'react-dom';import'./index.css';importAppfrom'./App';import*asserviceWorkerfrom'./serviceWorker';//rendermicrofrontendfunctionwindow.renderCreatereactapp=(containerId,history)=>{ReactDOM.render(,document.getElementById(containerId));serviceWorker.unregister();};//unmountmicrofrontendfunctionwindow.unmountCreatereactapp=containerId=>{ReactDOM.unmountComponentAtNode(document.getElementById(containerId));};//Mounttorootifitisnotmicrofrontendif(!document.getElementById('Createreactapp-container')){ReactDOM.render(,document.getElementById('root'));}//如果你想让你的应用离线并加载得更快,你可以改变//注销()toregister()below.Notethiscomeswithsomepitfalls.//了解更多关于serviceworkers:https://bit.ly/CRA-PWAserviceWorker.unregister();从第7行到第19行,正在添加Window.RenderCreateActApp和Window.unmountCreaterActApp。第23行成为一个条件。如果它是一个独立的应用程序,它将呈现为根元素。如果它是一个微前端,它将通过window.rendercreateActapp呈现给ContainID。第4步:使用src/setupproxy.js设置CORS规则在Web浏览器中启动微前端时,我们收到CORS错误:Accesstofetchat'http://localhost:4000/asset-manifest.json'fromorigin'http://localhost:3000'hasbeenblockedbyCORSpolicy:No'Access-Control-Allow-Origin'headerispresentsontherequestedresource.Ifanopaqueresponsesservesyourneeds,settherequest'smodeto'no-cors'tofetchtheresourcewithCORSdisabled.必须通过创建或编辑src/setupproxy.js来设置以下代理.module.exports=app=>{app.use((req,res,next)=>{res.header('Access-Control-Allow-Origin','*');next();});};在继续第5步之前,我们为容器做了一些额外的工作。在.env文件中,需要添加一个新的HostReact_App_CreateActApp_Host。端口4000需要与创建运行ReactApp的真实端口相匹配。REACT_APP_BROWSE_HOST=http://localhost:3001REACT_APP_RESTAURANT_HOST=http://localhost:3002REACT_APP_CREATEREACTAPP_HOST=http://localhost:4000REACT_APP_CONTENT_HOST=http://localhost:5000需要对.env做类似的修改。生产:REACT_APP_BROWSE_HOST=https://browse.demo.microfrontends.comREACT_APP_RESTAURANT_HOST=https://order.demo.microfrontends.comREACT_APP_CREATEREACTAPP_HOST=https://createreactapp.demo.microfrontends.comREACT_APP_CONTENT_HOST=https://content.demo.microfrontends。com在AppHeader.is添加导航链接以使UI易于访问。这是可选的。importReactfrom'react';import{NavLink}from'react-router-dom';import'./AppHeader.css';constAppHeader=()=>(
);exportdefaultAppHeader;将CreateAteActApp及其路径由添加到Container的App.js中:importReactfrom'react';import{BrowserRouter,Switch,Route,Redirect}from'react-router-dom';importAppHeaderfrom'./AppHeader';importMicroFrontendfrom'./MicroFrontend';importAboutfrom'./About';const{REACT_APP_BROWSE_HOST:browseHost,REACT_APP_RESTAURANT_HOST:restaurantHost,REACT_APP_CREATEREACTAPP_HOST:createreactappHost,}=process.env;letnumRestaurants=0;fetch(`${process.env.REACT_APP_CONTENT_HOST}/restaurants.json`).then(res=>res.json()).然后(restaurants=>{numRestaurants=restaurants.length;});constgetRandomRestaurantId=()=>Math.floor(Math.random()*numRestaurants)+1;constBrowse=({history})=>(
);constRestaurant=({history})=>(
);constCreatereactapp=({history})=>(
);constRandom=()=>
;constApp=()=>(
);exportdefaultApp;现在让我们尝试展示我们的微前端内容服务器:npmstart。浏览微前端:npmstart。餐厅订购微前端:npmstart。创建ReactAppMicrofrontend:npmstart.Container:npmstart.进入localhost:3000/createActapp启动页面哎呀,Reactspinninglogs在哪里?让我们重温一下http://localhost:4000/asset-manifest.json的标志对于微前端是一个单独的文件:{"files":{"main.js":"/static/js/bundle.js","main.js.map":"/static/js/bundle.js.map","index.html":"/index.html","static/media/logo.svg":"/static/media/logo.5d5d9eef.svg"},"entrypoints":["static/js/bundle.js"]}忘记抢了!查看这个logoSVG文件的来源,设置为/static/media/logo.5d5d9eef.svg。此文件在CreateReactApp(HTTPS://localhost:4000)中可用,但在容器(http://localhost:3000)中不可用。这是我们的最后一步。第五步:在.env文件中配置contenthost,并用它作为静态内容的前缀创建或编辑.env来设置contenthost:REACT_APP_CONTENT_HOST=http://localhost:4000当微前端使用静态内容时,需要在HTML中%JavaScript中的React_App_Content_host%前缀和JavaScript中的Process.env.reacect_app_content_host。这里我们更改了src/app.js中的第9行:importReactfrom'react';importlogofrom'./logo.svg';import'./App.css';functionApp(){return(
编辑src/App.js
和savetoreload。
LearnReact );}exportdefaultApp;通过此更改,徽标SVG文件的前缀为http://localhost:4000。该应用程序现在工作正常。原文链接:https://betterprogramming.pub/5-steps-to-turn-a-random-react-application-into-a-micro-frontend-946718c147e7