今天要介紹的周邊配備是webpack,通常會拿來和glup、grunt比較,但他們其實可以共存,甚至webpack不只是處理build task,最主要可以處理不同模組化的方式,AMD、CommonJS或ES6 Module。Webpack就是把所有可模組化的靜態資源整合,並且管理開發流程的一套強大的工具。
在webpack中,所有東西都可以視為module(EX:js、images、css),它是一個模組整合工具/模組打包工作,它的特性如下:
它可以把所有的code整合並且分裝,分開有用到的模組,假設你的網站有好幾頁入口(entry),它可以把每頁會用到的code分別打包,也可以把不同頁面會共同使用到的code合併成common code。
在build之前,可以預先處理像SASS/LESS,或是ES6/JSX這種需要預先處理的resource,除了JS也可以整合CSS、images等其他種resource。
支援AMD、CommonJS或ES6 Module方式。
使用前需要用前面我們提到的NPM來安裝webpack:
npm install webpack -g
然後,假設我們在根目錄下有一個開發的main.js,要把它build成bundle.js,我們可以用CLI指令執行build動作,也可以使用webpack.config.js來做設定。
(1) CLI指令
webpack main.js bundle.js
(2) webpack.config.js設定
module.exports = {
	entry: './main.js',
	output: {
		filename: 'bundle.js'
	}
};
當使用webpack.config.js的方式,要執行build的動作,只需要在CLI執行:
webpack
若要自己取config的檔案名稱,可以加上 --config 設定:
webpack --config webpack.config.prod.js
因為webpack功能強大,後面也會介紹到loaders和plugins,所以建議使用webpack.config.js來定義設定檔。
要使用JSX+ES6撰寫React,我們可以靠babel來編譯,所以先安裝babel-loader相關的package。
npm install babel-loader babel-core babel-preset-es2015 babel-preset-react --save-dev
一口氣我們就安裝了4個babel相關package:
然後,回到webpack.config.js設定loaders:
module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js'
  },
  module: {
    loaders: [
      {
        test: /\.js$/,
        loader: 'babel-loader',
        query: {
          presets: ['es2015', 'react']
        }
      }
    ]
  }
};
Webpack允許bundle任何靜態資源,不只是Javascript,像是CSS、images、JSON等,都可以使用loader來bundle,甚至也可以使用Node.js自己寫loader。
通常可以使用下面command來安裝loaders:
npm install xxxx-loader --save-dev
而loaders的寫法,用上面例子來說明:
module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js'
  },
  module: {
    // loaders列出要使用到的loaders array
    loaders: [
      {
        // 用正規表示法,表示babel-loader是用在.js副檔名的檔案
        test: /\.js$/,
        // 使用的loader,也可以只寫'babel'
        loader: 'babel-loader',
        // 提供給loader使用的參數,設定方式也可以寫在loader裡
        // loader: 'babel-loader?presets[]=es2015,presets[]=react'
        query: {
          presets: ['es2015', 'react']
        }
      }
    ]
  }
};
另外,也可以在loader裡面設定
Webpack可以用require的方式來加入css與圖片:
require('./bootstrap.css');
require('./myapp.less');
var img = document.createElement('img');
img.src = require('./logo.png');
當使用CSS(SASS/LESS)的時候,webpack會把style放在標籤裡面,並加到頁面上。而使用圖片時,會使用圖片路徑的URL。所以需要在loaders裡面設定,讓webpack知道用什麼loader來載入這兩種資源:
module.exports = {
  entry: './main.js',
  output: {
    // 產生bundle.js的路徑
    path: './build',
    // 使用require()時,產生URL的路徑,例如:圖片的URL
    publicPath: 'http://mycdn.com/',
    filename: 'bundle.js'
  },
  module: {
    loaders: [
      {
        test: /\.js$/,
        loader: 'babel-loader',
        query: {
          presets: ['es2015', 'react']
        }
      },
      {
        // 指定只處理.less檔案
        test: /\.less$/,
        // 使用!把loader串接在一起,會從最右邊的loader開始compile
        loader: 'style-loader!css-loader!less-loader'
      },
      {
        // 指定只處理.css檔案
        test: /\.css$/,
        // 這邊少了less-loader,因為.css檔不需轉譯LESS
        loader: 'style-loader!css-loader'
      },
      {
        test: /\.(png|jpg)$/,
        // query參數表示當圖片小於8192bytes,就使用inline base64 URLs
        // 剩下超過大小的圖片,就顯示URL
        loader: 'url-loader?limit=8192'
      }
    ]
  }
};
當然使用這幾個loader都需要npm install,以及加上--save-dev,表示寫入devDependencies。
webpack-howto
(這篇有說到更深入的Multiple entrypoints部分,值得一讀)