准备工作
目前webpack作为目前国内最火的打包及加载工具之一,经常在react工程中使用,接下来我们来详细了解下webpack的使用姿势
在接下来的操作步骤之前,需要先配置修改react工程下的package.json,增加devDependencies如下:
"css-loader": "^0.23.1",
"extract-text-webpack-plugin": "^1.0.1",
"less-loader": "^2.2.2",
"portfinder": "^0.4.0",
"react-hot-loader": "^1.3.0",
"style-loader": "^0.13.0",
"webpack": "^1.12.9",
"webpack-dev-server": "^1.14.0",
"react": "^0.14.0",
"react-dom": "^0.14.0",
"react-router": "^2.0.0-rc5"
然后根据package.json使用npm install安装依赖包,接下来就要开始我们的webpack之旅
- 其中react的工程文件结构为
- project
- demo01
- index.html
- main.js
- components
- list.js
- webpack.config.js
- project
- 工程文件具体内容(除 webpack.config.js之外)就不再赘述,网上均有类似内容,然后执行webpack,会出现webpack:command not found的错误提示,经资料查证,方法之一需在~/.bash_profile中添加如下设置: export NODE_PATH=”/usr/local/lib/node_modules,然而这个并不现实(并不是全局安装的webpack),方法之二是在package.json中加入
“scripts”: {
“build”: “webpack”
}
然后执行npm run build 即可实现webpack操作,接下来我们需要详细分析下webpack.config.js配置文件可以包含哪些内容~
webpack.config.js配置详解
最为基础的有以下几项:
- entry: 定义了打包的入口文件,数组中的所有文件会按顺序打包并寻找相关依赖(webpack建议使用commonJS的方式引入及定义依赖),数组数大于一经常是为多页面工程设计所需
- output: 定义输出文件的位置,常用参数有:
- path: 打包文件存放的绝对路径
- publicPath: 网站运行时的访问路径
filename: 打包后的文件名
如图为我们最原始的webpack.config.js文件
此时执行npm run build,则并不会在demo01文件夹下生成build/bundle_1.js,而是会报出You may need an appropriate loader to handle this file type这样的红色错误,这是因为我们用了react!!! 没有相关的预处理怎么可以,这也是webpack最为强大的地方,图片,js,css等均可通过loader的方式引入进来{
module: {
loaders: [
{ test: /.js$/, loader: “react” }
]
}
}
其中test正则匹配所需处理文件,loader为所需加载器,那如果需要多个loader去处理这些文件呢,我们可以将其中的loader替换成 loaders: [‘babel?presets[]=react,presets[]=es2015’] 其中presets后的为预处理工具,辅助babel处理第二步的transform过程,详细可见babel官网 (当使用loaders则不可再使用query选项)
那么此时执行npm run build 便会执行webpack打包过程,接下来我们谈谈webpack其他配置项
升级配置项及优化性能
- debug:debug模式开始,webpack该配置项共有七种,有inline-source-map,debug等,目前我采用devtool: ‘#source-map’方式(仅在开发时使用,影响性能)
- output: 通过配置output.libraryTarget,可以自定义输出的模块类型,包括AMD,CommonJS,变量等,通过设置library,可以定义其模块名称
plugins: 引入对应插件,插件列表在webpack官网可搜索到,其中较为主要的几个有:
- new webpack.optimize.CommonsChunkPlugin,该插件的引入可抽离文件的公共部分,譬如entry有 vendor: [“jquery”, “underscore”, …]的相关依赖时,我们可通过
把全部vendor依赖打包在vendor.bundle.js中
当entry存在多个文件需要打包时,使用CommonsChunk插件可将多个文件中的公共部分抽取出来,实现按需加载及缓存,提升页面性能 - new webpack.optimize.LimitChunkCountPlugin({maxChunks: 15}),new webpack.optimize.MinChunkSizePlugin({minChunkSize: 10000})为第一个的优化项,限制chunk的数目及chunk的最小大小,防止盲目的抽取公共部分,进而提高性能~
- new webpack.optimize.UglifyJsPlugin()和uglifyjs类似,压缩对应的js文件,如果使用css loader,则也可以压缩css文件
- extract-text-webpack-plugin实现css文件的单独抽离,而不是均包含在最终生成的 js文件中,有三种配置方式 ,new ExtractTextPlugin(“[name].css”)将每个entry下的css抽离成多个文件,
new ExtractTextPlugin(“style.css”, {
allChunks: true
})则将全部css文件合成一个,如若配合CommonsChunkPlugin使用,则可实现和CommonsChunkPlugin同样的css效果~
- new webpack.optimize.CommonsChunkPlugin,该插件的引入可抽离文件的公共部分,譬如entry有 vendor: [“jquery”, “underscore”, …]的相关依赖时,我们可通过
resolve: 其中最常用的有alias及 extensions,其中alias作用为别名定义,可定义webpack打包的文件别名(防止长文件的多次书写),譬如 alias下定义moment: “moment/min/moment-with-locales.min.js”,后期便可使用require(‘moment’)得到moment-with-locales.min.js文件,同时譬如我们不需要引入node_modules的react的全部,而只需引入下面的部分react.min.js,则也可以通过react别名定义,重写其查找路径,从而减少其打包时间,’react’:’react/dist/react.min.js’
extensions则自动扩展文件后缀名,意味着我们require模块可以省略不写后缀名总结与反思
以前看网上教程一直以为是蛮简单的一件事,但当自己全部重头做起及优化还是一件比较费脑筋的事情,官网尽管是英文的而且内容繁杂,但是官网往往是最靠谱的(当然官网内容仍不是很完全,从babel-loader的github介绍上我们也可找出关于webpack的不少优化项,可以下周再续)
本来还有react-hot-loader这个利器需要加进来,但限于篇幅,下周再续
- 绝大多数是总结项目经验及网上教程,官网而来,也许有纰漏或不准确的地方,希望后期会更正
更新
- 刚刚看到一篇很好的webpack文章,里面有很多补充优化了本文提到的webpack配置,https://segmentfault.com/a/1190000005770042 参考
- https://github.com/babel/babel-loader 参考自babel-loader官网,里面的 query: {
presets: [‘es2015’],
plugins: [‘transform-runtime’]
}中的plugins可以减少文件的依赖次数,可以起到优化性能的作用,而 loader: ‘babel?cacheDirectory’的cacheDirectory则可以实现loader结果的缓存~,也可以起到优化性能的作用,但仅限于该babel-loader