1. 程式人生 > >前端專案應該如何部署

前端專案應該如何部署

一個標準的前端專案,必定始於yarn start,它將會經歷babel編譯,webpack構建,server啟動等流程,然後由瀏覽器載入頁面。這是很Dev的開發方式,可生產環境我們卻往往不這麼做。

1.何為前端?

如果按照以前的看法,前後端最本質的區別當然是執行環境了,一個是瀏覽器中所寫即所見的UI介面,另一個則是藏在背後的服務。

在這種簡單的區分下,前端往往會被定義為HTML/CSS/Javascript。沒錯,前端就是這些東西,這就是瀏覽器所需要呈現的;可也不能只有這些東西:前端有時也需要自己的後端server來充當API的中間層,也需要資料儲存(如localStorage, sessionStorage, indexedDB...)

,甚至JS也快支援多執行緒了。所以現今,絕對不能用語言執行時(別給我說JS只在瀏覽器內執行)或者某項技術(ESX已經在草案了)來去定義前端。

個人認為,最簡單的區別方法就是用API來劃分:API的處理方如果在Node.js端,那麼這個JS專案絕對就是後端(Node端如果只作為中間層轉發則不算數);否則,如果只是作為API資料的請求方,並且有UI展現,就算是前端了。

2.有無server?

為什麼要浪費篇幅去講前端的定義,就是因為只有明確定義好前端之後,才能解決一個問題:前端到底要不要server?,因為它很大程度上決定了如何部署。

一般的前端專案都會有dist產出,通常是由一個index.html

, 多個vendor.js和其他類似圖片字型等資源構成。

那麼這個產出物是如何被render出來的呢?

  • Case1: 利用webpack server

以下為webpack配置啟用webpack server的片段:


var path = require('path');
module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist')
  },
  devServer: {
    contentBase
: path.join(__dirname, "dist"), compress: true, port: 3000, watchOptions: { poll: true } } };

這種case顯然只是render靜態的html和資源,因此webpack server只在開發使用,生產則根本不需要。

  • Case2: 利用靜態伺服器

其實和case1類似,如果只是render靜態html,那麼利用類似Python:


$ python -m SimpleHTTPServer 3000

或者Nginx做代理都是很方便實現的。

  • Case3: 不必要的Node服務

var express = require("express");
var path = require('path');
var project = require('../project.config');

const app = express();
app.use('*', function (req, res) {
  const file = path.resolve(project.basePath, project.outDir, 'index.html');
    res.sendFile(file);
});

app.listen(process.env.PORT || 3000, function () {
  console.log("Listening on port %d!", this.address().port);
});

如上,只是借用Node服務去render產出物,並未做其他任何請求處理,其實和case2,3沒有本質區別。

  • Case4: 將Node服務作為API中間層

router.route('/articles/send')
  .post(async (req, res) => {
    const {params} = req.body;
    const requestUrl = '/x/x/x/x';
    const response = await requestArticle(requestUrl, params);
    res.status(200).send(response).end();
  });

這種情況下,Node服務就必須存在,因為很有可能真正的API處理方不支援跨域,或者有身份驗證,那麼就得在這裡去處理,生產環境自然也得有。

  • Case5: Node端有完善的RESTful API

這種情況下,已經可以定義為一個前後端專案了,只是恰好前後端的語言一樣,並且可以共用大部分模組。

參考如上,你的專案,屬於哪種情況呢?

3.如何部署?

終於到了正題,其實部署無非就是執行環境(server)+資源(包),因此才需要搞清楚你的專案到底需不需要server?,更確切的說是你的專案的生產環境到底需不需要server?,從而決定如何部署。

  • 對於case1,2,3:

可以選擇任意靜態伺服器,執行在生產環境,每次部署只需拉取最新的程式碼或生成最新的包。如果需要多機部署,則推薦docker的node或nginx映象,server只作一層簡單的router和render,並將最新的原始碼打包在內即可。

體總來說這種情況是最簡單的case,一個靜態伺服器就可以,想練手的可以利用Github Page去玩玩。

  • 對於case4,5:

單機環境建議有部署指令碼(如ansible,去初始化各種環境依賴);多機部署則考慮node映象,每次部署時都把程式碼打進映象,並且設定啟動命令,最後的部署方式就是一鍵部署

BTW,對於這種case,如果部署時就是多機的情況,倒不如一勞永逸,開發環境直接用docker。但開發和生產還有點區別:建議開發時不要把原始碼打進映象,畢竟程式碼總是在變,可以將程式碼作為VOLUMN每次載入上去,然後手動啟動,如下片段:

Dockerfile:


FROM node:7.2

RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
RUN echo "deb http://dl.yarnpkg.com/debian/ stable main" > /etc/apt/sources.list.d/yarn.list
RUN apt-get update && apt-get install yarn

WORKDIR /app

VOLUME /app

只依賴Node服務和yarn。

Run docker:


docker run --rm -v [your path]:/app -ti -p 3000:3000  image:version /bin/bash

只需將程式碼掛載上去即可,完全的環境程式碼分離模式。

4.寫在最後

說了這麼多,給想實踐的朋友推薦以下資源: