当前位置: 首页 > Linux

vue、react等单页项目应该这样部署到服务端

时间:2023-04-06 05:58:24 Linux

服务端渲染:next等服务端渲染框架构建的项目。vue做的项目本地可用,但是部署到服务器时遇到很多问题:找不到资源,直接访问index.html页面是空白,刷新当前路由404。..用react做的项目也遇到了类似的问题。现在我们来讨论一下如何将订单页面部署到服务器上?由于前端路由,单页应用应放在nginx、apache、tomcat等web代理服务器中,不要直接访问index.html,根据项目路径更改react或vue的路由地址你自己的服务器。如果项目后面直接跟域名,比如:http://www.sosout.com,根路由就是'/'。如果项目在域名正后的子目录下,例如:http://www.sosout.com/children,根路由为'/children',无法直接访问index.html。以Nginx的配置为例,配置过程大致如下:(假设:1.项目文件目录:/mnt/html/spa(spa目录下的文件为执行npm后生成的dist目录下的文件运行dist)2.访问域名:spa.sosout.com)进入nginx.conf,添加如下配置:server{listen80;server_namespa.sosout.com;根/mnt/html/spa;索引index.html;位置~^/favicon\.ico${root/mnt/html/spa;}location/{try_files$uri$uri//index.html;proxy_set_header主机$host;proxy_set_headerX-Real-IP$remote_addr;proxy_set_headerX-Forwarded-For$proxy_add_x_forwarded_for;proxy_set_headerX-Forwarded-Proto$scheme;}access_log/mnt/logs/nginx/access.logmain;}注意事项:1、配置域名需要80端口。成功后只需要访问域名就可以访问项目2.如果你使用react-router的browserHistory模式或者vue-router的history模式,nginx的配置也需要重写路由:server{listen80;server_namespa.sosout.com;根/mnt/html/spa;索引index.html;位置~^/favicon\.ico${root/mnt/html/spa;}位置/{try_files$uri$ur我/@fallback;索引index.html;proxy_set_header主机$host;proxy_set_headerX-Real-IP$remote_addr;proxy_set_headerX-Forwarded-For$proxy_add_x_forwarded_for;proxy_set_headerX-Forwarded-Proto$scheme;}location@fallback{重写^.*$/index.html中断;}access_log/mnt/logs/nginx/access.logmain;}为什么要重写路由?因为我们的项目只有一个根入口,当输入/home这样的URL时,如果找不到对应的页面,nginx会尝试加载index.html,react-router或者vue-router都可以正确匹配到/主页路由以显示正确的主页。如果在浏览器历史模式或者历史模式项目中没有配置以上内容,就会出现404。随便举两个例子,一个vue项目和一个react项目:vue项目:域名:http://tb.sosout.comimportAppfrom'../App'//首页consthome=r=>require.ensure([],()=>r(require('../page/home/index')),'home')//Logisticsconstlogistics=r=>require.ensure([],()=>r(require('../page/logistics/index')),'logistics')//购物车constcart=r=>require.ensure([],()=>r(require('../page/cart/index')),'cart')//Myconstprofile=r=>require.ensure([],()=>r(require('../page/profile/index')),'profile')//登录界面constlogin=r=>require.ensure([],()=>r(require('../page/user/login')),'login')exportdefault[{path:'/',component:App,//顶层路由,对应index.htmlchildren:[{path:'/home',//首页component:home},{path:'/logistics',//物流组件:logistics,meta:{login:true}},{path:'/cart',//购物车组件:cart,meta:{login:true}},{path:'/profile',//我的组件:个人资料},{路径:'/login',//登录界面组件:login},{path:'*',redirect:'/home'}]}]#############其他配置############http{#############其他配置############server{listen80;server_nametb.sosout.com;根/mnt/html/tb;索引index.html;位置~^/favicon\.ico${root/mnt/html/tb;}location/{try_files$uri$uri/@fallback;索引index.html;proxy_set_header主机$host;proxy_set_headerX-Real-IP$remote_addr;proxy_set_headerX-Forwarded-For$proxy_add_x_forwarded_for;proxy_set_headerX-Forwarded-Proto$scheme;}location@fallback{重写^.*$/index.html中断;}access_log/mnt/logs/nginx/access.logmain;}#############其他配置#############}react项目:域名:http://antd.sosout。com/***疑点一:*ReactcreateClassandextendsReact.Component有什么区别?*之前的写法:*letapp=React.createClass({*getInitialState:function(){*//something*}*})*ES6写法(通过es6类继承实现时的状态初始化应该在构造函数中声明):*classexampleComponentextendsReact.Component{*constructor(props){*super(props);*this.state={example:'example'}*}*}*/importReact,{Component,PropTypes}来自'react';//反应核心import{Router,Route,Redirect,IndexRoute,browserHistory,hashHistory}from'react-router';//importConfigfrom'../config/indexrequiredtocreatearoute';importlayoutfrom'../component/layout/layout';//布局界面importloginfrom'../containers/login/login';//登录界面/***(路由根目录组件,显示当前符合条件的组件)**@classRoots*@extends{Component}*/classRootsextendsComponent{render(){//该组件是一个封装组件,并且所有通过路由重定向的页面都会使用this.props.children的形式加载到这个组件返回(

