Webpack是目前最火的前端自动化工具,它是一个module bundler并和大部分现代前端相关模块完美结合,包括Babel,ReactJS等等。本文从新手的角度一步一步用webpack配置一个react项目。
安装
首先要知道:
- Webpack和NPM配合比较好,Bower泪目。
- Webpack会使用模块系统,CommonJS ES6等。
全局安装Webpack:
npm install webpack -g
最简单的build
创建两个文件 index.html & app.js
app.js
document.write('welcome to my app');
console.log('app loaded');
index.html
在控制台里运行:
webpack ./app.js bundle.js
这个命令使用我们刚创建的app.js文件的相对路径作为第一个参数,表示这是我们希望的js文件入口,后面的参数则是我们希望build完成后webpack为我们创建的文件。这样就完成了最简单的webpack的build。
定义一个配置文件
Webpack中的配置文件基本上是一个commonJS模块。配置文件里面放了我们需要的配置项,loader(后面讲)还有一些其他的属性。
在刚才的那个目录定义一个webpack.config.js,这就是我们的Webpack配置文件,加入以下代码:
module.exports = {
entry: "./app.js",
output: {
filename: "bundle.js"
}
}
entry---该属性指的是我们文件的最顶层的入口,它可以是一个文件也可以是一个文件数组。在这里,我们就传入app.js。
output---该属性指的是输出文件。我们这里只给它指定一个名字bundle.js。
现在我们简单的运行:
webpack
这样Webpack就会按照配置文件的属性,完成build。
其他配置项
Watchmode
当配置了Watchmode,每当又文件修改的时候,Webpack都会自动重新build。
启用Watchmode有两种方式:
1.命令行
webpack --watch
2.在config.js中加入watch属性配置,并设为true
module.exports = {
entry: "./app.js",
output: {
filename: "bundle.js"
},
watch: true
}
Webpack Dev Server
Webpack自己有一个web server叫Webpack Dev Server。
可以在控制台全局安装:
npm install webpack-dev-server -g
然后启动:
webpack-dev-server
然后你可以访问http://localhost:8080/webpack-dev-server/就可以看到你的应用。
Webpack官方文档:
Dev server使用了watch模式。并且阻止了webpack将build结果输出到硬盘上,而是从内存中读取。这意味这你看不到打包好的bundle.js。如果你需要,则还是要运行webpack命令。
在dev server运行时,你本地的任何修改都会让浏览器自动刷新(hot-loading)。
默认hot-loading是打开的。如果你想禁用或者移除页面顶部的页面状态,则可以直接访问http://localhost:8080/ 。
如果你只是单纯的想移除状态条,不想禁用hot-loading,则可以运行:
webpack-dev-server --inline
然后访问http://localhost:8080/ 。
打包多个文件
1.require文件
为了展示webpack怎么打包多个文件,我们加入logger.js,代码就是打个log:
console.log('logger.js is now loaded...');
在app.js中require该文件:
require('./logger');
然后重新运行webpack-dev-server,你可以看到log正常输出。
2.在webpack.config.js中添加多个文件入口
我们添加一个和app.js没有关系的js文件,global.js:
console.log('global.js is now loaded...');
然后修改webpack.config.js:
module.exports = {
entry: ["./global.js", "./app.js"],
output: {
filename: "bundle.js"
}
}
同样,重新运行dev server,可以看到global.js的log也输出了。
Webpack loaders 和 preloaders
可以这么理解,loader是webpack学习新功能的渠道。(这里译者多说两句,webpack相对gulp等简化了很多的配置,不需要开发人员去配置压缩插件,合并插件等等,给人的感觉就是gulp是零散的工具,而webpack是一套标准的解决方案,但是怎么给这套方案添砖加瓦呢,这就是loader的功能了。)
官方文档:Loader允许使用require或者‘load’对它们进行预处理。Loader和其他构建工具里面的task任务很像,提供了前端一套完整的步骤。Loader可以转义,比如将CoffeeScript转成JavaScript。甚至可以在JS文件中require样式css文件。
下面我们举例安装两个常用的loader:Babel和JSHint。首先我们需要安装这些npm模块。
npm install babel-core babel-loader jshint jshint-loader node-libs-browser babel-preset-es2015 babel-preset-react webpack --save-dev
babel-core即babel的包。
babel-loader即babel的webpack loader。
jshint即js语法检测器。
jshint-loader即JSHint的webpack loader。
node-libs-browser提供了wepack浏览器使用的node模块。
babel-preset-es2015及es2015的babel预设。
babel-preset-react是babel针对react的预设。
Webpack配合Babel使用
ok,让我们写点es6,看看webpack能不能配合babel打包。
1.打开logger.js,改成下面这样:
let checkName= (firstName, lastName) => {
if(firstName !== 'nader' || lastName !== 'dabit') {
console.log('You are not Nader Dabit');
} else {
console.log('You are Nader Dabit');
}
}
checkName('nader', 'jackson');
2.将logger.js重命名为logger.es6
3.打开webpack.config.js,添加babel loader:
module.exports = {
entry: ["./global.js" , "./app.js"],
output: {
filename: "bundle.js"
},
module: {
loaders: [
{
test: /\.es6$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
presets: ['react', 'es2015']
}
}
]
},
resolve: {
extensions: ['', '.js', '.es6']
},
}
我们逐一解释一下这些关键字:
- test: 检测哪些文件需要此loader,是一个正则表达式,这里我们过滤所有es6后缀的文件。
- exclude: 忽略哪些文件,这里我们忽略node_module中的文件。
- loader: 我们将使用的loader。
- query: 我们传给loader的属性。
- cacheDirectory: 默认为false,设置之后,会将build文件换成在配置的文件夹中,然后之后的build就会从cache中读取,避免多次build的缓慢。
- presets:我们这里使用刚安装的react和es2015.
我们这里还配置了一个‘ resolve‘属性,reslove帮助我们配置那些后缀的文件是需要处理的,我们不需要在代码中写定后缀名,比方说,我们可以写:
require('./logger');
而不需要写:
require('./logger.es6');
搞定,现在重新运行dev server可以看到结果“You are not Nader Dabit”。
Preloaders: 使用JSHint
Preloader是在loader运行之前运行的,这里我们用JSHint作为示例:
module.exports = {
entry: ["./global.js" , "./app.js"],
output: {
filename: "bundle.js"
},
module: {
preLoaders: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'jshint-loader'
}
],
loaders: [
{
test: /\.es6$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
cacheDirectory: true,
presets: ['react', 'es2015']
}
}
]
},
resolve: {
extensions: ['', '.js', '.es6']
}
}
重启,可以看到JSHint运行并报了一个错误:
创建Start脚本
我们经常配合npm的package.json使用webpack,可以把脚本写在npm script中简化要手动敲的命令。
在package.json中添加:
"scripts": {
"start": "webpack-dev-server"
},
然后运行:
npm start
这样写也方便我们以后需要添加更多的选项。
开发环境和产线环境分离
产线bundle
一个production的bundle会压缩代码,在webpack中很简单:
webpack -p
加个-p属性就可以了。
使用多个webpack config文件
首先创建一个webpack-production.config.js作为我们产线打包的配置文件,我们这里安装strip-loader,它会帮我们过滤代码中不需要出现在产线的那部分,比方console.log:
npm install strip-loader --save-dev
然后在webpack-production.config.js加入:
var WebpackStripLoader = require('strip-loader');
var devConfig = require('./webpack.config.js');
var stripLoader = {
test: [/\.js$/, /\.es6$/],
exclude: /node_modules/,
loader: WebpackStripLoader.loader('console.log')
}
devConfig.module.loaders.push(stripLoader);
module.exports = devConfig;
- WebpackStripLoader引入strip-loader
- devConfig包含我们之前在webpack.config.js中的配置。
- devConfig.module.loaders.push(stripLoader)将此loader塞入webpack.config.js定义的loader数组中。
然后在控制台运行:
webpack --config webpack-production.config.js -p
这样我们就为产线build了一个压缩的并没有console.log的js文件。
React 和 Webpack
好,我们现在把react加进去。首先安装react:
npm install react react-dom --save
然后创建一个react组件hello.js:
import React from "react";
export default React.createClass({
render: function() {
return (
Hello, {this.props.name}!
);
},
});
打开我们之前的app.js,改成:
import React from "react";
import ReactDOM from "react-dom";
import Hello from "./hello";
ReactDOM.render(
,
document.body
);
最后修改webpack.config.js,给babel-loader的test属性添加js后缀文件过滤。这样babel就会去解析js文件,我们就可以在js中使用jsx了。重启dev server,搞定!