This is the fifth day of my participation in the More text Challenge. For details, see more text Challenge

preface

Now that the project is ready to load CSS files, this article will show you how to load resource files such as images.

The difference between the old version and WebPack5 + to load resources

Before WebPack5, you might need to use raw-loader, file-loader, or URl-loader to load resources.

  1. Raw-loader: imports files as strings
  2. File-loader: processes the file path and outputs the file to the output directory
  3. Url-loader: converts a file to a Base64 URL conditionally. If the file is larger than the limit value, it is usually submitted to file-Loader for processing.

In WebPack5 +, the above methods are obsolete and WebPack5 uses the “resource module” instead of the above loader. The official explanation for “resource module” is this.

An Asset Module is a module type that allows the use of resource files (fonts, ICONS, etc.) without the need to configure an additional loader.Copy the code

There are four types of “resource module”.

  1. Asset /resource: Send a separate file and export the URL. Previously, it was implemented using file-loader.
  2. Asset/Inline: Exports the data URI of a resource. Previously it was implemented using url-loader.
  3. Asset /source: Export the source code of the resource. Previously it was implemented using a RAW-loader.
  4. Asset: Automatically selects between exporting a data URI and sending a separate file. Previously, this was achieved by using url-loader and configuring resource volume limits.

asset/resource

The asset/ Resource serves two purposes, one is to parse the URL of the file and the other is to output the target file to the package directory.

Create an assets directory inside the SRC directory, create an img directory inside the assets directory, and copy the test image into it.

Do the configuration in webpack.config.js.

module: {
    rules: [{...test: /\.(jpe? g|png|svg|gif)/i,
        type: 'asset/resource'}}]Copy the code

Import the image in index.js

import '.. /assets/img/simao.jpg'
Copy the code

Run NPM run build.

The images are packaged into the dist directory, main.js also introduces the images, and the default image name is a hash string (naming rule: [hash][ext][query]).

But the image is packaged in the dist root directory, so let’s configure it to be in the dist/img directory

webpack.config.js

output: {
    ...
    assetModuleFilename: 'img/[hash][ext][query]'
}
Copy the code

After we package, we find that the image is in the specified directory.

This looks good, but the resource files are not just images, but also fonts and download files. These files should also be of the asset/resource type. Should we put them all in the img directory?

Obviously not reasonable, we can use the second option, locally to specify the directory.

