前端技術(shù)演進(jìn)發(fā)展簡(jiǎn)史

前言:為什么要了解歷史

以銅為鑒,可以正衣冠 ,以人為鑒,可以明得失,以史為鑒,可以知興替(李世民)。
如果說(shuō)我看得遠(yuǎn),那是因?yàn)槲艺驹诰奕说募绨蛏希ㄅnD)。
了解一門(mén)技術(shù)的歷史,可以幫助我們從歷史的角度來(lái)看技術(shù)演進(jìn)發(fā)展,理解前端技術(shù)為何會(huì)變成現(xiàn)在的模樣,理解技術(shù)社會(huì)之間的聯(lián)系,從歷史的更大的視野的層面來(lái)理解技術(shù)。

一、前端起源

1990 年,第一個(gè)web瀏覽器誕生,Tim 以超文本語(yǔ)言 HTML 為基礎(chǔ)在 NeXT 電腦上發(fā)明了最原始的 Web 瀏覽器。
1991 年,WWW誕生,這標(biāo)志著前端技術(shù)的開(kāi)始。
在開(kāi)始之前先看看什么是前端

  • 現(xiàn)在的前端其實(shí)是個(gè)很大的范疇(web,移動(dòng)端(Hybrid App),游戲,桌面端(electron.js, NW.js),小程序等)。
  • web前端開(kāi)發(fā):針對(duì)瀏覽器的開(kāi)發(fā),代碼在瀏覽器運(yùn)行,它實(shí)質(zhì)是前端代碼在瀏覽器端被編譯、運(yùn)行、渲染成頁(yè)面。前端代碼由HTML、CSS、 JavaScript構(gòu)成。
  • 后端:針對(duì)服務(wù)器的開(kāi)發(fā),代碼在服務(wù)器運(yùn)行。

二、前后端不分的時(shí)代

初期靜態(tài)網(wǎng)站

互聯(lián)網(wǎng)發(fā)展的早期,WWW(World Wide Web)、瀏覽器、JavaScript相繼誕生,最開(kāi)始大多是HTML靜態(tài)網(wǎng)頁(yè)。

動(dòng)態(tài)網(wǎng)站技術(shù)階段

比較有代表性的技術(shù)有JSP 、PHP、ASP、ASP.NET 等語(yǔ)言,它們都類(lèi)似,是運(yùn)行在服務(wù)端的語(yǔ)言。
那時(shí)候沒(méi)有專(zhuān)業(yè)的前端,前后端開(kāi)發(fā)是一體的,前端代碼是后端代碼的一部分,前端寫(xiě)靜態(tài)模板,后端加數(shù)據(jù)套模板。

瀏覽器展現(xiàn)頁(yè)面的流程是:
  • 1、后端收到瀏覽器的URL請(qǐng)求,后端路由響應(yīng)
  • 2、后端生成靜態(tài)頁(yè)面
  • 3、發(fā)送到瀏覽器渲染成頁(yè)面
后端 MVC 的開(kāi)發(fā)模式

那時(shí)的網(wǎng)站開(kāi)發(fā),采用的是后端 MVC 模式。

  • Model(模型層):提供/保存數(shù)據(jù)
  • Controller(控制層):數(shù)據(jù)處理,實(shí)現(xiàn)業(yè)務(wù)邏輯
  • View(視圖層):展示數(shù)據(jù),提供用戶(hù)界面
    前端只是后端 MVC 的 V,那時(shí)候前端的 V 是在服務(wù)端渲染的。
    PHP,ASP,ASP.NET,JSP等都是典型的這樣的模式;
JSP頁(yè)面長(zhǎng)這樣:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鳥(niǎo)教程(runoob.com)</title>
</head>
<body>
<p>
   今天的日期是: <%= (new java.util.Date()).toLocaleString()%>
</p>
</body> 
</html>
PHP模板
<h1>Car {{ $car->id }}</h1>
<ul>
  <li>Make: {{ $car->make }}</li>
  <li>Model: {{ $car->model }}</li>
  <li>Produced on: {{ $car->produced_on }}</li>
</ul>

三、AJAX誕生

