Webpack是什么?
Webpack是当下比较热门的前端资源模块化管理和打包工具。对于webpack来讲一切资源皆模块,它可以把诸如JS(含JSX)、coffee、样式(含less/sass)、图片等都作为模块来使用和处理,将许多松散的模块按照依赖和规则打包成适合生产环境部署的web前端资源。
使用webpack的优势
1. 物理上的模块化转变为逻辑上的模块化
在编写大型应用时,往往需要将一个部分分解为若干个模块分配给不同的开发人员进行编写,每个人所编写的模块代码最后都会以<script src=”/js/module”></script>引入到html页面中,这样做虽然使代码结构上更加清晰,但是每个页面都要向服务器请求多个资源。Webpack能将琐碎的模块打包为一个文件,在逻辑上代码仍然是模块划分,但是最终的文件会将所有的模块统统涵盖。
2. 可以把更多的资源当做模块使用
Webpack支持引入多种类型资源,尤其在做插件开发的时候,为了降低与主程序的耦合度都会在插件函数中加载该插件所有需要的资源,此时webpack就是不错的选择。
3. 支持多种规范编写
webpack 是以commonJS的形式来书写脚本滴,但对AMD/CMD的支持也很全面,方便旧项目进行代码迁移
webpack的使用
下面介绍一个完整的项目搭建流程,首先在磁盘上创建文件夹project和相关文件,并使用cd命令进入到当前目录。使用npm初始化一个配置文件
npm init

这里一路默认Enter键即可,最后在当前目录下回生成package.json文件
按照下图创建工程目录和文件

使用npm将webpack安装到全局(这里使用了淘宝镜像)
npm install webpack –g –-registry=https://registry.npm.taobao.org
如果针对自己的项目使用如下命令安装到当前项目
npm install webpack –-save-dev --registry=https://registry.npm.taobao.org
index.html简单地引入js文件即可(暂时不考虑文件在哪里)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <script type="text/javascript"src="./build/index.build.js"></script> </body> </html>
在js目录下创建三个文件分别命名为index.js、module1.js和module2.js
// index.js内容 var module1 = require('./module1') var module2 = require('./module2') console.log(module1) console.log('=================') console.log(module2)
// module1.js内容 module.exports = { content: { title: 'module1', notes: 'i am first module' }, other: { name: 'Liu', age: 22 } }
// module2.js内容 module.exports = { content: { title: 'module2', notes: 'i am second module' }, other: { name: 'Ding', age: 21 } }
在webpack.config.js中配置我们的webpack执行任务
const path = require('path') const webpack = require('webpack') module.exports = { entry: { index: './web/js/index.js' }, output: { path: path.resolve('./web/build'), filename: '[name].build.js' }, devtool: 'source-map' }
在命令行执行webpack后发现web目录下多出了build目录


至此,一个简单的测试案例完成,在浏览器中打开index.html并观察控制台输出情况

我们在回过头看看webpack.config.js文件中各项配置的具体含义
entry: { index: './web/js/index.js' }
entry值得是模块的入口,其值为一个对象,key和value分别代表着打包后的文件名和打包入口文件,若存在多个打包文件则依次定义。
output: { path: path.resolve('./web/build'), filename: '[name].build.js' }
output和entry对应,是文件打包后输出的相关配置。path指带输出文件目录,filename指的是输出的文件名称。output只需配置一个便可以适应所有的输入文件,而name指的就是entry中配置的key。
devtool指生成Source Maps的格式。开发总是离不开调试,如果可以更加方便的调试当然就能提高开发效率,不过打包后的文件有时候你是不容易找到出错了的地方对应的源代码的位置的,Source Maps就是来帮我们解决这个问题的。
通过简单的配置后,Webpack在打包时可以为我们生成的source maps,这为我们提供了一种对应编译文件和源文件的方法,使得编译后的代码可读性更高,也更容易调试。
在webpack的配置文件中配置source maps,需要配置devtool,它有以下四种不同的配置选项,各具优缺点,描述如下:

