webpack Basics: managing resources (image, css, fonts, csv, json5)

1. Processing resources - loader

Webpack can only understand JavaScript and JSON files, which is the built-in capability of webpack out of the box. loader enables webpack to process other types of files and convert them into valid files modular , for use by the application, and added to the dependency graph.

At a higher level, in the configuration of webpack, loader has two attributes:

  1. test attribute to identify which files will be converted.
  2. The use attribute defines which loader should be used during conversion.

webpack.config.js

const path = require('path');

module.exports = {
  output: {
    filename: 'my-first-webpack.bundle.js',
  },
  module: {
    rules: [{ test: /\.txt$/, use: 'raw-loader' }],
  },
};

In the above configuration, the rules attribute is defined for a separate module object, which contains two required attributes: test and use. This tells the webpack compiler the following information:

"Hey, webpack compiler, when you encounter the path resolved to '. txt' in the require()/import statement, use raw loader to convert it before you package it."


1.1 loading CSS - CSS loader

CSS loader handles @ import and url(), just as js parses import/require().

npm install --save-dev css-loader style-loader

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: ["style-loader", "css-loader"],
      },
    ],
  },
};

Note that the order of style loader and CSS loader here should not be wrong. The loader is loaded from right to left and is called in a chain. The loader executed after will process resources based on the results generated by the previous loader

Create a new css/style-1.css in the assets directory

Reference assets/css/style-1.css in src/index.js

import './assets/css/style-1.css'

const text = document.createElement('p')
text.style.cssText = 'width: 200px;height: 200px;background-color: pink;'
text.innerText = helloWebpack
text.classList.add('hello')
document.body.appendChild(text)

Execute NPX webpack dev server to see that the style has taken effect


1.2 handling less - less loader

npm install less less-loader --save-dev

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.(css|less)$/i,
        use: [
          // compiles Less to CSS
          'style-loader',
          'css-loader',
          'less-loader',
        ],
      },
    ],
  },
};

Create a new style-2.less in assets/css

@color: #a9a9e7;

body {
  background-color: @color;
}

Reference style.less in src/index.js

import './assets/css/style-2.less'

Execute NPX webpcak dev sercer and open index.html to see that the style of the body has changed


2. Load css

2.1 extracting css

MiniCssExtractPlugin

Using only style loader CSS will only be embedded in the packaged js file, and finally act as a style tag in the page. But this disadvantage is that it will make the js file larger and cannot be loaded on demand.

This plug-in will extract CSS into a separate file, create a CSS file for each JS file containing CSS, and support the on-demand loading of CSS and SourceMaps.

This plug-in is built based on the new features of webpack 5 and requires webpack 5 to work properly.

Compared with extract text webpack plugin:

  • Asynchronous loading
  • No duplicate compilation (performance)
  • Easier to use
  • Especially for CSS development
npm install --save-dev mini-css-extract-plugin

webpack.config.js

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  // ...
  plugins: [new MiniCssExtractPlugin()],
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [MiniCssExtractPlugin.loader, "css-loader"], // Replace style loader with MiniCssExtractPlugin.loader
      },
      // perhaps
      {
        test: /\.(css|less)/i,
        use: [MiniCssExtractPlugin.loader, "css-loader", "less-loader"],
      },
    ],
  },
};

Execute the command webpack, and you can see that a main.css is generated in dist

Execute the command NPX webpack dev server to open index.html. You can see that the style is still loaded normally

css file name of custom classification

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  // ...
  plugins: [new MiniCssExtractPlugin({
    filename: 'styles/[hash].css'
  })],
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [MiniCssExtractPlugin.loader, "css-loader"], // Replace style loader with MiniCssExtractPlugin.loader
      }
    ],
  },
};

Execute the webpack command to see the new css file generated in dist/styles

Execute NPX webpcak dev server and open index.html to see that the page style is displayed normally


2.2 compressing css

CssMinimizerWebpackPlugin

npm install css-minimizer-webpack-plugin --save-dev

webpack.config.js

const MiniCssExtractPlugin = require("mini-css-extract-plugin");
+ const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");

