高效能流媒體伺服器EasyDSS前端重構(一)-從零開始搭建 webpack + vue + AdminLTE 多頁面腳手架
本文圍繞著實現EasyDSS高效能流媒體伺服器的前端框架來展開的,具體EasyDSS的相關資訊可在:www.easydss.com 找到!
EasyDSS 高效能流媒體伺服器前端架構概述
EasyDSS 高效能流媒體伺服器前端部分最初採用的是 AdminLTE + 各方 jQuery 外掛
的開發方式, 也就是網路上通常講的 bootstrap + jquery plugins
的方式. 有經驗的前端開發者想必都瞭解這種架構下開發前端頁面的痛點. 當一個頁面上 UI 元件多起來的時候, 程式碼組織就容易變得混亂, 各種 $(document).on
穿梭其中. 這樣的頁面開發好以後, 隔一段時間, 再來二次開發, 我去, 簡直了.
為了解決這樣的痛點, 我想重構前端, 引入 vue 的元件化開發模式, 藉助 element-ui 這樣的元件庫, 可以用極少的程式碼, 碼出豐富的功能. 這篇部落格是 EasyDSS 高效能流媒體伺服器前端重構系列部落格的第一篇: 從零開始搭建 webpack + vue + AdmintLTE 多頁尾本架.
安裝前端開發腳手架
首先, 從零搭建 webpack 腳手架. 這裡不借助 vue-cli 工具來生成腳手架, 而是一步步從 npm install 開始到手寫配置指令碼. 因為, 我覺得 vue-cli 一下子生成出來那麼多的配置檔案和目錄, 會讓初學者眼花繚亂, 抓不住重點.
初始化工程目錄
node -v
v6.10.0
npm -v
5.3.0
mkdir easydss-web-src
cd easydss-web-src
npm init -y
安裝基礎包
npm i admin-lte font-awesome vue vuex webpack webpack-dev-server --save-dev
vuex : 用於 vue 元件間的狀態同步
font-awesome : 各種圖示
安裝常用的 webpack loader
npm i file-loader url-loader css-loader less less-loader style-loader vue-loader vue-template-compiler --save-dev
npm i babel-core babel-loader babel-preset-es2015 babel-preset-stage-2 babel-polyfill --save-dev
file-loader : 處理資原始檔, 比如圖片, 字型等
url-loader : 對 file-loader 的封裝, 針對小圖片資源提供 base64 data blob
css-loader : 處理 css 檔案中的 url 等
style-loader : 將 css 插入到頁面的 style 標籤
less-* : 將 less 轉成 css
vue-* : 處理 vue 單檔案元件
babel-* : es6 語法支援, 詳細說明參考阮一峰的 Babel 入門教程
安裝常用的 webpack 外掛
npm i clean-webpack-plugin html-webpack-plugin --save-dev
clean-webpack-plugin : 用來清空釋出目錄
html-webpack-plugin : 用來生成入口頁面, 自動引入生成的 js 檔案
工程目錄結構預覽
首先, 看一下最終的工程目錄結構和執行效果, 做到心中有數. 後面將介紹這些目錄檔案是如何一步步建立或生成的.
easydss-web-src [工程根目錄]
├── .babelrc [babel全域性配置檔案]
├── dist [釋出目錄]
├── package.json
├── package-lock.json
├── src [原始檔目錄]
│ ├── about.js
│ ├── assets [資原始檔目錄]
│ │ └── images [資源圖片]
│ ├── components [元件目錄]
│ │ ├── About.vue
│ │ ├── AdminLTE.vue
│ │ ├── Index.vue
│ │ ├── NaviBar.vue
│ │ └── Sider.vue
│ ├── index.html
│ ├── index.js
│ └── store [狀態管理]
│ └── index.js
└── webpack.config.js [webpack 配置檔案]
執行效果
看上圖, 最終產生兩個頁面 : 視訊廣場 和 版本資訊
兩個頁面, 佈局相同 : 頂部導航 NaviBar, 左側選單 Sider, 中間私有內容區
babel 配置
在工程根目錄下新建檔案 .babelrc
, 內容比較少, 如下:
{
"presets": [
"es2015",
"stage-2"
],
"plugins": []
}
webpack 配置
重頭戲來了, 在工程根目錄下新建檔案 webpack.config.js
, 內容如下:
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-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'],
about: ['babel-polyfill', './src/about.js']
},
output: {
path: resolve('dist'), // 指示釋出目錄
filename: 'js/[name].[chunkhash:8].js' //指示生成的頁面入口js檔案的目錄和檔名, 中間包含8位的hash值
},
//下面給一些常用元件和目錄取別名, 方便在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'
}),
//編譯前先清除 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: './src/index.html',
minify: {
removeComments: true,
collapseWhitespace: false
}
}),
//生成版本資訊頁面, 在這個頁面中自動引用入口 about --> dist/js/about.[chunkhash:8].js
//以 src/index.html 這個檔案作為模板
new HtmlWebpackPlugin({
filename: 'about.html',
title: '版本資訊',
inject: true,
chunks: ['about'],
template: './src/index.html',
minify: {
removeComments: true,
collapseWhitespace: false
}
})
]
};
建立網頁模板檔案
上面 webpack.config.js 中, 我們聲明瞭需要生成兩個頁面, 都是以 src/index.html 作為模板檔案, 實際上我們最終生成的兩個釋出頁面 dist/index.html
和 dist/about.html
就是在這個模板檔案基礎上, 插入 js 入口檔案引用生成出來的(HtmlWebpackPlugin 配置項中的 inject).
下面建立這個模板檔案:
src/index.html
<html>
<head>
<title><%= htmlWebpackPlugin.options.title %></title>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no" name="viewport">
</head>
<body class="skin-green sidebar-mini">
<div id="app"></div>
</body>
</html>
title 部分將會被 HtmlWebpackPlugin 中的 title 替換
宣告 #app div 用來掛載 vue 根元件
建立入口 js 檔案
有了網頁模板檔案, 接下來我們要編寫入口 js 檔案了. 在入口 js 檔案裡面, 我們建立 vue 根元件, 並將它掛載到模板頁面的 #app 上面.
先貼出兩個入口 js 內容, 再作說明.
src/index.js
import Vue from 'vue'
import store from "./store";
import AdminLTE from './components/AdminLTE'
import Index from './components/Index'
new Vue({
el: '#app',
store,
template: `
<AdminLTE>
<Index></Index>
</AdminLTE>`,
components: {
AdminLTE, Index
},
})
src/about.js
import Vue from 'vue'
import store from "./store";
import AdminLTE from './components/AdminLTE'
import About from './components/About'
new Vue({
el: '#app',
store,
template: `
<AdminLTE>
<About @btnClick="btnClick"></About>
</AdminLTE>`,
components: {
AdminLTE, About
},
methods: {
btnClick(msg){
alert(msg);
}
}
})
兩個 vue 根元件, 共同的地方是 :
1. 都引用了 vuex store 狀態管理, 我們用它來儲存各個頁面或元件之間共用的資料;
2. 都引用了 AdminLTE 這個子元件; 實際上在這個子元件裡面, 我們定義了 AdminLTE 的整體佈局, 先是頂部導航和左側選單欄佔位, 然後預留一個 slot 私有內容區域, 用以展示各個頁面不同的內容;
順帶說一下, about 頁面中演示了 父子元件間的資料互動
建立 vuex store
vuex store 中的資料在整個元件樹中共享, 只需要在根元件中引用一個 store. 子元件中通過 mapState, mapGetters, mapMutations, mapActions 訪問和修改. vuex 官方文件傳送門.
這裡, 暫時想到的共享資料僅僅包括 左上角的 logo 和 左側欄的選單資料, 所以我們的 store 檔案很簡單:
store/index.js
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
const store = new Vuex.Store({
state: {
logoText: "EasyDSS",
logoMiniText: "DSS",
menus: [
{
path: "/index.html",
icon: "mouse-pointer",
text: "視訊廣場"
}, {
path: "/about.html",
icon: "support",
text: "版本資訊"
}
]
},
getters : {
},
mutations: {
},
actions : {
}
})
export default store;
建立子元件
- AdminLTE.vue
引入 adminlte 樣式和指令碼檔案, 指定介面佈局, 預留 slot 內容區
components/AdminLTE.vue
<template>
<div class="wrapper">
<NaviBar :logoText="logoText" :logoMiniText="logoMiniText"></NaviBar>
<Sider :menus="menus"></Sider>
<div class="content-wrapper">
<section class="content">
<slot></slot>
</section>
</div>
</div>
</template>
<script>
import "font-awesome/css/font-awesome.min.css";
import "admin-lte/bootstrap/css/bootstrap.min.css";
import "admin-lte/dist/css/AdminLTE.min.css";
import "admin-lte/dist/css/skins/_all-skins.css";
import "admin-lte/bootstrap/js/bootstrap.min.js";
import "admin-lte/dist/js/app.js";
import { mapState } from "vuex"
import Vue from 'vue'
import Sider from './Sider'
import NaviBar from './NaviBar'
export default {
data() {
return {
}
},
components: {
NaviBar, Sider
},
computed: {
//訪問 vuex store 中的資料
//此處用到 es6 stage-2 才有的三個點展開物件的語法, 對應 .babelrc 中的配置
...mapState([
"logoText",
"logoMiniText",
"menus"
])
}
}
</script>
- NaviBar.vue
頂部導航元件, 主要是 logo 和 選單欄的 toggle, 資料從 AdminLTE 元件傳入
components/NaviBar.vue
<template>
<header class="main-header">
<a href="index.html" class="logo">
<span class="logo-mini">{{logoMiniText}}</span>
<span class="logo-lg">{{logoText}}</span>
</a>
<nav class="navbar navbar-static-top">
<a class="sidebar-toggle" data-toggle="offcanvas" role="button">
<span class="sr-only">Toggle navigation</span>
</a>
</nav>
</header>
</template>
<script>
export default {
props: {
logoText: {
default: "AdminLte"
},
logoMiniText: {
default: "AD"
}
}
}
</script>
- Sider.vue
左側選單欄元件 , 選單資料從 AdminLTE 元件傳入, 通過比較瀏覽器位址列 path , 決定 active 選單項
components/Sider.vue
<template>
<aside id="slider" class="main-sidebar">
<section class="sidebar">
<ul class="sidebar-menu">
<li :class="['treeview', path == item.path ? 'active' : '']" v-for="(item,index) in menus" :key="index">
<a :href="item.path">
<i :class="['fa', 'fa-' + item.icon]"></i>
<span>{{item.text}}</span>
</a>
</li>
</ul>
</section>
</aside>
</template>
<script>
export default {
props: {
menus : {
default : () => []
}
},
computed: {
path(){
return location.pathname;
}
}
}
</script>
- Index.vue
首頁內容區
components/Index.vue
<template>
<div class="container-fluid no-padding">
<div class="alert alert-success">{{msg}}</div>
</div>
</template>
<script>
export default {
data() {
return {
msg : "我是視訊廣場"
}
}
}
</script>
- About.vue
版本資訊內容區
components/About.vue
<template>
<div class="container-fluid no-padding">
<button class="btn btn-success" @click.prevent="btnClick">{{btnText}}</button>
</div>
</template>
<script>
export default {
props: {
btnText : {
type : String,
default : ""
}
},
methods: {
btnClick(){
this.$emit("btnClick", "hello");
}
}
}
</script>
<style lang="less" scoped></style>
執行和編譯
編輯 package.json
, 新增執行和編譯指令碼指令, 留意其中的 scripts > build, start
{
"name": "easydss-web-src",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "webpack --progress --hide-modules",
"start": "webpack-dev-server --open",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"admin-lte": "^2.3.11",
"babel-core": "^6.26.0",
"babel-loader": "^7.1.1",
"babel-polyfill": "^6.26.0",
"babel-preset-es2015": "^6.24.1",
"babel-preset-stage-2": "^6.24.1",
"clean-webpack-plugin": "^0.1.16",
"css-loader": "^0.28.5",
"file-loader": "^0.11.2",
"font-awesome": "^4.7.0",
"html-webpack-plugin": "^2.30.1",
"less": "^2.7.2",
"less-loader": "^4.0.5",
"style-loader": "^0.18.2",
"url-loader": "^0.5.9",
"vue": "^2.4.2",
"vue-loader": "^13.0.4",
"vue-template-compiler": "^2.4.2",
"vuex": "^2.3.1",
"webpack": "^3.5.5",
"webpack-dev-server": "^2.7.1"
}
}
命令列執行 :
npm run start #自動開啟瀏覽器, 檢視頁面效果
npm run build #生成釋出檔案到 dist 目錄
總結
以上, 我們從零開始, 建立了一個 webpack + vue + AdminLTE 多頁面工程的腳手架. 在此基礎上可以體驗 vue 元件化前端開發的簡潔和高效了.
後續部落格計劃:
EasyDSS高效能流媒體伺服器前端重構(二): webpack + vue + AdminLTE 多頁面提取共用檔案, 優化編譯時間
EasyDSS高效能流媒體伺服器前端重構(三): webpack + vue + AdminLTE 多頁面引入 element-ui
EasyDSS高效能流媒體伺服器前端重構(四): webpack + video.js 打造流媒體伺服器前端
獲取更多資訊
Copyright © EasyDarwin.org 2012-2017
相關推薦
高效能流媒體伺服器EasyDSS前端重構(一)-從零開始搭建 webpack + vue + AdminLTE 多頁面腳手架
本文圍繞著實現EasyDSS高效能流媒體伺服器的前端框架來展開的,具體EasyDSS的相關資訊可在:www.easydss.com 找到! EasyDSS 高效能流媒體伺服器前端架構概述 EasyDSS 高效能流媒體伺服器前端部分最初採用的是 A
從零開始搭建Electron+Vue+Webpack專案框架,一套程式碼,同時構建客戶端、web端(一)
摘要:隨著前端技術的飛速發展,越來越多的技術領域開始被前端工程師踏足。從NodeJs問世至今,各種前端工具腳手架、服務端框架層出不窮,“全棧工程師”對於前端開發者來說,再也不只是說說而已。在NodeJs及其衍生技術高速發展的同時,Nw和Electron的問世,更是為前端發展提速不少,依稀記得哪位前輩說過,“能
【原創】從零開始搭建Electron+Vue+Webpack專案框架,一套程式碼,同時構建客戶端、web端(二)
導航: (一)Electron跑起來(二)從零搭建Vue全家桶+webpack專案框架(三)Electron+Vue+Webpack,聯合除錯整個專案(未完待續)(四)Electron配置潤色(未完待續)(五)預載入及自動更新(未完待續)(六)構建、釋出整個專案(包括client和web)(未完待續) 摘要:
EasyDSS高效能流媒體伺服器前端重構(四): webpack + video.js 打造流媒體伺服器前端
video.js 介紹 Video.js - open source HTML5 & Flash video player 作為一款高效能流媒體伺服器的前端, 必不可少會用到流媒體播放器. 在播放器的選擇上, 我們選中了功能強大並且開源的 video
EasyNVR流媒體伺服器網頁相容除錯:ie瀏覽器下的介面呼叫成功但頁面無法顯示實時的資料
許多問題很難在開發的過程中就想的面面俱到,都是在實際應用、除錯的過程中一一的優化的。由於easynvr的受眾越來越多,因此也出現了好多在開發之初並沒有留意的一些細節。我這次發現的問題就是給客戶遠端解決問題過程中發現的。在此記錄下來方便自己,也方便大家瞭解。
Vue + Spring Boot從零開始搭建個人網站(一) 之 專案前端Vue.js環境搭建
前言: 最近在考慮搭建個人網站,想了想決定採用前後端分離模式 前端使用Vue,負責接收資料 後端使用Spring Boot,負責提供前端需要的API 就這樣開啟了我邊學習邊實踐之旅 Vue環境搭建步驟: 1、安裝node.js
教你從零開始搭建一款前端腳手架工具
寫於 2016.08.06 本文系原創,轉載請附帶作者資訊:Jrain Lau 專案地址:github.com/jrainlau/sc… 前言 在實際的開發過程中,從零開始建立專案的結構是一件讓人頭疼的事情,所以各種各樣的腳手架工具應運而生。筆者使用較多的yoeman,express
從零開始搭建一個簡易的伺服器(一)
前言 其實大家大可不必被伺服器這三個字嚇到,一個入門級後端框架,所需的僅僅是HTTP相關的知識與應用這些知識的程式設計工具。據本人的經驗,絕大多數人擁有搭建後端所涉及到的基礎理論知識,但是缺乏能將之應用出去的工具,而本文即是交給讀者這樣一個工具,並能夠運用之來
Spring Boot+Vue從零開始搭建系統(一):專案前端_Vuejs環境搭建
2.驗證Node.js是否安裝好,在windows下,win+r召喚出執行視窗,輸入cmd開啟命令列視窗。輸入node -v即可得到對應的Node.js版本。 npm包管理器是整合在Node.js中了,所以在安裝Node.js的時候就已經自帶了npm,輸入npm -v可得
從零開始搭建騰訊雲伺服器 (一)
本篇博文旨在將近期搭建雲伺服器的步驟記錄下來。 1、定義 雲伺服器是一種簡單高效、安全可靠、處理能力可彈性伸縮的計算服務。其管理方式比物理伺服器更簡單高效。使用者無需提前購買硬體,即可迅速建立或釋放任意多臺雲伺服器。雲伺服器幫助您快速構建更穩定、安全的應用,降低開發運
Windows環境下,從零開始搭建Nodejs+Express+Ejs框架(一)---安裝nodejs
直接 分享圖片 完成 info pre download png 安裝包 get 第一步,安裝nodejs https://nodejs.org/en/download/ 這個是nodejs的官網,由於操作系統是win7 64位的,所以,我下載的是node-v8.11.1-
從零開始搭建自己的VueJS2.0+ElementUI單頁面網站(一、環境搭建)
如圖所示 增刪改 type default sdn orm rain exp 名稱 原網址:https://blog.csdn.net/u012907049/article/details/72764151 前言 VueJS可以說是近些年來最火的前端框架之一,越來越多的
從零開始搭建linux下laravel 5.6環境(一)
yum acad 分享圖片 tps .html 啟動 服務 all 從零開始 首先你需要有一臺linux服務器,或者虛擬機,這裏就不贅述了,不會的可以自行百度。 我這裏準備的是一臺騰訊雲服務器,系統為CentOS 7.4 64位。 你可以使用騰訊雲的登錄按鈕登錄到服務器 也
從零開始搭建騰訊雲伺服器
本篇博文旨在將近期搭建雲伺服器的步驟記錄下來。 1、定義 雲伺服器是一種簡單高效、安全可靠、處理能力可彈性伸縮的計算服務。其管理方式比物理伺服器更簡單高效。使用者無需提前購買硬體,即可迅速建立或釋放任意多臺雲伺服器。雲伺服器幫助您快速構建更穩定、
前端之路從零開始——第二週第二天筆記(盒子模型)
目錄 1.盒子模型的初步瞭解 2.盒子模型型別:標準盒子模型和IE盒子模型 盒子模型的計算公式 3.標準模式下的盒模型 4.怪異模式下的盒模型 5.padding詳解 6.border詳解 利用border屬性製作三角形 7.marg
前端之路從零開始——第二週第四天筆記(background)
目錄 1.background-color背景色的詳解 2.background-image背景圖的詳解 3.background-repeat背景重複的詳解 4.background-attachment背景是否滾動的設定 5.background-position背景定位的詳解
前端之路從零開始——第二週第五天筆記(css屬性)
目錄 1.CSS color 顏色 2.CSS font 3.CSS text文字 4.文字裝飾類(Text-Decoration) 5.CSS Table 表格 6.CSS outline 輪廓 7.css的繼承性 8.css的層疊性 9.css常用單位總結:em,r
從零開始搭建物聯網平臺(7):使用Vue編寫前端頁面
摘要: Vue我也是剛開始學的,看了兩天的文件就開始著手做這件事了,所以對vue瞭解不太深入,沒有能力說的的太詳細萬一是錯誤的不就誤導別人了,所以只對幾個相對來說比較主要的點說明一下。 搭建開發環境: 老生常談的話題!首先自然是要安裝nodejs,這個直接去官網下載安裝即可,再使用命令n
從零開始搭建物聯網平臺(5):搭建後臺服務(一)
資料庫的設計: 後臺使用Django web框架實現,Django和python怎麼用就不介紹了,東西太多了,看完下面的這些部落格就可以了,差不多就夠了https://www.cnblogs.com/wupeiqi/articles/4938499.html 資料庫設計: &
vs code 第一次建立前端專案 vuejs 從零開始
2018年12月5日 第一階段 雖然網上教程很多,但是還是記錄一次完整的步驟 1.安裝nodejs,網上一堆的教程,基本上下載後傻瓜式一路next 2.安裝npm,網上一堆的教程,也是基本下載後傻瓜式一路next 3.安裝完成執行cmd,檢視是否安裝成功 4.安裝cnpm 由於有些npm有些