国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

2017前端技術預覽(未完結,最后更新于1月13日)

cnio / 1603人閱讀

摘要:圖離線情況下發送微信消息,等網絡正常后微信會繼續處理我們的消息。無論是在微信中還是手機短信,在沒有信號時都不影響我們編輯發送短信,等網絡恢復時會自動幫我們把之前編輯好的信息順利遞送出去。

(刪掉了第一小段,因為和內容關系不大。。)

本來這該是個技術分享會的內容,參加完 Google Developer Day(GDD) 后想做個 AI Demo 來分享,奈何技術實力不夠,害怕把大家帶進溝里,想想還是講比較擅長的前端領域的比較靠譜。等哪天經歷過人工智能相關項目后再分享也不遲。(分享會已經開過了,這是PPT)

圖:在 GDD 上海站圍觀 TensorFlow 與藝術分享會

Progressive Web Apps

Progressive Web Apps(PWA)指代那些使用最新的 Web 技術構建的類似原生 App 體驗的 webapp,這也是今年前端最熱詞之一,雖然感覺說來說去就是為了一堆新技術取個名字,就像之前的 HTML5 一樣。不過,這些技術確確實實提高 Web 的用戶體驗。

為此各大瀏覽器廠商都卯足了勁(我是說除了Safari,連 IE 都在努力了啊喂!),這篇文章將從三個方面來講解這些技術:

可靠,即使網絡不穩定也需要提供服務;

更快;

功能更豐富!

(恰好 PWA 也這么認為)

這些都是為了讓 WebApp 能像 App 一樣提供沉浸式的用戶體驗。

技術是為內容服務的,單純的技術沒法讓我們爬到馬斯洛需求理論的更高層,但是技術一直在為實現它而努力。接下來將要介紹的就是2016年各大瀏覽器廠商為前端技術做出的努力。(本文不包括類似 async 函數、Promise、以及 Websocket 之類的一些“老技術”)

圖:只有Safari還在考慮是否實現 Service worker,連 IE 都在努力你 Safari 憑啥不努力。。。

可靠

技術關鍵詞:Service WorkerBackground Sync

相對于 App , Web 最痛的點在于如果網絡不靠譜,一切無從談起。打開任何一個頁面,WebApp 都需要經過下載、解析并初始化代碼、執行路由邏輯跳轉到相應頁面、請求網絡數據、渲染頁面...而性能瓶頸最容易出現在網絡部分。設想如果可以預先將網頁的外殼安裝到設備上,啟動時從本地加載這層殼,并請求網絡獲取渲染需要的數據,甚至更極端一點,數據全存在本地磁盤,啟動時優先使用的本地已經保存同步好的數據,保證即使在 Lie-Fi* 環境下也能提供正常服務。

注:Lie-Fi是比斷網更要命的移動網絡。癥狀是手機告訴你你已經聯網,但是網頁卻打不開,甚至連“Chrome小恐龍”都不讓玩。

圖: 這就是那只“Chrome小恐龍”

在講 Service worker 之前,瀏覽器中已經實現了一個類似的功能,叫 AppCache ,AppCache 的運行原理不復雜,就是在網頁加載完成后,瀏覽器閑下來的時下載一個清單文件,這個文件列明了哪些資源可以離線使用,哪些資源需要請求網絡,如果請求不到網絡該怎么辦等等。類似一個配置清單。

圖:AppCache在首次啟動頁面時緩存數據到磁盤,此后打開的頁面如果有用到已緩存的資源則直接由緩存提供。

不過,HTTP 緩存在上古時期就實現了這個功能,看起來只是換了個馬甲。

的確,理論上 HTTP 緩存完全能實現這個功能,但實際卻不是這樣,由于瀏覽器廠商很多、版本也多,相互之間兼容性或多或少有些差異,如果某個瀏覽器對程序員的失誤容忍程度過低,很容易導致渲染出現問題。類似問題也出現在 HTTP 請求上,如果瀏覽器嚴格按照請求頭的緩存控制規則來控制網絡請求,很容易導致頁面無法更新或者部分更新、新舊代碼混合的問題。所以大部分瀏覽器傾向不完全相信 HTTP 請求頭。這也從另一個方面印證了“單一職責原則“的重要性(傳輸數據的就好好傳輸數據,別搶人家緩存的飯碗,你也搶不來。。)。

