前端面试题之webpack系列

1、说说你对webpack的理解,解决了什么问题?

webpack是一个用于现在JavaScript应用程序的静态模块打包工具。

模块化

最早的时候,我们会通过文件划分的形式实现模块化,也就是将每个功能及其相关状态数据各自单独放到不同的JS文件中,约定每个文件是一个独立的模块,然后再将这些js文件引入到页面,一个script标签对应一个模块,然后调用模块化的成员。但是这个模块弊端十分的明显,模块都是在全局中工作,大量模块成员污染了环境,模块与模块之间并没有依赖关系,维护困难,没有私有空间等问题。随后,就出现了命名空间方式,规定每个模块只暴露一个全局对象,然后模块的内容都挂载到这个对象中,但是这种方式也并没有解决第一种方式得到依赖等问题。再后来,我们使用立即执行函数为模块提供私有空间,通过参数的形式作为依赖声明。

这些都是早期解决模块的方式,但是仍然存在一些没有解决的问题。

【webpack解决的问题】:

1.通过模块化的方式来开发;

2.开发完成后,可以将代码进行压缩,合并已经其他相关的优化

3.解决浏览器兼容问题,提高效率

4.模块整合能力,解决浏览器频繁请求文件的问题

5.支持不同种类的前端模块类型,统一的模块化方案。

2、说说webpack的构建流程

【webpack的构建流程】:

1、初始化流程:初始化需要使用的插件和配置插件等执行环境所需要的参数;

2、编译构建流程:从entery出发,针对每个module 串行调用对应的Loader去翻译文件内容,再找到该Module依赖的Module,递归地进行编译处理。

3、输出流程:对编译后的module组合成chunk(大块代码),把chunk转为文件,输出到文件系统。

3、说说webpack中常见的Loader?解决了什么问题?

loader用于对模块的“源代码”进行转换,在import或“加载”模块时预处理文件

webapck做的事情,仅仅是分析出各种模块的依赖关系,然后形成资源列表,最终打包生成到指定的文件中,webpack只支持对js和json文件打包,像css、sass、png等这些类型的文件的时候,webpack则无能为力,这时候就需要配置对应的loader进行文件内容的解析。

常见的loader:

style-loader:将css添加到DOM的内联样式标签style里;

css-loader:允许将css文件通过require的方式引入,并返回css代码;

less-loader:处理less

sass-loader:处理sass

postcss-loader:用于postcss来处理CSS

html-minify-loader:压缩HTML

babel-loader:用babel来转换ES6文件到ES

4、说说webpack中常见的Plugin解决了什么问题?

Plugin是一种计算机应用程序,它和主应用程序互相交互,以提供特定的功能。

webpack中的plugin赋予其各种灵活的功能,例如打包优化,资源管理,环境变量注入等,它们会运行在webpack的不同阶段(钩子/生命周期),贯穿了webpack整个编译周期。目的在于解决loader无法实现的其他事。

几个常见的插件的用法:

  • HtmlWebpackPlugin,在打包结束后,自动生成一个html文件,并把打包生成的js模块引入到该html中
  • clear-webpack-plugin,删除(清理)构建目录
  • mini-css-extract-plugin,提取css到一个单独的文件中
  • DefinePlugin,允许在编译时创建配置的全局对象,是一个webpack内置的插件,不需要安装
  • copy-wepack-plugin,复制文件或目录到执行区域,如vue的打包过程中,如果我们将一些文件放到public的目录下,那么这个目录会被复制到dist文件夹中

5、说说Loader和Plugin的区别?

  • loader是文件加载器,能够加载资源文件,并对这些文件进行一些处理,诸如编译,压缩等,最终一起打包到指定的文件中;
  • plugin赋予了webpack各种灵活的功能,例如打包优化,资源管理,环境变量注入等,目的是解决loader无法实现的其他事。
  • loader运行在打包文件之前;
  • plugin在整个编译周期都起作用
  • 在webpack运行的生命周期中会广播出许多事件,Plugin可以监听这些事件,在合适的时机通过Webpack提供的API改变输出结果
  • 对于loader实质是一个转换器,将A文件进行编译成B文件,操作的是文件,比如将A.scss或A.less转变为B.css,单纯的文件转换过程。

6、webpack的热更新是如何做到的?原理是什么?

HMR全称Hot Module Replacement,可以理解为模块热替换,指在应用程序运行过程中,替换,添加,删除模块,而无需重新刷新整个应用。例如,我们在应用运行过程中修改了某个模块,通过自动刷新会导致整个应用的整体刷新,那页面中的状态信息都会丢失,如果使用的是HMR,就可以实现只将修改的模块实时替换至应用中,不必完全刷新整个应用。

原理:

1、通过webpack-dev-server创建两个服务器:提供静态资源的服务ExpressSocket服务;

2、express server负责直接提供静态资源的服务(打包后的资源直接被浏览器请求和解析)

3、socket server 是一个websocket的长连接,双方可以通信

4、当 socket server 监听到对应的模块发生变化时,会生成两个文件.json(manifest文件)和.js文件(update chunk)

5、通过长连接,socket server 可以直接将这两个文件主动发送给客户端(浏览器)

6、浏览器拿到两个新的文件后,通过HMR runtime机制,加载这两个文件,并且针对修改的模块进行更新

7、说说webpack proxy工作原理?为什么不能解决跨域?

webpack proxy,即webpack提供的代理服务,基本行为就是接受客户端发送的请求后转发给其他服务器,其目的是为了便于开发者模式下解决跨域问题。想要实现代理首先需要一个中间服务器,webpack中提供服务器的工具为 webpack-dev-server

