街撮りchの中のひとのブログ

webpack+spritesmithでページの高速化、複数のスプライト画像とRetina対応について

目次

webpack-spritesmithで複数のスプライト画像を作るってどうやるのか今ひとつわからなくてやってみたやり方の紹介。
やってみたら単純なことですね。SpritesmithPluginをnewしてpluginに複数設定してやればいい。

元となる画像をディレクトリわけて配置してそれぞれのディレクトリからスプライト画像を作る。
わける基準は例えばスプライト化した画像を最適化(減色をする)場合なんかは色味でわけると減色効率がよかったりする。
赤系は赤系だけでスプライト化するとかね。

ファイル構成はこんな感じ。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
├── app
│   ├── images
│   │   ├── sprite01.png
│   │   └── sprite02.png
│   └── styles
│   └── bundle.css
├── node_modules
├── package.json
├── src
│   ├── images
│   │   ├── sprite_assets01
│   │   │   ├── sprite01.png
│   │   │   ├── sprite02.png
│   │   │   └── sprite03.png
│   │   └── sprite_assets02
│   │   ├── sprite04.png
│   │   ├── sprite05.png
│   │   └── sprite06.png
│   └── scss
│   ├── _sprite01.scss
│   ├── _sprite02.scss
│   └── style.scss
└── webpack.config.js

package.jsonの中はこんな感じ。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
"name": "01",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"start": "webpack -w --config webpack.config.js"
},
"repository": {},
"license": "MIT",
"devDependencies": {
"browser-sync": "^2.18.6",
"browser-sync-webpack-plugin": "^1.1.3",
"css-loader": "^0.26.1",
"extract-text-webpack-plugin": "^1.0.1",
"node-sass": "^4.4.0",
"path": "^0.12.7",
"sass-loader": "^4.1.1",
"style-loader": "^0.13.1",
"webpack": "^1.14.0",
"webpack-spritesmith": "^0.3.1"
}
}

スプライト化する画像をこの場合は「sprite_assets01」と「sprite_assets02」にわけてる。 このディレクトリ内の画像がそれぞれsprite01.pngっていう名前でスプライト画像として出力されて、
scssも「_sprite01.scss」と「_sprite02.scss」っていう名前で出力される。

1
2
@import 'sprite01';
@import 'sprite02';

以下がwebpack.config.jsです。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
var path = require('path');
var webpack = require('webpack');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var BrowserSyncPlugin = require('browser-sync-webpack-plugin');
var SpritesmithPlugin = require('webpack-spritesmith');

module.exports = {
entry: {
application: './src/scss/style.scss'
},
output: {
path: './app/styles',
filename: 'bundle.css'
},
module: {
loaders: [
{
test: /\.css|scss$/,
loader: ExtractTextPlugin.extract('style-loader', 'css-loader?minimize!sass-loader')
},
{
test: /\.png$/,
loaders: ['file?name=i/[hash].[ext]']
}
]
},
resolve: {
modulesDirectories: ['web_modules', 'node_modules', 'sprite_assets']
},
plugins: [
new ExtractTextPlugin('bundle.css'),
new BrowserSyncPlugin(
{
host: 'localhost',
port: 8081,
server: { baseDir: ['public'] }
}
),
new SpritesmithPlugin({
src: {
cwd: './src/images/sprite_assets01/',
glob: '*.png'
},
target: {
image: './app/images/sprite01.png',
css: './src/scss/_sprite01.scss'
},
apiOptions: {
cssImageRef: '/images/sprite01.png'
}
}),
new SpritesmithPlugin({
src: {
cwd: './src/images/sprite_assets02/',
glob: '*.png'
},
target: {
image: './app/images/sprite02.png',
css: './src/scss/_sprite02.scss'
},
apiOptions: {
cssImageRef: '/images/sprite02.png'
}
})
]
}

同系色を同じスプライトにした方が良いよってのもあるけど、Retina対応の画像と普通の画像って感じにわけてもいい。 Retina対応なんだけどスプライト画像といっしょに出力されるScssにはmixinも含まれるんだけどRetina対応じゃなかったりする。 で以下がデフォルトで出力されるScssのmixin。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
@mixin sprite-width($sprite) {
width: nth($sprite, 5);
}

@mixin sprite-height($sprite) {
height: nth($sprite, 6);
}

@mixin sprite-position($sprite) {
$sprite-offset-x: nth($sprite, 3);
$sprite-offset-y: nth($sprite, 4);
background-position: $sprite-offset-x $sprite-offset-y;
}

@mixin sprite-image($sprite) {
$sprite-image: nth($sprite, 9);
background-image: url(#{$sprite-image});
}

@mixin sprite($sprite) {
@include sprite-image($sprite);
@include sprite-position($sprite);
@include sprite-width($sprite);
@include sprite-height($sprite);
}

@mixin sprites($sprites) {
@each $sprite in $sprites {
$sprite-name: nth($sprite, 10);
.#{$sprite-name} {
@include sprite($sprite);
}
}
}

これだとRetina用に書き出した2倍のサイズの画像だと変になる。 背景画像のサイズを半分にして位置も半分にするmixinを追加するといい。 出力されたScssに記述すると書き換えられるたびに追記しないといけないので自分で作ったScssに追記するのをおすすめする。

1
2
3
4
5
6
7
8
9
10
11
12
13
@mixin sprite-position-2x($sprite) {
$sprite-offset-x: nth($sprite, 3) / 2;
$sprite-offset-y: nth($sprite, 4) / 2;
background-position: $sprite-offset-x $sprite-offset-y;
}

@mixin sprite-2x($sprite) {
@include sprite-image($sprite);
@include sprite-position-2x($sprite);
@include sprite-width($sprite);
@include sprite-height($sprite);
background-size: $spritesheet-width / 2 auto;
}

いつもvブログを読んでいただきありがとうございます。
YouTubeチャンネルの運用を続けていくために機材購入、資料購入などで困っております。
よろしければAmazonの欲しいものリストから応援いただけると助かります。

街撮りchの欲しいものリスト

管理人:タケグチシゲキ

フロントエンドエンジニアとして働く55歳のジジイです。
首都圏を中心に散歩動画を撮影してYouTubeで配信してます。現在は夜の街のネオンや光が作り出す陰影が好きで撮影することが多いです。

YouTbueチャンネル

YouTubeチャンネルもぜひご覧ください。思い出の街や気になる街の風景を楽しんでいただければと思います

X(旧Twiiter)

X(旧Twiiter)でも情報発信しております。よろしければフォローいただけると嬉しいです

記事や動画について知っている情報を教えていただけると幸いです。どんなささいなことでも大丈夫です。

また、仕事依頼、コラボ依頼、著作物の提供などについてのお問い合わせは下記のお問い合わせフォーム、X(旧Twiiter)のDMでお待ちしております

お問い合わせ

ブログ記事やYouTubeチャンネルの動画に関するコメント、お仕事依頼、コラボ依頼、著作物の提供についてなどなどお問い合わせにて随時募集中です。
情報提供などもお待ちしております。

お問い合わせはこちらのGoogleフォームからお願いいたします