thymeleaf引入静态图片_webpack基础配置-管理项目中的静态资源

一、概述

对于像Browserify这样的打包工具而言,仅仅能够处理 JavaScript。然而我们的工程不仅仅有 JavaScript,还有模板、样式文件、图片等等其它类型的资源,这就意味着我们还需要使用别的工具去管理它们。在 Webpack 的思想中一切皆模块,所有模板、样式、图片等等这些资源都是模块,因为这些资源也具备模块的特性——它们都负责特定的职能,并且具有可复用性。因此,我们可以使用 Webpack 去管理所有这些资源,并且把它们都当做模块来处理。

静态资源指前端中常用的图片、富媒体(Video、Audio 等)、字体文件等。Webpack 中静态资源也是可以作为模块直接使用的。Webpack 提供了很多插件和 loader 对图片进行压缩、合并(CSS Sprite)。Webpack 还会使用url-loader等插件,将较小的资源通过 Base64 的方式引入。当项目足够大了之后,配置太多的静态资源处理流程也会影响 Webpack 的打包速度,想突破压缩和合并这类前端常见优化,我们可以通过让UI工程师提供最优图片格式等方式来人工解决。当然如果没专人优化,为避免上到线上图片太大,那么可以使用 Webpack 来优化图片。

1) 图片:借助 loader 让 Webpack 识别图片并且能够打包输出,比如file-loader和url-loader。

2) SVG图片:SVG 文件是纯文本,借助svg-url-loader 来打包;

3) 压缩-图片优化:借助image-webpack-loader来对使用到的图片进行优化。它支持 JPG、PNG、GIF 和 SVG 格式的图片,必须和url-loader以及svg-url-loader一起使用。

4) 合并-CSS雪碧图:借助 PostCSS 的postcss-sprites来给图片做雪碧图,经过简单的配置之后,生成雪碧图就是全自动的过程了。

5) 字体、富媒体文件:对于字体、富媒体等静态资源可以直接使用url-loader或者file-loader进行配置即可,不需要额外的操作。

6) 数据:要导入 CSV,TSV 和 XML,可以使用csv-loader和xml-loader。


二、webpack相关配置

2.1 图片loader

file-loader:能够根据配置项复制使用到的资源(不局限于图片)到构建之后的文件夹,并且能够更改对应的链接;The file-loader resolves import/require() on a file into a url and emits the file into the output directory.

url-loader:能够根据配置将符合配置的文件转换成 Base64 方式引入,将小体积的图片 Base64 引入项目可以减少 http 请求,也是一个前端常用的优化方式。A loader for webpack which transforms files into base64 URIs.

{
    test: /.(png|svg|jpg|gif)$/,
    use: {
        loader: 'url-loader',
        options: {
            limit: 3*1024 // 3k 不超过一定限制的图片才使用Base64,
            // 若超过了limit=3*1024不会被处理成Base64,直接用file-loader处理。
        }
    }
}

2.2 svg-url-loader:工作原理类似url-loader,除了它利用URL encoding而不是 Base64 对文件编码。对于 SVG 图片这是有效的,因为 SVG 文件恰好是纯文本,这种编码规模效应更加明显,使用方法如下:

// webpack.config.js
module.exports = {
    module: {
        rules: [
            {
                test: /.svg$/,
                loader: 'svg-url-loader',
                options: {
                    limit: 10 * 1024, // 小于 10kB(10240字节)的内联文件
                    noquotes: true // 移除 url 中的引号(在大多数情况下它们都不是必要的)
                }
            }
        ]
    }
}; // svg-url-loader 拥有改善 IE 浏览器支持的选项,但是在其他浏览器中更糟糕。如果你需要兼容 IE 浏览器,设置 iesafe: true选项。

2.3 img-webpack-loader:压缩图片

# 安装
npm install image-webpack-loader --save-dev

