Vue.js 实战系列之实现视频类WebApp的项目开发——20. 优化代码整体结构与打包发布

如果想看该实战系列的其他内容,请移步至 Vue.js 实战系列之实现视频类WebApp的项目开发

项目仓库地址,欢迎 Star


代码结构优化

  1. 公共组件的提取封装

    目前比较流行组件化开发,组件化开发的好处:方便我们在各个不同的项目中复用代码。当然,我们在项目开发中也一直不断的封装组件来使用,在这里总结一下如何完整的封装一个组件来使用:

    1. 建立组件的模板,先把架子搭起来,写写样式,考虑好组件的基本逻辑。
    2. 准备好组件的数据输入。即分析好逻辑,定好 props 里面的数据、类型。
    3. 准备好组件的数据输出。即根据组件逻辑,做好要暴露出来的方法。
    4. 封装完毕了,直接在其他页面调用即可。

    关于组件的创建使用可以看一下:13. 自定义全局弹出框组件的实现 就明白了如何创建封装一个组件了。

  2. 引入 Vuex 实现数据共享

    Vuex 是一个专门为 Vue.js 应用程序开发的状态管理模式,它采用集中式存储管理所有组件的公共状态,并以相应的规则保证状态以一种可预测的方式发生变化。

    Vuex 的优点:

    1. Vuex 可以保存数组、对象、或者嵌套结构,不用 toString
    2. 双向绑定,使用 commit 修改一处状态后,所有引用的地方自动更新,不需要重新取值
    3. 可以自定义数据过滤方法、取值方法、逻辑判断等
    4. 可以在 Vuex 里封装 Ajax 下·请求,外部只负责调用数据

    关于这一部分的优化使用,可以看一下:12. 引入Vuex实现数据管理以及登录流程的实现

  3. Vue 公共样式处理

    在项目中我们有一些公共样式是一样的,我们可以对这些样式进行提取,然后在我们需要的地方引入即可,也可以将部分公共样式放到 App.vue 中。

    比如:弹出动画的css相同,提取一个公共动画样式

    1. src/common/style 目录下, 新建 common.less
    .up-enter-active, .up-leave-active {
        transition: all .5s;
     }
    .up-enter, .up-leave-to /* .fade-leave-active below version 2.1.8 */ {
        opacity: 1;
        transform: translateY(100%);
    }
    
    1. 然后在需要用到的文件中引入
    <style lang="less" scoped>
    @import "../common/styles/common.less";
    </style>
    
  4. Vue 路由拆分

    当我们项目的路由文件 index.js 内配置特别多以及多人同时开发时将面临如下问题:

    1. 文件冲突
    2. 文件内容庞大 不利于优化

    此时我们可以对路由 index.js 进行拆分,将 index.js 拆分为如下结构:

    index.js 路由创建
    routers.js 页面路由配置
    module  路由模块
    	home.js 主页面路由
    	sign.js 登录页面路由
    	publish.js 发布页面路由
    

    通过如下步骤的拆分,这样就避免了如上问题,以后再配置新的路由 就很简单了。

    模块里的页面配置还是之前的相同配置,只不过将这些内容提取出来变成一个个模块来导入使用。

    具体代码如下:

    src/router/index.js

    import Vue from 'vue';
    import VueRouter from 'vue-router';
    import routes from './routers';
    
    Vue.use(VueRouter);
    
    const router = new VueRouter({
      mode: 'history',
      base: process.env.BASE_URL,
      routes,
    });
    
    // 解决重复点击导航时,控制台出现报错
    const VueRouterPush = VueRouter.prototype.push;
    VueRouter.prototype.push = function push(to) {
      return VueRouterPush.call(this, to).catch(err => err);
    };
    
    // 设置登录权限,用户未登录时需要前往登录
    router.beforeEach((to, from, next) => {
      const { meta: { requiresAuth } } = to;
      // 获取当前用户是否登录
      console.log(to, from);
      const isLogin = sessionStorage.getItem('isLogin');
      if (requiresAuth && !isLogin) {
        next({ path: '/sign' });
      } else {
        next();
      }
    });
    
    export default router;
    

    src/router/routers.js

    … 为ES6扩展运算符

    import home from './module/home';
    import sign from './module/sign';
    import publish from './module/publish';
    import edit from './module/edit';
    
    const routes = [
        {
            path: '/',
            redirect: '/index/recommend',
        },
        {
            path: '/index',
            redirect: '/index/recommend',
        },
        ...home,
        ...sign,
        ...publish,
        ...edit,
    ];
    
    export default routes;
    

    src/router/module/home.js

    import Home from '@/views/Home.vue';
    
    const home = [
        {
            path: '/',
            name: 'Home',
            component: Home,
            children: [
                {
                    path: '/index',
                    name: 'index',
                    component: () => import(/* webpackChunkName: "index" */ '@/views/index/index.vue'),
                    children: [
                        {
                            path: 'follows',
                            name: 'follows',
                            component: () => import(/* webpackChunkName: "follows" */ '@/views/follow/index.vue'),
                            children: [
                                {
                                    path: 'reVideoList',
                                    name: 'reVideoList',
                                    component: () => import(/* webpackChunkName: "VideoList" */ '@/common/components/videoList/VideoList.vue'),
                                },
                            ],
                        },
                        {
                            path: 'recommend',
                            name: 'recommend',
                            component: () => import(/* webpackChunkName: "recommend" */ '@/views/recommend/index.vue'),
                            children: [
                                {
                                    path: 'reVideoList',
                                    name: 'reVideoList',
                                    component: () => import(/* webpackChunkName: "VideoList" */ '@/common/components/videoList/VideoList.vue'),
                                },
                            ],
                        },
                    ],
                },
                {
                    path: '/friends',
                    name: 'friends',
                    component: () => import(/* webpackChunkName: "friends" */ '@/views/friends/index.vue'),
                },
                {
                    path: '/news',
                    name: 'news',
                    component: () => import(/* webpackChunkName: "news" */ '@/views/news/index.vue'),
                    meta: {
                        requiresAuth: true, // 是否需要登录权限
                    },
                },
                {
                    path: '/mine',
                    name: 'mine',
                    component: () => import(/* webpackChunkName: "mine" */ '@/views/mine/index.vue'),
                    meta: {
                        requiresAuth: true, // 是否需要登录权限
                    },
                },
            ],
        },
    ];
    
    export default home;
    

    src/router/module/sign.js

    const sign = [
        {
            path: '/sign',
            name: 'Sign',
            component: () => import(/* webpackChunkName: "sign" */ '@/views/Sign.vue'),
        },
        {
            path: '/codeSign',
            name: 'codeSign',
            component: () => import(/* webpackChunkName: "code" */ '@/views/Code.vue'),
        },
    ];
    
    export default sign;
    

    src/router/module/edit.js

    const edit = [
        {
            path: '/edit',
            name: 'edit',
            component: () => import(/* webpackChunkName: "edit" */ '@/views/mine/editInfo.vue'),
        },
        {
            path: '/update',
            name: 'update',
            component: () => import(/* webpackChunkName: "edit" */ '@/views/mine/updateInfo.vue'),
        },
    ];
    
    export default edit;
    

    src/router/module/publish.js

    const publish = [
        {
            path: '/publish',
            name: 'publish',
            component: () => import(/* webpackChunkName: "publish" */ '@/views/publish/index.vue'),
        },
    ];
    
    export default publish;
    

    注意:我们使用 ESLint + Standard 代码规范,在进行模块成员导出时,请使用 export default 的方式导出,使用 import xx from '@/xxx 的方式导入,具体使用如上。


