基於Webpack的CSS Sprites實現方案,如果直接在html中調用雪碧圖圖標已經很方便,可是實際開發過程可能遇到須要在僞元素中使用雪碧圖,或者須要hover切換另外一個圖標,這種狀況下就沒法在css中直接調用圖標類名。這時,就須要css預處理器,固然不限於stylus,less、sass都是能夠的,本文介紹stylus方案。css
+ node_modules + src // 開發目錄 + css - icon.styl // webpack-spritesmith生成 - index.styl + images - icon.png // webpack-spritesmith生成 + icon ..png ..png + js + main.js + dist // 代碼產出目錄 – index.html + js - main.js + css - index.css + images - icon.png – package.json – package-lock.json - postcss.config.js – webpack.config.js
npm init
{ "name": "cwwebpack", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "start": "webpack --mode development" }, "author": "", "license": "ISC", "devDependencies": { "autoprefixer": "^9.1.2", "clean-webpack-plugin": "^1.0.0", "css-loader": "^1.0.0", "cssnano": "^4.0.5", "file-loader": "^1.1.11", "postcss-loader": "^3.0.0", "stylus": "^0.54.5", "url-loader": "^1.1.1", "webpack": "^4.17.0", "webpack-cli": "^3.1.2", "webpack-spritesmith": "^0.5.4" }, "dependencies": { "mini-css-extract-plugin": "^0.4.1", "stylus-loader": "^3.0.2" } }
npm install
var path = require('path'); const MiniCssExtractPlugin = require("mini-css-extract-plugin"); const CleanWebpackPlugin = require('clean-webpack-plugin'); const SpritesmithPlugin = require('webpack-spritesmith'); var templateFunctionStylPC = function(data) { var sharedRem = '.ico\n display: inline-block\n background-image: url("I")\n' .replace('I', data.sprites[0].image); var perSpriteRem = data.sprites.map(function(sprite) { return '.ico-N\n width: Wpx\n height: Hpx\n background-position: Xpx Ypx' .replace('N', sprite.name.replace(/_/g, '-')) .replace('W', sprite.width) .replace('H', sprite.height) .replace('X', sprite.offset_x) .replace('Y', sprite.offset_y); }).join('\n'); return sharedRem + '\n' + perSpriteRem; }; var templateFunctionStylMobile = function(data) { var sharedRem = '.ico\n display: inline-block\n background-image: url(I)\n background-size: Drem Hrem' .replace('I', data.sprites[0].image) .replace('D', data.sprites[0].total_width / 100) .replace('H', data.sprites[0].total_height / 100); var perSpriteRem = data.sprites.map(function(sprite) { return '.ico-N\n width: Wrem\n height: Hrem\n background-position: Xrem Yrem' .replace('N', sprite.name.replace(/_/g, '-')) .replace('W', sprite.width / 100) .replace('H', sprite.height / 100) .replace('X', sprite.offset_x / 100) .replace('Y', sprite.offset_y / 100); }).join('\n'); return sharedRem + '\n' + perSpriteRem; }; module.exports = { entry: __dirname + "/src/js/main.js", //惟一入口文件 output: { path: __dirname + "/dist/js", //打包後的文件存放的地方 filename: "main.js" //打包後輸出文件的文件名 }, watch: false, //開啓自動編譯 module: { rules: [ { test: /\.styl$/, use: [{ loader: MiniCssExtractPlugin.loader }, { loader: "css-loader" }, { loader: "postcss-loader" }, { loader: "stylus-loader" }] }, { test: /\.(png|svg|jp?g|gif)$/, loader: 'url-loader', options: { limit: 8192, //大於 1KB = 1024B = 8192字節 的圖片正常打包,小於8192字節的圖片以base64的方式引用 name: '../images/[name].[ext]' } } ] }, plugins: [ new CleanWebpackPlugin( ['dist/css', 'dist/images'], //打包前須要清除的文件夾 { root: __dirname, //根目錄 verbose: true, //開啓在控制檯輸出信息 dry: true //關閉刪除文件 } ), new SpritesmithPlugin({ src: { cwd: path.resolve(__dirname, 'src/images/icon'), glob: '*.png' }, target: { image: path.resolve(__dirname, 'src/images/icon.png'), css: [ [path.resolve(__dirname, 'src/css/icon.styl'), { format: 'function_based_template' }] ] }, customTemplates: { 'function_based_template': templateFunctionStylPC }, apiOptions: { cssImageRef: '../images/icon.png' }, spritesmithOptions: { algorithm: 'binary-tree', padding: 2 } }), new MiniCssExtractPlugin({ filename: "../css/index.css", }), ], };
@import "icon.styl"
npm start
.ico display: inline-block background-image: url("../images/icon.png") .ico-btn-android-active width: 147px height: 59px background-position: -370px -250px .ico-btn-android width: 147px height: 59px background-position: -370px -320px
@import "icon.styl" .btn @extend .ico @extend .ico-btn-android &:hover @extend .ico @extend .ico-btn-android-active
npm start //若嫌每次手動打包麻煩的話,能夠在webpack.config.js中開啓自動編譯watch: true
.ico, .btn, .btn:hover { display: inline-block; background-image: url(../images/icon.png); } .ico-btn-android-active, .btn:hover { width: 147px; height: 59px; background-position: -370px -250px; }
expected "indent", got "outdent"html
expected "indent", got "literal ../"node
expected "indent" got "eos"android
清除舊文件webpack
npm operation not permittedweb
或許以上還不是最優方案,但仍在自動化的邊緣反覆試探,在試探的過程當中發現stylus的函數有點好用,配合圖片使用,能夠不用再去測量圖片的寬高,還有其餘特性慢慢摸索吧(ง'-̀'́)งnpm