这个 loader 不能将图片嵌入应用,所以它必须和url-loader以及svg-url-loader一起使用。为了避免同时将它复制粘贴到两个规则中(一个针对 JPG/PNG/GIF 图片, 另一个针对 SVG ),我们使用enforce:'pre'作为单独的规则涵盖在这个 loader:

// webpack.config.js
module.exports = {
    module: {
        rules: [
            {
                test: /.(jpe?g|png|gif|svg)$/,
                loader: 'image-webpack-loader',
                // 这会应用该 loader,在其它之前
                enforce: 'pre' // 提高了 img-webpack-loader 的优先级,保证在url-loader和svg-url-loader之前就完成了图片的优化。
            }

        ]
    }
};

2.4 postcss-sprites:

CSS 使用小图标图片的时候,我们经常做的优化项目是将小图标的图片合并成雪碧图(CSS Sprite),雪碧图的好处是将页面用到的小图片合并到一张大图中,然后使用background-position重新定位,这样节省了 HTTP 的请求数。在 Webpack 中我们可以借助 PostCSS 来给图片做雪碧图,经过简单的配置之后,生成雪碧图就是全自动的过程了。

npm install postcss-sprites -D
# 如果没有安装 postcss-loader 那么也安装它
npm install postcss-loader -D

修改 PostCSS 的postcss.config.js,增加插件的调用:

// postcss.config.js
const postcssSprites = require('postcss-sprites');

module.exports = {
    plugins: [
        postcssSprites({
            spritePath: './src/assets/img/' // 把合成后的雪碧图放在这个路径下
        })
    ]
};

修改webpack.config.js在css-loader之前配置上postcss-loader(注意 loader 加载顺序,从后往前):

{
    test: /.css$/,
    use: [
        MiniCssExtractPlugin.loader,
        'css-loader',
        {
            loader: 'postcss-loader'
        }
    ]
}

2.5 字体、富媒体文件:对于字体、富媒体等静态资源可以直接使用url-loader或者file-loader进行配置即可,不需要额外的操作。如果不需要 Base64,那么可以直接使用 file-loader,需要的话就是用url-loader,还需要注意,如果将正则(test)放在一起,那么需要使用[ext]配置输出的文件名。

{
    // 文件解析
    test: /.(eot|woff|ttf|woff2|appcache|mp4|pdf)(?|$)/,
    loader: 'file-loader',
    query: {
        // 这么多文件,ext不同,所以需要使用[ext]
        name: 'assets/[name].[hash:7].[ext]'
    }
},

2.6 数据:如果我们项目需要加载的类似 JSON、CSV、TSV 和 XML 等数据,那么我们需要单独给它们配置相应的 loader。对 JSON 的支持实际上是内置的,类似于 Node.js,这意味着import Data from './data.json'导入数据默认情况将起作用。要导入 CSV,TSV 和 XML,可以使用csv-loader和xml-loader。

首先是安装它们的 loader: npm install xml-loader csv-loader --save-dev,然后增加文件 loader 配置如下:

{
    test: /.(csv|tsv)$/,
    use: [
    'csv-loader'
    ]
},
{
    test: /.xml$/,
    use: [
    'xml-loader'
    ]
}

现在可以导入这四种类型的数据中的任何一种(JSON,CSV,TSV,XML),并且导入它的 Data 变量将包含已解析的 JSON 以便于使用。


三、代码实践

3.1 图片loader

3.1.1 新建如下结构新项目文件夹

├── src
│   ├── assets
│   │   └── img
│   │       ├── large.png  # 大图片-超过1
│   │       └── small.png  # 小图片
│   ├── index.css
│   ├── index.html
│   └── index.js  # webpack配置
└── webpack.config1.js

webpack.config1.js

const path = require('path')
module.exports = {
  resolve: {
    alias: {
      '@assets': path.resolve('./src/assets') // 使用别名简化相对路径
    }
  }
}

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>静态资源</title>
</head>
<body class="bg-img">
    <img src="~@assets/img/large.png" width="200" height="80" alt="背景图">
</body>
</html>

index.js

import img from './assets/img/large.png';
import style from './index.css';
console.log('index.js', img, style);