module.exports = {
  module: {
    rules: [
      {
        test: /.s?css$/,
        use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"],
      },
    ],
  },
+ optimization: {
+   minimizer: [
+     new CssMinimizerPlugin(),
+   ],
+ },
  plugins: [new MiniCssExtractPlugin()],
};

This will turn on CSS optimization only in the mode: production production environment

If you also want to enable CSS optimization in the development environment, set optimization.minimize to true:

webpack.config.js

// [...]
module.exports = {
  optimization: {
    // [...]
    minimize: true,
  },
};

Run the webpack command to see that the code has been compressed and optimized


3. Load images

front webpack Basics (1) We have learned the asste modules resource module built in weback and successfully processed picture resources such as png|svg|jpe?g. can it handle picture resources of css

webpack.config.js

 const path = require('path');

 module.exports = {
   entry: './src/index.js',
   output: {
     filename: 'bundle.js',
     path: path.resolve(__dirname, 'dist'),
   },
   module: {
     rules: [
       {
         test: /\.css$/i,
         use: ['style-loader', 'css-loader'],
       },
+      {
+        test: /\.(png|svg|jpg|jpeg|gif)$/i,
+        type: 'asset/resource',
+      },
     ],
   },
 };

Add in src/assets/css/style-1.css

.text-bg {
    background-image: url("../empty.svg") !important;
}

Modify the previous text element in src/index.js

const text = document.createElement('p')
text.style.cssText = 'width: 200px;height: 200px;background-color: pink;'
text.innerText = helloWebpack
text.classList.add('hello')
// Add style
text.classList.add('text-bg')
document.body.appendChild(text)

Execute webpack and see that the background image has been packaged into css

Execute NPX webpack dev server to see that the background image has been loaded successfully

Because we have previously configured the asset module resource module, the image resources in css can be loaded normally. This shows that the asset module can also handle image resources in css.


4. Load fonts

So what about other resources like fonts? Using Asset Modules, you can receive and load any file and then output it to the build directory. That is, we can use them for any type of file, including fonts. Let's update webpack.config.js to handle the font file:

webpack.config.js

 const path = require('path');

 module.exports = {
   entry: './src/index.js',
   output: {
     filename: 'bundle.js',
     path: path.resolve(__dirname, 'dist'),
   },
   module: {
     rules: [
       {
         test: /\.css$/i,
         use: ['style-loader', 'css-loader'],
       },
       {
         test: /\.(png|svg|jpg|jpeg|gif)$/i,
         type: 'asset/resource',
       },
+      {
+        test: /\.(woff|woff2|eot|ttf|otf)$/i,
+        type: 'asset/resource',
+      },
     ],
   },
 };

Add some font files to the project: Here I refer to iconfont online resources

Create a new fonts.css in src/assets/css

/*fonts.css*/
@font-face {
  font-family: "webpack-iconfont"; /* Project id 2975967 */
  src: url('//at.alicdn.com/t/font_2975967_payhpcjfltf.woff2?t=1638248030621') format('woff2'),
       url('//at.alicdn.com/t/font_2975967_payhpcjfltf.woff?t=1638248030621') format('woff'),
       url('//at.alicdn.com/t/font_2975967_payhpcjfltf.ttf?t=1638248030621') format('truetype');
}

