Skip to content

核心概念

webpack处理应用程序时,会在内部从一个或多个入口点构建一个依赖图,然后将项目中所需的每一个模块组合成一个或多个bundles,它们均为静态资源,用于展示内容。

webpack遵循CommonJS规范,通过require()引入其他文件

入口entry

指示webpack应该使用哪个模块来作为构建其内部依赖图的开始。进入入口起点后,webpack会找出哪些模块和库是入口起点(直接和间接)依赖的

默认值是./src/index.js,可以通过在配置文件中配置entry属性,来指定一个或多个不同的入口起点。

输出output

告诉webpack在哪里输出它创建的bundle,以及如何命名这些文件。主要输出文件的默认值是./dist/main.js,其他生成文件默认放置在./dist文件夹中。可以配置output字段。

loader

webpack只能理解JavaScript和JSON文件,loader让webpack能去处理其他类型的文件,并将它们转换为有效模块,以供应用程序使用,以及被添加到依赖图中。

webpack的配置中,loader有两个属性:

1、test属性,识别哪些文件会被转换

2、use属性,定义出在进行转换时,应该使用哪个loader

js
const path=require('path');

module.exports={
    ouput:{
        filename:'my-first-webpack.bundle.js',
    },
    module:{
        rules:[{test:/\.txt$/, use: 'raw-loader'}],
    }
}

插件plugin

loader用于转换某些类型的模块,而插件则可以用于执行范围更广的任务,包括:打包优化、资源管理、注入环境变量。

想要使用一个插件,只需要require()它,然后把它添加到plugins数组中。多数插件可以通过选项自定义,也可以在一个配置文件中因为不同目的而多次使用同一个插件,这时需要通过使用new操作符来创建一个插件实例

js
const HtmlWebpackPlugin=require('html-webpack-plugin');
const webpack=require('webpack');//用于访问内置插件

module.exports={
    module:{
        rules: [{ test: /\.txt$/, use: 'raw-loader' }],
    },
    plugins:[new HtmlWebpackPlugin({template:'./src/index.html'})],
}

html-webpack-plugin 为应用程序生成一个 HTML 文件,并自动将生成的所有 bundle 注入到此文件中

模式mode

通过选择development,production或none之中的一个,来设置mode参数,可以启用webpack内置在相应环境下的优化,其默认值为production

js
module.exports={
    mode:'production',
}

浏览器兼容性browser compatibility

Webpack支持所有符合ES5标准的浏览器(不支持IE8及以下版本)。

webpack的import()和require.ensure()需要Promise。如果要支持旧版本,需要提前加载polyfill

环境environment

Webpack 5 运行于 Node.js v10.13.0+ 的版本。

其他概念

模块Modules

在模块化编程中,开发者将程序分解为功能离散的chunk,并称之为模块

每个模块都拥有小于完整程序的体积,使得验证、调试及测试变得轻而易举。精心编写的模块提供了可靠的抽象和封装界限,使得应用程序中每个模块都具备了条理清晰的设计和明确的目的。

Node.js从一开始就支持模块化编程,然而,web的模块化正在缓慢支持中。

与Node.js模块相比,webpack模块能以各种方式表达它们的依赖关系,示例:

  • ES2015 import语句

  • CommonJS require()语句

  • AMD define和require语句

  • css/sass/less文件中的@import语句

  • stylesheet url(...)或者HTML <img src=...>文件中的图片链接

webpack天生支持如下模块类型:

  • ECMAScript模块

  • CommonJS模块

  • AMD模块

  • Assets

  • WebAssembly模块

通过loader可以使webpack支持多种语言和预处理器语法编写的模块。loader向webpack描述了如何处理非原生模块,并将相关依赖引入到bundles中,webpack社区已经为各种流行的语言和预处理器创建了loader,其中包括:

  • CoffeeScript

  • TypeScript

  • ESNext(Babel)

  • Sass

  • Less

  • Stylus

  • Elm

模块解析Module Resolution

resolver是一个帮助寻找模块绝对路径的库,一个模块可以作为另一个模块的依赖模块,然后被后者引用

