webpack是一个模块管理工具,它跟grunt,gulp,fis等诸多前端工具一样,为了使日渐增多的js代码变得合理有序,应运而生的模块化工具
1 - 它同时支持commonjs和AMD规范(甚至混合的形式); 2 - 它可以打成一个完整的包,也可以分成多个部分,在运行时异步加载(可以减少第一次加载的时间); 3 - 依赖在编译时即处理完毕,可以减少运行时包的大小; 4 - Loaders可以使文件在编译时得到预处理,这可以帮我们做很多事情,比如说模板的预编译,图片的base64处理; 5 - 丰富的和可扩展的插件可以适应多变的需求。
下面是我的webpack的配置:
var webpack = require('webpack'); var commonsPlugin = new webpack.optimize.CommonsChunkPlugin('common.js'); module.exports = { //插件项 plugins: [commonsPlugin], //页面入口文件配置 entry: { index : './app/js/index.js' }, //入口文件输出配置 output: { path: 'dist/js', filename: '[name].js' }, module: { //加载器配置 loaders: [ { test: /\.css$/, loader: 'style-loader!css-loader'}, { test: /\.jsx?$/, loader: 'babel',exclude: /node_modules/,query: {presets: ['es2015','react']}}, { test: /\.(png|jpg)$/, loader: 'url-loader?limit=8192'} ] }, //其它解决方案配置 resolve: { root: 'E:/react/app', //绝对路径 extensions: ['', '.js','css'], alias: { ReactDom : 'react-dom.js' } } };
webpack.config.js文件通常放在项目的根目录中,它本身也是一个标准的Commonjs规范的模块。在导出的配置对象中有几个关键的参数:
entry
entry可以是个字符串或数组或者是对象。
当entry是个字符串的时候,用来定义入口文件:
entry: './js/main.js'
当entry是个数组的时候,里面同样包含入口js文件,另外一个参数可以是用来配置webpack提供的一个静态资源服务器,webpack-dev-server。webpack-dev-server会监控项目中每一个文件的变化,实时的进行构建,并且自动刷新页面:
entry: [ 'webpack/hot/only-dev-server', './js/app.js' ]
当entry是个对象的时候,我们可以将不同的文件构建成不同的文件,按需使用,比如在我的hello页面中只要\<script src='build/Profile.js'></script>引入hello.js即可:
entry: { hello: './js/hello.js', form: './js/form.js' }
output
output参数是个对象,用于定义构建后的文件的输出。其中包含path和filename:
output: { path: './build', filename: 'bundle.js' }
module
关于模块的加载相关,我们就定义在module.loaders中。这里通过正则表达式去匹配不同后缀的文件名,然后给它们定义不同的加载器。
module: { //加载器配置 loaders: [ { test: /\.css$/, loader: 'style-loader!css-loader'}, { test: /\.jsx?$/, loader: 'babel',exclude: /node_modules/,query: {presets: ['es2015','react']}}, { test: /\.(png|jpg)$/, loader: 'url-loader?limit=8192'} ] }
resolve
webpack在构建包的时候会按目录的进行文件的查找,resolve属性中的extensions数组中用于配置程序可以自行补全哪些文件后缀:
resolve: { root: 'E:/react/app', //绝对路径 extensions: ['', '.js','css'], alias: { ReactDom : 'react-dom.js' } }
plugin
webpack提供了丰富的组件用来满足不同的需求,当然我们也可以自行实现一个组件来满足自己的需求。
plugins: [ new webpack.optimize.CommonsChunkPlugin('common.js'); ],
externals
当我们想在项目中require一些其他的类库或者API,而又不想让这些类库的源码被构建到运行时文件中,这在实际开发中很有必要。此时我们就可以通过配置externals参数来解决这个问题:
externals: { "jquery": "jQuery" }
这样我们就可以放心的在项目中使用这些API了:var jQuery = require("jquery");
webpack与gulp并不矛盾,甚至一起使用会得到最大化的利益。使用webpack进行assets编译,使用gulp进行打包似乎就是为了让它们各司其职,用其所长。
react-hot-loader加载器:
配置一个react-hot加载器,通过它,可以实现对react组件的热替换。
在entry参数中配置了`webpack/hot/only-dev-server`,所以我们只要在启动webpack开发服务器时开启--hot参数,就可以使用react-hot-loader了。
"scripts": { "start": "webpack-dev-server --hot --progress --colors", "build": "webpack --progress --colors" }
webpack-dev-server:web服务器
一个基于Node.js Express框架的开发服务器,它是一个静态资源Web服务器,对于简单静态页面或者仅依赖于独立服务的前端页面,都可以直接使用这个开发服务器进行开发。在开发过程中,开发服务器会监听每一个文件的变化,进行实时打包,并且可以推送通知前端页面代码发生了变化,从而可以实现页面的自动刷新。
react-hot-loader + webpack-dev-server 可以实现类似gulp-connect的功能: 构建服务器,代码修改实时刷新
1.下载安装两个插件
npm install -g webpack-dev-server
npm install —save-dev react-hot-loader
2.之后,Webpack开发服务器需要开启HMR参数hot,为了方便,我们创建一个名为server.js的文件用以启动Webpack开发服务器:
var webpack = require('webpack'); var WebpackDevServer = require('webpack-dev-server'); var config = require('../webpack.config'); new WebpackDevServer(webpack(config), { publicPath: config.output.publicPath, hot: true, noInfo: false, historyApiFallback: true }).listen(3000, '127.0.0.1', function (err, result) { if (err) { console.log(err); } console.log('Listening at localhost:3000'); });
3.为了热加载React组件,我们需要在前端页面中加入相应的代码,用以接收Webpack推送过来的代码模块,进而可以通知所有相关React组件进行重新Render。加入这个代码很简单:
entry: [ 'webpack-dev-server/client?http://127.0.0.1:3000', 'webpack/hot/only-dev-server', './scripts/entry' ]
PS: output里面还需要配置一个publicPath,serverJS里面有用到
需要注意的是,这里的client?127.0.0.1:3000需要和在server.js中启动Webpack开发服务器的地址匹配。
4.配置一下plugins,加上热替换的插件和防止报错的插件:
plugins: [ new webpack.HotModuleReplacementPlugin(), new webpack.NoErrorsPlugin() ]
5.下一步,我们需要让Webpack用react-hot-loader去加载React组件,如上一节所介绍,这通过加载器配置完成:
loaders: [{ test: /\.js$/, exclude: /node_modules/,
include : './app' loader: 'react-hot!jsx-loader?harmony' }, … ]
PS: loaders里面的include是必须的。。。。不然会报错
做完这些配置之后,使用Node.js运行server.js:
node server.js
这样,React的热加载开发环境即配置完成,任何修改只要以保存,就会在页面上立刻体现出来。无论是对样式修改,还是对界面渲染的修改,甚至事件绑定处理函数的修改,都可以立刻生效,不得不说是提高开发效率的神器。
babel-loader加载器:babel用于解析es6
1.下载babel加载器
npm install --dave-dev babel-loader
2.在加载器中使用babel:
{ test: /\.jsx?$/, loader: 'babel-loader'},
运行代码,webpack会报错(解析es6和jsx均不成功),这是为什么呢?
babel-loader解析es6,还需要插件支持,同时解析jsx也需要插件支持:
npm install --dave-dev babel-preset-es2015
npm install --dave-dev babel-preset-react
配置
{ test: /\.jsx?$/, loader: 'babel', exclude: /node_modules/, query: { presets: [ 'es2015', 'react' ] } },
这样就可以成功解析es6和jsx了