接下来介绍webpack的插件功能plugins。要使用某个插件,我们需要通过npm安装它,然后要做的就是在webpack配置中的plugins关键字部分添加该插件的一个实例(plugins是一个数组)继续看例子,我们添加了一个实现压缩的插件。
const path = require('path') const webpack = require('webpack') module.exports = { entry: { index: './web/js/index.js' }, output: { path: path.resolve('./web/build'), filename: '[name].build.js' }, devtool: 'source-map', plugins: [ new webpack.optimize.UglifyJsPlugin({ compress: { warnings: false, }, output: { comments: false, }, }) ] }
在当前工程目录下执行webpack命令可以发现和之前没有什么变化,但是文件大小和之前相比变得更小了,这就是压缩插件所实现的功能。

webpack的插件功能比较强大,对应的插件应用也比较多,需要实现什么功能直接在百度上就可搜索到相关的插件模块,npm引入之后就可以对着API文档使用了。
最后来看看webpack的重头戏——loaders
Loaders是webpack中最让人激动人心的功能之一了。通过使用不同的loader,webpack通过调用外部的脚本或工具可以对各种各样的格式的文件进行处理,比如说分析JSON文件并把它转换为JavaScript文件,或者说把下一代的JS文件(ES6,ES7)转换为现代浏览器可以识别的JS文件。或者说对React的开发而言,合适的Loaders可以把React的JSX文件转换为JS文件。
接下来看一个导入json模块的例子。要想打包的时候支持json格式文件的加载,我们必须先引入json模块:
npm install --save-dev json-loader –-registry=https://registry.npm.taobao.org
我们把webpack.config.js的内容改为:
const path = require('path') const webpack = require('webpack') module.exports = { entry: { index: './web/js/index.js' }, output: { path: path.resolve('./web/build'), filename: '[name].build.js' }, devtool: 'source-map', module: { loaders: [{ test: /\.json$/, loader: 'json' }] }, plugins: [ new webpack.optimize.UglifyJsPlugin({ compress: { warnings: false, }, output: { comments: false, }, }) ] }
然后在web/js目录下创建config.json文件
{ "server": "127.0.0.1:8080", "path": "D:/demo/vux/project", "port": "8088", "local": ["/web/", "/wap/","/res/"], "map": { "/web/wap/": "/web/wap/" } }
并将index.js内容改为:
// index.js内容 var module1 = require('./module1') var module2 = require('./module2') var config = require('./config.json') console.log(module1) console.log('=================') console.log(module2) console.log(config)
打包后查看结果

在webpack中比较常见的加载器是html、json、style!css、babel(语法转换器),详细看一下babel的用法。首先npm引入babel加载器的模块:
npm install --save-dev babel-core babel-loaderbabel-preset-es2015 babel-preset-react --registry=https://registry.npm.taobao.org
为了让webpack支持ES6的语法webpack.config.js中配置如下
const path = require('path') const webpack = require('webpack') module.exports = { entry: { index: './web/js/index.js' }, output: { path: path.resolve('./web/build'), filename: '[name].build.js' }, devtool: 'source-map', resolve: { extensions: ['', '.js'], alias: { vue: 'vue/dist/vue.js' } }, module: { loaders: [{ test: /\.json$/, loader: 'json' }, { test: /\.js$/, exclude: /node_modules/, loader: 'babel', //在webpack的module部分的loaders里进行配置即可 query: { presets: ['es2015'] } }] } }
我们将index.js改为ES6导入的语法:
// index.js内容 import module1 from './module1' const {content, other} = module1 console.log(module1) console.log(content) console.log(other)

webpack的基本操作到这里已经差不多了,当然我们在开发项目中不只是使用webpack进行项目管理,还会借助其他管理工具,例如grunt、gulp等。gulp拥有良好的任务操作,在项目中一般采用webpack来负责模块管理,而gulp等负责诸如压缩、混淆、清理、构建等多任务操作。