index.css

.bg-img {
    background: url(~@assets/img/small.png) no-repeat;
}

3.1.2 当前文件夹下执行npm init初始化package.json,并下载相关依赖:

npm init
npm install webpack webpack-cli --save-dev
npm install file-loader url-loader --save-dev
npm install style-loader css-loader --save-dev
npm install html-loader html-webpack-plugin --save-dev

3.1.3 完善webpack.config1.js文件:

const path = require('path')
const HTMLPlugin = require('html-webpack-plugin')

module.exports = {
    mode: 'development',
    entry: './src/index.js',
    resolve: {
        alias: {
            '@assets': path.resolve(__dirname, './src/assets')
        }
    },
    module: {
        rules: [
            {
                test: /.html$/,
                use: ['html-loader']
            },
            {
                test: /.css$/,
                use: [
                    'style-loader', 
                    'css-loader'
                ]
            },
            {
                test: /.(png|svg|jpg|gif)$/,
                use: {
                    loader: 'url-loader',
                    options: {
                        limit: 3*1024
                    }
                }
            }
        ]
    },
    plugins: [
        new HTMLPlugin({
            template: './src/index.html'
        })
    ]
}

3.1.4 package.json文件里scripts添加webpck命令:

"scripts": {
    "test": "echo "Error: no test specified" && exit 1",
+    "build1": "webpack --config webpack.config1.js"
  },

3.1.5 执行npm run build1命令(注:期间若报错sh: webpack: command not found,建议尝试npm uninstall webpack再重新下载npm install webpack --save-dev)

8125f12a7a0aae6da81c2a5417f25753.png

69b10a2b618a88c8a6d7c2462d6a0520.png

可以看到1.2MB的large.png因为超过了limit=3*1024所以没有被处理成Base64,其地址被webpack自动替换成了新的路径18d30cbadbf7750aff266ee9376b1401.png。而2KB的small.png则被打包成了Base64路径。

3.2 SVG图片loader

3.2.1 在例3.1工程文件夹的基础上操作,删除dist打包文件夹,新增一个SVG文件并在css文件中使用它。

├── package-lock.json
├── package.json
├── src
│   ├── assets
│   │   ├── img
│   │   │   ├── large.png
│   │   │   └── small.png
│   │   └── smile.svg  # 新增一个svg图片资源
│   ├── index.css  # 在css文件里以background形式用到svg
│   ├── index.html  # 在html文件里以img标签形式用到svg
│   └── index.js
├── webpack.config1.js
└── webpack.config2.js # 新的webpack配置文件

新增3KB的smile.svg文件:

<svg width="128" height="128" style="enable-background:new 0 0 128 128;" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <path d="M63.89,9.64C1.58,9.64,0.1,79.5,0.1,93.33c0,13.83,28.56,25.03,63.79,25.03 c35.24,0,63.79-11.21,63.79-25.03C127.68,79.5,126.21,9.64,63.89,9.64z" style="fill:#FCC21B;"/>
  <g>
    <defs>
      <path id="SVGID_1_" d="M63.89,98.06c23.15,0.05,40.56-12.97,41.19-29.05c-27.24,4.91-55.14,4.91-82.38,0 C23.33,85.09,40.74,98.11,63.89,98.06z"/>
    </defs>
    <use style="overflow:visible;fill:#FFFFFF;" xlink:href="#SVGID_1_"/>
    <clipPath id="SVGID_2_">
      <use style="overflow:visible;" xlink:href="#SVGID_1_"/>
    </clipPath>
    <g style="clip-path:url(#SVGID_2_);">
      <path d="M78.05,108c-1.1,0-2-0.9-2-2V61.07c0-1.1,0.9-2,2-2s2,0.9,2,2V106C80.05,107.1,79.16,108,78.05,108 z" style="fill:#2F2F2F;"/>
    </g>
    <g style="clip-path:url(#SVGID_2_);">
      <path d="M92.21,108c-1.1,0-2-0.9-2-2V61.07c0-1.1,0.9-2,2-2s2,0.9,2,2V106C94.21,107.1,93.32,108,92.21,108 z" style="fill:#2F2F2F;"/>
    </g>
    <g style="clip-path:url(#SVGID_2_);">
      <path d="M63.89,108c-1.1,0-2-0.9-2-2V61.07c0-1.1,0.9-2,2-2s2,0.9,2,2V106 C65.89,107.1,64.99,108,63.89,108z" style="fill:#2F2F2F;"/>
      <path d="M49.72,108c-1.1,0-2-0.9-2-2V61.07c0-1.1,0.9-2,2-2s2,0.9,2,2V106 C51.72,107.1,50.83,108,49.72,108z" style="fill:#2F2F2F;"/>
      <path d="M35.56,108c-1.1,0-2-0.9-2-2V61.07c0-1.1,0.9-2,2-2s2,0.9,2,2V106 C37.56,107.1,36.67,108,35.56,108z" style="fill:#2F2F2F;"/>
    </g>
  </g>
  <path d="M64.01,100.56h-0.25c-24.13,0-42.86-13.52-43.56-31.46c-0.03-0.76,0.29-1.49,0.86-1.98 c0.57-0.5,1.33-0.71,2.08-0.57c26.82,4.84,54.67,4.84,81.5,0c0.75-0.14,1.51,0.08,2.08,0.57c0.57,0.5,0.89,1.23,0.86,1.98 C106.87,87.04,88.14,100.56,64.01,100.56z M63.88,95.56h0.13c19.55,0,35.56-10.1,38.2-23.52c-25.29,4.18-51.36,4.18-76.65,0 c2.64,13.42,18.65,23.52,38.2,23.52H63.88z" style="fill:#2F2F2F;"/>
  <path d="M31.96,54.45c-0.78,1.28-2.44,1.7-3.73,0.93c-1.29-0.77-1.71-2.42-0.96-3.71 c0.18-0.31,4.6-7.62,14.37-7.62c9.78,0,14.2,7.31,14.39,7.62c0.76,1.29,0.32,2.97-0.97,3.73c-0.44,0.26-0.91,0.38-1.39,0.38 c-0.92,0-1.83-0.47-2.34-1.32c-0.13-0.22-3.12-4.96-9.69-4.96C35.07,49.49,32.1,54.24,31.96,54.45z" style="fill:#2F2F2F;"/>
  <path d="M100,55.39c-0.43,0.26-0.91,0.38-1.37,0.38c-0.94,0-1.85-0.49-2.36-1.34 c-0.11-0.2-3.08-4.94-9.66-4.94c-6.69,0-9.66,4.89-9.69,4.94c-0.77,1.29-2.43,1.73-3.73,0.96c-1.29-0.76-1.73-2.44-0.96-3.73 c0.18-0.31,4.6-7.62,14.38-7.62c9.77,0,14.18,7.31,14.36,7.62C101.73,52.96,101.29,54.63,100,55.39z" style="fill:#2F2F2F;"/>
</svg>

index.html改动:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>静态资源</title>
</head>
<body class="bg-img">
    <img src="~@assets/img/large.png" width="200" height="80" alt="背景图">

   + <div class="smile"></div>

   + <img src="~@assets/smile.svg" alt="emoj">
</body>
</html>

index.css改动:

.bg-img {
    background: url(~@assets/img/small.png) no-repeat;
}
+.smile {
+    width: 100px;
+    height: 82px;
+    background: url(~@assets/smile.svg);
+    background-size: 100px 82px;
+}

新增webpack.config2.js文件:

const path = require('path')
const HTMLPlugin = require('html-webpack-plugin')