嗯,看起來 AppCache 比 HTTP 緩存棒多了,功能強大而且單一職責,只要一份清單文件就能把資源都緩存起來離線訪問。

但AppCache犯了比HTTP嚴重的多的錯誤!

我們知道,AppCache的確是單一職責,意味著瀏覽器必須信任他,如果不相信那它存在的意義是什么?問題在于,假設程序員犯了一個小錯,一個匹配規則不小心匹配到了這個清單文件,你的代碼將永遠都更新不了!!

代碼不小心犯個錯簡直太正常不過了,就好像程序員需要吃飯睡覺上廁所一樣,程序員也需要會寫bug。。

延伸閱讀:AppCache Issue is a Douchebag

好的,冷靜一下。。其實有個不完美的解決方案,通過腳本自動生成緩存規則,具體可以參考 offline-plugin AppCache 部分的做法,但這樣 AppCache 的其他“好處”就完全體現無法體現出來!

這時候 Service worker 該登場了!簡單來說,Service worker 是一段運行在頁面之外的一段腳本,這段腳本在啟動時會注冊一些事件到瀏覽器中,當事件觸發時可以通過預先定義好的 Javascript handler 控制如何響應這個事件。

但為什么說 Service worker 比 AppCache 好呢?

首先 Service worker 應該說徹底解決了 AppCache 無法更新的問題,在使用 Service worker 時,只要網絡暢通,瀏覽器都會嘗試在啟動后檢查 Service worker 是否有更新,而且 Service worker 并不能截獲請求更新 Service worker 的事件,換句話說就是無法緩存自身,也就是永遠都有機會更新自己。

其次,Service Worker 通過事件機制配合 js 腳本來控制瀏覽器,并且脫離于頁面生存,這讓web終于有了“常駐”系統的機會!

這是技術上的一小步,但是卻給 web 的能力提供了無限的想象空間!

為了更好的理解什么是 Service Worker,我們可以把它想象成是生存于瀏覽器頁面中、頁面之外的動態代理,當類似網絡請求之類的事件觸發時,由這個代理決定如何處置這個事件。下面這個例子就是演示如何截獲并處理網絡請求的。


圖:瀏覽器向服務器發起請求前先被 Service worker 截獲,處理完成后再向遠端服務器發起請求

這里有個小視頻,演示了如何通過 Service worker “憑空捏造” 離線數據?。代碼在https://github.com/MofeLee/sw...

既然服務器沒有的數據都能造出來,離線訪問數據豈不是輕而易舉?并且這個例子實際上只有幾行關鍵代碼????

一、 注冊 service worker

navigator.serviceWorker.register("/sw.js")

二、 注冊響應規則

self.addEventListener("fetch", function(event) {
  if (/offline-data$/.test(event.request.url)) {
    event.respondWith(
      new Response("這是一條來自service worker的響應信息")
    );
  }
});

三、沒有第三步。。。

實際上現在已經有很多網頁可以離線訪問了,比如說大名鼎鼎的lodash,如果想知道你平常訪問的哪些網站是離線可訪問的,可以在瀏覽器地址欄輸入 chrome://serviceworker-internals/ 查看~

圖:可以看到 https://lodash.com/ 是注冊了service worker 到chrome中的,試著打開網址,稍微等下再斷網打開 https://lodash.com/ ~ Boom!

到目前為止,我們知道使用 Service Worker 可以解決在沒有網絡的情況加載應用的場景,現在,我們設想另一種場景:在線聊天。

圖:離線情況下發送微信消息,等網絡正常后微信會繼續處理我們的消息。

無論是在微信中還是手機短信,在沒有信號時都不影響我們編輯發送短信,等網絡恢復時 App 會自動幫我們把之前編輯好的信息順利遞送出去。而移動設備中的 webapp 體驗卻糟糕透了,我們必須開著網頁直到網絡恢復,以便發出我們的消息,假設這時候我們切換到其他App中,不但消息發不出去,很有可能連瀏覽器占用的資源都會被操作系統回收!!

