05. 资源模块

96 阅读2分钟

相关代码

Webpack 最出色的功能之一就是,除了引入 JavaScript,还可以利用内置的资源模块(Asset Modules)引入任何其他类型的文件。

资源模块(Asset Module)是一种模块类型,它允许我们应用 Webpack 来打包其他资源文件(如字体、图标等)。

4 种资源模块类型:

  • asset/resource:发送一个单独的文件并导出 URL;
  • asset/inline:导出一个资源的 data URI;
  • asset/source:导出资源的源代码;
  • asset:在导出一个 data URI 和发送一个单独的文件之间自动选择。

一、Resource 资源

asset/resource:发送一个单独的文件并导出 URL。意思是,会将指定文件打包到 dist 目录且生成 url 供代码使用。

1. 基本配置

webpack.config.js:

module.exports = {
    // 配置资源文件
    module: {
        rules: [
            {
                test: /\.jpg$/,
                type: 'asset/resource'
            }
        ]
    },
}

入口文件 index.js:

import imgsrc from './assets/img-1.jpg'

const img = document.createElement('img')
img.width = 400
img.src = imgsrc
document.body.appendChild(img)

执行 npx webpack 后,发现 dist 目录中多了个 .jpg 文件:

image.png

执行 npx webpack serve --open 并在浏览器查看:

image.png

2. 自定义文件目录及文件名

默认情况下, asset/resource 模块以 [contenthash][ext][query] 文件名发送到输出目录。

  • [contenthash]:表示根据文件的内容,生成一个哈希的字符串;
  • [ext]:表示使用原资源的扩展名;
  • [query]:表示查询参数。
  1. 设置 output.assetModuleFilename

    module.exports = {
        output: {
            assetModuleFilename: 'images/[contenthash][ext][query]'
        },
    }
    
  2. 将某些资源发送到指定目录

    module.exports = {
        module: {
            rules: [
                {
                    test: /\.jpg$/,
                    type: 'asset/resource',
                    generator: {        // 优先级高于 output 中的 assetModuleFilename
                        filename: 'imgs/[contenthash][ext][query]' 
                    }
                }
            ]
        },
    }
    

二、inline 资源

asset/inline:导出一个资源的 data URI。注意,这种方式不会将文件打包到 dist 目录中,而是生成 data URI,可以在浏览器中查看。

1. 基本配置

webpack.config.js:

module.exports = {
    module: {
        rules: [
            {
                test: /\.svg/,
                type: 'asset/inline'
            }
        ],
    },
}

入口文件 index.js:

import svgsrc from './assets/svg-1.svg'

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

npx webpack 后执行 npx webpack serve --open 在浏览器中查看:

image.png

2. 自定义 data URI 生成器

Webpack 输出的 data URI,默认是使用 Base64 算法编码的,如果要使用自定义编码算法,则可以指定一个自定义函数来编码文件内容。

npm install mini-svg-data-uri -D
const svgToMiniDataURI = require('mini-svg-data-uri')

module.exports = {
    module: {
        rules: [
            {
                test: /\.svg$/,
                type: 'asset/inline',
                generator: { 
                    dataUrl: content => { 
                        content = content.toString(); 
                        return svgToMiniDataURI(content); 
                    } 
                }
            },
        ]
    },
}

现在,svg 文件都将经过 mini-svg-data-uri 进行编译处理。重新启动服务,在浏览器中可以发现,这次的 data URI 与上次已经不同了:

image.png

三、source 资源

asset/source:导出资源的源代码。

webpack.config.js:

module.exports = {
    module: {
        rules: [
            {
                test: /\.txt$/,
                type: 'asset/source'
            }
        ]
    },
}

入口文件 index.js:

import exampleText from './assets/example.txt'

const block = document.createElement('div') 
block.style.cssText = `width: 200px; height: 200px; background: aliceblue` 
block.textContent = exampleText 
document.body.appendChild(block)

启动服务,在浏览器中查看效果:

image.png

四、通用类型资源

asset:在导出一个 data URI(asset/inline) 和发送一个单独的文件(asset/resource)之间自动选择。

默认条件是:当文件小于 8kb 时,将会视 inline 模块类型,否则会被视为 resource 模块类型。

module.exports = {
    module: {
        rules: [
            {
                test: /\.png$/,
                type: 'asset'
            }
        ]
    },
}

可以通过设置 Rule.parser.dataUrlCondition.maxSize 选项来修改自动选择的条件:

module.exports = {
    module: {
        rules: [
            {
                test: /\.png$/,
                type: 'asset',
                parser: {
                    dataUrlCondition: {
                        maxSize: 400 * 1024    // 400kb
                    }
                }
            }
        ]
    },
}

当文件大小小于 maxSize 指定的大小时,就会选择 asset/inline,生成 data URI:

image.png

当文件大小大于 maxSize 指定的大小时,就会选择 asset/resource,在 dist 目录中生成一个文件:

image.png