React+Webpack+Router搭建React基础工程

       本文主要介绍React+Webpack+Router搭建React基础工程的简单方式。

      React 起源于 Facebook 的内部项目,因为该公司对市场上所有的前端MVC框架都不满意,就决定自己写一套,用来构建Instagram。

       React主要用于构建UI。你可以在React里传递多种类型的参数,如声明代码,帮助你渲染出UI、也可以是静态的HTML DOM元素、也可以传递动态变量、甚至是可交互的应用组件。

       特点:

       1.声明式设计:React采用声明范式,可以轻松描述应用。

       2.React通过对DOM的模拟,最大限度地减少与DOM的交互。

3.灵活:React可以与已知的库或框架很好地配合。


如果你想对本文中的React、webpack、router有更加深入的了解,请访问以下网站进行深入的学习:

1.React官方中文文档:http://reactjs.cn/react/docs/getting-started-zh-CN.html(大多数文章后缀名加入zh-CN会变为中文)

2.webpack中文指南 :http://webpackdoc.com/loader.html

3.react-router中文文档:http://www.uprogrammer.cn/react-router-cn/


好了,废话不多说,下面介绍运用React+Webpack+Router搭建React基础工程,目录结构如图所示:(bundle.js和server.bundle.js为构建生成的文件)

React+Webpack+Router搭建React基础工程_第1张图片

package.json文件配置:

{
  "name": "webpack-react",
  "version": "1.0.0",
  "description": "",
  "main": "./justice/index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "if-env NODE_ENV=production && npm run start:prod || npm run start:dev",
    "start:dev": "webpack-dev-server --inline --content-base build --history-api-fallback",
    "start:prod": "npm run build && node server.bundle.js",
    "build:client": "webpack",
    "build:server": "webpack --config webpack.server.config.js",
    "build": "npm run build:client && npm run build:server",
    "dev": "webpack-dev-server --devtool eval --progress --colors --hot --content-base build --history-api-fallback"
  },
  "keywords": [
    "webpack"
  ],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "babel-core": "^6.18.2",
    "babel-loader": "^6.2.7",
    "babel-plugin-react-transform": "^2.0.0",
    "babel-preset-es2015": "^6.6.0",
    "babel-preset-react": "^6.5.0",
    "babel-preset-stage-0": "^6.16.0",
    "body-parser": "^1.4.3",
    "css-loader": "^0.21.0",
    "express": "^4.4.5",
    "extract-text-webpack-plugin": "^1.0.1",
    "file-loader": "^0.9.0",
    "jquery": "^3.1",
    "less": "^2.7.2",
    "less-loader": "^2.2.3",
    "react-dom": "^15.3.2",
    "react-redux": "^4.4.6",
    "react-router": "^3.0.0",
    "redux-devtools": "^3.3.1",
    "style-loader": "^0.13.0",
    "url-loader": "^0.5.7",
    "webpack": "^1.13.3",
    "webpack-dev-server": "^1.16.2"
  },
  "dependencies": {
    "babel-core": "^6.18.2",
    "babel-loader": "^6.2.7",
    "babel-plugin-react-transform": "^2.0.0",
    "babel-preset-es2015": "^6.3.13",
    "babel-preset-react": "^6.3.13",
    "babel-preset-stage-0": "^6.16.0",
    "body-parser": "^1.4.3",
    "compression": "^1.6.2",
    "css-loader": "^0.21.0",
    "express": "^4.14.0",
    "file-loader": "^0.9.0",
    "if-env": "^1.0.0",
    "jquery": "^3.1",
    "react": "^15.3.2",
    "react-dom": "^15.3.2",
    "react-redux": "^4.4.6",
    "react-router": "^3.0.0",
    "redux-devtools": "^3.3.1",
    "style-loader": "^0.13.0",
    "url-loader": "^0.5.7",
    "webpack": "^1.13.3",
    "webpack-dev-server": "^1.16.2"
  }
}


