乐趣区

关于前端:WebPack面试题汇总

1,Webpack 有什么作用,谈谈你对它的了解

当初的前端网页功能丰富,特地是 SPA(single page web application 单页利用)技术风行后,JavaScript 的复杂度减少和须要一大堆依赖包,还须要解决 Scss、Less……新增款式的扩大写法的编译工作。Webpack 最外围的性能就是实现动态模块打包,当 Webpack 解决应用程序时,会递归构建一个依赖关系图,其中蕴含应用程序须要的每个模块,而后将这些模块打包成一个或多个 bundle 资源包。

事实上,当初市面上最风行的三个前端框架,能够说和 webpack 都曾经严密相连,官网框架都推出了对应的 webpack 构建工具,常见的组合为 React+WebPack、Vue+WebPack 以及 Angluar+WebPack。

2,前端我的项目为什么要进行打包和构建

之所以要进行打包和构建,是从代码开发层面和部署层面来思考的:

代码层面

  • 打包能够使体积更小(Tree-shaking、压缩、合并),加载更快
  • 编译高级语言和语法(TS、ES6、模块化、scss)
  • 兼容性和谬误查看(polyfill、postcss、eslint)

研发流程层面

  • 对立、高效的开发环境
  • 对立的构建流程和产出规范
  • 集成公司构建标准(提测、上线)

3,gulp/grunt 与 Webpack 有哪些区别

三者都是前端构建工具,grunt 和 gulp 在晚期比拟风行,当初 webpack 相对来说比拟支流,不过一些轻量化的工作还是会用 gulp 来解决,比方独自打包 CSS 文件等。

grunt 和 gulp 是基于工作和流(Task、Stream)的。相似 jQuery,找到一个(或一类)文件,对其做一系列链式操作,更新流上的数据,整条链式操作形成了一个工作,多个工作就形成了整个 web 的构建流程。

而 webpack 的我的项目构建则是基于入口的,webpack 会主动地递归解析入口所须要加载的所有资源文件,而后用不同的 Loader 来解决不同的文件,用 Plugin 来扩大 webpack 性能。
 

从构建规定上来说,gulp 和 grunt 须要开发者将前端构建过程拆分多个 Task,并正当管制所有 Task 的调用关系,webpack 须要开发者找到入口,并须要分明对于不同的资源应该应用什么 Loader 做何种解析和加工的。

 

4,Webpack 提供的基本功能有哪些

目前,Webpack 反对如下一些常见的性能(具体视版本而定):

  • 代码转换 :TypeScript 编译成 JavaScript、SCSS 编译成 CSS 等等
  • 文件优化 :压缩 JavaScript、CSS、html 代码,压缩合并图片等
  • 代码宰割 :提取多个页面的公共代码、提取首屏不须要执行局部的代码让其异步加载
  • 模块合并 :在采纳模块化的我的项目有很多模块和文件,须要构建性能把模块分类合并成一个文件
  • 主动刷新 :监听本地源代码的变动、主动构建、刷新浏览器
  • 代码校验 :在代码被提交到仓库前须要检测代码是否符合规范,以及单元测试是否通过
  • 主动公布 :更新完代码后,主动构建出线上公布代码并传输给公布零碎。

5,简略形容下 webpack 的构建流程

Webpack 的运行流程是一个串行的过程,从启动到完结会会顺次执行以下流程:

  1. 初始化编译参数 :从配置文件和 shell 命令中读取与合并参数;
  2. 开始编译 :依据上一步失去的参数初始化 Compiler 对象,加载所有配置的 Plugin,执行对象的 run 办法开始执行编译;
  3. 确定入口 :依据配置中的 entry 找出所有的入口文件;
  4. 编译模块 :从入口文件触发,调用所有配置的 Loader 对模块进行翻译,再找出该模块依赖的模块,而后递归本步骤直到所有入口依赖的文件都进行翻译;
  5. 实现模块编译 :在通过第 4 步应用 Loader 翻译完所有模块后,失去了每个模块被翻译后的最终内容以及它们之间的依赖关系图。
  6. 输入资源 :依据依赖关系图,组装成一个个蕴含多个模块的 Chunk,再把每个 Chunk 转化成一个独自的文件退出到输入列表,依据配置确定输入的门路和文件名,输入。
  7. 输入实现 :在确定好输入内容后,依据配置确定输入的门路和文件名,把文件内容写入到文件系统。

在以上过程中,Webpack 会在特定的工夫点播送出特定的事件,插件在监听到感兴趣的事件后会执行特定的逻辑,并且插件能够调用 Webpack 提供的 API 扭转 Webpack 的运行后果。整体过程如下图所示。

 

6,简略介绍下 Webpack 的基本概念

  • Entry:入口,Webpack 执行构建的第一步将从 Entry 开始,通知 webpack 要应用哪个模块作为构建我的项目的入口,默认为./src/index.js。
  • output:进口,通知 webpack 在哪里输入它打包好的代码以及如何命名,默认为./dist
  • Module:模块,在 Webpack 里所有皆模块,一个模块对应着一个文件。Webpack 会从配置的 Entry 开始递归找出所有依赖的模块。
  • Chunk:代码块,一个 Chunk 由多个模块组合而成,用于代码合并与宰割。
  • Loader:模块转换器,用于把模块原内容依照需要转换成新内容。
  • Plugin:扩大插件,在 Webpack 构建流程中的特定时机会播送出对应的事件,插件能够监听这些事件的产生,在特定机会做对应的事件。

 

