react系列(12)React+Webpack的组合搭建

React是纯View层,但在最新的React V16版本中,按传统的纯js脚本开发已经不能适应项目的需要,配合Webpack打包,可以够更便捷地管理项目和更新插件;再者,使用ES6开发,将大大地提高团队地开发效率。本篇主要是介绍如何部署React+Webpack组合搭建,那么我们一步步来吧。

一.创建目录结构

创建一个web项目ReactWebpack,目录结构如图所示:

react系列(12)React+Webpack的组合搭建_第1张图片

app目录:存放核心代码。

components目录:存放React组件。

css目录:存放样式文件。

build目录:存放打包编译后的js文件。

index.html:展示页。

main.js:入口js文件。

 

二.安装cnpm镜像

假设你本机已经安装nodejs,可以使用命令行npm,我用的版本是node-v6.0.0-x64.msi,百度即可下载。

为什么用cnpm?因为cnpm是淘宝npm镜像,下载速度会更流畅,当然也可以使用npm。

安装命令行:

$ npm install -g cnpm --registry=https://registry.npm.taobao.org

 

三.创建package.json文件

package.json是一个标准的npm说明文件,里面蕴含了丰富的信息,包括当前项目的依赖模块,自定义的脚本任务等,通过这个文件即可知道您的项目跑起来需要哪些模块库,项目作者、版本等。

在dos环境下,检索至项目根目录,执行命令行:

$ npm init

输入项目名称:react_demo,其它直接enter即可,成功后如图所示:

react系列(12)React+Webpack的组合搭建_第2张图片

此时,会在项目的根目录下多了一个package.json文件,文件内容如下:

react系列(12)React+Webpack的组合搭建_第3张图片

 

四.安装webpack

webpack主要用于对项目的打包和管理,安装成功后,会在项目根目录上多了一个node_modules文件夹,里面是存放所有npm下载的库模块。安装命令行:

$ cnpm install --save-dev webpack

安装成功后如图所示:

react系列(12)React+Webpack的组合搭建_第4张图片

 

五.创建webpack.config.js文件

webpack.config.js是打包配置文件,文件内容如下:

var webpack = require('webpack');
module.exports = {
	//根目录
	context: __dirname + "",
	//文件入口
	entry: {
		index: './app/main.js'
	},
	//文件出口
	output: {
		path: __dirname + "/build", // 设置输出目录
		filename: '[name].bundle.js', // 输出文件名
	},
	module: {
		//loaders加载器
		loaders: [{
				test: /\.(js|jsx)$/, //【一个匹配loaders所处理的文件的拓展名的正则表达式,这里用来匹配js和jsx文件(必须)】
				exclude: /node_modules/, //【屏蔽不需要处理的文件(文件夹)(可选)】
				loader: 'babel-loader' //【loader的名称(必须)】此处为可以转换ES6和JSX语法的加载器
			},
			{
				test: /\.css$/,
				loader: "style!css"  //.css文件使用 style-loader 和 css-loader 来处理  
			},
			{
				test: /\.(jpeg|png|gif|svg)$/i,
				loader: 'url-loader?limit=8192&name=[name].[ext]'  //图片文件使用 url-loader来处理,小于8kb的直接转为base64 
			}
		]
	},
	// 插件
	plugins: [
		// 默认会把所有入口节点的公共代码提取出来,生成一个common.js
		//new webpack.optimize.CommonsChunkPlugin('common'),
		// 压缩代码抬头注释
		new webpack.BannerPlugin('此处添加打包抬头注释!'),
		// 代码压缩
		new webpack.optimize.UglifyJsPlugin({
			compress: {
				warnings: false
			}
		})
	],
	//由于压缩后的代码不易于定位错误,配置该项后发生错误时即可采用source-map的形式直接显示你出错代码的位置
	devtool: 'eval-source-map',
	//其它解决方案配置
	resolve: {
		// 配置简写,配置过后,书写该文件路径的时候可以省略文件后缀。如require("common")
		extensions: ['.js', '.jsx', '.coffee']
	}
}

详细的格式我就不解释了,里面都有注释。

 

六.安装React

执行命令行:

$ cnpm install --save-dev react react-dom

 

七.安装babel

执行命令行:

cnpm install --save-dev babel-core babel-loader  babel-preset-es2015 babel-preset-react

在项目根目录下新建.babelrc文件,就是只有后缀名的文件,如图所示:

 

react系列(12)React+Webpack的组合搭建_第5张图片
文件内容如下:

//.babelrc
{
  "presets": [
    "react",
    "es2015"
  ]
}

