likes
comments
collection
share

webpack系列-面试官:webpack用过么?原理是什么?你做过哪些配置?

作者站长头像
站长
· 阅读数 11

面试中会有一个评价,叫cli工程师,就是会用不会配,很扣分,尤其3年以上。

本文先从基础讲起,3年以下经验,如有疑惑,可要查漏补缺了。

接上篇: 《webpack系列-大厂webpack面试真题》

一、面试官灵魂三连问

  1. 你用过webpack么,它的原理是什么?
  2. 你还知道些构建工具,各有什么优缺点?
  3. 你在项目中有配置过么,在哪些场景配置过?

二、webpack介绍

1.什么是webpack?

webpack 是一个模块打包器。webpack 的主要目标是将 JavaScript 文件打包在一起,打包后的文件用于在浏览器中使用,但它也能够胜任转换(transform)、打包(bundle)。

2.webpack原理是什么?

核心概念

  • entry:一个可执行模块或者库的入口。
  • chunk:多个文件组成一个代码块。可以将可执行的模块和他所依赖的模块组合成一个chunk,这是打包。
  • loader:文件转换器。例如把es6转为es5,scss转为css等
  • plugin:扩展webpack功能的插件。在webpack构建的生命周期节点上加入扩展hook,添加功能。
  • output:编译结果文件输出

构建流程

Webpack 的运⾏流程是⼀个串⾏的过程,从启动到结束会依次执⾏以下流程:

  1. 初始化参数:解析webpack配置参数,合并shell传入和webpack.config.js文件配置的参数,形成最后的配置结果。
  2. 开始编译:上一步得到的参数初始化compiler对象,注册所有配置的插件,插件监听webpack构建生命周期的事件节点,做出相应的反应,执行对象的 run 方法开始执行编译。
  3. 确定入口:从配置的entry入口,开始解析文件构建AST语法树,找出依赖,递归下去。
  4. 编译模块:递归中根据文件类型和loader配置,调用所有配置的loader对文件进行转换,再找出该模块依赖的模块,再递归本步骤直到所有入口依赖的文件都经过了本步骤的处理。
  5. 完成模块编译:在经过第4步使⽤ Loader 翻译完所有模块后,得到了每个模块被翻译后的最终内容以及它们之间的依赖关系;
  6. 输出资源:根据⼊⼝和模块之间的依赖关系,组装成⼀个个包含多个模块的 Chunk,再把每个 Chunk 转换成⼀个单独的⽂件加⼊到输出列表,这步是可以修改输出内容的最后机会;
  7. 输出完成:在确定好输出内容后,根据配置确定输出的路径和⽂件名,把⽂件内容写⼊到⽂件系统。

注意:

在以上过程中,Webpack 会在特定的时间点,⼴播出特定的事件,插件在监听到感兴趣的事件后,会执⾏特定的逻辑。并且插件可以调⽤ Webpack 提供的 API ,改变 Webpack 的运⾏结果。比如UglifyPlugin,会在loader转换递归完,对结果使用UglifyJs压缩,覆盖之前的结果。

三、扩展:还知道哪些构建工具?有什么优缺点?

大致了解下就好 ,现在主流的是webpack、rollup、vite

1.构建工具有哪些?

webpackgruntgulpFIS3

2.他们有什么不同?

  • 都是前端构建工具,grunt和gulp在早期比较流行,FIS3停止维护了,现在webpack相对来说比较主流,不过一些轻量化的任务,还是会用gulp来处理,比如单独打包CSS文件等。
  • grunt和gulp是基于任务(Task、Stream)的。类似jQuery,找到一个(或一类)文件,对其做一系列链式操作,更新流上的数据, 整条链式操作构成了一个任务,多个任务就构成了整个web的构建流程
  • webpack是基于入口的。webpack会自动地递归解析入口所需要加载的所有资源文件,然后用不同的Loader来处理不同的文件,用Plugin来扩展webpack功能。
  • webpack优点是专注于处理模块化的项目,尤其适合单页应用。Webpack的缺点是只能用于采用模块化开发的项目。
  • FIS3并没有入口(entry)的概念,在FIS3中,构建流程不单单根据js来,而是分析每一个文件的依赖关系,生成一个资源表‘sourceMap’,你可以根据资源表定义任何的产出规则
  • Fis3的优点是集成了各种Web开发所需的构建功能,配置简单、开箱即用。其缺点是目前官方已经不再更新和维护不支持最新版本的Node.js。Fis3是一种专注于Web开发的完整解决方案,如果将Grunt、Gulp比作汽车的发动机,则可以将Fis3比作一辆完整的汽车

