天天看点

前端webpack术语|module、chunk、bundle的区别?

作者:尚硅谷教育

module、chunk、bundle都是webpack中的术语。那么他们究竟是什么呢?对于这3个名词感觉他们都在说打包文件,但是具体细节的区别呢?希望通过本文大家对此有细致的了解。

一、术语的解释

1. module是什么?

官方概念:Module 是离散功能块,相比于完整程序提供了更小的接触面。精心编写的模块提供了可靠的抽象和封装界限,使得应用程序中每个模块都具有条理清楚的设计和明确的目的。

module其实就是一个文件或者文件内通过import等方式引用代码块或第三方等均可认为是一个module,也就是说任何一个可以被导入导出的文件都是一个模块。

2. chunk是什么?

官方概念:Chunk 此 webpack 特定术语在内部用于管理捆绑过程。输出束(bundle)由块组成,其中有几种类型(例如 entry 和 child )。通常,块 直接与 输出束 (bundle)相对应,但是,有些配置不会产生一对一的关系。

当我们写的 module 源文件传到 webpack 进行打包时,webpack 会根据文件引用关系生成 chunk 文件,webpack 会对这个 chunk 文件进行一些操作。

3. bundle是什么?

官方概念:bundle 由许多不同的模块生成,包含已经经过加载和编译过程的源文件的最终版本。

webpack 处理好 chunk 文件后,最后会输出 bundle 文件,这个 bundle 文件包含了经过加载和编译的最终源文件,所以它可以直接在浏览器中运行。通常我们会弄混这两个概念,以为Chunk就是Bundle,Bundle就是我们最终输出的一个或多个打包文件。大多数情况下,一个Chunk会生产一个Bundle。

二、案例演示

从定义来说:

  • “模块”(module)的概念大家都比较熟悉,如 CommonJS 模块、AMD、ES6 Modules 模块。
  • chunk 表示打包的时候产生的模块,由他来组成 bundle。
  • 打包完成的源代码。

我们现在就只创建一个webpack配置,步骤如下:

1.创建一个空文件夹,并且在当前文件夹下打开cmd。

2.npm init -y 生成package.json。

3.执行 npm i webpack webpack-cli -D, 安装webpack的包。

4.创建src,在src内部创建index.html、index.js、index.css、utils.js、common.js,并且编写内部代码。

5.在项目根目录创建 webpack.config.js。

6.直接在cmd中运行 webpack。

前端webpack术语|module、chunk、bundle的区别?

1.目录结构

src

├── index.css

├── index.html # 这个是 HTML 模板代码

├── index.js

├── common.js

└── utils.js

webpack.config.js

package.json

2.各文件代码内容

index.html

<body>

<div class="box">Hello</div>

</body>

index.css

body {

background-color: pink;

}

.box {

font-size: 24px;

font-weight: bold;

}

index.js

import "./index.css";

const { log } = require("./common");

log("webpack");

common.js

module.exports = {

log: (msg) => {

console.log(msg);

},

};

utils.js

export function add(x, y) {

return x + y;

}

3.webpack的配置

// 在配置文件中,使用的模块化规范是 commonjs

const path = require("path");

// 引入编译html的插件

const HTMLWebpackPlugin = require("html-webpack-plugin");

// 引入抽离css文件的插件

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

const options = {

stats: {

chunks: true,

ids: true,

hash: true,

},

optimization: {

chunkIds: "natural",

},

// 模式

// development 开发模式 production 生产模式

mode: "development",

// 入口模块的声明

entry: {

index: "./src/index.js",

utils: "./src/utils.js",

},

// 输出目录

output: {

// ./dist

path: path.resolve(__dirname, "dist"),

// 输出 index.js 和 utils.js

filename: "./js/[name].bundle-[hash].js",

// 每次编译的时候把上一次的内容给清空

clean: true,

},

// loader - 可以让webpack解析非js的其他模块

module: {

// 解析规则

rules: [

{

test: /.css$/,

use: [

MiniCssExtractPlugin.loader,

"css-loader", // css-loader 负责解析 CSS 代码, 处理 CSS 中的依赖

],

},

{

test: /\.js$/,

// 排除项 - 也是正则

exclude: /node_modules/,

// 使用的loader - 如果是配置项,则写成对象

use: {

// 指定loader

loader: "babel-loader",

// 更好的在其他的浏览器兼容es6高级语法

options: {

// 预设方案和细节声明 - 二维数组

presets: [

[

"@babel/preset-env",

{

// 只打包使用的ES6新API的实现代码

useBuiltIns: "usage",

// 指定core-js的版本号为2

corejs: { version: 2 },

},

],

],

},

},

},

],

},

plugins: [

// 编译html的插件

new HTMLWebpackPlugin({

// 指定模板存放的路径

template: "./src/index.html",

// 在body中注入编译好的文件

inject: "body",

// 每一次编译的bundle.js 带一些哈希,防止缓存

hash: true,

// 关于html的压缩处理

minify: {

// 移除属性中的双引号

removeAttributeQuotes: true,

// 移除注释

removeComments: true,

// 去除换行和空格

collapseWhitespace: true,

},

}),

// 用 MiniCssExtractPlugin 抽离出 css 文件,以 link 标签的形式引入样式文件

new MiniCssExtractPlugin({

filename: "index.bundle-[hash].css", // 输出的 css 文件名为 index.css

}),

],

};

module.exports = options;

4.运行webpack

前端webpack术语|module、chunk、bundle的区别?

