注册
web

我也写了个低仿网易云音乐播放器,这是我的感受

开发一个基于Vue的低仿mac网易云音乐web播放器及开后感


前言


项目简介


预览地址 git地址

技术栈
  • webpack4(打包工具, 这个项目中我并没有用vue-cli, 因为想体验下自己搭建webpack有多痛苦:( )

  • element-ui (用到了其中轮播图, 表格等部分组件)

  • sass (css预处理器)

  • Vue全家桶

辅助工具 & 插件
  • better-scroll(歌词滚动)

  • xgplayer (西瓜视频播放器)]

  • postcss-pxtorem (px转rem工具, 自己搭webpack 加这玩意儿实在太费劲了)

  • charles (抓包工具)

  • axios

项目功能
  • 登录(账号密码 & 网易云Id)

  • 音乐播放

  • 视频播放

  • 歌单 & 专辑页

  • 搜索结果, 搜索面板

  • 播放记录 & 播放列表

  • 排行榜 & 最新音乐 & 个性推荐

  • 我的收藏歌单列表

  • 歌词, 评论, 相关推荐

  • 有些功能相较于网易云音乐是残疾版, 因为提供的接口是2年前的, 所以有些不支持现在的业务逻辑

项目预览

16f936fa63cc76b7~tplv-t2oaga2asx-zoom-in-crop-mark:3024:0:0:0.awebp16f9370054257f69~tplv-t2oaga2asx-zoom-in-crop-mark:3024:0:0:0.awebp 16f93700c3a49a95~tplv-t2oaga2asx-zoom-in-crop-mark:3024:0:0:0.awebp 16f93702d66aff2f~tplv-t2oaga2asx-zoom-in-crop-mark:3024:0:0:0.awebp 16f93703689a1de5~tplv-t2oaga2asx-zoom-in-crop-mark:3024:0:0:0.awebp 16f93703ff335a2c~tplv-t2oaga2asx-zoom-in-crop-mark:3024:0:0:0.awebp

跑一下
cnpm i 

npm run start 本地预览

npm run build 打包

npm run analyz 打包文件分析

npm run release 部署到服务器

webpack

这个项目写到目前为止, 我花费精力最多是webpack相关以及打包优化相关的内容(这里的精力 = 花费时间 / 代码量). 脚手架 很方便, 但是我还是想体验下从0搭建一个小项目的webpack配置

  • 个人觉得自己配置webpack起手式, 就是碰到问题去搜, 逐个击破, 像我这样的小白千万不要代码还没开始写就想撘出个脚手架级别的配置, 像这样... 16f93dda017dacff~tplv-t2oaga2asx-zoom-in-crop-mark:3024:0:0:0.awebp

  • 16f93de45a05265f~tplv-t2oaga2asx-zoom-in-crop-mark:3024:0:0:0.awebp

  • 16f93dec5837fec1~tplv-t2oaga2asx-zoom-in-crop-mark:3024:0:0:0.awebp

  • 搜着搜着 就这样了

16f93e1256877c6b~tplv-t2oaga2asx-zoom-in-crop-mark:3024:0:0:0.awebp

简述打包优化历程

  • 先上一张啥也没有优化时的图片
    16f93f8ffbfa7a8a~tplv-t2oaga2asx-zoom-in-crop-mark:3024:0:0:0.awebp
    呵呵呵呵... 一个破音乐播放器 6.1M 48.9s

开始优化
  1. 在生产环境的配置文件中, 加上(mode: production), 有了这句话, webpack会自动帮你压缩代码, 且效果非常显著

16f93e9c57cf8df3~tplv-t2oaga2asx-zoom-in-crop-mark:3024:0:0:0.awebp

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

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

以及nginx配置文件中配置

 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文件传到服务端 可以节省服务端在收到请求后对文件进行的压缩的性能损耗

16f93f1945f990c7~tplv-t2oaga2asx-zoom-in-crop-mark:3024:0:0:0.awebp

webpack端配置gzip压缩

16f93f3bbf55ff38~tplv-t2oaga2asx-zoom-in-crop-mark:3024:0:0:0.awebp

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点会说

  • 至此, 我的初步优化已经完成了, 那还有没有优化空间呢, 这里可以先用下打包分析工具 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'
     }
  ),
 ],

16f947fef663b850~tplv-t2oaga2asx-zoom-in-crop-mark:3024:0:0:0.awebp

  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, 这个工具可以帮你分析出文件利用率(即加载的文件中, 真正用到的代码有哪些), 附上一张我优化好的截图

16f9488b57cde87b~tplv-t2oaga2asx-zoom-in-crop-mark:3024:0:0:0.awebp

首屏加载的文件利用率只有35%,该部分优化的核心思想就是将首屏看不见的资源全部异步导入, 例如采用component: () => import('xxxx')路由懒加载, 将需要用户交互才会用到的逻辑代码单独封装,按需加载,例如

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

当然这样做会很繁琐, 不过对于追求极致体验的应用来说, 也是个路子...

附上两张优化完状态, 当然 这不是还不是最佳的状态...

16f949fff92cf0aa~tplv-t2oaga2asx-zoom-in-crop-mark:3024:0:0:0.awebp16f94a01ebe49e32~tplv-t2oaga2asx-zoom-in-crop-mark:3024:0:0:0.awebp

总结

不用脚手架从0搭webpack及优化打包能让自己接触到很多业务代码以外的东西, 这些东西也是前端职责中很重要的但也常常被忽视的模块, 过程很艰难但也充满意义.

作者:stormsprit
来源:juejin.cn/post/6844904045765722125

0 个评论

要回复文章请先登录注册