問題究竟出在哪?

仔細思考后會發現問題出在網絡請求生命周期和頁面的生命周期耦合了,我們必須要找到一種方法能讓瀏覽器在關掉頁面后也能繼續為我們繼續工作!

但是,Webapp 不像普通的 App, 有權限在退出應用之后繼續在后臺運行,如何才能既安全又高效的在后臺運行程序成了一個比較關鍵的問題,如果放出權限讓 js 持續在后臺運行勢必會影響整個操作系統的效率(沒有人能寫出沒有bug的程序,只是訪問了一個網頁,卻強奸了我的系統。。當然不能忍。。)。所以 Service worker 把后臺應用的權限局限在"事件"級別,這里的事件就是前文提到的 Service worker 在瀏覽器啟動時注冊的事件。后臺腳本是否執行完全取決于瀏覽器是否喚醒它,這也意味著如果這段腳本很煩人,我們可以通過設置關掉這段腳本執行的入口,并且,統一管理所有事件的觸發也有利于提高執行效率,畢竟讓專業的“人”做專業的事更靠譜~

同樣的,Background Sync 也是Service worker 事件之一,它讓我們有機會在退出瀏覽器后也能繼續執行一些功能。

是不是急不可耐的想看一段演示了呢?
帶梯子可以訪問這個鏈接 圖片打不開點這

圖:斷網后發送的消息,聯網后自動發送到服務器

圖片打不開點這里

圖:演示流程

斷網

注冊Background sync

聯網觸發sync事件

截獲sync事件,彈出彈窗

實際上,除了這些,Service worker 還可以完成很多有趣的東西,比如制作一個網頁,網頁的header和footer由緩存提供,中間的content從網絡上獲取。如果對Service worker的其他功能感興趣,可以看看這個視頻 Instant-loading Offline-first (Progressive Web App Summit 2016)(需自帶梯子)

更快

技術關鍵詞:WebAssemblypassive event listenersrequestIdleCallback

實際上,web的痛點不止在網絡層面上,相對于 native,js的執行效率也是硬傷之一,雖然js在操作 DOM 上得心應手,但在處理大量數據或者圖形計算上,依舊比較吃力,以至于web平臺上很難有比較華麗動作游戲。直到WebAssembly的出現,讓 web 平臺實現炫酷的動畫效果成為可能。WebAssembly可以讓我們在瀏覽器中執行C或者C++已經編譯出來的字節碼。但有一點需要注意的是,WebAssembly的出現并不是為了替代 js,更多的是用來編寫高性能的模塊,替換js中容易出現性能瓶頸的地方。

圖: 試玩WebAssembly 試玩鏈接

鑒于 WebAssembly 目前還處于試驗階段,這里不細講相關的代碼如何實現了。有興趣可以點擊后面的鏈接了解更多內容 How Webassembly Will Change the Way You Write Javascript | Seth Samuel(需自帶梯子) demo源代碼

除了 js 的執行效率外,流暢的屏幕滾動體驗對web來說非常重要,這點在基于觸摸的移動設備體現的尤為明顯,但事實上,web瀏覽器中很容易在屏幕滾動上出現問題,如果細心的話,會發現即使在設置一個空函數為event handler也可能會造成滾動不流暢。

問題出現在滾動時我們可以調用preventDefault來取消滾動,即使完全沒有調用preventDefault,瀏覽器頁需要在每次滾動前先等待handler調用結束,以確定我們的確沒有調用preventDefault來阻止滾動。

但實際情況卻是大多數handler都只是需要獲取滾動的位置信息,監聽與否并不會影響滾動這個動作的發生,我們完全讓屏幕一邊滾著一邊調用回調函數。所以,只要明確告訴瀏覽器這個監聽事件是不會影響瀏覽器滾動的,對滾動事件的執行效率有非常大的提升。

為了解釋清楚這其中的區別,我再舉個例子,游戲中的高樓,即使再高你也會毫不猶豫的往下跳,現實中的蹦極,雖然前人無數次的驗證過安全也會猶豫擔心。

明確知道安全:無所畏懼

潛在可能危險:畏首畏尾

