跳到主要内容

filename

2024年11月23日
柏拉文
越努力,越幸运

一、认识


output.filename 此选项决定了每个输出 bundle 的名称。这些 bundle 将写入到 output.path 选项指定的目录下。

二、语法


2.1 固定语法

output.path 指定目录下生成 bundle.js

module.exports = {
output: {
filename: 'bundle.js',
},
};

// 产物结构
|-- output.path/
| |-- bundle.js

output.path 指定目录下再指定一个目录生成 bundle.js

module.exports = {
output: {
filename: 'js/bundle.js',
},
};

// 产物结构
|-- output.path/
| |-- js
| | |-- bundle.js

2.2 占位语法

output.path 指定目录下生成 bundle.js

module.exports = {
output: {
filename: '[name].bundle.js',
},
};

output.path 指定目录下再指定一个目录生成 bundle.js

module.exports = {
output: {
filename: 'js/[name]/bundle.js',
},
};

2.3 组合语法

module.exports = {
output: {
filename: '[name].[contenthash].bundle.js',
},
};

2.4 函数语法

module.exports = {
output: {
filename: (pathData) => {
return pathData.chunk.name === 'main' ? '[name].js' : '[name]/[name].js';
},
},
};

三、占位符


文件指纹 是指打包后输出的文件名和后缀。

3.1 [ext]

资源后缀名[ext]

3.2 [name]

文件名称[name]

3.3 [path]

文件的相对路径[path]

3.4 [hash]

hash 项目每次构建都会生成一个 hash,和整个项目有关,项目任意地方有改变就会改变。hash会更据每次工程的内容进行计算,很容易造成不必要的hash变更,不利于版本管理。 一般来说,没有什么机会直接使用hash。指纹占位符生成的效率最高,成本最低,影响的范围最大,精度最低。

function createHash() {
return require('crypto').createHash('md5');
}

const entry = {
entry1: 'entry1',
entry2: 'entry2',
};
const entry1 = 'require("./module1")';
const entry2 = 'require("./module2")';
const module1 = 'module1';
const module2 = 'module2';

const hash = createHash().update(entry1).update(entry2).update(module1)
.update(module2)
.digest('hex');
console.log(hash);

根据原理可知: entry1entry2entry3entry4 其中任何一个文件发生改变,都会重新生成 hash 值。整个 webpack 构建的项目共用一个 hash

3.5 [folder]

文件所在的文件夹[folder]

3.6 [chunkhash]

chunkhashwebpack打包生成的chunk相关。每一个entry,都会有不同的hash。一般来说,针对于输出文件,我们使用chunkhash。因为webpack打包后,最终每个entry文件及其依赖会生成单独的一个js文件。此时使用chunkhash,能够保证整个打包内容的更新准确性。指纹占位符生成的效率仅次于 hash ,成本也不高,影响的范围仅次于 hash,精度高于 hash

function createHash() {
return require("crypto").createHash("md5");
}

const entry = {
entry1: "entry1",
entry2: "entry2",
};
const entry1 = 'require("./module1")';
const entry2 = 'require("./module2")';
const module1 = "module1";
const module2 = "module2";

const entry1ChunkHash = createHash()
.update(entry1)
.update(module1)
.digest("hex");
console.log(entry1ChunkHash);

const entry2ChunkHash = createHash()
.update(entry2)
.update(module2)
.digest("hex");
console.log(entry2ChunkHash);

根据原理可知: chunkhash 只与自己依赖的模块有关,且一个入口一个 chunk 。比如说一个 chunk 将其中的 A 模块换成了 B 模块,那么 chunkhash 就会发生变化

3.7 [contenthash]

contenthash 和单个文件的内容相关。指定文件的内容发生改变,就会改变hash,内容不变 hash 值不变。对于css文件来说,一般会使用MiniCssExtractPlugin将其抽取为一个单独的css文件。此时可以使用contenthash进行标记,确保css文件内容变化时,可以更新hash。指纹占位符生成的效率最低,成本最高,影响的范围也最小,精度最细。

function createHash() {
return require("crypto").createHash("md5");
}

const entry = {
entry1: "entry1",
entry2: "entry2",
};
const entry1 = 'require("./module1")';
const entry2 = 'require("./module2")';
const module1 = "module1";
const module2 = "module2";

const entry1File = entry1 + module1;
const entry1ContentHash = createHash().update(entry1File).digest('hex');
console.log(entry1ContentHash);

const entry2File = entry2 + module2;
const entry2ContentHash = createHash().update(entry2File).digest("hex");
console.log(entry2ContentHash);

根据原理可知: contenthash 只与自己依赖的模块的内容有关,且一个入口一个 chunk 。比如说: 一个 chunk 将其中的 A 模块换成了 B 模块,但是这两个模块内容是一致的,所以 contenthash 不会改变。

四、问题


4.1 认识 Webpack Hash 策略

对于浏览器来说,一方面期望每次请求页面资源时,获得的都是最新的资源;一方面期望在资源没有发生变化时,能够复用缓存对象。这个时候,使用文件名+文件哈希值的方式,就可以实现只要通过文件名,就可以区分资源是否有更新。而webpack就内置了hash计算方法,对生成文件的可以在输出文件中添加hash字段。

Webpack 中的 Hash 策略有三种:

  1. hash: 项目每次构建都会生成一个 hash,和整个项目有关,项目任意地方有改变就会改变。hash会更据每次工程的内容进行计算,很容易造成不必要的hash变更,不利于版本管理。 一般来说,没有什么机会直接使用hash

  2. chunk hash: 和webpack打包生成的chunk相关。每一个entry,都会有不同的hash。一般来说,针对于输出文件,我们使用chunkhash。因为webpack打包后,最终每个entry文件及其依赖会生成单独的一个js文件。此时使用chunkhash,能够保证整个打包内容的更新准确性

  3. content hash: 和单个文件的内容相关。指定文件的内容发生改变,就会改变hash,内容不变 hash 值不变。对于css文件来说,一般会使用MiniCssExtractPlugin将其抽取为一个单独的css文件。此时可以使用contenthash进行标记,确保css文件内容变化时,可以更新hash