webpack给前端开发带来了毋庸置疑的改变,它把JS,图片,css都作为模块处理,同时具有开发便捷,自动化,兼容AMD写法等等诸多无须赘述的优点,更令人称道的是其插件社区非常强大,对于不同的业务需求和技术需求社区都有大量插件可供使用。
凡事都具有两面性,许多人说:前端开发再也不能只需新建HTML文件和JS文件就可以开始写代码了。webpack带来了更高级更规范的前端开发模式,由于其本身也在不断完善中,从1到2再到发布不久的webpack3,频繁的修改给新手带来了许多困惑。而且网络上各种教程鱼目混杂,经常出现别人的教程代码copy下来在自己的环境却跑不通的蛋疼问题。就拿 devtool 配置项来说,官方文档提供了多达7种的配置方法,连react核心团队成员Pete Hunt都在twitter上调侃:我分不清webpack的许多配置之间的区别。所以今天我们抛开那些琳琅满目的插件和令人烦躁的配置项,笔者和大家一起5分钟从零搭建一个简易高效的webpack开发环境。
首先我们明确一下需求:
打包调试
提取公共代码
压缩
热替换
1.打包调试
第一步,我们在目标文件夹下安装webpack(假设已有 package.json )
npm i webpack@ -g cnpm i webpack@ --save-dev
(这里推荐大家安装稳定的2.x版本)
项目结构如图:
我们将编写的js代码和样式文件放置在 app 文件夹内(正常项目开发需要 js 文件和 less文件更规范的组织文件结构,此处仅为演示方便)。
第二步,我们在目标文件夹下新建 webpack.config.js
module.exports = { entry:{ main:__dirname + '/app/main.js', }, output:{ path:__dirname + '/public', filename:'[name].[id].js',//此格式写法后续会提到为什么 publicPath:'/public/' } }
我们已经完成了webpack最基础的部分:添加了文件的输入和输出。入口是 app 文件夹内的 main.js 文件,出口为 public 文件夹。接下来我们来处理各种文件的解析,就是大名鼎鼎的 loader 的舞台了。假设我们使用 es6 和 less 开发,那么我们需要:
npm i babel-loader babel-core babel-preset-es2015 babel-preset-stage-0 --save-dev npm i less less-loader css-loader style-loader --save-dev
接下来我们只需要在 modules 字段下把这些 loader 加进去:
module.exports = { devtool:'cheap-module-eval-source-map',//多种选择,选择最适合自己的 entry:{ main:__dirname + '/app/main.js', }, output:{ path:__dirname + '/public', filename:'[name].[id].js', publicPath:'/public/' }, module:{ loaders:[ { test:/\.js$/, //解析文件类型 exclude:/node_modules/, //排除node_modules文件 loader:'babel-loader', //使用哪种loader解析 query:{ presets:['es2015','stage-0']//loader的配置项,解析es6 } }, { test:/\.less$/, exclude:/node_modules/, loader:'style-loader!css-loader!less-loader'//顺序为从右向左 } ] }, }
大功告成!
如果你在全局安装有webpack的话,可以在终端敲入webpack并回车,几秒钟后, main.js 文件已经在 public 打包出来了!
之后我们在 index.html 中引入 main.0.js 文件,再打开 index.html 就可以看到效果了。
以上步骤,我们已经实现了文件的打包调试,但是现在有个问题摆在我们面前:第三方库代码和业务代码打包到了同一个文件 main.0.js 内,每次更新代码都要更新整个文件。那么接下来我们对代码进行拆分。
2.提取公共代码
引入 CommonsChunkPlugin 插件,在 webpack.config.js 添加如下内容:
module.exports = { devtool:'cheap-module-eval-source-map', entry:{ main:__dirname + '/app/main.js', vendor:'moment' }, output:{ path:__dirname + '/public', filename:'[name].[id].js', publicPath:'/public/' }, module:{ loaders:[ { test:/\.js$/, exclude:/node_modules/, loader:'babel-loader', query:{ presets:['es2015','stage-0'] } }, { test:/\.less$/, exclude:/node_modules/, loader:'style-loader!css-loader!less-loader' } ] }, plugins:[ new webpack.optimize.CommonsChunkPlugin({ names:['vendor','manifest'] }) ] }
我们看到向插件的构造函数传入了两个参数 vendor 和 manifest ,以及我们在 entry 也加入了新的入口 moment 。 moment 是常用的时间处理的第三方库,我们可以通过 npm i moment --save-dev 进行安装。而 entry 处的 vendor 将成为 output 字段 filename 中 [name] 的值,也就是说将打包出 main.x.js 和 vendor.x.js 两个文件, main.x.js 文件将保存我们的业务代码, vendor.x.js 将保存 moment 的代码,这样我们将公共代码和业务代码进行了初步分离。