※こちらは旧サイトです(新サイトはこちら

WebpackでcssとjsをBundleしたメモ

2017-07-03 21:08:24

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

環境

サーバサイドは Django 1.10.5 です

$ 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が出力される予定です

// 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には、まとめたい単位でファイルを列挙し、中身は以下のようになっています

// 共通のエントリポイント
$ 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を使う事にしました)

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'
            },
        ]
    },
    plugins: [
        new webpack.ProvidePlugin({
            $: "jquery",
            jQuery: "jquery",
            "window.jQuery": "jquery"
        }),
        new ExtractTextPlugin("./static/[name]/bundle.css")
    ]
};

実行

project_rootでWebpackを実行します

$ ./node_modules/.bin/webpack -p

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

// 長いので抜粋
$ ./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とか書いてなければ特に問題なさそう)

$ ./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]

        (以下略)