Giter Site home page Giter Site logo

admin's Introduction

admin

前言

自己一直想做个包括前后端的项目,了解和熟悉一个网站从构建到部署整个流程。正好以前做过一个react的后台模板(纯前端)。另外在慕课网找了一个node项目学习后,开始自己做一个前后台项目。

所有权限都在后台做,比如非管理员不能添加和删除作品,如果仅靠前台禁用按钮,用户可以直在浏览器修改dom属性绕过禁用功能,所以前台只是起对不同权限用户展示不同UI的功能,而不是通过前台做权限功能。

想测试多个账号在线,请用不同的浏览器登陆

项目地址github地址
预览地址:服务器到期,暂时没有预览地址

1.项目截图

在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述


2.项目功能

  • 用户注册功能
  • 用户登录功能
  • 修改账号信息上传头像等功能
  • 网站换肤、切换全屏功能
  • 网站留言板
  • 聊天室

jwt实现注册与登陆系统
react+koa实现留言板功能
webSocket实现聊天室功能
react编写打字组件
antd实现换肤功能
富文本编辑器braft-editor的使用


3.前端

前端使用的技术栈:react、react-router、redux、canvas、fetch、antd、websocket、es6

3.1创建

使用create-react-app脚手架搭建了前端项目并扩展了webpack的配置(配置可以参考这里)。 新增修饰器语法,这是ES7的一个新语法,作用就是修改组件的一些属性。比如路由的withRouter将组件包裹,可以在组件的props上传递history对象等等。

//不使用修饰器语法
withRouter(Test)

//使用修饰器语法
@withRouter
class Test extends React.Component{
	...
}

当有一个组件需要多个高阶组件包裹时,这种写法就很有优势

withRouter(Form.create()(Test))

@withRouter @Form.create() ...
class Test extends React.Component{
	...
}

当然包裹的顺序也很重要


3.2依赖

自己根据需求封装了一个fetch来进行前后台通信,使用简单。

const res = await get('/test')
console.log(res)
3.3组件

公用组件应该完全隔离业务逻辑,我通过事件分发和props传递编写了以下组件,这些组件完全隔离了业务逻辑,所以在其它项目中也可以使用。

组件 组件的作用 组件接收的props
AnimatedBooks 展示翻书动画效果的组件 content(内容) 、cover(封面)
Background 登录粒子背景 url(背景图)
ColorPicker 拾色器 color(当前颜色)、onChange(颜色改变的函数)
Loading loading动画
Typing 打字插件 delay(打印延时)、frequency(打印频率)、done(打印完成的回调)
3.4页面

页面可以拆分成不同的组件,然后将组件拼接成一个页面,使得页面维护和编写变得简单。但是会带来不同组件之间通信的问题,解决的方法有两个:

  • 状态提升
  • 状态管理

状态提升适用于组件关系简单的通信,比如兄弟组件之间的通信,就可以将状态提升到它们的父组件中,通过props和事件传递给子组件。这种方式不适合层级结构太深的组件通信,否则一层层传递太过麻烦。

在Index页面中,我将页面按照UI拆分成了头部、侧边栏、中间部分、底部组件,然后使用了状态提升进行组件之间的通信。

状态管理适用于需要全局使用的状态或者组件嵌套复杂的状态,

至于如何拆分页面,我认为可以按UI拆分功能拆分,如果拆分的组件可以共用,我们可以进一步抽象成公共组件使用(公共组件就是将业务逻辑解耦出去)


4.项目后端

后端采用的是koa、mysql使用了一些koa的中间件

4.1创建

后端通过koa-generator脚手架搭建后端项目 这是我第一次写后端项目,对于后端的的mvc也不算特别熟悉,参考网上的介绍后以自己的理解去写了,routes文件存储路由、controller文件件实现对应的路由逻辑,如果有问题欢迎指出。

为什么要使用框架? 原生的node只提供了最基本的功能,我们还需要编写一些额外的代码才能达到我们的要求,比如获取前台传过来的参数,原生node只提供了url属性,需要我们自己解析url来获取querying,而koa2框架已经封装好了,直接在ctx中提供了query对象;还有前台post的数据、cookie、session、路由等,在原生中都需要我们自己处理,而koa2框架直接封装好了,就算koa2没有提供也有很多其他人编写好了的中间件供我们使用。

我认为使用的框架的意义就是编写更好可维护的代码,减少和业务逻辑无关的代码,比如解析前台参数、数据库连接等等重复的代码。

之所以用koa2而不用express是相较于promise我更喜欢async/await。

接口规范

当然也有很多方式定义状态码,只有自己写好文档即可。

{
	"status":0,     //0代表成功,1失败
	"httpCode":200,    
	"message":"请求成功",
	"data":{}
}

5.项目部署

5.1项目打包

我将前端项目打包到node服务器上, 我想访问网址根目录就能直接访问项目首页了