這就是“明確知道”和“潛在可能”的差別,也是passive event能提升瀏覽器效率的原因。

當然,Passive Event Listeners的接口非常簡單,只需要將第三個參數設置為{passive: true}即可。

var elem = document.getElementById("elem");
elem.addEventListener("touchmove", function listener() {
  /* do something */
}, { passive: true });

圖:對比執行效率的差別,右邊的listener設置了passive屬性

了解更多相關passive event listeners的信息

上面都是一些主動提高web執行效率的方法,下面要講的是利用好瀏覽器的空閑時間。

在web開發中,更快的顯示出有內容的首屏非常重要,尤其對于webapp來說。相對于傳統web頁面,webapp在初始化時需要占用大量的時間運行腳本,并且大多數 webapp 在第一次打開時執行的腳本遠遠多于后續的頁面,如何分配好腳本的執行時間也是非常重要的課題。

圖:react webapp 在啟動前500ms需要進行非常密集的計算。

setTimeout(()=>{
  const head = document.getElementsByTagName("head")[0];
  const gajs = document.createElement("script");
  gajs.async = 1;
  gajs.src = "https://www.google-analytics.com/analytics.js";
  head.insertBefore(gajs, head.lastChild);
}, 2000);

這是一段等瀏覽器空閑下來再去加載google analytics的腳本。

相對于動畫以及加載首屏頁面,加載第三方統計代碼的優先級低得多,所以設置2000ms對于大多數場景夠用了,但事實上我們完全無法保證timer觸發時瀏覽器處于空閑狀態。

如果對于 JavaScript 足夠了解的話,應該知道瀏覽器中的 Timer 是在瀏覽器的調用棧清空時才會從回調隊列中取setTimeout推入的回調函數。但調用棧清空是瀏覽器空閑的假象,很有可能下一刻就要執行類似requestAnimationFrame注冊的回調函數,但是我們卻無法查詢到已經注冊的回調函數會在何時觸發。

圖:年初做的視頻教程截圖,下方為回調隊列,事件輪詢在調用棧清空時會從回調隊列取函數出來運行

實際上,真正空閑的時候是在調用棧清空并且Web Api中注冊的沒有需要立刻推入回調隊列的回調函數時。結合下面的圖片可能更容易理解上面這句話

圖:圖中的idel period才是瀏覽器真正空閑的時候。

requestIdleCallback 提供的接口也非常簡單

var handle = window.requestIdleCallback(callback[, options])

如果想了解更多關于requestIdleCallback的內容,可以查看Using requestIdleCallback和Cooperative Scheduling of Background Tasks

功能更豐富

