what:
前端资源构建工具及静态模块打包器
前端资源主要包括:sass,less,ts,ES6等
静态模块指在web开发过程中的各种资源文件:js,css等
webpack根据引入关系构建一个依赖关系图,然后利用这个关系图打包成一个bundle输出
why:
- 前端新框架新语言(es6等)构成的源码无法在浏览器中直接运行,必须经过转化
- 打包问题,如果没有webpack,需要使用额外的平台进行打包
- 代码更改后需要手动刷新浏览器,webpack提供热刷新功能
- ……
how:
一般一个中型项目的webpack配置文件绝对不会只有一个,而是被拆分成多个,如:webpack.config.base.js(基础配置),webpack.config.prod.js(开发环境配置),webpack.config.dev.js(预上线配置)等等。
基础核心配置
Entry:
入口文件,表示webpack在打包时以哪个文件为入口,然后再递归解析其余依赖构成关系图,可以是字符串,数组,对象类型
//字符串类型entry
entry:'./app/entry'
//array类型entry,多个入口文件只会生成一个chunk
entry:['./app/entry1','./app/entry2']
//对象类型,object有几个对象就会生成几个chunk,chunk的名称就是对象的key值
entry:{index:'./app/entry-index',test:'./app/entry-test'}
output
出口,指示webpack打包后的资源bundle输出到哪里。以及如何命名filename在指定的entry中。
output:{
//配置输出文件存放本地的目录
path:
//文件名称
filename:
//配置发布线上资源的url
publicPath:
//配置无入口的chunk
chunkFilename:
library:{
name:"[name]",//整个库向外暴露的变量名
type:"window"//库的暴露方式
}
}
webpack的chunk和bundle是什么?
假设在index.js中引入index.css以及common.js,那么他们经过webpack打包后会生成一个chunk,而utils.js没有引入其他任何模块,所以独自生成一个chunk。
- 对于一份同逻辑的代码,单个的文件无论是commonjs或者是amd,他们都是module;
- module源文件传到webpack进行打包时,webpack会根据文件引用关系生成chunk文件,webpack会对这个chunk文件进行一些操作。
- webpack处理好chunk文件后会输出bundle文件,这个bundle文件包含了经过加载和编译的最终源文件(index.bundle.css/index.bundle.js/utiles.bundle.js),可以直接在浏览器中运行。
一般来说一个chunk对应一个bundle,但也有例外,使用一些插件的时候可以从chunk中抽离出另外的bundle。
Module
module如何配置模块:
module.export = {
module:{
rules:[
{test:/\.css$/,use:'css-loader'},
{test:/\.ts$/,use:'ts-loader'}
]
}
};
编写一些规则指定如何去处理css,js等
Loader
webpack自身只能理解javascript和json文件,loader可以让webpack处理其他文件
rules:[
{
//匹配哪些文件
test:/\.css$/,
//使用哪些loader进行处理。执行顺序:从右到左,从下到上
use:['style-loader','css-loader','sass-loader'],
},
{
test:/\.js$/,
loader:"babel-loader",//规则只使用一个loader时的推荐写法
},
]
Plugins
可以用于执行范围更广的任务。从打包优化压缩到重新定义环境中的额变量。
plugin实际上就是钩子函数,分为同步和异步,异步中又分为并发执行和串行执行。
常见plugin:
- HtmlWebpackPlugin
- CleanWebpackPlugin
- MiniCssExtraplugin
- VueLoaderPlugin
Mode
提供mode配置选项,告知webpack使用相应模式的内置优化,可以直接在moudle中配置,也可以在cli中传递参数。//:在命令行中输入:webpack–mode=production
module.exports = {
mode = 'production';
};
其余配置
- devserver
为项目开启一个本地(我是这么理解)
devServer:{
contentBase:path.resove(__dirname,"build"),
compress:true,//为静态文件开启gzip压缩
host:"localhost",
port:5000,
open:true,//自动打开浏览器
hot:true,//开启HMR功能
//设置代理
proxy:{
//一旦devserver(5000端口)接受到/api/xxx的请求,就会用devserver起的服务把请求转发到另一个服务器(3000)
//可以用来解决开发中的跨域问题
api:{
target:"http://localhost:3000",
//重写路径
pathRewrite:
}
}
}
- resolve
解析模块的规则
resolve:{
//配置模块解析别名:可简写路径
alias:{},
extentions:[".js",".json",".css"],
}
- optimization
生产环境下配置,提取公共代码,配置生产环境的压缩方案
打包优化
- HMR
在开发环境中可以打开webpack的HMR(hot module replacement),指的是在本地对代码修改保存后,webpack会对代码进行重新打包,并将改动的模块发送到浏览器。浏览器用新的模块替换掉旧的模块,去实现局部更新页面而非整体刷新页面。
- Source-map
开启后将bundle和js文件都展示在控制台,方便调试
生产环境中的打包优化:
- oneOf
- 缓存
- 多进程打包
- externals
- dll
- ……
实现一个loader
-
style-loader编写:
经cssloader转化后css会变成数组格式,这种格式是没有办法将样式展现在页面上的,所以需要style-loader进行转化 -
设计思路
loader是一个函数,最终需要返回一个js脚本:在脚本中创建一个style标签,将css代码赋值给style标签,再将这个style插入html的head标签中
1.normal loader:loader模块中导出的函数称为normal loader
2.pitch loader:pitching loader除了可以提前执行外,在返回非undefined值的时候会实现熔断效果
实现一个plugins
webpack插件是一个具有apply方法的js对象。apply方法会被webpack compiler调用,并在整个编译生命周期都可以访问compiler对象
webpack的打包过程
一次完整的wepack打包过程大致如下:
- 将命令行参数与webpack配置文件进行合并,解析,得到参数对象
- 将参数传给webpack得到compiler对象
- compiler的run方法开始编译,每次run都会生成一个compilation对象
- 触发compiler的make方法分析入口文件,调用compilation的buildmodule方法创建主模块对
- 生成入口文件AST抽象语法树,通过AST分析和递归加载依赖模块
- 所有模块分析完成后,执行compilation的seal方法对每个chunk进行整理,优化,封装
- 最后执行compiler的emitAssets方法把生成的文件输出到output目录中