跳到主要内容

常见面试题

介绍一下 webpack

Webpack 是一个现代 JavaScript 应用程序的静态模块打包工具。它主要用于将各种资源,如 JavaScript、CSS、图片等,打包成静态文件,以便在浏览器中加载。

以下是 Webpack 的一些主要特性和概念:

  1. 模块化支持:Webpack 支持各种模块化规范,如 CommonJS、ES Modules、AMD 等,可以将项目中的各种模块打包成静态文件。
  2. 入口(Entry):Webpack 通过指定一个或多个入口文件来开始构建打包过程。入口文件是整个应用程序的起点,Webpack 会从入口文件开始分析项目中的依赖关系,并逐步构建整个依赖图。
  3. 输出(Output):Webpack 通过指定一个输出文件来指定打包后的结果。输出文件可以是单个文件,也可以是多个文件,可以是 JavaScript 文件、CSS 文件、图片文件等。
  4. Loader:Webpack 使用 Loader 来处理各种类型的资源文件。
  5. Plugin:Webpack 使用 Plugin 来扩展其功能。Plugin 可以在打包过程中执行各种任务,如压缩代码、提取公共模块、生成 HTML 文件等。
  6. 模式(Mode):Webpack 提供了 development 和 production 两种模式。开发模式(development)会开启一些辅助开发的功能,如代码映射、热更新等;生产模式(production)则会开启一些优化功能,如代码压缩、Tree Shaking 等。
  7. 代码分割(Code Splitting):Webpack 支持将代码拆分成多个块,并按需加载。这样可以提高页面加载速度,减小初始加载时间。
  8. DevServer:Webpack 提供了一个开发服务器(DevServer),可以在本地快速启动一个服务器,支持热更新、模块替换等功能,方便开发调试。

webpack 代码分块实现方式是什么

Webpack 提供了几种代码分块(Code Splitting)的实现方式,以便优化应用程序的加载性能。以下是一些常见的代码分块实现方式:

  1. 使用动态 import()

在代码中使用动态 import() 函数,可以在运行时根据需要动态加载模块。Webpack 会将 import() 中的模块单独打包成一个 chunk,并在需要时按需加载。

import('./module').then(module => {
// 使用 module
});
  1. 使用 SplitChunksPlugin

使用 Webpack 的 SplitChunksPlugin 可以将项目中共享的模块抽取出来,打包成单独的 chunk。可以通过配置 SplitChunksPlugin 来指定哪些模块应该被抽取,以及如何分割和命名 chunk。

module.exports = {
optimization: {
splitChunks: {
chunks: 'all'
}
}
};
  1. 使用 magic comments

可以在 import 语句中使用 magic comments 来控制代码分块的行为。例如,使用 /* webpackChunkName: "my-chunk" */ 来指定生成的 chunk 的名称。

import(/* webpackChunkName: "my-chunk" */ './module');
  1. 使用 bundle-loader

bundle-loader 是一个 Webpack Loader,可以将模块打包成一个单独的 chunk,并在需要时异步加载。

module.exports = {
module: {
rules: [
{
// 定义了一个规则,指定了文件名后缀为 .bundle.js 的文件将使用 bundle-loader 进行处理。
test: /\.bundle\.js$/,
use: {
loader: 'bundle-loader',
options: {
lazy: true // 延迟加载
}
}
}
]
}
};
import myModule from 'bundle-loader!./module';
myModule(module => {
// 使用 module
});

对于一个大型文件,应该根据其功能和依赖关系进行合理的代码分块。一般来说,可以按照以下原则进行分块:

  • 按路由分块:根据页面路由进行分块,每个路由对应一个 chunk,这样可以实现按需加载页面的代码,提高首屏加载速度。
  • 按功能分块:将具有相似功能的模块分组打包成一个 chunk,例如将所有的 UI 组件打包成一个 chunk、将所有的数据处理模块打包成一个 chunk 等。
  • 按第三方库分块:将第三方库单独打包成一个 chunk,可以利用浏览器的缓存机制,减少第三方库的重复下载,提高页面加载速度。
  • 按业务逻辑分块:根据业务逻辑的复杂度和重要性进行分块,将复杂的业务逻辑打包成一个 chunk,以便管理和维护。