AJAX誕生是前端發(fā)展的一個(gè)里程碑,Ajax 技術(shù)誕生,改變了一切。

  • 1999年,微軟公司發(fā)布IE瀏覽器5.0版,第一次引入新功能:允許JavaScript腳本向服務(wù)器發(fā)起HTTP請(qǐng)求。這個(gè)功能當(dāng)時(shí)并沒(méi)有引起注意,直到2004年Gmail發(fā)布和2005年Google Map發(fā)布,才引起廣泛重視。
  • 2005年2月,AJAX這個(gè)詞第一次正式提出,指圍繞這個(gè)功能進(jìn)行開(kāi)發(fā)的一整套做法。從此,AJAX成為腳本發(fā)起HTTP通信的代名詞。
  • 2006年W3C發(fā)布了它的國(guó)際標(biāo)準(zhǔn)。
AJAX是基于現(xiàn)有的Internet標(biāo)準(zhǔn),并且聯(lián)合使用它們:

XMLHttpRequest 對(duì)象 (異步的與服務(wù)器交換數(shù)據(jù))
JavaScript/DOM (信息顯示/交互)
CSS (給數(shù)據(jù)定義樣式)
XML 、JSON(作為轉(zhuǎn)換數(shù)據(jù)的格式)
lamp AJAX應(yīng)用程序與瀏覽器和平臺(tái)無(wú)關(guān)的!
在 2005 年,Google 通過(guò)其 Google Suggest 使 AJAX 變得流行起來(lái)。
Google Suggest 使用 AJAX 創(chuàng)造出動(dòng)態(tài)性極強(qiáng)的 web 界面 當(dāng)您在谷歌的搜索框輸入關(guān)鍵字時(shí),JavaScript 會(huì)把這些字符發(fā)送到服務(wù)器,然后服務(wù)器會(huì)返回一個(gè)搜索建議的列表。

AJAX 如何工作
ajax.png
AJAX使用的進(jìn)化
  • STEP1:XMLHttpRequest 原生對(duì)象
var request = new XMLHttpRequest();
request.open('GET', '/my/url', true);
request.onload = function() {
  if (request.status >= 200 && request.status < 400) {
    // Success!
    var data = JSON.parse(request.responseText);
  } else {
    // We reached our target server, but it returned an error
  }
};
request.onerror = function() {
  // There was a connection error of some sort
};
 //  send request
request.send();
  • STEP2:$.ajax 操作
$.ajax({
    type: 'GET',
    url: '/my/url',
    data: data,
    success : function(result){
        //TODO RESULT
    }
});
  • STEP3:Promise 操作
let getData = function (url) {
    return new Promsie(function (resolve, reject) {
        $.ajax({
            type: 'GET',
            url: url,
            success: function (data) {
                resolve(data);         
            },
            error: function (err) {
                reject(err);
            }
        });
    });
};
 
var data = getData('/my/url').then(function (data) {
     //TODO DATA
});
  • STEP4:生成器 Gererator (koa1 使用了此函數(shù))
let it = null;
let ajax = function(url,data){
    $.ajax({
       type: 'GET',
       url: url,
       data: data || {},
       success : function(result){
            it.next(result);
       }
    });
};
 
function *getData(){
    var data = yield ajax('/my/url');
    console.log('data=',data);
};
 
it = getData();
it.next();
  • STEP5:Async/Await 高級(jí)操作 (koa2使用了async函數(shù))
let ajax = function(url,data){
    return $.ajax({
       type: 'GET',
       url: url,
       data: data || {}
    });
};
 
async function getData(){
    var data = await ajax('/my/url');
    console.log('data=',data);
};
 
getData();

四、前后分離時(shí)代

1、jQuery 時(shí)代(開(kāi)始注重前后端分離)
  • 2006年,jQuery發(fā)布,它當(dāng)時(shí)的競(jìng)爭(zhēng)對(duì)手很多:Dojo、Prototype、ExtJS、MooTools。
    那時(shí)jQuery的宣傳口號(hào)僅能說(shuō)是它的性能上升了100%、200%、300%。
  • 2009年,Sizzle選擇器引擎研發(fā)成功,jQuery才取得壓倒性的優(yōu)勢(shì)。
    當(dāng)時(shí)前端界首要面對(duì)的是瀏覽器兼容性問(wèn)題,jQuery在處理DOM兼容上真是知微見(jiàn)著, 發(fā)掘出大量的DOM/BOM兼容方案(例如Dean Edwrad的addEvent(), IE的px轉(zhuǎn)換方案,domReady的doScroll方案,globalEval的兼容方案等)

