天天看點

Webpack 開發工具與子產品熱替換Webpack 開發工具與子產品熱替換Webpack 系列教程

Webpack 開發工具與子產品熱替換

​️ 注意:

永遠不要在生産環境中使用這些工具,永遠不要。

devtool

當 JavaScript 異常抛出時,你常會想知道這個錯誤發生在哪個檔案的哪一行。然而因為 webpack 将檔案輸出為一個或多個 bundle,是以 追蹤這一錯誤會很不友善。

Source maps 試圖解決這一問題。它有很多選擇,各有優劣:

build rebuild production quality
eval +++ no generated code
cheap-eval-source-map + ++ transformed code (lines only)
cheap-source-map o yes
cheap-module-eval-source-map original source (lines only)
cheap-module-source-map -
eval-source-map -- original source
source-map
nosources-source-map without source content

+

 表示較快,

-

 表示較慢,

o

 表示時間相同

對于開發環境,通常希望更快速的 Source Map,需要添加到 bundle 中以增加體積為代價,但是對于生産環境,則希望更精準的 Source Map,需要從 bundle 中分離并獨立存在。

個人建議:開發環境使用

cheap-module-eval-source-map

;開發環境使用

cheap-module-source-map

使用方式非常簡單,在

webpack.config.js

中配置如下:

module.exports = {
  // 通過在浏覽器調試工具(browser devtools)中添加元資訊(meta info)增強調試
  // devtool: "eval", // 沒有子產品映射,而是命名子產品。以犧牲細節達到最快。
  // devtool: "source-map", // 犧牲了建構速度的 `source-map' 是最詳細的
  // devtool: "inline-source-map", // 嵌入到源檔案中
  // devtool: "eval-source-map", // 将 SourceMap 嵌入到每個子產品中
  // devtool: "hidden-source-map", // SourceMap 不在源檔案中引用
  // devtool: "cheap-source-map", // 沒有子產品映射(module mappings)的 SourceMap 低級變體(cheap-variant)
  // devtool: "cheap-module-source-map", // 有子產品映射(module mappings)的 SourceMap 低級變體
  devtool: "cheap-module-eval-source-map",
};           

webpack-dev-server

webpack-dev-server 可以提供了一個伺服器和實時重載(live reloading) 功能。

在開始前,确定你有一個 

index.html

 檔案指向你的 bundle。假設 

output.filename

 是 

bunlde.js

<html>
<body>
<script type="text/javascript" src="./dist/bundle.js"></script>
</body>
</html>           

首先從 npm 安裝 

webpack-dev-server

$ npm install --save-dev webpack-dev-server           

安裝完成之後,你應該可以使用 

webpack-dev-server

 了,方式如下:

$ webpack-dev-server --open           

上述指令應該自動在浏覽器中打開 

http://localhost:8080

​ 提示:

本教程中的

示例代碼 除了

demo00

,都可以使用 webpack-dev-server 指令啟動服務。

在你的檔案中做一點更改并且儲存。你應該可以在控制台中看到正在編譯。編譯完成之後,頁面應該會重新整理。如果控制台中什麼都沒發生,你可能需要調整下 

watchOptions

預設情況下 webpack 會使用inline mode(内聯模式)。這種模式在你的 bundle 中注入用戶端(用來 live reloading 和展示建構錯誤)。Inline 模式下,你會在你的 DevTools 控制台中看到建構錯誤。

webpack-dev-server 可以做很多事情,比如轉發請求到你的後端伺服器。

webpack-dev-server 支援很多 cli 參數,來手動配置服務的選項。

但是,個人建議,一種更好的做法是在

webpack.config.js

檔案中通過配置

devServer

屬性來配置 webpack-dev-server 。

更多配置項參考:

官方文檔 - 開發中 Server(DevServer)
​ 示例DEMO12: ( DEMO / SOURCE

)

在本示例中,devServer 配置如下:

devServer: {
  contentBase: [path.join(__dirname, "dist")],
  compress: true,
  port: 9000, // 啟動端口号
  inline: true,
}           
執行 webpack-dev-server 後,會啟動一個端口為 9000 的本地服務。

熱子產品替換(Hot Module Replacement)

​​ 提示:

子產品熱替換功能一般用于開發環境。