//app.js
app.use(views(__dirname + '/public/build'))   //这里的路径是前端项目打包后放在后端的位置

//routes ->index.js
router.get('/', async (ctx, next) => {
	await ctx.render('index.html')
})

由于我们前端使用的是HTML5的history,页面一刷新就404了,所以后端要配置。我使用了koa-connect-history-api-fallback中间件来支持。 中间件实现的功能是如果 当URL 匹配不到任何静态资源,返回指定的页面(中间件默认返回的是index.html,配置参考文档

//app.js
const historyApiFallback = require('koa-history-api-fallback')
app.use(historyApiFallback());

这里要注意中间的顺序,historyApiFallback一定要放在所有接口路由后面,否则所有接口都是返回index.html了。 historyApiFallback一定要在静态资源前面,否则资源找不到

//app.js
const historyApiFallback = require('koa-history-api-fallback')
// routes
app.use(index.routes(), index.allowedMethods())
app.use(user.routes(), user.allowedMethods())
app.use(works.routes(), works.allowedMethods())
app.use(message.routes(), message.allowedMethods())
app.use(score.routes(), score.allowedMethods())

app.use(historyApiFallback());

app.use(require('koa-static')(__dirname))
app.use(require('koa-static')(__dirname + '/public/build'))
app.use(require('koa-static')(__dirname + '/public/upload-files'))

另外项目用了jwt进行权限认证了,前端打包后的资源(css、js、图片等)这些资源不应该权限认证,否则401,前端获取不到这些js来生成页面了

上线时,创建数据报错Unknown collation: 'utf8mb4_0900_ai_ci',我的数据库版本不支持这种格式。SHOW COLLATION,可查看数据库所有支持的collation,我将排序规则改为utf8mb4_general_ci


总结

期间遇见的问题我都是边找边学边用,磕磕绊绊完成了这个小项目。通过这个小项目,我熟悉了一个基本的网站从零到上线的整个流程,并从中发现问题、解决问题。这也是我写这个项目的初衷。我并没有过多深入每个细节,如数据库的字段设计,加密、防止mysql的注入、数据库优化等。

部署时,发现网页太慢了,查看network发现 用了nginx的gzip进行了压缩。 压缩前 在这里插入图片描述 压缩后 在这里插入图片描述 可以看到size明显变小了,但是请求的时间还是有点长 下面是我的nginx配置

upstream admin{                                                                                                            
    server 47.99.130.140:8888;                                                                                             
}                                                                                                                          
upstream reactMusic{                                                                                                       
    server 47.99.130.140:8088;                                                                                             
}                                                                                                                          
                                                                                                                           
                                                                                                                           
                                                                                                                           
server{                                                                                                                    
     gzip on;                                                                                                              
     gzip_min_length 1k;                                                                                                   
     gzip_buffers 4 16k;                                                                                                   
     gzip_comp_level 6;                                                                                                    
     #gzip_types text/plain application/x-javascript text/css application/xml text/javascript application/x-httpd-php;     
     gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/x
ml application/xml+rss text/javascript application/x-font-woff;                                                            
     gzip_http_version 1.1;                                                                                                
     gzip_vary on;                                                                                                         
     gzip_proxied off;                                                                                                     
                                                                                                                           
     listen 80;                                                                                                            
     server_name 47.99.130.140;                                                                                            
     location /admin/ {                                                                                                    
          proxy_redirect   off;                                                                                            
            proxy_set_header Host $host;                                                                                   
            proxy_set_header X-Forwarded-For $remote_addr;                                                                 
            proxy_set_header X-Real-IP $remote_addr;                                                                       
            proxy_pass http://admin/;                                                                                      
     }                                                                                                                     
     location /react-music/ {
                 proxy_set_header Host $host;                                                                              
            
            proxy_set_header X-Forwarded-For $remote_addr;
            proxy_set_header X-Real-IP $remote_addr;
                proxy_pass http://reactMusic/;   
     }

}                                                                                                        
                                                                           
                                                                           

admin's People

Contributors

z-9527 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

admin's Issues

本地前端打包测试路径错误 导致后端启动静态资源 404

如果直接将前端部分打包放到 /public/build 下后启动后端,出现报错:

GET /index.html -
  --> GET /admin/static/css/xxxxx.chunk.css 404 -
GET /index.html -
  --> GET /admin/static/js/xxxxx.chunk.js 404 -

打开本地 8888 端口跳进了 /admin/login,不能正常访问,而访问 /login 是正常的。

后来我改了前端的 react/src/utils/history.jsoptions.basename,改成 '/',就能自动跳进 /login ,资源加载正常了。

import { createBrowserHistory } from 'history'

const env = process.env.NODE_ENV  // 环境参数
let options = {}
if (env === 'production') {
    options.basename = '/admin'   // 这里改成 '/'
}

export default createBrowserHistory(options)

作者做展示时在服务器做了 Nginx 就没事,如果本地测试请大家注意。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.