Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 国产刚刚发育被强j在线播放,一二三四社区在线高清观看在线,国产精品91在线

          整合營銷服務(wù)商

          電腦端+手機端+微信端=數(shù)據(jù)同步管理

          免費咨詢熱線:

          PHP的緩沖區(qū)你了解過嗎

          PHP的緩沖區(qū)你了解過嗎

          篇文章是翻譯自Julien Pauli的博客文章PHP output buffer in deep,Julien是PHP源碼的資深開發(fā)和維護人員。這篇文章從多個方面講解了PHP中的輸出緩沖區(qū)以及怎么使用它。輸出緩沖區(qū)可能一直都是PHP開發(fā)人員的一個盲點,很多人可能只是知道這個東西,而且也知道大概怎么使用,但對于它為什么是這個樣子,以及還可能是其他什么樣子,可能并不了解,這篇文章可以解決你的所有困惑!

          引言

          大家都知道PHP中有一個名為“輸出緩沖區(qū)”層(layer)的東西。這篇文章就是來講解它到底是個什么東西的?PHP內(nèi)部是怎么實現(xiàn)它的?以及在PHP程序中怎么使用它?這個層并不復雜,但經(jīng)常會被誤解,很多PHP開發(fā)者并沒有完成掌握它。今天我們就一起來徹底把它搞清楚吧。

          我們要討論的東西是基于PHP 5.4(及以上版本),PHP中的OB層從5.4版開始就發(fā)生了很多變化,確切說是完全重寫了,有些地方可能都不兼容PHP 5.3了。

          什么是輸出緩沖區(qū)?

          PHP的輸出流包含很多字節(jié),通常都是程序員要PHP輸出的文本,這些文本大多是echo語句或者printf()函數(shù)輸出的。對于PHP中的輸出緩沖區(qū),你要知道三點內(nèi)容。

          第一點是任何會輸出點什么東西的函數(shù)都會用到輸出緩沖區(qū),當然這說的是用PHP寫的程序。如果你是編寫PHP擴展,你使用的函數(shù)(C函數(shù))可能會直接將輸出寫到SAPI緩沖區(qū)層,而不需要經(jīng)過OB層。你可以在源文件main/php_output.h中了解到這些C函數(shù)的API文檔,這個文件給我們提供了很多其他的信息,例如默認的緩沖區(qū)大小。

          第二點你需要知道的是輸出緩沖區(qū)層不是唯一用于緩沖輸出的層,它實際上只是很多層中的一個。最后一點你要記住輸出緩沖區(qū)層的行為跟你使用的SAPI(web或cli)相關(guān),不同的SAPI可能有不同的行為。我們先通過一個圖片來看看這些層的關(guān)系:

          上面這張圖片展示了PHP中的三種緩沖區(qū)層的邏輯關(guān)系。上面的兩層就是我們通常所認識到的“輸出緩沖區(qū)”,最后一個是SAPI中的輸出緩沖區(qū)。這些都是PHP中的層,當輸出的字節(jié)離開PHP進入計算機體系結(jié)構(gòu)中的更底層時,緩沖區(qū)又會不斷出現(xiàn)(終端緩沖區(qū)(terminal buffer),fast-cgi緩沖區(qū),web服務(wù)器緩沖區(qū),OS緩沖區(qū),TCP/IP棧緩沖區(qū)。。。)。請記住一個通用原則,除了這篇文章中討論的PHP中的情況外,一個軟件的很多部分都會先保留信息,然后再把它們傳遞到下一部分,直到最終把這些信息傳遞給用戶。

          CLI的SAPI有點特殊,這里重點講一下。CLI會將INI配置中的output_buffer選項強制設(shè)置為0,這表示禁用默認PHP輸出緩沖區(qū)。所以在CLI中,默認情況下你要輸出的東西會直接傳遞到SAPI層,除非你手動調(diào)用ob_()類函數(shù)。并且在CLI中,implicit_flush的值也會被設(shè)置為1。我們經(jīng)常會搞不清implicit_flush的作用,源代碼已說明一切:當implicit_flush被設(shè)置為打開(值為1),一旦有任何輸出寫入到SAPI緩沖區(qū)層,它都會立即刷新(flush,意思是把這些數(shù)據(jù)寫入到更低層,并且緩沖區(qū)會被清空)。換句話說就是:任何時候當你寫入任何數(shù)據(jù)到CLI SAPI中時,CLI SAPI都會立即將這些數(shù)據(jù)扔到它的下一層去,一般會是標準輸出管道,write()和fflush()這兩個函數(shù)就是負責干這個事情的。簡單,對吧!

          默認PHP輸出緩沖區(qū)

          如果你使用不同于CLI的SAPI,像PHP-FPM,你會用到下面三個跟緩沖區(qū)相關(guān)的INI配置選項:

          output_buffering
          implicit_flush
          output_handler
          

          在搞清楚這幾個選項的含義之前,有一點需要先說明下,不能在運行時使用ini_set()改這幾個選項的值。這些選項的值會在PHP程序啟動的時候,還沒有運行任何腳本之前解析,所以也許在運行時可以使用ini_set()改變它們的值,但改變后的值并不會生效,一切都已經(jīng)太遲了,因為輸出緩沖區(qū)層已經(jīng)啟動并已激活。你只能通過編輯php.ini文件或者是在執(zhí)行PHP程序的時候使用-d選項才能改變它們的值。

          默認情況下,PHP發(fā)行版會在php.ini中把output_buffering設(shè)置為4096個字節(jié)。如果你不使用任何php.ini文件(或者也不會在啟動PHP的時候使用-d選項),它的默認值將為0,這表示禁用輸出緩沖區(qū)。如果你將它的值設(shè)置為“ON”,那么默認的輸出緩沖區(qū)的大小將是16kb。你可能已經(jīng)猜到了,在web應(yīng)用環(huán)境中對輸出的內(nèi)容使用緩沖區(qū)對性能有好處。默認的4k的設(shè)置是一個合適的值,這意味著你可以先寫入4096個ASCII字符,然后再跟下面的SAPI層通信。并且在web應(yīng)用環(huán)境中,通過socket一個字節(jié)一個字節(jié)的傳輸消息的方式對性能并不好。更好的方式是把所有內(nèi)容一次性傳輸給服務(wù)器,或者至少是一塊一塊地傳輸。層與層之間的數(shù)據(jù)交換的次數(shù)越少,性能越好。你應(yīng)該總是保持輸出緩沖區(qū)處于可用狀態(tài),PHP會負責在請求結(jié)束后把它們中的內(nèi)容傳輸給終端用戶,你不用做任何事情。

          implicit_flush已在前面談?wù)揅LI的時候提到過。對于其他的SAPI,implicit_flush默認被設(shè)置為關(guān)閉(off),這是正確的設(shè)置,因為只要有新數(shù)據(jù)寫入就刷新SAPI的做法很可能并非你所希望的。對于FastCGI協(xié)議,刷新操作(flushing)是每次寫入后都發(fā)送一個FastCGI數(shù)組包(packet),如果發(fā)送數(shù)據(jù)包之前先把FastCGI的緩沖區(qū)寫滿會更好一些。如果你想手動刷新SAPI的緩沖區(qū),使用PHP的flush()函數(shù)。如果你想寫一次就刷新一次,你可以設(shè)置INI配置中的implicit_flush選項,或者調(diào)用一次ob_implicit_flush()函數(shù)。

          output_handler是一個回調(diào)函數(shù),它可以在緩沖區(qū)刷新之前修改緩沖區(qū)中的內(nèi)容。PHP的擴展提供了很多回調(diào)函數(shù)(用戶也可以自己編寫回調(diào)函數(shù),下面會講到)。

          ob_gzhandler : 使用ext/zlib壓縮輸出
          mb_output_handler : 使用ext/mbstring轉(zhuǎn)換字符編碼
          ob_iconv_handler : 使用ext/iconv轉(zhuǎn)換字符編碼
          ob_tidyhandler : 使用ext/tidy整理輸出的HTML文本
          ob_[inflate/deflate]_handler : 使用ext/http壓縮輸出
          ob_etaghandler : 使用ext/http自動生成HTTP的Etag
          

          緩沖區(qū)中的內(nèi)容會傳遞給你選擇的回調(diào)函數(shù)(只能用一個)來執(zhí)行內(nèi)容轉(zhuǎn)換的工作,所以如果你想獲取PHP傳輸給web服務(wù)器以及用戶的內(nèi)容,你可以使用輸出緩沖區(qū)回調(diào)。當前有一點也需要提一下,這里說的“輸出”指的是消息頭(headers)和消息體(body)。HTTP的消息頭也是OB層的一部分。

          消息頭和消息體

          當你使用一個輸出緩沖區(qū)(無論是用戶的,還是PHP的)的時候,你可能想以你希望的方式發(fā)送HTTP消息頭和內(nèi)容。你知道任何協(xié)議都必須在發(fā)送消息體之前發(fā)送消息頭(這也是為什么叫做“頭”),但是如果你使用了輸出緩沖區(qū)層,那么PHP會接管這些,而不需要你操心。實際上,任何跟消息頭的輸出有關(guān)的PHP函數(shù)(header(),setcookie(),session_start())都使用了內(nèi)部的sapi_header_op()函數(shù),這個函數(shù)只會把內(nèi)容寫入到消息頭緩沖區(qū)中。然后當你輸出內(nèi)容是,例如使用printf(),這些內(nèi)容會寫入到輸出緩沖區(qū)(假設(shè)只有一個)。當這個輸出緩沖區(qū)中的內(nèi)容需要被發(fā)送時,PHP會先發(fā)送消息頭,然后發(fā)送消息體。PHP為你搞定了所有的事情。如果你覺得不爽,想自己動手,那你就只有把輸出緩沖區(qū)禁用掉,除此之外別無他法。

          用戶輸出緩沖區(qū)(user output buffers)

          對于用戶輸出緩沖區(qū),我們先通過一個示例來看看它是怎么工作的,以及你可以用它來做什么。再強調(diào)一下,如果你想使用默認PHP輸出緩沖區(qū)層的話,你不能使用CLI,因為它已禁用了這個層。下面的這個示例用的就是默認PHP輸出緩沖區(qū),使用了PHP的內(nèi)部web服務(wù)器SAPI:

          /* launched via php -doutput_buffering=32 -dimplicit_flush=1 -S127.0.0.1:8080 -t/var/www */
          echo str_repeat('a', 31);
          sleep(3);
          echo 'b';
          sleep(3);
          echo 'c';
          

          在這個示例中,啟動PHP的時候?qū)⒛J輸出緩沖區(qū)的大小設(shè)置為32字節(jié),程序運行后會先向其中寫入31個字節(jié),然后進入睡眠狀態(tài)。此時屏幕是空的,什么都不會輸出,跟預(yù)計一樣。2秒之后睡眠結(jié)束,再寫入了一個字節(jié),這個字節(jié)填滿了緩沖區(qū),它會立即刷新自身,把里面的數(shù)據(jù)傳遞給SAPI層的緩沖區(qū),因為我們將implicit_flush設(shè)置為1,所以SAPI層的緩沖區(qū)也會立即刷新到下一層。字符串’aaaaaaaaaa{31個a}b’會出現(xiàn)在屏幕上,然后腳本再次進入睡眠狀態(tài)。2秒之后,再輸出一個字節(jié),此時緩沖區(qū)中有31個空字節(jié),但是PHP腳本已執(zhí)行完畢,所以包含這1個字節(jié)的緩沖區(qū)也會立即刷新,從而會在屏幕上輸出字符串’c’。

          從這個示例我們可以看到默認PHP輸出緩沖區(qū)是如何工作的。我們沒有調(diào)用任何跟緩沖區(qū)相關(guān)的函數(shù),但這并不意味這它不存在,你要認識到它就存在當前程序的運行環(huán)境中(在非CLI模式中才有效)。

          OK,現(xiàn)在開始討論用戶輸出緩沖區(qū),它通過調(diào)用ob_start()創(chuàng)建,我們可以創(chuàng)建很多這種緩沖區(qū)(至到內(nèi)存耗盡為止),這些緩沖區(qū)組成一個堆棧結(jié)構(gòu),每個新建緩沖區(qū)都會堆疊到之前的緩沖區(qū)上,每當它被填滿或者溢出,都會執(zhí)行刷新操作,然后把其中的數(shù)據(jù)傳遞給下一個緩沖區(qū)。

          ob_start(function($ctc) { static $a=0; return $a++ . '- ' . $ctc . "\n";}, 10);
          ob_start(function($ctc) { return ucfirst($ctc); }, 3);
          echo "fo";
          sleep(2);
          echo 'o';
          sleep(2);
          echo "barbazz";
          sleep(2);
          echo "hello";
          /* 0- FooBarbazz\n 1- Hello\n */
          

          在此我代替原作者講解下這個示例。我們假設(shè)第一個ob_start創(chuàng)建的用戶緩沖區(qū)為緩沖區(qū)1,第二個ob_start創(chuàng)建的為緩沖區(qū)2。按照棧的后進先出原則,任何輸出都會先存放到緩沖區(qū)2中。

          緩沖區(qū)2的大小為3個字節(jié),所以第一個echo語句輸出的字符串'fo'(2個字節(jié))會先存放在緩沖區(qū)2中,還差一個字符,當?shù)诙cho語句輸出的'o'后,緩沖區(qū)2滿了,所以它會刷新(flush),在刷新之前會先調(diào)用ob_start()的回調(diào)函數(shù),這個函數(shù)會將緩沖區(qū)內(nèi)的字符串的首字母轉(zhuǎn)換為大寫,所以輸出為'Foo'。然后它會被保存在緩沖區(qū)1中,緩沖區(qū)1的大小為10。

          第三個echo語句會輸出'barbazz',它還是會先放到緩沖區(qū)2中,這個字符串有7個字節(jié),緩沖區(qū)2已經(jīng)溢出了,所以它會立即刷新,調(diào)用回調(diào)函數(shù)得到的結(jié)果為'Barbazz',然后被傳遞到緩沖區(qū)1中。這個時候緩沖區(qū)1中保存了'FooBarbazz',10個字符,緩沖區(qū)1會刷新,同樣的先會調(diào)用ob_start()的回調(diào)函數(shù),緩沖區(qū)1的回調(diào)函數(shù)會在字符串前面添加行號,以及在尾部添加一個回車符,所以輸出的第一行是'o- FooBarbazz'。

          最后一個echo語句輸出了字符串'hello',它大于3個字符,所以會觸發(fā)緩沖區(qū)2刷新,因為此時腳本已執(zhí)行完畢,所以也會立即刷新緩沖區(qū)1,最終得到的第二行輸出為'1- Hello'。

          輸出緩沖區(qū)的內(nèi)部實現(xiàn)

          自5.4版后,整個緩沖區(qū)層都被重寫了(由Michael Wallner完成)。之前的代碼很垃圾,很多事情都做不了,并且有很多bug。這篇文章會給你提供更多相關(guān)信息。所以PHP 5.4才會對這部分進行重新,現(xiàn)在的設(shè)計更好,代碼也更整潔,添加了一些新特性,跟5.3版的不兼容問題也很少。贊一個!

          其中最贊的一個特性是擴展可以聲明它自己的輸出緩沖區(qū)回調(diào)與其他擴展提供的回調(diào)沖突。在此之前,這是不可能的,之前如果要開發(fā)使用輸出緩沖區(qū)的擴展,必須先搞清楚所有其他提供了緩沖區(qū)回調(diào)的擴展可能帶來的影響。

          下面是一個簡單的示例,它展示了怎樣注冊一個回調(diào)函數(shù)來將緩沖區(qū)中的字符轉(zhuǎn)換為大寫,這個示例的代碼可能不是很好,但是足以滿足我們的目的:

          #ifdef HAVE_CONFIG_H
          #include "config.h"
          #endif
          #include "php.h"
          #include "php_ini.h"
          #include "main/php_output.h"
          #include "php_myext.h"
          static int myext_output_handler(void **nothing, php_output_context *output_context)
          {
           char *dup=NULL;
           dup=estrndup(output_context->in.data, output_context->in.used);
           php_strtoupper(dup, output_context->in.used);
           output_context->out.data=dup;
           output_context->out.used=output_context->in.used;
           output_context->out.free=1;
           return SUCCESS;
          }
          PHP_RINIT_FUNCTION(myext)
          {
           php_output_handler *handler;
           handler=php_output_handler_create_internal("myext handler", sizeof("myext handler") -1, myext_output_handler, /* PHP_OUTPUT_HANDLER_DEFAULT_SIZE */ 128, PHP_OUTPUT_HANDLER_STDFLAGS);
           php_output_handler_start(handler);
           return SUCCESS;
          }
          zend_module_entry myext_module_entry={
           STANDARD_MODULE_HEADER,
           "myext",
           NULL, /* Function entries */
           NULL,
           NULL, /* Module shutdown */
           PHP_RINIT(myext), /* Request init */
           NULL, /* Request shutdown */
           NULL, /* Module information */
           "0.1", /* Replace with version number for your extension */
           STANDARD_MODULE_PROPERTIES
          };
          #ifdef COMPILE_DL_MYEXT
          ZEND_GET_MODULE(myext)
          #endif
          

          陷阱

          大部分陷阱都已經(jīng)揭示出來了。有一些是邏輯的問題,有一些是隱藏的。邏輯方面,最明顯的是你不應(yīng)該在輸出緩沖區(qū)回調(diào)函數(shù)內(nèi)調(diào)用任何緩沖區(qū)相關(guān)的函數(shù),也不要在回調(diào)函數(shù)中輸出任何東西。

          相對不太明顯的是有些PHP的內(nèi)部函數(shù)也使用了輸出緩沖區(qū),它們會疊加到其他的緩沖區(qū)上,這些函數(shù)會填滿自己的緩沖區(qū)然后刷新,或者是返回里面的內(nèi)容。print_r()、highlight_file()和highlight_file::handle()都是這類函數(shù)。你不應(yīng)該在輸出緩沖區(qū)的回調(diào)函數(shù)中使用這些函數(shù)。這種行為會導致未定義的錯誤,或者至少得不到你期望的結(jié)果。

          總結(jié)

          輸出層(output layer)就像一個網(wǎng),它會把所有從PHP”遺漏“的輸出圈起來,然后把它們保存到一個大小固定的緩沖區(qū)中。當緩沖區(qū)被填滿了的時,里面的內(nèi)容會刷新(寫入)到下一層(如果有的話),或者是寫入到下面的邏輯層:SAPI緩沖區(qū)。開發(fā)人員可以控制緩沖區(qū)的數(shù)量、大小以及在每個緩沖區(qū)層可以執(zhí)行的操作(清除、刷新和刪除)。這種方式非常靈活,它允許庫和框架設(shè)計者可以完全控制它們自己輸出的內(nèi)容,并把它們放到一個全局的緩沖區(qū)中。對于輸出,我們需要知道任何輸出流的內(nèi)容和任何HTTP消息頭,PHP都會以正確的順序發(fā)送它們。

          輸出緩沖區(qū)也有一個默認緩沖區(qū),可以通過設(shè)置3個INI配置選項來控制它,它們是為了防止出現(xiàn)過大量的細小的寫入操作,從而造成訪問SAPI層過于頻繁,這樣網(wǎng)絡(luò)消耗會很大,不利于性能。PHP的擴展也可以定義回調(diào)函數(shù),然后在每個緩沖區(qū)上執(zhí)行這個回調(diào),這種應(yīng)用已經(jīng)有很多了,例如執(zhí)行數(shù)據(jù)壓縮,HTTP消息頭管理以及搞很多其他的事情。

          的互聯(lián)網(wǎng)產(chǎn)品不僅僅在功能上要高人一籌,在性能層面也需要出類拔萃,否則金玉其外敗絮其中,頁面是美輪美奐了,結(jié)果首屏半天加載不出來,難免讓用戶乘興而來,敗興而歸。

          幸運的是,前端的性能優(yōu)化有諸多有跡可循的理論和方法,其中相對權(quán)威的,無疑是LightHouse。

          LightHouse 是一個開源的自動化工具,它作為 Chrome 瀏覽器的擴展程序運行,提供一套完整的站點評分標準,我們可以依據(jù)此標準對站點進行基準測試,從而達到優(yōu)化的效果。

          怎么打開LightHouse?可以在Chrome瀏覽器開發(fā)人員工具中找到LightHouse。

          要打開“開發(fā)人員工具”,請選擇:
          “頂部菜單→查看→開發(fā)人員→開發(fā)人員工具”
          或者使用快捷鍵:

          Mac系統(tǒng)上的“?+?+I”
          Win系統(tǒng)上的“F12+Ctrl+Shift+I”。

          隨后點擊生成報告按鈕即可:

          LightHouse評分大體上有四大指標,分別為:性能、無障礙、最佳做法以及SEO。

          性能指標(Performance)

          性能指標里又分為六個小指標:

          Largest Contentful Paint 【簡稱LCP: 最大內(nèi)容渲染】
          FCP最大內(nèi)容渲染時間標記了渲染出最大文本或圖片的時間。
          Total Blocking Time 【簡稱TBT: 總阻塞時間】
          TBT測量了FCP(首次內(nèi)容渲染)和TTI(可交互時間)之間的總耗時。TTI可能會被主線程阻塞以至于無法及時響應(yīng)用戶。大于50ms的任務(wù)稱為長任務(wù),當任意長任務(wù)出現(xiàn)時,主線程則稱為被阻塞狀態(tài)。由于瀏覽器不會打斷正在進行中的長任務(wù),所以,如果用戶在執(zhí)行長任務(wù)時和頁面有交互事件時,瀏覽器必須等到該長任務(wù)完成才能響應(yīng)。TBT計算的是在FCP到TTI之間所有長任務(wù)時間內(nèi)總和。
          First Contentful Paint 【簡稱FCP: 首次內(nèi)容渲染】

          FCP測量了從頁面開始加載到頁面任意部分的內(nèi)容渲染到屏幕上。

          Speed Index 【簡稱SI: 速度指數(shù)】
          SI速度指數(shù)表明了網(wǎng)頁內(nèi)容的可見填充速度。lighthouse首先捕獲頁面加載的視屏,然后對比幀與幀之間視覺效果變化(通過計算結(jié)構(gòu)相似指數(shù)SSMI來比較)。
          Time to Interactive 【簡稱TTI: 可交互時間】
          可交互時間是指網(wǎng)頁需要多長時間才能提供完整交互功能。TTI測量了從頁面開始加載到頁面的主要附屬資源加載完畢,并且可以足夠快速回應(yīng)用戶輸入的所用時間。
          Cumulative Layout Shift 【簡稱CLS: 累積布局偏移】
          CLS累積布局偏移旨在測量可見元素在視口內(nèi)的移動情況。CLS值越小越好。

          性能優(yōu)化手段

          有哪些手段可以提高這些性能指標?

          首先需要優(yōu)化的是頁面“資源”,這里的資源指的是頁面中加載的一切元素,包含但不限于:js文件、css文件、圖片、視頻等。

          對于js文件來說,首先要做的是業(yè)務(wù)分拆,不同頁面只加載對應(yīng)需要的文件,并且做到單頁面只加載一個js文件,減少Http請求數(shù),多余的文件要做合并壓縮操作,但其實這里有一個基礎(chǔ)問題,就是如果js文件本身就很龐大,壓縮比例再高,也是杯水車薪,舉個例子,一般情況下Jquery官方的壓縮版就已經(jīng)高達80kb左右了,這樣的體積很難有再次壓縮的優(yōu)化空間,所以還不如直接摒棄Jquery,換成別的功能上可以替換的庫,比如zepto,后者的體積只有26kb,是前者的四分之一。隨后進行壓縮合并操作,首先安裝:

          npm install uglify-js -g

          以本站為例,業(yè)務(wù)上用到的js庫分別為zepto.min.js、my.js、lazyload.min.js、wordcloud2.min.js iconfont.js,將這五個js文件進行合并壓縮:

          uglifyjs zepto.min.js my.js lazyload.min.js wordcloud2.min.js iconfont.js -o ./1-min.js

          如此,最后得到一個體積為59kb的1-min.js文件,當然這是業(yè)務(wù)層面的壓縮,還可以通過修改服務(wù)器進行g(shù)zip壓縮:

          location ~ .*.(jpg|gif|png|bmp|js|css)$ {
                          gzip on;
                          gzip_http_version 1.1;
                          gzip_comp_level 3;
                          gzip_types text/plain application/json application/x-javascript application/css application/xml application/xml+rss text/javascript application/x-httpd-php image/jpeg image/gif image/png image/x-ms-bmp;
                          }

          加載方式上,盡量使用預(yù)加載:

          <link rel="preload" as="script" href="1-min.js" />

          同時,對于一些站外js比如廣告,或者一些js特效,我們可以對其進行延時加載的操作,即首屏加載好之后,再加載這些邏輯:

          <script nonce="EDNnf03nceIOfn39fn3e9h3sdfa">
          (function() {
          var done=false;
          var script=document.createElement('script');
          script.async=true;
          script.type='text/javascript';
          script.src='//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js';
          
          var createScript=setTimeout(
          function(){
          document.getElementsByTagName('HEAD').item(0).appendChild(script);
          WordCloud(canvas, options);
          }, 7000
          );
          
          script.onreadystatechange=script.onload=function(e) {
          if (!done && (!this.readyState || this.readyState=='loaded' || this.readyState=='complete')) {
          (adsbygoogle=window.adsbygoogle || []).push({});
          }
          };
          })();
          </script>

          上面的邏輯就是首屏完成7秒后再加載Google廣告和標簽云特效。

          對于css文件的處理,原理和js文件差不多,宗旨也是分拆,縮小體積,并且壓縮:

          cssMinifier(['./bootstrap.min.css', '../js/kindeditor/plugins/code/prettify_dark.css', './style.css'], './tidy_min.css');

          優(yōu)化后,得到體積為17kb的tidy_min.css文件。

          對于圖片文件,不僅是首圖,所有圖片最好都采用新的圖片格式Webp,用以減少其體積,具體操作方法請移步:石火電光追風逐日|前端優(yōu)化之次時代圖片壓縮格式WebP的項目級躬身實踐(Python3 PIL+Nginx) 。對于特定的圖片,比如Logo,使用svg格式圖片,請移步:Logo小變動,心境大不同,SVG矢量動畫格式網(wǎng)站Logo圖片制作與實踐教程(Python3)

          同時,對于圖片一律聲明寬高屬性,并且使用支持lazyload.js組件推遲對屏幕外圖片的加載。

          使用viewport標簽加快移動端的載入速度:

          <meta name="viewport" content="width=device-width, initial-scale=1">
              <meta name="applicable-device" content="pc,mobile"/>

          無障礙(Accessibility)

          訪問無障礙檢測所有用戶是否都能有效地訪問內(nèi)容并瀏覽網(wǎng)站,無障礙性的每個指標項測試結(jié)果為pass或者fail,與性能指標項的計算方式不同,當頁面只是部分通過某項指標時,頁面的這項指標將不會得分。例如,如果頁面中的一些元素有屏幕閱讀器友好的命名,而其他的元素沒有,那么這個頁面的 screenreader-friendly-names 指標項得分為0。

          一般情況下,優(yōu)化無障礙其實是對于站點標簽的優(yōu)化,比如頁面元素是否具備title標簽、title元素是否按降序排列、是否聲明了頁面語言類型、元素是否具備alt標簽等等,值得一提的是,頁面對比度也是無障礙評分重要的一環(huán),假如背景色是white,那么前景色最好選擇高對比度的顏色,比如black。

          最佳做法(Best Practice)

          最佳做法檢測可以改善網(wǎng)頁的代碼健康狀況的一些最佳做法,評分的分值由相關(guān)指標的加權(quán)平均值計算而來。

          最佳做法指標我們可以理解為就是站點安全性的指標,多數(shù)情況下,需要保證協(xié)議為HTTPS,同時要開啟CSP網(wǎng)頁安全政策防止XSS攻擊。

          CSP 的實質(zhì)就是白名單制度,開發(fā)者明確告訴客戶端,哪些外部資源可以加載和執(zhí)行,等同于提供白名單。它的實現(xiàn)和執(zhí)行全部由瀏覽器完成,開發(fā)者只需提供配置。CSP 大大增強了網(wǎng)頁的安全性。攻擊者即使發(fā)現(xiàn)了漏洞,也沒法注入腳本,除非還控制了一臺列入了白名單的可信主機。

          開啟方法:

          <meta http-equiv="Content-Security-Policy" content="script-src 'self'; object-src 'none'; style-src cdn.example.org third-party.org; child-src https:">

          搜索引擎優(yōu)化(SEO)

          搜索引擎優(yōu)化檢測搜索引擎對網(wǎng)頁內(nèi)容的理解程度是怎樣的,評分的分值由相關(guān)指標的加權(quán)平均值計算而來。

          說白了,就是站點頁面是否適合搜素引擎蜘蛛的抓取以及收錄,以本站為例,搜索引擎需要的標簽如下:

          <head>
              <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
              <meta http-equiv="X-UA-Compatible" content="IE=edge">
              <meta name="viewport" content="width=device-width, initial-scale=1">
              <meta name="applicable-device" content="pc,mobile"/>
              <title>當我們進行性能優(yōu)化,我們在優(yōu)化什么(LightHouse優(yōu)化實操)-劉悅</title>
              <meta name="description" content="好的互聯(lián)網(wǎng)產(chǎn)品不僅僅在功能上要高人一籌,在性能層面也需要出類拔萃,否則金玉其外敗絮其中,頁面是美輪美奐了,結(jié)果首屏半天加載不出來,難免讓用戶乘興而來,敗興而歸。幸運的是,前端的性能優(yōu)化有諸多有跡可循的理論和方法,其中相對權(quán)威的,無疑是LightHouse。LightHouse是一個開源的自動化工具,它作為Chrome瀏覽器的擴展程序運行,提供一套完整的站點評分標準,我們可以依">
              <meta content="劉悅" name="Author">
              <link rel="canonical" href="https://v3u.cn/a_id_214"/>
              <link rel="miphtml" href="https://v3u.cn/mipa_id_214">
              <link rel="stylesheet" href="/v3u/Public/css/tidy_min.css?v=11"/>
              <link rel="shortcut icon" href="favicon.ico" type="image/x-icon"/>
              <link rel="icon" href="favicon.ico" type="image/x-icon"/>
              <link rel="stylesheet" href="/v3u/Public/css/share.min.css?v=1">
          </head>

          包括頁面標題、描述、作者、頁面唯一標識等等元素。

          當我們完成上面這些指標的優(yōu)化之后,就可以,坐下來,欣賞這紫禁煙花一萬重了:

          正是:東風夜放花千樹,更吹落,星如雨。

          結(jié)語

          前端的性能分析和優(yōu)化方式,無論是傳統(tǒng)性能還是感官性能完全可以根據(jù)LightHouse按圖索驥。過程中可以針對某些指標進行一定的取舍,雖然本站在LightHouse的優(yōu)化實踐中取得了一定的效果,但路漫漫其修遠兮,吾將上下而求索。

          于開發(fā)人員來說,利用一款好用的代碼編輯器,可以起到事半功倍的作用。本人歸納整理了開發(fā)人員比較常用的代碼編輯器,希望大家喜歡!

          1) chocolatapp

          這款代碼編輯器,是最新出現(xiàn)的一個版本。它屬于Mac系統(tǒng)文本編輯器,不僅具有原生的Cocoa和強大文本編輯功能。這款代碼編輯器支持多種編輯語言,且支持關(guān)鍵字高亮顯示、窗口分割、標簽頁、色彩主題等功能。

          2)webide

          w3cschool開發(fā)的這款代碼編輯器功能相當豐富,不僅代碼可以自動提示,還有適合各種場景下使用的自定義字體。運用這個編輯器,還可以多光標編輯、支持多標簽、維持多個文檔、在線實時預(yù)覽。很多程序員愛用這一款編輯器,最主要的原因就是它有自動補全功能,寫代碼健步如飛。


          3) aptana

          這個開發(fā)工具主要用于Ajax開發(fā),功能也很強大。Aptana近來經(jīng)開發(fā)人員重新設(shè)計而煥發(fā)了新的活力,同以前相比,現(xiàn)在定制功能更強大,也更加快速。

          4) barebones

          這款代碼編輯器,不知道大家有沒有用過,小編沒用過,對相關(guān)功能不太清楚。

          5) Coda

          Coda是面向Web開發(fā)人員、網(wǎng)頁設(shè)計師的一款優(yōu)秀Mac下編輯器軟件。Coda不但輕巧,而且功能強大。它整合了終端、文字編輯器、CSS編輯器、內(nèi)容發(fā)布(結(jié)合了Transmit的FTP Client功能)等整個Web開發(fā)流程所需工具。與Textmate、BBEdit有一拼。

          6) editplus

          7) emacs

          Emacs即Editor MACroS(宏編輯器),是一種強大的文本編輯器。Emacs使用了Emacs Lisp這種有著極強擴展性的編程語言(它的核心是一個Emacs Lisp解釋器),并實現(xiàn)了文本編輯支持等的擴展。

          8) espresso

          9) komodo-ide

          10) e-texteditor

          E-TextEditor是一款新概念的窗口文本編輯軟件,號稱Windows平臺的TextMate,帶有強大文字編輯功能,和一些獨立的特性。支持多種語言文字,可以輸入大量和實時性通信信息。圖形庫用的是wxWindows。

          11) notepad++

          Notepad++ 是一款免費開源的跨平臺的代碼編輯器,基于GPL許可證。它支持包括中文在內(nèi)的多國語言,功能強大,除了可以用來制作一般的純文字說明文件,也十分適合當作撰寫電腦程序的編輯器。Notepad++不僅可以實現(xiàn)語法高亮顯示,也有語法折疊功能,并且支持宏以及擴充基本功能的外掛模組。

          12) macromates

          13) textpad

          一款強大的可以替代Notepad(記事本)的編輯器。可用于網(wǎng)頁編輯或者作為編程IDE。

          14) netbeans

          15) visual-web-developer-express

          16) jetbrains

          JetBrains的IDEA是Java開發(fā)最好用的IDE,沒有之一。

          17)CleverCSS

          18)Sass

          19)Sajax

          20)Komodo Edit for Perl, Python, Tcl, PHP, Ruby, Javascript

          21)CSSTidy

          22)Less

          23)About Markup Generator

          24)Haml

          25)XCSS

          26)Zen Coding — a new way of writing HTML and CSS code

          27)Vim

          28)Layer Styles

          這是一個HTML5應(yīng)用。利用它,開發(fā)者可以更直觀地編寫CSS3代碼。尤其看來,這個工具相當好用。

          29)Spritemapper

          Spritemapper應(yīng)用可將多張小圖片合并為一張圖片,從而減少服務(wù)器的Http連接數(shù),對提高網(wǎng)站的吞吐量有一定幫助,同時它還會每個圖像切片產(chǎn)生相應(yīng)的CSS定位。

          30)Tridiv

          免費Web應(yīng)用Tridiv可以很容易地創(chuàng)建出漂亮的3D圖形。使用該應(yīng)用,我們可以創(chuàng)建4種不同的形狀,包括長方體、金字塔、圓柱體和棱柱體,同時也可以對它們進行旋轉(zhuǎn)并改變大小。

          31)Responsive Web CSS

          Responsive Web CSS是基于Web的一個工具,可用來創(chuàng)建響應(yīng)式布局框架。你可以很容易地添加任意數(shù)量的頁面和div,并定義它們的百分比寬度。

          32)CSS Form Code Maker

          CSS Form Code Maker主要用來為表格創(chuàng)建美觀的外觀布局。

          33)Buttons

          Buttons為CSS庫,可用來創(chuàng)建高度定制化、靈活的現(xiàn)代Web按鈕。

          上面介紹的33個代碼編輯器,也不知道有沒有你最愛用的一款。當然,每個人的習慣不同,興趣愛好也不同,喜歡使用的代碼編輯器也不同,如果你有好的代碼編輯器推薦,歡迎來留言哦!


          主站蜘蛛池模板: 中文字幕AV一区二区三区| 精品视频一区二区观看| 日韩精品乱码AV一区二区| 无码人妻久久一区二区三区免费丨 | 一区二区三区免费看| 在线视频一区二区| 99精品高清视频一区二区| 精品国产AV无码一区二区三区| 亚洲一区二区三区免费在线观看| 精品无码人妻一区二区三区不卡 | 中文字幕亚洲一区二区va在线| 在线精品自拍亚洲第一区| 黑巨人与欧美精品一区| 亚洲中文字幕一区精品自拍| 亚洲熟妇成人精品一区| 精品一区二区三区四区在线播放 | 亚洲Aⅴ无码一区二区二三区软件| 欲色aV无码一区二区人妻| 人妻体体内射精一区二区| 日产亚洲一区二区三区| 久久综合精品不卡一区二区| 韩国福利一区二区三区高清视频| 精品一区二区三区免费观看| 国产一区二区三区免费看| 国产在线精品一区二区| 夜精品a一区二区三区| 国模吧一区二区三区精品视频| 精品国产一区二区三区麻豆| 久久久久人妻精品一区蜜桃| 少妇无码一区二区三区| 国产对白精品刺激一区二区| 男人的天堂av亚洲一区2区| 日韩精品一区二区三区中文3d| 国产精品一区二区在线观看| 精彩视频一区二区| 久久99热狠狠色精品一区| 麻豆一区二区三区精品视频| 怡红院AV一区二区三区| 影院无码人妻精品一区二区| 久久中文字幕一区二区| 亚洲中文字幕乱码一区|