jQuery也打破了前端開(kāi)發(fā)者的編程思維,之前是按照后端的開(kāi)發(fā)思路來(lái)的:做一個(gè)業(yè)務(wù)就先封裝一個(gè)類(lèi),有了這個(gè)類(lèi)后,再想辦法傳入一個(gè)DOM,然后再通過(guò)類(lèi)方法操作DOM。而jQuery是DOM為中心,開(kāi)發(fā)者可以選一個(gè)或多個(gè)DOM,變成jQuery對(duì)象,然后進(jìn)行鏈?zhǔn)讲僮?。?dāng)時(shí)為了改變用戶(hù)的思維,國(guó)內(nèi)的高手寫(xiě)了不少文章來(lái)引導(dǎo)大家。
其次,開(kāi)發(fā)者們已開(kāi)始注重前后端分離,并要求不能污染Object原型對(duì)象,不能污染window全局變量。這樣,jQuery只占用兩個(gè)全局變量。
再次,jQuery非常輕量級(jí),采用Dean Edwards編寫(xiě)的Packer壓縮后, 大小不到30KB。并且里面實(shí)現(xiàn)得非常精妙,以令人瞠目的手段解決各種兼容痼疾。
為了學(xué)習(xí)這些技巧,高手們翻了一遍遍jQuery的源碼,所以網(wǎng)上有大量關(guān)于其源碼詳解的書(shū)藉。甚至前端工程師在面試時(shí)也會(huì)被考到j(luò)Query的源碼實(shí)現(xiàn),這樣,jQuery在國(guó)內(nèi)更加流行。

jQuery的流行間接帶來(lái)以下的發(fā)展:
  • 促使人們對(duì)CSS1~CSS3選擇器的學(xué)習(xí)
  • 促進(jìn)了瀏覽器原生選擇器引擎document.querySelectorAll、Element.matches的誕生
  • 提高人們對(duì)domReady(DOMContentLoaded事件)的認(rèn)識(shí)
  • 促進(jìn)了Promise與requestAnimateFrame 的誕生
    最重要的是降低前端門(mén)檻,讓更多人進(jìn)入這行業(yè),前端工程師的隊(duì)伍越來(lái)越壯大。
    這樣的話(huà),不斷涌現(xiàn)出優(yōu)秀的工程師,他們創(chuàng)造了大量jQuery插件與UI庫(kù)。為后jQuery時(shí)代,人們研發(fā)前端模塊加載、統(tǒng)一異步機(jī)制、 打造大型MVC框架, 甚至伸向后端,接管打包腳本而發(fā)明Node.js,來(lái)騰出大量時(shí)間。

這個(gè)時(shí)期涌現(xiàn)了大量jQuery-like的庫(kù),其中最著名的是Zepto.js。Zepto的出現(xiàn)也標(biāo)志著我們進(jìn)入移動(dòng)互聯(lián)網(wǎng)時(shí)代。那時(shí)配套出的著名庫(kù)還有iScroll、fastclick、Lazy Load、Modernizr、fullPage。

隨著社會(huì)的發(fā)展jQuery存在的問(wèn)題:

jQuery的鏈?zhǔn)讲僮黠L(fēng)靡一時(shí),也帶來(lái)許多問(wèn)題,當(dāng)Ajax出現(xiàn)依賴(lài)時(shí),就不可避免就出現(xiàn)回調(diào)地獄。因此針對(duì)這方面的討論,誕生Deffered與Promise。有關(guān)回調(diào)地獄的討論,在后來(lái)講Node.js異步處理時(shí),將會(huì)再一次熱烈地討論。

  • 回調(diào)地獄
// Demonstrates nesting, CPS, 'callback hell'
 $.get('api1/data', function(resp1) {
     // Next that depended on the first response.
     $.get('api2/data', function(resp2) {
         // Next request that depended on the second response.
         $.get('api3/data', function(resp3) {
             // Next request that depended on the third response.
             $.get(); // ... you get the idea.
         });
     });
 });

jQuery如此多的選擇器不好維護(hù),隨著社會(huì)的發(fā)展,頁(yè)面的交互也越來(lái)越復(fù)雜,造就了Web Page向Web App進(jìn)化,新的趨勢(shì)帶來(lái)新的開(kāi)發(fā)方式。

