# 对webpack的理解?解决了什么问题?

# 1. Webpack

可以看做一个模块化打包机,分析项目结构,处理模块化依赖,转换成为浏览器可运行的代码。

  • 代码转换: TypeScript 编译成 JavaScript、SCSS,LESS 编译成 CSS.
  • 文件优化:压缩 JavaScript、CSS、HTML 代码,压缩合并图片。
  • 代码分割:提取多个页面的公共代码、提取首屏不需要执行部分的代码让其异步加载。
  • 模块合并:在采用模块化的项目里会有很多个模块和文件,需要构建功能把模块分类合并成一个文件。
  • 自动刷新:监听本地源代码的变化,自动重新构建、刷新浏览器。

构建把一系列前端代码自动化去处理复杂的流程,解放生产力。

# 1.1 webpack配置entry有几个

# 1.2 webpack的构建流程

webpack的构建流程包括compile、make、build、seal、emit阶段。

  • 初始化参数: 从配置文件和 Shell 语句中读取与合并参数,得出最终的参数。
  • 开始编译: 根据我们的webpack配置注册好对应的插件调用 compile.run 进入编译阶段,在编译的第一阶段是 compilation,他会注册好不同类型的module对应的 factory,不然后面碰到了就不知道如何处理了。
  • 编译模块: 进入 make 阶段,会从 entry 开始进行两步操作:第一步是调用 loaders 对模块的原始代码进行编译,转换成标准的JS代码, 第二步是调用 acorn 对JS代码进行语法分析,然后收集其中的依赖关系。每个模块都会记录自己的依赖关系,从而形成一颗关系树。
  • 输出资源:根据入口和模块之间的依赖关系,组装成一个个包含多个模块的 Chunk,再把每个 Chunk 转换成一个单独的文件加入到输出列表,这步是可以修改输出内容的最后机会。
  • 输出完成:在确定好输出内容后,根据配置确定输出的路径和文件名,把文件内容写入到文件系统。

# 1.3 webpack和rollup有什么相同和不同点?

# 1.4 介绍一下Loader

前端工程师都得掌握的 webpack Loader (opens new window) Loader 的作用很简单,就是处理任意类型的文件,并且将它们转换成一个让 webpack 可以处理的有效模块。

常用的Loader有:js-babel-loader、css-style-loader``css-loader、``

Loader 可以在 webpack.config.js 里配置,也可以在 require 语句里内联;

# 1.4.1 在config里配置

Loader 可以在 webpack.config.js里配置,这也是推荐的做法,定义在 module.rules 里。

每一条 rule 会包含两个属性:test 和 use,比如 { test: /.js$/, use: 'babel-loader' } 意思就是:当 webpack 遇到扩展名为 js 的文件时,先用 babel-loader 处理一下,然后再打包它。

# 1.4.2 Loader 类型
  1. 同步Loader:this.callback()
  2. 异步Loader:this.async()
  3. Pitching Loader:
  4. Raw Loader:

# 1.5 介绍一下Plugin

通过插件,扩展 webpack,加入自定义的构建行为,使 webpack 可以执行更广泛的任务,拥有更强的构建能力。

# 1.6 webpack 热更新是如何实现的?

轻松理解webpack热更新原理 (opens new window)

Hot Module Replacement,简称HMR,无需完全刷新整个页面的同时,更新模块。HMR的好处,在日常开发工作中体会颇深:节省宝贵的开发时间、提升开发体验。

  1. webpack-dev-server启动本地服务:我们根据webpack-dev-server的package.json中的bin命令,可以找到命令的入口文件bin/webpack-dev-server.js。
  2. 修改webpack.config.js的entry配置
  3. 监听webpack编译结束
  4. webpack监听文件变化
  5. 浏览器接收到热更新的通知
  6. HotModuleReplacementPlugin 或 --hot
  7. moudle.hot.check 开始热更新
  8. hotApply 热更新模块替换
    • 删除过期的模块,就是需要替换的模块
    • 将新的模块添加到 modules 中
    • 通过__webpack_require__执行相关模块的代码