webpack-dev-server是webpack官方推出的一款开发工具,将自动编译和自动刷新浏览器等一系列对开发友好的功能全部集成在一起。目的是为了提高开发者日常的开发效率,只适用在开发阶段。

跨域

在开发阶段,webpack-dev-server会启动一个本地开发服务器,所以我们的应用在开发阶段是独立运行在localhost的一个端口上,而后端服务器又是运行在另外一个地址上,所以在开发阶段中,由于浏览器同源策略的原因,当本地访问后端就会出现跨域请求的问题。

通过设置webpack proxy实现代理请求后,相当于浏览器与服务端中添加一个代理者,当本地发送请求的时候,代理服务器响应该请求,并将请求转发给目标服务器,目标服务器响应数据后再将数据返回给代理服务器,最终再由代理服务器将数据响应给本地。在者过程中,两者同源,并不存在跨域行为,这时候浏览器就能正常接收数据。

注意:服务器与服务器之间请求数据并不会存在跨域行为,跨域行为是浏览器安全策略限制

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

通过webpack优化前端的手段有:

  • JS代码压缩

terser是一个JavaScript的解释,绞肉机,压缩机的工具集,可以帮助我们压缩代码,让bundle更小

  • CSS代码压缩

CSS压缩通常是去除无用的空格等,因为很难去修改选择器,属性的名称,值等

  • Html文件压缩

  • 文件大小压缩

  • 图片压缩

  • Tree Sharing

    在计算机中表示消除死代码,用来与ES module的静态语法分析。没有用到的代码,webpack打包的时候就会去掉。

  • 代码分离,将代码分离到不同的bundle中,之后我们可以按需加载,或者并行加载这些文件

9、如何提高webpack的构建速度

常见的提升构建速度的手段有如下:

  • 优化loader配置

在使用loader时,可以通过配置include、exclude、test属性来匹配文件,接触include、exclude规定哪些匹配应用loader

  • 合理使用resolve.extensions

在开发中我们会有各种各样的模块依赖,这些模块可能来自于自己编写的代码,也可能来自第三方库, resolve可以帮助webpack从每个 require/import 语句中,找到需要引入到合适的模块代码

resolve.extensions是根据扩展名去进行查找,引入到合适的模块代码

  • 优化resolve.modules

resolve.modules 用于配置 webpack 去哪些目录下寻找第三方模块。默认会从node_modules中查找文件。如果你安装的第三方模块都放在项目根目录下的 ./node_modules目录下时,你就可以指明存放第三方模块的绝对路径,以减少寻找。

  • 优化 resolve.alias

alias给一些常用的路径起一个别名,特别当我们的项目目录结构比较深的时候,一个文件的路径可能是./…/…/的形式通过配置alias以减少查找过程。

  • 使用DLLPlugin插件

DLL动态链接库,是为软件在window中实现共享函数库的一种实现方式

  • 使用cache-loader

是将结果缓存到磁盘里,显著提升二次构建速度,但是保存和读取这些缓存文件会有有些时间开销,所以请只对性能开销较大的loader使用此cache-loader

10、webpack类似的工具还有哪些?区别?

模块化是将应该复杂系统分割成一个特定功能的子功能模块,在把所有的模块按照某种方式组装起来,成为一个整体。

在前端领域中,并非只有webpack这一款优秀的模块打包工具,还有其他类似的工具,如Rollup/Parcel/snowpack/Vite,

这里没有提及gulp,grunt是因为它们只是定义为构建工具,不能类比。

Rollup

Rollup 是一款 ES Modules 打包器,从作用上来看,Rollup 与 Webpack 非常类似。不过相比于 Webpack,Rollup要小巧的多。

优点:

  • 代码效率更简洁,效率更高
  • 默认支持Tree-shaking
  • 打包出来的代码比webpack更小更快

缺点:

加载其他类型的资源文件或者支持导入CommonJS模块,又或是编译ES新特性,这些额外的需求Rollup需要使用插件去完成

Parcel

Parcel,是一款完全零配置的前端打包器,它提高了“傻瓜式”的使用体验,只需要了解简单的命令,就能构建前端应用程序。

Snowpack

Snowpack,是一种闪电般快速的前端构建工具,专为现代Web设计,较复杂的打包工具(如Webpack或Parcel)的替代方案。

开发阶段,每次保存单个文件时,Webpack和Parcel都需要重新构建和重新打包应用程序的整个bundle。而Snowpack为你的应用程序每个文件构建一次,就可以永久缓存,文件更改时,Snowpack会重新构建该单个文件。

Vite

vite,是一种新型前端构建工具,能够显著提升前端开发体验。

它主要由两部分组成

  • 一个开发服务器,它是基于原生ES模块,提高了丰富的内建功能,如速度快到叫人的模块热更新HMR
  • 一套构件指令,它使用Rollup打包你的代码

Vite会直接启动开发服务器,不需要进行打包操作,也就意味着不需要分析模块的依赖,不需要编译,因此启动速度非常快;利用现代浏览器支持ES Module的特性,当浏览器请求某个模块的时候,再根据需要对模块的内容进行编译,这种方式大大缩短了编译时间

Webpack

相对于上述的模块化工具,webpack大而全,很多常用的功能能做到开箱即用。有两大最核心的特点:一切皆模块和按需加载。

优势:

  • 智能解析:对CommonJS、AMD、ES6的语法做了兼容
  • 万物模块:对js、css、图片等资源文件都支持打包
  • 开箱即用
  • 代码分割:可以将代码分割成不同的chunk,实现按需加载,降低了初始化时间
  • 插件系统:具有强大的Plugin接口,具有更好的灵活性和扩展性
  • 易于调试
  • 快速运行
  • 生态环境好
  • 6
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

*neverGiveUp*

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值