我也寫了個低仿網易雲音樂播放器,這是個人感覺

開發一個基於Vue的低仿mac網易雲音樂web播放器及開後感


前言


  • 在寫該項目以前, 參考了ssh大佬的音樂項目(掘金地址), 由於瞭解到ssh效力於國內著名大廠,因此本着學習的態度在動手以前將其音樂項目的基礎架構代碼風格研究了一遍(確實收穫了不少)javascript

  • 感謝大佬提供的apicss

項目簡介


預覽地址 git地址html

技術棧
  • webpack4(打包工具, 這個項目中我並無用vue-cli, 由於想體驗下本身搭建webpack有多痛苦:( )
  • element-ui (用到了其中輪播圖, 表格等部分組件)
  • sass (css預處理器)
  • Vue全家桶
輔助工具 & 插件
  • better-scroll(歌詞滾動)
  • xgplayer (西瓜視頻播放器)]
  • postcss-pxtorem (px轉rem工具, 本身搭webpack 加這玩意兒實在太費勁了)
  • charles (抓包工具)
  • axios
項目功能
  • 登陸(帳號密碼 & 網易雲Id)
  • 音樂播放
  • 視頻播放
  • 歌單 & 專輯頁
  • 搜索結果, 搜索面板
  • 播放記錄 & 播放列表
  • 排行榜 & 最新音樂 & 個性推薦
  • 個人收藏歌單列表
  • 歌詞, 評論, 相關推薦
  • 有些功能相較於網易雲音樂是殘疾版, 由於提供的接口是2年前的, 因此有些不支持如今的業務邏輯
項目預覽

跑一下
cnpm i 

npm run start 本地預覽

npm run build 打包

npm run analyz 打包文件分析

npm run release 部署到服務器
複製代碼

webpack

這個項目寫到目前爲止, 我花費精力最可能是webpack相關以及打包優化相關的內容(這裏的精力 = 花費時間 / 代碼量). 腳手架 很方便, 可是我仍是想體驗下從0搭建一個小項目的webpack配置前端

  • 我的以爲本身配置webpack起手式, 就是碰到問題去搜, 逐個擊破, 像我這樣的小白千萬不要代碼還沒開始寫就想撘出個腳手架級別的配置, 像這樣...
    搜着搜着 就這樣了

簡述打包優化歷程

  • 先上一張啥也沒有優化時的圖片
    呵呵呵呵... 一個破音樂播放器 6.1M 48.9s
開始優化
  1. 在生產環境的配置文件中, 加上(mode: production), 有了這句話, webpack會自動幫你壓縮代碼, 且效果很是顯著

2. 使用 gzip, 這一步須要在webpack使用 compression-webpack-plugin插件

