Webpack 资源模块

资源模块(asset module) 是一种模块类型,它允许使用资源文件(icon,img)而无需配置额外的loader。
资源模块类型(asset module type) 通过添加四种新的模块类型来替换所有这些loader:

  • asset/resource 发送一个单独的文件并导出 URL,之前通过 file-loader 实现
  • asset/inline 导出一个资源的 data URL,之前通过 url-loader 实现
  • asset/source 导出资源 源代码,之前通过 raw-loader 实现
  • asset 在导出一个 data URL 和发送一个 单独文件 之间自动选择,之前通过 url-loader 实现

    asset/resource

    发送一个单独的文件并导出 URL,之前通过 file-loader 实现

    配置

    我们在 webpack.config.js 中配置 module 模块: ```javascript const path = require(‘path’) const HtmlWebpackPlugin = require(‘html-webpack-plugin’); // 引入 html-webpack-plugin 插件

module.exports = { entry: ‘./src/index.js’, // 入口文件路径 output: { // 出口文件 filename: ‘bundle.js’, // 出口文件名 path: path.resolve(__dirname, ‘./dist’), // 出口文件路径 clean: true // 生成新文件的同时是否删除旧文件 }, mode: ‘development’, // 设置模式 ‘none’ | ‘development’ | ‘production’ devtool: ‘inline-source-map’, // 帮助定位错误源文件位置 plugins: [ new HtmlWebpackPlugin({ // 实例化 HtmlWebpackPlugin,它将帮我们生成一个 dist/index.html 文件 template: ‘./index.html’, // 指定模板 filename: ‘index.html’, // 生成的文件名 inject: ‘body’ // script标签的生成位置 }) ], devServer: { static: ‘./dist’ // 路径 }, module: { rules: [ // 配置资源模块 { test: /.png$/, // 利用正则匹配以 .png 结尾的文件 type: ‘asset/resource’ // 设置资源模块类型 } ] } }

  1. <a name="VLetS"></a>
  2. #### 准备
  3. 我们把提前准备好的一些资源文件放到 src 中:<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/12391273/1646031689883-11cfc86f-8e6b-4b17-9638-cb86e4ff5e06.png#clientId=u021b7dfd-2f9e-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=139&id=u2e85aa32&margin=%5Bobject%20Object%5D&name=image.png&originHeight=139&originWidth=343&originalType=binary&ratio=1&rotation=0&showTitle=false&size=5857&status=done&style=none&taskId=ue5968612-09aa-4d4d-9385-20799fa25a7&title=&width=343)
  4. <a name="iMXsY"></a>
  5. #### 加载
  6. 我们在index.js中加载这个模块
  7. ```javascript
  8. import Hello from './hello'
  9. import imgSrc from './asset/web.png' // 返回一个 url
  10. Hello()
  11. const img = document.createElement('img') // 创建一个 img标签
  12. img.src = imgSrc // 将返回的 url 设置给 img标签 的 src 属性
  13. document.body.appendChild(img) // 在 body 中加入 img标签

打包

我们运行 npx webpack从新打包,然后在dist下发现有一个 png 的文件,打开页面发现图片正常显示了,我们选中元素查看发现 asset/resource 确实导出了一个 URL
image.png

修改生成资源文件名

  1. const path = require('path')
  2. const HtmlWebpackPlugin = require('html-webpack-plugin'); // 引入 html-webpack-plugin 插件
  3. module.exports = {
  4. entry: './src/index.js', // 入口文件路径
  5. output: { // 出口文件
  6. filename: 'bundle.js', // 出口文件名
  7. path: path.resolve(__dirname, './dist'), // 出口文件路径
  8. clean: true // 生成新文件的同时是否删除旧文件
  9. },
  10. mode: 'development', // 设置模式 'none' | 'development' | 'production'
  11. devtool: 'inline-source-map', // 帮助定位错误源文件位置
  12. plugins: [
  13. new HtmlWebpackPlugin({ // 实例化 HtmlWebpackPlugin,它将帮我们生成一个 dist/index.html 文件
  14. template: './index.html', // 指定模板
  15. filename: 'index.html', // 生成的文件名
  16. inject: 'body' // script标签的生成位置
  17. })
  18. ],
  19. devServer: {
  20. static: './dist' // 路径
  21. },
  22. module: {
  23. rules: [ // 配置资源模块
  24. {
  25. test: /\.png$/, // 利用正则匹配以 .png 结尾的文件
  26. type: 'asset/resource', // 设置资源模块类型
  27. generator: { // 修改生成资源文件名
  28. filename: 'images/[contenthash][ext]' // contenthash 表示随机生成hash字符串作为文件名,ext 表示生成文件的后缀和源文件保持一致
  29. }
  30. }
  31. ]
  32. }
  33. }