module.exports = {
    ...
    output: {...// assetModuleFilename: 'img/[hash][ext][query]}...module: {
        rules: [{...test: /\.(jpe? g|png|svg|gif)/i,
                type: 'asset/resource'.generator: {
                  filename: 'img/[hash][ext][query]' // Locally specify the output location}},]}}Copy the code

asset/inline

When a browser requests a web page with images, it will send HTTP requests to download the corresponding images. There are as many HTTP requests as there are images. This is very expensive for the image server and it will cost you a lot of time.

Therefore, converting small images to Base64 strings is a good choice. (The Sprite diagram technique is also designed to solve this problem, so you can explore it further if you are interested.) Asset /inline does this.

Remember to comment out the asset/resource rule above to prevent conflicts.

webpack.config.js

module: {
     rules: [.../ / {
          // test: /\.(jpe? g|png|svg|gif)/i,
          // type: 'asset/resource',
          // generator: {
          // filename: 'img/[hash][ext][query]
          / /}
          // },
          {
            test: /\.(jpe? g|png|svg|gif)/i,
            type: 'asset/inline',]}}Copy the code

index.js

import img from '.. /assets/img/simao.jpg'

document.body.style.background = `url(${img}) `
Copy the code

Build up.

As you can see, the image is not packaged. If you open main.js at this point, you will find a long string inside. That string is a Base64 string.

Open dist/index.html in your browser, or run NPM run dev, and the background of the web page will appear as expected.

Note that asset/inline converts all resources that conform to the rule to base64 strings, which means that large images are also converted to Base64, which takes up a lot of space (try it out). In WebPack5, the Asset resource type solves this problem.

asset

The asset resource type can determine whether the image needs to be converted to Base64 based on the specified image size, using asset/resource processing if the image is greater than or equal to the limit, and asset/inline processing if the image is less than the limit. An asset acts as a judgment tool.

The image in the project (simao.jpg) is 10KB in size. Now I put a 3KB image (named webpack.svg) in SRC /asset/img for testing.

Again, comment out the rules you set earlier, and then add new rules.

webpack.config.js

module: { rules: [ ... // { // test: /\.(jpe?g|png|svg|gif)/i, // type: 'asset/resource', // generator: { // filename: 'img / [hash] [ext] [query]' local specified output location / / / / / /}}, {/ / / test: / \ | PNG (jpe? G | SVG | GIF), / I / / type: 'asset/inline', //}, { test: /\.(jpe?g|png|svg|gif)/i, type: 'asset', generator: { filename: }, parser: {dataUrlCondition: {maxSize: 8 * 1024 // Limit to 8KB}}]}Copy the code

Index.js introduces webpack.svg and sets the body’s background to Webpack.svg.

index.js

import img from '.. /assets/img/simao.jpg'
import img2 from '.. /assets/img/webpack.svg'

// Replace the imG2 background
document.body.style.background = `url(${img2}) `
Copy the code

NPM run build, dist/img has image file (original simao.jpg), simao.jpg is not converted to base64.

When we look at the index.html page in the browser, we find that webpack.svg has been converted to base64 and written into the body background.

Since simao.jpg is larger than 8KB, the asset chooses to handle it with asset/ Resource. Since webpack.svg is less than 8KB, the asset chooses to process it with Asset /inline.

asset/source

This is rarely used in real development, so it’s a quick one.

The function of the asset/source can be interpreted as “output the contents of the object file to the JS variable”.

Write a rule to process a TXT file whose resource type is asset/source.

webpack.config.js

module: {
     rules: [{...test: /\.txt/,
            type: 'asset/source'}}]Copy the code

Create test.txt inside SRC /assets. Create test.txt inside SRC /assets.

Hello World
Copy the code

index.js

import txt from '.. /assets/txt/test.txt'

console.log(txt)
Copy the code

NPM run dev, you can see “Hello World” printed

Added: Webpack alias Settings

From “Using WebPack5 (part 1) : Getting started” to this article, did you find a problem?

It seems that each time you import a resource, you need to write the relative path. If the file is changed to a different directory, then not every import needs to be changed. Don’t worry, WebPack has an alias setting, you can set the path alias.

Set @ to the alias of SRC.

webpack.config.js

module.exports = {
    resolve: {
        alias: {
          The '@': path.resolve(__dirname, '.. /src'),
          // You can continue to add aliases}}}Copy the code

Import this in index.js

import '@/css/index.css'
import '@/scss/index.scss'
import img from '@/assets/img/simao.jpg'
import img2 from '@/assets/img/webpack.svg'
import txt from '@/assets/txt/test.txt'
Copy the code

The complete code

directory

webpack.config.js

const path = require('path')

const HtmlWebpackPlugin = require('html-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')

console.log('Environment variables:', process.env.NODE_ENV)

module.exports = {
  // entry: path.resolve(__dirname, '.. /src/js/index.js'),
  entry: {
    main: path.resolve(__dirname, '.. /src/js/index.js'),
    header: path.resolve(__dirname, '.. /src/js/header.js'),
    footer: path.resolve(__dirname, '.. /src/js/footer.js'),},output: {
    // filename: 'main.js',
    filename: 'js/[name].[fullhash].js'.path: path.resolve(__dirname, '.. /dist'),
    // assetModuleFilename: 'img/[hash][ext][query]' // Globally specify the output location and filename of the resource file
  },
  // devServer: {
  // port: 3000,
  // hot: true,
  // contentBase: '.. /dist'
  // },
  plugins: [
    // new HtmlWebpackPlugin({
    //   title: '首页'
    // }),
    // Configure multiple htmlWebPackPlugins for as many pages as possible
    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, '.. /src/html/index.html'),
      filename: 'index.html'.chunks: ['main'] // The module name corresponding to the entry file (entry configuration), which can be understood here as importing main.js
    }),
    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, '.. /src/html/header.html'),
      filename: 'header.html'.chunks: ['header']}),new HtmlWebpackPlugin({
      template: path.resolve(__dirname, '.. /src/html/footer.html'),
      filename: 'footer.html'.chunks: ['footer']}),new CleanWebpackPlugin(),
    new MiniCssExtractPlugin({
      filename: 'css/[name].[fullhash].css'})].module: {
    rules: [{test: /\.css$/i,
        use: [
          //'style-loader', 'css-loader'
          MiniCssExtractPlugin.loader, 'css-loader'] {},test: /\.s[ac]ss$/i,
        use: [
          MiniCssExtractPlugin.loader, 'css-loader'.'sass-loader']},/ / {
      // test: /\.(jpe? g|png|svg|gif)/i,
      // type: 'asset/resource',
      // generator: {
      // filename: 'img/[hash][ext][query]
      / /}
      // },
      / / {
      // test: /\.(jpe? g|png|svg|gif)/i,
      // type: 'asset/inline',
      // },
      {
        test: /\.(jpe? g|png|svg|gif)/i,
        type: 'asset'.generator: {
          filename: 'img/[hash][ext][query]' // Locally specify the output location
        },
        parser: {
          dataUrlCondition: {
            maxSize: 8 * 1024 // Limit to 8KB}}}, {test: /\.txt/,
        type: 'asset/source'}},resolve: {
    alias: {
      The '@': path.resolve(__dirname, '.. /src'),
      // You can continue to add aliases}}}Copy the code

index.js

import '@/css/index.css'
import '@/scss/index.scss'
import img from '@/assets/img/simao.jpg'
import img2 from '@/assets/img/webpack.svg'
import txt from '@/assets/txt/test.txt'

document.body.style.background = `url(${img2}) `

console.log('This is an entry file.')
console.log('Environment variables:', process.env.NODE_ENV)

console.log(txt)
Copy the code

series

Using WebPack5 (0) : Concepts Using WebPack5 (1) : Starting Using WebPack5 (2) : Configuring Multiple environments Using WebPack5 (3) : Loading the CSS Using WebPack5 (4) : Load resource file Webpack5 use (5) : Babel translation JS code use (6) : optimization