前端項目應該如何部署

一個標準的前端項目,必定始于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.寫在最后

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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,869評論 18 139
  • 文:森林樹 元宵節,團團圓圓的日子。雖然因為住在宿舍條件比較艱苦,但是我和朋友們還是熱熱鬧鬧地做了一大桌菜,一起八...
    森林樹閱讀 891評論 0 1
  • “做一個有趣的人。” 在一個普通的夜晚,莫小凡發了這條朋友圈,配圖是自己半年前在東南亞的海邊拍的風景照。隨后,她把...
    茶茶的平行世界閱讀 408評論 0 1
  • 20年的時光匆匆而過,有太多的感受。想說的不想說的,都不知道該咋么表達。既然傷害了過去,就別辜負了未來。感謝父母給...
    幸福給你看閱讀 363評論 0 0