遇到前端部署问题怎么办?nginx、端口、https域名怎么配置,跨域问题咋整,react/vue项目怎么部署,什么是反向代理,请您耐心往下看。本文通俗易懂,可操作,旨在抛砖引玉。要是帮到了您,还请顺便点个赞。


前言

前端部署,是让前端代码在服务器环境正常运行。而前端日常工作,主要还是业务代码开发,资源引用,前端路由配

置等。至于部署,更多的是运维人员操作接触不多。但现实项目中,往往一部署到这些环境就出现各种各样的问题,如果我们有部署相关的理论、实践经验,面对问题就能更容易定位到问题,提高上线效率。


背景

当你兴致勃勃买了台服务器,然后规划着美好的未来,规划搭建平台。问题来了,前端项目如何部署(demo来自于Internet项目版权归各自所有)...


【从零起步】详尽&全面的前端部署_java

预期的几个目标:


1.web站点(SEO) 基于nextjs前端web服务,port 18001(可修改)。通过nextjs官方example创建 github.com/zeit/next.j…


2.api服务 基于koa的前端nodejs服务,port 18000(可修改)。通过koa脚手架 github.com/17koa/koa2-… 创建


3.静态web项目1-基于vue的前端单页面静态资源项目 /vue-app。通过vue-cli创建 cli.vuejs.org/zh/


4.静态web项目2-基于react/typescript等前端静态资源项目 /react-app。通过create-react-app-antd创建 github.com/ant-design/…


5.公共静态资源图片、css、js等。/static


目录

按照从零起步的原则,按照以下目录来循序渐进


1.服务器分类

2.轻量强大的nginx

3.前端服务管理工具-pm2

4.解决跨域“问题”

5.☆部署react/vue单页面静态项目

6.实现https

7.持续集成CI-自动化部署


1.服务器分类

1.1 应用服务器

专注于动态资源、解析高级开发语言编写的代码。前端服务一般基于解析JavaScript语言的nodejs搭建

JAVA:Tomcat、resin、jboss、weblogic 等

PHP:Apache等

.NET:IIS等

Nodejs:express、 koa、eggjs等

1.2 网关服务器

专注于静态资源、代理转发、负载均衡等

Nginx、Tengine等


2.轻量强大的Nginx

Nginx特性很多,前端常用一些特性,其他特性各大互联网公司经过大量实践已证明。关于nginx配置,主要就是配置nginx.conf以及修改后reload使配置生效。具体nginx下载与教程可以参照官网等。Nginx主要是修改配置文件以及生效。

2.1 简介

2.1.1 前端常用特性

域名绑定

静态资源

反向代理

支持https

跨平台

2.1.2 其他特性

负载均衡、高并发

2.1.5 nginx下载和目录说明

nginx官方网站:nginx.org/


nginx主要通过修改conf/nginx.conf配置文件,重启nginx程序生效实现服务器功能。

【从零起步】详尽&全面的前端部署_java_02

// 重启使配置文件生效
// windows
.\nginx.exe -s reload

// linux/mac
nginx -s reload

// ps windows下强制结束nginx.exe进程命令
taskkill /f /t /im nginx.exe
复制代码


2.2 实战配置

2.2.1 环境准备

nginx.org下载最新的nginx压缩包直接解压,windows/linux/mac下载对应的版本

创建文件夹,windows下为如C盘根目录创建 c:/server;linux/mac可以在某个目录创建如根目录创建 /server

2.2.2 静态资源

首先,我们来实现js、png图片、css资源的静态资源配置。server文件夹下创建static文件夹,里面分别创建js、img、css文件夹并在对应文件夹放置对应格式的测试文件内容随意。最终访问路径和效果如下:

/static/js/js.js
/static/img/img.png
/static/css/css.css
复制代码

【从零起步】详尽&全面的前端部署_java_03


2.2.3 nginx配置静态资源

找到nginx文件夹中的 conf/nginx.conf配置文件对应如下配置,配置完成后需要重启nginx,上面有如何重启,结束进程再次打开进程或者reload。

# nginx.conf文件找到server区域

server {
   # nginx监听端口号,不能被其他应用占用
   listen 80;

   # nginx绑定的域名,本文用localhost
   server_name  localhost;

   # 公共静态资源
   location /static/ {
     #root C:/server/;
     alias C:/server/static/;
     autoindex on;
     # 是否启用目录索引
     #autoindex on;
   }
}
复制代码


