散らばるasset類(css,js)をまとめたいなぁと思って色々調べてみると、今はWebpackが流行ってるらしいので使ってみた

環境

サーバサイドは Django 1.10.5 です

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ node --version
v8.1.0

$ cat package.json
{
"name": "projectname",
"version": "1.0.0",
"description": "",
"devDependencies": {
"css-loader": "^0.28.4",
"extract-text-webpack-plugin": "^2.1.2",
"file-loader": "^0.11.2",
"style-loader": "^0.18.2",
"url-loader": "^0.5.9",
"webpack": "^2.6.1"
},
"dependencies": {
"jquery": "^1.11.3"
}
}

Webpackについて

以下の記事が参考になりました

ディレクトリ構成

あんまりよく調べず適当に触ってたら何度か右往左往しました 計画は大事

実際のソースコードはこちらにもありますが、簡略化すると以下のような構成で、ルートの/webpackというディレクトリにまとめてます

最終的には、ルートの/staticというディレクトリに、bundleしたjs,cssが出力される予定です

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
// webpackでまとめるファイル
project_root/webpack/
├── common
│   ├── css
│   │   ├── library1.css
│   │   ├── library2.css
│   │   └── library3.css
│   ├── entry.js
│   ├── fonts
│   │   ├── FontAwesome.otf
│   │   ├── fontawesome-webfont.eot
│   │   ├── fontawesome-webfont.svg
│   │   ├── fontawesome-webfont.ttf
│   │   ├── fontawesome-webfont.woff
│   │   └── fontawesome-webfont.woff2
│   └── js
│   ├── jquery.js
│   ├── library1.js
│   ├── library2.js
│   └── library3.js
└── app
└── contact
├── css
│   ├── contact1.css
│   └── contact2.css
├── entry.js
└── js
├── contact1.js
└── contact2.js

// bundle後、出力されるファイル
project_root/static/
├── common
│   ├── bundle.js
│   └── bundle.css
└── app
└── contact
├── bundle.js
└── bundle.css

実際に運用するコンテンツを想定すると、共通のファイル(/webpack/common)と、アプリケーション側のコンテンツ毎のファイル(/webpack/app/**)に分け、こんな感じになると思います

エントリポイント(entry.js)を作成

各第1階層のディレクトリ毎に、「entry.js」という名前のファイルを用意します

各entry.jsには、まとめたい単位でファイルを列挙し、中身は以下のようになっています

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 共通のエントリポイント
$ cat webpack/common/entry.js
require("./js/jquery.js");
require("./js/library1.js");
require("./js/library2.js");
require("./js/library3.js");

require("./css/library1.css");
require("./css/library2.css");
require("./css/library3.css");

// お問い合わせページのエントリポイント
$ cat webpack/app/contact/entry.js
require("./js/contact1.js");
require("./js/contact2.js");

require("./css/contact1.css");
require("./css/contact2.css");

設定ファイル(webpack.config.js)を作る

webpackの設定ファイル(webpack.config.js)を作成します

前述のpackage.jsonの通り、ここでは、extract-text-webpack-pluginと、各loader(style,css,url,file)をInstallしてある前提です

(cssはjsに変換せず、.cssとして出力したかったので、extract-text-webpack-pluginを使う事にしました)

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
var ExtractTextPlugin = require("extract-text-webpack-plugin");
var path = require('path');
var webpack = require('webpack');

module.exports = {
entry: {
"common": path.join(__dirname, "./webpack/common/entry.js"),
"app/contact": path.join(__dirname, "./webpack/app/contact/entry.js"),
},
output: {
filename: "./static/[name]/bundle.js"
},
module: {
loaders: [
{
test: /\.css$/,
loader: ExtractTextPlugin.extract({fallback:'style-loader',use:'css-loader'})
},
{
test: /\.(jpg|gif|png|woff|woff2|eot|ttf|svg)$/,
loader: 'url-loader?limit=100000'
},
]
},
resolve: {
modules: ['./node_modules'],
},
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
"window.jQuery": "jquery"
}),
new ExtractTextPlugin("./static/[name]/bundle.css")
],
performance: { hints: false },
cache: true
};

実行

project_rootでWebpackを実行します

1
$ ./node_modules/.bin/webpack -p

-p--optimize-minimize--define process.env.NODE_ENV="production"のショートカットで、jsの圧縮とかをやってくれます(環境変数はDocker側で管理してるので本記事では未使用)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 長いので抜粋
$ ./node_modules/.bin/webpack --help

webpack 2.6.1

Basic options:
-d shortcut for --debug --devtool eval-cheap-module-source-map
--output-pathinfo [真偽]
-p shortcut for --optimize-minimize --define
process.env.NODE_ENV="production" [真偽]
--progress Print compilation progress in percentage [真偽]

Optimizing options:
--optimize-minimize Minimize javascript and switches loaders to
minimizing [真偽]

実行後はこんな感じになります(文字が赤かったりerrorとか書いてなければ特に問題なさそう)

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
$ ./node_modules/.bin/webpack -p

Hash: 85ae538d885249b17609
Version: webpack 2.6.1
Time: 154723ms
Asset Size Chunks Chunk Names
d7c639084f684d66a1bc66855d193ed8.svg 392 kB [emitted] [big]
1dc35d25e61d819a9c357074014867ab.ttf 153 kB [emitted]
.//static/portfolio/contact/bundle.js 248 kB 0, 1 [emitted] portfolio/contact
.//static/common/bundle.js 246 kB 1 [emitted] common
.//static/common/bundle.css 525 kB 1 [emitted] [big] common
.//static/portfolio/contact/bundle.css 526 kB 0, 1 [emitted] [big] portfolio/contact
[2] ./webpack/common/css/library1.css 41 bytes {0} {1} [built]
[3] ./webpack/common/css/library2.css 41 bytes {0} {1} [built]
[4] ./webpack/common/css/library3.css 41 bytes {0} {1} [built]

(中略)

+ 39 hidden modules
Child extract-text-webpack-plugin:
[0] ./~/css-loader/lib/css-base.js 2.26 kB {0} [built]
[1] ./webpack/common/fonts/fontawesome-webfont.eot 102 kB {0} [built]
[2] ./webpack/common/fonts/fontawesome-webfont.eot?v=4.6.3 102 kB {0} [built]
[3] ./webpack/common/fonts/fontawesome-webfont.svg?v=4.6.3 82 bytes {0} [built]
[4] ./webpack/common/fonts/fontawesome-webfont.ttf?v=4.6.3 82 bytes {0} [built]
[5] ./webpack/common/fonts/fontawesome-webfont.woff2?v=4.6.3 95.9 kB {0} [built]
[6] ./webpack/common/fonts/fontawesome-webfont.woff?v=4.6.3 121 kB {0} [built]
[7] ./~/css-loader!./webpack/common/css/font-awesome.min.css 31.2 kB {0} [built]

(以下略)