前端的發(fā)展離不開(kāi)瀏覽器的發(fā)展
  • 瀏覽器現(xiàn)狀


    llqxz.png
  • 瀏覽器內(nèi)核


    llqnh.png
值得一提的是V8引擎(JS虛擬機(jī)):
  • 2008年9月2日,Google的chrome瀏覽器發(fā)布,一并發(fā)布的Js引擎,就是V8引擎。V8使用BSD協(xié)議開(kāi)源。
  • V8引擎使用 C++ 開(kāi)發(fā),將JavaScript編譯成了機(jī)器碼,而不是字節(jié)碼,還用很多優(yōu)化方法提高性能,因此,V8引擎 速度非???。
  • V8引擎還可以獨(dú)立運(yùn)行,可以嵌入到其他任何C++程序中,使在服務(wù)端運(yùn)行JS成為可能。
  • 2009年,基于V8引擎,誕生了Nodejs,這是服務(wù)器端運(yùn)行JS的運(yùn)行環(huán)境。
    google的V8意義重大,它間接催生了,前端工程化。
2、前端模塊化階段(后jQuery時(shí)代、node.js誕生)

jQuery的出現(xiàn)讓前端工程師開(kāi)發(fā)更加輕松,假如工程師想實(shí)現(xiàn)一個(gè)功能,搜索出一個(gè)jQuery插件來(lái)實(shí)現(xiàn)。那時(shí)候大家在前端網(wǎng)站就整天介紹jQuery插件,很少討論一些底層的實(shí)現(xiàn)。

同時(shí)也冒出很多新的問(wèn)題:
  • 前端工程師通常編寫(xiě)一個(gè)頁(yè)面,會(huì)引入十多個(gè)乃至幾十個(gè)jQuery插件,頁(yè)面上塞滿(mǎn)了Script標(biāo)簽。眾所周知,瀏覽器是單線(xiàn)程,Script的加載,會(huì)影響到頁(yè)面的解析與呈現(xiàn),導(dǎo)致著名的白屏問(wèn)題(當(dāng)時(shí)前端用力過(guò)猛,body中的所有東西都是動(dòng)態(tài)生成的)。
  • jQuery另一個(gè)問(wèn)題是全局污染,由于插件的質(zhì)量問(wèn)題,或者開(kāi)發(fā)的素質(zhì)問(wèn)題,這已經(jīng)是IIEF模塊或命名空間等傳統(tǒng)手段無(wú)法解決了。

于是一些優(yōu)秀的前端工程師們決定向后端取經(jīng),引入模塊機(jī)制。早期,這種模塊機(jī)制在Dojo、EXT這些框架中都是內(nèi)置的,但是顯然說(shuō)服不了另一個(gè)框架的用戶(hù)用對(duì)方的模塊機(jī)制,于是有人立志要統(tǒng)一這種模塊定義方式,成立了CommonJS。CommonJS誕生很久一段時(shí)間后,在后端的Node.js出現(xiàn)時(shí)才有用武之地。

CommonJS

CommonJS規(guī)范是誕生比較早的。NodeJS就采用了CommonJS。是這樣加載模塊:

// clock.js 定義
module.exports ={
  satrt:function(){}
}
// 引用
var clock = require('clock');
clock.start();

但不料,CommonJS內(nèi)部也有派系,誰(shuí)也說(shuō)不服對(duì)方。終于有一個(gè)人忍不住自己獨(dú)立開(kāi)發(fā)出RequireJS,其模塊規(guī)范即為AMD。AMD最大的優(yōu)勢(shì)是它支持各種插件,且簡(jiǎn)單明了,并且提供shim機(jī)制加載以非AMD規(guī)范編寫(xiě)的JavaScript代碼。

AMD

AMD,即 (Asynchronous Module Definition),這種規(guī)范是異步的加載模塊,requireJs應(yīng)用了這一規(guī)范。先定義所有依賴(lài),然后在加載完成后的回調(diào)函數(shù)中執(zhí)行:

// 定義
define(function () {
    return {
        attr1: 'attr1',
        attr2: 456,
        start:function(){}
    }
});
// 引用
require(['clock'],function(clock){
  clock.start();
});