1. plugin 和 loader 有什么区别和联系

loader:

由于 webpack 本身只能打包 commonjs 规范的 js 文件,所以针对 css,图片等格式的文件没法打包,就需要引入第三方的模块进行打包。 loader 扩展了 webpack,只专注于转化文件这一个领域,完成压缩 / 打包 / 语言翻译等,仅仅只是为了打包。

plugin:

plugin 也是为了扩展 webpack 的功能,plugin 是作用于 webpack 本身的;从打包优化到压缩,到重新定义环境变量,针对 html 文件打包和拷贝(还有很多设置)的插件:html-webpack-plugin

区别:

  1. loader 运行在打包文件之前(loader 为在模块加载时的预处理文件)
  2. plugins 在整个编译周期都起作用。

2. tree shaking 底层是如何实现的

Webpack 的 Tree Shaking 是通过静态代码分析和依赖图来实现的。在 JavaScript 模块化编程中,模块之间的依赖关系可以表示为一个有向图,其中节点是模块,边是依赖关系。Webpack 通过分析这个依赖图,确定哪些代码实际上被引用,从而可以进行 Tree Shaking。

下面是 Webpack Tree Shaking 的基本实现原理:

  1. 静态分析:Webpack 会分析代码,并建立模块之间的依赖关系图。它会追踪模块导出的成员以及模块之间的引用关系,形成一个静态的依赖图。
  2. 标记未使用代码:Webpack 在分析代码时,会标记那些被引用但未被使用的代码。这些未被使用的代码被认为是可剔除的。
  3. 消除未使用代码:在标记完未使用的代码后,Webpack 会通过构建工具进行优化,从最终的打包文件中移除这些未使用的代码。这样,最终生成的代码包将只包含被实际使用到的代码。
  4. ES6 模块静态特性:Tree Shaking 主要依赖于 ES6 模块的静态特性。ES6 模块是静态的,意味着它们的导入和导出在编译时就已经确定,不会受到运行时条件的影响。这使得 Webpack 能够在构建过程中静态地分析模块之间的依赖关系,并识别出哪些代码被使用,哪些代码没有被使用。

总的来说,Webpack 的 Tree Shaking 是通过静态分析代码和依赖图,识别和移除未被使用的代码来实现的。这种优化技术可以帮助减小打包后的文件大小,提高应用程序的性能。

3. DllPlugin 和 DllReferencePlugin 有什么区别和联系

  • DllPlugin是一个用于创建动态链接库(Dynamic Link Library)的插件。它的作用是将一些不经常变更的代码打包成一个单独的动态链接库,以便在构建过程中能够被重复利用,从而提升构建速度。
  • DllReferencePlugin 用于在项目的 Webpack 配置中引用动态链接库,以便在构建时重用其中的模块。DllReferencePlugin 会根据 DllPlugin 生成的 manifest 文件,告诉 Webpack 在构建时去哪里找到动态链接库。

具体来说,工作流程如下:

  1. 将一组模块打包成一个单独的动态链接库。
  2. 生成一个 manifest 文件,记录了模块的映射关系和路径。
  3. 在 webpack 配置中使用DllReferencePlugin引入这个 manifest 文件,告诉 Webpack 在构建时去哪里找到这个动态链接库。
  4. 当 Webpack 构建时,它会根据 manifest 文件中的映射关系去动态链接库中寻找对应的模块,从而避免了对这些模块的重复打包工作,提升了构建速度。

总的来说,DllPlugin 的作用是优化 Webpack 构建过程,通过将不经常变更的代码提取成动态链接库,减少了重复打包的时间,提高了构建效率。