module.exports = {
    mode: 'development',
    entry: './src/index.js',
    resolve: {
        alias: {
            '@assets': path.resolve(__dirname, './src/assets')
        }
    },
    module: {
        rules: [
            {
                test: /.html$/,
                use: ['html-loader']
            },
            {
                test: /.css$/,
                use: [
                    'style-loader', 
                    'css-loader'
                ]
            },
            {
                test: /.(png|jpg|gif)$/, // 使用了svg-url-loader的.svg文件需要排除掉url-loader的rules
                use: {
                    loader: 'url-loader',
                    options: {
                        limit: 2.5*1024
                    }
                }
            },
            {
                test: /.svg$/,
                loader: 'svg-url-loader',
                options: {
                    // 小于 10kB(10240字节)的内联文件
                    limit: 10 * 1024,
                    // 移除 url 中的引号
                    // (在大多数情况下它们都不是必要的)
                    noquotes: true
                }
            }
        ]
    },
    plugins: [
        new HTMLPlugin({
            template: './src/index.html'
        })
    ]
}

package.json针对新配置文件添加命令:

"scripts": {
    "test": "echo "Error: no test specified" && exit 1",
    "build1": "webpack --config webpack.config1.js",
+    "build2": "webpack --config webpack.config2.js"
  },

注意:使用了svg-url-loader的.svg文件需要排除掉url-loader的rules(原因见原作者https://github.com/bhovhannes/svg-url-loader/issues/28)

03729a0ebcd7a1480a75971ce4ca07f1.png

3.2.2 命令行运行npm run build2得到打包结果:

673567232ae6f3cde93afbf0b265712d.png

aec30f7953aaae2776ba3c45e5f6a798.png

3.3 image-webpack-loader压缩图片

3.3.1 我们先看一下只使用url-loader和file-loader的打包结果:

aaf668b86bf465d07a90b87114142ea8.png

现在我们再使用image-webpack-loader来对图片大小做压缩看看效果:

3.3.2 npm install image-webpack-loader --save-dev安装好后在webpack.config2.js的基础上另写一套使用了image-webpack-loader做图片压缩的webpack配置:

// webpack.config3.js
const path = require('path')
const HTMLPlugin = require('html-webpack-plugin')

module.exports = {
    mode: 'development',
    entry: './src/index.js',
    resolve: {
        alias: {
            '@assets': path.resolve(__dirname, './src/assets')
        }
    },
    module: {
        rules: [
            {
                test: /.html$/,
                use: ['html-loader']
            },
            {
                test: /.css$/,
                use: [
                    'style-loader', 
                    'css-loader'
                ]
            },
            {
                test: /.(gif|png|jpe?g|svg)$/i,
                use: [
                    'file-loader',
                    {
                      loader: 'image-webpack-loader',
                      options: {
                        // optipng.enabled: false will disable optipng
                        optipng: {
                          enabled: true,
                        },
                        pngquant: {
                          quality: [0.65, 0.90],
                          speed: 4
                        }
                      }
                    },
                  ],
              }
        ]
    },
    plugins: [
        new HTMLPlugin({
            template: './src/index.html'
        })
    ]
}

在pakage.json的scripts中加入"build3": "webpack --config webpack.config3.js"命令并执行npm run build3得到打包后的dist文件夹,可以看到图片大小被压缩了:比如原来1.2MB的large.png变成了450KB的58fe00f105867c009b85491e96f302bb.png。

dd0c814cadf0b384995f5f0d40959c3f.png

注:如果执行npm run build3后报错——Module build failed (from ./node_modules/image-webpack-loader/index.js): Error

dfa95d9d7112aa0e0c03efcf1ea945ed.png

则是下载的image-webpack-loader出了问题(因墙的缘故npm源下载可能有问题),此时需要npm uninstall image-webpack-loader再cnpm image-webpack-loader --save-dev(自行设置cnpm淘宝源使用国内网)便可解决问题。(npm config set registry https://registry.npm.taobao.org npm install -g cnpm --registry=https://registry.npm.taobao.org)

c3609fceba2a92ae3943249291ff26b0.png

3.4 postcss-sprites合并雪碧图

3.4.1 在3.3实验的基础上删掉dist目录,新增4张图片用以雪碧图实验:

├── package-lock.json
├── package.json
├── postcss.config.js # 新增postcss配置文件
├── src
│   ├── assets
│   │   ├── img
│   │   │   ├── large.png
│   │   │   ├── small-02.png # 新增图片1
│   │   │   ├── small-03.png # 新增图片2
│   │   │   ├── small-04.png # 新增图片3
│   │   │   ├── small-05.png # 新增图片4
│   │   │   └── small.png
│   │   └── smile.svg
│   ├── index.css
│   ├── index.html # 新增显示内容用到以上新增图片资源
│   ├── index.js
│   ├── sprite.css # html内新增DOM的样式分别设置背景为以上新增资源
│   └── sprite.js # 新增逻辑入口
├── webpack.config1.js
├── webpack.config2.js
├── webpack.config3.js
└── webpack.config4.js # 新增webpack配置

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>静态资源</title>
</head>
<body class="bg-img">
    <img src="~@assets/img/large.png" width="200" height="80" alt="背景图">
    <div class="smile"></div>
    <img src="~@assets/smile.svg" alt="emoj">

+    <div class="bg-img02"></div>
+    <div class="bg-img03"></div>
+    <div class="bg-img04"></div>
+    <div class="bg-img05"></div>
</body>
</html>

sprite.css

.bg-img02 {
    background: url(./assets/img/small-02.png) no-repeat;
}

.bg-img03 {
    background: url(./assets/img/small-03.png) no-repeat;
}

.bg-img04 {
    background: url(./assets/img/small-04.png) no-repeat;
}

.bg-img05 {
    background: url(./assets/img/small-05.png) no-repeat;
}
div {
    width: 160px;
    height: 160px;
    border: 1px solid black;
}

sprite.js

import style from './sprite.css';
console.log(style);

webpack.config4.js

const path = require('path')
const HTMLPlugin = require('html-webpack-plugin')

module.exports = {
    mode: 'development',
    entry: './src/sprite.js',
    resolve: {
        alias: {
            '@assets': path.resolve(__dirname, './src/assets')
        }
    },
    module: {
        rules: [
            {
                test: /.html$/,
                use: ['html-loader']
            },
            {
                test: /.css$/,
                use: [
                    'style-loader', 
                    'css-loader',
                    {
                        loader: 'postcss-loader'
                    }
                ]
            },
            {
                test: /.(png|svg|jpg|gif)$/,
                use: {
                    loader: 'url-loader',
                    options: {
                        limit: 3*1024
                    }
                }
            }
        ]
    },
    plugins: [
        new HTMLPlugin({
            template: './src/index.html'
        })
    ]
}

postcss.config.js

const postcssSprites = require('postcss-sprites')

module.exports = {
    plugins: [
        postcssSprites({
            spritePath: 'dist/sprite/'
        })
    ]
}

package.json

 "scripts": {
    "test": "echo "Error: no test specified" && exit 1",
    "build1": "webpack --config webpack.config1.js",
    "build2": "webpack --config webpack.config2.js",
    "build3": "webpack --config webpack.config3.js",
 +   "build4": "webpack --config webpack.config4.js"
  },

3.4.2 我们先直接在index.html里引入sprite.css看一下不打包前的设计效果:

2f3c101b04ea39ef358f6e8f8da72f8b.png

3.4.3 去掉3.4.2里的<link rel="stylesheet" href="./sprite.css">复原html,安装postcss-sprites :

cnpm install postcss-sprites --save-dev
cnpm install postcss-loader --save-dev

然后命令行执行npm run build4打包:

a12dc25550a9954f7be253879d5aaa4a.png

可以看到postcss-sprites将页面用到的小图片合并到一张大图中并使用background-position自动重新定位:

cdc57057dbed9228b196c27e66a0a477.png

以上代码见github

本文参考引用:

12 使用 Webpack 管理项目中的静态资源-慕课专栏​www.imooc.com Webpack 前端工程化入门​gitbook.cn
6b81462d03f6188b89985dd895cfd454.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值