【前端小白向】前端常見名詞大盤點(diǎn)
時(shí)間:2023-09-11 03:42:01 | 來源:網(wǎng)站運(yùn)營(yíng)
時(shí)間:2023-09-11 03:42:01 來源:網(wǎng)站運(yùn)營(yíng)
【前端小白向】前端常見名詞大盤點(diǎn):最近寫了太多技術(shù)文章,今天想寫一點(diǎn)簡(jiǎn)單的東西。當(dāng)一個(gè)新人問:如何開始學(xué)前端?很多本站人都會(huì)發(fā)這樣的腦圖:
新人表示很淦,并點(diǎn)上右上角的“關(guān)閉”。
個(gè)人也有很討厭找學(xué)習(xí)資源的時(shí)候,老手總是給一些“大而全”但對(duì)新人極度不友好的答案,我知道發(fā)圖的人可能真的想為了新人好,但是這種圖除了增加焦慮,沒有大多作用。
但是前端發(fā)明了那么多的“名詞”,不去了解又會(huì)一頭霧水。這篇文章就給大家盤一盤前端開發(fā)那些“名詞”的由來。
萬維網(wǎng)
讓我們把時(shí)間倒回 1989 年。一個(gè)英國(guó)佬 Tim Berners-Lee
發(fā)現(xiàn)他們實(shí)驗(yàn)室 CERN(European Organization for Nuclear Research) 的資料越來越難管理了,資料很容易“丟失”,比如文件名忘了、或者維護(hù)這個(gè)文件的人走了,那么這些文件可能就永遠(yuǎn)“消失”在茫茫資料中了。
這個(gè) CERN 實(shí)驗(yàn)室其實(shí)是研究物理的,并不是搞計(jì)算機(jī)的!但是當(dāng)時(shí)各個(gè)地方的實(shí)驗(yàn)室都和這個(gè)實(shí)驗(yàn)室有合作,就難免要相互分享資料。當(dāng)資料變得越發(fā)龐大的時(shí)候就很難管理了。另一個(gè)點(diǎn)是 CERN 的全名并不是英文名,而是法文:Conseil européen pour la recherche nucléaire
為此,Lee 提出 “Linked information systems” 的構(gòu)想,并稱為
World Wide Web,也即我們熟知的“萬維網(wǎng)”。
兩年后,在 1990 年,Lee 又發(fā)了第二個(gè)提案。最后提出需要2個(gè)人在6個(gè)月內(nèi)造出的萬維網(wǎng)的想法。最后造出了第一個(gè)網(wǎng)站:
http://info.cern.ch/。
從上面可以看到,一個(gè)簡(jiǎn)單的 Client-Server 架構(gòu)已經(jīng)出現(xiàn)了。把文件放到服務(wù)器上,在客戶端上訪問它。
構(gòu)建頁(yè)面骨架
對(duì)于學(xué)術(shù)論文,一般都是有專業(yè)格式的,如果只是純文字展示,換誰也受不了呀。
所以,Lee 受 SGML(Standard Generalized Markup Language) 的啟發(fā)創(chuàng)建了
HTML(Hyper Text Markup Language)。一般常用的標(biāo)簽有:h1~h6, div, header, body, main, footer, table, ul, li, button 等。
<header>頭</header><main>身</main><footer>腳</footer>
如果你簡(jiǎn)單嘗試寫一個(gè) .html 出來,會(huì)發(fā)現(xiàn)
<article>
和
<div>
的效果是一樣的。但是,為了代碼更
語(yǔ)義化,也即可以讓后面的人能看得懂,一般在頭部會(huì)使用
<header>
,如果是文章則用
<article>
作代碼塊的區(qū)分。如果非要扛:我就喜歡用 div 行不行,那不用扛了,當(dāng)然行!
美化頁(yè)面
雖然標(biāo)簽可以做一些簡(jiǎn)單的樣式,但是依然滿足不了設(shè)計(jì)師的樣式要求。
為了解決網(wǎng)頁(yè)的樣式問題,Lee 的同事 H?kon Wium Lie 在 1994 年,起草并提出了
CSS(Cascading Styling Sheet)。一段簡(jiǎn)單的 CSS 就可以讓頁(yè)面豐富起來了:
body { color: red;}
很多人可能都知道 CSS 這個(gè)玩意,用得理所當(dāng)然,但是你有沒有想過,其實(shí) XML 也可以用來表示樣式的,比如在 Android 上就是這么做的。在那個(gè)時(shí)候, DSSSL 和 FOSI 也曾是瀏覽器樣式的候選人,但是用這兩玩意來寫樣式太麻煩了,所以最后才選擇 CSS 作為瀏覽器的樣式書寫標(biāo)準(zhǔn)。
現(xiàn)在我們使用 CSS 已經(jīng)是非常好用了,但在以前 CSS 的標(biāo)準(zhǔn)化之路是充滿著坎坷的:
- 當(dāng) CSS1.0 發(fā)布后,幾乎沒多少瀏覽器可以支持它。等支持 CSS1.0 的時(shí)候 CSS2.0 都已經(jīng)被放出來了
- CSS2.0 增加了更多的樣式選擇。CSS2.0 是在1997年提出來的,但是在升級(jí)為 3.0 的時(shí)候經(jīng)歷了大幅的打回、重改,重新提名。直到 2011年 CSS2.1 才作為標(biāo)準(zhǔn)發(fā)布出來
- 到了 CSS3.0,它不像 1.0 和 2.0 那樣整個(gè)版本升級(jí),而是將樣式的升級(jí)模塊化?,F(xiàn)在,雖然我們用的還是 “CSS3.0”,但是其實(shí)某些模塊已經(jīng)可以算是 4.0
CSS UI 庫(kù)
寫了很多次 CSS 后,前端工程師們發(fā)現(xiàn),一些好看的 CSS 樣式可以拿出來共享呀,比如我寫好了一個(gè)按鈕的樣式:
.btn { ...}
然后,其它人只要復(fù)制這個(gè) CSS 到他的項(xiàng)目里,然后在 HTML 用上 CSS 類名,就可以直接用上我寫的效果啦。
<button class="btn">我的按鈕</button>
在這段時(shí)間里,各種 UI 小組件的 CSS 樣式滿天飛,比如今天出個(gè)按鈕的,明天就出了個(gè)輸入框的。市面上還曾出現(xiàn)過很多類似《XX個(gè)好看的UI組件》和《XXXX年最好看的Y個(gè)UI組件》的文章。
不久后,開發(fā)者就發(fā)現(xiàn)另一 個(gè)問題:組件樣式之間的沖突,比如,按鈕的樣式影響了自定義按鈕的樣式。另一個(gè)大問題是,單看一個(gè)組件的樣式挺好看的,但是如果一個(gè)網(wǎng)頁(yè)用了4 5 個(gè)別人寫好的 CSS 樣式,就會(huì)顯得非常不協(xié)調(diào),沒有統(tǒng)一感。兼容性也很差。
Twitter 的 Mark Otto 和 Jacob Thornton 也想過這個(gè)問題,所以他們開發(fā)了
Bootstrap UI 庫(kù):
<div class="input-group mb-3"> <span class="input-group-text" id="basic-addon1">@</span> <input type="text" class="form-control" placeholder="Username" aria-label="Username" aria-describedby="basic-addon1"></div>
把常用的按鈕、字體、輸入框的一些樣式都寫好了,還提供示例代碼。這個(gè) UI 庫(kù)發(fā)布了之后,幾乎所有開發(fā)者用過了,畢竟 CSS 終于可以不用自己寫了。
當(dāng)時(shí)我的也用 Bootstrap 寫過課堂作業(yè),那真是爽啊,一行 CSS 都沒寫過。
響應(yīng)式布局
2011年,蘋果發(fā)布了那款經(jīng)典的 iPhone4S,標(biāo)志著智能手機(jī)真正成為人們不可或缺的一部分,而手機(jī)上訪問的需求也同時(shí)增加了不少。
當(dāng)年在手機(jī)上看網(wǎng)頁(yè),用戶都要先進(jìn)入頁(yè)面,手動(dòng)放大,點(diǎn)擊對(duì)應(yīng)鏈接再進(jìn)入下一個(gè)網(wǎng)頁(yè),操作非常復(fù)雜,而且界面很丑陋。
另一個(gè)方面,隨著手機(jī)進(jìn)入人們的生活,手機(jī)上的 App 也像雨后春筍一樣瘋狂冒出。這時(shí),程序員就想:就把網(wǎng)頁(yè)做成 App 的樣子不就好看了嘛。
那怎么判斷用戶用的是手機(jī)還是電腦呢?很簡(jiǎn)單:通過屏幕寬度來判斷嘛,而 CSS 的
media query(媒體查詢) 正好可以用來解決這個(gè)問題:
/*屏幕寬度在 600px 以內(nèi)時(shí),背景色顯示紅色*/@media only screen and (max-width: 600px) { body { background-color: red; }}/*大于 600它時(shí),背景色顯示白色*/@media only screen and (min-width: 600px) { body { background-color: white; }}
問題又來了:難道每個(gè)兼容樣式都要寫兩遍?能不能只寫一種樣式就能兼容手機(jī)和電腦端呢?程序員們開始通過百分比,em,rem,優(yōu)化布局等方式,使得屏幕變小后樣式還是不會(huì)亂。
這種寫 CSS 的思路就叫做
響應(yīng)式 布局,兼容了手機(jī)和網(wǎng)頁(yè)。
不過
響應(yīng)式 也不是萬能的。比如今天淘寶頁(yè)面里的一些花里胡哨的樣式就沒法兼容手機(jī)端,所以現(xiàn)在的做法是做兩套網(wǎng)頁(yè),電腦端做一套,手機(jī)端做一套。區(qū)別是:手機(jī)端的樣式做得像 App 一些,而且功能不會(huì)太多,樣式也不會(huì)很復(fù)雜,而且提供“從XX App”打開的按鈕,向自家的 App 引流。電腦端更酷炫,功能更強(qiáng)大。畢竟現(xiàn)在應(yīng)該沒人在手機(jī)網(wǎng)頁(yè)上購(gòu)物吧?
如果你仔細(xì)看手機(jī)端的網(wǎng)頁(yè)地址,都會(huì)以 m.xxxxx 開頭,就表示網(wǎng)頁(yè)只在手機(jī)上看的。
JavaScript 將內(nèi)容動(dòng)起來
注意:上面的 HTML、CSS 都不屬于編程語(yǔ)言,HTML 是標(biāo)記語(yǔ)言,而 CSS 是樣式表。
現(xiàn)在我們有 HTML 和 CSS 已經(jīng)可以讓頁(yè)面變好看了,但是頁(yè)面內(nèi)容都是定死的。為了能讓頁(yè)面“動(dòng)”起來,瀏覽器必須要引入一種編程語(yǔ)言。那就是
JavaScript。
當(dāng)年,本來有人想把 Java 用作瀏覽器的編程語(yǔ)言的,但是搞 Java 的 Sun 公司說:沒空理你。所以,網(wǎng)景公司 NetSpace 只好自研編程語(yǔ)言。本來新語(yǔ)言想叫作 LiveScript,但是覺得這個(gè)名字又平平無其,不能一炮而紅。當(dāng)時(shí) Java 正如日中天,所以,為了做個(gè)標(biāo)題黨、蹭個(gè)熱度,在 12 月發(fā)布的時(shí)候改名為
JavaScript,并引入了一些 Java 的特性,然而,令人沒想到的是,這些特性將會(huì)成為前端工程師的噩夢(mèng)。
JavaScript 除了做一些簡(jiǎn)單的業(yè)務(wù)邏輯,比如判斷是男是女:
if (you === 'male') { console.log('男男')}
還會(huì)操作 HTML,但是 HTML 不是一段文本么?怎么操作呢?實(shí)際上當(dāng)瀏覽器拿到 .html 文件后,會(huì)自動(dòng)解析 HTML 文本,將其轉(zhuǎn)為為
DOM(Document Object Modal),將普通的文本轉(zhuǎn)換為一棵樹的結(jié)構(gòu)。
JS 只需操作 DOM 就可以修改 HTML 的布局和結(jié)構(gòu)了。
document.getDocumentById('hello').textContent = '我是帥哥' // 內(nèi)容變成“我是帥哥”
JavaScript 是一個(gè)設(shè)計(jì)極其糟糕的語(yǔ)言,比如
getMonth()
時(shí),如果現(xiàn)在是1 月,返回的則是
0
,而
getHours()
又會(huì)準(zhǔn)確返回當(dāng)前的小時(shí)數(shù)。對(duì)于數(shù)組的操作又少得可憐,比如沒有
unique
,
findBy
這些 API。
為了給 JavaScript 的設(shè)計(jì)擦屁股,一些工具庫(kù)營(yíng)運(yùn)而生:
- jQuery: 提供很多操作 DOM 的 API
- moment, dayjs:提供很多操作 Date 對(duì)象的 API
- lodash:更多像是個(gè)工具庫(kù)
服務(wù)端渲染
雖然 JS 能動(dòng)態(tài)修改內(nèi)容了,但是,在以前發(fā)異步請(qǐng)求是一件很麻煩的事情。
Java 程序員想到了一個(gè)辦法:JSP。反正要訪問服務(wù)端,不如在你訪問的時(shí)候,我直接從數(shù)據(jù)庫(kù)里把數(shù)據(jù)讀出來,生成一個(gè) HTML 給你不就好了嘛。這種技術(shù)就叫做 JSP。
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><%@ page import="java.io.*,java.util.*" %><!DOCTYPE html><html><head><meta charset="utf-8"><title>菜鳥教程(runoob.com)</title></head><body><h2>HTTP 頭部請(qǐng)求實(shí)例</h2><table width="100%" border="1" align="center"><tr bgcolor="#949494"><th>Header Name</th><th>Header Value(s)</th></tr><% Enumeration headerNames = request.getHeaderNames(); while(headerNames.hasMoreElements()) { String paramName = (String)headerNames.nextElement(); out.print("<tr><td>" + paramName + "</td>/n"); String paramValue = request.getHeader(paramName); out.println("<td> " + paramValue + "</td></tr>/n"); }%></table></body></html>
被程序員一直喊為 “世界上最好的編程語(yǔ)言” PHP也沿用了這個(gè)思路。這類通過服務(wù)端動(dòng)態(tài)生成 HTML 的方法就叫
SSR(Server Side Rendering) 服務(wù)端渲染。
但是這上面有兩個(gè)問題: 1. 如果 Java 里有報(bào)錯(cuò)的時(shí)候,頁(yè)面會(huì)顯示整個(gè)錯(cuò)誤 Stack 給用戶,體驗(yàn)非常不友好,而且一崩全崩
- 高度耦合的代碼非常不利于維護(hù),比如,第一眼看上面的代碼能看出個(gè)啥子哦
- 一個(gè)工程師除了要處理服務(wù)端的邏輯、也要考慮樣式要怎么寫、頁(yè)面邏輯,職責(zé)不明確
雖然上面的 JSP 和 PHP 流行過一段時(shí)間,但是程序員們?yōu)榱朔止じ鞔_,都選擇了前端程序員管頁(yè)面開發(fā)、而后端程序員管服務(wù)端的開發(fā)。這種開發(fā)模式也被稱作
前后端分離。
而前后端的重要溝通橋梁就是
異步請(qǐng)求,也即大家現(xiàn)在經(jīng)常說的
Ajax請(qǐng)求,但是在很久以前,異步請(qǐng)求還是一個(gè)實(shí)現(xiàn)上特別困難的事情。在那個(gè)時(shí)候發(fā)完請(qǐng)求,頁(yè)面就不得不重新刷新一遍,用戶體驗(yàn)非常差。
JSONP
上面說到的問題在于:瀏覽器很難在不刷新頁(yè)面的情況下,向服務(wù)器發(fā)異步請(qǐng)求來獲取內(nèi)容。
聰明的程序員就開始想:什么東西能發(fā)異步請(qǐng)求呢?然后他們發(fā)現(xiàn)如果直接創(chuàng)建一個(gè) img 標(biāo)簽并寫上 src 就會(huì)向服務(wù)器發(fā)一個(gè) xxx.jpg 的異步請(qǐng)求了:
<img src="xxx.jpg">
那么如果要發(fā)個(gè)異步的 Get 請(qǐng)求,可以這樣搞呀: 1. 偷偷摸摸地創(chuàng)建一個(gè)看不見的 img 標(biāo)簽 2. 把要訪問的 url 放到 src 里
function getData(url) { var imgEl = document.createElement('img') // 創(chuàng)建 img 標(biāo)簽 imgEl.visibility = 'none' // 把 img 標(biāo)簽變成不可見 imgEl.src = url document.appendChild(img) // 加在網(wǎng)頁(yè)上,自動(dòng)發(fā)送 Get 請(qǐng)求}
但是上面這么又引出下面的問題: 1. 不知道什么時(shí)候要清理新生成的 img 2. 請(qǐng)求發(fā)了就發(fā)了,響應(yīng)后不知道怎么獲取數(shù)據(jù) 3. 每次都要寫
imgEl.visibility = 'none' // 把 img 標(biāo)簽變成不可見
這句話
為此,程序員再次想了很多辦法。
首先,不再使用 img 標(biāo)簽,而使用 script 標(biāo)簽,就可以把第 3 步省略了。
第二步,在全局定義一個(gè)函數(shù)用于獲取 users 信息:
function getUsers(users) { console.log(users)}
在寫 url 的時(shí)候加一個(gè)參數(shù)上去:
https://www.baidu.com/users?callback=getUsers
。服務(wù)端從參數(shù)里讀取到 getUsers,向?yàn)g覽器返回 JS 腳本:
getUsers(['Jack'. 'Mary'])
由于剛剛添加的標(biāo)簽是 script 標(biāo)簽,所以等服務(wù)器返回后,
getUsers(['Jack'. 'Mary'])
就會(huì)被馬上執(zhí)行,最終就會(huì)將
users
打印出來。這種技術(shù)就叫做
JSONP,全稱為 JSON with padding。
JSONP 另一個(gè)好處是可以實(shí)現(xiàn)跨域請(qǐng)求,因?yàn)?script 標(biāo)簽可以請(qǐng)求非同源策略的資源并獲取返回的數(shù)據(jù)。但是這非常不安全,服務(wù)器很容易被一些惡意的 JS 代碼給攻擊了。
Ajax
從上面看出來 JSONP 能用但是很不規(guī)范,程序員們非常想要一套完善的異步請(qǐng)求機(jī)制。
2004 年,Google 在開發(fā) Gmail 和 Map 兩個(gè)應(yīng)用的時(shí)候,完善了異步請(qǐng)求的機(jī)制,并制定了一些標(biāo)準(zhǔn)。
2006年時(shí), W3C 起草了第一份 XMLHttpRequest 的草案,然后不斷完善,一直到最后一份草案則在 2016年 被提出,
XMLHttpRequest 才成為正式的標(biāo)準(zhǔn)。我們經(jīng)常所說的 Ajax 請(qǐng)求其實(shí)就是使用這個(gè)對(duì)象來發(fā)請(qǐng)求的。下面就是用這個(gè)對(duì)象發(fā)送請(qǐng)求的代碼:
// 生成請(qǐng)求對(duì)象xmlhttp = new XMLHttpRequest();// 監(jiān)聽請(qǐng)求的狀態(tài)和返回xmlhttp.onreadystatechange = function () { if (xmlhttp.readyState === 4) { if (xmlhttp.status === 200) { // 200 = OK console.log('成功'); } else { console.log('失敗'); } }};// 打開通道xmlhttp.open('GET', url, true)// 發(fā)送請(qǐng)求xmlhttp.send(null);
Ajax 全名是 Asynchronous JavaScript and XML,它不是單單一門技術(shù),而是多門技術(shù)的全集,所表求的是:在客戶端創(chuàng)建異步應(yīng)用的一系列技術(shù)。只不過核心其中一步就是發(fā)異步請(qǐng)求,而 XMLHttpRequest 正好可以幫助我們完成這項(xiàng)工作。
Node.js
2009 年,前端另一大颶風(fēng)席卷了全球。Ryan Dahl 編寫了第一個(gè)最初版本的 Node.js,使得 JavaScript 除了可以在瀏覽器里運(yùn)行,也可以在擁有 Node.js 平臺(tái)的地方運(yùn)行,比如自己電腦的終端里。
JavaScript 終于不再是客戶端語(yǔ)言,也可以做服務(wù)端的開發(fā)了。為了更方便做服務(wù)端的開發(fā),TJ Holowaychuk 一個(gè)國(guó)外超級(jí)大佬,借鑒了 Ruby 社區(qū)的 Rack,開發(fā)了 Express.js,一個(gè)簡(jiǎn)易的 JS 服務(wù)器框架。
由于 Express.js 提供的功能太簡(jiǎn)單了,所以,很多開發(fā)者不斷給這個(gè)框架開發(fā)各種各樣的中間件,使用者可以用這些中間件增強(qiáng)自己服務(wù)器的功能,比如
body-parser, cookie-parser, passport 等。
后來,TJ 覺得 Express.js 寫得還是不夠精簡(jiǎn),本來想重構(gòu)的,但是重構(gòu)成本太大了,干脆再造一個(gè)輪子吧,這個(gè)輪子也就是我們熟悉的 Koa.js。
為了讓 JS 更好地完成服務(wù)端開發(fā)的工作,前端開發(fā)人員把后端開發(fā)的一些工具都造了一遍:
- 連接數(shù)據(jù)庫(kù):mysql, mysql2, mongodb
- 緩存:session, redis
- ORM: TypeORM, sequelize
- 定時(shí)任務(wù):node-schedule, cron
- ...
Serverless
當(dāng)很多人都開始用 Node.js 的時(shí)候,大家又發(fā)現(xiàn)一些問題:
- 寫完代碼,本地跑起來也挺好的,那怎么部署到服務(wù)器上呢?
- 服務(wù)器要怎么買?HTTPS證書從哪里獲???Nginx是個(gè)啥?啊,好煩啊,我只想
npm run start
啊
作為前端程序員,平時(shí)搬磚就夠累了,還要我配置服務(wù)器,一劍殺了我算了。
聰明的程序員發(fā)現(xiàn),不管你寫 Express.js 還是 Koa.js 不就是寫響應(yīng)函數(shù)么?
app.get('/users', (req, res) => { res.send('我是帥哥')})
那我把服務(wù)器、證書、域名這些東西都統(tǒng)統(tǒng)給你弄好,你就負(fù)責(zé)寫相應(yīng)函數(shù)和給錢不就很爽了么?這就是
Serverless 的由來。它的好處是不再操心服務(wù)器的配置、擴(kuò)展等瑣碎的事情,只需要寫好響應(yīng)函數(shù)就好了。而這種“響應(yīng)函數(shù)”也被稱為
云函數(shù),Amazon 稱此為
Lambda。
這時(shí)候有人發(fā)現(xiàn),我自己寫好的一些服務(wù),比如收發(fā)郵件、數(shù)據(jù)庫(kù)的存取也可以作為一種服務(wù)對(duì)外提供,前端工程師只需要給錢,然后請(qǐng)求我提供的 API 接口就可以享受我的服務(wù)啦。這也是很多云廠商另一種收入來源:賣服務(wù)。
比如,常見的:語(yǔ)言翻譯服務(wù)、手機(jī)短信發(fā)送服務(wù)、鑒黃師、圖形識(shí)別等。
模塊化
當(dāng)工具變得越來越多,Web 應(yīng)用體積也變得越來越大了。一個(gè)大項(xiàng)目里可能有成百上千個(gè) JavaScript 文件,它們之間相互依賴,可怕的是當(dāng)前沒有工具可以告訴你到底哪個(gè)文件是最先被執(zhí)行的。
文件的管理就成了一個(gè)大問題,所以以應(yīng)用需要?jiǎng)澐帜K。
在 ES6 之前,社區(qū)制定了一些模塊加載方案,最主要的有
CommonJS 和
AMD 兩種。前者用于服務(wù)器,后者用于瀏覽器。
const xxx = require('xxx')
ES6 在語(yǔ)言標(biāo)準(zhǔn)的層面上,實(shí)現(xiàn)了模塊功能,而且實(shí)現(xiàn)得相當(dāng)簡(jiǎn)單,完全可以取代 CommonJS 和 AMD 規(guī)范,成為瀏覽器和服務(wù)器通用的模塊解決方案。ES6 模塊的設(shè)計(jì)思想是盡量的靜態(tài)化,使得編譯時(shí)就能確定模塊的依賴關(guān)系,以及輸入和輸出的變量。
import xxx from 'xxx'export default xxx
模塊化思想的提出大大提高了 JS 程序員的幸福感,所有的 JS 文件都不再是同一層級(jí),而可以分塊管理了。對(duì)前端的工程化有著不可或缺的作用。
包管理工具
有的工程師發(fā)現(xiàn),自己抽象出來的模塊其實(shí)也可以放在社區(qū)讓別人使用,比如發(fā)異步請(qǐng)求的 axios,工具庫(kù) lodash 等。這就需要一個(gè)中心倉(cāng)庫(kù)來存放這些庫(kù)了,同時(shí)也需要一個(gè)包管理工具來管理包的發(fā)布、安裝、升級(jí)等。
目前
npm 就是使用最多的包管理工具,當(dāng)電腦里裝了 Node.js 后,
npm 也會(huì)一并裝上。不過使用 npm 在國(guó)內(nèi)下載時(shí)會(huì)很慢,一般推薦使用
yarn 這個(gè)包管理工具,速度更快。
工程化
模塊拆分使得寫代碼時(shí)候爽了,但是如果把這些 JS 文件都引入到一個(gè) HTML 上是不是太恐怖了?一個(gè) HTML 里有 1000 個(gè) script 標(biāo)簽,比內(nèi)容還多也有點(diǎn)反人類了吧。CSS 文件同理。
為了解決這個(gè)問題,前端工程師提出了 bundle 這個(gè)概念——不管你的模塊多亂,多分散,最終通過一個(gè)工具,直接轉(zhuǎn)換為1 個(gè) .js 文件。這樣的工具就叫做打包工具。
在 2016 年,Grunt,一個(gè) JavaScript Task Runner 被制作出來了,開發(fā)者可以編寫自己的任務(wù),然后流水線地執(zhí)行。這已經(jīng)有了工程化的雛形了。
但是 Grunt 的打包速度太慢了。工程師們受不了了,又造了一個(gè)
Glup 的打包工具,功能差不多,但是一個(gè)字快!
與此同時(shí),另一只巨獸也在悄然進(jìn)化——
Webpack。
Webpack 以其強(qiáng)大的功能、高靈活配置度的特性直接搶奪了 Glup 的市場(chǎng),很多人都紛紛用起了 Webpack。
隨著 Webpack 的功能不斷增強(qiáng),開發(fā)者的要求也不斷提高,市面上充斥著大量的 Loader 和插件:
- 熱加載
- 代碼混淆
- 代碼壓縮
- 精簡(jiǎn)代碼、TreeShaking
- loader: file-loader, css-loader, vue-loader
- ...
Webpack 的另一個(gè)問題是,不同環(huán)境需要不同的 Webpack 打包配置,導(dǎo)致 Webpack 的配置越來越繁瑣,前端工程師除了平常寫代碼之外,還要負(fù)責(zé)維護(hù)
webpack.config.js
的配置項(xiàng)目。
而
Parcel 的出現(xiàn)正好打破了這一局面,使用 Parcel 就像使用 iPhone 一樣,不用太多配置可以馬上跑出小網(wǎng)頁(yè)。但是,治本不治根,在大型項(xiàng)目面前,還是沒辦法解決繁瑣配置的問題。所以,Webpack 依舊是占領(lǐng)市場(chǎng)的巨頭。
使用 Webpack 的另一個(gè)問題是本地開發(fā)打包很慢,Webpack 一般先打包構(gòu)建再啟動(dòng)開發(fā)服務(wù)器。而 Evan You 則想到另一個(gè)方法:先啟動(dòng)開發(fā)服務(wù)器,當(dāng)代碼執(zhí)行到模塊加載時(shí)再請(qǐng)求對(duì)應(yīng)模塊的文件。加快本地開發(fā)時(shí)的打包編譯速度,然后造出了
Vite。目前 Vite 還是個(gè)新生兒,可以關(guān)注一波,看看以它以后會(huì)迸發(fā)出什么好玩的東西。
CSS 預(yù)處理器
CSS 讓人詬病的一點(diǎn)是不夠簡(jiǎn)潔,很多東西不能復(fù)用。比如:
.container { background: red; /*背景為紅色*/}.container .title { color: red; /*標(biāo)題字體為紅色*/}
為什么不寫成這樣呢:
.container { backtround: red; /*背景為紅色*/ .title { color: red; /*標(biāo)題字體為紅色*/ }}
遺憾的是,瀏覽器只認(rèn)識(shí) CSS,不認(rèn)識(shí)上面這樣的寫法。程序員又開始思考了:其實(shí)我不用瀏覽器認(rèn)識(shí)第二種寫法,我只要把第二種寫法在打包的時(shí)候轉(zhuǎn)換成 CSS 不就行了嘛。有了打包工具的加成,這件事我覺得能成!所以,第二種高級(jí)寫法被稱為
CSS 預(yù)處理器,即這些寫法要先被處理成 CSS,然后再以普通 CSS 使用。
于是,在 2007 年,
Sass 誕生了,借鑒了 Ruby 社區(qū)的 Sass 語(yǔ)法,但是前端程序員比較傲嬌:憑啥要跟你叫一個(gè)名,就叫為 Scss,不過一般叫法還是叫 Sass,因?yàn)?Scss 不會(huì)讀,哈哈。
后來在 2009 年,
Less 被創(chuàng)造出來了,語(yǔ)法 Scss 差不多,沒多大差別。
在 2010 年,又一個(gè)預(yù)處理器
Stylus 誕生了。
目前 Scss 和 Less 用的比較多,Stylus 名氣比較小。新手不用擔(dān)心,這三玩意語(yǔ)法都差不多,大同小異,會(huì)一個(gè)相當(dāng)于3個(gè)都會(huì)了。
進(jìn)擊的 JavaScript
雖然 JavaScript 本來是一個(gè)設(shè)計(jì)非常糟糕的編程語(yǔ)言,但是 JS 它不是咸魚,它也要努力成為世界上最好的編程語(yǔ)言!
JavaScript 總不能一成不變吧?但是也不能一下子就變天了吧?所以,需要有一個(gè)起草方案,審核方案,同意方案,變成規(guī)范的過程,這需要大量的人力和專家,那不如做一個(gè) “JS愛好者協(xié)會(huì)”?
European Computer Manufacturers Association (ECMA) 就是類似這樣的組織,不過這個(gè)組織格局比“JS愛好者協(xié)會(huì)”的格局大多了,主要任務(wù)是是將 Computer System 標(biāo)準(zhǔn)化。
ECMA International 在 ECMA-262 里規(guī)范了 JavaScript,可以認(rèn)為 ECMAScript 就是標(biāo)準(zhǔn)的 JavaScript,所有瀏覽器都要支持標(biāo)準(zhǔn)的 JavaScript。這個(gè) 262 的標(biāo)準(zhǔn)規(guī)范從 1997 年開始提出了第 1 版。
從上面可以看到,往后幾年就是第 N 代的 ES 標(biāo)準(zhǔn)對(duì)應(yīng)標(biāo)準(zhǔn)的 JavaScript 就是 ECMAScript 201(N-1),比如我們最熟悉的 ES6 其實(shí)就是 ECMAScript 2015。而 ES6 對(duì) JavaScript 一個(gè)大變革,后面的 ES7,ES8 新增的東西就很少了,所以現(xiàn)在 ES6 其實(shí)是 ES6+ 的一個(gè)泛指。
但是你有沒有想過一個(gè)問題:雖然我用最新的語(yǔ)法做開發(fā),但是用戶用的可能還是老版本的瀏覽器呀,這要怎么辦呢?
再次得益于自動(dòng)化打包工具的興起,我們可以在開發(fā)的時(shí)候用最新的語(yǔ)法,在打包生產(chǎn)代碼時(shí)將新語(yǔ)法都轉(zhuǎn)成舊語(yǔ)法就好了嘛。這種語(yǔ)法的轉(zhuǎn)換聽起來就很麻煩,不過,聰明的前端工程師已經(jīng)幫各位大哥大嫂做好,那就是
Babel。
Babel 發(fā)展到了現(xiàn)在,除了做新舊語(yǔ)法的轉(zhuǎn)換,還支持 JSX 語(yǔ)法的轉(zhuǎn)換。
TypeScript
雖然 ES6 新增的語(yǔ)法和 API 已經(jīng)大幅提升前端程序員的幸福感了,但是 JavaScript 依然是個(gè)弱類型的語(yǔ)言:
類型不規(guī)范,同事兩行淚。當(dāng)不正確使用類型時(shí):
那能不能強(qiáng)行給 JavaScript 加上類型呢?微軟說:可以!由微軟牽頭,開發(fā)了
TypeScript 編程語(yǔ)言和 TypeScript 的編譯器,前者其實(shí)是 JavaScript 的超集,只是多加了很多料;后者則是負(fù)責(zé)將 TypeScript 編譯成 JavaScript。
注意:這里的 TypeScript -> JavaScript 是不能用 Babel 實(shí)現(xiàn)的,因?yàn)檫@一步是編譯,而不是新舊語(yǔ)法的替換。TypeScript 不是新語(yǔ)法,是一門正經(jīng)的編程語(yǔ)言,只不過可以被編譯成 JavaScript。
有了 TypeScript,開發(fā)者終于享受到了強(qiáng)類型約束的福利了:
const x: string = '123'
再再再一次得益于自動(dòng)化打包工具人 Webpack,可以在輸出生產(chǎn)代碼時(shí)將 TypeScript 編譯成 JavaScript,如果再加上 Babel,則能進(jìn)一步轉(zhuǎn)為某個(gè)時(shí)代的 ECMAScript。
單頁(yè)應(yīng)用
在打包工具不斷廝殺的同時(shí),單頁(yè)應(yīng)用框架也一并發(fā)展。
在以前,大部分都是一直在用 jQuery 直接操作 DOM 來更新頁(yè)面。
每次操作 DOM 時(shí)就不得不寫一些面條代碼。但是這樣很麻煩啊,操作 DOM 這一步能不能封裝一下,數(shù)據(jù)更新時(shí)自動(dòng)操作 DOM 去更新頁(yè)面?
2010 年,Google 研發(fā)的
Angular.js 率先實(shí)現(xiàn)了
MVVM 想法,即開發(fā)者不再需要操作 DOM,可以直接拿數(shù)據(jù)渲染頁(yè)面 Modal-View,而頁(yè)面的變化,比如輸入值改變,可以反過來改變數(shù)據(jù)內(nèi)容。后來又研發(fā)了 Angular2,但是無論是 Angular.js 還是 Angular 本身都太復(fù)雜了,借鑒了非常多的后端設(shè)計(jì),前端工程師上手難度非常巨大,最終并沒有形成大潮流。
注意 Angular.js 和 Angular 是兩個(gè)不同的東西!
2013 年,一個(gè)新的前端框架誕生了——Facebook 的 React.js。React 可以說是一個(gè)非常純凈的 JS 框架,沒有 Angular 繁瑣的內(nèi)容,開發(fā)者只需要關(guān)注單向數(shù)據(jù)流就可以上手?jǐn)]頁(yè)面了。最后 React.js 在前端社區(qū)流行了起來。
但是 React.js 也有自己的問題:由于 React.js 內(nèi)容太過于純凈了,本身沒有太多的功能,導(dǎo)致開發(fā) React 應(yīng)用時(shí)出現(xiàn)非常多的解決方案,但沒有一個(gè)方案是最優(yōu)的,各有各的優(yōu)缺點(diǎn)。這也導(dǎo)致了 React 社區(qū)總是罵戰(zhàn)不斷、幫派林立、出現(xiàn)各式各樣的鄙視鏈的局面。
比如,在寫樣式時(shí)你可以直接 import 樣式文件:
import 'xxx.css'const xxx = <button className="xxx">xxx</button>
也可以用 CSS module
import styles from 'xxx.css'const xxx = <button className={styles.xxx}>xxx</button>
也可以用 styled-component
const Button = styled.a` color: white;`const xxx = <Button>xxx</Button>
但是偏偏有人說 styled-components 是高級(jí)人,別的都是垃圾,使用 CSS Module 的人就受不了了,說你天天引那么多庫(kù)來干嘛?
另一個(gè)麻煩點(diǎn)是,單向數(shù)據(jù)流并不是所有人都喜歡的,人們開始懷念 Angular 的數(shù)據(jù)雙向綁定了。
到了 2014 年,那個(gè)男人來了,他帶著
Vue.js 來了!
Evan You 以前在 Google 和 Meteor 工作過。
Vue.js 取了 Angular 和 React 的中間位置,以一種優(yōu)雅、輕便的姿態(tài)登陸前端社區(qū)。保留了 Angular 的數(shù)據(jù)雙向綁定,但是摒棄了 Angular 很多復(fù)雜的設(shè)計(jì)和 API,同時(shí)不像 React.js 那么純凈,開放很多方便的 API 給使用者爽爽。而且還基于 Webpack 開發(fā)了 vue-loader 用來解析 .vue 模板文件。這種 .vue 模板文件和 .html 非常相象,新人上手十分簡(jiǎn)單。
同時(shí),得益于 Vue 簡(jiǎn)潔好看的中文官方文檔,Vue.js 在中國(guó)迅速搶占了小公司的市場(chǎng)。
但是由于 Vue.js 太容易上手了,所以經(jīng)常被 React.js 社區(qū)的一些人覺得寫 Vue.js 的人都是新手。而 Vue.js 的人又覺得寫 React.js 的人天天折騰這么多“最佳實(shí)踐”,簡(jiǎn)直是在浪費(fèi)生命,而且 JSX 的語(yǔ)法太丑了,不如我的 template 語(yǔ)法簡(jiǎn)潔好懂。直到現(xiàn)在,Vue 和 React 社區(qū)時(shí)不時(shí)就會(huì)爆發(fā)小規(guī)模的罵戰(zhàn)。
另一個(gè)問題出現(xiàn)了:原來的 UI 庫(kù)僅僅提供了簡(jiǎn)單的 CSS 和原生的 JS,這些 JS 放到單頁(yè)應(yīng)用里顯得有點(diǎn)冗余了,有的還會(huì)報(bào)錯(cuò),因?yàn)榇蠖鄶?shù)都是 DOM 的操作。所以 UI 庫(kù)必須要配合對(duì)應(yīng)的 SPA 框架進(jìn)行升級(jí)。在別的 UI 庫(kù)升級(jí)的同時(shí),餓了么針對(duì) Vue.js 開發(fā) Element UI,而螞蟻金服則針對(duì) React 開發(fā)了 Antd。隨后,更多的 UI 庫(kù)再次涌現(xiàn),比如 iView、Ant Design for Vue, Ant Design for Angular 等。
總得來說,Angular, React.js, Vue.js 都開發(fā)了自己的一套單頁(yè)應(yīng)用框架,這套框架最后要做的就是 SPA(Single Page Application) 單頁(yè)應(yīng)用。即所有的邏輯都打包在 JavaScript 文件里了,對(duì)外,只會(huì)看到一個(gè) .html,一個(gè) .css 和一個(gè) .js 文件。
等一下?一個(gè) .html 文件?那不同頁(yè)面怎么做跳轉(zhuǎn)呢?這就是前端路由的由來了。
前端路由
不妨想想以前是怎么做路由的:用戶頁(yè)是 user.html,首頁(yè)是 index.html,一個(gè) url 對(duì)應(yīng)著一個(gè)文件,也就說我們每次鍵入 url 時(shí),實(shí)際上是訪問某個(gè) .html。
而瀏覽器里有一個(gè)監(jiān)聽瀏覽器地址改變的功能,單頁(yè)應(yīng)用的開發(fā)者就想了:我只要監(jiān)聽地址 url 的變化,再用 JS 渲染對(duì)應(yīng)的頁(yè)面組件,不就可以實(shí)現(xiàn)前端控制路由了么?這就是前端路由的基本思想。
上面的三大單頁(yè)應(yīng)用框架都有自己的前端路由框架:
@angular/router, react-router, vue-router。
數(shù)據(jù)管理
單頁(yè)應(yīng)用框架另一個(gè)問題就是數(shù)據(jù)的管理,子組件訪問的數(shù)據(jù)都只能靠父組件傳過來,如果一個(gè)在很深的子組件想要最外層組件的數(shù)據(jù)時(shí),就不得不把數(shù)據(jù)從頭一路傳到尾。
為了應(yīng)對(duì)這種數(shù)據(jù)很難共享的問題,程序員就想:我把數(shù)據(jù)都存到一個(gè)公共的地方不就行了嘛?要的時(shí)候隨便拿。
那公共地方是哪里呢?存全局變量?不行啊,會(huì)被別人覆蓋啊,而且數(shù)據(jù)改了之后視圖不能隨之改變呀。所以,工程師又開發(fā)一些全局?jǐn)?shù)據(jù)管理庫(kù):
mobx, vuex, redux。同構(gòu)渲染
用多了單頁(yè)框架之后,程序員們又發(fā)現(xiàn)問題了,單頁(yè)最后生成的 HTML 是這樣的:
<body> <div id="root"></div> <script src="bundle.js"></script></body>
要知道搜索引擎每天都會(huì)用
網(wǎng)絡(luò)爬蟲抓取成千上萬個(gè)網(wǎng)頁(yè),分析 HTML 里的內(nèi)容,以此來提高搜索準(zhǔn)確性,這種做法做叫 SEO(Search engine optimization) 搜索引擎優(yōu)化。但是你看上面這樣的結(jié)構(gòu),搜索引擎根本不知道你這個(gè)網(wǎng)頁(yè)是用來干嘛的。另一個(gè)問題是,如果用戶網(wǎng)絡(luò)環(huán)境很差,那只要 JS 還沒被加載出來,網(wǎng)頁(yè)永遠(yuǎn)是一片白色,這非常影響用戶體驗(yàn)。這要怎么解決呢?
大家開始懷念當(dāng)時(shí) JSP、PHP 服務(wù)端渲染 HTML 的時(shí)候了,因?yàn)榉?wù)端渲染 HTML 可以馬上返回 HTML 結(jié)構(gòu),頁(yè)面會(huì)先展示一些內(nèi)容,不至于白屏,而且有了大概的 HTML 結(jié)構(gòu),搜索引擎更容易做 SEO。服務(wù)端的渲染也被叫做
SSR(Server Side Rendering)。
前端工程師想到了:對(duì)于一些靜態(tài)內(nèi)容,比如商品種類、導(dǎo)航欄內(nèi)容,其實(shí)可以在生成 HTML 的時(shí)候就加上,不需要再通過 API 獲取了。這樣的技術(shù)就叫做 SSG(Static Site Generation)。那動(dòng)態(tài)的內(nèi)容,比如朋友圈列表怎么做呢?初始展示的數(shù)據(jù)可以先通過服務(wù)端先渲染,等用戶與頁(yè)面發(fā)生交互,比如點(diǎn)擊按鈕后再發(fā)請(qǐng)求獲取數(shù)據(jù)。這就是
同構(gòu)渲染。
與傳統(tǒng)的服務(wù)端渲染不同,同構(gòu)渲染的服務(wù)端也使用 JavaScript 來編寫,這樣一來前后端都使用上了 JavaScript 了。
同構(gòu)渲染簡(jiǎn)單來說就是一份代碼,服務(wù)端先通過服務(wù)端渲染(server-side rendering),生成html以及初始化數(shù)據(jù),客戶端拿到代碼和初始化數(shù)據(jù)后,通過對(duì) html 的 dom 進(jìn)行 patch 和事件綁定對(duì) Dom 進(jìn)行客戶端激活(client-side hydration)。
這個(gè)整體的過程叫同構(gòu)渲染。既可以吸取服務(wù)端的優(yōu)點(diǎn),比如加速首屏渲染,又保留了 SPA 應(yīng)用的特點(diǎn),比如前端控制路由跳轉(zhuǎn),使得跳轉(zhuǎn)時(shí)不需要再渲染新 HTML。
Single-SPA
當(dāng)越來越多項(xiàng)目用上了 SPA 框架后,當(dāng)公司要把多個(gè)項(xiàng)目合并成一個(gè)項(xiàng)目的時(shí)候,這就很麻煩了,不同項(xiàng)目可能用的框架都不一樣,比如用戶詳情用的是 Vue.js,而首頁(yè)用的是 React.js,怎么把這兩者結(jié)合呢?
single-spa 和國(guó)內(nèi)阿里開發(fā)的
乾坤就是解決這種問題的。本質(zhì)上相當(dāng)于造一個(gè)更大的“單頁(yè)的應(yīng)用”,這個(gè)“單頁(yè)應(yīng)用”里又會(huì)有多個(gè)單頁(yè)的應(yīng)用。
這種將多個(gè) SPA 整合成一個(gè)大 Project 的技術(shù)就是
微前端。
自動(dòng)化測(cè)試
隨著前端越來越工程化,自動(dòng)化測(cè)試是比不可少的一件事。當(dāng)造好一些輪子后,就需要接入自動(dòng)化測(cè)試,不然每次修改都要做點(diǎn)點(diǎn)點(diǎn)的人工測(cè)試。
最簡(jiǎn)單的莫過于單元測(cè)試,目前單測(cè)常用的庫(kù)有
ava, jest, moch, sinon, chai* 等。而前端又是一個(gè)非常依賴環(huán)境的工種,經(jīng)常要用到不同的環(huán)境,比如 JSX 環(huán)境、瀏覽器環(huán)境,Vue 環(huán)境。又催生出很多提供 Mock 環(huán)境的庫(kù),比如 enzyme** 就是用來提供 React 環(huán)境的。
同時(shí),為了模擬一些特定的場(chǎng)景,前端還要 Mock 一些東西,比如 localStorage, indexedDB, cookie 等。這些都有不同的庫(kù)和工具來實(shí)現(xiàn),比如 mock-axios, mock-redux, mock-cookie 等。
上面的只是屬于白盒測(cè)試的做法,前端能不能直接模擬人工做點(diǎn)點(diǎn)點(diǎn)的操作呢?可以的,這就叫
端對(duì)端測(cè)試、或者叫
e2e 測(cè)試,或者叫集成測(cè)試?,F(xiàn)在比較火的工具是
cypress 和
nightwatch。
不過對(duì)于業(yè)務(wù)經(jīng)常頻繁改動(dòng)的項(xiàng)目,自動(dòng)化測(cè)試并不是一件好事,改動(dòng)頻繁的業(yè)務(wù)帶來的是變化無常的測(cè)試用例。寫太多的測(cè)試代碼,有時(shí)候變得事倍功半。
手機(jī)H5
隨著智能手機(jī)發(fā)展得越來越快,微信等一些應(yīng)用里都不得不內(nèi)嵌一些前端的 H5 頁(yè)面,比如微信公眾號(hào)文章,其實(shí)就是一個(gè)小型網(wǎng)頁(yè)。
另一個(gè)應(yīng)用場(chǎng)景是,工程師們發(fā)現(xiàn) App 里也可以嵌入 H5 來做簡(jiǎn)單的展示和交互,這樣一來移動(dòng)端就可以少開發(fā)一些內(nèi)容了。這種內(nèi)嵌H5頁(yè)面的應(yīng)用開發(fā)也稱為
混合開發(fā),開發(fā)出來的 App 就是
Hybird App.
現(xiàn)在我們手機(jī)上的支付寶、微信、QQ 等都是采用了混合開發(fā)的模式,既能使用原生的代碼保證流暢度,同時(shí)又可以內(nèi)嵌H5提升開發(fā)速度(注意,速度不等于效率)。
低代碼
手機(jī)上的 H5 寫多了之后,前端工程師們又發(fā)現(xiàn)很多 H5 都千篇一律,很多都是模板一套,再改個(gè)顏色就OK了。
因此,聰明的程序員就想到了能不能用拖拽就生成網(wǎng)頁(yè)呢?其實(shí)拖拽生成網(wǎng)頁(yè)并不是什么新鮮事,也不難實(shí)現(xiàn),早在 wordpress 的時(shí)代已經(jīng)出現(xiàn)拖拽生成個(gè)人博客的工具了。只不過現(xiàn)在用到手機(jī)上了。
但是拖拽的問題在于不靈活,有時(shí)候非常死板。有些運(yùn)營(yíng)人員還是懂一點(diǎn)代碼的。所以拖拽工具再度進(jìn)化成了:可以給別人留個(gè)入口做一些簡(jiǎn)單的自定義事情。這種模板+簡(jiǎn)單代碼做開發(fā)的就稱為
“低代碼”開發(fā),通過簡(jiǎn)單的配置就能自動(dòng)生成頁(yè)面。
需求生成代碼
除了拖拽,有沒有更高級(jí)的生成代碼工具呢?有!比如,用文字描述場(chǎng)景來生成前端代碼,這也是阿里正在做的事情,它們正在研究 P2C (PRD to Code)。個(gè)人覺得這是一件好事,對(duì)于簡(jiǎn)單需求來說可以直接生成比什么都快。
有人會(huì)擔(dān)心:這會(huì)不會(huì)取代前端工程師呢?答案是不可能,也不科學(xué)。再厲害的人工智能最終也無法實(shí)現(xiàn)設(shè)計(jì)復(fù)雜、靈活多變、千奇百怪、瘋狂迭代的產(chǎn)品需求。最終取代的是只會(huì)寫簡(jiǎn)單 html、css 的低級(jí)工程師。
最后
不知不覺就寫好了多東西,可見前端東西真的很多很雜。其實(shí)再下寫去還能再細(xì)寫下去,但是文章實(shí)在太長(zhǎng)了,到此結(jié)束了。
這篇文章除了帶大家了解前端常見的“名詞”之外,還希望大家學(xué)前端時(shí)不要上來就我要精通XXX。你看前端的發(fā)展多么坎坷、都是通過解決一個(gè)一個(gè)問題才有今天的前端,學(xué)習(xí)也是同樣的道理,先實(shí)現(xiàn)一個(gè)最 Low 的版本,再慢慢升級(jí)自己。