Webpack 是一個 module 整合工具,用來將javascript 打包成一支讓瀏覽器能夠運行的 bundle.js。

看似簡單,但其實功能非常強大

webpack 的功能:

  • 和 Browserify一樣,可以整合 ES Modules, CommonJS 及 AMD modules,減少依賴進而加速了運行的時間
  • 可以將js打包成單一個 bundle.js 或者多個可以非同步載入的模塊(需搭配plugin,可減少初期載入時間)
  • 可結合babel等編譯器,進行文件預編譯功能。例如,將 JSX、ES6、Typescript…轉javascript,Handlebar 字串({{expression}}) 編譯,images 轉 Base64等

此外,還有一些 plugin 可以使用

例如 common-chunks-webpack-plugin - 可以將一些要再多地方共享的模組拆分成獨立的 bundle extract-text-webpack-plugin - 可以將 bundle 中的 CSS 另外存成一支 app.bundle.css html-webpack-plugin - 可用來動態產生HTML內容,並且會自動將打包過的js整合再一起 i18n-webpack-plugin - 可製作多國語系 compression-webpack-plugin - 壓縮內容

【Yarn】

在這裡會使用 yarn 來做套件管理,

因為部分套件npm沒有提供,所以建議先配置好 yarn 環境

yarn 官網安裝教學 https://yarnpkg.com/en/docs/install 在C:/目錄,透過npm 安裝 yarn (建議cmd用管理員權限來執行安裝)

npm install --global yarn

檢查是否安裝成功

yarn --version

【安裝 Webpack 】

首先,安裝webpack 所需要的一些依賴項目

yarn add webpack webpack-dev-server path

這時會建立一個 yarn.lock

繼續,建立一個名稱為 webpack.config.js 的檔案,並輸入內容 webpack.config.js

/*
    ./webpack.config.js
*/
const path = require('path');
module.exports = {
  //entry: Specifies the entry file where the bundler starts the bundling process.
  entry: './client/index.js',
  //output: Specifies the location where the bundled Javascript code is to be saved.
  output: {
    path: path.resolve('dist'),
    filename: 'index_bundle.js'
  },
  module: {
    //loaders: They are transformations that are applied on a file in our app.
    loaders: [
      { test: /\.js$/, loader: 'babel-loader', exclude: /node_modules/ },
      { test: /\.jsx$/, loader: 'babel-loader', exclude: /node_modules/ }
    ]
  }
}

【設定Babel 】

安裝 Babel 以及相關的依賴模組

yarn add babel-loader babel-core babel-preset-es2015 babel-preset-react --dev

建立名稱為 .babelrc 的檔案,並輸入內容 .babelrc

/* 
    ./.babelrc
*/  
{
    "presets":[
        "es2015", "react"
    ]
}

Babel可以幫我們處理JSX及ES6,翻譯成瀏覽器看得懂的語法 例如,下面兩段的語法,作用都會相同,但第一種的寫法,會讓我們更容易辨識

const element = (
  <h1 className="greeting">
    Hello, world!
  </h1>
);
const element = React.createElement(
  'h1',
  {className: 'greeting'},
  'Hello, world!'
);

【建立 Clinet 檔案 】

建立一個 client 資料夾,並在資料夾內新增 index.html, index.js

|-- client
     |-- index.html
     |-- index.js
|-- .babelrc
|-- package.json
|-- webpack.config.js
|-- yarn.lock

./client/index.html

/*
    ./client/index.html
    basic html skeleton
*/
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>React App Setup</title>
  </head>
  <body>
    <div id="root">

    </div>
  </body>
</html>

./client/index.js

/*
    ./client/index.js
    which is the webpack entry file
*/
console.log('Hey guys and ladies!!')

【新增 html-webpack-plugin 】

html-webpack-plugin 主要是用來動態產生HTML內容,並且會自動將打包過的js整合再一起 安裝 html-webpack-plugin

yarn add html-webpack-plugin