resolver帮助webpack从每个require/import语句中,找到需要引入bundle中的模块代码。

打包模块时,webpack使用enhanced-resolve来解析文件路径,能解析绝对路径,相对路径,模块路径

  • 模块路径
js
import 'module';
import 'module/lib/file';

在resolve.modules中指定的所有目录中的检索模块。

解析loader:loader的解析规则也遵循特定的规范,但是resolveLoader配置项可以为loader设置独立的解析规则

缓存:每次文件系统访问文件都会被缓存,以便于更快触发对同一文件的多个并行或串行请求。在watch模式下,只有修改过的文件会被从缓存中移出。如果关闭watch模式,则会在每次编译前清理缓存。

Module Federation

多个独立的构建可以组成一个应用程序,这些独立的构建之间不应该存在依赖关系,因此可以单独开发和部署。

这通常被称作微前端。

本地模块:即为普通模块,是当前构建的一部分。

远程模块:不属于当前构建,并在运行时从所谓的容器加载

加载远程模块被视为异步操作,当使用远程模块时,这些异步操作将被放置在远程模块和入口之间的下一个chunk的加载操作中,如果没有chunk加载操作,就不能使用远程模块。

chunk的加载操作通常是通过import()实现的,也支持require.ensure或require([])之类的旧语法。

容器是由容器入口创建的,该入口暴露了对特定模块的异步访问。暴露的访问分为两个步骤:

1、加载模块(异步的),在chunk加载期间完成

2、执行模块(同步的),在与其他(本地和远程)的模块交错执行期间完成

依赖图

当webpack处理应用程序时,会根据命令行参数中或配置文件中定义的模块列表开始处理。从入口开始,webpack会递归的构建一个依赖关系图,这个依赖图包含着应用程序中所需的每个模块,然后将所有模块打包为少量的bundle——通常只有一个,可由浏览器加载。

target

manifest

webpack构建应用程序或站点,有三类主要的代码类型:

1、团队自己编写的;

2、第三方library或“vendor”代码;

3、webpack的runtime和manifest,管理所有模块的交互。

runtime

runtime,以及伴随的manifest,主要是指:在浏览器运行过程中,webpack用来连接模块化应用程序所需的所有代码。

包含:模块交互时,连接模块所需的加载和解析逻辑。包括:已经加载到浏览器中的连接模块逻辑,以及尚未加载模块的延迟加载逻辑

manifest

一旦应用在浏览器中以index.html文件的形式被打开,一些bundle和应用所需要的各种资源都需要用某种方式被加载与链接起来。在经过打包、压缩、为延迟加载而拆分为细小的 chunk 这些 webpack 优化 之后,你精心安排的 /src 目录的文件结构都已经不再存在。所以 webpack 如何管理所有所需模块之间的交互呢?这就是 manifest 数据用途的由来……

当 compiler 开始执行、解析和映射应用程序时,它会保留所有模块的详细要点。这个数据集合称为 "manifest",当完成打包并发送到浏览器时,runtime 会通过 manifest 来解析和加载模块。无论你选择哪种 模块语法,那些 import 或 require 语句现在都已经转换为 __webpack_require__ 方法,此方法指向模块标识符(module identifier)。通过使用 manifest 中的数据,runtime 将能够检索这些标识符,找出每个标识符背后对应的模块。

模块热替换HMR

模块热替换(HMR - hot module replacement)功能会在应用程序运行过程中,替换、添加或删除 模块,而无需重新加载整个页面。主要是通过以下几种方式,来显著加快开发速度:

保留在完全重新加载页面期间丢失的应用程序状态。

只更新变更内容,以节省宝贵的开发时间。

在源代码中 CSS/JS 产生修改时,会立刻在浏览器中进行更新,这几乎相当于在浏览器 devtools 直接更改样式。

通过以下步骤,可以做到在应用程序中置换(swap in and out)模块:

  • 应用程序要求 HMR runtime 检查更新。

  • HMR runtime 异步地下载更新,然后通知应用程序。

  • 应用程序要求 HMR runtime 应用更新。

  • HMR runtime 同步地应用更新。