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

开发一个基于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

相关文章
相关标签/搜索