前端工程的過去、現在與未來
Zet @ SITCON 2017
2017.03.18
About me
- 周昱安(Zet)
- 國立中央大學資工所 – Web 智慧與資料探勘實驗室
- EXMA-Square 實習工程師
- 熱衷於前端技術開發與學習
- 願望是養一隻貓,當一個職業貓奴
前端的工程化
-
早期的年代,前端不工程
-
頁面互動複雜度低
-
美術人員如果會一點基礎的 HTML、CSS 的話,與程式設計師配合就幾乎已經足以開發前端
-
架構單純,沒有可維護性或可重用性等問題
-
-
近年的前端工程化需求
-
Web Application 的普及,伴隨而來使用者介面的複雜性提高,需要有組織的架構與工作流程
-
舊有的前端技術與標準難以應付日漸增強的工程化需要
-
Timeline
2007 ~ 2008:百廢待舉
- Firefox 剛從 IE 大一統的天下瓜分掉大半領土,逼的微軟開始繼續關注瀏覽器開發與 Web 領域
- Google Chrome 帶著 V8 Engine 橫空出世,打響新ㄧ波的瀏覽器大戰
- Web 標準開始繼續在各家瀏覽器廠商的角力與爭執中推動
- jQuery 開始普及,漸漸成為最熱門的 JavaScript 函式庫
- HTML5 第一份正式草案發佈
2009 ~ 2010:尋求方向
- ECMAScript 5 發佈
- 微軟發佈
世紀遺毒IE 8 - Node.js 問世,原本只能寄宿於前端瀏覽器的 JavaScript 開始能作為一個 Server-Side 語言使用
- HTML 5 成為大多數人認可的 Web 未來主流技術,眾多特性開始被主流瀏覽器實作支援
- 行動裝置訪問 Web 流量開始顯著成長
2011 ~ 2012:行動裝置的崛起
- HTML 5 技術獲得重大發展以及廣泛地被應用,稱霸十餘載的 Flash 開始漸漸凋零
- Web 標準開始穩定的由各家瀏覽器廠商角力與協商來慢慢的持續推進,最後經過共識而產生的標準,各家瀏覽器也絕大部分會遵守標準來實作
- 行動裝置上的 Web 體驗開始被重視,RWD 概念廣泛被採用,相關的前端套件如雨後春筍般冒出
- 前端的工程化開始被討論與推動
- 社群自發推行各種模組機制
- CoffeeScript 與 TypeScript 等 Transpiler 問世
2013 ~ 2014:工程化逐漸發展
- HTML 5 正式定稿成為推薦標準
- 各種 CSS 預處理器出現並被使用
- PhoneGap 這種 Hybrid Mobile App 模式被廣泛應用
- ECMAScript 6 漸漸受到矚目與發展,但還未被普遍用於開發
- 第一代的 SPA 開發技術成熟,如 Angular / Backbone / Ember
- 新時代的前端應用技術 ReactJS 剛問世,前端應用的組件化開發趨勢開始萌芽
- Node.js 開始大量被採用於企業級應用
2015 ~ 2016:新時代的來臨
- ES6 定稿,隨著 Babel Transpiler 的普及而開始極度大規模的被使用到實際開發中
- npm 與 Webpack 脫穎而出,成為前端建構工具的主流
- React 相關生態系大放異彩,全面的影響並主導前端技術與社群的趨勢走向
- 受到 React 影響並借鑑之,Angular 2、Vue 等新一代前端解決方案到來,與 React 生態系互相競爭與推動進步
- React Native 這種 JS Bridge Native App 解決方案問世,Weex、NativeScript 等接踵而至
- Redux 問世,將 Functional Programing 在前端的趨勢大幅拉升
Past
HTML
HTML
- HTML API 分成兩大部分
- DOM(Document Object Model)
- BOM(Browser Object Model)
- W3C 曾經決定放棄 HTML,轉而推動其他標準
- 瀏覽器廠商們不認同,搞小團體(WHATWG)以民間力量自行推動新一代 HTML 標準
- 因為 WHATWG 的成員就是瀏覽器廠商,所以如果他們不願意實作的話,W3C 強行推動什麼標準也都是枉然
- 最後 W3C 屈服了,接納 WHATWG 所推動的成果,重開 HTML 工作小組,最後與瀏覽器廠商們合力推出現在的 HTML 5 標準
HTML 5
- Try it out on Internet Explorer
- Did it works?
- No?
- It's HTML 5.
HTML 5
-
HTML 5 提供了大量的新特性,其中最重要的一類是提供瀏覽器原生的 RIA(Rich Internet Application)能力,而不再需要 Flash 等外部 Plugin
-
影片播放
-
音訊播放
-
繪圖
-
遊戲
-
視訊
-
jQuery
jQuery
-
早期各家瀏覽器對於標準的制定流程沒有共識,導致各瀏覽器的 DOM 操作或是 AJAX 等 API 都非常不一致
-
jQuery 帶來了在當時相當先進的思維與功能
-
抽象化統一各家瀏覽器的 API 操作差異
-
使用 CSS Selector 來選擇 DOM
-
鏈結串式操作的習慣
-
...etc
-
-
首個取得巨大成功與高程度廣泛應用的 JS 函式庫
-
現今已有點不敷使用於大型且複雜的前端應用程式開發,但仍然擁有承先啟後的重要歷史地位,在簡單的場景中也依然可以使用
Flash
Flash
-
Flash 在那個 HTML 原生不支援 RIA 功能的年代,提供了重要的替代方案,使得 Web 能夠更快速的流行於世界
- 跟 jQuery 一樣,在 HTML 5 發達的這個年代已經逐漸被淘汰,但仍然在歷史中有重要地位,完成了承先啟後的歷史使命
Present
ECMAScript
-
ECMAScript 是 JavaScript 的語言標準規格,後者是前者的實作品
-
Node.js 是 ECMAScript 在伺服器端的實作品語言
-
ECMAScript 6 是 2015 年時正式發表的新一代版本標準,加入了許多重要的新語法與功能,令 JavaScript 往成為企業級語言邁進一大步
-
後面還有 ES7(ES 2016)、ES8(ES 2017)在規劃與實作中,慣例將之統稱為 ES6+,代表新時代的 JavaScript 版本
前端開發所面臨的問題
- 建構工具
- 標準相容性
- 模組化與套件管理
- 非同步處理
- 大型且複雜的前端應用開發
建構工具
(Building Tool)
Webpack
- 能夠對前端程式碼或圖片、字形等檔案進行一些轉譯、打包、壓縮、額外加工處理
- Webpack 取代 Gulp 與 Grunt 成為主流的最大原因
- Gulp 或 Grunt 都是純粹的工作自動化工具,並不是專門為 Web 前端所設計
- Webpack 是只用於 Web 前端的建構處理,為其訂製了一套平台與介面,以達到有系統性的配置與建構
- Webpack 的發展為前端 SPA 提供更進階的環境處理
標準相容性
ECMAScript 6+ 的問題
-
各家瀏覽器的支援還不夠完美與普遍,目前仍有部分功能未被實作完成
-
某些使用者可能永遠也不會更新到支援 ES6+ 的瀏覽器
-
因此我們需要依賴工具將我們的 ES6+ 程式碼轉譯成 ES5 環境能運行的版本,讓我們能放心無虞的使用 ES6+ 語法或功能來開發
Babel
-
Babel 是目前最主流的 JavaScript Transpiler
-
可以單獨運行,也可以配合 Webpack 這種前端打包工具一起使用
-
早期原名 6 to 5,專門處理 ES6 to ES5 的程式碼轉換
-
後來 Babel 決定平台化,除了可以使用官方維護的 ES6+ 與 React JSX 轉換功能之外,也提供 API 讓大家自行開發其他的擴充轉換功能
-
Babel 現今已經成為 ECMAScript 標準的重要推動力量
模組化與套件管理
為什麼需要模組機制?
-
命名衝突
-
全域命名空間下容易造成變數命名衝突,尤其是跟第三方套件衝突時更難解決
-
-
程式碼間的順序與依賴性維護困難
-
開發人員必須自行理解並解決不同 JS 檔案之間,以及與第三方套件的相互依賴關係
-
-
在大型專案中各種資源難以管理,長期積累的問題導致程式碼庫混亂不堪
但是...
-
JavaScript 這個語言本身長時間以來都沒有設計這樣子的模組機制功能
-
因此社群只好自行設計並推廣一些民間標準
-
AMD
-
CommonJS:Node.js 採用的模組規範
-
-
直到 ES6 裡才制訂了原生的模組機制規範與語法
-
融合了各家社群標準的優點,並更加先進易用
-
現況
-
ES6 Module 標準本身已經定案,但瀏覽器對於如何支援與配套仍然未有定論,因此前端至今仍無法原生支援模組系統
-
可以使用 Webpack 來做打包處理,以達到前端環境中模擬模組機制的效果
npm ( Node Module Manager )
-
npm 本身是 Node.js(後端)的套件管理系統
-
因為 Node.js 的逐漸崛起以及 npm 的普及,前端的 JS 或 CSS 套件也被放上了 npm,漸漸也成為了前端的套件管理系統主流,通吃前後端
-
Bower 等純前端套件的管理系統逐漸式微
-
配合 Webpack 的模組機制模擬能力,可以讓一些本來只能在 Node 上使用的套件也能在前端中使用
非同步處理
Callback Hell
-
在 JavaScript 中做非同步流程處理,傳統的方法是使用 Callback Function
-
當連續性的非同步 Callback 一多的時候,就像是...
Promise
- Promise 是一種非同步程式設計的解決方案,比傳統使用 Callback Function 的方式要更合理與強大
- Promise 是一個容器,裡面保存了某個未來才會結束的事件
- 透過原生的 Promise API 來操作這些非同步事件的流程與資料傳遞
const timeout = (delay) => new Promise((resolve, reject) => {
if (typeof delay == 'number') {
setTimeout(() => {
resolve(`${delay}ms passed away.`)
}, delay);
} else {
reject('input is a non-number value.');
}
});
timeout(3000)
.then(value => {
console.log(value);
}).catch(error => {
console.error(error);
});
// "3000ms passed away."
timeout('abc')
.then(value => {
console.log(value);
}).catch(error => {
console.error(error);
});
// "input is a non-number value."
Promise
- 以下是搭配 jQuery Ajax 的範例情境
const getArticleList = () => new Promise((resolve, reject) => {
$.ajax({
url: '/api/article/list',
dataType: 'json',
success: (result) => resolve(result)
});
});
const getArticle = (id) => new Promise((resolve, reject) => {
$.ajax({
url: `/api/article/detail/${id}`,
dataType: 'json',
success: (result) => resolve(result)
});
});
const getAuthor = (id) => new Promise((resolve, reject) => {
$.ajax({
url: `/api/author/${id}`,
dataType: 'json',
success: (result) => resolve(result)
});
});
getArticleList()
.then(articles => getArticle(articles[0].id))
.then(article => getAuthor(article.authorId))
.then(author => console.log(author))
.catch(error => console.error(error));
asnyc / await
- async function 是基於 Promise 的擴充語法
- 能夠讓 Promise 非同步操作更接近同步的語意
- async 關鍵字
- 表示這是一個 asnyc function,該 function 會自動變成一個 會 return promise 的 function
- await 關鍵字
- 表示在此處等待這個 promise 的 resolve 或 reject 結果
- async 關鍵字
const getAuthorByArticle = async() => {
try {
const articles = await getArticleList();
const article = await getArticle(articles[0].id);
const author = await getAuthor(article.authorId);
console.log(author);
} catch (error) {
console.error(error);
}
}
Fetch API
-
Fetch 是目標取代 XHR 的新 AJAX 技術標準,已經被一些主流瀏覽器實作
-
是一個 HTML BOM 的 API,並非來自 ECMAScript 標準
-
Fetch 原生基於 Promise 實現,因此也可以直接搭配 async / await 使用
const getArticleList = async() => {
const response = await fetch('/api/article/list');
return await response.json();
}
const getArticle = async(id) => {
const response = await fetch(`/api/article/detail/${id}`);
return await response.json();
}
const getAuthor = async(id) => {
const response = await fetch(`/api/author/${id}`);
return await response.json();
}
try {
const articles = await getArticleList();
const article = await getArticle(articles[0].id);
const author = await getAuthor(article.authorId);
console.log(author);
} catch (error) {
console.error(error);
}
前端應用開發
主要趨勢
-
組件化開發
-
Virtual DOM
-
Ony-way Dataflow vs Two-way Binding
組件化
-
將 HTML 程式碼分拆為一個一個的組件模板
-
方便進行抽象化以及重用
-
React、Vue、Angular 2 等技術都有實現自己的組件機制,而 HTML 標準本身也在發展原生的組件系統
class ProductItem extends React.Component {
handleButtonClick = () => {
alert(this.props.price);
}
render() {
return (
<div className="item">
<div className="title">{this.props.title}</div>
<div className="price">{this.props.price}</div>
<button onClick={this.handleButtonClick}>購買</button>
</div>
);
}
}
Virtual DOM
-
在框架與瀏覽器 DOM 之間實作一套模擬的 DOM 夾層
-
當畫面需要改變時
-
根據最新的資料重繪出新的 VDOM Tree
-
與改變前的舊 VDOM Tree 進行全面式的比較與計算
-
其中新舊差異的地方,才真的會在實際的 DOM 上發生操作改變,藉此來減少不必要的實體 DOM 操作以節省效能
-
One-way Dataflow
& Two-way Binding
-
One-way Dataflow
-
資料是 UI 發生改變的唯一變因,只有資料改變時才會導致 UI 改變,並且 UI 不能直接改變資料
-
-
Two-way Binding
-
UI 擁有直接改變特定資料的能力,自動與指定的資料做雙向綁定
-
主流方案
React | Vue | Angular 2 | |
---|---|---|---|
類型 | 專注 UI | 專注 UI | 全能型框架 |
主導者 | 個人項目 | ||
組件化 | 是 | 是 | 是 |
Virtual DOM | 有 | v2 開始有 | 無 |
Dataflow | 單向 | 單向 / 雙向 | 單向 / 雙向 |
View 結構定義 | JSX | template / JSX | template |
學習門檻 | 中 | 低 | 高 |
Future
HTTP / 2
-
新版的 HTTP 傳輸協定
-
能夠支援更好的平行加載資源
-
現今將多個資源打包成少數檔案的優化處理,未來可能不再是最佳實踐
-
-
主流的瀏覽器都已經支援
PWA(Progressive Web App)
-
Google 推廣的一種 Web Mobile App 技術,目的是希望提高手機版網頁應用的體驗
-
安裝性:可以瞬間添加到主畫面並且全螢幕運行,不用包成真的的 App 到 Store 裡下載安裝
-
離線使用:安裝時會將應用的基本架構暫存在本地端,以達到在斷網或網路訊號弱的時候依然能秒開的體驗
-
推播:能夠主動發起推播訊息
-
JS Bridge Native App
-
使用 JavaScript 來開發原生的行動裝置 App(Android、iOS)
-
原理是框架包含了 JS 與原生程式的橋樑,以及 JS 程式碼翻譯引擎,以達到寫 JS 程式碼產原生組件的效果,並且兩大平台的應用能共用大部分程式碼
-
與 Web 三大前端應用方案有密切關係
-
React:React Native
-
Vue:Weex
-
Angular 2:NativeScript
-
WebAssembly
-
各大瀏覽器廠商合作發展的一項技術,目的是能夠將其他程式語言經過編譯之後在瀏覽器環境中執行
-
目前主要的用途導向是遊戲(C++)
-
還在初期階段,到正式廣泛應用可能還要 5 ~ 8 年的時間
-
發展順利並成熟的話,我們可能可以看到用多個語言皆可撰寫前端程式的一天
展望 2017
2017 前端冥燈大預測
-
模組系統可能會在瀏覽器上原生實現
-
Babel 繼續擔任 ECMAScript 的重要推動力量
-
React 依然稱霸,核心重寫之後的新版會再一次掀起前端方案的效能與思想之爭
-
Vue 會迎來高峰,力壓 Angular 2 的地位,緊逼 React
-
Redux 依然在 State 管理的主流競爭者當中
-
HTTP / 2 普及
-
HTML 原生的 Web Component 依然受到冷落,但伺機而動
-
更多前端技術與開發廠商放棄支援 IE 8,IE 9 準備上刑場
大前端時代
大前端時代
-
前端工程由於使用者體驗的需求提高、UI 複雜度大幅增加而重要性提高
-
各種行動裝置、平台更讓前端的需求廣泛
-
HTML 5 的發展、Hybrid App、PWA、JS Bridge Native App 讓 Web 前端工程師能有效的跨足於行動裝置平台的開發
-
前端技術發展熱絡,工程化技術不斷在推翻與進步
-
對前端工程師來說,學習的能力非常重要
學習管道
-
實體書籍
-
網路資源:文章、影片課程、線上社團、線上讀書會
-
社群活動:Conf、小型分享會、工作坊
-
實習、接案
-
認識並跟其他人交流、溝通、合作
Thanks!
SITCON 2017 - 前端工程的過去、現在與未來
By tz5514
SITCON 2017 - 前端工程的過去、現在與未來
- 2,874