Vue.Js开源:bilibili-vue-前端 vue + 后端 koa,全栈式开发 bilibili 首页

wangjunji 3年前
   <h2>前言</h2>    <p>为什么是写哔哩哔哩(俗称B站)呢?其一是因为本人是B站的重度使用者,每周基本上都会在B站上看看火影忍者、暴走大事件等。另外一个原因呢,就是B站首页很美观大方,而且处处充满了细节。所以对于实践确实是一个不错的项目。目前的技术栈主要的采用的是前端Vue2+后端Koa2的前后端分离的方式,语法全部使用ES6/7。关于数据也来自真实的数据接口。</p>    <h2>技术栈</h2>    <p>前端:vue2 + vuex + webpack + ES6/7 + stylus + nginx</p>    <p>后端:koa2</p>    <h2>项目运行</h2>    <p>源码地址: <a href="/misc/goto?guid=4959747982184304088" rel="nofollow,noindex">https://github.com/lybenson/bilibili-vue</a></p>    <p>如何运行</p>    <p>运行前请先安装 nodejs</p>    <p>clone 项目到本地</p>    <pre>  git clone https://github.com/lybenson/bilibili-vue.git</pre>    <p>前端运行</p>    <pre>  cd bilibili-vue  npm install  npm run dev</pre>    <p>后端运行</p>    <pre>  cd bilibili-vue/bilibili-api  npm install  npm run dev</pre>    <p>为了确保运行正确,请先运行后端服务。再运行前端,之后访问 <a href="/misc/goto?guid=4958965640789895086" rel="nofollow,noindex">http://localhost:8080</a></p>    <h2>组件</h2>    <p>根据首页的各模块的功能不同,划分出了共20多个可复用的组件。具体请看下方</p>    <pre>  ├── banner  //轮播组件  │   ├── Banner.vue  │   └── BannerItem.vue  ├── common  // 公共组件  │   ├── BHeader.vue  │   ├── BMenu.vue  │   ├── BMenuItem.vue  │   ├── PostMaterial.vue  │   ├── Search.vue  │   └── TopContainer.vue  ├── content  // 主内容组件  │   └── BContent.vue  ├── contentRow  // 单个分类的组件  │   ├── BContentRow.vue  │   ├── BRowBody.vue  │   ├── BRowHead.vue  │   ├── BRowItem.vue  │   ├── BRowRank.vue  │   └── BRowRankBody.vue  ├── contentTop  // 页面顶部组件  │   ├── BContentTop.vue  │   └── BContentTopItem.vue  ├── live  //直播所在的组件  │   ├── BLive.vue  │   ├── BLiveItem.vue  │   ├── BLiveRank.vue  │   └── BLiveRankItem.vue  ├── nav  //右侧导航条组件  │   ├── BNavSide.vue  │   └── smooth-scroll.js  └── promote  // 推广组件      ├── BPromote.vue      └── BPromoteItem.vue</pre>    <p>组件的原则就是尽量将复杂的UI布局划分成单个小的UI组件,逻辑处理也被划分成更多的单个小的逻辑。数据流动采用的单向数据流动。子组件的数据更多的是来自于父组件,父组件的数据主要是其本身发起的 ajax 请求。本项目中 ajax 请求库使用的是 axios 。</p>    <h2>状态管理</h2>    <p>目前的状态管理采用 vuex 。由于 vuex 可以分多个子 module 。所以在不同模块下单独维护一份状态,同时对于一些公共的状态,比如发起网络请求的 requesting ,错误时的状态 error 则保存在根状态中,之后可以通过子模块中的 rootState.requesting 获取来赋值。</p>    <p>在子模块中发送网络请求获取数据是一个异步的过程,所以将网络请求放在 actions 。每次发起网络需要经历下面的步骤</p>    <ol>     <li> <p>请求中</p> <pre>  rootState.requesting = true  //请求状态更新为true,表示请求中  commit(TYPE.XX_REQUEST)  // 发送同步操作,请求中的数据处理</pre> </li>     <li> <p>请求成功</p> <pre>  rootState.requesting = false  //请求状态更新为false,表示请求结束  commit(TYPE.XX_SUCCESS, response) //发送同步操作,处理请求成功后数据</pre> </li>     <li> <p>请求失败</p> <pre>  rootState.requesting = false  //请求状态更新为false,表示请求结束  commit(TYPE.XX_SUCCESS, response) //发送同步操作,处理请求失败</pre> </li>    </ol>    <h2>动画</h2>    <p>B站首页充斥着大量的动画效果。目前动画使用的主要有三种方式:</p>    <ol>     <li> <p>以 hover 效果触发。</p> </li>     <li> <p>通过 js 触发的效果,如点击轮播图的原点时,主要通过设置css属性 transition: .2s; ,再通过 js 设置css属性 this.$refs.banner.style.marginLeft = left 。</p> </li>     <li> <p>通过 vue 提供的动画方式。</p> <pre>  <transition name="fade">   <div v-if="isSort">       <div class="tip"></div>       <div class="custom-bg"></div>   </div>  </transition></pre> </li>    </ol>    <h2>样式</h2>    <p>样式文件使用的是 stylus ,暂未使用任何 vue 现成的UI组件。需要安装 stylus-loader , stylus ,由于 vue-cli 中的 webpack 已经配置好了 stylus 了,所以只需要安装就可以了。</p>    <pre>  npm install stylus-loader --save-dev  npm install stylus --save-dev</pre>    <h2>性能优化</h2>    <ul>     <li> <p>图片懒加载</p> </li>     <li> <p>压缩 js 、 css</p> </li>     <li> <p>服务器开启 gzip</p> </li>     <li> <p>浏览器缓存</p> </li>     <li> <p>...</p> </li>    </ul>    <h2>发布</h2>    <p>完成项目后将发布到自己的服务器上,首先确保服务器已安装 nodejs ,具体安装步骤不再赘述。</p>    <p>后端发布</p>    <p>后端采用 pm2 做项目管理</p>    <p>安装 pm2</p>    <pre>  npm install pm2 -g</pre>    <p>启动项目</p>    <pre>  cd bilibili-api && npm install   pm2 start index.js</pre>    <p>前端发布</p>    <ol>     <li>webpack 打包</li>    </ol>    <pre>  npm run build</pre>    <p>需要注意的是,直接运行此命令可能会导致资源无法找到的问题。所以需要对 webpack 配置做一定的修改。</p>    <p>在 webpack.base.conf.js 文件中修改 publicPath 如下</p>    <pre>  output: {      path: config.build.assetsRoot,      publicPath: './',  //资源的公共路径      // publicPath: process.env.NODE_ENV === 'production' ? config.build.assetsPublicPath : config.dev.assetsPublicPath,      filename: '[name].js'  }</pre>    <p>这样打包后还会出现 stylus 中 background-image 资源无法找到的问题,我采用的方式修改 ExtractTextPlugin 配置,在 webpack.prod.conf.js 中修改</p>    <pre>  new ExtractTextPlugin('[name].[contenthash].css')</pre>    <p>将分离的 css 打包路径分离到 static 文件夹之外。</p>    <p>打包完成后上传到服务器 /var/www/html/bilibili 目录下。</p>    <ol start="2">     <li> <p>配置nginx服务器。</p> <pre>  location /bilibili {    root /var/www/html;    index index.html;  }</pre> </li>    </ol>    <h2>总结</h2>    <p>目前主要功能都已经完成的差不多。主要还差一个预览视频与弹幕的功能尚未完成,希望能把B站首页写完,并且会持续更新中,后面可能会加上直播等功能。</p>    <p>相关截图:</p>    <p>首页:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/fb850b67fbd9769eacadf7d94278c3ed.png"></p>    <p>轮播:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/ca02fd0fd7471161db497f7d3c21df8f.png"></p>    <p>直播:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/7e583509ff80b1605f22f2fafe3e87d8.png"> <img src="https://simg.open-open.com/show/d3513f362ca3736f6288118e9885937b.png"></p>    <p>排行:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/ec07aa40833a44199ae390346386be67.png"></p>    <p>游戏:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/5fc79cf642484ef8ee429e2a5c574a0c.png"></p>    <p>拖拽排序与滚动效果:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/420e9d774543833d976bcfb58a6c33ec.png"></p>    <p> </p>    <p>项目主页:<a href="http://www.open-open.com/lib/view/home/1493172369974">http://www.open-open.com/lib/view/home/1493172369974</a></p>    <p> </p>