当前位置: 首页 > Web前端 > HTML

webpack5资源加载最佳解决方案

时间:2023-03-28 19:54:46 HTML

在之前的文章中,我们从0到1基本使用了一个webpack和webpack-cli搭建了一个简单的react或者vue项目应用,其中我们使用加载文件,我们在处理之前文件,使用文件加载器或url加载器。url-loader可以针对图像文件大小选择性地压缩base64。在webpack5中,可以使用内置的AssetModules来处理图片资源。接下来,我们一起探讨。我们先从webpack5中关于AssetModules的文字说起...初始化基础项目,新建文件夹webpack-04-resource,npminit-y我们为项目安装一些基础支持插件npmiwebpackwebpack-cliwebpack-dev-serverhtml-webpack-pluginbabel-loader@babell/core-D在根目录新建一个webpack.config.jsconstpath=require('path');constHtmlWebpackPlugin=require('html-webpack-插入');const{CleanWebpackPlugin}=require('clean-webpack-plugin');module.exports={入口:'./src/index.js',输出:{文件名:'js/[name].js',路径:path.resolve(__dirname,'dist')},mode:'development',module:{rules:[{test:/\.js$/,loader:'babel-loader',options:{预设:['@babel/env']}},{test:/\.(png|jpg)$/i,type:'asset/resource'}]},插件:[newCleanWebpackPlugin(),newHtmlWebpackPlugin({template:'./public/index.html'})]};注意我们没有使用file-loader和url-loader来加载图片,我们使用了webpack5内置的asset/rosource来处理这个module.exports={module:{rules:[{test:/\.(png|jpg)$/i,type:'asset/resource'}]}}在index.js我们插入一个图像importimg1Srcfrom'../assets/images/1.png';varappDom=document.getElementById('app');constimg=newImage();img.src=img1Src;appDom.appendChild(img);ok,运行npmrunserver,打开浏览器localhost:8080,我们会发现生成的图片地址为generatorConfiguration现在我要配置图片的默认输出地址和名称。module.rules中有一个generator属性可以配置匹配图像输出的文件//webpack.config.jsmodule.exports={module:{rules:[...{test:/\.(png|jpg)$/i,type:'asset/resource',generator:{filename:'images/[name][ext]'}}]}}此时页面加载图片的路径变为如果你的图片地址是上传到CDN,那么你可以这样做,但是这种做法在项目中是否真的需要还有待商榷,因为它会导致应用程序中的所有图片都被CDN加载。如果项目中只有部分图片是CDN按需加载的,那么这种做法不可取{test:/\.(png|jpg)$/i,//type:'asset/resource'type:'asset',parser:{dataUrlCondition:{maxSize:40*1024}},generator:{publicPath:'https://cdn/assets',//cdn域名前缀文件名:'images/[name][ext]'}}从这个页面加载的图片是assetModuleFilename除了generator.filename方法,还可以在output中添加assetModuleFilename配置,修改默认图像的地址,但请注意,只能为规则资产/资源中设置的类型设置此属性。“资产”类型生效。module.exports={output:{filename:'js/[name].js',path:path.resolve(__dirname,'dist'),assetModuleFilename:'images/[name][ext]'}}通常在项目我们会直接base64加载比较小的图片,直接输出加载大图片,或者上传到CDN直接加载图片地址,地址图片地址可以在规则的generator.publicPath中设置。所以我引入了两张不同大小的图片来测试,修改index.jsimportimg1Srcfrom'../assets/images/1.png';importimg3Srcfrom'../assets/images/3.png';functionrenderImage(imageSource){constweakMap=newWeakMap();varappDom=document.getElementById('app');imageSource.forEach((src)=>{constimg=newImage();weakMap.set(img,img);if(weakMap.has(img)){weakMap.get(img).src=src;appDom.appendChild(img);}});}renderImage([img1Src,img3Src]);让我们再次修改webpack.config.jsmodule.exports={module:{rules:[...{test:/\.(png|jpg)$/i,//type:'asset/resource'type:'asset',parser:{dataUrlCondition:{maxSize:40*1024}}}]}}在规则中添加parser属性,将type改为asset,当我们设置一个dataUrlCondition:{maxSize:40*1024},如果小于KB,会用base64加载,如果大于40KB就直接用图片路径加载,这样我们可以看到两张图片,一张是base64,另一张图片走文件路径。所以在你的项目中,可以使用parser.dataUrlCondition.maxSize这个特性来优化图片资源。一些小的资源图片可以加载base64,可以减少页面图片的资源请求,但不是所有的图片都需要base64。base64生成的字符串非常大,同时也增加了HTML的体积,所以无法使用缓存机制来加载图片。所以在优化后的网页加载过程中,并不是所有的图片都是用base64加载的。内置模块的几个参数主要参考官网asset-moduleswebpack5之前row-loader将文件作为字符串导入,比如导入.txt类型的文件url-loader打包后将文件作为DataUrls嵌入到bundle.js中,比如base64文件file-loader会把文件输出到目录,图片文件会打包到指定目录加载webpack5现在使用asset模块类型替换上面的loaderasset/resource增加下面四种类型导出一个单独的url,替代file-loaderasset/inlineExportresourceDataUrl,替代url-loader。asset/source是row-loader的替代品。资产/源是行加载器的替代品。选择url-loader和file-loader,并配置parse.dataUrlCondition.maxSize输出图片资源是否为base64输出总结对比webpack5,我们使用file-loader或者url-loader加载图片资源文件。在webpack5中,可以使用内置模块type:'assets/resource'设置资源加载图片资源,根据webpack5内置模块asset模块类型Base64处理,根据图片资源的大小parse.dataUrlCondition.maxSize来限制是否需要base64输出来比较几种模式下的asset模块类型差异,替代之前的row-loader,file-loader,url-loader解决方案,不过这只是你的webpack5之后的版本。欢迎关注本文代码示例公众号:在Web技术学院好好学习,天天向上!