阿里云主机折上折
  • 微信号
您当前的位置:网站首页 > 图片/字体等资源优化

图片/字体等资源优化

作者:陈川 阅读数:19761人阅读 分类: 构建工具

图片资源优化

图片通常是前端项目中体积最大的静态资源,优化图片能显著提升页面加载速度。Webpack提供了多种处理图片的loader和插件,帮助我们实现自动化优化。

图片压缩 使用image-webpack-loader可以在构建阶段自动压缩图片:

module.exports = {
  module: {
    rules: [
      {
        test: /\.(jpe?g|png|gif|svg)$/i,
        use: [
          'file-loader',
          {
            loader: 'image-webpack-loader',
            options: {
              mozjpeg: {
                progressive: true,
                quality: 65
              },
              optipng: {
                enabled: false
              },
              pngquant: {
                quality: [0.65, 0.90],
                speed: 4
              },
              gifsicle: {
                interlaced: false
              },
              webp: {
                quality: 75
              }
            }
          }
        ]
      }
    ]
  }
}

Base64编码小图片 对于小于特定尺寸的图片,可以转换为Base64编码内联到代码中:

{
  test: /\.(png|jpg|gif)$/i,
  use: [
    {
      loader: 'url-loader',
      options: {
        limit: 8192, // 8KB以下的图片转为base64
        name: 'images/[name].[hash:8].[ext]'
      }
    }
  ]
}

响应式图片处理 使用responsive-loader生成多尺寸图片:

{
  test: /\.(jpe?g|png|webp)$/i,
  use: [
    {
      loader: 'responsive-loader',
      options: {
        adapter: require('responsive-loader/sharp'),
        sizes: [300, 600, 1200, 2000],
        placeholder: true,
        placeholderSize: 50
      }
    }
  ]
}

字体资源优化

字体文件也是影响页面性能的重要因素,特别是中文字体文件通常体积较大。

字体子集化 使用fontmin-webpack插件提取实际使用的字符:

const FontminPlugin = require('fontmin-webpack');

module.exports = {
  plugins: [
    new FontminPlugin({
      autodetect: true, // 自动提取使用的字符
      glyphs: ['额外需要的字符'], // 手动添加字符
      allowedFilesRegex: null, // 需要处理的字体文件正则
      skippedFilesRegex: null // 跳过的文件正则
    })
  ]
}

WOFF2格式优先 现代浏览器都支持WOFF2格式,它比WOFF有更好的压缩率:

{
  test: /\.(woff|woff2|eot|ttf|otf)$/,
  use: [
    {
      loader: 'file-loader',
      options: {
        name: 'fonts/[name].[hash:8].[ext]',
        publicPath: '../fonts/'
      }
    }
  ]
}

字体加载策略 使用fontfaceobserver实现无样式文本闪现(FOUT)控制:

// CSS中定义字体
@font-face {
  font-family: 'MyFont';
  src: url('myfont.woff2') format('woff2');
  font-display: swap;
}

// JavaScript中控制加载
const font = new FontFaceObserver('MyFont');
font.load().then(() => {
  document.documentElement.classList.add('fonts-loaded');
});

雪碧图生成

将小图标合并为雪碧图可以减少HTTP请求:

const SpritesmithPlugin = require('webpack-spritesmith');

module.exports = {
  plugins: [
    new SpritesmithPlugin({
      src: {
        cwd: path.resolve(__dirname, 'src/icons'),
        glob: '*.png'
      },
      target: {
        image: path.resolve(__dirname, 'src/assets/sprite.png'),
        css: path.resolve(__dirname, 'src/assets/sprite.css')
      },
      apiOptions: {
        cssImageRef: '../assets/sprite.png'
      }
    })
  ]
}

SVG优化

SVG作为矢量图形,可以通过多种方式优化:

SVG压缩 使用svgo-loader自动优化SVG:

{
  test: /\.svg$/,
  use: [
    {
      loader: 'svg-url-loader',
      options: {
        limit: 8192,
        encoding: 'base64'
      }
    },
    'svgo-loader'
  ]
}

SVG Sprite 将多个SVG合并为一个Sprite:

const SpriteLoaderPlugin = require('svg-sprite-loader/plugin');

module.exports = {
  module: {
    rules: [
      {
        test: /\.svg$/,
        use: [
          {
            loader: 'svg-sprite-loader',
            options: {
              extract: true,
              spriteFilename: 'sprite.svg'
            }
          }
        ]
      }
    ]
  },
  plugins: [
    new SpriteLoaderPlugin()
  ]
}

资源缓存策略

利用Webpack的hash机制实现长期缓存:

module.exports = {
  output: {
    filename: '[name].[contenthash:8].js',
    chunkFilename: '[name].[contenthash:8].chunk.js'
  },
  module: {
    rules: [
      {
        test: /\.(png|jpe?g|gif|svg|woff2?|eot|ttf|otf)$/,
        use: [
          {
            loader: 'file-loader',
            options: {
              name: '[name].[contenthash:8].[ext]'
            }
          }
        ]
      }
    ]
  }
}

按需加载非关键资源

使用Webpack的动态导入延迟加载非关键资源:

// 图片懒加载
const lazyImage = document.createElement('img');
import(/* webpackPrefetch: true */ './images/hero.jpg').then(src => {
  lazyImage.src = src;
});

// 字体延迟加载
window.addEventListener('load', () => {
  import(/* webpackPreload: true */ './fonts/noto-sans-sc.woff2');
});

资源预加载提示

使用preload-webpack-plugin添加资源预加载提示:

const PreloadWebpackPlugin = require('preload-webpack-plugin');

module.exports = {
  plugins: [
    new PreloadWebpackPlugin({
      rel: 'preload',
      include: 'allAssets',
      fileWhitelist: [/\.woff2/],
      as(entry) {
        if (/\.woff2$/.test(entry)) return 'font';
      }
    })
  ]
}

现代格式支持

使用新一代图片格式如WebP:

const ImageminWebpWebpackPlugin = require('imagemin-webp-webpack-plugin');

module.exports = {
  plugins: [
    new ImageminWebpWebpackPlugin({
      config: [{
        test: /\.(jpe?g|png)/,
        options: {
          quality: 75
        }
      }],
      overrideExtension: true,
      detailedLogs: true
    })
  ]
}

资源内联决策

合理选择需要内联的资源:

const HtmlWebpackPlugin = require('html-webpack-plugin');
const InlineSourceWebpackPlugin = require('inline-source-webpack-plugin');

module.exports = {
  plugins: [
    new HtmlWebpackPlugin(),
    new InlineSourceWebpackPlugin({
      compress: true,
      rootpath: './src',
      test: [/\.(js|css)$/, /critical\.(css|js)$/]
    })
  ]
}

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

前端川

前端川,陈川的代码茶馆🍵,专治各种不服的Bug退散符💻,日常贩卖秃头警告级的开发心得🛠️,附赠一行代码笑十年的摸鱼宝典🐟,偶尔掉落咖啡杯里泡开的像素级浪漫☕。‌