AMD雖然實(shí)現(xiàn)了異步加載,但是開(kāi)始就把所有依賴(lài)寫(xiě)出來(lái)是不符合書(shū)寫(xiě)的邏輯順序的,能不能像commonJS那樣用的時(shí)候再require,而且還支持異步加載后再執(zhí)行呢?
而國(guó)內(nèi),則流行另一種規(guī)范風(fēng)格,背靠阿里的大旗,有人推出了SeaJS,號(hào)稱(chēng)其規(guī)范為CMD。其實(shí)無(wú)論國(guó)內(nèi)還是國(guó)外,都產(chǎn)生許多模塊加載器,但最后還是被淘汰了,規(guī)范一個(gè)就夠了,不宜過(guò)多。

CMD

CMD (Common Module Definition), 是seajs推崇的規(guī)范,CMD則是依賴(lài)就近,用的時(shí)候再require。它寫(xiě)起來(lái)是這樣的:

define(function(require, exports, module) {
   var clock = require('clock');
   clock.start();
});
還有一種模塊引入方法 ES6 import 、export

但是前端工程師的創(chuàng)造力就是這么驚人,從無(wú)到有,再到泛濫成災(zāi),一年足矣。這可能與前端代碼是開(kāi)源的原因。最后有人統(tǒng)一了前兩種規(guī)范(AMD、Node.js模塊),同時(shí)還支持老式的“全局”變量規(guī)范。
自此,JavaScript開(kāi)發(fā)模式煥然一身了,大家只要在代碼外面包一層就可以全世界通用,不用擔(dān)心全局污染的問(wèn)題。
其次,jQuery開(kāi)發(fā)者需要解決大段HTML的生成問(wèn)題,之前jQuery有.html,.append, $before等方法,可以將一大段符合HTML結(jié)構(gòu)的字符串轉(zhuǎn)換成DOM再插入到頁(yè)面上。
但現(xiàn)在我們想分離出來(lái),讓HTML獨(dú)立到不同的文件中,然后插數(shù)據(jù),這就是前端模板。前端模板的情況與模板規(guī)范一樣,從沒(méi)有到多如芝麻的境地。這時(shí)篩選一個(gè)好用且性能高的模板是一件讓前端工程師頭疼的問(wèn)題,那時(shí)網(wǎng)上有許多評(píng)測(cè)文章來(lái)介紹它們。
前端模板技術(shù)可以用一個(gè)公式來(lái)描述:
HTML = template(vars)
有了前端模板后,又誕生了前端路由,基于它們,人們發(fā)明一個(gè)新詞匯SPA。作為這個(gè)時(shí)代的尾聲,來(lái)自Ruby界的高手Ryan Dahl發(fā)明了Node.js。前端工程師們歡呼:可以不用傳統(tǒng)的后端就能自己寫(xiě)一個(gè)網(wǎng)站了!
Node.js的發(fā)展就不詳述了,很快它就冒出海量模塊、路由、狀態(tài)管理、數(shù)據(jù)庫(kù)、MVC框架都有了。這時(shí),前端就缺自己的MVC框架了。Node.js轉(zhuǎn)眼就十歲生日了。

3、MVC, MVVM,SPA、小程序(前端工程化階段)

在大量的MVC與MVVM框架中。最先火起來(lái)的是Backbone.js,使用純正的MVC模型, Backbone.js是jQuery最后的支持者,它強(qiáng)依賴(lài)于jQuery。
Backbone.js的作者還搞了另一套編譯語(yǔ)言CoffeeScript, 里面的箭頭函數(shù)、類(lèi)機(jī)制、 解構(gòu)賦值等語(yǔ)法糖都深深影響了后來(lái)的ES6。

前端MVC

傳統(tǒng)的MVC主要分為三部分

  • View 傳送指令到 Controller
  • Controller 完成業(yè)務(wù)邏輯后,要求 Model 改變狀態(tài)
  • Model 將新的數(shù)據(jù)發(fā)送到 View,用戶(hù)得到反饋
mvc.jpg

MVC簡(jiǎn)單實(shí)現(xiàn)

function Model(value) {
    this._value = typeof value === 'undefined' ? '' : value;
    this._listeners = [];
}
Model.prototype.set = function(value) {
    var self = this;
    self._value = value;
    setTimeout(function() {
        self._listeners.forEach(function(listener) {
            listener.call(self, value);
        });
    });
};
Model.prototype.watch = function(listener) {
    this._listeners.push(listener);
};
Model.prototype.bind = function(node) {
    this.watch(function(value) {
        node.innerHTML = value;
    });
};