現在你有了實時重載功能,你甚至可以更進一步:Hot Module Replacement(熱子產品替換)。這是一個接口,使得你可以替換子產品而不需要重新整理頁面。不用每次修改都重新啟動服務,這可以極大地提高開發效率。

那麼,如何配置 webpack 來實作熱替換呢?

請按以下步驟一步步來:

首先,安裝依賴  

react-hot-loader

(確定使用這個包的 

next

 版本)

$ npm install --save babel-loader react-hot-loader@next           

配置 entry

你需要定義幾個用于熱替換的入口路徑

entry: {
  main: [
    // App 入口
    "./app/index",

    // 開啟 React 代碼的子產品熱替換(HMR)
    'react-hot-loader/patch',

    // 為 webpack-dev-server 的環境打包代碼
    // 然後連接配接到指定伺服器域名與端口
    'webpack-dev-server/client?http://localhost:9000',

    // 為熱替換(HMR)打包好代碼
    // only- 意味着隻有成功更新運作代碼才會執行熱替換(HMR)
    'webpack/hot/only-dev-server',
  ],
},           

配置 output

publicPath

對于熱替換(HMR)是必須的,讓 webpack 知道在哪裡載入熱更新的子產品(chunk)

output: {
  ... ...
  // 對于熱替換(HMR)是必須的,讓 webpack 知道在哪裡載入熱更新的子產品(chunk)
  publicPath: "/"
},           

配置 module

需要使用 ES2015 子產品來使 HMR 正常工作。為此,在我們的 es2015 preset 設定中,将 

module

 選項設定為 false。

并且,在此要引入

react-hot-loader/babel

開啟 React 代碼的子產品熱替換(HMR)

module: {

    rules: [
      {
        // 語義解釋器,将 js/jsx 檔案中的 es2015/react 文法自動轉為浏覽器可識别的 Javascript 文法
        test: /\.jsx?$/,
        include: path.resolve(__dirname, "app"),
        exclude: /node_modules/,

        // 應該應用的 loader,它相對上下文解析
        // 為了更清晰,`-loader` 字尾在 webpack 2 中不再是可選的
        // 檢視 webpack 1 更新指南。
        loader: "babel-loader",

        // loader 的可選項
        options: {
          presets: [
            // webpack 現在已經支援原生的 import 語句了, 并且将其運用在 tree-shaking 特性上
            [
              "es2015",
              {
                "modules": false
              }
            ],

            "react" // 轉譯 React 元件為 JavaScript 代碼
          ],
          plugins: [
            "react-hot-loader/babel" // 開啟 React 代碼的子產品熱替換(HMR)
          ]
        },
      },
    ]
  },           

配置 devServer

此處,也需要引入

publicPath

,且和上文

output

publicPath

值保持一緻。

hot

屬性需要置為 true,表示開啟伺服器的子產品熱替換。

devServer: {
  contentBase: [path.join(__dirname, "dist")],
  compress: true,
  port: 9000, // 啟動端口号
  hot: true, // 啟用 webpack 的子產品熱替換特性
  inline: true,
  publicPath: "/", // 和上文 output 的“publicPath”值保持一緻
}           

配置 plugins

最後,需要開啟 webpack 自帶的

HotModuleReplacementPlugin

NamedModulesPlugin

插件,啟動熱替換功能。

plugins: [
  // 開啟全局的子產品熱替換(HMR)
  new webpack.HotModuleReplacementPlugin(),

  // 當子產品熱替換(HMR)時在浏覽器控制台輸出對使用者更友好的子產品名字資訊
  new webpack.NamedModulesPlugin(),
],           
​ 示例DEMO13: ( 在示例中,啟動服務後,打開浏覽器,通路 http://localhost:9000/ 按快捷鍵

F12

打開浏覽器調試視窗,可以看到類似提示資訊
[HMR] Waiting for update signal from WDS...
[HMR] Waiting for update signal from WDS...
[WDS] Hot Module Replacement enabled.           

這表示熱替換功能已啟動。

修改

app/index.jsx

檔案,來看看熱替換的效果:

修改前:

ReactDOM.render(
  <Welcome name="Victor Zhang"/>,
  document.getElementById("root")
);           
修改後:
ReactDOM.render(
  <Welcome name="guest"/>,
  document.getElementById("root")
);           
此時,應該看到頁面内容會替換為你修改的内容。

Webpack 系列教程

歡迎閱讀其它内容:

繼續閱讀