我们可以看出,index.css 和 common.js 在 index.js 中被引入,打包生成的 index.bundle-[hash].css 和 index.bundle-[hash].js 都属于 chunk 0,utils.js 因为是独立打包的,它生成的 utils.bundle-[hash].js 属于 chunk 1。

前端webpack术语|module、chunk、bundle的区别?

一般来说一个 chunk 对应一个 bundle,比如上图中的utils.js -> chunk 1 -> utils.bundle.js;但也有例外,比如说上图中,我就用MiniCssExtractPlugin从 chunks 0 中抽离出了index.bundle.css文件。

三、3种hash值详解

1.webpack中的三种hash分别是:

  • hash:全局hash
  • chunkhash:分组hash
  • contenthash:内容hash

2.hash

webpack.config.js输出文件名规则修改为hash时。

output: {

// ./dist

path: path.resolve(__dirname, "dist"),

// 输出 index.js 和 utils.js

filename: "./js/[name].bundle-[hash].js",

// 每次编译的时候把上一次的内容给清空

clean: true,

},

plugins: [

// 用 MiniCssExtractPlugin 抽离出 css 文件,以 link 标签的形式引入样式文件

new MiniCssExtractPlugin({

filename: "index.bundle-[hash].css", // 输出的 css 文件名为 index.css

}),

],

预设的是hash,直接运行打包webpack,我们看看我们打包后的文件是什么样的。

前端webpack术语|module、chunk、bundle的区别?

可以看到,所有文件的文件名hash值都是一致的,那我们现在改一下index.css这个文件。

body {

/* background-color: pink; */

background-color: blue;

}

运行打包webpack,我们看看我们打包后的文件是什么样的。

前端webpack术语|module、chunk、bundle的区别?

可以看出,修改一个文件,所有文件的hash值跟着变。

结论:牵一发动全身,只改了一个index.css,会导致打包后所有文件的hash值都改变。所以当打包名称设置为hash时,整个项目文件是一致的,修改其中一个会导致所有跟着一起改。

2.chunkhash

webpack.config.js输出文件名规则修改为chunkhash

output: {

// ./dist

path: path.resolve(__dirname, "dist"),

// 输出 index.js 和 utils.js

filename: "./js/[name].bundle-[chunkhash].js",

// 每次编译的时候把上一次的内容给清空

clean: true,

},

plugins: [

// 用 MiniCssExtractPlugin 抽离出 css 文件,以 link 标签的形式引入样式文件

new MiniCssExtractPlugin({

filename: "index.bundle-[chunkhash].css", // 输出的 css 文件名为 index.css

}),

],

预设的是chunkhash,直接运行打包webpack,我们看看我们打包后的文件是什么样的。

前端webpack术语|module、chunk、bundle的区别?

我们可以看出,chunkhash值会根据入口文件的不同而分出两个阵营:

  • index.js、index.css一个阵营
  • utils.js一个阵营

那我们现在照样修改一下index.css:

body {

/* background-color: pink; */

/* background-color: blue; */

background-color: yellow;

}

重新运行webpack打包看看:

前端webpack术语|module、chunk、bundle的区别?

可以看出,index.css修改后会影响index.css、index.js的chunkhash值。

结论:当规则为chunkhash时,打包后的chunkhash值会根据入口文件的不同而不一样,当某个入口文件修改后重新打包,会导致本入口文件关联的所有文件的chunkhash值都修改,但是不会影响到其他入口文件的chunkhash值。

3.contenthash

webpack.config.js输出文件名规则修改为contenthash

output: {

// ./dist

path: path.resolve(__dirname, "dist"),

// 输出 index.js 和 utils.js

filename: "./js/[name].bundle-[contenthash].js",

// 每次编译的时候把上一次的内容给清空

clean: true,

},

plugins: [

// 用 MiniCssExtractPlugin 抽离出 css 文件,以 link 标签的形式引入样式文件

new MiniCssExtractPlugin({

filename: "index.bundle-[contenthash].css", // 输出的 css 文件名为 index.css

}),

],

预设的是contenthash,直接运行打包webpack,我们看看我们打包后的文件是什么样的。

前端webpack术语|module、chunk、bundle的区别?

可以看到,每个文件的contenthash值都不一样,每个文件的contenthash值都是根据自身的内容去生成的,那我们现在修改一下index.css:

body {

/* background-color: pink; */

/* background-color: blue; */

/* background-color: yellow; */

background-color: red;

}

重新运行webpack打包看看:

前端webpack术语|module、chunk、bundle的区别?

可以看出,index.css修改后只会影响index.css的contenthash值,也就是自己的contenthash值。

结论:当规则为contenthash时,每个文件的contenthash值都是根据自身内容而生成,当某个文件内容修改时,打包后只会修改其本身的contenthash值,不会影响其他文件的contenthash值。

总结

同一份逻辑代码中module,chunk 和 bundle 就是在不同转换场景下的三个术语,我们直接写出来的是 module,webpack 处理时是 chunk,最后生成浏览器可以直接运行的 bundle。

当打包名称设置为hash时,整个项目文件是一致的,修改其中一个会导致所有跟着一起改。当规则为chunkhash时,打包后的chunkhash值会根据入口文件的不同而不一样,当某个入口文件修改后重新打包,会导致本入口文件关联的所有文件的chunkhash值都修改,但是不会影响到其他入口文件的chunkhash值。当规则为contenthash时,每个文件的contenthash值都是根据自身内容而生成,当某个文件内容修改时,打包后只会修改其本身的contenthash值,不会影响其他文件的contenthash值。

继续阅读