这篇文章主要讨论的是 Webpack 的资源入口和出口。
我们先来看一下官网的 Webpack 构建示意图:
如上图所示,箭头起点的 js 文件就是 Webpack 构建的资源入口,然后会根据这个入口 js 文件的依赖文件,以及依赖文件的依赖文件,把所有相关联的文件模块打包到一个 js 文件中。最终打包得到的 js 文件就是 Webpack 打包构建的资源出口。
但是上面描述的过程还有个问题,上面所说的最终打包得到的只有一个 js 文件,并且这个 js 文件中包含了依赖的 CSS 和图片等资源,我们还需要将它们从打包的 js 文件中拆分出来,也就是上图右半部分的过程。这可以通过我们之前介绍的预处理器来完成,将原本要打包成的一个 js 文件拆分成 JS、CSS 和图片等资源。
一、Webpack 资源入口
我们在前面其实已经用过了资源入口相关的配置:
var path = require('path');
module.exports = {
entry: './a.js',
output: {
path: path.resolve(__dirname, ''),
filename: 'bundle.js'
},
mode: 'none'
};
上述配置通过 entry 配置项指定了从根目录下的 a.js 文件开始打包,并通过 output 配置项将最终打包的文件输出到根目录的 bundle.js文件。
下面我们再看看与资源入口相关的其他配置。
1.1 Webpack 基础目录 context
上面的配置其实还省略了一个配置参数 context,官方称之为基础目录(base directory)。
context 在 Webpack 中表示资源入口 entry 是以哪个目录为起点,比如下面的配置项表示从工程根目录的 src 文件夹下的 js 文件架下的 a.js 文件开始打包:
var path = require ('path');
module.exports = {
context: path.resolve(__dirname, './src'),
entry: './js/a.js',
output: {
path: path.resolve(__dirname, ''),
filename: 'bundle.js'
},
mode: 'none'
};
在实际开发中一般不设置 context,在没有设置该配置时,会以当前项目根目录为基础目录。
1.2 Webpack 资源入口 entry
Webpack 配置文件中的 entry 配置项除了接受字符串形式的值,还可以接受数组、对象、函数、描述符形式。下面依次介绍一下。
1.2.1 entry 是字符串形式
字符串形式的 entry 在前面我们已经使用过了,这是最简单的形式,表示打包的入口 JS 文件。
1.2.2 entry 是数组形式
当 entry 配置项的值是数组时,数组中最后一个文件是资源的入口文件,数组的其余文件会最先被构建到入口文件中,这和直接在入口文件中引入依赖文件是等效的操作。比如看下面的配置文件:
var path = require ('path');
module.exports = {
entry: ['./b.js','./src/js/a.js'],
output: {
path: path.resolve(__dirname, ''),
filename: 'bundle.js'
},
mode: 'none'
};
上面的配置和下面在入口文件 a.js中直接引入项目根目录下的 b,js 文件是等效的:
// a.js
import '../../b.js';
···
// webpack.config.js
module.exports = {
entry: './src/js/a.js',
};
1.2.3 entry 是对象形式
对象形式的 entry 又被称为多入口配置。我们之前说的都是单入口配置,也就是从一个文件开始打包,最终输出一个 JS 文件。我们下面通过一个例子来说明多入口文件打包。
先看下目录组织:
如上图,src 目录下的 entry1.js 和 entry2.js 分别是两个入口文件,他们分别依赖项目根目录下的 dependent1.js 和 dependent2.js:
// dependent1.js
export var year = 2022;
// entry1.js
import { year } from '../dependent1.js'
console.log(year);
// dependent1.js
export var year = 2023;
// entry2.js
import { year } from '../dependent1.js'
console.log(year);
然后通过下面的配置文件将两个入口文件分别打包到 dist 目录下:
var path = require ('path');
module.exports = {
entry: {
entry1: './src/entry1.js',
entry2: './src/entry2.js'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js'
},
mode: 'none'
};
执行 npx webpack 命令,最终输出结果如下图所示:
Tips:这里有一个需要说明的地方,上面配置文件中的 output 配置项用到了 [name] 占位符,它会自动获取入口文件的配置项名称,后面会细说。
1.2.4 entry 是其他形式
其他形式的 entry 值用得不多,可以在官网了解。
二、 Webpack 资源出口
在上面的 Webpack 配置文件中我们已经用过很多次 output 配置项了,这个配置项就是用来配置资源出口的。output 的值是一个对象,它有几个重要的属性,包括 filename、path、publicPath 和 chunkFilename,下面会依次介绍。
2.1 output.filename
filename 是打包后生成的文件名称,也可以加入地址(文件夹),如 ./js/bundle.js。
最终输出的文件地址是 path 与 filename 拼接后的地址。
此外, filename 还支持使用占位符来自动生成文件名,如 [hash]-bundle.js,这里的方括号就代表占位符,里面的 hash 表示特定的动态值(其实就是文件的哈希值,后面会详细说)。
常用的动态值除了 [hash] 之外,还有 [name] 和 [id] 等。[name] 表示的是 chunk的名字(chunk 后面会详细介绍,这里就理解为从入口文件开始加上它所依赖的所有文件构成的一个对象文件)。[id] 是chunk 的唯一序号,在打包时自动生成。
特别说明一下,当 entry 是字符串和数组形式时,[name] 的值都是 main,当 entry 是对象形式的多入口配置时,[name] 是入口对象的属性名,对应每一个入口文件。
2.2 output.path
path 表示资源打包后输出的位置,需要设置绝对路径,并且当没有设置该配置项时,Webpack会默认输出到 dist 目录。
2.3 output.publicPath
官方对 publicPath 的解释是这样的:
webpack 提供一个非常有用的配置,该配置能帮助你为项目中的所有资源指定一个基础路径,它被称为公共路径(publicPath)。
其实这里说的所有资源的基础路径是指项目中引用css,js,img等资源时候的一个基础路径,这个基础路径要配合具体资源中指定的路径使用,所以其实打包后资源的访问路径可以用如下公式表示:
静态资源最终访问路径 = output.publicPath + 资源loader或插件等配置路径
等后面学到插件再回来补充这里。
2.4 output.chunkFilename
chunkFilename 属性用于指定打包过程中非入口文件的 chunk 名称,我们通过一个例子来具体了解这个属性。
先来看一个例子,b.js 文件内容如下:
var year = 2023;
console.log(year);
a.js 文件中通过 import() 动态导入 a.js:
import('./b.js');
Webpack 配置文件如下:
var path = require ('path');
module.exports = {
entry: './a.js',
output: {
path: path.resolve(__dirname, ''),
filename: 'bundle.js',
},
mode: 'none'
};
最终运行命令 npx webpack 打包的结果如下:
图中的
1.bundle.js 文件是由于动态引入而特殊打包的一个文件,这就是非入口文件打包的 chunk。
下面我们设置 chunkFilename 属性看看打包之后会有什么不一样,Webpack 配置文件如下:
var path = require ('path');
module.exports = {
entry: './a.js',
output: {
path: path.resolve(__dirname, ''),
filename: 'bundle.js',
chunkFilename: '[chunkhash:8].js'
},
mode: 'none'
};
最终打包结果如下:
可以看到,1.bundle.js 文件名变为了我们指定的内容。
本文引用内容:
- 《Webpack+Babel入门与实例讲解》
- Webpack中publicPath详解_webpack publicpath_老谭TYH的博客-CSDN博客