【你應該瞭解的】詳盡&全面的前端部署(從零起步,前端上線不用愁)

NO IMAGE

團隊:skFeTeam  本文作者:陸程

遇到前端部署問題怎麼辦?nginx、端口、https域名怎麼配置,跨域問題咋整,react/vue項目怎麼部署,什麼是反向代理,請您耐心往下看。本文通俗易懂,可操作,旨在拋磚引玉。要是幫到了您,還請順便點個贊。

目錄

前言

前端部署,是讓前端代碼在服務器環境正常運行。而前端日常工作,主要還是業務代碼開發,資源引用,前端路由配置等。至於部署,更多的是運維人員操作接觸不多。但現實項目中,往往一部署到這些環境就出現各種各樣的問題,如果我們有部署相關的理論、實踐經驗,面對問題就能更容易定位到問題,提高上線效率。

背景

當你興致勃勃買了臺服務器,然後規劃著美好的未來,規劃搭建平臺。問題來了,前端項目如何部署(demo來自於Internet項目版權歸各自所有)…

【你應該瞭解的】詳盡&全面的前端部署(從零起步,前端上線不用愁)

預期的幾個目標:

  • 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程序生效實現服務器功能。

【你應該瞭解的】詳盡&全面的前端部署(從零起步,前端上線不用愁)

// 重啟使配置文件生效
// 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

【你應該瞭解的】詳盡&全面的前端部署(從零起步,前端上線不用愁)

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。一般為了服務器安全不被探測,都是關閉索引目錄。

開啟索引效果

【你應該瞭解的】詳盡&全面的前端部署(從零起步,前端上線不用愁)

關閉索引效果

【你應該瞭解的】詳盡&全面的前端部署(從零起步,前端上線不用愁)

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

【你應該瞭解的】詳盡&全面的前端部署(從零起步,前端上線不用愁)

2.基於koa2的nodejs服務:127.0.0.1:18000

【你應該瞭解的】詳盡&全面的前端部署(從零起步,前端上線不用愁)

3.pm2 list列出所有pm2託管的node服務

【你應該瞭解的】詳盡&全面的前端部署(從零起步,前端上線不用愁)

配置

最終我們是直接通過目錄下的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等同源限制

瀏覽器出於安全當訪問不同端口、域名默認情況下是不允許的,也是出於安全。如果誰都能互相隨便調用豈不是沒有了安全可言。

【你應該瞭解的】詳盡&全面的前端部署(從零起步,前端上線不用愁)

場景二、iframe跨域引用問題

一般出於安全,頁面的HTTP請求的Response頭部設置了X-Frame-Options:sameorigin,防止頁面被其他站點內嵌。

【你應該瞭解的】詳盡&全面的前端部署(從零起步,前端上線不用愁)

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)返回數據

【你應該瞭解的】詳盡&全面的前端部署(從零起步,前端上線不用愁)

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";
} 
}

【你應該瞭解的】詳盡&全面的前端部署(從零起步,前端上線不用愁)

4.4 http報頭跨域

一般為開發階段的mock server,或者設置允許跨域的域名.這樣,我們可以直接訪問mock數據

【你應該瞭解的】詳盡&全面的前端部署(從零起步,前端上線不用愁)

【你應該瞭解的】詳盡&全面的前端部署(從零起步,前端上線不用愁)

☆5.部署react/vue單頁面靜態項目

本章節作為react/vue開發者必備部署知識,因為你的代碼始終是要發佈的,出了啥問題你就能很快定位(甩鍋)問題所在。

5.1 單頁面應用核心問題

部署單頁面應用項目我們核心思考的問題:服務器端路由與靜態單頁面應用路由的轉換過程

【你應該瞭解的】詳盡&全面的前端部署(從零起步,前端上線不用愁)

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,配置完是會報錯的。

【你應該瞭解的】詳盡&全面的前端部署(從零起步,前端上線不用愁)

問題原因:css/js資源引用路徑沒有引用到,解決方法1改成相對路徑訪問

【你應該瞭解的】詳盡&全面的前端部署(從零起步,前端上線不用愁)

修改後重新編譯,成功訪問

【你應該瞭解的】詳盡&全面的前端部署(從零起步,前端上線不用愁)

react項目配置

默認create-react-app-antd項目npm run build後配置完會出現資源無法訪問的問題。原因,項目都是絕對路徑訪問資源。

【你應該瞭解的】詳盡&全面的前端部署(從零起步,前端上線不用愁)

react項目裡面由於腳手架配置讀取package.json的homepage項為根路徑

【你應該瞭解的】詳盡&全面的前端部署(從零起步,前端上線不用愁)

重新打包編譯後正常訪問。這裡稍作修改,項目內容增加了路由跳轉,這樣好測試靜態資源路由功能。

【你應該瞭解的】詳盡&全面的前端部署(從零起步,前端上線不用愁)

問題二:我上線出現了點擊上面react項目首頁 http://localhost/react-app/ 點擊鏈接跳轉 http://localhost/react-app/test 能打開,但我刷新頁面報nginx404了。(很多小夥伴都出現了發佈後出現這個情況明明默認都能點,刷新頁面後就打不開了報404)

【你應該瞭解的】詳盡&全面的前端部署(從零起步,前端上線不用愁)

子路由刷新頁面後404

【你應該瞭解的】詳盡&全面的前端部署(從零起步,前端上線不用愁)

why刷新報錯?

冷靜思考,根源還是來自於前後端路由的轉換問題,還記得上面配置行(3行)中重要的一句話:try_files 嘗試文件,也就是說服務器找不到文件你得告訴怎麼處理跳轉到哪兒。也就定位到問題:try_files 【你應該瞭解的】詳盡&全面的前端部署(從零起步,前端上線不用愁)uri/ /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

【你應該瞭解的】詳盡&全面的前端部署(從零起步,前端上線不用愁)

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訪問後瀏覽器提示不安全的連接

【你應該瞭解的】詳盡&全面的前端部署(從零起步,前端上線不用愁)

解答:由於瀏覽器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常用軟件

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度鞠躬)。

想了解skFeTeam更多的分享文章,可以點這裡,謝謝~

相關文章

Chrome的小恐龍遊戲,被我破解了…

🔥Java基礎之網絡編程(二)

Taro小程序開發大型實戰(三):實現微信和支付寶多端登錄

答應我,別再寫上千行的類了好嗎