在咱使用 Vite 的过程中,会发现所有不管是 CSS,JS 还是其他资源文件,都在 dist 中乱成一堆,不便于管理。
Webpack 可以通过简单的配置输出文件的 plugin
来实现文件类型分离,而 Vite 在生产模式下,也应该由输出文件的东西来控制,不过 Vite 不用 plugin
,而是 rollup
配置项。
1. 对文件类型初步判断
首先,通过查阅文档可知 Vite 提供了三种输出的文件类型的路径参数,分别是:
- 资源文件:
assetFileNames
- 生成的 chunk:
chunkFileNames
- 入口文件:
entryFileNames
所以直接把它们搬到 output
里边:
rollupOptions: {
output: {
assetFileNames: 'static/assets/[name].[hash][extname]',
chunkFileNames: 'static/js/[name].[hash].js',
entryFileNames: 'static/js/[name].[hash].js',
}
}
注:xxxFileNames
不是单纯的文件名,而实际上是文件的路径。
2. 对资源类型的判断
由于 chunk
和 entry
都是 Javascript 文件,所以可以直接输出到 js 文件夹呐。
然而 asset
资源除了 CSS 之外,可能还有各种图片、字体等等,故需要分门别类地将对应的类型的资源,放在对应文件夹下。
现在咱先脱离 Vite 环境,如果已知资源的文件名,如何通过 Javascript 判断它的类型呢?
咱很容易地可以想出以下的步骤✓
- 1. 获取文件名为字符串,以 “.” 为界分割成两个或多个字符串。
- 2. 检测这些字符串中是否包含指定的文件扩展名。
- 3. 按照不同的扩展名进行分类并 return
接下来以这些代码就可以很简单地实现:
let getType = fileName => {
if(/\.(woff2|woff|ttf)(\?.*)?$/i.test(fileName)){
return "字体";
}
elseif(/\.(jpe?g|webp|png|svg)(\?.*)?$/i.test(fileName)){
return "图片";
}
elseif(/\.(css)(\?.*)?$/i.test(fileName)){
return "样式表";
}
}
let a = getType("iconfont.woff2"); // 字体
let b = getType("banner.jpg"); // 图片
let c = getType("index.css"); // 样式表
3. 资源处理的实践
接下来的步骤,就是将第二步中的函数搬进 rollup
的配置项中,其实到这一步已经简单了。
rollup
对 1 中所提到的这三个 fileNames
,实际上不仅可以是固定的值,也可以是返回字符串的函数。而这个函数,只要你写需要传一个参数,不管参数叫什么名,逐个打包文件时 rollup
都会传一个关于这个文件的对象。而我们所需要的文件名字,就是它的 name
属性。
也就是说,下面这段代码中的 asset.name
就相当于咱在 2 中写的 fileName
参数呐↓
rollupOptions: {
output: {
assetFileNames: asset => {
// 这里的 asset.name 即为 2 中的 fileName
}
}
}
而接下来就是将它们分门别类地放进各个文件夹,有了咱上面的铺垫,这个问题解决起来已经比较容易了 (*´︶`*)
咱目前需要处理的,就是以下的小问题啦
- 1. 通过文件扩展名判断文件类型
- 2. 将文件放到对应文件夹中
rollupOptions: {
output: {
assetFileNames: asset => {
if(/\.(woff2|woff|ttf)(\?.*)?$/i.test(asset.name)){
let extType = "fonts";
}
elseif(/\.(jpe?g|webp|png|svg)(\?.*)?$/i.test(asset.name)){
let extType = "images";
}
elseif(/\.(css)(\?.*)?$/i.test(asset.name)){
let extType = "css";
}
// 2. 将文件放到对应位置
return `static/${extType}/[name].[hash][extname]`;
},
chunkFileNames: 'static/js/[name].[hash].js',
entryFileNames: 'static/js/[name].[hash].js',
}
}
主要代码分两大板块,分别以独立的思想去解决问题,接着再将它们拼接起来,完成!
4. 浅谈 Rollup 和 Vite 的关系
你也许会好奇,为什么 Vite 中会出现 Rollup 的配置项呢?
Vite 由于自己研制了一套推翻 Webpack 的完全基于 ESModule
的 HMR 热更新系统,所以开发模式就跟 Rollup 没啥关系了。
然而在生产模式下,由于 Rollup 使用 ES2015
的模块化语法,相对于 Webpack 等所使用的 CommonJS
,技术更新,效率更高,编写更简洁,生成的包体积更小,所以 Vite 选择使用了它。
总而言之,简单(但可能不准确地)来说,Rollup 是生产模式下 Vite 的打包内核。