web應用無非是兩臺主機之間互相傳輸數據包
的一個過程; 如何減小傳輸過程的耗時就是網絡方向優化的重點, 優化出發點從第一篇文章中提及css
DNS解析
過程的優化當瀏覽器從第三方服務跨域請求資源
的時候,在瀏覽器發起請求以前,這個第三方的跨域域名須要被解析爲一個IP地址,這個過程就是DNS解析;DNS緩存
能夠用來減小這個過程的耗時,DNS解析可能會增長請求的延遲,對於那些須要請求許多第三方的資源的網站而言,DNS解析的耗時延遲可能會大大下降網頁加載性能。html
當站點引用跨域域上的資源時,都應在<head>元素中放置dns-prefetch提示,可是要記住一些注意事項。首先,dns-prefetch僅對跨域域上的DNS查找有效,所以請避免將其用於您當前訪問的站點前端
<link rel="dns-prefetch" href="https://fonts.googleapis.com/">
因爲dns-prefetch僅執行DNS查找,但preconnect會創建與服務器的鏈接。若是站點是經過HTTPS服務的,則此過程包括DNS解析,創建TCP鏈接以及執行TLS握手。將二者結合起來可提供機會,進一步減小跨源請求的感知延遲vue
<!-- 注意順序, precontent和dns-prefetch的兼容性 --> <link rel="preconnect" href="https://fonts.googleapis.com/" crossorigin> <link rel="dns-prefetch" href="https://fonts.googleapis.com/">
這個前端方面好像能作的有限, 咱們都知道 http協議 是基於 tcp的;
升級http協議版本能夠考慮下, 好比把 http/1.0 -> http/1.1 -> http/2;
這個須要咱們在應用服務器上配置(nginx, Apache等), 不作概述了, 另外還須要客戶端和服務器都支持哦, 目前還沒開發出穩定版本,好多隻支持https,不過也不遠了...html5
# 1.多路複用: 同一個tcp鏈接傳輸多個資源 這樣能夠突破統一域名下只容許有限個tcp同時鏈接, 這樣http1.1所作的減小請求數優化就沒有太大必要了 如多張小圖合成一張大圖(雪碧圖),合併js和css文件 # 2.報文頭壓縮和二進制編碼: 減小傳輸體積 http1 中第一次請求有完整的http報文頭部,第二次請求的也是; http2 中第一次請求有完整的http報文頭部,第二次請求只會攜帶 path 字段; 這樣就大大減小了發送的量。這個的實現要求客戶端和服務同時維護一個報文頭表。 # 3.Server Push http2可讓服務先把其它極可能客戶端會請求的資源(好比圖片)先push發給你, 不用等到請求的時候再發送,這樣能夠提升頁面總體的加載速度 但目前支持性不太好...emm...
總的來講, 在 c 端業務下不會太普及, 畢竟須要軟件支持才行...node
爲了讓數據包傳輸的更快, 咱們能夠從兩個方面
入手: 請求的數據包大小(服務器), 請求數據包的頻率(客戶端)webpack
請求文件對應的是咱們項目完成後,打包所指的靜態資源文件(會被部署到服務器), 文件越小, 傳輸的數據包也會相對較小, 講道理也會更快到達客戶端nginx
目前咱們都會使用打包工具了(好比webpack, rollup, glup 等), 如何使用工具來減少包的體積呢? 這邊建議您去官網文檔呢...固然這裏列舉一下經常使用的手段(webpack 的), 可是注意要插件版本更新哦git
const UglifyJsPlugin = require('uglifyjs-webpack-plugin'); module.exports = { plugins: [ new UglifyJsPlugin({ // 容許併發 parallel: true, // 開啓緩存 cache: true, compress: { // 刪除全部的console語句 drop_console: true, // 把使用屢次的靜態值自動定義爲變量 reduce_vars: true, }, output: { // 不保留註釋 comment: false, // 使輸出的代碼儘量緊湊 beautify: false } }) ] }
// optimize-css-assets-webpack-plugin plugins: [ new OptimizeCSSAssetsPlugin({ assetNameRegExp: /\.css$/g, cssProcessor: require('cssnano'), }), ];
// html-webpack-plugin plugins: [ new HtmlWebpackPlugin({ template: path.join(__dirname, 'src/index.html'), filename: 'index.html', chunks: ['index'], inject: true, minify: { html5: true, collapseWhitespace: true, preserveLineBreaks: false, minifyCSS: true, minifyJS: true, removeComments: false, }, }), ];
1.代碼不會被執行,不可到達,好比 if(false){// 這裏邊的代碼} 2.代碼執行的結果不會被用到 3.代碼只會影響死變量(只寫不讀) 4.方法不能有反作用 // 原理相關: 之後在研究 利用 ES6 模塊的特色: 只能做爲模塊頂層的語句出現 import 的模塊名只能是字符串常量 import binding 是 immutable 的 代碼擦除: uglify 階段刪除無用代碼
分析出模塊之間的依賴關係,儘量的把打散的模塊合併到一個函數中去,但前提是不能形成代碼冗餘github
const ModuleConcatenationPlugin = require('webpack/lib/optimize/ModuleConcatenationPlugin'); module.exports = { resolve: { // 針對 Npm 中的第三方模塊優先採用 jsnext:main 中指向的 ES6 模塊化語法的文件 mainFields: ['jsnext:main', 'browser', 'main'] }, plugins: [ // 開啓 Scope Hoisting new ModuleConcatenationPlugin(), ], };
const router = new VueRouter({ routes: [ { path: '/foo', component: () => import(/* webpackChunkName: "foo" */ './Foo.vue') } { path: '/bar', component: () => import(/* webpackChunkName: "bar" */ './Bar.vue') } ] })
有時候啓用也會消耗服務器性能, 看狀況使用吧
暫時先提這麼些吧...後續想到了再加
由於同一域名下 tcp 鏈接數的限制致使過多的請求會排隊阻塞, 因此咱們須要儘可能控制請求的數量和頻率
這樣這些資源無需從服務器獲取, 但可能影響到渲染進程...
<!-- 1.小圖片內聯 base64 (url-loader) --> <!-- 2.css內聯 --> <!-- 3.js內聯 --> <script> ${require('raw-loader!babel-loader!./node_modules/lib-flexible/flexible.js')} </script>
一般都是在服務端作相關配置
, 但你要知道
咱們能夠利用http緩存(瀏覽器端)來減小和攔截二次請求, 固然通常都是在服務端設置的; 服務器端也能夠設置緩存(redis等), 減小數據查詢的時間一樣能夠縮短整個請求時間
咱們能夠將經常使用不變的信息存在本地(cookie,storage API 等); 判斷存在就不去請求相關的接口, 或者按期去請求也是能夠的
CDN 又叫內容分發網絡,經過把資源部署到世界各地,用戶在訪問時按照就近原則從離用戶最近的服務器獲取資源,從而加速資源的獲取速度。 CDN 實際上是經過優化物理鏈路層傳輸過程當中的網速有限、丟包等問題來提高網速的...
購買 cdn 服務器; 而後把網頁的靜態資源上傳到 CDN 服務上去, 在請求這些靜態資源的時候須要經過 CDN 服務提供的 URL 地址去訪問; # 注意, cdn 緩存致使的新版本發佈後不生效的問題 因此打包的時候常在文件後面加上 hash 值 而後在 HTML 文件中的資源引入地址也須要換成 CDN 服務提供的地址 /alicdn/xx12dsa311.js # 利用不一樣域名的 cdn 去存放資源, (tcp鏈接限制)
// 靜態資源的導入 URL 須要變成指向 CDN 服務的絕對路徑的 URL 而不是相對於 HTML 文件的 URL。 // 靜態資源的文件名稱須要帶上有文件內容算出來的 Hash 值,以防止被緩存。 // 不一樣類型的資源放到不一樣域名的 CDN 服務上去,以防止資源的並行加載被阻塞。 module.exports = { // 省略 entry 配置... output: { // 給輸出的 JavaScript 文件名稱加上 Hash 值 filename: '[name]_[chunkhash:8].js', path: path.resolve(__dirname, './dist'), // 指定存放 JavaScript 文件的 CDN 目錄 URL publicPath: '//js.cdn.com/id/', }, module: { rules: [ { // 增長對 CSS 文件的支持 test: /\.css$/, // 提取出 Chunk 中的 CSS 代碼到單獨的文件中 use: ExtractTextPlugin.extract({ // 壓縮 CSS 代碼 use: ['css-loader?minimize'], // 指定存放 CSS 中導入的資源(例如圖片)的 CDN 目錄 URL publicPath: '//img.cdn.com/id/' }), }, { // 增長對 PNG 文件的支持 test: /\.png$/, // 給輸出的 PNG 文件名稱加上 Hash 值 use: ['file-loader?name=[name]_[hash:8].[ext]'], }, // 省略其它 Loader 配置... ] }, plugins: [ // 使用 WebPlugin 自動生成 HTML new WebPlugin({ // HTML 模版文件所在的文件路徑 template: './template.html', // 輸出的 HTML 的文件名稱 filename: 'index.html', // 指定存放 CSS 文件的 CDN 目錄 URL stylePublicPath: '//css.cdn.com/id/', }), new ExtractTextPlugin({ // 給輸出的 CSS 文件名稱加上 Hash 值 filename: `[name]_[contenthash:8].css`, }), // 省略代碼壓縮插件配置... ], }; /* 以上代碼中最核心的部分是經過 publicPath 參數設置存放靜態資源的 CDN 目錄 URL, 爲了讓不一樣類型的資源輸出到不一樣的 CDN,須要分別在: output.publicPath 中設置 JavaScript 的地址。 css-loader.publicPath 中設置被 CSS 導入的資源的的地址。 WebPlugin.stylePublicPath 中設置 CSS 文件的地址。 設置好 publicPath 後,WebPlugin 在生成 HTML 文件和 css-loader 轉換 CSS 代碼時,會考慮到配置中的 publicPath,用對應的線上地址替換原來的相對地址。 */