1、对webpack的理解
- webpack是一个现代化的JavaScript应用的
静态模块打包工具,处理模块间的依赖关系。 - 我们进行模块化开发时 必须要借助其他工具来支持模块化开发,概念:一个模块就是
实现特定功能的文件,有了模块,我们就可以更方便地使用别人的代码,想要什么功能,就加载什么模块。 - 打包:开发过程中的
各种资源模块合并成一个或多个包(bundle),对资源进行处理压缩和转化等。 - 与grunt/gulp的区别在于:grunt没有模块的概念,只能进行一些简单的合并、压缩、预处理;webpack更强调模块化开发管理(监听文件的变化来并且反映到浏览器上,提高开发的效率),压缩、合并、预处理等功能只是它附带的功能。
- 现在还有vite ,是一种新型前端构建工具,能够显著提升前端开发体验(趋势)
- Webpack-cli 为webpack提供命令行的工具
- Main.js webpack打包时的入口文件
- Webpack.config.js 配置文件
2、webpack的构建流程
- 初始化流程:从配置文件和
Shell语句中读取与合并参数,并初始化需要使用的插件和配置插件等执行环境所需要的参数 - 编译构建流程:从 Entry 发出,针对每个 Module 串行调用对应的 Loader 去翻译文件内容,再找到该 Module 依赖的 Module,递归地进行编译处理
- 输出流程:对编译后的 Module 组合成 Chunk,把 Chunk 转换成文件,输出到文件系统
3、webpack的热更新是如何做到的
HMR 全称 Hot Module Replacement,可以理解为模块热替换,指在应用程序运行过程中,替换、添加、删除模块,而无需重新刷新整个应用
例如,我们在应用运行过程中修改了某个模块,通过自动刷新会导致整个应用的整体刷新,那页面中的状态信息都会丢失
如果使用的是 HMR,就可以实现只将修改的模块实时替换至应用中,不必完全刷新整个应用
- 通过
webpack-dev-server创建两个服务器:提供静态资源的服务(express)和Socket服务 - express server 负责直接提供静态资源的服务(打包后的资源直接被浏览器请求和解析)
- socket server 是一个 websocket 的长连接,双方可以通信
- 当 socket server 监听到对应的模块发生变化时,会生成两个文件.json(manifest文件)和.js文件(update chunk)
- 通过长连接,socket server 可以直接将这两个文件主动发送给客户端(浏览器)
- 浏览器拿到两个新的文件后,通过HMR runtime机制,加载这两个文件,并且针对修改的模块进行更新
4、webpack proxy工作原理?为什么能解决跨域?
- 即
webpack提供的代理服务,基本行为就是接收客户端发送的请求后转发给其他服务器,便于开发者在开发模式下解决跨域问题(浏览器安全策略限制),实现代理首先需要一个中间服务器,webpack中提供服务器的工具为webpack-dev-server(只适用于开发阶段)。 - 在开发阶段,
webpack-dev-server会启动一个本地开发服务器,所以我们的应用在开发阶段是独立运行在localhost的一个端口上,而后端服务又是运行在另外一个地址上。所以在开发阶段中,由于浏览器同源策略的原因,当本地访问后端就会出现跨域请求的问题。 - 通过设置
webpack proxy实现代理请求后,相当于浏览器与服务端中添加一个代理者。当本地发送请求的时候,代理服务器响应该请求,并将请求转发到目标服务器,目标服务器响应数据后再将数据返回给代理服务器,最终再由代理服务器将数据响应给本地。 - 在代理服务器传递数据给本地浏览器的过程中,两者同源,并不存在跨域行为,这时候浏览器就能正常接收数据。而代理服务器与目标服务器由于服务器之间不存在跨域问题,可以正常进行数据交流。
5、webpack中常见的Loader?解决了什么问题?
webpack做的事情,仅仅是分析出各种模块的依赖关系,然后形成资源列表,最终打包生成到指定的文件中。
Loader用于对模块的"源代码"进行转换,在 import 或"加载"模块时预处理文件
常见的loader:
- style-loader: 将css添加到DOM的内联样式标签style里
- css-loader :允许将css文件通过require的方式引入,并返回css代码
- less-loader: 处理less
- sass-loader: 处理sass
- postcss-loader: 用postcss来处理CSS
- autoprefixer-loader: 处理CSS3属性前缀,已被弃用,建议直接使用postcss
- file-loader: 分发文件到output目录并返回相对路径
- url-loader: 和file-loader类似,但是当文件小于设定的limit时可以返回一个Data Url
- html-minify-loader: 压缩HTML
- babel-loader :用babel来转换ES6文件到ES
- vue-loader :解析vue文件
- vue-template-compiler :解析vue中模板的工具
- @vue/babel-preset-jsx : 支持解析vue中的jsx语法
6、webpack中常见的Plugin?解决了什么问题?
plugin赋予其各种灵活的功能,例如打包优化、资源管理、环境变量注入等,它们会运行在 webpack 的不同阶段(钩子 / 生命周期),贯穿了webpack整个编译周期
目的在于解决
loader 无法实现的其他事
- HtmlWebpackPlugin: 将index.html打包进dist
- Webpack-UglifyjsWebpackPlugin: 将js代码进行压缩
- Banner-plugin 横幅
7、Loader和Plugin的区别?编写Loader,Plugin的思路?
- 区别:
- loader 是文件加载器,能够加载资源文件,并对这些文件进行一些处理,诸如编译、压缩等,
最终一起打包到指定的文件中 - plugin 拓展 webpack 各种灵活的功能,例如打包优化、资源管理、环境变量注入等,
目的是解决 loader 无法实现的其他事 loader 运行在打包文件之前plugins 在整个编译周期都起作用
- 编写思路:
- 一般在编写
loader的过程中,保持功能单一,避免做多种功能 - 插件必须是一个函数或者是一个包含
apply方法的对象,这样才能访问compiler实例 - 传给每个插件的
compiler和compilation对象都是同一个引用,因此不建议修改 - 异步的事件需要在插件处理完任务时调用回调函数通知
webpack进入下一个流程,不然会卡住
8、如何借助webpack来优化前端性能?
- JS代码压缩
- CSS代码压缩(通常是去除无用的空格):css-minimizer-webpack-plugin
- Html文件代码压缩:HtmlWebpackPlugin
- 文件大小压缩(减少
http传输过程中宽带的损耗):compression-webpack-plugin - 图片压缩:
- Tree Shaking
- 代码分离(将代码分离到不同的
bundle中,之后我们可以按需加载) - 内联 chunk