接著開啟 webpack.config.js,加入新增的擴充,這裡會看到,我們將會把 client/index.html 作為模板 分別加入這些內容:

//html-webpack-plugin
...
const HtmlWebpackPlugin = require('html-webpack-plugin');
const HtmlWebpackPluginConfig = new HtmlWebpackPlugin({
  template: './client/index.html',
  filename: 'index.html',
  inject: 'body'
});
module.exports = {
	...
  // add this line
  plugins: [HtmlWebpackPluginConfig]
}
...

加入完成後,webpack.config.js內容如下: webpack.config.js

/*
    ./webpack.config.js
*/
const path = require('path');
//html-webpack-plugin
const HtmlWebpackPlugin = require('html-webpack-plugin');
const HtmlWebpackPluginConfig = new HtmlWebpackPlugin({
  template: './client/index.html',
  filename: 'index.html',
  inject: 'body'
});

module.exports = {
  //entry: Specifies the entry file where the bundler starts the bundling process.
  entry: './client/index.js',
  //output: Specifies the location where the bundled Javascript code is to be saved.
  output: {
    path: path.resolve('dist'),
    filename: 'index_bundle.js'
  },
  module: {
    //loaders: They are transformations that are applied on a file in our app.
    loaders: [
      { test: /\.js$/, loader: 'babel-loader', exclude: /node_modules/ },
      { test: /\.jsx$/, loader: 'babel-loader', exclude: /node_modules/ }
    ]
  },
  // add this line
  plugins: [HtmlWebpackPluginConfig]
}

【新增啟動及執行】

開啟 package.json,新增一個 script 以及加入 webpack-dev-server

	"scripts": {
    "start": "webpack-dev-server"
  }

新增後的 package.json如下: package.json

{
  "name": "react",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "scripts": {
    "start": "webpack-dev-server"
  },
  "dependencies": {
    "html-webpack-plugin": "^2.30.1",
    "path": "^0.12.7",
    "webpack": "^3.8.1",
    "webpack-dev-server": "^2.9.2"
  },
  "devDependencies": {
    "babel-core": "^6.26.0",
    "babel-loader": "^7.1.2",
    "babel-preset-es2015": "^6.24.1",
    "babel-preset-react": "^6.24.1"
  }
}

【執行 webpack server】

由於剛剛在package script 我們已經將啟動webpack-dev-server的行為設定為名稱 start 因此,只要執行 yarn start 就可以啟動 webpack server

yarn start

啟動完畢後,開啟 localhost:8080 並且開啟開發者模式,查看console.log是否成功輸出 “Hey guys and ladies!!”

【React 淺入門】

接下來,我們準備來安裝React需要的依賴元件

yarn add react react-dom

接著新增一個 JSX 檔案,並且依照Pascal Case 命名規則,將檔名第一字母大寫,副檔名則可以是jsx或js,建議使用 jsx 在 client 資料夾 新增一個 components/App.jsx

|-- client
     |-- components
         |-- App.jsx
     |-- index.html
     |-- index.js
|-- .babelrc
|-- package.json
|-- webpack.config.js
|-- yarn.lock

client/index.html

/*
    ./client/index.html
    basic html skeleton
*/
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>React App Setup</title>
  </head>
  <body>
    <div id="root">

    </div>
  </body>
</html>

client/index.js

/* 
    ./client/index.js
*/
import React from 'react';
import ReactDOM from 'react-dom';
import App from './components/App.jsx';

ReactDOM.render(<App />, document.getElementById('root'));

client/components/App.jsx

/*
    ./client/components/App.jsx
*/
import React from 'react';

export default class App extends React.Component {
  render() {
    return (
     <div style={{textAlign: 'center'}}>
        <h1>Hello World</h1>
      </div>);
  }
}

接著執行 yarn start,迎接第一個 Hello world~

yarn start
## 【參考資源】 本文根據 Joy Warugu 的文章進行整理而成, 文章位置: https://scotch.io/tutorials/setup-a-react-environment-using-webpack-and-babel