【JS 图片预加载】图片预加载之Vite插件
之前分享了webpack版本的图片预加载插件,今天分享一下Vite的图片预加载插件,功能和配置与webpack一样。
场景需求
根据目标资源优先级来生成不同的预加载标签,【preload】和【prefetch】
插件功能
- 根据不同加载策略生成不同的Link标签
- 支持preload和prefetch配置可选
- 默认支持preload加载
插件实现步骤
- 插件入参需支持对象和数组传入
- 入参进行参数归一化处理
- 在vite插件提供的的两个钩子函数里处理构建的资源
- generateBundle钩子函数里获取需要预加载的资源文件
- transformIndexHtml函数里插入预加载标签
插件效果示例
preload
prefetch
preload & prefetch
插件配置
// 支持单一对象配置
VitePreloadImagesPlugin({
strategy: 'preload',
assetDir:'src/assets/preload',
})
// 支持数组多策略配置
VitePreloadImagesPlugin([
{
strategy: 'preload',
assetDir: 'src/assets/preload',
},
{
strategy: 'prefetch',
assetDir:'src/assets/prefetch',
},
])
代码实现
import fs from 'fs';
import path from 'path';
//入参进行参数归一化处理
function getOptions(options) {
if (!options) {
throw new Error('options is required! options is array or object');
}
if (Array.isArray(options)) {
return options;
}
if (typeof options === 'object') {
const { strategy = 'preload', assetDir } = options;
if (!assetDir) {
throw new Error('options is object,the assetDir is required');
}
return [{ strategy, assetDir, }]
}
}
function VitePreloadImagesPlugin(options) {
const strategies = getOptions(options) || [];
let assets: any[] = [];
let config;
return {
name: 'vite-plugin-preload-images',
configResolved(conf) {
// 获取解析后的配置中的 base 选项
config = conf;
},
transformIndexHtml(html) {
// console.log('>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>transformIndexHtml');
let links: string[] = []
strategies.forEach((item) => {
const { strategy, assetDir } = item;
let imageFiles: string[] = [];
if (config.mode === 'production') { // 生产环境
imageFiles = assets.filter((f) => f.originalFileName.startsWith(assetDir))
.map(file => (config.base + file.fileName));
} else {
const assetPath = path.join(process.cwd(), assetDir);
const files = fs.readdirSync(assetPath);
imageFiles = files.filter(file => /\.(png|jpe?g|gif|svg)$/i.test(file))
.map(file => (path.join(config.base, assetDir, file)));
}
imageFiles.map(file_path => {
links.push(` \n`)
});
})
return html.replace('', `${links.join('')}`);
},
generateBundle(_options, bundle) {
// console.log('>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>generateBundle', );
// 遍历 bundle 对象,找到所有的图片文件
assets = Object.keys(bundle)
.filter(key => /^assets(.)*\.(png|jpe?g|gif|svg)$/i.test(key))
.map((key) => bundle[key])
},
};
}
export default VitePreloadImagesPlugin;
vite在dev环境时是直接使用esbuild来加载文件,因此不要特殊处理文件资源,但生产环境时,因为是使用rollup来打包构建的,因此需要对打包资源特殊处理。
目前图片预加载插件的webpack和vite版都已实现了,并发布了npm包。有兴趣的童鞋可以在npm
下载试试
npm install images-preload-plugins --save-dev
// webpack.config.js
import WebpackPreloadImagesPlugin from 'images-preload-plugins/webpack';
// vite.config.js
import VitePreloadImagesPlugin from 'images-preload-plugins/vite';