zoukankan      html  css  js  c++  java
  • EasyDSS高性能流媒体服务器前端重构(五)- webpack + vue-router 开发单页面前端实现按需加载

    为了让页面更快完成加载, 第一时间呈现给客户端, 也为了帮助客户端节省流量资源, 我们可以开启 vue-router 提供的按需加载功能, 让客户端打开页面时, 只自动加载必要的资源文件, 当客户端操作页面, 切换功能模块, 触发页面路由变化时, 再去加载相应需要的资源.

    本系列博客的前面几篇一直在讲利用 webpack + vue 开发多页面前端, 然而多页面并不是利剑所指. 本篇将重点介绍使用 vue-router 开发单页面前端, 并且实现按需加载的效果.

    关于 vue-router 的按需加载, 官方的文档点这里, 这篇博客主要是根据文档的内容, 结合实例代码, 按步骤,把需要的操作过一遍, 如果你觉得文档描述不够细节, 可以往下看看.

    下面, 我们基于 blog_4 的代码 , 把它改造成按需加载的单页面.

    安装 vue-router

    npm i vue-router -D

    修改 webpack.config.js 配置

    修改 webpack.config.js, 改造成单页面

    const HtmlWebpackPlugin = require('html-webpack-plugin');
    const CleanWebpackPlugin = require('clean-webpack-plugin');
    const CopyWebpackPlugin = require('copy-webpack-plugin');
    const webpack = require('webpack');
    const path = require('path');
    require("babel-polyfill");
    
    function resolve(dir) {
        return path.resolve(__dirname, dir)
    }
    
    module.exports = {
        //定义页面的入口, 因为js中将要使用es6语法, 所以这里需要依赖 babel 垫片
        entry: {
            index: ['babel-polyfill', './src/index.js']
        },
        output: {
            path: resolve('dist'), // 指示发布目录
            chunkFilename: 'js/[name].[chunkhash:8].js',
            filename: 'js/[name].[chunkhash:8].js' //指示生成的页面入口js文件的目录和文件名, 中间包含8位的hash值
        },
        externals: {
            //video.js 作为外部资源引入
            'video.js': 'videojs'
        },
        //下面给一些常用组件和目录取别名, 方便在js中 import
        resolve: {
            extensions: ['.js', '.vue', '.json'],
            alias: {
                'vue$': 'vue/dist/vue.common.js',
                'jquery$': 'admin-lte/plugins/jQuery/jquery-2.2.3.min.js',
                'src': resolve('src'),
                'assets': resolve('src/assets'),
                'components': resolve('src/components')
            }
        },
        module: {
            //配置 webpack 加载资源的规则
            rules: [{
                test: /.js$/,
                loader: 'babel-loader',
                include: [resolve('src')]
            }, {
                test: /.vue$/,
                loader: 'vue-loader'
            }, {
                test: /.css$/,
                loader: 'style-loader!css-loader'
            },
            {
                test: /.less$/,
                loader: "less-loader"
            },
            {
                test: /.(png|jpe?g|gif|svg)(?.*)?$/,
                loader: 'url-loader?limit=10000&name=images/[name].[hash:8].[ext]'
            },
            {
                test: /.(woff2?|eot|ttf|otf)(?.*)?$/,
                loader: 'url-loader?limit=10000&name=fonts/[name].[hash:8].[ext]'
            },
            {
                test: /.(swf|mp4|webm|ogg|mp3|wav|flac|aac)(?.*)?$/,
                loader: 'url-loader?limit=10000&name=media/[name].[hash:8].[ext]'
            }]
        },
        plugins: [
            //引入全局变量
            new webpack.ProvidePlugin({
                $: 'jquery',
                jQuery: 'jquery',
                "window.jQuery": 'jquery',
                "window.$": 'jquery'
            }),
            new webpack.DllReferencePlugin({
                context: __dirname,
                manifest: require('./dll/vendor-manifest.json')
            }),
            new CopyWebpackPlugin([
                { from: 'dll', ignore: ['template.html', 'vendor-manifest.json'] }
            ]),
            //编译前先清除 dist 发布目录
            new CleanWebpackPlugin(['dist']),
            //生成视频广场首页, 在这个页面中自动引用入口 index --> dist/js/index.[chunkhash:8].js
            //以 src/index.html 这个文件作为模板
            new HtmlWebpackPlugin({
                filename: 'index.html',
                title: '视频广场',
                inject: true, // head -> Cannot find element: #app
                chunks: ['index'],
                template: './dll/template.html',
                minify: {
                    removeComments: true,
                    collapseWhitespace: false
                }
            })
        ]
    };

    只保留一个 entry, 一个 HtmlWebpackPlugin
    在 output 中添加 chunkFilename 属性, 以对按需加载的 js 文件命名

    新建路由文件

    add src/router.js

    import Vue from 'vue'
    import Router from 'vue-router'
    import AdminLTE from 'components/AdminLTE.vue'
    
    import Index from 'components/Index.vue'
    // import Player from 'components/Player.vue'
    const Player = () => import(/* webpackChunkName: 'player' */ 'components/Player.vue')
    const About = () => import(/* webpackChunkName: 'about' */ 'components/About.vue')
    
    Vue.use(Router);
    
    const router = new Router({
        routes: [
            {
                path: '/',
                component: AdminLTE,
                children: [
                    {
                        path: '',
                        component: Index
                    }, {
                        path: 'player',
                        component: Player
                    }, {
                        path: 'about',
                        component: About
                    }
                ]
            }
        ],
        linkActiveClass: 'active'
    })
    
    export default router;

    / –> Inex 直接加载
    /player –> Player 懒加载
    /about –> About 懒加载

    其中, Player 和 About 两个组件以按需加载的方式的引入, 区别于 Index, 注意文件开始部分, import 的写法, 就是 vue-router 官方文档中 懒加载 部分的写法

    改造入口文件

    src/index.js

    import Vue from 'vue'
    import store from 'src/store'
    import router from 'src/router'
    
    new Vue({
      el: '#app',
      store,
      router,
      template: `
      <transition>
        <router-view></router-view>
      </transition>`
    })

    router-view 标签用于占位路由指向的目标组件

    修改 Sider 为路由导航

    components/Sider.vue

    <template>
      <aside id="slider" class="main-sidebar">
        <section class="sidebar">
          <ul class="sidebar-menu">
              <router-link class="treeview" v-for="(item,index) in menus" :key="index" tag="li" :exact="item.path == '/'" :to="item.path">
                <a>
                  <i :class="['fa', 'fa-' + item.icon]"></i>
                  <span>{{item.text}}</span>
                </a>
              </router-link>
          </ul>
        </section>
      </aside>
    </template>
    
    <script>
    export default {
      props: {
        menus : {
            default : () => []
        }
      }
    }
    </script>

    router-link 定义路由导航链接, 这里路由链接渲染为 li > a 的形式, 当前访问路径为 router-link 或者其子路由时, 该 router-link 自动触发为激活状态, 激活状态的 class name 可以通过 linkActiveClass 指定, 我们在前面的创建 router 的时候, 统一将其指定为 active

    如果只想让访问路径严格匹配路由时, 触发为激活状态, 即子路由激活时, 父路由不激活, 需要在父路由上使用 exact 标识. 这个选项, 常用于首页路由 /

    改造 AdminLTE.vue

    将原来的 slot 占位, 替换成 router-view 占位

    <template>
      <div class="wrapper">
        <NaviBar :logoText="logoText" :logoMiniText="logoMiniText"></NaviBar>
        <Sider :menus="menus"></Sider>
        <div class="content-wrapper">
          <section class="content">
            <transition>
              <router-view @btnClick="btnClick"></router-view>
            </transition>
          </section>
        </div>
      </div>
    </template>
    
    <script>
    import "font-awesome/css/font-awesome.css"
    import "admin-lte/bootstrap/css/bootstrap.css"  
    import "admin-lte/dist/css/AdminLTE.css"
    import "admin-lte/dist/css/skins/_all-skins.css"
    
    import "admin-lte/bootstrap/js/bootstrap.js"
    import "admin-lte/dist/js/app.js"
    
    import { mapState } from "vuex"
    import Vue from 'vue'
    
    import Sider from 'components/Sider'
    import NaviBar from 'components/NaviBar'
    
    export default {
      data() {
        return {
        }
      },
      mounted() {
        $(() => {
          $.AdminLTE.layout.fix();
        })
      },
      components: {
        NaviBar, Sider
      },
      computed: {
        //访问 vuex store 中的数据
        //此处用到 es6 stage-2 才有的三个点展开对象的语法, 对应 .babelrc 中的配置
        ...mapState([
          "logoText",
          "logoMiniText",
          "menus"
        ])
      },
      methods: {
        btnClick(msg){
          alert(msg);
        }
      }  
    }
    </script>
    

    运行程序, 看看效果

    npm run start

    懒加载效果

    如上图所示, 当首次点击 [HLS 播放器] 改变路由时, 从 Netwok 观察到加载 player.xxx.js , 表明懒加载开启成功

    代码位置: https://github.com/penggy/easydss-web-src/tree/blog_5

    关于EasyDSS

    EasyDSS商用流媒体服务器解决方案是一套集流媒体点播、转码与管理、直播、录像、检索、时移回看于一体的一套完整的商用流媒体服务器解决方案,EasyDSS高性能RTMP流媒体服务器支持RTMP推流,同步输出HTTP、RTMP、HLS、HTTP-FLV,支持推流分发/拉流分发,支持秒开、GOP缓冲、录像、检索、回放、录像下载、网页管理等多种功能,是目前市面上最合理的一款商用流媒体服务器!

    详细说明:http://www.easydss.com/

    点击链接加入群【EasyDSS流媒体服务器】:560148162

    获取更多信息

    邮件:support@easydarwin.org

    WEB:www.EasyDarwin.org

    Copyright © EasyDarwin.org 2012-2017

    EasyDarwin

  • 相关阅读:
    383. Ransom Note
    598. Range Addition II
    453. Minimum Moves to Equal Array Elements
    492. Construct the Rectangle
    171. Excel Sheet Column Number
    697. Degree of an Array
    665. Nondecreasing Array
    视频网站使用H265编码能提高视频清晰度吗?
    现阶段的语音视频通话SDK需要解决哪些问题?
    企业远程高清会议平台视频会议系统在手机端使用的必备要求有哪些?
  • 原文地址:https://www.cnblogs.com/babosa/p/9217763.html
Copyright © 2011-2022 走看看