2023前端面试八股文(自用,不断完善中)-Webpack

447 阅读4分钟

参考[webpack构建流程 - 掘金 (juejin.cn)]

webpack的构建流程

  • 初始化参数。获取用户在webpack.config.js文件配置的参数

  • 开始编译。初始化compiler对象,注册所有的插件plugins,插件开始监听webpack构建过程的生命周期事件,不同环节会有相应的处理,然后开始执行编译。

  • 确定入口。根据webpack.config.js文件的entry入口,开始解析文件构建ast语法树,找到依赖,递归下去。

  • 编译模块。递归过程中,根据文件类型和loader配置,调用相应的loader对不同的文件做转换处理,在找出该模块依赖的模块,递归本操作,直到项目中依赖的所有模块都经过了本操作的编译处理。

  • 完成编译并输出。递归结束,得到每个文件结果,包含转换后的模块以及他们之前的依赖关系,根据entry以及output等配置生成代码块chunk

  • 打包完成。根据output输出所有的chunk到相应的文件目录

plugins和loader的区别

关于这个问题,首先要会到webpack定义loader、plugin的定义:

loader:loader让webpack去处理那些非JavaScript文件(webpack自身只理解javascript)。loader可以将所有类型的文件转换成webpack能处理的有效模块。然后利用webpack的打包能力,对它们进行处理。

plugin:插件可以用于执行其他范围更广的任务,插件的范围包括,打包优化,代码压缩,甚至可以重新定义环境中的变量。插件的目的是用于解决loader无法实现的其他事。

首先要了解loader是将非javascript文件转换为webpack能处理的有效模块,那么loader是一个输入资源转换输出的过程。

  • loader.js需要到导出一个函数,这个函数对加载的资源进行处理
  • 函数输入为加载到的资源,输出为加工的资源
  • 输出的结果有两种形式:第一就是输出为标准的JS代码,让打包结果可以正常执行,第二就是输出的结果交给下一个loader继续执行
  • 开发好的loader.js配置到webpack.config.js下面的module.rules

webpack常用loader

  1. bable-loader , babel-loader基于babel,用于解析JavaScript文件。babel有丰富的预设和插件,babel的配置可以直接写到options里或者单独写到配置文件里。
  2. ts-loader , 用来打包编译Typescript;
  3. file-loader, 用于处理文件类型资源,如jpg,png等图片。返回值为publicPath为准
  4. url-loader: 它与file-loader作用相似,也是处理图片的,只不过url-loader可以设置一个根据图片大小进行不同的操作,如果该图片大小大于指定的大小,则将图片进行打包资源,否则将图片转换为base64字符串合并到js文件里。
  5. style-loader 通过注入标签将CSS插入到DOM中;
  6. css-loader , 仅处理css的各种加载语法。
  7. postcss-loader,PostCSS 是一个允许使用 JS 插件转换样式的工具。
  8. less-loader。

webpack常用plugin

  1. html-webpack-plugin,基本作用是生成html文件

  2. clean-webpack-plugin,默认情况下,这个插件会删除webpack的output.path中的所有文件,以及每次成功重新构建后所有未使用的资源。

  3. mini-css-extract-plugin, 本插件会将 CSS 提取到单独的文件中,为每个包含 CSS 的 JS 文件创建一个 CSS 文件。

  4. webpack.HotModuleReplacementPlugin

  5. webpack-bundle-analyzer,可以看到项目各模块的大小,可以按需优化。

webpack的分包策略

  1. 按需加载:使用像 import() 这样的动态导入语法,可以实现加载代码的按需异步加载。
  2. 公共代码分离:使用 SplitChunksPlugin,可以把公共模块单独提取出来,防止重复加载。
  3. 页面级代码分割:使用 entry 配置多入口,然后抽取公共部分,可以实现每个页面只加载它需要的代码。
  4. 动态导入分包:使用 include/exclude 规则,使得 node_modules 中的模块按需进行代码分割。
  5. 组件级代码分割:结合 React.lazy 和 Suspense,可以将页面拆分为多个组件级的代码块。
  6. Hash 分割:通过配置 output.filename 进行 hash 分割,可以做到文件缓存优化。
  7. CDN 分割:把一些静态资源分别部署到不同的 CDN 上,实现资源并行加载。
  8. 路由级代码分割:基于路由进行代码分割,每个路由只加载对应的组件。