总结:

从构建思路来说:gulp和grunt需要开发者将整个前端构建过程拆分成多个Task,并合理控制所有Task的调用关系; webpack需要开发者找到入口,并需要清楚对于不同的资源应该使用什么Loader做何种解析和加工;FIS3任何文件都可以作为入口

对于知识背景:gulp更像后端开发者的思路,需要对于整个流程了如指掌; webpack更倾向于前端开发者的思路。

参考文章:前端工具简介 fis3,webpack

3.有类似webpack的工具么?

同样是基于入口的打包工具还有以下几个:webpack,rollupparcelvitesnowpack

从应用场景上来看:

  • webpack:适合大型复杂的前端站点构建,尤其是模块化的,单页应用。
  • rollup:专门针对类库进行打包,它的优点是小巧而专注。因此现在很多我们熟知的库都都使用它进行打包,比如:Vue、React和three.js等。
  • parcel:零配置,傻瓜式。适用于简单的实验室项目,打包出错很难调试。不支持Tree Shaking。更多优点:传送门
  • vite:灵活、复杂度适中,未来趋势。开发期间无需打包,越大型体验感越好。
  • snowpack与vite类似。

rollup、vite、snowpack,都是基于ESM,开发期间无需构建,浏览器直用。

参考文章:

从Npm Script到Webpack,6种常见的前端构建工具对比

webpack VS parcel

深入对比Webpack、Parcel、Rollup打包工具

4.作为官方推荐的vite,和现在应用最广的webpack的区别?

需要理解,当下最火,被问到概率大

逸轩技巧提示:

加粗字体连起来,就是浓缩重点~

看看我这么贴心,还不小手点赞关注~

Webpack 是一个打包模块化 JavaScript 的工具,在 Webpack 里一切文件皆模块,通过 Loader 转换文件,通过 Plugin 注入钩子,最后输出由多个模块组合成的文件。Webpack 专注于构建模块化项目。

一切文件:JavaScript、CSS、SCSS、图片、模板,在 Webpack 眼中都是一个个模块,这样的好处是能清晰的描述出各个模块之间的依赖关系,以方便 Webpack 对模块进行组合和打包。 经过 Webpack 的处理,最终会输出浏览器能使用的静态资源。因此每次编译都需要重新构建

vite主要遵循的是使用ESM(Es modules模块)的规范来执行代码,由于现代浏览器基本上都支持了ESM规范,所以在开发阶段并不需要将代码打包编译成es5模块,即可直接在浏览器上运行。我们只需要从入口文件出发, 在遇到对应的 import 语句时,将对应的模块加载到浏览器中就可以了。当项目越大,文件越多时,vite的开发时优势越明显。vite热更新比webpack,vite在HRM方面,当某个模块内容改变时,让浏览器直接重新请求该模块即可,而不是像webpack重新将该模块的所有依赖重新编译

Vite的使用简单,只需执行初始化命令,就可以得到一个预设好的开发环境,开箱即获得一堆功能,包括:CSS预处理、html预处理、异步加载、分包、压缩、HMR等。使用复杂度介于Parcel和Webpack的中间,只是暴露了极少数的配置项和plugin接口,既不会像Parcel一样配置不灵活,又不会像Webpack一样需要了解庞大的loader、plugin生态,灵活适中、复杂度适中。

总体来说,Vite在前端构建工具领域上开辟了一条和webpack完全不同的道路,很好地解决了前端开发阶段构建速度慢的问题。

参考文章:Vite介绍和原理解析

