vue、react等单页面项目应该这样子部署到服务器.docx
服务端渲染:next. js. nuxt. js等服务端渲染框架构建的项目部署到服务器,并用PM2守护程序最近好多伙伴说,我用vue做的项目本地是可以的,但部署到服务器遇到好多问 题:资源找不到,直接访问以dcx.比;恒/页面空白,刷新当前路由404。o o用react做的项目 也同样遇到类似问题。现在我们一起讨论下单页面如何部署到服务器?由于前端路由缘故,单页面应用应该放到nginx或者apache、tomcat等web代 理服务器中,千万不要直接访问index.html,同时要根据自己服务器的项目路径 更改react或vue的路由地址。如果说项目是直接跟在域名后面的,比如:http: ,根路由就是 7'o如果说项目是直接跟在域名后面的一个子目录中的,比如:http: ,根路由就是'/children ,不能直接访问 index.htmlo以配置Nginx为例,配置过程大致如下:(假设:1、项目文件目录:/mnt/html/spa(spa目录下的文件就是执行了 npm run dist后 生成的dist目录下的文件)2、访问域名:)进入nginx.conf新增如下配置:server listen 80;serve、八spasosout.coi;rootindex Mdex.html;location 八/favicon.ico$ root /"mt/k力)location / try .files furi furi/ /i 八* g况心击a/Stntc:八cti。八。/ somc thing为)* ES6写法(通过es6类的继承实现时state的初始化要在contractor中声明):* class exaipleCoipoieit extends Rcact.Comp。八。t cotriACtoir(prop)* s?c / rops);thsstate = example: 'example'*)*)Vimport React, Com?。八ent, PropTypcs frok Yeact1; / react 核心 import Router, Root%Redirect, I八dexRonte, browserHistory, story froh eact-router1; / 仓ll建 route 所需import Config owx L/co八fig/Mdex'iMport layout froix ycoipoMit/layout/layout1; / 布局界面import (ogM Fkom L/c。八taMedogi八/logM,; / 登录界面/*为(路由根目录组件,显示当前符合条件的组件)兴* class Roots* extc八ds ConA?o八c八珏关/class Roots extends C。岬。八"t %八戏匕0 /这个组件是一个包裹组件,所有的路由跳转的页面都会以防匕八的形式加 载到本组件下return (divthis.pn)ps.chiE 七人卜/div);)/ const history = pocess.CAV.NODE_EN/ !二二'prodbictio ? browserHistory : hashHistorg;/ 快速入门 covst konAC = (location, ch) => cbull, Keq"eC./c0nt4MeKS/ho3c/kokc/hdex').def4a/2)/ 百度图表-折线图 co八st ckartLiie = (location cb) => reqiAire.esurequire => c。(八ireq认ihc('./co八taicers/chairts/(iAes').4efaL(lt)JckrtLi 八 c);)/ 基础组件-按钮 c。八st button = (location cb) => reuire.esuref, require => cb(iL(ll, Keqa"eC./co八八ers/gehcrH/btto八伉dcx').dcf4a化)/ 基础组件-图标 c。八st "。八=(location, cb) => %"ire.ehsure reurre => c。(八川。reqiAire(,./coitaiiaers/geeiral/icoyldexldefault) Jico");)/ 用户管理 const user = (location, cb) => reqiAire.eisurequire => c。(八化 yequi匕优。./co八±4以ed/aseK/aseK伉dex)def化) JseL);)/ 系统设置 const setting = (location, cb) => reqiAire.eisure(? require => c。(八Yeq(Aiye(',./c。八tai八ers/setti八g/setti八gl八dex).defabdt) , 1 setting1);/ 广告管理 const adver - (location, cb) => reqiAire.eisure(, require => cb(八川。ireq(Aire(,./coitaiers/adveir/adverlidex,ydefaiAlt>) LZdvcF);)/ 组件一 co八st o八如二(location, cb) => require(j require => cbullj req认ire('/co八tai八ers/认i/o八el八Hex'),Wefa认也)jo 八cr);)/ 组件二 coiriSt twoui = (location, cb => reqiAire.eiASurequire => cb(八rcq(AircC/c。八taMe匕/ui/tw。【八dcx')defabdt)? 'twoui1);/ 登录验证 const reu/reAutM = (iextState, replace => let token = (new PateO).getTiieQ - Coifig.localltei(,USER._AUTHORlZATlON,>);if(toke八 > 72.00000) / 模拟 Token 保存 2 个小时replace(path 八 ame/bgMLstate: 八cxtP”协八mc: nextState.Iocatioi.pathia);)co八st RobcteConfig =(<Router history=browserHistory>Route pa协二/kohc coipoieit-layout o八E八ter=rcq»eA协MdcxRobctc getCok?。八c八七二kokc。八E八tc匕=reqa/'rcAatk /> / 默认加载的组件,比如访问会自动跳转到www.test.coi/love<R.oute path二/kohc gctCo3?o八e八2二koiMc o八Ehter=reqiKeAth) /> <Route path="/chart/【Mc g况Cohp。八e八七二chartLi八eo八E八ter=r*eqircA网 /><Ro(Ate path="/geieral/huttoi" getC。叫>。八。t=btt。八。八E八ter=Keqw'rcA”网 /><Route path-'7geieral/icoi" getCo3Po八c八七二ico八) on.En.ter=reuireAuth/><Route path二/”scr gctCon/1?o八ent=scr。八Enter=rcqixireA协) /><Route path="/settMg" getConApo八e八七二setting o八E八ter=KcqircAtk /><Route path'/adver" getCoMpo八c八土二adver on.Eiater=re6/u/reAutM) /><Route path="/ui/o八。以"gctComp。八ent=。八cf on.Enter=reuireAuth /><Route path="/ai/twoL(i getCoipoMt=twob(i。八E八ter=reqaireAa网 />/Route<Route path="/(ogM" c。3?。八c八土二Roots/ 所有的访问,都跳转到 Roots次dexRoatc com?。八。八七=/ogi八 /> /默认加载的组件,比如访问。m会自动跳转到</Route> Redirect frov=/*,/ 2。="/kokc" /></Router> );) J222S#慕圃训苴# d中#曷训苴#(.Ajp,)adieaj39udsnop)pitqopuddde*Apoq>u»n>op 0<JdpJAOJd/><ajo)sHajo)s japTAOJd>)japuaj打即网/ L;()ams”6ao”)6o;adiosuo3 /:H-JI / <= ()aqiJ3sqns ajois,.$S31 uouro»31Aw. uoduiT 隼版?/3llWlod-lgeq, ”ods号士就ift劈依。)。*>39、2S、弓。神飘M9SJ程'昭果第3“法H11*181幼/Ijodurr jodurr )JOdWT IJOdmj )jodwr里里WHXWIM / f.noj/jnoj/-.出。八no “1。,丫|3 / !.ajos/ajos/xnpaj/aa w。” ajois ?PTAOdJ察if,'我蚓KRxn时由CRi/ J.xnpaj-oeaj. g ( japjAOJd )囤N8I道* / J.wop-:3edjt idoj (“u> > 'N0(nx初o)sih eiueig MeyOSHMMI 4弟第"fftS困'QIHJaj / 鼠"R。."o ( sXAidcud ')guoO«o3 ) I川如s“仙 318”。】5 61) 3叫1 EZsjoinqij:uo9 oqPA!dqPA!dxspdde / ojs / p)ue-)oeaj joiseuj :y9uejg鹏。”。才川力叫2P "0dX2“St0 8(9;serve、八aitdsosoiAt.coiv;root /Mnt/h±M(/YcactA八td;index i八dex.ktW;location 八/favic。心ic。* root /m八t/htm(/veactA八td;) location / trg_files 料H *“ri/ router;M4cx 证dcx.ktn/U;pn)xg_set_hcadeHHost$host;poxg_setjxeadc 忆X-Rea(-IP$ireivote_addnpgxg_setJcadeYX -Forwarded-For *proxg_add _x_fo rwa rded_fo r;proxg_sct_kc«dcrX-Forwarded -Proto 轲Mcmc;location ro(Ater rewrite 人.美$ /Sdex.htM( break;accessog /mt/ogs/hgi 八 x/ccessJog vaiia;srpeajsfanAs0e|n6uexui6uxnu!|(#慕囤训苴#Host于host;proxyX-Real-IP$reiote_addnpKoxg_set_headcYX-Forwarded-For * psxg_aHd _x_fo irwa rdedjo r;pg乂 g_sct_hea,wX-Forwarded -Proto 轲 cheMe;accessjog /iit/logs/igiix/acce.log注意事项:工、配置域名的话,需要80端口,成功后,只要访问域名即可访问的项目2、如果你使用了忆4比-匕。笈匕的browserHistory模式或ve-Koatcr的history模式,在八gMx配置还需要重写路由:server listen 80;serve、八 "Me spasosobct.coM;root /m八±/人七/62;index,八dex.kt&/;location 八/faviconico$ root /n/mt/k力W/sp可location / tiry_files $" fallback;Mde乂 M&x.ktml;Host于host;proxy _set_eaderX-Real-IP$reiote_addnproxy_setReaderproxy_setReaderX-Forwarded-For * pexg_aHd _xJo irwa rded_fo r;X-Forwarded -Proto 于 scken/e;location fallback rewrite A.关,/i八dcx.ktM/ hireak)accessog /恒八 t/ogs/八gi n x/“ccessog iaiia;为什么要重写路由?因为我们的项目只有一个根入口,当输入类似/k0MC的时,如果找不到对应的页面,八gi八x会尝试加载i八dex.ktnM 这是通过react-router或/ue-router就能正确的匹配我 们输入的/ko3e路由,从而显示正确的人。出。页面,如果browserHistory模式或histoirg模式的项目 没有配置上述内容,会出现404的情况。简单举两个例子,一个vue项目一个react项目:vue项目:域名:Branch: master vue-taobao / src / router / index.jsO sosout登录拦截1 contributor47 lines (40 sloe) 1.04 KBimport App from ./App'3 首页const home = r => require.ensure(, () => r(require(*./page/home/index')f 'home')6 /物濠const logistics = r => require.ensure(, () => r(require('./page/logistics/index1),9 /购物车const cart = r => require.ensure(, () => r(require(./page/cart/index'), cart*)18 /我的const profile = r => require.ensure(, () => r(requireC1./page/profile/index1), *pr 141 s / 31而iipoirt App froh 匚/App'/ 首页 co八亢 home = r => 匕四川'七.0八6%(口/ () =>八dex') Jkohe')/ 物流 c。八st logistics = r =>()=> 夕(vcq认i./pagc/1ogistics/i八de乂')logistics,)/ 贝勾物车 cost cart = r => Keqaire.e八() => 丫(requireC./pagc/cart/i八4。乂),/ 我的 cot profile = r => reqaire.e八()=>keq认Mc('/page/profi(e/i八dex'),profile1)/ 登录界面 coist logii = r => 小俨,匕,0八6%(口()=> r(reqiKcC./p4ge/seK/ogi") J(ogi")export default patk. 7Z?component: App, /顶层路由,对应对屹x.ktMchildren: path: '/homcL / 首页component: homeL(path '/logistics / 物流com?。八。t: logistics,veta: logits: true)L(path: 7cart,J / 购物车coipoMiat: cart,login; true),patk '/profile1, / 我的c。叫2。八c八t: profileL(path: '/(ogM / 登录界面com?。八。t: (oginpath:保Lredirect: Vkoie1)2 (runtime-only or standalone) has been set in webpack.base.conf with an alias.3 import Vue from 'vue,import VueRouter from 'vue-router,import routes from ./router/index,importFastClick from ,fastclick,6 importStorage from store'import Config from 1./config/index'7 importstore from *./store/1import'./config/rem112 if (addEventListener1 in document) document.addEventListener(,DOMContentLoaded, function () 13 FastClick9attach(document.body)14 18Vue.config.productionTip = falseVue. use( VueRouter)22 const router = new VueRouter(23routes,24mode: Config,routerMode,25strict: != "production,26scrollBehavior (to, from, savedPosition) 27if (savedPosition) 28return savedPosition29 else 30if (from.meta.keepAlive) 3.from.meta.savedPosition = documentbody.scrollTop3233return x: 0, y: to.meta.savedPosition | 0 3435坤d/-犷2才_ X*。阴,soh/砰 u2M ? kfixo/dfjWIJ*X9/2W xopuj印叫冈 /,以力右 P舛5刃弓54 / AOyOQO(fqj/WV/juvu/ ?。/ 本O2VO2”UJ/v AOyOQOf)A/l4“X砰列 xapwfqj/jwiw/juwi/ j。/fWI。力。SOS'q? 2AAVA。8 V 邓“ J2AJ2s#层明训苴#办H#曷圃训苴#iuoD-inosos-piue/:dnq :后狗:自西Peaj(#慕囤训苴#(fwvwi6。1 5S2229/XU 旧U/s6oj/?UWI / 6oSS2gb(fy/U2/q )W4“X叩V/)型叫眄 AOyVQO(f2W12Vps本 OJOJJ- pdpjv/vjo x j?pvsfixojdfjv/vj of)r 抨 kfixo/d* joj-p?pjv/vjoj-又/吓"甲钙一族。"Branch: master react-antd / src / router / route.jsxP sosout引入百度图表、修改webpack配置1 contributor139 lines (122 sloe) 4.27 KB* It 雇一:3 React createClass 和 extends React.Component 有什么区别?4 *之前写法:5 * let app = React.createClass(getlnitialState: function()*/ some thing8 * )* ES6写法(通过es6类的继承实现时state的初始化要在constructor中声明):9 * class examplecomponent extends React.Component *constructor(props) 10 *super(props);*this.state = example: example*11 * 12 */import React, Component, PropTypes from 1 react1; / react核心; import Router, Route, Redirect, IndexRoute, browserHistoryf hashHistory froiimport Config from 1./config/index1;import layout from 1. ./component/layout/layout1; / 布局界面23import login from 1. ./containers/login/login,; / 登录界面*疑惑一:* React createClass 和 extends React.CoipoMit 有什么区别?*之前写法:* let app = React.createCla(