博客地址:http://blog.poetries.top/2018/11/18/react-ssr-next-deploy/
一、 npm run export
導(dǎo)出文件上傳到CDN
在項(xiàng)目中執(zhí)行
npm run export
后導(dǎo)出outCDN
文件上傳到CDN
// scripts/upload.js
const fs = require('fs');
const path = require('path');
const OSS = require('ali-oss');
const filePath = path.join(__dirname,'../outCDN');
const excludeFiles = ['index.html']
const client = new OSS({
region: 'oss-cn-shenzhen',
accessKeyId: '',
accessKeySecret: '',
bucket: ''
});
// 遍歷文件夾中所有文件
async function uploadFile(filePath){
//根據(jù)文件路徑讀取文件东囚,返回文件列表
fs.readdir(filePath,async function(err,files){
if(err){
console.warn(err)
}else{
//遍歷讀取到的文件列表
files.forEach(async function(filename){
//獲取當(dāng)前文件的絕對路徑
const filedir = path.join(filePath,filename);
//根據(jù)文件路徑獲取文件信息跺嗽,返回一個(gè)fs.Stats對象
fs.stat(filedir,async function(eror,stats){
if(eror){
console.warn('獲取文件stats失敗');
}else{
const isFile = stats.isFile();//是文件
const isDir = stats.isDirectory();//是文件夾
if(!excludeFiles.includes(filename) && isFile){
const fileKey = `${filedir.split('outCDN/').pop()}`
try {
// object表示上傳到OSS的Object名稱,localfile表示本地文件或者文件路徑
let data = await client.put(fileKey,filedir);
console.error('upload success: %j', data);
} catch(err) {
console.error('upload failed: %j', err);
}
}
if(isDir){
uploadFile(filedir);//遞歸页藻,如果是文件夾桨嫁,就繼續(xù)遍歷該文件夾下面的文件
}
}
})
});
}
});
}
uploadFile(filePath)
二、處理next build
后的文件
執(zhí)行
next build
以后,把.next
份帐、package.json
璃吧、server.js
、next.config.js
废境、ecosystem.json
拷貝到一個(gè)文件夾統(tǒng)一管理畜挨,最后部署這個(gè)文件夾下的內(nèi)容即可
// scripts/copyFiles.js
const fs = require( 'fs' ),
stat = fs.stat;
const path = require('path')
const includeFiles = ['package.json','server.js','next.config.js','ecosystem.json']
/*
* 復(fù)制目錄中的所有文件包括子目錄
* @param{ String } 需要復(fù)制的目錄
* @param{ String } 復(fù)制到指定的目錄
*/
const readDir = function( src, dst ){
// 讀取目錄中的所有文件/目錄
fs.readdir( src, function( err, paths ){
if( err ){
throw err;
}
paths.forEach(function( filename ){
var _src = src + '/' + filename,
_dst = dst + '/' + filename,
readable, writable;
stat( _src, function( err, st ){
if( err ){
throw err;
}
// 判斷是否為文件
if( st.isFile()){
// 創(chuàng)建讀取流
readable = fs.createReadStream( _src );
// 創(chuàng)建寫入流
writable = fs.createWriteStream( _dst );
// 通過管道來傳輸流
readable.pipe( writable );
}
// 如果是目錄則遞歸調(diào)用自身
else if( st.isDirectory()){
copyDir( _src, _dst, readDir );
}
});
});
});
};
// 在復(fù)制目錄前需要判斷該目錄是否存在,不存在需要先創(chuàng)建目錄
const copyDir = function( src, dst, callback ){
fs.exists( dst, function( exists ){
// 已存在
if( exists ){
callback( src, dst );
}
// 不存在
else{
fs.mkdir( dst, function(){
callback( src, dst );
});
}
});
};
const copyFile = ()=>{
includeFiles.forEach(filename=>{
fs.createReadStream(path.join(__dirname,'../'+filename)).pipe(fs.createWriteStream(path.join(__dirname,'../deployBuildFiles',filename)))
console.log('拷貝完成!')
})
}
// 復(fù)制目錄
copyDir( '.next', 'deployBuildFiles/.next', readDir);
// 拷貝文件
copyFile()
三噩凹、pm2之ecosystem部署項(xiàng)目
PM2
部署應(yīng)用流程巴元,通過pm2
的配置文件來部署
http://pm2.keymetrics.io/docs/usage/deployment/
3.1 配置部署腳本文件
在項(xiàng)目根目錄添加
pm2
的部署腳本文件ecosystem.json
{
"apps": [
{
"name": "goodsapp", //pm2運(yùn)行的應(yīng)用名稱
"script": "server.js",//服務(wù)啟動(dòng)入口
"env":{
"COMON_VARIABLE": "true"
},
"env_production": {
"NODE_ENV": "production", //env
"HOST": "localhost"
}
}
],
"deploy": {
// 最后這樣使用 pm2 deploy ecosystem.json production
"production": {
"user": "user_00",// 服務(wù)器用戶名
"host": ['192.68.1.201'],//服務(wù)器ip地址 可寫多個(gè)
"ref": "origin/master",//從指定分支拉取代碼
"repo": "http://p.yesdat.com/diffusion/49/goodsh.git",
"path": "/data/poetry/testDir/prev-goods.yesdat.com", //上傳本地目錄到服務(wù)器
"ssh_options": "StrictHostKeyChecking=no",
"post-deploy": "npm install --registry=https://registry.npm.taobao.org && npm install && pm2 startOrRestart ecosystem.json --env production",//部署腳本
"env": {
"NODE_ENV": "production"
}
}
}
}
或者簡單
scp
上傳到服務(wù)器
scp -P36000 -r deployBuildFiles/.next user_00@192.168.1.201:/home/data/services/goods-prev.yesdat.com/
3.2 部署Nginx配置規(guī)則
在
nginx
安裝目錄下的vhost
中新建一個(gè)xx-3000.conf
的配置文件
- 在Nginx目錄
/etc/nginx
下執(zhí)行sudo /usr/sbin/nginx -t
檢測配置文件是否成功
upstream goodsapp { // website項(xiàng)目的目錄名稱
server 127.0.0.1:3000; // 服務(wù)器上的本地啟動(dòng)入口,端口對應(yīng)項(xiàng)目中server.js中的端口
}
// 配置server
server {
listen 80;
server_name prev-goods.yesdat.com; //指向的域名
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forward-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Nginx-Proxy true;
proxy_pass http://goodsapp; // 請求將會(huì)轉(zhuǎn)發(fā)到goodsapp的node服務(wù)下
proxy_redirect off;
}
// 處理靜態(tài)資源
location ~* ^.+\.(jpg|jpeg|gif|png|ico|css|js|pdf|txt) {
root /data/goodsapp/static; //請求轉(zhuǎn)發(fā)到靜態(tài)資源路徑
}
}
更多配置參考 https://github.com/poetries/poetry-configure/blob/master/nginx.conf
3.3 本地項(xiàng)目根執(zhí)行的命令
-
pm2 deploy ecosystem.json goodsapp setup
初始化 -
pm2 deploy ecosystem.json goodsapp
部署
3.4 部署到阿里云
第一步:配置Nginx
查看
Nginx
安裝路徑which nginx
注意/etc/nginx
和/usr/local/nginx/
下的nginx
區(qū)別
# 切換到Nginx當(dāng)前目錄下
/usr/local/nginx/conf/
# 創(chuàng)建vhost
mkdir vhost
# 創(chuàng)建goodsapp-3001.conf驮宴,內(nèi)容如下
server {
listen 8080;
server_name 39.108.74.36;# 在ifconfig的拿到的ip地址或者是公網(wǎng)ip逮刨,這里填公網(wǎng)ip,如果是域名阿里云需要備案才可以正常訪問
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forward-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Nginx-Proxy true;
proxy_pass http://127.0.0.1:3001;# 把172.16.0.223:8080的請求轉(zhuǎn)發(fā)代理到本機(jī)的3001端口
}
}
# 在/usr/local/nginx/sbin/nginx/conf/nginx.conf下include創(chuàng)建的vhost文件
include /etc/nginx/vhost/*.conf; # 在文件最后include配置文件
# 在/usr/local/nginx/sbin/nginx/conf/nginx.conf下執(zhí)行檢測配置文件
sudo /usr/local/nginx/sbin/nginx -t
# 重新加載Nginx配置
/usr/local/nginx/sbin/nginx -s reload
一些注意事項(xiàng)
-
server_name
可以是域名堵泽,也可以是ip
修己。ip
可以是本地,也可以是公網(wǎng)ip
本機(jī)ip
公網(wǎng)ip
- 阿里云防火墻規(guī)則設(shè)置
這里訪問了
8080
需要在阿里云后臺(tái)配置一下
第二步:pm2部署到服務(wù)器
首先在服務(wù)端全局安裝
pm2
迎罗、npm
node
并且建立軟鏈
npm i pm2 -g
重要:請注意:
一定要做建立軟鏈這步睬愤,否則出現(xiàn)如下問題
建立
npm
軟鏈
建立
node
軟鏈
建立
pm2
軟鏈
正式部署
- 根目錄執(zhí)行
pm2 deploy deploy-app.json production setup
初始化服務(wù)端環(huán)境 - 根目錄執(zhí)行
pm2 deploy deploy-app.json production --force
輸入服務(wù)端用戶root密碼,部署即可
來到
/home/production
目錄查看上傳的文件
{
"apps": [
{
"name": "goodsapp-prev",
"script": "server.js",# 根目錄server.js文件
"env":{
"COMON_VARIABLE": "true"
},
"env_production": {
"NODE_ENV": "production"
}
}
],
"deploy": {
"production": {
"user": "root",//用戶名
"host": ["39.108.74.36"], //公網(wǎng)ip
"ref": "origin/master",
"repo": "https://gitee.com/Poetries1/goods-prev.yesdat.com.git",
"path": "/home/production",
"ssh_options": ["StrictHostKeyChecking=no", "PasswordAuthentication=no"],
"post-deploy": "npm install && pm2 startOrRestart deploy-app.json --env production",
"pre-deploy-local": "echo 'Deploy Done!'",
"env": {
"NODE_ENV": "production"
}
}
}
}
-
pm2 list
查看啟動(dòng)的項(xiàng)目
-
pm2 logs
查看啟動(dòng)日志
然后在瀏覽器訪問
http://39.108.74.36:8080
(http://公網(wǎng)ip:端口)即可看到纹安,到此部署結(jié)束