这是React和ECMAScript2015系列文章的末了一篇,我们将继承探究React 和 Webpack的运用。
下面是一切系列文章章节的链接:
React | JS |
---|---|
什么是Webpack?
就像JSPM一样,Webpack
是你的前端运用的模块治理的解决方案。
运用Webpack,你可以用一种轻易的要领完全掌握你的运用资本。
为何Webpack这么受欢迎?主要有以下几个缘由:
Webpack运用npm作为外部模块源。假如你想增加React到你的项目中,只须要实行
npm install react
即可。这是一个附加的上风,由于你已晓得怎样将你喜好的库增加到你的项目中。你险些可以加载一切的东西,而不只是JavaScript。
Webpack
运用名字为loaders
的装载机来完成加载。这是对应的loaders清单Webpack有一个很壮大的开辟东西生态系统。像热更新如许的东西将戏剧性的转变你的开辟流程。
关于种种类型的使命有许多
Webpack plugins
。在大多数情况下,你可以运用已存在的解决方案。Webpack 有很漂亮的logo :)
Getting started
让我们最先从之前的系列文章中调解我们的运用顺序。
起首,我们将要装置初始的开辟依靠。
npm install --save-dev webpack
npm install --save-dev babel-core
npm install --save-dev babel-preset-es2015 babel-preset-react babel-preset-stage-0
在上面的列表中,webpack
是自诠释型的。Babel
是用于将ES6转换成ES5(假如你浏览了前面的React and ES6
系列文章,你应当对ES6和ES5异常熟习)。自从babel 6后你必需为每个分外的言语特征装置自力的包。这些包叫做presets
。我们装置es2015 preset
,react preset
和stage-0 preset
。关于更多关于babel 6
的信息,你可以浏览这篇文章。
下一步,装置非开辟依靠(react和react-dom包):
npm install --save react react-dom
如今在你的项目中基于Webpack最主要的一步。在你的项目根目录下面建立webpack.config.dev.js
文件。这个文件将用来打包你一切的在一个bundle(或许多个bundle)内里的JavaScript(在大多数项目中不只是JavaScript),打包完就可以在用户的浏览器中正式运转。
webpack.config.dev.js
的内容以下:
var path = require('path');
var webpack = require('webpack');
var config = {
devtool: 'cheap-module-eval-source-map',
entry: [
'./app.js'
],
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js',
publicPath: '/dist/'
},
plugins: [
new webpack.NoEmitOnErrorsPlugin()
]
};
module.exports = config;
以上代码的亮点:
Line 5. 在进步运用顺序的种种调试战略中,我们有一个挑选,你可以点击这里相识更多关于
cheap-module-eval-source-map
的内容。Lines 6-8. 这里我们定义了
app.js
为运用顺序的主进口。Lines 9-13. 这个设置制订
Webpack
将打包一切的模块成文件bundle.js
,而且将bundle.js
文件放到dist/
途径下面。
Webpack loaders
用Webpack
险些可以加载一切的东西到你的代码中(这里是清单)。Webpack运用的名字叫做Webpack装载机。
你可以制订文件扩展名关联到迥殊的装载机。
在我们的案例中,我们将运用babel-loader
来将ES2015 / ES6
的代码转换成ES5
.起首,我们须要装置npm
依靠包。
npm install --save-dev babel-loader
然后,经由过程增加一些新的装载机关键字到出口对象中来调解webpack.config.dev.js
文件的设置。
var config = {
... add the below code as object key ...
module: {
loaders: [
{
test: /\.js$/,
loaders: ['babel-loader'],
exclude: /node_modules/
}
]
}
};
module.exports = config;
这里须要重点注重的是,我们经由过程exclude
关键字的设置制止Webpack
剖析node_modules
文件夹内里的文件。
接下来我们在项目的根目录下面增加.babelrc
文件。
{
"presets": ["react", "es2015", "stage-0"]
}
这个文件是设置babel
以便可以运用前面我们增加的react
,es2015
和stage-0
presets。
如今,不管什么时候Webpack
碰到,比方:import CartItem from './cartItem.js'
,它将加载这个文件而且将ES6
转换成ES5
。
增加Webpack
开辟服务器
为了运转这个顺序,我们须要在服务器上运转这些文件。
荣幸的是,Webpack
生态系统已供应一切你须要的东西。你可以运用Webpack开辟服务器或许Webpack开辟中间件,比方:Express.js。
我们将运用后者。上风是在内存中处置惩罚文件时速度快。
让我们装置npm
模块:
npm install --save-dev webpack-dev-middleware express
下一步,在根目录下面增加server.js
文件:
var path = require('path');
var express = require('express');
var webpack = require('webpack');
var config = require('./webpack.config.dev');
var app = express();
var compiler = webpack(config);
var port = 3000;
app.use(require('webpack-dev-middleware')(compiler, {
noInfo: true,
publicPath: config.output.publicPath
}));
app.use(require('webpack-hot-middleware')(compiler));
app.get('*', function (req, res) {
res.sendFile(path.join(__dirname, 'index.html'));
});
app.listen(port, function onAppListening(err) {
if (err) {
console.error(err);
} else {
console.info('==> Webpack development server listening on port');
}
});
这是典范的运用Webpack Dev Middleware
的express.js
服务器。
增加热革新模块
Webpack Dev Middleware
已包含了热革新的特征。不管什么时候,你的代码发生变化,它都邑马上革新页面。
假如想简朴的看看热革新的演示结果,可以看看Dan Abramov
的视频。
为了激活Hot Module Reloading
,你起首得装置必需得npm
包。
npm install --save-dev webpack-hot-middleware
然后在webpack.config.dev.js
文件中设置entry
和plugins
:
var config = {
entry: [
'./app.js',
'webpack-hot-middleware/client'
],
...
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin()
]
};
module.exports = config;
假如想对React 运用更进一步运用模块革新其实有许多种要领。
个中一个简朴的要领就是装置babel-preset-react-hmre
模块。
npm install --save-dev babel-preset-react-hmre
调解.babelrc
文件的内容:
{
"presets": ["react", "es2015", "stage-0"],
"env": {
"development": {
"presets": ["react-hmre"]
}
}
}
到这一步,这个运用就具有热革新的功用。
末了几步
建立
index.html
文件
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>React and ES6 Part 6</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/foundation/5.5.2/css/foundation.min.css">
</head>
<body>
<nav class="top-bar" data-topbar role="navigation">
<section class="top-bar-section">
<ul class="left">
<li class="active">
<a href="http://egorsmirnov.me/2016/04/11/react-and-es6-part6.html" target="_blank">
Blog post at egorsmirnov.me: React and ES6 - Part 6, React and ES6 Workflow with Webpack
</a>
</li>
</ul>
</section>
</nav>
<div class="root"></div>
<script src="/dist/bundle.js"></script>
</body>
</html>
建立
app.js
文件
import React from 'react';
import ReactDOM from 'react-dom';
import CartItem from './cartItem.js';
const order = {
title: 'Fresh fruits package',
image: 'http://images.all-free-download.com/images/graphiclarge/citrus_fruit_184416.jpg',
initialQty: 3,
price: 8
};
ReactDOM.render(
< CartItem
title={order.title}
image={order.image}
initialQty={order.initialQty}
price={order.price
}
/>,
document.querySelector('.root')
)
;
建立
cartItem.js
文件
import React from 'react';
export default class CartItem extends React.Component {
static propTypes = {
title: React.PropTypes.string.isRequired,
price: React.PropTypes.number.isRequired,
initialQty: React.PropTypes.number
};
static defaultProps = {
title: 'Undefined Product',
price: 100,
initialQty: 0
};
state = {
qty: this.props.initialQty,
total: 0
};
constructor(props) {
super(props);
}
componentWillMount() {
this.recalculateTotal();
}
increaseQty() {
this.setState({qty: this.state.qty + 1}, this.recalculateTotal);
}
decreaseQty() {
let newQty = this.state.qty > 0 ? this.state.qty - 1 : 0;
this.setState({qty: newQty}, this.recalculateTotal);
}
recalculateTotal() {
this.setState({total: this.state.qty * this.props.price});
}
render() {
return (
<article className="row large-4">
<figure className="text-center">
<p>
<img src={this.props.image}/>
</p>
<figcaption>
<h2>{this.props.title}</h2>
</figcaption>
</figure>
<p className="large-4 column"><strong>Quantity: {this.state.qty}</strong></p>
<p className="large-4 column">
<button onClick={this.increaseQty.bind(this)} className="button success">+</button>
<button onClick={this.decreaseQty.bind(this)} className="button alert">-</button>
</p>
<p className="large-4 column"><strong>Price per item:</strong> ${this.props.price}</p>
<h3 className="large-12 column text-center">
Total: ${this.state.total}
</h3>
</article>
);
}
}
修正package.json
如今已将前面一切碎片化的代码已整合在一个项目中。
我们须要在package.json
文件的scripts
地区增加一些剧本。
{
"name": "awesome-application",
"version": "1.0.0",
...
"scripts": {
"start": "node server.js"
},
...
}
运转项目
Webpack临盆环境设置
如今我们可以在服务器上运转我们的运用顺序而且可以经由过程热模块更新革新我们的页面。
然则假如我们想要将产物布置到临盆环境?没问题,Webpack
有对应的解决方案。
建立webpack.config.prod.js
文件,文件内容为:
var path = require('path');
var webpack = require('webpack');
var config = {
devtool: 'source-map',
entry: [
'./app.js'
],
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js'
},
plugins: [
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': JSON.stringify('production')
}
}),
new webpack.optimize.UglifyJsPlugin({
compressor: {
warnings: false
}
})
],
module: {
loaders: [
{
test: /\.js$/,
loaders: ['babel-loader'],
exclude: /node_modules/
}
]
}
};
module.exports = config;
它和开辟形式下的设置文件有点类似,然则有以下不同点:
热革新的功用不再有,由于在临盆环境中不须要这个功用。
JavaScript bundle
被依靠于webpack.optimize.UglifyJsPlugin
的UglifyJs
紧缩。环境变量
NODE_ENV
被设置成production
。这须要屏障来自React开辟环境中的正告。
下一步,更新package.json
文件中的scripts
:
{
...
"scripts": {
"start": "node server.js",
"clean": "rimraf dist",
"build:webpack": "NODE_ENV=production webpack --progress --colors --config webpack.config.prod.js",
"build": "npm run clean && npm run build:webpack"
},
...
}
到如今为止,假如你在掌握台运转npm run build
,紧缩文件bundle.js
将被建立而且放在dist/
途径下面。这个文件预备在临盆环境中运用。
这只是刚刚最先
我们适才学到的东西只是Webpack
的一些基本。
Webpack
是一个很轻易入门的东西,然则要想通晓,须要点时候好好研讨研讨。
参考文档
社群品牌:从零到壹全栈部落
定位:寻觅共好,配合进修,延续输出全栈手艺社群
业界声誉:IT界的逻辑思维
文明:输出是最好的进修体式格局
官方民众号:全栈部落
社群发起人:春哥(从零到壹创始人,交换微信:liyc1215)
手艺交换社区:全栈部落BBS
全栈部落完全系列教程:全栈部落完全电子书进修笔记
关注全栈部落官方民众号,每晚十点吸收系列原创手艺推送 |
---|