四、webpack基本配置

安装

全局安装

npm install -g webpack

npm install -g webpack-cli

项目依赖

npm install --save-dev webpack

npm install --save-dev webpack-cli

1. 基本配置-入口:

入口起点(entry point)指示 webpack 应该使用哪个模块,来作为构建其内部依赖图的开始。

2.基本配置-出口

output 属性告诉 webpack 在哪里输出它所创建的 bundles

3.基本配置-loaders

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

4.基本配置-plugins

webpack插件(自动打开浏览器、热更新等)

5.基本配置-模式

package.json中设置:

”scripts": {
    "dev": "webpack --mode development",  // 开发环境
     "build": "webpack --mode production",  // 生产环境
  }

webpack.config.js中设置:

module.exports = {
    entry: './src/app.js',
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'main.js'
    },
    mode: 'development' // 设置mode
}

development:有内置的调试功能;打包后的代码可阅读,没被压缩

production:内置生产阶段的很多优化功能;代码被压缩

6.基本配置-启动本地服务

方式一:

在package.json里的script属性里配置,完了执行npm run xxx

例如vue项目中

package.json

"scripts": {
  "dev": "vue-cli-service serve",
  "build": "vue-cli-service build",
  "lint": "vue-cli-service lint"
}

命令行:

npm run dev

方式二:

通过npx

例如vue项目中

命令行:

npx cli-service serve

npx:www.npmjs.com/package/npx

7.模块化

webpack 默认使用commonjs规范

webpack系列-面试官:webpack用过么?原理是什么?你做过哪些配置? 如果只是使用import 导入模块后,浏览器是不能直接识别的,必须导入webpack才行。

五、其他基本常用配置

1.webpack跨域解决方案

proxy

2.ES6转ES5

babel

3.less转css

less-loader

webpack系列-面试官:webpack用过么?原理是什么?你做过哪些配置? 注意:配置时执行顺序默认是从右到左,从下到上

面试官追问:loader为什么是从右到左,从下到上的执行顺序?

埋个坑,会在下一篇里公布结果

4.处理图片

方式一:url-loader

小于limit限制的转base64

webpack系列-面试官:webpack用过么?原理是什么?你做过哪些配置? 说明:url-loader处理的图片一般比较小,会把图片转换成base64代码,直接添加页面。提供了一个方便的选择 limit,该选项用于控制当文件大小小于 limit 时才使用 url-loader。通常会设置5-8kb

扩展:哈希的作用是命中缓存,使返回更快些。

方式二:file-loader

把图片转换成路径。

webpack系列-面试官:webpack用过么?原理是什么?你做过哪些配置?

5.拆分配置和merge

背景:''四-5基本配置-模式'',里面介绍过模式之间的区别,为了解决手动更改mode带来的不便,所以,要将这些打包的配置,拆分到不同的文件里面来。

  • webpack.dev.config.js 开发环境的配置;
  • webpack.prod.config.js生产环境的配置;
  • webpack.base.config.js是开发环境和生产环境都会使用的配置;
  • 通过webpack-merge模块将不同配置的代码合并;

webpack.dev.config.js

const commonConfig = require('./webpack.base.config')
// webpack-merge 将公共的配置 和 开发的配置合并结合
const { smart: merge } = require('webpack-merge')
const devConfig = {
  mode: 'development'
}
module.exports = merge(commonConfig, devConfig)

webpack.prod.config.js

const commonConfig = require('./webpack.base.config')
const { smart: merge } = require('webpack-merge')
const prodConfig = {
  mode: 'production'
}
module.exports = merge(commonConfig, prodConfig)

六、业务场景

1、单页应用

2、一个项目管理多个单页面

3、代码分隔优化

一个好的代码分割对浏览器首屏效果提升很大。

4、构建服务端渲染

5、热更新

6、优化开发编译、生产环境打包速度

7、优化首屏速度

等等,说几个就好,例子越具体越好,第6、7条很宽泛,但也很万金油。

下一篇:《webpack高级配置》,介绍下更高级的配置,也顺便剖析下以上场景具体如何去做。