前端工程化-webpack

169 阅读6分钟

1、对webpack的理解

  1. webpack是一个现代化的JavaScript应用的静态模块打包工具,处理模块间的依赖关系。
  2. 我们进行模块化开发时 必须要借助其他工具来支持模块化开发,概念:一个模块就是实现特定功能的文件,有了模块,我们就可以更方便地使用别人的代码,想要什么功能,就加载什么模块。
  3. 打包:开发过程中的各种资源模块合并成一个或多个包(bundle),对资源进行处理压缩和转化等
  4. 与grunt/gulp的区别在于:grunt没有模块的概念,只能进行一些简单的合并、压缩、预处理;webpack更强调模块化开发管理(监听文件的变化来并且反映到浏览器上,提高开发的效率),压缩、合并、预处理等功能只是它附带的功能。
  5. 现在还有vite ,是一种新型前端构建工具,能够显著提升前端开发体验(趋势)
  • Webpack-cli   为webpack提供命令行的工具
  • Main.js     webpack打包时的入口文件
  • Webpack.config.js     配置文件

2、webpack的构建流程

  1. 初始化流程:从配置文件和 Shell 语句中读取与合并参数,并初始化需要使用的插件和配置插件等执行环境所需要的参数
  2. 编译构建流程:从 Entry 发出,针对每个 Module 串行调用对应的 Loader 去翻译文件内容,再找到该 Module 依赖的 Module,递归地进行编译处理
  3. 输出流程:对编译后的 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工作原理?为什么能解决跨域?

  1. webpack提供的代理服务,基本行为就是接收客户端发送的请求后转发给其他服务器,便于开发者在开发模式下解决跨域问题(浏览器安全策略限制),实现代理首先需要一个中间服务器,webpack中提供服务器的工具为webpack-dev-server(只适用于开发阶段)。
  2. 在开发阶段, webpack-dev-server 会启动一个本地开发服务器,所以我们的应用在开发阶段是独立运行在 localhost 的一个端口上,而后端服务又是运行在另外一个地址上。所以在开发阶段中,由于浏览器同源策略的原因,当本地访问后端就会出现跨域请求的问题。
  3. 通过设置webpack proxy实现代理请求后,相当于浏览器与服务端中添加一个代理者。当本地发送请求的时候,代理服务器响应该请求,并将请求转发到目标服务器,目标服务器响应数据后再将数据返回给代理服务器,最终再由代理服务器将数据响应给本地。
  4. 在代理服务器传递数据给本地浏览器的过程中,两者同源,并不存在跨域行为,这时候浏览器就能正常接收数据。而代理服务器与目标服务器由于服务器之间不存在跨域问题,可以正常进行数据交流。

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的思路?

  1. 区别:
  • loader 是文件加载器,能够加载资源文件,并对这些文件进行一些处理,诸如编译、压缩等,最终一起打包到指定的文件中
  • plugin 拓展 webpack 各种灵活的功能,例如打包优化、资源管理、环境变量注入等,目的是解决 loader 无法实现的其他事
  • loader 运行在打包文件之前
  • plugins 在整个编译周期都起作用
  1. 编写思路:
  • 一般在编写loader的过程中,保持功能单一,避免做多种功能
  • 插件必须是一个函数或者是一个包含 apply 方法的对象,这样才能访问compiler实例
  • 传给每个插件的 compilercompilation 对象都是同一个引用,因此不建议修改
  • 异步的事件需要在插件处理完任务时调用回调函数通知 webpack 进入下一个流程,不然会卡住

8、如何借助webpack来优化前端性能?

  • JS代码压缩
  • CSS代码压缩(通常是去除无用的空格):css-minimizer-webpack-plugin
  • Html文件代码压缩:HtmlWebpackPlugin
  • 文件大小压缩(减少http传输过程中宽带的损耗):compression-webpack-plugin
  • 图片压缩:
  • Tree Shaking
  • 代码分离(将代码分离到不同的bundle中,之后我们可以按需加载)
  • 内联 chunk