webpack基础篇(三):管理资源(image、css、fonts、csv、json5)

1. 处理资源 - loader

webpack 只能理解 JavaScript 和 JSON 文件,这是 webpack 开箱可用的自带能力。loader 让 webpack 能够去处理其他类型的文件,并将它们转换为有效 模块,以供应用程序使用,以及被添加到依赖图中。

在更高层面,在 webpack 的配置中,loader 有两个属性:

  1. test 属性,识别出哪些文件会被转换。
  2. use 属性,定义出在进行转换时,应该使用哪个 loader。

webpack.config.js

const path = require('path');

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

以上配置中,对一个单独的 module 对象定义了 rules 属性,里面包含两个必须属性:testuse。这告诉 webpack 编译器(compiler) 如下信息:

“嘿,webpack 编译器,当你碰到「在 require()/import 语句中被解析为 ‘.txt’ 的路径」时,在你对它打包之前,先 use(使用) raw-loader 转换一下。”


1.1 加载css - css-loader

css-loader 会对 @importurl() 进行处理,就像 js 解析 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"],
      },
    ],
  },
};

注意这里的style-loadercss-loader顺序不要写错,loader是从右向左加载的,并且为链式调用。后执行的loader会以前面loader生成的结果进行处理资源

assets目录中新建css/style-1.css

src/index.js中引用assets/css/style-1.css

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)

执行npx webpack-dev-server可以看到样式已经生效


1.2 处理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',
        ],
      },
    ],
  },
};

assets/css新建style-2.less

@color: #a9a9e7;

body {
    
    
  background-color: @color;
}

src/index.js引用style.less

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

执行npx webpcak-dev-sercer,打开index.html 可以看到body的样式已经变化了


2. 加载css

2.1 抽离css

MiniCssExtractPlugin

仅仅使用style-loadercss只会内嵌在打包出的js文件中,最终以style标签作用在页面中。但这样的缺点是会使js文件变大、无法按需加载。

本插件会将 CSS 提取到单独的文件中,为每个包含 CSS 的 JS 文件创建一个 CSS 文件,并且支持 CSS 和 SourceMaps 的按需加载。

本插件基于webpack 5的新特性构建,并且需要 webpack 5 才能正常工作。

extract-text-webpack-plugin 相比:

  • 异步加载
  • 没有重复的编译(性能)
  • 更容易使用
  • 特别针对 CSS 开发
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"], // MiniCssExtractPlugin.loader 替换 style-loader
      },
      // 或者
      {
    
    
        test: /\.(css|less)/i,
        use: [MiniCssExtractPlugin.loader, "css-loader", "less-loader"],
      },
    ],
  },
};

执行命令webpack,可以看到dist中生成了一个main.css
在这里插入图片描述
在这里插入图片描述

执行命令npx webpack-dev-server可以看到样式依旧加载正常

自定义分类的css文件名

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

module.exports = {
    
    
  // ...
  plugins: [new MiniCssExtractPlugin({
    
    
    filename: 'styles/[contenthash].css' // [contenthash]启动长期缓存,将根据资源内容创建出唯一 hash
  })],
  module: {
    
    
    rules: [
      {
    
    
        test: /\.css$/i,
        use: [MiniCssExtractPlugin.loader, "css-loader"], // MiniCssExtractPlugin.loader 替换 style-loader
      }
    ],
  },
};

执行webpack命令可以看到dist/styles中生成新的css文件

执行npx webpcak-dev-server打开index.html可看到页面样式正常显示


2.2 压缩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()],
};

这将仅在mode: production 生产环境开启 CSS 优化

如果还想在开发环境下启用 CSS 优化,optimization.minimize 设置为 true:

webpack.config.js

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

运行命令 webpack可以看到代码已压缩优化
在这里插入图片描述

3. 压缩 js

在上面,我们通过 optimization.minimizer 配置插件实现了css代码压缩,那js该怎么压缩呢?
webpack 有开箱即用的 terser 插件实现 js 代码压缩,可以在 mode: 'production' 生产环境实现 js 代码压缩
因为 optimization.minimizer 我们已经自定义配置了 css 压缩,因此我们需要单独配置一下 terser

npm i terser-webpack-plugin -D

webpack.config.js

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

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

执行 webpack,可以看到

压缩前:
压缩前
压缩后:
在这里插入图片描述

4. 加载images图像

前面webpack基础篇(二):资源模块asset module我们已经学习了weback内置的模块asste modules资源模块,成功处理了如png|svg|jpe?g等图片资源,那它能处理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',
+      },
     ],
   },
 };

src/assets/css/style-1.css加入

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

src/index.js中修改之前的 text 元素

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

执行webpack看到背景图片已经被打包到css中了
在这里插入图片描述

执行npx webpack-dev-server可以看到背景图片已经成功加载

因为我们前面已经配置过asset module资源模块,所以css中的图片资源能够正常加载。这说明asset module也能处理css中的图片资源。


5. 加载 fonts 字体

那么,像字体这样的其他资源如何处理呢?使用 Asset Modules 可以接收并加载任何文件,然后将其输出到构建目录。这就是说,我们可以将它们用于任何类型的文件,也包括字体。让我们更新 webpack.config.js 来处理字体文件:

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',
+      },
     ],
   },
 };

在项目中添加一些字体文件:这里我引用了iconfont在线资源

src/assets/css中新建fonts.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";
}

src/index.js引入fonts.css

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

index.html中使用字体

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

执行webpack命令,可以看到
在这里插入图片描述

图片资源已经被打包进css中

执行npx webpcak-dev-server打开index.html可以看到,字体图标已经加载显示了
在这里插入图片描述

6. 加载数据

此外,可以加载的有用资源还有数据,如 JSON 文件,CSV、TSV 和 XML。类似于 NodeJS,JSON 支持实际上是内置的,也就是说 import Data from './data.json' 默认将正常运行。要导入 CSV、TSV 和 XML,你可以使用 csv-loaderxml-loader。让我们处理加载这三类文件:

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'],
+      },
     ],
   },
 };

在项目中添加一些数据文件:

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

现在,你可以 import 这四种类型的数据(JSON, CSV, TSV, XML)中的任何一种,所导入的 Data 变量,将包含可直接使用的已解析 JSON:

src/index.js

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

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

执行npm webpack-dev-server命令,打开index.html打开工作台可以看到,两个数据已经被成功加载
在这里插入图片描述

6.1 自定义 JSON 模块 parser

通过使用 自定义 parser 替代特定的 webpack loader,可以将任何 tomlyamljson5 文件作为 JSON 模块导入。

假设你在 src/assets 文件夹下有一个 data.toml、一个 data.yaml 以及一个 data.json5 文件:

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',
  },
}

首先安装 tomlyamljsjson5 的 packages:

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);

执行npx webpack-dev-server打开控制台可以看到数据已经加载成功
在这里插入图片描述



源码地址:https://gitee.com/yanhuakang/webpack-test

如果有用,就点个赞吧(*^▽^*)

猜你喜欢

转载自blog.csdn.net/qq_41887214/article/details/121636739