react +webpack+express router实现登录与页面跳转

1、演示效果


2、webpack多入口配置

2.1在webpack.config.js中配置entry

var webpack = require('webpack');
var path = require('path');

//公共文件打包到common.js中
var commonsPlugin = new webpack.optimize.CommonsChunkPlugin('common.js',['main','login']);

module.exports = {
  cache: true,
  entry: {
    //登陆后进入的主页面
    main: './src/index.js',
    //登录页面
    login:'./src/login.js',
  },
  output: {
    //输出到公共文件public/build下
    path: path.resolve(__dirname, 'public/build'),
    //名称也就是对应的main.js和login.js
    filename: '[name].js',
  },
  module: {
    loaders: [
      {
        test: /\.jsx?$/,
        loader: 'babel',
        exclude: /(node_modules|bower_components)/,
        query: {
          presets: ['react', 'es2015', 'stage-0']
        }
      },
      {
        test: /\.css$/,
        loader: 'style-loader!css-loader'
      },
      {
        test: /\.(png|jpg)$/,
        loader: 'url-loader?limit=8192'
      },
      {
        test: /\.(woff|eot|ttf|svg)$/, // Have to configure fonts loaders for the generated fonts,视频播放中出现的文字样式不识别
        loader: 'url',
      }
    ]
  },
  resolve: {
    extensions: ['', '.js', '.jsx', '.css', '.json'],
  },
  plugins: [
    //动态刷新引擎
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoErrorsPlugin(),
    // 公共文件打包引擎
    commonsPlugin
  ]
};

2.2在express app中配置动态打包

var express = require('express');
var path = require('path');
var app = express();

//热更新模块
if (process.env.NODE_ENV !== 'production') {
  var webpack = require('webpack');
  var webpackConfig = require('./webpack.config.js');
  var webpackCompiled = webpack(webpackConfig);
  // 配置运行时打包
  var webpackDevMiddleware = require('webpack-dev-middleware');
  app.use(webpackDevMiddleware(webpackCompiled, {
    //暂存的检测更新的打包文件放入publicPath中,因此需要额外注意publicPath和webpack.config.js中配置的output的path相同,仅需要最后的一个文件夹build
    publicPath: "/build/",
    stats: { colors: true },
    lazy: false,
    watchOptions: {
      aggregateTimeout: 300,
      poll: true
    },
  }));
  // 配置热更新
  var webpackHotMiddleware = require('webpack-hot-middleware');
  app.use(webpackHotMiddleware(webpackCompiled));
}     


3、模板引擎jade文件与app文件引用jade文件

3.1view文件夹中的布局文件layout.jade、登录布局login.jade、主页面index.jade

3.1.1 layout.jade

doctype html
html
  head
    title= title
    //公共文件的引入
    script(src='/build/common.js')
  body
    //body中划分区块,供其他需要的jade引用
    block content

3.1.2 login.jade

//引入layout.jade
extends layout

//引入body的布局
block content
  //声明react-container块,供react DOM绑定
  #react-container
  //文件来源是打包文件/build/login.js
  script(src='/build/login.js')

3.1.3 index.jade

extends layout

  block content
    #react-container
      script(src='/build/main.js')


3.2 app中引入jade模板引擎

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');


4、react使用form提交登录信息

import React, { Component } from 'react';
import ReactDOM from 'react-dom';

class Login extends Component {
    render() {
      return (
            <form action="/login" method="post">//提交表单信息至app中
                <div>
                    <label>Username:</label>
                    <input type="text" name="username" /><br />
                </div>
                <div>
                    <label>Password:</label>
                    <input type="password" name="password" />
                </div>
                <div>
                    <input type="submit" value="Submit" />
                </div>
            </form>
        );
    }
}

export default Login;

ReactDOM.render(
    <Login />,
    document.getElementById("react-container")
);


5、express app 利用passport实现登录验证与跳转

var express = require('express');
var app= express();

var passport = require('passport');
var Strategy = require('passport-local').Strategy;

//react提交的表单信息进行验证
passport.use(new Strategy(
  function (username, password, done) {
    if(username == 'test' && password =='test'){
      done(null,{id:1234,name:username});//done相当于一个缓存器,接下来在passort中serializeUser中取出 
    }else {
      console.log('no user');
      done(null, false, { message: 'Incorrect username.' })
    }
  }));

passport.serializeUser(function (user, done) {
  let sessioninfo = {
    uid: user.id,
    username: user.name
  }
  done(null, sessioninfo);//页面跳转前的session存储

});
//加载下一页面是的session存储
passport.deserializeUser(function (user, done) {
  if (user != null) {
    done(null, user);
  } else {
    console.log('no user');
    done(null, false, { message: 'Incorrect userid.' })
  }
});
//app在任何时候均会加载这个文件,对这个文件进行限制,即可完成跳转
app.use(function (req, res, next) {

  if (req.url != '/login' && (!req.session || !req.session.passport || !req.session.passport.user)) {
    res.redirect('/login');
  }
  next();
})


//主页面/,进入jade中的index
app.get('/',
  function (req, res) {
    res.render('index', { title: 'index', user: JSON.stringify(req.session.passport) });
  });


app.get('/login',
  function (req, res) {
    res.render('login');
  });
//获取react中form提交的表单信息,利用passport.authenticate进行验证
app.post('/login',
  function (req, res, next) {
    passport.authenticate('local', function (err, user, info) {
      if (err) { return next(err); }
      //验证失败,仍在login页面
      if (!user) { return res.redirect('/login'); }
      req.logIn(user, function (err) {
        if (err) { return next(err); }
        //验证成功跳转到主页面
        return res.redirect('/');
      });
    })(req, res, next);
  })

app.get('/me', function (req, res) {

  console.log(req.url);
  console.log(req.session);
  console.log(req.session.passport);
  res.send(JSON.stringify(req.session.passport));
})

app.get('/logout',
  function (req, res) {
    req.logout();
    res.redirect('/');
  });

module.exports = app;


6、react主页面获取用户信息

import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import $ from 'jquery';
export default class Index extends Component {
  constructor(props, context) {
    super(props, context);
    this.state={
      username:null,
      uid:null,
    }
  }
  //再次通过api获取express 中的session信息
 componentWillMount() {
 $.ajax({
     url: "/me",
     method: "GET", 
     success: function (data) 
      { 
        data=JSON.parse(data);
        console.log(data);
this.setState({ username:data.user.username, uid:data.user.uid, })
        }.bind(this), 
     error: function (xhr, status, err)
      { console.log(err); }.bind(this) });
        }
render() {
     return ( <div> <p>username:{this.state.username}</p> 
              <a href="/logout">Log out</a> </div> )
 }}

ReactDOM.render(
<Index />,
document.getElementById("react-container")
);


7、结束语

通过webpack打包、react与jade文件映射、express router作为路由,实现了登录、验证、session缓存、主页面获取登录信息一系列流程,希望此篇文章对你有所帮助。

猜你喜欢

转载自blog.csdn.net/zfan520/article/details/78889506