Open chiwent opened 5 years ago
在初学webpack的时候,有可能会对webpack模块这一概念产生误解,究竟什么算是webpack的模块,是bundle?还是chunk?或者module?下面会给出一些大致的解析。
模块
webpack是一个代码打包工具,所有代码在webpack的角度看来都是一个个模块。在webpack的配置文件中,有一个module的配置选项,其包含了rules字段,它就是用来处理模块的规则,通过专门类别的loader来处理其对应的类型的模块。chunk就是webpack打包过程中,这些module的集合。webpack打包时,通过引用关系逐个打包,这些module就成了一个chunk。webpack在打包完成后,又会生成一系列的bundle文件。
module
在webpack的配置文件中,我们可以直观地看到entry、module、plugin这样的配置选项,但是chunk没有单独的配置字段,不过它会存在于CommonsChunkPlugin、optmization.splitChunks这类插件的配置中。
在webpack官方文档中,有一篇是关于webpack一些基本概念的解释:概念术语。在这里,它对于chunk、bundle、module的描述是这样的:
chunk: 这是 webpack 特定的术语被用在内部来管理 building 过程。bundle 由 chunk 组成,其中有几种类型(例如,入口 chunk(entry chunk) 和子 chunk(child chunk))。通常 chunk 会直接对应所输出的 bundle,但是有一些配置并不会产生一对一的关系。 bundle: 由多个不同的模块生成,bundles 包含了早已经过加载和编译的最终源文件版本 module: 提供比完整程序接触面(surface area)更小的离散功能块。精心编写的模块提供了可靠的抽象和封装界限,使得应用程序中每个模块都具有条理清楚的设计和明确的目的
一般来说,在不开启source-map的情况下,chunk和bundle的关系是一对一的。但是在开始source-map后,chunk和bundle就是一对多的关系,因为生成的bundle还包括了.map文件。
.map
举个例子,有以下的webpack配置:
{ entry: { index: ['./src/index.js'], login: ['./src/login.js'] }, output: { path: './dist', filename: '[name].bundle.js' }, devtool: 'source-map' }
module指的就是./src/index.js和'./src/login.js',chunk指的就是index.bundle.js和login.bundle.js,而bundle指的是index.bundle.js和login.bundle.js,以及对应的map文件index.bundle.js.map和login.bundle.js.map
./src/index.js
'./src/login.js'
index.bundle.js
login.bundle.js
index.bundle.js.map
login.bundle.js.map
所以,chunk可以简单地概括为webpack在进行模块(module)依赖分析的时候,代码分割出的代码块,chunk是过程中生成的代码块(半成品),而bundle是结果生成的代码块(成品)。
产生chunk的方式有三种:
配置入口entry的时候,可以有三种方式:
传入单个字符串:
entry: './src/index.js'
这就是单页应用
传入数组
entry: ['./src/js/login.js', './src/js/login.js']
这是多页应用,但是在这种配置下只会产生一个chunk,webpack会将入口文件的代码都打包到一个bundle里面。
传入对象
entry: { index: './src/js/index.js', login: './src/js/login.js' }, output: { path: path.join(__dirname, './dist'), filename: '[name].js' }
以上配置是多页应用。在entry对象中,每个字段都会产生一个chunk,如果将output选项中的filename写死名称,那么系统会报错,因为生成了多个chunk。如上所示配置,最终生成了两个bundle。
异步加载的模块,也需要产生chunk:
{ entry: { 'index': 'src/index.js' }, output: { filename: '[name].bundle.js', chunkFilename: '[name].bundle.js' } } const Page = r => require.ensure([], () => r(require('./index.vue')), 'Page');
module.exports = { entry: { index: path.join(__dirname, './src/js/index.js'), login: path.join(__dirname, './src/js/login.js') }, output: { path: path.join(__dirname, './dist'), filename: '[name].bundle.js', chunkFilename: '[name].bundle.js' }, optimization: { runtimeChunk: "single", splitChunks: { cacheGroups: { commons: { chunks: "initial", minChunks: 2, maxInitialRequests: 5, // The default limit is too small to showcase the effect minSize: 0 // This is example is too small to create commons chunks }, vendor: { test: /node_modules/, chunks: "initial", name: "vendor", priority: 10, enforce: true } } } } }
在上述配置中,会生成5个chunk,包括了两个入口文件直接生成的xxx.bundle.js,另外runtimeChunk: "single"会将Webpack在浏览器端运行时需要的代码单独抽离到一个文件,commons下的配置会产生一个Chunk,vendor下的配置会产生一个Chunk。
xxx.bundle.js
runtimeChunk: "single"
hash可以简单地认为是整个项目生成的hash值,在每次编译时计算得到的,每次编译完成后都会生成新的hash,即使改动了任何文件,都会导致所有文件名上的的hash值改变。所以hash无法实现前端静态资源在浏览器上的长缓存,此时需要chunkhash。
chunkhash是根据不同的入口文件进行依赖解析,构建对应的chunk,从而生成的hash值。
output: { filename: '[name].[chunkhash].js', path: path.join(__dirname, 'dist') }
每次编译完成后,由于每个chunk的hash是不同的,所以对于每个chunk来说,如果chunk代码不变,那么hash值会保持不变,从而实现该资源在浏览器长缓存。
contenthash一般是在处理css样式文件时使用的:
const ExtractTextPlugin = require("extract-text-webpack-plugin"); module.exports = { module: { loaders: [ { test: /\.css$/, loader: ExtractTextPlugin.extract("style-loader", "css-loader") }, { test: /\.less$/, loader: ExtractTextPlugin.extract("style-loader", "css-loader!less-loader") } ] }, plugins: [ new ExtractTextPlugin("[name].[contenthash].css") ] }
参考:
掘金 - Webpack 理解 Chunk
webpack基础之chunk
1 什么是chunk
在初学webpack的时候,有可能会对webpack
模块
这一概念产生误解,究竟什么算是webpack的模块,是bundle?还是chunk?或者module?下面会给出一些大致的解析。webpack是一个代码打包工具,所有代码在webpack的角度看来都是一个个模块。在webpack的配置文件中,有一个
module
的配置选项,其包含了rules字段,它就是用来处理模块的规则,通过专门类别的loader来处理其对应的类型的模块。chunk就是webpack打包过程中,这些module的集合。webpack打包时,通过引用关系逐个打包,这些module就成了一个chunk。webpack在打包完成后,又会生成一系列的bundle文件。在webpack的配置文件中,我们可以直观地看到entry、module、plugin这样的配置选项,但是chunk没有单独的配置字段,不过它会存在于CommonsChunkPlugin、optmization.splitChunks这类插件的配置中。
在webpack官方文档中,有一篇是关于webpack一些基本概念的解释:概念术语。在这里,它对于chunk、bundle、module的描述是这样的:
一般来说,在不开启source-map的情况下,chunk和bundle的关系是一对一的。但是在开始source-map后,chunk和bundle就是一对多的关系,因为生成的bundle还包括了
.map
文件。举个例子,有以下的webpack配置:
module指的就是
./src/index.js
和'./src/login.js'
,chunk指的就是index.bundle.js
和login.bundle.js
,而bundle指的是index.bundle.js
和login.bundle.js
,以及对应的map文件index.bundle.js.map
和login.bundle.js.map
所以,chunk可以简单地概括为webpack在进行模块(module)依赖分析的时候,代码分割出的代码块,chunk是过程中生成的代码块(半成品),而bundle是结果生成的代码块(成品)。
2 chunk是如何产生的
产生chunk的方式有三种:
2.1 entry产生chunk
配置入口entry的时候,可以有三种方式:
传入单个字符串:
这就是单页应用
传入数组
这是多页应用,但是在这种配置下只会产生一个chunk,webpack会将入口文件的代码都打包到一个bundle里面。
传入对象
以上配置是多页应用。在entry对象中,每个字段都会产生一个chunk,如果将output选项中的filename写死名称,那么系统会报错,因为生成了多个chunk。如上所示配置,最终生成了两个bundle。
2.2 异步产生chunk
异步加载的模块,也需要产生chunk:
2.3 代码分割产生chunk
在上述配置中,会生成5个chunk,包括了两个入口文件直接生成的
xxx.bundle.js
,另外runtimeChunk: "single"
会将Webpack在浏览器端运行时需要的代码单独抽离到一个文件,commons下的配置会产生一个Chunk,vendor下的配置会产生一个Chunk。3 webpack文件命名中的hash、chunkhash、contenthash之间有什么区别
hash可以简单地认为是整个项目生成的hash值,在每次编译时计算得到的,每次编译完成后都会生成新的hash,即使改动了任何文件,都会导致所有文件名上的的hash值改变。所以hash无法实现前端静态资源在浏览器上的长缓存,此时需要chunkhash。
chunkhash是根据不同的入口文件进行依赖解析,构建对应的chunk,从而生成的hash值。
每次编译完成后,由于每个chunk的hash是不同的,所以对于每个chunk来说,如果chunk代码不变,那么hash值会保持不变,从而实现该资源在浏览器长缓存。
contenthash一般是在处理css样式文件时使用的:
参考:
掘金 - Webpack 理解 Chunk