基于 Swoole 开发实时在线聊天室(四):前端资源初始化

由 学院君 创建于1年前, 最后更新于 1年前

版本号 #3

3922 views

0 likes

0 collects

正如学院君开篇所说,本实战教程的前端界面将会基于 https://github.com/hua1995116/webchat 这个前端技术栈实现的聊天室项目,以便将重心专注于基于 Swoole 的聊天室功能开发,为了方便介绍,后面统一将其称之为 Vue-Webchat。

不过 Vue-Webchat 前后端都是基于 JavaScript 实现的,前端使用的是 Vue 框架,后端使用的是 Express 框架,数据库使用的是 MongoDB,并且 WebSocket 通信前后端都是基于 Socket.io,而在本实战项目中,我们希望基于 Laravel 框架作为后端,将数据存储在 MySQL 数据库里面,并且 WebSocket 服务器基于 Swoole 实现,此外,我们还希望借助 Laravel 提供的 Laravel Mix 作为前端资源编译工具,取代原生的 Webpack,所以必须要对原来的前端代码进行适当的改造。

注:为了更好的专注于 Swoole 聊天室功能开发,学院君只使用一篇教程的篇幅来介绍前端代码的改造,更多关于 Vue 组件、Vue Router 以及 Vuex 等 Vue 生态系统工具的使用和完整开发流程,可以参考学院君之前发布的前后端分离项目系列教程,这里不再具体展开介绍了。

前端目录结构迁移

在 Vue-Webchat 这个项目中,前端资源代码位于 src 目录下:

jquery pc端聊天室 前端聊天室_dropify php

我们先删除 Laravel 项目 webchat 的 resources/js 目录下的所有文件,然后将 Vue-Webchat 的 src 目录迁移过来:

jquery pc端聊天室 前端聊天室_Vue_02

这里我对部分目录结构做了调整,比如将原项目的 static/css/reset.css 迁移到了 resources/css/reset.css,将原项目的 src/styles 下的样式代码整合到了 resources/sass/app.scss 中,以更好地适配 Laravel 项目的目录结构。另外,我还将原项目 src 目录下的 App.vue 和 BaseTransition.vue 文件移到 resources/js/layout 目录下,将原项目 src 目录下的 view 子目录重命名为 pages,这个只是个人喜好问题,当然,相应的,需要修改所有的引入文件路径。

此外,前端 JavaScript 入口文件由 main.js 重命名为 app.js。

前端视图入口文件

原项目的前端视图入口文件位于根目录下的 index.html,本项目的视图入口文件位于 resources/views/index.blade.php:

Laravel学院在线聊天室

window.Laravel = <?php echo json_encode(['csrfToken' => csrf_token(),]); ?>

相应的,需要到 routes/web.php 路由文件中调整默认的首页视图模板:

Route::get('/', function () {
return view('index');
});

前端代码调整

接下来,重点看下为了适配 Laravel 后端框架和 Swoole WebSocket 服务器而对前端代码所做的修改。

与后端接口的交互

与后端接口的交互都统一封装在 resources/js/api 目录下,在 axios.js 中提供了对 Axios 库的基础封装,然后所有后端接口调用都位于 server.js 中,这里我们需要对 axios.js 进行调整,加入 CSRF Token 请求头:

import axios from 'axios';
const baseURL = '/api/';
const instance = axios.create();
instance.defaults.timeout = 30000; // 所有接口30s超时
instance.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
// 所有请求头设置 CSRF Token
let token = document.head.querySelector('meta[name="csrf-token"]');
if (token) {
instance.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
} else {
console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');
}
...

具体调用后端接口的路由和处理逻辑先不管,后面开发具体功能时再逐一调试。

与 WebSocket 服务器的交互

Vue-Webchat 项目基于 socket.io-client 库作为客户端与 WebSocket 服务器进行通信,这里我们沿用这一客户端方案,但是需要修改连接配置,将后端配置修改为 Swoole WebSocket 服务器,修改 resources/js/socket.js 代码如下:

// 通过 Socket.io 客户端发起 WebSocket 请求
import io from 'socket.io-client'
const socket = io.connect(process.env.APP_URL + ':' + process.env.LARAVELS_LISTEN_PORT + '/ws/')
export default socket

和 axios 一样,具体调用这个 socket 模块的地方先不管,后面开发到具体功能的时候再逐一调试。

别名路径的调整

Vue-Webchat 项目在引入组件和视图模块时配置了 @ 路径别名,比如这种:

import {queryString} from '@utils/queryString';

本项目取消了这一配置,直接通过相对路径引入:

import {queryString} from './utils/queryString';

所有涉及到 @ 路径引用的地方都要调整,主要是在 pages 子目录下的 Vue 组件中。

前端样式编译的调整

前面已经提到,本项目的 JavaScript 入口文件是 app.js,我将原项目在这里引入的 CSS 资源文件通通移出,整合到 webpack.mix.js 下通过 Laravel Mix 进行编译:

mix.js('resources/js/app.js', 'public/js')
.sass('resources/sass/app.scss', 'public/css')
.styles([
'resources/css/reset.css',
'public/css/app.css',
'node_modules/muse-ui/dist/muse-ui.css'
], 'public/css/app.css');

添加前端依赖到 package.json

接下来,我们把前端代码中涉及到的所有新的依赖库添加到项目根目录下的 package.json 中:

"devDependencies": {
"axios": "^0.18",
"cross-env": "^5.1",
"file-loader": "^4.2.0",
"jquery": "^3.2",
"laravel-mix": "^4.0.7",
"lodash": "^4.17.5",
"muse-ui": "^3.0.2",
"popper.js": "^1.12",
"resolve-url-loader": "^2.3.1",
"sass": "^1.23.1",
"sass-loader": "7.*",
"socket.io-client": "^2.3.0",
"stylus": "^0.54.7",
"stylus-loader": "^3.0.2",
"timers": "^0.1.1",
"url-loader": "^2.2.0",
"vivus": "^0.4.5",
"vue": "^2.6.10",
"vue-cropper": "^0.4.9",
"vue-picture-preview": "^1.3.0",
"vue-router": "^3.1.2",
"vue-style-loader": "^4.1.2",
"vue-template-compiler": "^2.6.10",
"vuex": "^3.1.1",
"xss-filters-es6": "^1.0.0"
}

然后运行 npm install 安装所有前端依赖库。

当然,以上所有前端代码迁移和调整都已经提交到 Github 仓库,你可以直接从这里下载对应的资源到本地:https://github.com/nonfu/webchat。

编译前端资源

最后,在项目根目录下运行 npm run dev 通过 Laravel Mix 来编译上述所有前端资源:

jquery pc端聊天室 前端聊天室_Laravel_03

编译成功后,接下来,我们将着手调试前端界面与后端接口的交互,这些放到后续教程去逐一讲解。