{this.props.children}
);}}//consthistory=process.env.NODE_ENV!=='产品化'?browserHistory:hashHistory;//快速启动consthome=(location,cb)=>{require.ensure([],require=>{cb(null,require('../containers/home/homeIndex').default)},'home');}//百度图表-折线图constchartLine=(location,cb)=>{require.ensure([],require=>{cb(null,require('../containers/charts/lines').default)},'chartLine');}//基本组件-按钮constbutton=(location,cb)=>{require.ensure([],require=>{cb(null,require('../containers/general/buttonIndex').default)},'button');}//基本组件-iconconsticon=(location,cb)=>{require.ensure([],require=>{cb(null,require('../containers/general/iconIndex').default)},'icon');}//用户管理constuser=(location,cb)=>{require.ensure([],require=>{cb(null,require('../containers/user/userIndex').default)},'user');}//系统设置常量设置=(location,cb)=>{require.ensure([],要求=>{cb(null,require('../containers/setting/settingIndex').default)},'setting');}//广告管理constadver=(location,cb)=>{require.ensure([],require=>{cb(null,require('../containers/adver/adverIndex').default)},'adver');}//组件一constoneui=(location,cb)=>{require.ensure([],require=>{cb(null,require('../containers/ui/oneIndex').default)},'oneui');}//组二consttwoui=(location,cb)=>{require.ensure([],require=>{cb(null,require('../containers/ui/twoIndex').default)},'twoui');}//登录验证constrequireAuth=(nextState,replace)=>{lettoken=(newDate()).getTime()-Config.localItem('USER_AUTHORIZATION');if(token>7200000){//模拟Token保存2小时replace({pathname:'/login',state:{nextPathname:nextState.location.pathname}});}}constRouteConfig=(//默认加载的组件,比如访问www.test.com,会自动跳转到www.test.com/home//所有访问,跳转到Roots//默认加载的组件,比如访问www.test.com,会自动跳转到www.test.com/home);exportdefaultRouteConfig;#############其他配置#############http{#############其他配置############服务器{听80;server_nameantd.sosout.com;根/mnt/html/reactAntd;索引index.html;位置~^/favicon\.ico${root/mnt/html/reactAntd;}location/{try_files$uri$uri/@router;索引index.html;proxy_set_header主机$host;proxy_set_headerX-Real-IP$remote_addr;proxy_set_headerX-Forwarded-For$proxy_add_x_forwarded_for;proxy_set_headerX-Forwarded-Proto$scheme;location@router{重写^.*$/index.html中断;}access_log/mnt/logs/nginx/access.logmain;}#############其他配置############}