3.2 新建示例工程
当我们准备好了开发工具及开发环境后,接下来需要建立一个HTML5示例工程来详细阐述WebRTC技术在Web上的应用。示例采用React作为UI展示,所以你需要了解以下基础知识。
·React:掌握React的状态控制、属性传递以及组件创建等。
·AntDesign:AntDesign为React的一个UI框架,这里主要用来进行界面布局及组件展示。
·Node:Node主要作为程序的运行环境,需要了解npm及package.json配置等。
·Webpack:React工程配置打包工具。
·JavaScript:React使用的编程语言,需要了解ES6语法及规范,如箭头函数的使用方法。
·CSS:界面布局及细节展示使用。
·HTML:HTML标签使用,尤其是Video、Audio的使用。
首先,新建一个工程目录,命名为h5-samples,按照如下所示创建文件及目录。
├── README.md(项目说明) ├── configs(配置文件目录) │ ├──server.crt(证书文件) │ └──server.key (证书Key) ├── dist(build后生成文件目录) ├── package.json(项目描述及库引用文件) ├── .bablelrc(bable配置) ├── src(示例源码) │ ├── App.jsx(主组件) │ ├── Camera.jsx(摄像头示例) │ ├── Microphone.jsx(麦克风示例) │ └── index.jsx(首页) ├── styles(样式目录) │ └── css(css目录) │ ├── canvas.scss(画板样式) │ ├── record.scss(录制样式) │ └── styles.scss(全局样式) └── webpack.config.js(打包配置文件)
其中,src及styles/css目录为示例源码及样式目录,这里暂时不需要添加文件,随着示例的创建会逐步添加。
configs目录下的两个文件为证书相关文件,可以使用源码中提供的文件,正式发布项目需要申请商业证书。使用证书的原因是WebRTC技术需要使用HTTPS安全协议才能正常使用。
dist目录为存放打包后生成文件的目录,你可以使用npm build命令打包示例工程,然后把dist目录下的文件部署至Nginx下即可发布。开发测试阶段只需要使用npm start命令启动一个本地HTTPS服务即可。
3.2.1 package.json配置
首先,在工程目录下新建package.json文件,此文件的作用有以下几点:
·工程描述:包括工程名称、作者、版本、项目描述以及关键字等。
·项目脚本:如npm start表示启动项目。
·开发依赖库:项目开发中使用到的依赖库。
·生产依赖库:项目开发完成后发布使用到的依赖库。
完整的配置信息如下所示。
{ //项目名称 "name": "h5-samples", //版本号 "version": "0.0.1", //项目描述 "description": "h5 webrtc samples", "main": "src/index.jsx",//入口程序 "scripts": { //可使用npm build命令构建打包程序 "build": "webpack --mode=production --config webpack.config.js", //可使用npm start命令启动程序 "start": "webpack-dev-server --config ./webpack.config.js --mode development --open --https --cert ./configs/server.crt --key ./configs/server.key" }, //作者 "author": "kangshaojun", //授权 "license": "MIT", //开发库 "devDependencies": { //语法转换库,如ES6转ES5 "@babel/core": "^7.4.3", "@babel/plugin-proposal-class-properties": "^7.4.4", "@babel/plugin-transform-runtime": "^7.4.4", "@babel/preset-env": "^7.4.3", "@babel/preset-react": "^7.0.0", "@babel/runtime": "^7.4.4", "babel-loader": "^8.0.5", "babel-plugin-import": "^1.13.0", //CSS加载器 "css-loader": "^3.2.0", //webpack文本插件 "extract-text-webpack-plugin": "^4.0.0-beta.0", //node使用sass库 "node-sass": "^4.9.2", //sass加载库 "sass-loader": "^7.0.3", //样式加载器 "style-loader": "^0.23.1", //打包工具 "webpack": "^4.30.0", "webpack-cli": "^3.3.1", "webpack-dev-server": "^3.3.1", //文件拷贝插件 "copy-webpack-plugin": "^5.0.5" }, //引用库 "dependencies": { //ant desgin组件 "antd": "^4.1.1", //文件拷贝插件 "copy-webpack-plugin": "^5.0.5", //react使用的mdi图标库 "mdi-react": "^6.4.0", //react相关库 "react": "^16.8.6", "react-dom": "^16.8.6", "react-mdi": "^0.5.7", "react-router-dom": "^5.1.2", "reactjs-localstorage": "0.0.8" }, //关键字 "keywords": [ "h5", "webrtc", "js" ] }
你可以查询此项目中用到的开发库的作用是什么,尽量做到精简,如果依赖的库过多,会增加项目的复杂度。
package.json文件的本质就是一个json文件,不是代码文件,所以不能在上面添加“//”注释,这里添加注释的目的是解释每一个配置项的作用,实际使用时需要去掉这些注释。
如果想增加一个库,以react为例,可以使用如下命令进行安装。其中@16.8.6为react的版本,如果不指定,则安装的是最新版本。--save表示要保存至package.json中。
npm install react@16.8.6 --save
如果想卸载一个库,以react为例,可以使用如下命令进行卸载。--save表示将react库的引用从package.json中去除。
npm uninstall react@16.8.6 --save
当准备好package.json文件后,使用npm install命令安装所有依赖库,安装完成后会在项目根目录下生成一个node_modules文件夹,如图3-4所示。
图3-4 node_modules文件夹
一定不要在node_modules里手动添加或删除库文件,而是要使用npm命令来维护项目依赖。如果手动添加库文件,当使用npm install命令后会把手动添加的库文件移除。
scripts配置下有两个配置项作用,如下所示。
·build:使用npm build命令可以打包构建应用程序,打包后可以进行程序发布。
·start:使用npm start命令可以启动一个HTTPS服务,方便程序调试开发。
其中,npm build命令调用了webpack,关于webpack的配置及使用后面会有详细介绍。npm start命令调用了webpack-dev-server,可以指定参数启动一个HTTPS的服务,复制如下两个文件至configs文件夹中。
./configs/cert.pem ./configs/key.pem
3.2.2 babel支持
babel是一种JavaScript语法编译器,在前端开发过程中,由于浏览器的版本和兼容性问题,很多JavaScript的新方法和特性都受到了使用限制。使用babel可以将代码中JavaScript代码编译成兼容大多数主流浏览器的代码。
进入项目根目录添加.babelrc文件,添加如下代码即可。注意文件名前需要添加一个点。
{ //预制套件 "presets": [ //处理转译需求 "@babel/preset-env", //处理react "@babel/preset-react" ], //插件 "plugins": [ "@babel/plugin-transform-runtime", "@babel/plugin-proposal-class-properties", ["import", { "libraryName": "antd", "libraryDirectory": "es", "style": "css" }] ] }
3.2.3 webpack配置
webpack本质上是一个现代JavaScript应用程序的静态模块打包器(bundler)。webpack处理应用程序时,会递归地构建一个依赖关系图,其中包含应用程序需要的每个模块,然后将这些模块打包成一个或多个bundler。webpack的核心概念及配置项请参考https://www.webpackjs.com/concepts/文档。
进入项目根目录后,添加webpack.config.js文件,添加如下完整配置。
//引用webpack const webpack = require('webpack'); //模块导出 module.exports = { //入口文件 entry: './src/index.jsx', //开发调试时可以看到源码 devtool: 'source-map', //模块 module: { //规则 rules: [ //加载js|jsx源码文件 { test: /\.(js|jsx)$/, exclude: /node_modules/, use: ['babel-loader'] }, //加载scss|less|css等样式文件 { test: /\.(scss|less|css)$/, use: ['style-loader', 'css-loader', 'sass-loader'] }, ] }, //配置如何寻找模块所对应的文件 resolve: { //寻找所有js、jsx文件 extensions: ['*', '.js', '.jsx'] }, //输出文件配置 output: { //输出路径 __dirname表示当前目录 path: __dirname + '/dist', //公共路径为项目根目录 publicPath: '/', //打包后输出文件名 filename: 'samples.js' }, //webpack插件 plugins: [ //热加载插件 new webpack.HotModuleReplacementPlugin(), ], //开发服务器配置 devServer: { //加载内容目录 contentBase: './dist', //是否热加载 hot: true, //加载IP地址 host: '0.0.0.0', } };
其中,entry:'./src/index.jsx'为项目的入口文件,一定要命名为index.jsx。dist目录为项目打包生成的文件存放的目录。打包后输出的文件名为samples.js,这个文件和dist/index.html里引用的js文件是一一对应的。另外,注意devtool:'source-map',加上此配置的目的是当我们需要在浏览器里调试React程序时可以看到其源码,从而可以进行断点调试。如图3-5所示,在Chrome浏览器的程序调试窗口里,代码的第26行被打上了断点。
图3-5 Chrome断点示意图
3.2.4 首页模板文件
配置好webpack后就可以打包应用了,打包后的文件为一个js文件。需要添加一个首页把它引入才能生效。打开项目根目录下的dist目录添加index.html文件。添加如下代码。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>H5 WebRTC Samples</title> </head> <body> <!-- 此处一定要指定id,react组件渲染在App这个div里 --> <div id="app" style="height:100%"></div> <!-- 引入打包后的js文件 --> <script src="samples.js"></script> </body> </html>
这里的id为App的div,一定要添加,react的根组件是渲染在这个div里,如果没有它,react的内容显示不出来。另外,samples.js是webpack打包后生成的js文件,需要引入,这个文件名和webpack.config.js里输出的文件名一一对应。这时还不能使用npm build命令来生成samples.js文件,因为react的入口文件还没有添加,执行命令会报错,导致打包不成功。
3.2.5 全局样式
全局样式中提供了一些默认样式,如视频的默认大小、背景色等。打开根目录下的styles/css/styles.scss文件,添加如下代码。
//html样式 html { //垂直方向滚动 overflow-y: scroll; } //body样式 body { //字体加粗 font-weight: 300; //文字自动换行 word-break: break-word; } //标题1 h1 { border-bottom: 1px solid #ccc; font-family: 'Roboto', sans-serif; font-weight: 500; font-size: 22px; } //标题2 h2 { color: #444; font-weight: 500; } //标题3 h3 { border-top: 1px solid #eee; color: #666; font-weight: 500; margin: 10px 0 10px 0; white-space: nowrap; } //主容器 .container { //左右居中 margin: 0 auto 0 auto; //最大宽度 max-width: 600px; padding: 10px 0px 10px 0px; } //视频默认样式 .video { //背景色 background: #222; margin: 0 0 20px 0; //宽高值,宽高比为4:3 width: 640px; height: 480px; } //画布默认样式 .canvas { background-color: #ccc; //宽高值,宽高比为4:3 width: 640px; height: 480px; } //错误警告样式 .warning { color: red; fontv-weight: 400; }
视频界面和画布默认大小是640×480,这是一个4:3的宽高比,还可以采用16:9的宽屏比例,如640×360。
样式采用scss的原因是当我们在开发调试时,每次修改文件后保存会立即刷新样式,而不需要每次都从首页点进来测试,从而提高开发效率。
3.2.6 入口文件
入口文件为React程序的第一个jsx文件,主要作用是引入全局样式、主组件以及将主组件渲染至首页里。打开项目根目录下的src目录添加index.jsx文件。添加如下代码。
import React from "react"; import ReactDOM from "react-dom"; //导入主组件 import App from "./App"; //导入antd样式 import "antd/dist/antd.css"; //导入全局样式 import "../styles/css/styles.scss"; //将根组件App渲染至首页div里 ReactDOM.render( <App />, document.getElementById("app"));
这里引入的是全局的样式,当某个组件里如果引入了局部样式,则会覆盖全局样式。
3.2.7 主组件及路由
打开src目录,添加App.jsx及Samples.jsx文件。首先来看App.jsx的作用,它就是用程序的根组件,里面主要用来配置全局路由,如摄像头示例的路由、麦克风示例的路由等。添加代码,如下所示。
import React from "react"; import { HashRouter as Router,Route,} from 'react-router-dom'; //导入示例 import Samples from './Samples'; //主组件 class App extends React.Component { render() { //路由配置 return <Router> <div> {/* 首页 */} <Route exact path="/" component={Samples} /> </div> </Router> } } //导出主组件 export default App;
其中,根路径是直接路由向Samples页面跳转的,Samples页面里放了WebRTC的所有示例。所以此页面需要添加一个列表来展示所有示例,代码如下所示。
import React from "react"; import {List} from "antd"; import {Link} from 'react-router-dom'; //标题和路径 const data = [ {title:'首页',path:'/'}, ]; //示例组件 class Samples extends React.Component { render() { return <div> {/* 示例列表 */} <List header={<div>WebRTC示例</div>} footer={<div>Footer</div>} bordered //数据源 dataSource={data} //列表项 renderItem={item => ( <List.Item> {/* 链接 */} <Link to={item['path']}>{item['title']}</Link> </List.Item> )} /> </div> } } //导出示例组件 export default Samples;
完成上述步骤后,就可以启动应用程序了。进入项目根目录,输入npm start命令。控制台输出内容如图3-6所示。
图3-6 启动示例程序
当出现Compiled successfully提示时表示编译并启动成功。这时在浏览器地址栏中输入https://0.0.0.0:8080/#/即可访问页面,如图3-7所示。
图3-7 首次运行效果图
值得注意的是,地址栏里提示是不安全的链接,这是因为使用的是自定义签名,正式发布应用程序后使用正式证书即可。