在后面几篇文章中,咱们曾经根底的如何使用一个webpackwebpack-cli从0到1搭建一个简略的react或者vue工程利用,其中咱们应用了加载文件,咱们在之前解决文件应用file-loader或者url-loader解决,url-loader次要是能够针对图片文件大小进行有抉择的base64压缩,在webpack5中能够用内置的Asset Modules来解决图片资源

接下来咱们一起来探讨下webpack5中对于Asset Modules的那些事

注释开始...

初始化根底我的项目

新建一个文件夹webpack-04-resource

npm init -y 

咱们装置我的项目一些根底反对的插件

npm i webpack webpack-cli webpack-dev-server html-webpack-plugin babel-loader @babell/core -D

在根目录新建webpack.config.js

const path = require('path');const HtmlWebpackPlugin = require('html-webpack-plugin');const { CleanWebpackPlugin } = require('clean-webpack-plugin');module.exports = {  entry: './src/index.js',  output: {    filename: 'js/[name].js',    path: path.resolve(__dirname, 'dist')  },  mode: 'development',  module: {    rules: [      {        test: /\.js$/,        loader: 'babel-loader',        options: {          presets: ['@babel/env']        }      },      {        test: /\.(png|jpg)$/i,        type: 'asset/resource'      }    ]  },  plugins: [    new CleanWebpackPlugin(),    new HtmlWebpackPlugin({      template: './public/index.html'    })  ]};

留神咱们加载图片没有应用file-loaderurl-loader,咱们应用的是webpack5内置的asset/rosource这个来解决

  module.exports = {    module: {      rules: [        {          test: /\.(png|jpg)$/i,          type: 'asset/resource'        }      ]    }  }

index.js中咱们插入一张图片

import img1Src from '../assets/images/1.png';var appDom = document.getElementById('app');const img = new Image();img.src = img1Src;appDom.appendChild(img);

ok,运行npm run server,关上浏览器localhost:8080

咱们会发现,生成的图片地址就是<img src="http://localhost:8080/js/../b1640e009cff6a775ce5.png">

generator配置

当初我想配置图片的默认输入地址与名字,在module.rules中有一个generator的属性能够配置匹配图片输入的文件

// webpack.config.js module.exports = {    module: {      rules: [        ...        {          test: /\.(png|jpg)$/i,          type: 'asset/resource',          generator: {            filename: 'images/[name][ext]'          }        }      ]    }  }

此时页面加载图片的门路就变成<img src="http://localhost:8080/js/../images/1.png">

如果你的图片地址是上传到cdn上的,那么你能够这么做,然而这种做法是不是在我的项目中真的须要,还有待商讨,因为这样会导致利用所有的所有图片用cdn形式加载,如果我的项目中只是局部图片按需cdn加载,那么这种做法是不可取的。

 {        test: /\.(png|jpg)$/i,        // type: 'asset/resource'        type: 'asset',        parser: {          dataUrlCondition: {            maxSize: 40 * 1024          }        },        generator: {          publicPath: 'https://cdn/assets', // cdn域名前缀          filename: 'images/[name][ext]'        }      }

自此页面的加载的图片就是<img src="https://cdn/assets/images/3.png">

assetModuleFilename

除了generator.filename形式,你也能够在output中退出assetModuleFilename配置来批改图片默认的地址,不过留神这个属性只能是针对rule中设置的type''asset/resource' | 'asset'类型才失效。

module.exports = {  output: {    filename: 'js/[name].js',    path: path.resolve(__dirname, 'dist'),    assetModuleFilename: 'images/[name][ext]'  }}

通常我的项目里咱们会把比拟小的图片间接坐base64加载,大的图片就间接输入加载,或者上传到cdn间接加载图片地址,你能够在rulesgenerator.publicPath设置地址图片地址。

因而我引入两张大小不一样的图片测试,批改一下index.js

import img1Src from '../assets/images/1.png';import img3Src from '../assets/images/3.png';function renderImage(imageSource) {  const weakMap = new WeakMap();  var appDom = document.getElementById('app');  imageSource.forEach((src) => {    const img = new Image();    weakMap.set(img, img);    if (weakMap.has(img)) {      weakMap.get(img).src = src;      appDom.appendChild(img);    }  });}renderImage([img1Src, img3Src]);

咱们再批改下webpack.config.js

module.exports = {  module: {    rules: [       ...       {        test: /\.(png|jpg)$/i,        // type: 'asset/resource'        type: 'asset',        parser: {          dataUrlCondition: {            maxSize: 40 * 1024          }        }      }    ]  }}

rules中减少parser属性,并且将type改成asset,当咱们设置一个dataUrlCondition: {maxSize: 40 * 1024},小于KB就用base64加载了,大于40KB就间接用图片门路加载


因而咱们能够看到两张图片,一张图片是base64一张图片就走文件门路了。

所以在你的我的项目中你能够利用这个parser.dataUrlCondition.maxSize个性来优化图片资源,有些资源小图片就能够用base64来加载,这样能够缩小页面图片的资源申请

然而并不是所有的图片都要base64,base64生成的字符串十分大,同时也是减少了html的体积,无奈利用缓存机制加载图片。

所以在优化的网页加载过程中,并不是全副都用base64来加载图片。

对于内置模块的几个参数

次要参考官网asset-modules

webpack5之前

  • row-loader 将文件导入为字符串,比方导入.txt类型的文件
  • url-loader 将文件作为Data Url嵌入到打包后bundle.js中,比方base64文件
  • file-loader 将文件输入目录,图片文件会被打包到指定目录中加载

webpack5当初

asset module type通过增加以下四种类型来代替以上loader

  • asset/resource 导出独自的url,是file-loader的替代品
  • asset/inline 导出资源Data Url,是url-loader的替代品
  • asset/source 到处文件资源内容,是row-loader的替代品
  • asset 在url-loaderfile-loader中抉择,配置parse.dataUrlCondition.maxSize
    来输入图片资源是否base64输入

总结

  • 相比拟webpack5之前咱们加载图片资源文件应用file-loader或者url-loaderwebpack5中能够应用内置模块type: 'assets/resource'
  • 基于webpack5内置模块asset module type来设置资源的加载
  • 图片资源base64解决,依据图片资源的大小parse.dataUrlCondition.maxSize来限度是否须要base64输入
  • 比拟asset module type几种模式区别,代替以前row-loaderfile-loaderurl-loader计划,然而这仅仅是你的webpack版本在5当前。
  • 本文code example