好用的打包工具webpack
<什么是webpack>
webpack是一个模块打包器,任何静态资源(js、css、图片等)都可以视作模块,然后模块之间也可以相互依赖,通过webpack对模块进行处理后,可以打包成我们想要的静态资源。
gulp的打包是将js、css、图片等分开打包的,但是webpack是将所有的静态资源打包到一起,因此一个请求就可以了。
<webpack的特点>
·支持CommonJs(require的写法)和AMD模块,也就是说基本可以无痛迁移旧项目
·支持模块加载器和插件机制,可对模块灵活定制,特别是babel-loader,有效支持es6
·可以通过配置,打包成多个文件。有效利用浏览器的缓存功能提升性能。将公用的东西抽离出来,比如jQuery等
·将样式文件和图片等静态资源视为模块进行打包。配合loader加载器,支持sass、less等css预处理器
·内置有source map,即使打包在一起也方便调试
<webpack的安装>
1,先全局安装
npm install webpack -g
·webpack -w 提供watch方法,实时进行打包更新
·webpack -p 对打包后的文件进行压缩
·webpack -d 提供sourcemap,方便调试
·webpack --config 以某个config作为打包
·webpack --help 更多命令
2,再本地安装
npm init 先初始化一下,生成package.json。再安装,这样可以方便的查看依赖的文件
npm install webpack --save-dev 开发式依赖,一些打包工具,像gulp、webpack等都是开发式依赖,上线时并不需要
<webpack初体验>
比如说所有的文件打包到bundle.js中,则要在页面中引入bundle.js
webpack ./entry.js bundle.js //编译entry.js并打包到bundle.js
<模块依赖>
·webpack会分析入口文件,解析包含依赖关系的各个文件
·这些文件(模块)都打包到bundle.js文件中
·webpack会给每个模块分配一个唯一的id并通过这个id索引和访问模块
·页面启动时先执行entry.js代码,其他的模块会在require时懒加载
<loader加载器>
·webpack本身只能处理JavaScript模块,如果要处理其他类型的文件,就需要使用loader进行转换
·Loader可以理解为是模块和资源的转换器,可以转换任何类型(jsx、jade等)的模块
·Loader可以通过管道方式链式调用,每个loader可以把资源转换成任意格式并传递给下一个loader,但是最后一个loader必须返回JavaScript,因为webpack只认识js。不同的文件,使用的loader也不一样
·Loader可以接受参数,以此来传递配置项给loader。
·Loader可以通过npm安装
·Loader可以通过文件扩展名(或正则表达式)绑定不同的加载器
<加载css文件>
安装两个loader:npm install css-loader style-loader
·首先将style.css也看作一个模块
·用css-loader来读取它
·用style-loader把它内嵌到html中
在entry.js中引入:
require("css!./style.css")//相当于require("css-loader!.style.css").因为css-loader的-loader是固定的,所以一般省略-loader。
/*将原始的css通过css-loader读出来,需要传递给style-loader。所以该require还需要补充为如下所示:*/
require("style!css!./style.css")
//!相当于gulp中的流一样,从右向左依次流动
再次执行
webpack ./entry.js bundle.js
编译entry.js引入的样式文件打包到bundle.js
<加载图片url-loader>
url-loader会将样式中引用到的图片转为模块来处理
npm install url-loader
limit的参数意思是图片大小小于这个限制的时候,会自动启用base64编码图片
<配置文件>
·webpack在执行的时候可以通过指定的配置文件
·默认情况下会执行当前目录中的webpack.config.js,当输入webpack时,会自动寻找该文件。
·配置文件是一个node.js模块,返回一个json格式的配置信息对象
·添加配置文件,然后执行webpack --progress --colors就可以了
配置文件格式为:
var webpack = require("webpack") module.exports = { entry:"./entry.js",//指定打包的入口文件,每个键值对,就是一个入口文件。 output:{//配置打包结果 path:__dirname,//定义了输出的文件夹 filename:"bundle.js"//定义了打包结果文件的名称 }, module:{//定义了模块的加载逻辑 loaders:[//定义了一系列的加载器 {test:/\.css$/,loader:"style!css"},//当需要加载的文件匹配`test`的正则时,就会使用相应的loader {test:/\.(png|jpg)$/,loader:"url?limit=40000"}, {test:/\.js?$/,loader:"babel",exclude:/node_modules/,query:{compact:false,presets:['es2015']}}//对于所有的js文件,用babel-loader //进行加载,忽略node_modules下面 // 的js文件。query表示参数,相当于 // url-loader的?形式。 ] }, plugins:[//插件的使用一般在webpack配置信息plugins选项中指定,我们可以向生成的打包文件头部插入一些信息 new webpack.BannerPlugin("//叮呤在学习webpack"),//向打包之后的文件头部添加注释信息 new webpack.optimize.CommonChunkPlugin("common.js")//把多个模块中的公共部分,单独提取出来,单独加载 ], resolve:{ alias:{//别名,它的作用是把用户的一个请求重定向到另一个路径 jquery:"./js/jquery.js" //这样,在使用jQuery的组件中只需要require("jquery")即可,而不再需要逐级去寻找jQuery的存放位置 } } }
·expose,如果想在前台使用打包的jQuery,需要把jQuery暴露出来,先安装该模块 npm install expose-loader --save-dev
eg:把$作为别名为jquery的变量暴露到全局上下文中require("expose?$!jquery"),在引入jquery的时候,把jQuery对象绑定到window的$上面
·entry属性可以使一个对象,而对象名也就是key,会作为下面output的filename属性的name
entry:{
bundle1:"./entry1.js",
bundle2:"./entry2.js"
}
output:{
path:__dirname,
filename:"[name].js"//此处的[name]就表示bundle1和bundle2
}
假如bundle1和bundle2都包含有功能相同的部分,则可以把这部分提取出来
·公共模块。我们利用插件可以智能的提取公共部分,以提供我们浏览器的缓存复用
plugins:[
new webpack.optimize.CommonChunkPlugin("common.js")//把多个模块中的公共部分,单独提取出来,单独加载
]
我们需要手动在html上加载common.js,并且是必须最先加载
<使用es6>
npm install babel-core --save-dev
npm install babel-loader --save-dev
npm install babel-preset-es2015
<webpack-dev-server>
npm install webpack-dev-server -g
安装好之后,执行webpack-dev-server,在当前目录启动一个express服务,会自动打包和实时刷新
<与webpack相比gulp的优势>
webpack不可以做自动部署和代码检查,webpack只是个打包工具。所以可以采用gulp与webpack混合使用的方法
var gutil = require("gulp-util"); var webpack = require("webpack"); var webpackConfig = require("./webpack.config.js"); gulp.task("webpack",function(callback){ var myConfig = Object.create(webpackConfig); webpack(myConfig,function(err,stats){ callback(); }) }) gulp.task("default",function(){ gulp.watch("./**",["webpack"]); })