webpack中如何使用雪碧圖

一、什麼是雪碧圖?

CSS雪碧 即CSS Sprite,也有人叫它CSS精靈,是一種CSS圖像合併技術,該方法是將小圖標和背景圖像合併到一張圖片上,然後利用css的背景定位來顯示需要顯示的圖片部分。

二:爲什麼要用雪碧圖

結合我們公司的需求來說,因爲有很多組件,每個組件下有大概50張圖片,每張圖片是一個請求,也就是發了300多個請求,這樣是很可怕的,所以爲了優化性能,減少http請求,決定採用雪碧圖的形式。

雪碧圖是將你想要的很多張圖片整理成一張圖片,然後通過background-*來進行圖片識別和定位來達到之前的效果。

三:如何使用雪碧圖

雪碧圖在之前有很多方式,如ps之類,現在最佳的方案還是在webpack-spritesmith

我其實對webpack並不是很瞭解,我現在列出使用方法和我在使用webpack時候遇到的問題。

1.安裝

執行命令行npm install --save-dev webpack-spritesmith

2.在webpack.config.js中寫入

 var path = require('path')

 var SpritesmithPlugin = require('webpack-spritesmith')

 //自定義樣式
 var templateFunction = function (data) {
   var shared = '.ico { background-size: TWpx THpx }'
        .replace('TW', data.sprites[0].total_width / 2)
        .replace('TH', data.sprites[0].total_height / 2)

   var perSprite = data.sprites.map(function (sprite) {
       return '&.element-N {\n  width: Wpx;\n  height: Hpx;\n  background-position: Xpx Ypx;\n}'
           .replace('N', sprite.name)
           .replace('W', sprite.width / 2)
           .replace('H', sprite.height / 2)
           .replace('X', sprite.offset_x / 2)
           .replace('Y', sprite.offset_y / 2)
           .replace('TW', sprite.total_width / 2)
           .replace('TH', sprite.total_height / 2)
   }).join('\n')

   return shared + '\n' + perSprite
 }

 module.exports = {
      ...
     module: {
         rules: [
             {test: /\.styl$/, use: [
                 'style-loader',
                 'css-loader',
                 'stylus-loader'
             ]},
             {test: /\.png$/, use: [
                 'file-loader?name=i/[hash].[ext]'
             ]}
         ]
     },
     resolve: {
         modules: ['node_modules', 'spritesmith-generated']
     },
     plugins: [
         new SpritesmithPlugin({
             src: { //引入路徑
                 cwd: path.resolve(__dirname, 'src/images/ios/'),
                 glob: '*.png'
             },
             target: { //輸出路徑
                 image: path.resolve(__dirname, 'src/spritesmith-generated/ios.png'),
                 css: [
                   [path.resolve(__dirname, 'src/spritesmith-generated/sprite-1.css'), {
                       format: 'function_based_template'
                   }],
                   [path.resolve(__dirname, 'src/spritesmith-generated/sprite-2.css'), {
                       format: 'handlebars_based_template'
                   }]
                 ]
             },
             customTemplates: {
               'function_based_template': templateFunction, //自定義輸出什麼樣的css樣式
             },
             apiOptions: {
                 cssImageRef: 'ios.png'
             }
         })
     ]
 }

3.根據地址更改後執行命令

wbpack

其實這樣已經滿足了大部分需求,根據需要將你所在的輸入和輸出地址進行更改即可,可以設置自己想要設置的的css(style-components、styl等),然後直接複製在自己的項目css文件,很有靈活性。

四:需要注意的點

我有的時候指定不同文件下的圖片合成一張雪碧圖,那該如何呢

例如我的需求是:

  • resources
    • ios
      • images
    • ant
      • images
    • ios
      • images
    • ...

翻譯: resources下有幾個文件夾(ios、ant、ios),相對應下面images文件夾放着各自對應的圖片。

需要注意下,它是支持glob

src: { 
  //引入路徑
  cwd: path.resolve(__dirname, 'src/images/ios/'),
  glob: '*.png' //這裏進行更改
},

這裏可以參考在這裏根據需求進行設置http://www.globtester.com/

glob改成

@(wechat|element|ios)/images/*.png

效果

五:更深層次的需求

我其實是想在各自的文件夾下的圖片,生成各自文件夾下的雪碧圖和css,那該如何實現呢,我寫了一部分,還沒有寫完,感覺遇到了技術難點,我呈現出代碼,會繼續優化來實現

var path = require('path')
var SpritesmithPlugin = require('webpack-spritesmith')

var platforms = ['android', 'ant', 'element', 'ios', 'wechat']//, 'windows']

// var url = 'ant'
const TARGET = process.env.TARGET

console.log({ TARGET })

module.exports = [TARGET].map(l => {
  console.log(l)
  const url = l

  const fn = (data) => {
    console.log(url)
    var shared = 'background-size: TWpx THpx\n'
        .replace('TW', data.sprites[0].total_width / 2)
        .replace('TH', data.sprites[0].total_height / 2)

    var perSprite = data.sprites.map(function (sprite) {
        return `&.${url}-N {\n  width: Wpx;\n  height: Hpx;\n  background-position: Xpx Ypx;\n}\n`
            .replace('N', sprite.name)
            .replace('W', sprite.width / 2)
            .replace('H', sprite.height / 2)
            .replace('X', sprite.offset_x / 2)
            .replace('Y', sprite.offset_y / 2)
            .replace('TW', sprite.total_width / 2)
            .replace('TH', sprite.total_height / 2)
    }).join('\n')

    return shared + '\n' + perSprite
  }

  return {
    module: {
        rules: [
            {test: /\.styl$/, use: [
                'style-loader',
                'css-loader',
                'stylus-loader'
            ]},
            {test: /\.png$/, use: [
                'file-loader?name=i/[hash].[ext]'
            ]}
        ]
    },
    entry: {
      [url]: path.join(__dirname, url),
    },
    output: {
      path: path.join(__dirname, '../parsed/', url),
      filename: '[name].css'
    },
    resolve: {
        modules: ['node_modules', 'spritesmith-generated']
    },
    plugins: [
        new SpritesmithPlugin({
            src: {
                cwd: path.resolve(__dirname, 'images/'+url+'/'),
                glob: '*.png' // '@(android|ant|element|ios|wechat|windows)/*.png'
            },
            target: {
                image: path.resolve(__dirname, '../parsed/'+url+'/'+url+'.png'),
                css: [
                    [path.resolve(__dirname, '../parsed/'+url+'/'+url+'.css'), {
                        format: 'function_based_template'
                    }]
                ]
            },
            customTemplates: {
                'function_based_template': fn
            }
        })
    ]
  }
})

以上。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章