番外篇 - 讓你的 HTML 可以 hot reload

所以,當我測試的時候我才知道 index.html 不會被 hot reload!在之後搜尋的結果,我最後找到了有幫助的答案, 這需要一個 loader 來讓我們 hacky,也需要另一個 plugin 來防止這個 hacky 到 production。

基本上要讓 webpack 可以 hot reload 我們的 HTML,我們需要 require 我們其中檔案之一,讓它變成我們 dependency tree 的一部份。為了做到這一點,我們將會使用 raw-loader loader,它可以 pull 我們的 HTML 變成字串到我們的 JavaScript,但是另外我們真正需要做的是:加入 HTML 到 dependency tree。

所以讓我們加入這個 loader 到我們的 dev 設定檔:

首先我們需要安裝:

npm install --save-dev raw-loader

然我們加入:

// webpack.config.dev.js
var path = require('path')
var webpack = require('webpack')
var HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  devtool: 'cheap-eval-source-map',
  entry: [
    'webpack-dev-server/client?http://localhost:8080',
    'webpack/hot/dev-server',
    './src/index'
  ],
  output: {
    path: path.join(__dirname, 'dist'),
    filename: 'bundle.js'
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin(),
    new HtmlWebpackPlugin({
      template: './src/index.html'
    })
  ],
  module: {
    loaders: [{
      test: /\.css$/,
      loaders: ['style', 'css']
    }, {
      test: /\.html$/,
      loader: "raw-loader" // loaders: ['raw-loader'],這個方式也是可以被接受的。
    }]
  },
  devServer: {
    contentBase: './dist',
    hot: true
  }
}

這個時候當你執行 webpack,如果們 require 一個檔案它的附檔名是 .html,我們將使用 raw-loader loader,加入 HTML 到 bundle。

現在我們目前空的 index.js 檔案內我們可以這麼做。

// index.js
require('./index.html')

如果你現在要檢查 hot reload 是否可以執行,但是你必須要知道我們只是 require index.html 到我們的 index.js,這麼做絕對與 hot reload 無關。我們不想要在 production 使用 hot reload,這就是為什麼我們要使用 DefinePlugin

這個 plugin 讓我們建立一個全域的常數到我們整個 bundle,我們可以命名任何常數,像是:DONT_USE_IN_PRODUCTION: true,但實際上,更普遍的做法會像是 process.env.NODE_ENV: JSON.stringify('production')。為什麼要 JSON.stringify?根據文件的解釋:

如果值是一個字串,它會被作為一個程式碼片段。

現在我們已經了解了,我們可以加入這個 plugin 到我們的 production 設定檔:

// webpack.config.prod.js
var path = require('path')
var webpack = require('webpack')
var HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  devtool: 'source-map',
  entry: ['./src/index'],
  output: {
    path: path.join(__dirname, 'dist'),
    filename: 'bundle.js'
  },
  plugins: [
    new webpack.optimize.UglifyJsPlugin({
      compressor: {
        warnings: false,
      },
    }),
    new webpack.optimize.OccurrenceOrderPlugin(),
    new HtmlWebpackPlugin({
      template: './src/index.html'
    }),
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify('production')
    })
  ],
  module: {
    loaders: [{
      test: /\.css$/,
      loaders: ['style', 'css']
    }]
  }
}

並在我們的 index.js 加入一個條件判斷:

if (process.env.NODE_ENV !== 'production') {
  require('./index.html')
}

解決問題啦!在 production build 中,我們不需要 index.html 作為 dependency tree 的一部份,我們不需要 index.html,這也意味著我們不需要 raw-loader

results matching ""

    No results matching ""