asset/inline

导出一个资源的 data URL,之前通过 url-loader 实现
实现和 asset/resource 一样

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin'); // 引入 html-webpack-plugin 插件

module.exports = {
    entry: './src/index.js', // 入口文件路径
    output: { // 出口文件
        filename: 'bundle.js', // 出口文件名
        path: path.resolve(__dirname, './dist'), // 出口文件路径
        clean: true // 生成新文件的同时是否删除旧文件
    },
    mode: 'development', // 设置模式 'none' | 'development' | 'production'
    devtool: 'inline-source-map', // 帮助定位错误源文件位置
    plugins: [
        new HtmlWebpackPlugin({ // 实例化 HtmlWebpackPlugin,它将帮我们生成一个 dist/index.html 文件
            template: './index.html', // 指定模板
            filename: 'index.html', // 生成的文件名
            inject: 'body' // script标签的生成位置
        })
    ],
    devServer: {
        static: './dist' // 路径
    },
    module: {
        rules: [ // 配置资源模块
            {
                test: /\.png$/, // 利用正则匹配以 .png 结尾的文件
                type: 'asset/resource', // 设置资源模块类型
                generator: {
                    filename: 'images/[contenthash][ext]' // contenthash 表示随机生成hash字符串作为文件名,ext表示生成文件的后缀和源文件保持一致
                }
            },
            {
                test: /\.svg$/, // 利用正则匹配以 .svg 结尾的文件
                type: 'asset/inline', // 设置资源模块类型
            }
        ]
    }
}
import Hello from './hello'
import imgSrc from './asset/web.png' // 返回一个 url
import logoSvg from './asset/web.svg' // 返回 data url

Hello()

const img = document.createElement('img') // 创建一个 img标签
img.src = imgSrc // 将返回的 url 设置给 img标签 的 src 属性
document.body.appendChild(img) // 在 body 中加入 img标签

const img2 = document.createElement('img')
img2.src = logoSvg
document.body.appendChild(img2)

选中元素查看发现确实是 data url 是base64 格式的
image.png

asset/source

导出资源 源代码

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin'); // 引入 html-webpack-plugin 插件

module.exports = {
    entry: './src/index.js', // 入口文件路径
    output: { // 出口文件
        filename: 'bundle.js', // 出口文件名
        path: path.resolve(__dirname, './dist'), // 出口文件路径
        clean: true // 生成新文件的同时是否删除旧文件
    },
    mode: 'development', // 设置模式 'none' | 'development' | 'production'
    devtool: 'inline-source-map', // 帮助定位错误源文件位置
    plugins: [
        new HtmlWebpackPlugin({ // 实例化 HtmlWebpackPlugin,它将帮我们生成一个 dist/index.html 文件
            template: './index.html', // 指定模板
            filename: 'index.html', // 生成的文件名
            inject: 'body' // script标签的生成位置
        })
    ],
    devServer: {
        static: './dist' // 路径
    },
    module: {
        rules: [ // 配置资源模块
            {
                test: /\.png$/, // 利用正则匹配以 .png 结尾的文件
                type: 'asset/resource', // 设置资源模块类型
                generator: {
                    filename: 'images/[contenthash][ext]' // contenthash 表示随机生成hash字符串作为文件名,ext表示生成文件的后缀和源文件保持一致
                }
            },
            {
                test: /\.svg$/, // 利用正则匹配以 .svg 结尾的文件
                type: 'asset/inline', // 设置资源模块类型
            },
            {
                test: /\.txt$/, // 利用正则匹配以 .txt 结尾的文件
                type: 'asset/source', // 设置资源模块类型
            }
        ]
    }
}

