<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                Web 前端工程師寫的頁面要跑在瀏覽器里面,所以面試中也會出現很多跟瀏覽器相關的面試題目。 ## 知識點梳理 * 瀏覽器加載頁面和渲染過程 * 性能優化 * Web 安全 本小節會從瀏覽器的加載過程開始講解,然后介紹如何進行性能優化,最后介紹下 Web 開發中常見的安全問題和預防。 * * * ## 加載頁面和渲染過程 可將加載過程和渲染過程分開說。回答問題的時候,關鍵要抓住核心的要點,把要點說全面,稍加解析即可,簡明扼要不拖沓。 > 題目:瀏覽器從加載頁面到渲染頁面的過程 ### 加載過程 要點如下: * 瀏覽器根據 DNS 服務器得到域名的 IP 地址 * 向這個 IP 的機器發送 HTTP 請求 * 服務器收到、處理并返回 HTTP 請求 * 瀏覽器得到返回內容 例如在瀏覽器輸入`https://juejin.im/timeline`,然后經過 DNS 解析,`juejin.im`對應的 IP 是`36.248.217.149`(不同時間、地點對應的 IP 可能會不同)。然后瀏覽器向該 IP 發送 HTTP 請求。 server 端接收到 HTTP 請求,然后經過計算(向不同的用戶推送不同的內容),返回 HTTP 請求,返回的內容如下: ![](https://user-gold-cdn.xitu.io/2018/2/23/161c107496accac7?w=1176&h=294&f=png&s=77020) 其實就是一堆 HMTL 格式的字符串,因為只有 HTML 格式瀏覽器才能正確解析,這是 W3C 標準的要求。接下來就是瀏覽器的渲染過程。 ### 渲染過程 要點如下: * 根據 HTML 結構生成 DOM 樹 * 根據 CSS 生成 CSSOM * 將 DOM 和 CSSOM 整合形成 RenderTree * 根據 RenderTree 開始渲染和展示 * 遇到`<script>`時,會執行并阻塞渲染 上文中,瀏覽器已經拿到了 server 端返回的 HTML 內容,開始解析并渲染。最初拿到的內容就是一堆字符串,必須先結構化成計算機擅長處理的基本數據結構,因此要把 HTML 字符串轉化成 DOM 樹 —— 樹是最基本的數據結構之一。 解析過程中,如果遇到`<link href="...">`和`<script src="...">`這種外鏈加載 CSS 和 JS 的標簽,瀏覽器會異步下載,下載過程和上文中下載 HTML 的流程一樣。只不過,這里下載下來的字符串是 CSS 或者 JS 格式的。 瀏覽器將 CSS 生成 CSSOM,再將 DOM 和 CSSOM 整合成 RenderTree ,然后針對 RenderTree 即可進行渲染了。大家可以想一下,有 DOM 結構、有樣式,此時就能滿足渲染的條件了。另外,這里也可以解釋一個問題 —— **為何要將 CSS 放在 HTML 頭部?**—— 這樣會讓瀏覽器盡早拿到 CSS 盡早生成 CSSOM,然后在解析 HTML 之后可一次性生成最終的 RenderTree,渲染一次即可。如果 CSS 放在 HTML 底部,會出現渲染卡頓的情況,影響性能和體驗。 最后,渲染過程中,如果遇到`<script>`就停止渲染,執行 JS 代碼。因為瀏覽器渲染和 JS 執行共用一個線程,而且這里必須是單線程操作,多線程會產生渲染 DOM 沖突。待`<script>`內容執行完之后,瀏覽器繼續渲染。最后再思考一個問題 —— **為何要將 JS 放在 HTML 底部?**—— JS 放在底部可以保證讓瀏覽器優先渲染完現有的 HTML 內容,讓用戶先看到內容,體驗好。另外,JS 執行如果涉及 DOM 操作,得等待 DOM 解析完成才行,JS 放在底部執行時,HTML 肯定都解析成了 DOM 結構。JS 如果放在 HTML 頂部,JS 執行的時候 HTML 還沒來得及轉換為 DOM 結構,可能會報錯。 關于瀏覽器整個流程,百度的多益大神有更加詳細的文章,推薦閱讀下:《[從輸入 URL 到頁面加載完成的過程中都發生了什么事情?](http://fex.baidu.com/blog/2014/05/what-happen/) 》。 * * * ## 性能優化 性能優化的題目也是面試常考的,這類題目有很大的擴展性,能夠擴展出來很多小細節,而且對個人的技術視野和業務能力有很大的挑戰。這部分筆者會重點講下常用的性能優化方案。 > 題目:總結前端性能優化的解決方案 ### 優化原則和方向 性能優化的原則是**以更好的用戶體驗為標準**,具體就是實現下面的目標: 1. 多使用內存、緩存或者其他方法 2. 減少 CPU 和GPU 計算,更快展現 優化的方向有兩個: * **減少頁面體積,提升網絡加載** * **優化頁面渲染** ### 減少頁面體積,提升網絡加載 * 靜態資源的壓縮合并(JS 代碼壓縮合并、CSS 代碼壓縮合并、雪碧圖) * 靜態資源緩存(資源名稱加 MD5 戳) * 使用 CDN 讓資源加載更快 ### 優化頁面渲染 * CSS 放前面,JS 放后面 * 懶加載(圖片懶加載、下拉加載更多) * 減少DOM 查詢,對 DOM 查詢做緩存 * 減少DOM 操作,多個操作盡量合并在一起執行(`DocumentFragment`) * 事件節流 * 盡早執行操作(`DOMContentLoaded`) * 使用 SSR 后端渲染,數據直接輸出到 HTML 中,減少瀏覽器使用 JS 模板渲染頁面 HTML 的時間 ### 詳細解釋 #### 靜態資源的壓縮合并 如果不合并,每個都會走一遍之前介紹的請求過程 ``` <script src="a.js"></script> <script src="b.js"></script> <script src="c.js"></script> ``` 如果合并了,就只走一遍請求過程 ``` <script src="abc.js"></script> ``` #### 靜態資源緩存 通過鏈接名稱控制緩存 ``` <script src="abc_1.js"></script> ``` 只有內容改變的時候,鏈接名稱才會改變 ``` <script src="abc_2.js"></script> ``` 這個名稱不用手動改,可通過前端構建工具根據文件內容,為文件名稱添加 MD5 后綴。 #### 使用 CDN 讓資源加載更快 CDN 會提供專業的加載優化方案,靜態資源要盡量放在 CDN 上。例如: ``` <script src="https://cdn.bootcss.com/zepto/1.0rc1/zepto.min.js"></script> ``` #### 使用 SSR 后端渲染 可一次性輸出 HTML 內容,不用在頁面渲染完成之后,再通過 Ajax 加載數據、再渲染。例如使用 smarty、Vue SSR 等。 #### CSS 放前面,JS 放后面 上文講述瀏覽器渲染過程時已經提過,不再贅述。 #### 懶加載 一開始先給為 `src` 賦值成一個通用的預覽圖,下拉時候再動態賦值成正式的圖片。如下,`preview.png`是預覽圖片,比較小,加載很快,而且很多圖片都共用這個`preview.png`,加載一次即可。待頁面下拉,圖片顯示出來時,再去替換`src`為`data-realsrc`的值。 ``` <img src="preview.png" data-realsrc="abc.png"/> ``` 另外,這里為何要用`data-`開頭的屬性值?—— 所有 HTML 中自定義的屬性,都應該用`data-`開頭,因為`data-`開頭的屬性瀏覽器渲染的時候會忽略掉,提高渲染性能。 #### DOM 查詢做緩存 兩段代碼做一下對比: ``` var pList = document.getElementsByTagName('p') // 只查詢一個 DOM ,緩存在 pList 中了 var i for (i = 0; i < pList.length; i++) { } ``` ``` var i for (i = 0; i < document.getElementsByTagName('p').length; i++) { // 每次循環,都會查詢 DOM ,耗費性能 } ``` 總結:DOM 操作,無論查詢還是修改,都是非常耗費性能的,應盡量減少。 #### 合并 DOM 插入 DOM 操作是非常耗費性能的,因此插入多個標簽時,先插入 Fragment 然后再統一插入 DOM。 ``` var listNode = document.getElementById('list') // 要插入 10 個 li 標簽 var frag = document.createDocumentFragment(); var x, li; for(x = 0; x < 10; x++) { li = document.createElement("li"); li.innerHTML = "List item " + x; frag.appendChild(li); // 先放在 frag 中,最后一次性插入到 DOM 結構中。 } listNode.appendChild(frag); ``` #### 事件節流 例如要在文字改變時觸發一個 change 事件,通過 keyup 來監聽。使用節流。 ``` var textarea = document.getElementById('text') var timeoutId textarea.addEventListener('keyup', function () { if (timeoutId) { clearTimeout(timeoutId) } timeoutId = setTimeout(function () { // 觸發 change 事件 }, 100) }) ``` #### 盡早執行操作 ``` window.addEventListener('load', function () { // 頁面的全部資源加載完才會執行,包括圖片、視頻等 }) document.addEventListener('DOMContentLoaded', function () { // DOM 渲染完即可執行,此時圖片、視頻還可能沒有加載完 }) ``` #### 性能優化怎么做 上面提到的都是性能優化的單個點,性能優化項目具體實施起來,應該按照下面步驟推進: 1. 建立性能數據收集平臺,摸底當前性能數據,通過性能打點,將上述整個頁面打開過程消耗時間記錄下來 2. 分析耗時較長時間段原因,尋找優化點,確定優化目標 3. 開始優化 4. 通過數據收集平臺記錄優化效果 5. 不斷調整優化點和預期目標,循環2~4步驟 性能優化是個長期的事情,不是一蹴而就的,應該本著先摸底、再分析、后優化的原則逐步來做。 * * * ## Web 安全 > 題目:前端常見的安全問題有哪些? Web 前端的安全問題,能回答出下文的兩個問題,這個題目就能基本過關了。開始之前,先說一個最簡單的攻擊方式 —— SQL 注入。 上學的時候就知道有一個「SQL注入」的攻擊方式。例如做一個系統的登錄界面,輸入用戶名和密碼,提交之后,后端直接拿到數據就拼接 SQL 語句去查詢數據庫。如果在輸入時進行了惡意的 SQL 拼裝,那么最后生成的 SQL 就會有問題。但是現在稍微大型一點的系統,都不會這么做,從提交登錄信息到最后拿到授權,要經過層層的驗證。因此,SQL 注入都只出現在比較低端小型的系統上。 ### XSS(Cross Site Scripting,跨站腳本攻擊) 這是前端最常見的攻擊方式,很多大型網站(如 Facebook)都被 XSS 攻擊過。 舉一個例子,我在一個博客網站正常發表一篇文章,輸入漢字、英文和圖片,完全沒有問題。但是如果我寫的是惡意的 JS 腳本,例如獲取到`document.cookie`然后傳輸到自己的服務器上,那我這篇博客的每一次瀏覽都會執行這個腳本,都會把訪客 cookie 中的信息偷偷傳遞到我的服務器上來。 其實原理上就是黑客通過某種方式(發布文章、發布評論等)將一段特定的 JS 代碼隱蔽地輸入進去。然后別人再看這篇文章或者評論時,之前注入的這段 JS 代碼就執行了。**JS 代碼一旦執行,那可就不受控制了,因為它跟網頁原有的 JS 有同樣的權限**,例如可以獲取 server 端數據、可以獲取 cookie 等。于是,攻擊就這樣發生了。 #### XSS的危害 XSS 的危害相當大,如果頁面可以隨意執行別人不安全的 JS 代碼,輕則會讓頁面錯亂、功能缺失,重則會造成用戶的信息泄露。 比如早些年社交網站經常爆出 XSS 蠕蟲,通過發布的文章內插入 JS,用戶訪問了感染不安全 JS 注入的文章,會自動重新發布新的文章,這樣的文章會通過推薦系統進入到每個用戶的文章列表面前,很快就會造成大規模的感染。 還有利用獲取 cookie 的方式,將 cookie 傳入入侵者的服務器上,入侵者就可以模擬 cookie 登錄網站,對用戶的信息進行篡改。 #### XSS的預防 那么如何預防 XSS 攻擊呢?—— 最根本的方式,就是對用戶輸入的內容進行驗證和替換,需要替換的字符有: ``` & 替換為:&amp; < 替換為:&lt; > 替換為:&gt; ” 替換為:&quot; ‘ 替換為:&#x27; / 替換為:&#x2f; ``` 替換了這些字符之后,黑客輸入的攻擊代碼就會失效,XSS 攻擊將不會輕易發生。 除此之外,還可以通過對 cookie 進行較強的控制,比如對敏感的 cookie 增加`http-only`限制,讓 JS 獲取不到 cookie 的內容。 ### CSRF(Cross-site request forgery,跨站請求偽造) CSRF 是借用了當前操作者的權限來偷偷地完成某個操作,而不是拿到用戶的信息。 例如,一個支付類網站,給他人轉賬的接口是`http://buy.com/pay?touid=999&money=100`,而這個接口在使用時沒有任何密碼或者 token 的驗證,只要打開訪問就直接給他人轉賬。一個用戶已經登錄了`http://buy.com`,在選擇商品時,突然收到一封郵件,而這封郵件正文有這么一行代碼`<img src="http://buy.com/pay?touid=999&money=100"/>`,他訪問了郵件之后,其實就已經完成了購買。 CSRF 的發生其實是借助了一個 cookie 的特性。我們知道,登錄了`http://buy.com`之后,cookie 就會有登錄過的標記了,此時請求`http://buy.com/pay?touid=999&money=100`是會帶著 cookie 的,因此 server 端就知道已經登錄了。而如果在`http://buy.com`去請求其他域名的 API 例如`http://abc.com/api`時,是不會帶 cookie 的,這是瀏覽器的同源策略的限制。但是 —— **此時在其他域名的頁面中,請求`http://buy.com/pay?touid=999&money=100`,會帶著`buy.com`的 cookie ,這是發生 CSRF 攻擊的理論基礎。** 預防 CSRF 就是加入各個層級的權限驗證,例如現在的購物網站,只要涉及現金交易,肯定要輸入密碼或者指紋才行。除此之外,敏感的接口使用`POST`請求而不是`GET`也是很重要的。 * * * ## 小結 本小節總結了前端運行環境(即瀏覽器)的一些常考查知識點,包括頁面加載過程、如何性能優化以及需要注意的安全問題。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看