plugins: [
    ...
    new CompressionWebpackPlugin({
      algorithm: 'gzip',
      test: /\.js(\?.*)?$/i,
      threshold: 10240,
      minRatio: 0.8
    }),
複製代碼

以及nginx配置文件中配置vue

http{
  ....
    gzip on;
    gzip_comp_level 6;
    gzip_types text/xml text/plain text/css application/javascript application/x-javascript application/rss+xml;
    gzip_disable "MSIE[1-6]\.";
複製代碼

使用過程當中我發現webpack不配置gzip壓縮僅配置nginx, 在最終訪問項目時, 拿到的文件也是gzip格式的. 查閱後,才知道 gzip 服務端也能進行壓縮, 可是若是客戶端直接把壓縮好的gzip文件傳到服務端 能夠節省服務端在收到請求後對文件進行的壓縮的性能損耗java


webpack端配置gzip壓縮

webpack端不配置gzip壓縮
  1. 使用ParallelUglifyPlugin, 開啓多個子進程並行壓縮 節省壓縮時間, 而且去除調試日誌
plugins:[
    ...
    new ParallelUglifyPlugin({
      cacheDir: '.cache/',
      uglifyJS:{
        output: {
          comments: false
        },
        warnings: false,
        compress: {
          drop_debugger: true, // 去除生產環境的 debugger 和 console.log
          drop_console: true
        }
      }
    }),
複製代碼
  1. 將一些依賴 用cdn連接引入, 而且使用dns預解析
// webpack.prod.conf.js
    externals:{
        vue: 'Vue',
        'vue-router': 'VueRouter',
        vuex: 'Vuex',
        axios: 'axios',
    },

// index.html 
    <head>
    //使用dns預解析(將域名解析成ip是很耗時的)
      <link rel="dns-prefetch" href="//cdn.bootcss.com">
      <link rel="dns-prefetch" href="//cdnjs.cloudflare.com">
    </head>
    ...
    <body>
    //這串奇怪的代碼html-webpack-plugin插件會解析的
        <% if ( process.env.NODE_ENV === 'production' ) { %>
            <script src="https://cdn.bootcss.com/vue/2.6.10/vue.runtime.min.js"></script>
            <script src="https://cdn.bootcss.com/vue-router/3.1.3/vue-router.min.js"></script>
            <script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.0/axios.min.js"></script>
            <script src="https://cdnjs.cloudflare.com/ajax/libs/vuex/3.1.2/vuex.min.js"></script>
        <%} %>

複製代碼
  1. 使用splitChunks, 這個插件不須要install, 直接使用便可, 它的做用是將公共依賴單獨提取出來,避免被重複打包, 具體細節能夠看這
splitChunks: {
  chunks: 'all',
  cacheGroups: {
    xgplayer: {
      test: /xgplayer/,
      priority: 0,
      name: 'xgplayer'
    },
    vendor: {
      test: /[\\/]node_modules[\\/]/,
      priority: -10,
      name: 'vendors',
      minChunks: 10
    }
  }
}
複製代碼

注意下'xgplayer', 這是個視頻播放器庫, 我這裏單獨配置也是爲了優化打包, 第7點會說node

  • 至此, 個人初步優化已經完成了, 那還有沒有優化空間呢, 這裏能夠先用下打包分析工具 webpack-bundle-analyzer
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
 plugins: [
    // 打包分析
    new BundleAnalyzerPlugin(
      {
        analyzerMode: 'server',
        analyzerHost: '127.0.0.1',
        analyzerPort: 8888,
        reportFilename: 'report.html',
        defaultSizes: 'parsed',
        openAnalyzer: true,
        generateStatsFile: false,
        statsFilename: 'stats.json',
        statsOptions: null,
        logLevel: 'info'
      }
    ),
  ],
複製代碼

  1. 從圖中能夠清晰的看到打包後代碼的結構, moment這個庫中有不少的語言包, 能夠用webpack自帶的ContextReplacementPlugin插件進行過濾
//過濾moment其餘語言包 打包體積縮小200kb
    new webpack.ContextReplacementPlugin(
      /moment[/\\]locale$/,
      /zh-cn/,
    ),
複製代碼
  1. xgplayer也佔用了很大的體積, 那如何優化呢? 這裏引入一個'prefetching'概念, 其思想就是將一些文件在瀏覽器資源空閒時去分配資源下載, 從業務邏輯考慮, 在用戶初次訪問項目時, 是不須要用到視頻庫的資源的, 因此能夠把瀏覽器資源分配給首屏須要的文件. 在業務邏輯中這樣配置
watch: {
    url: {
      handler(newV, oldV) {
        if (newV && newV !== oldV) {
          if (!this.player) {
            import(/* webpackPrefetch:true */'xgplayer').then((module) => {
              xyPlayer = module.default;
              this.initVideo()
              //這裏這樣寫的目的是,若是有用戶經過url直接打開視頻頁, 那我也能夠同步加載完視頻庫文件後, 再初始化視頻組件
            })
          } else {
            this.player.src = newV
            this.player.reload()
          }
        }
      },
      immediate: !0
    }
  }
複製代碼
  • 至至至此, 個人第二步優化已經完成了, 那還有沒有優化空間呢, 這裏能夠用下chrome瀏覽器的調試工具coverage, 這個工具能夠幫你分析出文件利用率(即加載的文件中, 真正用到的代碼有哪些), 附上一張我優化好的截圖

首屏加載的文件利用率只有 35%,該部分優化的核心思想就是 將首屏看不見的資源所有異步導入, 例如採用 component: () => import('xxxx')路由懶加載, 將須要用戶交互纔會用到的邏輯代碼單獨封裝,按需加載,例如

//click.js 
function click() {
    ....
}
export default click
//main.js
document.addEventListener('click', () => {
    import('./click').then(({ default: click }) => {
        click()
    })
})
複製代碼

固然這樣作會很繁瑣, 不過對於追求極致體驗的應用來講, 也是個路子...webpack

附上兩張優化完狀態, 固然 這不是還不是最佳的狀態... ios

總結

不用腳手架從0搭webpack及優化打包能讓本身接觸到不少業務代碼之外的東西, 這些東西也是前端職責中很重要的但也經常被忽視的模塊, 過程很艱難但也充滿意義.nginx

相關文章
相關標籤/搜索