我们在 asset 文件夹下新建一个 test.txt 文件:

hello 索大

剩下的和 asset/resource 相同:

import Hello from './hello'
import imgSrc from './asset/web.png' // 返回一个 url
import logoSvg from './asset/web.svg' // 返回 data url
import testTxt from './asset/test.txt' // 返回 源文件

Hello()

const img = document.createElement('img') // 创建一个 img标签
img.src = imgSrc // 将返回的 url 设置给 img标签 的 src 属性
document.body.appendChild(img) // 在 body 中加入 img标签

const img2 = document.createElement('img')
img2.src = logoSvg
document.body.appendChild(img2)

const block = document.createElement('div')
block.textContent = testTxt
document.body.appendChild(block)

image.png

asset

在导出一个 data URL 和发送一个 单独文件 之间自动选择,也就是 asset/resource asset/inline。
默认情况下:小于 8kb 的文件,将会视为 inline 模块类型,否则会被视为 resource 模块类型。
我们可以通过配置 parser 来修改边界值,如下:

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin'); // 引入 html-webpack-plugin 插件

module.exports = {
    entry: './src/index.js', // 入口文件路径
    output: { // 出口文件
        filename: 'bundle.js', // 出口文件名
        path: path.resolve(__dirname, './dist'), // 出口文件路径
        clean: true // 生成新文件的同时是否删除旧文件
    },
    mode: 'development', // 设置模式 'none' | 'development' | 'production'
    devtool: 'inline-source-map', // 帮助定位错误源文件位置
    plugins: [
        new HtmlWebpackPlugin({ // 实例化 HtmlWebpackPlugin,它将帮我们生成一个 dist/index.html 文件
            template: './index.html', // 指定模板
            filename: 'index.html', // 生成的文件名
            inject: 'body' // script标签的生成位置
        })
    ],
    devServer: {
        static: './dist' // 路径
    },
    module: {
        rules: [ // 配置资源模块
            {
                test: /\.png$/, // 利用正则匹配以 .png 结尾的文件
                type: 'asset/resource', // 设置资源模块类型
                generator: {
                    filename: 'images/[contenthash][ext]' // contenthash 表示随机生成hash字符串作为文件名,ext表示生成文件的后缀和源文件保持一致
                }
            },
            {
                test: /\.svg$/, // 利用正则匹配以 .svg 结尾的文件
                type: 'asset/inline', // 设置资源模块类型
            },
            {
                test: /\.txt$/, // 利用正则匹配以 .txt 结尾的文件
                type: 'asset/source', // 设置资源模块类型
            },
            {
                test: /\.jpg$/, // 利用正则匹配以 .jpg 结尾的文件
                type: 'asset', // 设置资源模块类型
                parser: { // 修改边界值
                    dataUrlCondition: {
                        maxSize: 4 * 1024 * 1024 // 改为 4MB
                    }
                }
            }
        ]
    }
}
import Hello from './hello'
import imgSrc from './asset/web.png' // 返回一个 url
import logoSvg from './asset/web.svg' // 返回 data url
import testTxt from './asset/test.txt' // 返回 源文件
import imgFree from './asset/web.jpg' // 自动选择

Hello()

const img = document.createElement('img') // 创建一个 img标签
img.src = imgSrc // 将返回的 url 设置给 img标签 的 src 属性
document.body.appendChild(img) // 在 body 中加入 img标签

const img2 = document.createElement('img')
img2.src = logoSvg
document.body.appendChild(img2)

const block = document.createElement('div')
block.textContent = testTxt
document.body.appendChild(block)

const img3 = document.createElement('img')
img3.src = imgFree
document.body.appendChild(img3)