7,简略形容下 Webpack 的工作原理

webpack 通过入口文件逐层遍历到模块依赖,进行代码剖析、代码转换,最终生成可在浏览器运行的打包后代码。实质上,webpack 是一个古代 JavaScript 应用程序的动态模块打包器。当 webpack 解决应用程序时,它会递归地构建一个依赖关系图,其中蕴含应用程序须要的每个模块,而后将所有这些模块打包成一个或多个 bundle 包。并且在 3.0 版本之后,Webpack 还肩负起了优化我的项目的责任。
 

8,如何进步 Webpack 的构建速度

随着前端我的项目波及到的页面越来越多,性能和业务代码也会随着减少,相应的 webpack 的构建工夫也会越来越久,如果构建工夫过长,会大大降低工作效率。以下是常见的进步 Webpack 我的项目构建的措施:

  • 多入口状况下,应用 CommonsChunkPlugin 来提取公共代码。
  • 通过 externals 配置来提取罕用库。
  • 利用 DllPlugin 和 DllReferencePlugin 预编译资源模块通过 DllPlugin 来对那些咱们援用然而相对不会批改的 npm 包来进行预编译,再通过 DllReferencePlugin 将预编译的模块加载进来。
  • 应用 Happypack 实现多线程减速编译。
  • 应用 webpack-uglify-paralle 来晋升 uglifyPlugin 的压缩速度,webpack-uglify-parallel 采纳了多核并行压缩来晋升压缩速度。
  • 应用 Tree-shaking 和 Scope Hoisting 来剔除多余代码
  • 优化 Loader 配置

 

9,Webpack 是怎么配置单页利用和多页面利用的

单页利用能够了解为 Webpack 的规范模式,间接在 entry 中指定单页利用的入口即可。多页利用的话,能够应用 webpack 的 AutoWebPlugin 来实现简略自动化的构建,然而前提是我的项目的目录构造必须恪守他预设的标准。多页利用中须要留神以下几点:

  • 每个页面都有公共的代码,能够将这些代码抽离进去,防止反复的加载。比方,每个页面都援用了同一套 css 样式表。
  • 随着业务的一直扩大,页面可能会一直的追加,所以肯定要让入口的配置足够灵便,防止每次增加新页面还须要批改构建配置。

 
事实上,单页应用程序和多页应用程序的 webpack 配置文件其实绝大部分都还是雷同的,只不过多页的配置须要在单页配置的根底上顾及到多个页面罢了,loader、output、plugins 这些根本都不须要改变,须要改变的个别都是入口文件 entry,如果你用到了 抽离 css 款式的插件 extract-text-webpack-plugin、主动模板插件  html-webpack-plugin 的话,那么还须要对这两个插件进行额定的改写。

10,Webpack 中 Loader 的作用是什么,有哪些常见的 Loader

Loader 是 webpack 中提供了一种解决多种文件格式的机制,因为 Webpack 默认只反对辨认 JS 和 JSON,然而 Webpack 打造的概念是“所有皆模块”,想要实现这个概念,就须要应用 Loader。Loader 相当于翻译官,能够将其余类型资源进行预处理,并对模块的 ” 源代码 ” 进行转换。

常见的 Loader 有如下一些:

  • less-loader:将 less 文件编译成 css 文件
  • css-loader:将 css 文件变成 commonjs 模块加载到 js 中,模块内容是款式字符串
  • style-loader:创立 style 标签,将 js 中的款式资源插入标签内,并将标签增加到 head 中失效
  • ts-loader:打包编译 Typescript 文件
  • url-loader:将文件转换为 base64 URI
  • source-map-loader:加载额定的 Source Map ⽂件,以⽅便断点调试
  • babel-loader:将 ES6 转化为 ES5
  • file-loader:把⽂件输入到⼀个⽂件夹中,在代码中通过绝对 URL 去引⽤输入的⽂件

11,Plugin 有什么作用,有哪些常见的 Plugin

Plugin 的次要做用就是为了解决 Loader 无奈实现的事件,比方打包优化和代码压缩等。通过扩大 Webpack 性能,在构建流程里注入钩子来解决很多 Loader 无奈解决的工作,给 Webpack 带来了很大的灵活性。

通常,Webpack 通过 plugins 属性来配置须要应用的插件列表。plugins 属性是一个数组,外面的每一项都是插件的一个实例,在实例化一个组件时能够通过构造函数传入这个组件反对的配置属性。

常见的 Plugin 插件有如下一些:

  • html-webpack-plugin:解决 html 资源,默认会创立一个空的 HTML,主动引入打包输入的所有资源(js/css)。
  • mini-css-extract-plugin:打包过后的 css 在 js 文件里,该插件能够把 css 独自抽出来。
  • clean-webpack-plugin:每次打包时候,CleanWebpackPlugin 插件就会主动把上一次打的包删除。