.webpack-iconfont {
  font-family: "webpack-iconfont" !important;
  font-size: 16px;
  font-style: normal;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

.webpack-icon-webpack:before {
  content: "\e799";
}

Introduce fonts.css in src/index.js

import './assets/css/fonts.css'

Use fonts in index.html

<i class="webpack-iconfont webpack-icon-webpack"></i>

Execute the webpack command, and you can see

Image resources have been packaged into css

Execute NPX webpcak dev server and open index.html. You can see that the font icon has been loaded and displayed


5. Load data

In addition, useful resources that can be loaded include data, such as JSON files, CSV, TSV, and XML. Similar to NodeJS, JSON support is actually built-in, that is, import Data from './data.json' will work normally by default. To import CSV, TSV and XML, you can use csv-loader and xml-loader . Let's deal with loading these three types of files:

npm install --save-dev csv-loader xml-loader

webpack.config.js

 const path = require('path');

 module.exports = {
   module: {
     rules: [
      	// ...
+      {
+        test: /\.(csv|tsv)$/i,
+        use: ['csv-loader'],
+      },
+      {
+        test: /\.xml$/i,
+        use: ['xml-loader'],
+      },
     ],
   },
 };

Add some data files to the project:

src/assets/data.xml

<?xml version="1.0" encoding="UTF-8"?>
<note>
  <to>Mary</to>
  <from>John</from>
  <heading>Reminder</heading>
  <body>Call Cindy on Tuesday</body>
</note>

src/assets/data.csv

to,from,heading,body
Mary,John,Reminder,Call Cindy on Tuesday
Zoe,Bill,Reminder,Buy orange juice
Autumn,Lindsey,Letter,I miss you

Now, you can import any of the four types of Data (JSON, CSV, TSV, XML). The imported Data variable will contain the parsed JSON that can be used directly:

src/index.js

import dataXml from './assets/data.xml'
import dataCsv from './assets/data.csv'

console.log('dataXml', dataXml);
console.log('dataCsv', dataCsv);

Execute the NPM webpack dev server command, open index.html, and open the workbench. You can see that the two data have been successfully loaded


5.1 custom JSON module parser

through the use of Custom parser Instead of a specific webpack loader, you can import any toml, yaml, or JSON 5 file as a JSON module.

Suppose you have a data.toml, a data.yaml and a data.json5 file in the src/assets folder:

src/assets/data.toml

title = "TOML Example"

[owner]
name = "Tom Preston-Werner"
organization = "GitHub"
bio = "GitHub Cofounder & CEO\nLikes tater tots and beer."
dob = 1979-05-27T07:32:00Z

src/assets/data.yaml

title: YAML Example
owner:
  name: Tom Preston-Werner
  organization: GitHub
  bio: |-
    GitHub Cofounder & CEO
    Likes tater tots and beer.
  dob: 1979-05-27T07:32:00.000Z

src/assets/data.json5

{
  // comment
  title: 'JSON5 Example',
  owner: {
    name: 'Tom Preston-Werner',
    organization: 'GitHub',
    bio: 'GitHub Cofounder & CEO\n\
Likes tater tots and beer.',
    dob: '1979-05-27T07:32:00.000Z',
  },
}

First, install the packages of toml, yamljs and json5:

npm install toml yamljs json5 --save-dev

webpack.config.js

const path = require('path');
+const toml = require('toml');
+const yaml = require('yamljs');
+const json5 = require('json5');

 module.exports = {
   entry: './src/index.js',
   output: {
     filename: 'bundle.js',
     path: path.resolve(__dirname, 'dist'),
   },
   module: {
     rules: [
       {
         test: /\.css$/i,
         use: ['style-loader', 'css-loader'],
       },
       {
         test: /\.(png|svg|jpg|jpeg|gif)$/i,
         type: 'asset/resource',
       },
       {
         test: /\.(woff|woff2|eot|ttf|otf)$/i,
         type: 'asset/resource',
       },
       {
         test: /\.(csv|tsv)$/i,
         use: ['csv-loader'],
       },
       {
         test: /\.xml$/i,
         use: ['xml-loader'],
       },
+      {
+        test: /\.toml$/i,
+        type: 'json',
+        parser: {
+          parse: toml.parse,
+        },
+      },
+      {
+        test: /\.yaml$/i,
+        type: 'json',
+        parser: {
+          parse: yaml.parse,
+        },
+      },
+      {
+        test: /\.json5$/i,
+        type: 'json',
+        parser: {
+          parse: json5.parse,
+        },
+      },
     ],
   },
 };

src/index.js

import toml from './assets/data.toml';
import yaml from './assets/data.yaml';
import json5 from './assets/data.json5';

console.log('toml', toml);
console.log('yaml', yaml);
console.log('json5', json5);

Execute NPX webpack dev server, open index.html, and open the console to see that the data has been loaded successfully



Source address: https://gitee.com/yanhuakang/webpack-test

If it's useful, just like it (* ^ ▽ ^ *)

Tags: Front-end Webpack

Posted on Tue, 30 Nov 2021 04:18:35 -0500 by Termina