2.2.4 目录索引

以上配置有个 autoindex on,如果配置了如果访问的是目录,则展示目录索引,如果关闭则展示403 Forbidden。一般为了服务器安全不被探测,都是关闭索引目录。


开启索引效果

【从零起步】详尽&全面的前端部署_java_04

关闭索引效果

【从零起步】详尽&全面的前端部署_java_05


2.2.5 附:nginx静态站点

配置三个静态web站点备用。配置方法很简单,C:/server创建两个文件夹,立马分别有个index.html文件。nginx.conf增加以下配置后重启nginx生效。

server {
   listen       10001;
   server_name  localhost;
   root C:/server/siteA;
   index  index.html index.htm;
}
server {
   listen       10002;
   server_name  localhost;
   root C:/server/siteB;
   index  index.html index.htm;
}
server {
   listen       10003;
   server_name  localhost;
   root C:/server/siteB;
   index  index.html index.htm;
   location / {
     add_header X-Frame-Options SAMEORIGIN;
   }
}
复制代码

至此,任务5静态资源任务达成。恭喜您已经具备使用nginx搭建静态web站点和静态文件服务的能力了,具体相关其他配置可以自行深入研究。


3 部署前端服务-pm2

前端服务-即前端使用如基于nodejs平台下能够有独立运行访问的web服务等。如nextjs、express、koa、eggjs等前端应用服务器。


pm2是什么

众所周知,我们一般启动前端服务,开启一个bash,然后执行如npm start服务器愉快的跑起来,但如果有多个服务,就必须要打开多个,一般在服务器环境你只有一个bash端口必须得后台运行,如何后台运行nodejs服务,以及方便的管理各个nodejs服务的暂停、重启、销毁,我们得需要一个能够管理他们的软件。pm2应运而生。


pm2工具:把nodejs服务变为后台服务,统一管理(常用于服务器环境、控制台命令环境)


详见pm2官方文档

www.npmjs.com/package/pm2, pm2.keymetrics.io/docs/usage/…


安装

npm install pm2 –g复制代码


常用命令

pm2 start pm2.json #根据pm2.json配置方式启动进程

pm2 list, pm2 status #列出当前所有pm2管理列表

pm2 stop 0 #停用指定id的服务

pm2 delete 0 #删除指定id的服务

pm2 restart 0 #重启指定id的服务

实战

我们根据上述最开始官方项目启动nextjs、koa2的nodejs服务,(以前我们是执行npm run start,本地模拟可以直接先启动),现在如果需要pm2改造


先看运行效果:


1.基于nextjs的nodejs服务:127.0.0.1:12111

【从零起步】详尽&全面的前端部署_java_06

部署前端服务-nextjs

2.基于koa2的nodejs服务:127.0.0.1:18000

【从零起步】详尽&全面的前端部署_java_07

部署前端服务-koa

3.pm2 list列出所有pm2托管的node服务

【从零起步】详尽&全面的前端部署_java_08

.部署前端服务-pm2

配置

最终我们是直接通过目录下的start.bat/start.sh执行pm2命令。最终为了间接执行到npm start的命令,给予pm2进行托管

windows下的pm2存在一些问题,需要通过间接方式执行npm命令

// 1.koa/nextjs项目根目录增加start.bat / start.sh,内容为pm2的命令
pm2 start ecosystem.config.js

// 2.创建ecosystem.config.js配置文件,以下已沟通。详细其他参数可参照pm2官网查看具体配置. https://pm2.keymetrics.io/docs/usage/application-declaration/
module.exports = {
   apps: [{
       name: 'MyKoa',
       script: 'start.js',
       args: 'one two',
       instances: 1,
       autorestart: true,
       watch: false,
       max_memory_restart: '1G',
       env: {
           NODE_ENV: 'development'
       },
       env_production: {
           NODE_ENV: 'production'
       }
   }]
};

// 3.创建start.js
const cmd = require('node-cmd');
cmd.run('npm run start');

// 4.package.json配置,需要项目安装node-cmd的包,具体npm run start就是项目中如何启动nodejs服务根据具体项目来
{
 "start": "node bin/development.js",
}

至此,您已经本地运行了两个前端node服务。任务1、2完成50%.


4.解决跨域"问题"

4.1跨域——“正常”的安全策略

我们两个node都启了,你一定会立马就想让nextjs的fetch请求来请求koa的api服务,结果跨域了。。