打包与部署

经过前面章节的开发,我们完成了 vue实战项目的全部内容,下面我们将进行项目打包与部署。

我们在使用 Vue 做前后端分离项目时,通常前端是单独部署,用户访问的也是前端项目地址,因此前端开发人员很有必要熟悉一下项目部署的流程与各类问题的解决办法了。

其实 Vue 项目打包部署本身不复杂,不过对于服务器接触不多,但是实际工作过程中一般是不需要我们前端人员进行部署的,所以这里只需要了解一下项目是如何部署的就可以了。

默认情况下,使用 vue-cli 创建的项目,package.json 里的 script 应该已经配置了 build 指令,直接执行 yarn build 或者 npm run build 即可。

yarn build
OR
npm run build
// 以上两个指令最终运行的代码是 vue-cli-service build

我们的项目一般是通过 nginx 进行转发的,nginx 的转发规则是需要配置上下文的,为了解决这个问题,我们需要对 vue.config.jsenv.productionenv.development 以及 router 下的 index 进行修改

  1. vue.config.js

    module.exports = {
    	// 设置打包文件输出路径
    	outputDir: process.env.NODE_ENV === 'production' ?  'dist': 'dy' ,
    	// 生产环境是否生成SourceMap
    	productionSourceMap: false, 
    	// 资源访问路径
    	publicPath: process.env.VUE_APP_NGINX_CONTENT,
    }
    
  2. env.production

    NODE_ENV="production";
    # 是否开启移动端调试
    VUE_APP_ERUDA=false
    BASE_URL='/'
    VUE_APP_BASE_API="/prod-api"
    # nginx 上下文
    VUE_APP_NGINX_CONTENT = '/'
    
  3. env.development

    NODE_ENV="development";
    BASE_URL='/'
    # 是否开启移动端调试
    VUE_APP_ERUDA=true
    VUE_APP_BASE_API="/dev-api"
    
  4. router/index.js

    const router = new VueRouter({
      mode: 'history',
      // base: process.env.BASE_URL,
      base: process.env.VUE_APP_NGINX_CONTENT,
      routes,
    });
    

项目开发完成需要部署时,都需要将接口等配置文件更新成服务器地址,然后打包发布部署就可以了。


测试打包代码

上面我们对 Vue 项目进行打包以及线上地址的配置,打包完成后我们通常需要在本地进行测试一下,然后再放到服务器上,以免将有问题的代码部署到服务器上。

  1. 将代码打包

    上面我们以及打包过了,不再赘述

    yarn build
    
  2. 根目录下新建 app.js 文件

  3. 配置 app.js 文件

    var express = require('express');
    var fs = require('fs');
    var http = require('http');
    var app = express();
    app.use(express.static('./dy'));
    app.use(function (req, res,next) {
      res.sendFile('./dy/index.html');  //路径根据自己文件配置
    });
    var httpsServer = http.createServer(app);
    httpsServer.listen(8888, function () {
      var host = '127.0.0.1';
      var port = httpsServer.address().port;
      console.log('app listening at http://%s:%s', host, port);
    });
    
  4. 运行 app.js

    node app.js
    // => app listening at http://127.0.0.1:8888
    
  5. 在浏览器上访问该地址即可。
    在这里插入图片描述
    在这里插入图片描述


至此,大功告成!


上一章节: 19. 发布页面的实现(摄像头调用,视频录制等功能)

下一章节: 21. 项目总结

项目整体介绍:Vue.js 项目实战之实现视频播放类WebApp的项目开发(仿抖音app)


项目仓库地址,欢迎 Star。

有任何问题欢迎评论区留言讨论。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值