webpack学习笔记1:基本概念
前言:
现在在日常的开发中,webpack已经是必不可少的东西了,现在的需求基本都是用webpack对资源进行打包整合,所以打算写一点关于webpack的东西,这是第一篇,主要是介绍一些基本的概念。
webpack的概念
众所周知,webpack是一个模块打包器,他会把项目里的各种资源进行统一打包,webpack打包的时候会递归的构建一个依赖图,每个用到的模块都在这个流程图上,最后输出一个javascript文件。
webpack由四个核心部分构成,分别是:
entry(入口)
output(出口)
loader(加载器)
plugin(插件)
entry入口
前边说过,webpack打包的时候会构建一个依赖图,而entry就是这个图的起点,webpack会知道,从哪个文件开始进行他的打包之旅。
webpack中有多种方法指定entry
简单语法
用法:
const config = {entry:'./path/app.js'
};module.exports = config;
其实这是下边方式的简写
const config = {entry:{main:'./path/app.js'}
};module.exports = config;
上边表示app.js文件是这个项目的入口文件,entry的值除了是一个字符串,还可能是一个数组。
如果你的项目很小,没有依赖其他的大型库,那么这种简单的写法是个很好的选择,从app.js开始,按照依赖图一次打包各个文件。
缺点是,这种配置缺乏一定的灵活性。
对象语法
前边说,简单写法缺乏灵活性,是因为,加入依赖了一个很大的库,比如react,每次执行打包的时候都需要把react打包一遍。
const config = {entry:{app:'./path/app.js',vendor:'./vendor.js'}
}module.exports = config;
上面看起来项目有两个入口,app和vendor,两者独立于彼此,分别开始构建各自依赖的资源。这种方式常见于只有一个入口(app而不是vendor)的单页面(SPA)应用。
vendor是一些公共的库,不会发生轻易改变,甚至是不会改变,把他们提取出来会优化打包的效率,可以理解起到了一个缓存的作用。
多页面应用程序
const config = {entry:{page1:'./src/page1/page1.js',page2:'./src/page2/page2.js',page3:'./src/page3/page3.js'}
}module.exports = config;
当项目是一个多页面应用的时候,需要的是多个webpack入口,所以就会有多个依赖图。这个我们看到,page1页面的入口是page1.js,其他两个页面的也是如此。
多页面不能用一个单个的入口的原因是,每次载入一个新的html,需要重新下载新的文件,所以页面需要哪个文件,就依赖哪个。
我们可以用CommonshunkPlugin来每个页面的共享代码创建bundle,提供复用的机制,提高效率。
output出口
有入口就有出口,在webpack中,output表示项目的出口,即打完包输出的文件。
即便有多个entry入口文件,可是在webpack中,只有指定一个输出配置
用法
const config = {entry:'./sec/app.js',output:{filename:'bundle.js',path:'./src'}
}
配置项是一个对象,对象里有两个属性。
filename:表示打包输出之后的文件名
path:表示打包输出的路径
多个入口的情况下
如何项目是有多个入口的情况下,这个时候使用占位符来确保每个文件有唯一的名称
const config = {entry:{app1:'./src/app1.js',app2:'./src/app2.js'},output:{filename:[name].js,path:__dirname+'/dist'}
}
在dist文件夹下,会有打完包之后的app1.js和app2.js两个文件。
loader加载
loader提供方法进行构建,包括去源代码进行转换,把不同的语言转成javascript,或者把图片转成dataUrl或者把sass文件中换成css。总之,loader是webpack的精髓,功能强大。
示例
比如,我们要用webpack加载css文件或者把typescript转成js,首先要安装对应的loader。
npm install css-loader --save-dev
npm install ts-loader --save-dev
然后指示每个css使用css-loader,每个ts使用ts-loader.
const config = {entry:'./src/app.js',output:{filename:'bundle.js',path:__dirname+ '/dist'},module:{rules:[{test:/\.css$/,use:'css-loader'},{test:/\.ts$/,use:'ts-loader'}]}
}
使用loader的三种方式
在webpack中,有三种使用loader的方法,
配置,在webpack的配置文件中配置(推荐)
内联,在import中指定相关loader
CLI, shell命令使用(这个先不研究了)
配置
module.rules允许你在webpack中配置多个loader,这是最好的方式,可以让你一目了然的看到项目到底配置了哪些loader。
module:{rules:[{test:/\.css$/,use:[{loader:'style-loader'},{loader:'css-loader',options:{modules:true}}]},]
}
这是webpack2的语法。
内联
可以在import或者任何等价于import的语句中使用loader,不过用的很少,其语法是这样的
import style from 'style-loader!css-loader?modules'
尽量使用上一种配置的方法,因为可以减少代码量,每次都import引用也是一件很麻烦的事情。
loader解析
多数情况下,loader将会从模块路径开始解析,就是npm install安装的模块。
loader需要导出为一个函数,通常采用node兼容的js写法,有的时候也可以将自定义loader作为应用程序中的文件。通常情况下,采用xxx-loader的方式命名。
plugin插件
插件是webpack的支柱功能,一句话概括插件的作用就是做loader不能做的事情。
剖析
插件是一个拥有apply属性的js对象。apply会被webpack compiler调用,comliler是个对象,可以再在整个编译周期访问。
function plugin1(){...
}
plugin.prototype.apply = function(compiler){compiler.plugin('run',function(compiler,callback){console.log('webpack构建开始了');callback();})
}
用法
由于插件是可能存在选项或者是参数的,所以在webpack文件中,需要在plugin属性里用new把需要的插件传进去,看下边例子
配置
const config = {entry:{app:'./src/app.js',vendor:'./src/vendor.js'},output:{filename:[name].js,path:__dirname+'/dist'},nodule:{loaders:[{test:/\.css$/,use:'style-loader!css-loader' }]},plugin:[new webpack.optimize.UglifyJsPlugin(),new HtmlWebpackPlugin({emplate:'./src/index.html'})]
};module.export = config;
后记
这篇文章主要介绍了一下webpack的基础概念,包括webpack配置文件的四个主要部分,entry,output,loader,plugin的写法。