# 1.7 webpack 层面如何做性能优化

# 1.8 介绍一下 webpack 的 dll

DLL动态链接

第三库不是经常更新,打包的时候希望分开打包,来提升打包速度。打包dll需要新建一个webpack配置文件,在打包dll的时候,webpack做一个索引,写在manifest文件中。然后打包项目文件时只需要读取manifest文件。

# 1.9 介绍一下 webpack 的 tree-shaking

webpack 4 只需要配置mode为 production即可

# 一、背景

Webpack 最初的目标是实现前端项目的模块化,旨在更高效地管理和维护项目中的每一个资源

# 模块化

最早的时候,我们会通过文件划分的形式实现模块化,也就是将每个功能及其相关状态数据各自单独放到不同的JS 文件中

约定每个文件是一个独立的模块,然后再将这些js文件引入到页面,一个script标签对应一个模块,然后调用模块化的成员

<script src="module-a.js"></script>
<script src="module-b.js"></script>

但这种模块弊端十分的明显,模块都是在全局中工作,大量模块成员污染了环境,模块与模块之间并没有依赖关系、维护困难、没有私有空间等问题

项目一旦变大,上述问题会尤其明显

随后,就出现了命名空间方式,规定每个模块只暴露一个全局对象,然后模块的内容都挂载到这个对象中

window.moduleA = {
  method1: function () {
    console.log('moduleA#method1')
  }
}

这种方式也并没有解决第一种方式的依赖等问题

再后来,我们使用立即执行函数为模块提供私有空间,通过参数的形式作为依赖声明,如下

// module-a.js
(function ($) {
  var name = 'module-a'

  function method1 () {
    console.log(name + '#method1')
    $('body').animate({ margin: '200px' })
  }

  window.moduleA = {
    method1: method1
  }
})(jQuery)

上述的方式都是早期解决模块的方式,但是仍然存在一些没有解决的问题。例如,我们是用过script标签在页面引入这些模块的,这些模块的加载并不受代码的控制,时间一久维护起来也十分的麻烦

理想的解决方式是,在页面中引入一个JS入口文件,其余用到的模块可以通过代码控制,按需加载进来

除了模块加载的问题以外,还需要规定模块化的规范,如今流行的则是CommonJSES Modules

# 二、问题

从后端渲染的JSPPHP,到前端原生JavaScript,再到jQuery开发,再到目前的三大框架VueReactAngular

开发方式,也从javascript到后面的es5es6、7、8、9、10,再到typescript,包括编写CSS的预处理器lessscss

现代前端开发已经变得十分的复杂,所以我们开发过程中会遇到如下的问题:

  • 需要通过模块化的方式来开发
  • 使用一些高级的特性来加快我们的开发效率或者安全性,比如通过ES6+、TypeScript开发脚本逻辑,通过sass、less等方式来编写css样式代码
  • 监听文件的变化来并且反映到浏览器上,提高开发的效率
  • JavaScript 代码需要模块化,HTML 和 CSS 这些资源文件也会面临需要被模块化的问题
  • 开发完成后我们还需要将代码进行压缩、合并以及其他相关的优化

webpack恰巧可以解决以上问题

# 三、是什么

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

  • 静态模块

这里的静态模块指的是开发阶段,可以被 webpack 直接引用的资源(可以直接被获取打包进bundle.js的资源)

webpack处理应用程序时,它会在内部构建一个依赖图,此依赖图对应映射到项目所需的每个模块(不再局限js文件),并生成一个或多个 bundle

# webpack的能力

编译代码能力,提高效率,解决浏览器兼容问题 模块整合能力,提高性能,可维护性,解决浏览器频繁请求文件的问题 万物皆可模块能力,项目维护性增强,支持不同种类的前端模块类型,统一的模块化方案,所有资源文件的加载都可以通过代码控制

# 参考文献

更新时间: 12/14/2021, 10:12:35 AM