講完了前面相對來說比較復雜的api,終于可以講些輕松的內容了,如果是比較簡單的內容我就一筆帶過啦~(點擊右側導航欄快速跳轉到相應內容

Fullscreen Api

全屏Api,可以將類似視頻圖片或者Canvas之類的元素占滿全屏demo

code

var i = document.getElementById("myimage");
    
// click event handler
i.onclick = function() {
    // in full-screen?
    if (
        document.fullscreenElement ||
        document.webkitFullscreenElement ||
        document.mozFullScreenElement ||
        document.msFullscreenElement
    ) {
        // exit full-screen
        if (document.exitFullscreen) {
            document.exitFullscreen();
        } else if (document.webkitExitFullscreen) {
            document.webkitExitFullscreen();
        } else if (document.mozCancelFullScreen) {
            document.mozCancelFullScreen();
        } else if (document.msExitFullscreen) {
            document.msExitFullscreen();
        }
    } else {
        // go full-screen
        if (i.requestFullscreen) {
            this.requestFullscreen();
        } else if (i.webkitRequestFullscreen) {
            i.webkitRequestFullscreen();
        } else if (i.mozRequestFullScreen) {
            i.mozRequestFullScreen();
        } else if (i.msRequestFullscreen) {
            i.msRequestFullscreen();
        }
    
    }
}
Media Recorder

Media Recorder API 讓我們的網頁實現錄制流媒體的能力。

給個相對簡單的demo以及源代碼地址:source code demo

延伸閱讀:Record Audio and Video with MediaRecorder

(寫到這發現可以直接嵌入視頻。吐血中。讓我靜靜。。。。???)

Media Source Extensions

另一個比較有用的接口就是 Media source extensions,它讓我們可以在 web 上有機會播放任意格式的視頻格式,著名的 flv.js 就是靠這個接口實現的。另外,由于視頻的內容可以完全用腳本控制,我們可以使用這個接口完成類似播放加密的視頻流、限制視頻流的加載速度、根據緩沖的快慢自動切換視頻流的源、web頁面視頻聊天等等等等~

說點題外話,直播現在在國內這么火爆,但是直播流的格式兼容性卻還有些小問題,要想一個格式支持全平臺就會涉及到相關 media source extensions 的接口。flv支持桌面平臺,移動設備支持m3u8,一個方案是桌面用flv.js直播,但在實際使用中發現iOS不支持media source extensions,無法使用flv.js直播;另一個方案是在桌面環境使用 media source extensions 將 m3u8 轉換成瀏覽器支持的直播流格式,實際使用中發現后面這個方案還是更靠譜,而且輪子都已經造好了,有興趣可以看看 videojs-contrib-hls

圖:使用 media source extensions 分片加載音頻內容。source code demo

Offscreen Canvas

可以在 web worker 上渲染canvas的接口,沒有 demo 因為還沒有支持的瀏覽器。。(就算有那應該怎么演示??)

example:


var one = document.getElementById("one").getContext("bitmaprenderer"); 
var two = document.getElementById("two").getContext("bitmaprenderer");

var offscreen = new OffscreenCanvas(256, 256);
var gl = offscreen.getContext("webgl");

// ... some drawing for the first canvas using the gl context ...

// Commit rendering to the first canvas
var bitmapOne = offscreen.transferToImageBitmap();
one.transferImageBitmap(bitmapOne);

// ... some more drawing for the second canvas using the gl context ...

// Commit rendering to the second canvas 
var bitmapTwo = offscreen.transferToImageBitmap();
two.transferImageBitmap(bitmapTwo);

延伸閱讀:OffscreenCanvas

Pointer Events pointer lock

demo

web bluetooth api

..

webrtc

..
demo

canvas media capture

demo

延伸閱讀

https://developer.mozilla.org...

https://platform-status.mozil...

https://developers.google.com...

原創博文,轉載寫明出處就好(是的,出處就是這個頁面)。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/86620.html

相關文章

  • web前端教程《每一題》(1-99)完結

    摘要:輸出在中,值表示一個空對象指針,而這正是使用操作符檢測值時會返回的原因。屬性規定必需在提交之前填寫輸入字段。通過字面量方式創建的數組對象是屬于類的一個實例,所以返回,故彈出。第期年月日代碼運行的結果輸出前端教程。 第1期(2016年4月6日): (1)js中關閉當前窗口的方法是:window.close(); 第2期(2016年4月7日): (1)js中使字符串中的字符變為小寫的方法是...

    golden_hamster 評論0 收藏0
  • web前端教程《每一題》(1-99)完結

    摘要:輸出在中,值表示一個空對象指針,而這正是使用操作符檢測值時會返回的原因。屬性規定必需在提交之前填寫輸入字段。通過字面量方式創建的數組對象是屬于類的一個實例,所以返回,故彈出。第期年月日代碼運行的結果輸出前端教程。 第1期(2016年4月6日): (1)js中關閉當前窗口的方法是:window.close(); 第2期(2016年4月7日): (1)js中使字符串中的字符變為小寫的方法是...

    forsigner 評論0 收藏0
  • web前端教程《每一題》(1-99)完結

    摘要:輸出在中,值表示一個空對象指針,而這正是使用操作符檢測值時會返回的原因。屬性規定必需在提交之前填寫輸入字段。通過字面量方式創建的數組對象是屬于類的一個實例,所以返回,故彈出。第期年月日代碼運行的結果輸出前端教程。 第1期(2016年4月6日): (1)js中關閉當前窗口的方法是:window.close(); 第2期(2016年4月7日): (1)js中使字符串中的字符變為小寫的方法是...

    fox_soyoung 評論0 收藏0

發表評論

0條評論

cnio

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<