场景一、XMLHttpRequest、fetch等同源限制

浏览器出于安全当访问不同端口、域名默认情况下是不允许的,也是出于安全。如果谁都能互相随便调用岂不是没有了安全可言。

【从零起步】详尽&全面的前端部署_java_09

场景二、iframe跨域引用问题

一般出于安全,页面的HTTP请求的Response头部设置了X-Frame-Options:sameorigin,防止页面被其他站点内嵌。

【从零起步】详尽&全面的前端部署_java_10


4.2nginx解决方案-反向代理

4.2.1 什么是反向代理

一句话解释:客户端请求服务器,服务器接收转发给其他服务器获得内容,再传给客户端。


反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器。


正向代理:意思是一个位于客户端和原始服务器(origin server)之间的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容返回给客户端。


4.2.2 先看nginx的预期效果

当localhost访问 /api/test/list成功转发到koa服务(127.0.0.1:12111)返回数据

【从零起步】详尽&全面的前端部署_java_11


4.2.3 nginx配置反向代理

# 1.首页为nextjs的web server,便于SEO优化。访问所有优先转发给nextjs服务
location / {
   proxy_pass http://127.0.0.1:12111/;
   proxy_redirect  off;
   proxy_set_header Host $proxy_host;
   proxy_set_header X-Real-IP $remote_addr;
   proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
   proxy_set_header Via "nginx";
}

# 2.转发/api请求给前端koa服务器
location /api {
   proxy_pass http://127.0.0.1:18000/api;
   proxy_redirect  off;
   proxy_set_header Host $proxy_host;
   proxy_set_header X-Real-IP $remote_addr;
   proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
   proxy_set_header Via "nginx";
}
复制代码

4.3 iframe跨域解决

iframe跨域一般还是通过服务器设置response header头。分为旧版本浏览器和新版本浏览器。旧版本:X-Frame-Options,新版本:Content-Security-Policy。可参考:developer.mozilla.org/en-US/docs/…


nginx下具体设置如下,可以指定对应可跨域iframe访问的域名

# 被内嵌iframe web设置server {    
   listen       10004;
   server_name  localhost;
   root C:/server/siteB;
   index  index.html index.htm;
   location / {      
# 旧版本
     add_header X-Frame-Options
"ALLOW-FROM http://localhost";      # 新版本使用csp
     
# add_header Content-Security-Policy "frame-ancestors 'self’ http://localhost";
   }
}
复制代码

【从零起步】详尽&全面的前端部署_java_12


4.4 http报头跨域

一般为开发阶段的mock server,或者设置允许跨域的域名.这样,我们可以直接访问mock数据

【从零起步】详尽&全面的前端部署_java_13

【从零起步】详尽&全面的前端部署_java_14


☆5.部署react/vue单页面静态项目

本章节作为react/vue开发者必备部署知识,因为你的代码始终是要发布的,出了啥问题你就能很快定位(甩锅)问题所在。


5.1 单页面应用核心问题

部署单页面应用项目我们核心思考的问题:服务器端路由与静态单页面应用路由的转换过程

【从零起步】详尽&全面的前端部署_java_15


5.2 nginx配置单页面应用

我们进行分析:当访问url时,先访问nginx服务器,nginx路由判定后给前端路由托管。我们得出以下的配置:访问静态资源子路径下的所有路由均转发给静态资源的index.html文件。实现后端路由转换为前端路由。

# 1.create-react-app静态项目
location /react-app {
 # 路径
 alias C:/server/create-react-app-antd/build;
 # 默认首页
 index index.html;
 # 访问不到资源后的处理
 try_files $uri $uri/ /react-app/index.html;
}

# 2.vue静态项目
location /vue-app {
 alias C:/server/vueapp/build;
 index index.html;
 try_files $uri $uri/ /vue-app/index.html;
}
复制代码

问题一:原始项目直接配置完成无法访问,资源报错

vue-cli项目配置

首先,如果直接从vue官网的命令安装依赖,执行npm run build,配置完是会报错的。


【从零起步】详尽&全面的前端部署_java_16


问题原因:css/js资源引用路径没有引用到,解决方法1改成相对路径访问

【从零起步】详尽&全面的前端部署_java_17

修改后重新编译,成功访问

【从零起步】详尽&全面的前端部署_java_18

react项目配置