12,简述下 Webpack sourceMap 的作用

当咱们应用 webpack 打包代码出错的时候,如果不应用 sourceMap,咱们只能晓得打包后的代码第几行出错,并不知道对应源代码哪里出了错,所以须要它来做源代码和指标代码的映射,而 sourceMap 的次要作用就是灾打包后将文件映射到源代码,用于定位谬误地位。sourceMap 的配置如下所示:

module.exports = {
    devtool: 'source-map', // 应用 sourceMap
    ...
}

同时,加不同前缀的意义也不同:

  • inline:不生成映射关系文件,打包进 main.js
  • cheap:只准确到行,不准确到列,打包速度快;只管业务代码,不论第三方模块
  • module:不仅管业务代码,而且管第三方代码
  • eval:执行效率最快,性能最好

同时,依据官网文档介绍,配置 source-map 形式打包后,我的项目打包速度会变慢,因为打包过程中会构建映射关系,比拟消耗性能。因而,咱们须要对开发环境和线上环境进行辨别:

  • 开发者模式下 (development):去应用 sourceMap 的话,倡议应用 cheap-module-eval-source-map 的模式,这种形式提醒谬误比拟全,同时打包速度也是比拟快的。
  • 生产者模式下 (production):应用 cheap-module-source-map 能够疾速定位问题。

同时,sourceMap 还能够通过 nginx 设置将.map 文件只对白名单凋谢。

13,什么是模热更新,如何配置模块热更新

模块热更新是 webpack 的一个性能,它能够使得代码批改之后,不必刷新浏览器就能够更新。在利用过程中替换增加删出模块,无需从新加载整个页面,是高级版的主动刷新浏览器。长处是只更新变更内容,以节俭贵重的开发工夫。调整款式更加疾速,简直相当于在浏览器中更改款式。

开启 Webpack 热更新须要借助 webpack.HotModuleReplacementPlugin(),devServer 开启 hot。比方,实现热更新,只更新指定的 js 模块。

if (module.hot) {module.hot.accept(’./library.js’, function() {// Do something with the updated library module…});
}

热更新的原理图下图所示。

14,什么是模块懒加载

懒加载或者按需加载,是一种很好的优化网页或利用的形式。实际上是先把代码在一些逻辑断点处罚来到,而后在一些代码块中实现某些操作后,立刻援用或援用另外一些新的代码块。这样放慢了利用的初始加载速度,加重了加载的体积。

在 WebPack 中,实现模块 / 文件的懒加载须要用到 prefetch 和 preloading 等关键字。比方,先加载主业务文件,而后利用网络闲暇工夫异步加载其余组件。

import(/* webpackPrefetch: true /‘LoginModal’);

如果须要和主业务文件一起加载,异步加载组件,能够应用上面的形式。

import(/ webpackPreload: true */‘ChartingLibrary’);

15,什么是长缓存,在 webpack 中如何实现长缓存优化

Webpack 打包的资源,最终都是在浏览器上出现给用户,浏览器在用户拜访页面的时候,为了放慢加载速度,会对用户拜访的动态资源进行存储。浏览器缓存能够分为强缓存和协商缓存两种。

强缓存是指在不拜访服务器的状况下,间接从浏览器获取前端资源。读取资源的形式能够从缓存中读取,也能够从磁盘中读取。实现的形式是在响应头设置 Expires 字段或者 Cache-Control 字段。

协商缓存是指在拜访服务器的状况下,服务器告知浏览器文件没变动,这时服务器会返回 304,能够间接利用缓存中的资源。实现协商缓存的形式是两对组合 (响应头 / 申请头):Last-Modified/If-Modified-Since;ETag/If-None-Match。

对于长缓存,能够在 output 给出输入的文件制订 chunkhash,并且拆散常常更新的代码和框架代码,通过 NameModulesPlugin 或者 HashedModulesPlugin 使再次打包文件名不变。

参考:webpack4 配置浏览器长缓存

16,polyfill 和 runtime 有什么区别

babel-polyfill 的原理是当运行环境中并没有实现的一些办法,babel-polyfill 会做兼容。babel-runtime 它是将 es6 编译成 es5 去执行。通常,咱们应用 es6 的语法来编写利用,最终都会通过 babel-runtime 编译成 es5。也就是说,不论浏览器是否反对 ES6,只有是 ES6 的语法,它都会进行转码成 ES5,所以就会产生很多冗余的代码。

babel-polyfill 它是通过向全局对象和内置对象的 prototype 上增加办法来实现的。比方运行环境中不反对 Array.prototype.find 办法,引入 polyfill, 咱们就能够应用 es6 办法来编写了,然而毛病就是会造成全局空间净化。

babel-runtime 它不会净化全局对象和内置对象的原型,比如说咱们须要 Promise,咱们只须要 import Promise from ‘babel-runtime/core-js/promise’即可,这样不仅防止净化全局对象,而且能够缩小不必要的代码。

退出移动版