webpack.config.js是启动webpack的配置文件,遵循nodejs的commonJS规范,使用require引入模块,并最终通过module.exports导出配置,实际上就是一个nodejs文件.
1.启动方式
webpack默认使用同目录下的webpack.config.js文件,也可以自定义指定文件位置
在package.json文件中配置:
"scripts": {
"build:dev":"webpack --config ./src/webpack.config.dev.js"
}
2.webpack.config.js的配置格式
webpack不仅仅可以使用js,还支持ts,coffeeScript,甚至JSX的语法配置.
(1) 导出一个对象
const path=require('path');
module.exports={
mode:'development',
entry:[
'./es/index.js',
'./src/index.js'
],
output:{
filename:'[hash].js',
path:__dirname+'/dist'
}
}
(2)导出一个函数
const path=require('path');
module.exports=(env,args)=>{
return {
mode:'development',
entry:[
'./es/index.js',
'./src/index.js'
],
output:{
filename:'[hash].js',
path:__dirname+'/dist'
}
}
}
其中env的值是通过在package.json这样配置的
"scripts": {
"build:dev":"webpack --env.prod=production --mode development"
},
配置和函数中env的对应输出如下表所示
args输出webpack命令行的一些配置项对应的值
"build:dev":"webpack --env.prod=33 port=33 --mode development"
对应输出
args {
_: [ 'port=33' ],
cache: null,
bail: null,
profile: null,
color: { level: 3, hasBasic: true, has256: true, has16m: true },
colors: { level: 3, hasBasic: true, has256: true, has16m: true },
env: { prod: 33 },
mode: 'development'
}
(3)导出一个Promise
Promise可以用于需要异步输出配置项的情况下,例如,需要请求接口之后执行webpack,在Promise的resolve中输出配置
module.exports=(env,args)=>{
console.log('args',args);
return new Promise(resolve=>{
setTimeout(()=>{
resolve({
mode:'development',
entry:[
'./es/index.js',
'./src/index.js'
],
output:{
filename:'[hash].js',
path:__dirname+'/dist'
}
})
},3000)
})
}
(4) 导出一个数组
在某些情况下,可能需要一次打包多次,因此需要用数组输入webpack配置,会根据数组的顺序依次执行webpack
module.exports=[
{
mode:'development',
entry:[
'./es/index.js',
],
output:{
filename:'[hash].js',
path:__dirname+'/dist'
}
},
{
mode:'development',
entry:[
'./src/index.js'
],
output:{
filename:'[hash].js',
path:__dirname+'/dist'
}
}
]
3.webpack.config中涉及到的名词
名词 | 说明 |
---|---|
entry | 入口文件,webpack从这个配置的文件开始获取整个项目的依赖 |
module | 模块,可以理解为每个引入的依赖都是一个模块,不仅仅js,也包括css,img文件 |
chunk | 代码块,多个模块的集合,将多个module抽出整合在一起 |
loader | 模块转化器,用来处理特定格式的文件,如less,sass文件转css等 |
plugin | 扩展插件,可以处理chunk,也可以处理bundle,可以处理loader处理不了的任务 |
bundle | 最终打包完成的文件,一般和chunk一一对应,一般是chunk经过压缩打包处理之后形成 |
4. webpack的一些配置项
(1) mode
type mode = 'production' | 'development'
表示是生产环境打包还是开发环境打包,生产环境会对代码进行压缩,也会优化图片
也可以通过命令行设置
webpack --mode production
(2) entry和output
webpack是一个模块打包工具,从一个需要处理的js文件开始,构建一个依赖关系图,然后将这个依赖关系图输出到一个或者多个bundle中去
而entry所表示的就是webpack从哪个文件开始,构建依赖关系图;
而output表示,文件的输出形式
过程可以表示为
entry文件 ⇒ 寻找相关依赖模块(源文件) ⇒ loader和plugins对模块进行处理 ⇒ 生成bundle ⇒ 输出到output
entry
entry可以支持多种格式,包括对象,数组,字符串,可以分为单文件入口和多文件入口
单文件
// string
module.exports={
entry:'./src/index.js'
}
// object
module.exports={
entry:{
main:'./src/index.js'
}
}
// array
module.exports={
entry:['./src/index.js','./es/index.js']
}
注意: array格式实际上也是单文件入口,webpack会自动生成另外一个入口模块,并将数组中的各个模块加载进来,并将最后一个模块的module.exports作为入口模块的module.exports导出
多文件
module.exports={
mode:'development',
entry:{
home:'./src/index.js',
about:'./es/index.js'
},
output:{
filename:'[name]_[hash].js',
path:__dirname+'/dist'
}
}
生成了两个bundle
output
webpack的output是指定了entry对应文件编译打包之后输出的bundle,常用的属性有
path: 指定输出bundle存放的路径,默认为dist
filename :指定输出的bundle的文件名,默认为main.js
publicPath:指定了一个在浏览器中被引用的 URL 地址
也就是说默认输出为dist/main.js
webpack可以有多个入口文件,但是只能有一个output,在output.filename中可以通过占位符语法来生成不同的文件
占位符 | 含义 |
---|---|
[hash] | 模块标识符的 hash |
[chunkhash] | chunk内容的hash |
[name] | entry模块的名称 |
[id] | 模块标识符 |
[query] | 模块的query名,例如,文件名?后面的字符串 |
hash类占位符都支持 [hash:length] ,length表示hash值的位数,也可以 通过output.hashDigestLength在全局配置长度
hash和chunkhash的区别
[hash]: 是整个项目的hash值,每次项目编译之后会生成一个hash值,不同入口文件对应的hash值一样,任何文件的改变都会导致hash值的变化,因此hash不适合长缓存,长缓存可以考虑使用chunkhash
[chunkhash]: 根据不同的入口文件进行依赖文件解析,构建出对应的chunk,并生成对应的hash值,因此不同的entry对应的chunkhash不同.但是只要entry对应的文件不变,对应的chunkhash也是不变的.所以在做代码优化时,可以将公共代码库拆分到一起,变动比较少,使用chunkhash可以发挥最长缓存作用
output.publicPath
path
是我们指定的构建打包后输出的路径,但是我们可以指定publicPath
来指向该目录
output:{
filename:'file.js',
path:__dirname+'/dist/assets',
publicPath:'/assets/'
}
可以使用
/assets/file.js
指向对应的bundle
在这里可以将publicPath设定为cdn地址
library和libraryTarget
如果项目最终构建出来是一个库,可以使用library
和libraryTarget
配合
不加library
加了library,
output:{
library:'mylib_[hash]'
}
可以通过libraryTarget指定输出的形式,默认为var,也就是上面这种格式输出
还有比较常见的有
libraryTarget | 输出格式 |
---|---|
var | var mylib= |
assign | mylib= |
this | this[‘mylib’] |
window | window[‘mylib’] |
global | global [‘mylib’] |
commonjs | exports[‘mylib’] |
commonjs2 | exports.module= |
等等其他的可以参考官方文档
注意: libraryTarget=global 的时候,如果 target=node 才是 global,默认 target=web 下 global 为 window,保险起见可以使用 this。
output.externals
如果你在开发一个库(library),开发过程中引入了vue或者jquey,如果按照正常的打包方式,会将vue和jquery一起构建成bundle,但是实际上vue和jquery应该是使用库的开发者去引入.此时我们就需需要用到externals
去指定那些依赖不被打包进bundle中.
ouput.target
项目开发中,我们可能开发的是一个web项目,或者时node应用,甚至是electron应用,这是时候我们就需要通过target
指定应用类型,来做一些相关处理.
output:{
target:"web"
}
output.devtool
配置devtool
来控制如何显示sourcemap,通过sourcemap我们可以快速定位代码的错误,但是由于生成sourcemap包含的数据量大,因此会影响打包构建的速度
这里的取值和构建关系的权衡可以参考官方文档