function Controller(callback) {
    var models = {};
    var views = Array.prototype.slice.call(document.querySelectorAll('[data-bind]'), 0);
    views.forEach(function(view) {
        var modelName = view.getAttribute('data-bind');
        (models[modelName] = models[modelName] || new Model()).bind(view);
    });
    callback.call(this, models);
}


// html:
<span data-bind="hour"></span> : <span data-bind="minute"></span> : <span bind="second"></span>

// controller:
new Controller(function (models) {
    function setTime() {
        var date = new Date();
        models.hour.set(date.getHours());
        models.minute.set(date.getMinutes());
        models.second.set(date.getSeconds());
    }
    setTime();
    setInterval(setTime, 1000);
});

接著下來(lái)是谷歌的Angular,微軟的Knockout.js,蘋(píng)果的Ember.js這三個(gè)MVVM框架,MVVM就是比MVC多一個(gè)數(shù)據(jù)綁定功能,但這數(shù)據(jù)綁定功能是非常難實(shí)現(xiàn)。Knockout是使用函數(shù)代替屬性的技巧實(shí)現(xiàn),它的設(shè)計(jì)影響到后來(lái)的Mobx;Ember.js是基于Object.defineProperty;Angular是將函數(shù)體轉(zhuǎn)譯成setter()、getter()函數(shù)。

大公司將后端開(kāi)發(fā)經(jīng)驗(yàn)挪用過(guò)來(lái),用Node.js開(kāi)發(fā)了一套CLI,里面包含了腳手架生成, 打包腳本、語(yǔ)法風(fēng)格檢測(cè)、環(huán)境變量插入,代碼復(fù)雜度檢測(cè),代碼提交時(shí)自動(dòng)跑單元測(cè)試, 圖片與JS壓縮等功能。ESLint、JSLint、JSHint、CSS Lint、 htmllint等就是那時(shí)期出現(xiàn)的。

但CLI的出現(xiàn)導(dǎo)致了前端的分裂,以前大家都使用jQuery,但自CLI幫你建好項(xiàng)目的那一刻起,就將你劃歸某一子陣營(yíng),你是Angular?Ember.js?還是jQuery?對(duì)了,jQuery沒(méi)有大公司支撐的陣營(yíng)被快速邊緣化。

對(duì)于個(gè)人開(kāi)發(fā)者,他們是沒(méi)有能力開(kāi)發(fā)這么功能完備的CLI,于是出現(xiàn)了Code Climate、Travis CI、CircleCI這樣的平臺(tái)。它們的出現(xiàn)標(biāo)志著jQuery小作坊時(shí)代的終結(jié)了。

前端開(kāi)發(fā)者也出現(xiàn)分化:有些人轉(zhuǎn)向后端,出現(xiàn)了CNode的門(mén)戶(hù)網(wǎng)站。另外一些人開(kāi)始搞工程化。一時(shí)間出現(xiàn)上百種構(gòu)建工具,出名的有Grunt、Gulp、FIS3、webpack、 Rollup、npm-script。

你方唱罷我登場(chǎng),這些構(gòu)建工具均會(huì)經(jīng)歷時(shí)代的考驗(yàn),如大浪淘沙般,最后存活得僅為寥寥?,F(xiàn)在使用較多的webpack,Rollup。

jQuery的時(shí)代一去不返了,再?zèng)]有人關(guān)心拖了N年的Bootstrap 4終于發(fā)布了,沒(méi)有人知道jQuery3.5的瘦身計(jì)劃,也沒(méi)有人問(wèn)jQuery的源碼,漸漸地,大家不關(guān)注jQuery的工具鏈了。

以React, Vue, Angular為代表的前端框架,造就了如今SPA(single page application)的大勢(shì)所趨勢(shì)。同時(shí)React - React Native, Vue - Weex,node.js,各種小程序等也正在拓展前端的邊界。
SPA 單頁(yè)面應(yīng)用原理
  • 什么是SPA? SPA 即單頁(yè)面,就是頁(yè)面整體不刷新,不同的頁(yè)面只改變局部的內(nèi)容的一種實(shí)現(xiàn)方式。
  • 瀏覽器URL,location.hash部分發(fā)生變化,頁(yè)面不會(huì)重新請(qǐng)求,其它參數(shù)變化,均會(huì)引起頁(yè)面的重新請(qǐng)求,而在Js中恰恰有事件 window.onhashchange 能監(jiān)聽(tīng)到 location.hash的變化,于是就利用這個(gè)原理來(lái)達(dá)到一個(gè)修改局部?jī)?nèi)容的操作(vueRouter就是利用這一原理實(shí)現(xiàn)的,還有HTML5,history.pushState實(shí)現(xiàn)history模式)。
