使用React、Node.js、MongoDB、Socket.IO开发一个角色投票应用的学习过程一

本项目是对使用React、Node.js、MongoDB、Socket.IO开发一个角色投票应用的学习过程。

英文原文:Create a character voting app using React,Node.js,MongoDB and Socket.IO
原项目github

学习过程

要想系统的学习些新东西,网上看了很多代码片段,但很少有这样完整的一个系统来学习,基实我本来是比较偏向Vue的但是看到了这个文章,太全面了,对于想入门的人来说,方方面面都有,有前端,有后端,所以忍不住想把它提供的代码全敲一遍。敲代码的过程,虽然只是个抄的过程,但比光看要很很多,有的时候往往看人家代码的时候,感觉是这样的,"哦,就是这样的啊.so easy,不过如此吗~",但一句一句去敲的时候,感觉就是这样的,"WTF,这是什么鬼,这个函数哪里来的,这个库是干嘛用的,这里这么写到底是为了什么",所以当你把过程中的这些疑问都搞清楚了,才是真正的提高了,光看很多细节是注意不到的。

对原有的改动

代码是好,但是最好在原来的基础上加点自己的相法,所以我做的改动主要有如下

  1. 把所有不是用ES6的代码全部改成ES6的

  2. 数据库从mongodb 改成了MysqL

  3. 用waterline替换mongoose操作数据库

改动后的代码,我也全发布在github上了,还没改完,我会不定期commit的

https://github.com/papersnake/newdenfaces-es6

改写的过程和遇到的坑

对ES6学也的也不深,改了这么多也发现语法上也只用到了import let const 和=>,希望大家提出更多的改进意见
原文第一步的代码

原文第一步的改进

var express = require('express');
var path = require('path');
var logger = require('morgan');
var bodyParser = require('body-parser');

var app = express();

app.set('port',process.env.PORT || 3000);
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.static(path.join(__dirname,'public')));

app.listen(app.get('port'),function() {
  console.log('Express server listening on port ' + app.get('port'));
});

改写后,变成

import express    from 'express';
import path       from 'path';
import logger     from 'morgan';
import bodyParser from 'body-parser';

let app = express();

app.set('port',() => {
    console.log('Express server listening on port ' + app.get('port'));
});

为了能让它跑起来,要在原有依赖的基础上添加

npm install --save-dev babel-cli,babel-core,babel-preset-es2015,babel-preset-react,babel-register

有几个依赖是后面才用到的,我这里一并安装了
在根目录新建一个.babelrc文件

{
  "presets": [
    "es2015"
  ]
}

babel-node server.js 就要以跑起来了

原文第二步分 构建系统的改写

为了节省篇幅,有些全篇的代码我就不粘贴,给出连接吧 gulpfile.js

gulp 从3.9.0开始支持babel,但是要把文件名改为gulpfile.babel.js
改写后的代码

import gulp from 'gulp';
import gutil from 'gulp-util';
import gulpif from 'gulp-if';
import streamify from 'gulp-streamify';
import autoprefixer from 'gulp-autoprefixer';
import cssmin from 'gulp-cssmin';
import less from 'gulp-less';
import concat from 'gulp-concat';
import plumber from 'gulp-plumber';
import source from 'vinyl-source-stream';
import babelify from 'babelify';
import browserify from 'browserify';
import watchify from 'watchify';
import uglify from 'gulp-uglify';

const production = process.env.NODE_ENV === 'production';

const dependencies = [
    'alt','react','react-router','underscore'
];

/*
 |--------------------------------------------------------------------------
 | Combine all JS libraries into a single file for fewer HTTP requests.
 |--------------------------------------------------------------------------
 */
gulp.task('vendor',()=>
    gulp.src([
        'bower_components/jquery/dist/jquery.js','bower_components/bootstrap/dist/bootstrap.js','bower_components/magnific-popup/dist/jquery.magnific-popup.js','bower_components/toastr/toastr.js'
        ]).pipe(concat('vendor.js'))
          .pipe(gulpif(production,uglify({ mangle:false })))
          .pipe(gulp.dest('public/js'))
    );


/*
 |--------------------------------------------------------------------------
 | Compile third-party dependencies separately for faster performance.
 |--------------------------------------------------------------------------
 */
gulp.task('browserify-vendor',() =>
  browserify()
    .require(dependencies)
    .bundle()
    .pipe(source('vendor.bundle.js'))
    .pipe(gulpif(production,streamify(uglify({ mangle: false }))))
    .pipe(gulp.dest('public/js'))
);

/*
 |--------------------------------------------------------------------------
 | Compile only project files,excluding all third-party dependencies.
 |--------------------------------------------------------------------------
 */
gulp.task('browserify',['browserify-vendor'],() =>
  browserify('app/main.js')
    .external(dependencies)
    .transform(babelify,{ presets: ["es2015","react"]}) //注意这里,只有加上presets配置才能正常编译
    .bundle()
    .pipe(source('bundle.js'))
    .pipe(gulpif(production,streamify(uglify({ mangle: false }))))
    .pipe(gulp.dest('public/js'))
);

/*
 |--------------------------------------------------------------------------
 | Same as browserify task,but will also watch for changes and re-compile.
 |--------------------------------------------------------------------------
 */