webpack.config.js构建客户端

var path = require('path');
var webpack = require('webpack');
var ExtractTextPlugin = require("extract-text-webpack-plugin");
var config = {
    //构建入口
    entry:['webpack/hot/dev-server', path.resolve('', './justice/index.js')],
    //构建出口 path:打包文件存放的绝对路径 filename:打包后的文件名 publicPath:运行时的访问路径
    output: {
        path: path.resolve('', 'build'),
        filename: 'bundle.js',
        publicPath: '/'
    },
    module: {
        loaders: [
            //es6 es7 react加载器
            {
                test: /\.js?$/,
                exclude: /node_modules/,
                loader: 'babel-loader',
                query: {
                    presets: ["es2015",'stage-0',"react"]
                }
            },
            {
                test: /\.jsx?$/,
                exclude: /node_modules/,
                loader: 'babel-loader',
                query: {
                    presets: ["es2015",'stage-0',"react"]
                }
            },
            //css解析器
            {
                test:  /\.css$/,
                loader: 'style!css'
            },
            //style解析器
            {
                test: /\.less$/,
                use: [
                    'style-loader',
                    { loader: 'css-loader', options: { importLoaders: 1 } },
                    'less-loader'
                ]
            },
            //图片处理 小于8K按base64处理
            { test: /\.(png|jpg)$/,
                 loader: 'url-loader?limit=8192'
            }
        ]
    },
    babel: {
        presets: ['es2015','stage-0','react']
    },
    resolve:{
        //自动扩展文件后缀名,意味着我们require模块可以省略不写后缀名
        extensions:['','.js','.json']
    },
    //插件配置  ExtractTextPlugin:提取样式插件
    plugins: process.env.NODE_ENV === 'production' ? [
        new webpack.optimize.DedupePlugin(),
        new webpack.optimize.OccurrenceOrderPlugin(),
        new webpack.optimize.UglifyJsPlugin(),
        new ExtractTextPlugin("styles.css")
    ] : [
        new webpack.HotModuleReplacementPlugin(),
        new ExtractTextPlugin("styles.css")
    ]
};

module.exports = config;

server.js 服务端配置

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

var react=require('react');
var match=require('react-router');
var RouterContext=require('react-router');
var renderToString=require('react-dom/server');

var app=express();
//must be first! 文件压缩
app.use(compression());

app.use(express.static(path.join(process.cwd(), 'build')));

app.get('*',function(req,res){
    res.sendFile(path.join(process.cwd(),'build','index.html'));
});

function renderPage(appHtml) {
    return `
    
    
    
    
${appHtml}
` } var PORT = process.env.PORT || 8080 app.listen(PORT, function(){ console.log('Production Express server running at localhost:' + PORT); });
 webpack.server.config.js 构建服务端:

var fs = require('fs')
var path = require('path')

module.exports = {

    entry: path.resolve(__dirname, 'server.js'),

    output: {
        filename: 'server.bundle.js'
    },

    target: 'node',

    // keep node_module paths out of the bundle
    externals: fs.readdirSync(path.resolve(__dirname, 'node_modules')).concat([
        'react-dom/server', 'react/addons',
    ]).reduce(function (ext, mod) {
        ext[mod] = 'commonjs ' + mod
        return ext
    }, {}),

    node: {
        __filename: true,
        __dirname: true
    },

    module: {
        loaders: [
            {
                test: /\.js?$/,
                exclude: /(node_modules|bower_components)/,
                loader: 'babel',
                query: {
                    presets: ['es2015', 'react','stage-0']
                }
            },
            {
                test: /\.jsx?$/,
                exclude: /node_modules/,
                loader: 'babel-loader',
                query: {
                    presets: ["es2015",'stage-0',"react"]
                }
            },
            {
                test:  /\.css$/,
                loader: 'style!css'
            },
            { test: /\.(png|jpg)$/,
                loader: 'url-loader?limit=8192'
            }
        ]
    }

}
webpack部分到此为止,接下来我们继续写react和router部分:

index.html



    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    


从上面的webpack.config.js中可知,我们构建的入口为index.js,index.js也必为路由的入口,配置如下:

index.js
var React=require('react');
var ReactDOM=require('react-dom');
var Router=require('react-router').Router;
//hashHistory url中带有#号,browserHistory不带有#号
var hashHistory=require('react-router').hashHistory;
var browserHistory=require('react-router').browserHistory;

var routes=require('./routes.js').routes
//url上的userName 和 repoName 会传到this.props.params中
//IndexRoute 当没有其他明确url时会首先render
ReactDOM.render((
    
), document.getElementById('content'))
我们发现index.js引用了routes即路由的集合,这个集合存在于routes.js

routes.js的内容如下:

var React=require('react');
var Route= require('react-router').Route;
var IndexRoute=require('react-router').IndexRoute;

var Home=require('./home').Home;
var Welcome=require('./page/welcome').Welcome;
var Tree=require('./page/tree.jsx').Tree;
var Silder=require('./page/silder.jsx').Silder;
var Calendar=require('./page/calendar.jsx').Calendar;
var Dialog=require('./page/dialog.jsx').Dialog;
var Table=require('./page/table.jsx').Table;
var Datepicker=require('./page/datepicker').Datepicker;
var $=require('jquery');

//即进入路由时触发的函数
var enterFun=function(nextState,replace){
    if(nextState.location.pathname=='/'){
        $('#home').addClass('active');
    }
    if(nextState.location.pathname!='/'){
        $('#home').removeClass('active');
    }
}
//component代表使用的组件 IndexRoute为首页路由 path为路径 路由按层级进入,一开始进入Home组件 然后组合首页路由同时进入Welcome组件
var routes=(
    
        
        
        
        
        
        
        
    
);


exports.routes=routes;
 首页路由welcome.js的内容如下

var React=require('react');
var Link= require('react-router').Link;
var IndexLink=require('react-router').IndexLink;

var Welcome = React.createClass({
    render : function(){
        return (
            
欢迎来到React
构建方式为React+webpack+router
); } }) exports.Welcome=Welcome;
Home.js的内容如下
   
var React=require('react');
var Link= require('react-router').Link;
var IndexLink=require('react-router').IndexLink;

var Header=require('./header.js').Header;
var Footer=require('./footer.js').Footer;
var Navigation=require('./nav.js').Navigation;
var Menu=require('./menu.js').Menu;
var Welcome=require('./page/welcome.js').Welcome;

var Home = React.createClass({
    render : function(){
        return (
            
  1. 主页
  2. 数据分析
  3. 表格
{this.props.children||}
); } }) exports.Home=Home;
接下来是menu.js 为访问路由的方式: to='xxx'中的路径与route中的path对应
 
  
 
  

 
  
 
  
var React=require('react');
var Link= require('react-router').Link;
var IndexLink=require('react-router').IndexLink;

//React SilderBar
var Menu = React.createClass({
    render : function(){

        return (
            
Home React Tree React Table React Calendar React Dialog
); } }) exports.Menu=Menu;
 header.js(footer.js结构与之形式相似,这里不赘述)

var React=require('react');

var Header = React.createClass({
    render : function(){
        return (
            

{this.props.name}

); } }) exports.Header=Header;

table.jsx(其他组件与之结构相似,这里不赘述)
    
var React=require('react');
var PropTypes=require('react').PropTypes;
var Link= require('react-router').Link;
var IndexLink=require('react-router').IndexLink;

var myTree = React.createClass({
    render() {
        return (
tree
); } }); exports.Tree=myTree;

至此,一个简单的react+webpack+router的基础工程搭建完毕
第一步:执行npm install 安装node modules
第二步:执行npm start 或npm run start:dev 运行dev模式
	     
             执行npm run start:prod 运行生产模式
 















你可能感兴趣的:(react,react,webpack,router)