<!DOCTYPE html>
    <head>
        <script type="text/javascript">
            window.onhashchange = function(){
                var page = location.hash;
                if(page === '#home'){
                    document.getElementById('main').innerHTML = '這是首頁(yè)';
                    return;
                };
                
                if(page === '#help'){
                    document.getElementById('main').innerHTML = '這是幫助頁(yè)面';
                    return;
                };
                document.getElementById('main').innerHTML = '404';
            }
        </script>
    </head>
    <body>
        <header>
            <a href="#home">首頁(yè)</a>
            <a href="#help">幫助</a>
        </header>
        <article id="main"></article>
    </body>
</html>
單頁(yè)面應(yīng)用的問(wèn)題:
  • 對(duì)現(xiàn)有的搜索引擎不友好
  • 首頁(yè)加載速度變慢
    于是,為了解決這個(gè)問(wèn)題,前端又把網(wǎng)頁(yè)搬到后端去渲染了,出現(xiàn)了,服務(wù)端渲染(SSR: server side render)只是這次不一樣的后端渲染,跟JSP,PHP,ASP不一樣了,現(xiàn)在可以前后的分離開(kāi)發(fā),一套后臺(tái)多端使用,前后端代碼解耦,專(zhuān)業(yè)的人做專(zhuān)業(yè)的事!

什么是服務(wù)端渲染
簡(jiǎn)單理解是將組件或頁(yè)面通過(guò)服務(wù)器生成html字符串,再發(fā)送到瀏覽器,最后將靜態(tài)標(biāo)記"混合"為客戶(hù)端上完全交互的應(yīng)用程序。
需要SEO的程序,就需要SSR,但是,SSR會(huì)讓服務(wù)器的開(kāi)銷(xiāo)增加,服務(wù)器壓力比較大。

webServer(可以用node服務(wù)),CGI:(Common Gateway Interface)公共網(wǎng)關(guān)接口,CDN,交互圖:
  • 1、紅圈1表示SSR
  • 2、紅圈2表示瀏覽器渲染


    timg.jpg

五、結(jié)語(yǔ)

在前后不分的時(shí)代,由于靜態(tài)網(wǎng)頁(yè)完全滿(mǎn)足不了社會(huì)的發(fā)展對(duì)網(wǎng)頁(yè)的需求,于是,由后端工程師主導(dǎo)的PHP,JSP,ASP的動(dòng)態(tài)網(wǎng)頁(yè)誕生了,但是服務(wù)端渲染有很多的弊端,服務(wù)器壓力大,前后端代碼耦合高,交互差,頁(yè)面的交互需要刷新整個(gè)網(wǎng)頁(yè),2005年Ajax誕生,改變了一切,前端走上了第一個(gè)里程碑式的時(shí)代,前后的分離開(kāi)始注重,jQuery風(fēng)靡一時(shí),它的成功是前端人的一代記憶,各種jQuery插件層出不窮,問(wèn)題頁(yè)誕生了,各種插件的全局變量污染,jQuery的鏈?zhǔn)讲僮鞯幕卣{(diào)地獄,導(dǎo)致了模塊化,延遲對(duì)象等新技術(shù)的提出,2009年node.js誕生,催生了前端工程化,react,vue,anguler等MVC,MVVM框架的流行讓前端SPA成為大勢(shì)所趨!
前端技術(shù)的發(fā)展,是在不斷的解決問(wèn)題,誕生新的技術(shù),是社會(huì)在不斷發(fā)展中催生了新技術(shù),同時(shí)新技術(shù)又促進(jìn)社會(huì)的前進(jìn),相互交織,螺旋前進(jìn)!
本人學(xué)識(shí)有限,難免會(huì)存在理解錯(cuò)誤的地方,望碼友高逼格指正,勿噴。

參考資料:
前端的發(fā)展歷程
大前端的技術(shù)原理和變遷史
前端發(fā)展簡(jiǎn)史
前端開(kāi)發(fā)進(jìn)化史,你經(jīng)歷過(guò)哪幾個(gè)時(shí)期
等等!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容