WebPack 是一个模块打包工具,可以使用WebPack管理模块,并分析模块间的依赖关系,最终编绎输出模块为HTML、JavaScript、CSS以及各种静态文件(图片、字体等),让开发过程更加高效。
对于不同类型的资源,webpack有对应的模块加载器loader,比如说:
CSS:解析CSS的css-loader、style-loader,解析less的less-loader,sass的sass-loader,
JS:解析将 TypeScript 转换成 JavaScript的ts-loader,解析ES6为ES5的babel-loader,解析JavaScript 代码规范的eslint-loader
Vue:解析.vue文件的vue-loader、
解析常用图片以及音视频资源的url-loader、
解析文件的file-loader,
解析 JSON 文件的json-loader等
Webpack运行在node.js环境下,它的配置文件webpack.config.js遵循CommonJS规范,最终export出一个json对象。
webpack.config.js基础配置说明:
1、entry:指定了模块的入口,它让源文件加入构建流程中被webpack控制。
2、output:配置输出文件的存放位置、文件名、文件基础路径publicPath。
3、module:配置各种类型文件的解析规则,比如说.vue文件、.js文件、.css文件的loader等。
4、rosolve:配置alias(别名),或者定义寻找模块的规则。
5、plugins:配置扩展插件,扩展webpack的更多功能。
6、devServer:实现本地http服务等。
1、从入口(entry) 开始,递归转换入口文件所依赖的module
2、每找到一个module,就根据对应的loader去转换这个module
3、然后,再对当前module依赖的所有module进行转换,如果子module还有依赖的话,再转换,直至没有依赖
4、其次,根据入口和模块之间的依赖关系,组装成一个个包含多个模块的 Chunk
5、最后,Webpack会把所有Chunk转换成文件输出,在整个流程中Webpack会在恰当的时机执行plugin里定义的扩展插件。
功能不同:
Loader 本质是一个函数,对接收到的文件进行转换,比如将ts转换成js,将scss转换成css等。
Plugin 是webpack的插件,可以扩展 Webpack 的功能。
运行时机不同
loader运行在打包文件之前,对文件进行预处理;
plugins 运行在loader结束后,webpack打包的整个过程中,它是基于事件机制,监听webpack打包过程中的某些节点,从而执行相应任务,进而改变输出。
6、有哪些常见的Plugin(插件)
1、ProvidePlugin:将指定模块暴露到全局,使用的时候就不需要再import和require,比如说jquery;
2、DefinePlugin:允许在编译时将你代码中的变量替换为其他值或表达式,比如说Vue中生产、开发环境的判断,所用的process.env;(项目)
3、HotModuleReplacementPlugin:热更新功能(项目)
4、CommonsChunkPlugin : 主要是用来提取第三方库和公共模块,避免首屏加载的bundle文件体积过大,从而导致加载时间过长。
1、copy-webpack-plugin: 将单个文件或整个目录复制到打包后的目录。(项目)
2、clean-webpack-plugin: 目录清理
3、html-webpack-plugin:该插件将为你生成一个 HTML5 文件, 在 body 中使用 script 标签引入你所有 webpack 生成的 bundle。(项目)
4、uglifyjs-webpack-plugin:压缩代码,同时可以去掉代码中的debugger、console.log
5、compression-webpack-plugin : 压缩指定类型的文件为gzip 文件,以部署在服务器上时,加载页面时,传输时使用gzip文件,浏览器自行解析。(gzip文件的体积比正常文件体积小3-5倍)
6、hard-source-webpack-plugin : 利用缓存,提高打包与启动项目的速度;
7、extract-text-webpack-plugin : 抽离css样式,防止将样式打包在js中引起页面样式加载错乱的现象。
8、mini-css-extract-plugin : 分离样式文件,CSS 提取为独立文件,支持按需加载;
webpack 的热更新又称为热替换(Hot Module Replacement),缩写为 HMR,这个机制可以做到不用刷新浏览器而将新变更的模块替换掉旧的模块。
热更新的核心就是客户端与服务端建立的websocket连接
服务端监听文件变化,编译后再推送给客户端告之其哪些地方改变了,最终客户端发送ajax请求,获取最新资源,使用文件系统替换修改的内容实现局部更新。
1、使用高版本的 Webpack 和 Node.js
2、通过 externals 配置提取页面公共资源, 将基础包通过 CDN 引入,不打入 bundle 中
3、充分利用缓存提升二次构建速度:babel-loader 开启缓存或terser-webpack-plugin 缓存等
4、使用 thread-loader /HappyPack实现多进程加速编译。
5、使用 uglifyjs-webpack-plugin 对js进行代码压缩。
6、 优化 resolve 配置缩小范围,如只采用 main 字段作为入口文件描述字段 (减少搜索步骤)。
7、使用 tree-shaking 和 Scope hoisting 来剔除多余代码。
webpack中,Tree shaking 是一种通过清除多余代码方式来优化项目打包体积的技术,清除一些被 import 了但其实没有被使用的代码。
实现原理
Tree-shaking 的实现一是先标记出模块导出值中哪些没有被用过,二是使用 Terser 删掉这些没被用到的导出语句。标记过程大致可划分为三个步骤:
1、Make 阶段,收集模块导出变量并记录到模块依赖关系图 ModuleGraph 变量中
2、Seal 阶段,遍历 ModuleGraph 标记模块导出变量有没有被使用
3、生成产物时,若变量没有被其它模块使用则删除对应的导出语句
标记功能只会影响到模块的导出语句,真正执行“「Shaking」”操作的是 Terser 插件。只需要用 Terser 提供的 DCE 功能就可以删除这一段定义语句(不可能被执行到的代码),以此实现完整的 Tree Shaking 效果。
source map 是将编译、打包、压缩后的代码映射会源代码的过程。打包压缩后的代码不具备良好的可读性,想要调试源码就需要 source map。
map 文件只要不打开开发者工具,浏览器是不会加载的。
文件指纹是指打包后输出文件的名的后缀。
文件指纹通常有两个用途:
1、版本管理:在发布版本时,通过文件指纹来区分 修改的文件 和 未修改的文件。
2、使用缓存:未修改的文件,文件指纹保持不变,浏览器继续使用缓存访问。
常见的文件指纹
1、hash:和整个项目的构建相关,只要项目文件有修改,整个项目构建的 hash 就会变化。
2、chunkhash:和webpack打包的 chunk 有关,不同的 chunk、不同的 entry 会生成不同的 chunkhash。
3、contenthash:根据文件内容来定义 hash,文件内容不发生变化,则contenthash就不会变化。直接在输出文件名添加对应的 hash值即可。
vite ,是一种新型前端构建工具,能够显著提升前端开发体验
它主要由两部分组成:
其作用类似webpack+ webpack-dev-server,其特点如下:
1、快速的冷启动
2、即时的模块热更新
3、真正的按需编译
vite会直接启动开发服务器,不需要进行打包操作,也就意味着不需要分析模块的依赖、不需要编译,因此启动速度非常快
利用现代浏览器支持ES Module的特性,当浏览器请求某个模块的时候,再根据需要对模块的内容进行编译,这种方式大大缩短了编译时间