Babel其实可以完全在webpack.config.js中进行配置。但是考虑到babel具有非常多的配置选项,在单一的webpack.config.js文件中进行配置往往使得这个文件显得太复杂,因此一些开发者支持把babel的配置选项放在一个单独的名为 ".babelrc" 的配置文件中。

 

八.添加代码

新建如下图目录所示文件(其中index.bundle.js为打包时才会有的文件,可以不用新建):

react系列(12)React+Webpack的组合搭建_第6张图片

Component.jsx脚本如下:

import React from 'react';

class Component extends React.Component {
	constructor(props) {
    	super(props);
    	this.state = {};
  	}	
  	
  	handleClick(e) {
  	}
	
    render() {
        return (
            
Hello {this.props.name}!
) } } //导出组件 export default Component;

color.css脚本如下:

.red{
	color: red;
}

main.js脚本如下:

//ES6
import React from 'react';
import ReactDom from 'react-dom';
import Component from './components/Component.jsx';

ReactDom.render(
    ,
    document.getElementById('content')
);

(注)SayHello.jsx为ES5写法,后面会介绍到。

 

九.打包

执行命令行:

$ webpack -d

(注)监察打包 webpack --watch 其中copy+c结束监察,监察是指只要代码有变动即会自动打包。
打包成功后会在build目录下自动生成一个index.bundle.js文件,打开index.html文件,写入脚本:




	
		
		
		
	

	
		
		

打开浏览器运行,运行结果:
react系列(12)React+Webpack的组合搭建_第7张图片

 

 

 

至此,我们已经成功部署好了React+Webpack组合开发环境。当然,毕竟并不是所有初学者都学过ES6语法,那么我们可否用ES5组合开发呢?答案是可以的。我们把SayHello.jsx写入脚本如下:

var React = require('react');
var createReactClass = require('create-react-class');
var SayHello = createReactClass({
	render:function(){
		var style = {color:"red"};
		return (

Hello ES5(2)

); } }); exports = module.exports = SayHello;

然后更改main.js脚本为:

//ES6
//import React from 'react';
//import ReactDom from 'react-dom';
//import Component from './components/Component.jsx';
//
//ReactDom.render(
//  ,
//  document.getElementById('content')
//);

//ES5 写法1
var React = require('react');
var ReactDOM = require('react-dom');
var createReactClass = require('create-react-class');

var SayHello = createReactClass({
	render:function(){
		return (

Hello ES5(1)

); } }); ReactDOM.render(,document.getElementById("content")); //ES5 写法2 //var React = require('react'); //var ReactDOM = require('react-dom'); //var createReactClass = require('create-react-class'); //var SayHello = require('./components/SayHello'); //ReactDOM.render(,document.getElementById("content"));

打包后执行结果(上例中写法2为引入外部组件方式,效果与写法1一致):

react系列(12)React+Webpack的组合搭建_第8张图片

 

 

(新补充)关于webpack -d命令打包失败问题

有反馈说根据上面代码敲了一遍,发现打包不了。这是因为我再写这个demo的时候用的是webpack3.x版本,现在最新版本已经是4.23.0,可以通过命令webpack -v查看自己的版本。此处打包建议需要版本一致,所以可修改package.json文件,修改如下:

{
	"name": "react_demo",
	"version": "1.0.0",
	"description": "",
	"main": "index.js",
	"scripts": {
		"start": "webpack"
	},
	"author": "huangzp",
	"license": "ISC",
	"devDependencies": {
		"babel-core": "^6.26.0",
		"babel-loader": "^7.1.2",
		"babel-preset-es2015": "^6.24.1",
		"babel-preset-react": "^6.24.1",
		"create-react-class": "^15.6.2",
		"react": "^16.1.1",
		"react-dom": "^16.1.1",
		"webpack": "^4.23.0"
	}
}

然后通过命令先把原有node_modules清理:

npm install rimraf -g
rimraf node_modules

再重新初始化:

npm install

关于使用webpack4.x还有一个地方需要修改,就是该版本不再支持UglifyJs代码压缩方法,所以webpack.config.js文件修改如下:

var webpack = require('webpack');
module.exports = {
	//根目录
	context: __dirname + "",
	//文件入口
	entry: {
		index: './app/main.js'
	},
	//文件出口
	output: {
		path: __dirname + "/build", // 设置输出目录
		filename: '[name].bundle.js', // 输出文件名
		//		filename:'./build/[name].bundle.js'
	},
	module: {
		//rules加载器
		rules: [{
				test: /\.(js|jsx)$/, //【一个匹配rules所处理的文件的拓展名的正则表达式,这里用来匹配js和jsx文件(必须)】
				exclude: /node_modules/, //【屏蔽不需要处理的文件(文件夹)(可选)】
				loader: 'babel-loader' //【loader的名称(必须)】此处为可以转换ES6和JSX语法的加载器
			},
			{
				test: /\.css$/,
				loader: "style-loader!css-loader" //.css文件使用 style-loader 和 css-loader 来处理  
			},
			{
				test: /\.(jpeg|png|gif|svg)$/i,
				loader: 'url-loader?limit=8192&name=[name].[ext]' //图片文件使用 url-loader来处理,小于8kb的直接转为base64 
			}
		]
	},
	// 插件
	plugins: [
		// 默认会把所有入口节点的公共代码提取出来,生成一个common.js
		//new webpack.optimize.CommonsChunkPlugin('common'),
		// 压缩代码抬头注释
		new webpack.BannerPlugin('此处添加打包抬头注释!'),
		// 代码压缩
		//		new webpack.optimize.UglifyJsPlugin({
		//			compress: {
		//				warnings: false
		//			}
		//		})
	],
	// 代码压缩
	optimization: {
		minimize: false // 当发布环境打包时需设为true
	},
	//由于压缩后的代码不易于定位错误,配置该项后发生错误时即可采用source-map的形式直接显示你出错代码的位置
	devtool: 'eval-source-map',
	//其它解决方案配置
	resolve: {
		// 配置简写,配置过后,书写该文件路径的时候可以省略文件后缀。如require("common")
		extensions: ['.js', '.jsx', '.coffee']
	}
}

这样,webpack -d即可打包成功。

 

(新补充)综合应用参考案例

// 综合应用ES5
var React = require('react');
var ReactDOM = require('react-dom');
var createReactClass = require('create-react-class');
var $ = require('jquery');

// 内联样式
var stateCSS = {
	cursor: "pointer"
};

// 混合函数对象
var mixinCommon = {
	componentWillMount: function() {
		console.log("mix componentWillMount!");
	}
}

// 子组件数据传递
var ChildComp = createReactClass({
	componentDidMount: function() {
		this.setState({
			dataCallBackFun: this.props.callBackFun
		});
	},
	getInitialState: function() {
		return {
			dataFromParant: "",
			dataCallBackFun: null,
			respData: ""
		}
	},
	// 静态方法
	statics: {
		doMethod: function() {
			console.log("静态方法被调用!");
		}
	},
	setInputData: function(value) {
		this.setState({
			dataFromParant: value
		});
	},
	childDataChangeHandle: function(e) {
		this.setState({
			respData: e.target.value
		});
	},
	clickHandle: function(e) {
		this.state.dataCallBackFun(this.state.respData);
	},
	staticHandle: function(e) {
		ChildComp.doMethod();
	},
	render: function() {
		return(
); } }); // 列表组件展示 var ListComp = createReactClass({ render: function() { return(
    { this.props.listData.map(function(item,index){ return
  • ID:{item.id},值:{item.data}
  • }) }
); } }); // 父组件 var MyComp = createReactClass({ // 混合函数mixin mixins: [mixinCommon], // 默认参数 getDefaultProps: function() { return { msg: "helloui.prop" } }, // 状态变量 getInitialState: function() { return { param: "helloui.state", inValue: "", callBackValue: "", list: [] } }, // 操作事件 clickHandle: function(e) { this.setState({ param: "hello.clicked" }); }, // 父子组件参数传递 inputDataChangeHandle: function(e) { this.setState({ inValue: e.target.value }); }, // 父子组件参数传递 putDataToChildHandle: function(e) { this.refs.childcomp.setInputData(this.state.inValue); }, // 父子组件参数传递 childCallBackFunHandle: function(resp) { this.setState({ callBackValue: resp }); }, // 生命钩子函数 componentDidMount: function() { console.log('Mount挂载完成'); this.setState({ list: [{ id: "id1", data: "data1" }, { id: "id2", data: "data2" }, { id: "id3", data: "data3" } ] }); // ajax请求 $.ajax({ url: "https://api.github.com/users/octocat/gists", data: "", type: 'GET', timeout: 30000, error: function(response, state) { console.log(response); }, success: function(response, state) { console.log(response) } }); }, // 渲染 render: function() { return(
默认参数:{this.props.msg}
状态变量:{this.state.param}
); } }); ReactDOM.render(, document.getElementById("content")); // Element + Factory 用法 var EleComp = createReactClass({ render: function() { return(
{this.props.text}
); } }); var EleFactory = React.createFactory(EleComp); var MyElements = React.createElement('div', null, EleFactory({ text: 'element1' }), EleFactory({ text: 'element2' })); ReactDOM.render(MyElements, document.getElementById("elements"));

 

你可能感兴趣的:(前端集合,react)