一、背景問題
項目中如果有大量的小圖標,如果不使用阿里的iconfont。UI給一個加一個,加一個引用一個,每個圖標雖然很小,但是也是一次請求,每次請求都是消耗性能資源的.
二、解決思路
使用webpack-spritesmith可以將所有的icon小圖標整合成一張圖片。每次都只會請求一次,同時還能自動生成定位樣式,對於都是同尺寸的小圖標,直接可以使用。
三、廢話少說,直接來code
1、我是使用vue-cli3配置這個webapck的插件的。如果使用cli2的網上也很多,自行查找
2、查閱資料:(npm官網 github的readme)
3、來來。配置走起。
(1)假裝你的vue-cli3腳手架已經搭建起來了,在項目根目錄,新建一個vue.config.js的文件(webpack就是在這里配置。cli3不建議修改webapck,但是如果需要修改,在這里可以覆蓋默認的配置)
(2)npm install webpack-spritesmith --save
(3)在vue.config.js里面寫東西啊
const path = require('path') //引入node模塊,一會要操作文件,輸入,生成,輸出都需要這玩意。 const SpritesmithPlugin = require('webpack-spritesmith'); // 主角,必須引入。要不然咋用 /* 這里是我們自己修改的模板樣式,webpack,會自動生成一個sprite.css的樣式,有時候生成的不滿意, 我們可以在這里修改,可以自己打印一下 data里面的參數,看着就會大概明白(先看下面的配置,最后看這個模板) */ var templateFunction = function (data) { var shared = '.icon { background-image: url(I);background-size: Wpx Hpx;}'.replace('I', data.sprites[0].image).replace('W', data.spritesheet.width) .replace('H', data.spritesheet.height) var perSprite = data.sprites.map(function (sprite) { return '.icon-N { width: Wpx; height: Hpx; background-position: Xpx Ypx; }' .replace('N', sprite.name) .replace('W', sprite.width) .replace('H', sprite.height) .replace('X', sprite.offset_x) .replace('Y', sprite.offset_y); }).join('\n'); return shared + '\n' + perSprite; }; // 所有的配置都在這個導出里面 module.exports = { // webpack的配置入口可以打印這個config。可以看到webpack的配置項 configureWebpack: config => { /* 細節坑。文檔里面寫着 需要resolve,引入圖片生成的位置, 不加這行會報錯。因為github,Readme里面有這句話 resolve contains location of where generated image is (要把生成的地址resolve到modules里面。不寫就錯) 一定要加,血的教訓啊 */ config.resolve.modules = ['node_modules', './src/assets/images'] // 定義一個插件數組。用來覆蓋,在里面使用我們的主角 const Plugins = [ new SpritesmithPlugin({ /* 目標小圖標,這里就是你需要整合的小圖片的老巢。 現在是一個個的散兵,把他們位置找到,合成一個 */ src: { cwd: path.resolve(__dirname, './src/assets/icon'), glob: '*.png' }, // 輸出雪碧圖文件及樣式文件,這個是打包后,自動生成的雪碧圖和樣式,自己配置想生成去哪里就去哪里 target: { image: path.resolve(__dirname, './src/assets/images/sprite.png'), css: [ [path.resolve(__dirname, './src/assets/css/sprite.scss'), { // 引用自己的模板 format: 'function_based_template' }], ] }, // 自定義模板入口,我們需要基本的修改webapck生成的樣式,上面的大函數就是我們修改的模板 customTemplates: { 'function_based_template': templateFunction, }, // 樣式文件中調用雪碧圖地址寫法(Readme這么寫的) apiOptions: { cssImageRef: '~sprite.png' }, // 讓合成的每個圖片有一定的距離,否則就會緊挨着,不好使用 spritesmithOptions: { padding: 20 } }) ] // config里面,覆蓋掉以前的,要不然不好使 config.plugins = [...config.plugins, ...Plugins] } }
四、組件里面怎么使用
1.根據你的配置。重新npm run serve以后。會在你配置的文件 里面生成合成圖sprite.png 和 sprite.css(或者其他格式)
2.在sprite.css里面已經通過webpack的機制,引入了sprite.png,所以組件里面直接在style部分直接@import'../xx/sprite/.css'就可以了
3.根據模板的要求,我們在html使用
<span class="icon icon-每個小圖的名字"></sapn>
五、幾個問題
1.css模板配置(就是最上面的大函數),webapck自己官方代碼 全是最基礎的。沒有background-size的設置,這樣生成的圖大小是沒有規定尺寸的。所以引用顯示會很有問題 。所以我在后邊加了replace('W', data.spritesheet.width) .replace('H', data.spritesheet.height)
var templateFunction = function (data) { var shared = '.icon { background-image: url(I);background-size: Wpx Hpx;}'.replace('I', data.sprites[0].image) .replace('W', data.spritesheet.width) .replace('H', data.spritesheet.height)
這樣這個合成的大圖尺寸就固定了,小圖定位就很准確, 里面所有不清楚的參數,打印data,看一下就明白了
2.這句代碼。在cli2 里面很好找,cli3里面因為我對webpack的把不熟悉,打印了config才找到,才加上。找不到的配置,就打印config,
config.resolve.modules = ['node_modules', './src/assets/images']
3.在組建里面使用,前兩個是固定寫法,否則不生效,最后可以繼續定義樣式名,修改樣式
<span class="icon icon-小圖名字 自定義名字"></span>