gulp.task('browserify-watch',() =>{
  var bundler = watchify(browserify('app/main.js',watchify.args));
  bundler.external(dependencies);
  bundler.transform(babelify,"react"]});
  bundler.on('update',rebundle);
  return rebundle();

  function rebundle() {
    var start = Date.Now();
    bundler.bundle()
      .on('error',function(err) {
        gutil.log(gutil.colors.red(err.toString()));
      })
      .on('end',function() {
        gutil.log(gutil.colors.green('Finished rebundling in',(Date.Now() - start) + 'ms.'));
      })
      .pipe(source('bundle.js'))
      .pipe(gulp.dest('public/js/'));
  }
});


/*
 |--------------------------------------------------------------------------
 | Compile LESS stylesheets.
 |--------------------------------------------------------------------------
 */
gulp.task('styles',() =>
  gulp.src('app/stylesheets/main.less')
    .pipe(plumber())
    .pipe(less())
    .pipe(autoprefixer())
    .pipe(gulpif(production,cssmin()))
    .pipe(gulp.dest('public/css'))
);

gulp.task('watch',() =>{
  gulp.watch('app/stylesheets/**/*.less',['styles']);
});

gulp.task('default',['styles','vendor','browserify-watch','watch']);
gulp.task('build','browserify']);

由于到现在为止,还没有做其他工作,所以看不到打包的实际效果, 但是也是要控制台下运行一下gulp 看看有没有语法错误

到这里为止没有遇到多大的坑,最多的往往是拼写错误引起的问题,唯一由于拼写导致,但不提示错误的是

app.use(bodyParser.json());

我打成了

app.use(bodyParser.json);

运行的时候服务器一直没有响应,找了好久才找到这个错误

后篇

使用React、Node.js、MongoDB、Socket.IO开发一个角色投票应用的学习过程(二)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


react 中的高阶组件主要是对于 hooks 之前的类组件来说的,如果组件之中有复用的代码,需要重新创建一个父类,父类中存储公共代码,返回子类,同时把公用属性...
我们上一节了解了组件的更新机制,但是只是停留在表层上,例如我们的 setState 函数式同步执行的,我们的事件处理直接绑定在了 dom 元素上,这些都跟 re...
我们上一节了解了 react 的虚拟 dom 的格式,如何把虚拟 dom 转为真实 dom 进行挂载。其实函数是组件和类组件也是在这个基础上包裹了一层,一个是调...
react 本身提供了克隆组件的方法,但是平时开发中可能很少使用,可能是不了解。我公司的项目就没有使用,但是在很多三方库中都有使用。本小节我们来学习下如果使用该...
mobx 是一个简单可扩展的状态管理库,中文官网链接。小编在接触 react 就一直使用 mobx 库,上手简单不复杂。
我们在平常的开发中不可避免的会有很多列表渲染逻辑,在 pc 端可以使用分页进行渲染数限制,在移动端可以使用下拉加载更多。但是对于大量的列表渲染,特别像有实时数据...
本小节开始前,我们先答复下一个同学的问题。上一小节发布后,有小伙伴后台来信问到:‘小编你只讲了类组件中怎么使用 ref,那在函数式组件中怎么使用呢?’。确实我们...
上一小节我们了解了固定高度的滚动列表实现,因为是固定高度所以容器总高度和每个元素的 size、offset 很容易得到,这种场景也适合我们常见的大部分场景,例如...
上一小节我们处理了 setState 的批量更新机制,但是我们有两个遗漏点,一个是源码中的 setState 可以传入函数,同时 setState 可以传入第二...
我们知道 react 进行页面渲染或者刷新的时候,会从根节点到子节点全部执行一遍,即使子组件中没有状态的改变,也会执行。这就造成了性能不必要的浪费。之前我们了解...
在平时工作中的某些场景下,你可能想在整个组件树中传递数据,但却不想手动地通过 props 属性在每一层传递属性,contextAPI 应用而生。
楼主最近入职新单位了,恰好新单位使用的技术栈是 react,因为之前一直进行的是 vue2/vue3 和小程序开发,对于这些技术栈实现机制也有一些了解,最少面试...
我们上一节了了解了函数式组件和类组件的处理方式,本质就是处理基于 babel 处理后的 type 类型,最后还是要处理虚拟 dom。本小节我们学习下组件的更新机...
前面几节我们学习了解了 react 的渲染机制和生命周期,本节我们正式进入基本面试必考的核心地带 -- diff 算法,了解如何优化和复用 dom 操作的,还有...
我们在之前已经学习过 react 生命周期,但是在 16 版本中 will 类的生命周期进行了废除,虽然依然可以用,但是需要加上 UNSAFE 开头,表示是不安...
上一小节我们学习了 react 中类组件的优化方式,对于 hooks 为主流的函数式编程,react 也提供了优化方式 memo 方法,本小节我们来了解下它的用...
开源不易,感谢你的支持,❤ star me if you like concent ^_^
hel-micro,模块联邦sdk化,免构建、热更新、工具链无关的微模块方案 ,欢迎关注与了解
本文主题围绕concent的setup和react的五把钩子来展开,既然提到了setup就离不开composition api这个关键词,准确的说setup是由...
ReactsetState的执行是异步还是同步官方文档是这么说的setState()doesnotalwaysimmediatelyupdatethecomponent.Itmaybatchordefertheupdateuntillater.Thismakesreadingthis.staterightaftercallingsetState()apotentialpitfall.Instead,usecom