默认create-react-app-antd项目npm run build后配置完会出现资源无法访问的问题。原因,项目都是绝对路径访问资源。

【从零起步】详尽&全面的前端部署_java_19

react项目里面由于脚手架配置读取package.json的homepage项为根路径

【从零起步】详尽&全面的前端部署_java_20

重新打包编译后正常访问。这里稍作修改,项目内容增加了路由跳转,这样好测试静态资源路由功能。

【从零起步】详尽&全面的前端部署_java_21

问题二:我上线出现了点击上面react项目首页 http://localhost/react-app/ 点击链接跳转 http://localhost/react-app/test 能打开,但我刷新页面报nginx404了。(很多小伙伴都出现了发布后出现这个情况明明默认都能点,刷新页面后就打不开了报404)

【从零起步】详尽&全面的前端部署_java_22

子路由刷新页面后404

【从零起步】详尽&全面的前端部署_java_23


why刷新报错?

冷静思考,根源还是来自于前后端路由的转换问题,还记得上面配置行(3行)中重要的一句话:try_files 尝试文件,也就是说服务器找不到文件你得告诉怎么处理跳转到哪儿。也就定位到问题:try_files uriuri/ /react-app/index.html;这句异常处理如果不加就会导致刷新访问不到文件的问题。回味一下配置:访问不到的时候转发给下面的index.html页面,index.html无缝对接前端的路由。问题解决。

location /react-app {
 alias C:/server/create-react-app-antd/build;
 index index.html;
 # 下面这句话就起作用了很关键
 try_files $uri $uri/ /react-app/index.html;
}
复制代码

至此,您已具备单页面应用项目的能力,判定资源访问路径,而且还能够排查出部署刷新页面报404这样的经典问题。任务3,4react/vue的静态子项目成功部署。


6 https访问

至此,上述的几个应用系统已经完全贯通运作。但http不是不安全吗,我需要用https让网站能够安全访问。


6.1 https基于ssl证书访问关键要素

申请证书、秘钥(openssl工具)

配置nginx

其实本地环境是可以通过命令行工具生成秘钥和证书,用来测试https


nginx 本地https秘钥可参考文档:www.cnblogs.com/isylar/p/10…


先看效果:https访问后端口号变为了443

【从零起步】详尽&全面的前端部署_java_06

nginx配置如下:最关键的就是pem证书和key的生成。按照上面文档本地就可以生成,网上也有很多关于https证书秘钥生成教程。

 server {
       listen 443 ssl;
       server_name localhost;
       index index.html index.htm index.php;
       root  C:/lc/server;        
# pem证书路径
       ssl_certificate  C:/lc/work/proj/https/server/server.pem;        
# pem证书路径
       ssl_certificate_key C:/lc/work/proj/https/server/server.key;
       ssl_session_timeout 5m;
       ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
       ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
       ssl_prefer_server_ciphers on;
       location / {
         …
       }
}
复制代码

问题:本地刚配置https访问后浏览器提示不安全的连接

【从零起步】详尽&全面的前端部署_java_25

解答:由于浏览器https是需要经过合法CA办法的证书,我们自己配置的并非经过证书颁发机构。点击继续前往还是能够本地访问到。


如何强制http请求转为https请求

nginx配置为:80端口访问后rewrite所有请求为https

server {
     listen 80;
     server_name  localhost;      
# 强制使用https
     rewrite ^(.*)$ https://
$host$1 permanent;
}
复制代码

7.持续集成CI-自动化部署

7.1核心思想

具有执行服务器端脚本能力

通过web等UI界面方便操作

支持通过如git web hook等触发式构建

7.2常用软件

Jenkins jenkins.io/zh/

7.3本地写个自动更新代码自动打包的脚本

我们在刚刚 C:/server/create-react-app-antd下新建build.sh和build.bat,用来执行后自动拉取代码以及自动执行编译打包

build.bat

echo start build...
echo running step 1.git pull
git pull
echo running step 2.npm run build
npm run build
复制代码

build.sh

#!/usr/bin/env bash
echo start build...
echo running step 1.git pull
git pull
echo running step 2.npm run build
npm run build
复制代码

收尾

能看到这里,真心感谢您的耐心,是不是有种醍醐灌顶,原来前端部署一篇就够了。有了这些,我们在以后的前端上线部署不再是盲区,又能够快速定位问题。结尾还是那句话:要是帮到了您,还请顺便点个赞,谢谢(90度鞠躬)。