在 Electron 中使用模塊熱替換

Electron + React + Webpack 這個組合開發桌面應用仍是挺爽的。html

若是再搭上 WebpackHot Module Replacement 那簡直完美,不用刷新就搞定。react

關於 HMR 的演示能夠看 Dan Abramov 的演講視頻 Hot Reloading with Time Travelwebpack

Electron 中使用 HMR 碰到的問題是打開的文件是本地的,host 就變成了 file://git

因此監聽到變化以後,Webpack 嘗試更新模塊時,就查找不到 hot-update.json ,而後 Webpack 沒法更新模塊...github

當時這個問題搞瘋了我,花了很長時間,因此這篇就是爲了記錄下當時的坑。web

上圖出現的狀況,當時用的配置就是使用的比較官方的方式, 使用 webpack-dev-serverreact-hot-loaderexpress

import path from 'path'
import webpack from 'webpack'

module.exports = {
  devtool: 'eval',
  entry: [
    'webpack-dev-server/client?http://localhost:3000',
    'webpack/hot/only-dev-server',
    './src/index'
  ],
  output: {
    path: path.join(__dirname, 'dist'),
    filename: 'bundle.js',
    publicPath: '/static/'
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin()
  ],
  module: {
    loaders: [{
      test: /\.js$/,
      loaders: ['react-hot', 'babel'],
      include: path.join(__dirname, 'src')
    }]
  }
}

而後換成 React Hot Loader 3 試了一下,果真不出所料,仍是沒能成功。json

本來覺得問題就是出在 webpack-dev-server 上,因此就把精力集中在替換 webpack-dev-server 上了。babel

而後用 express + webpack-dev-middleware + webpack-hot-middleware 本身搭建服務。app

'use strict'

import express from 'express'
import webpack from 'webpack'
import webpackDevMiddleware from 'webpack-dev-middleware'
import webpackHotMiddleware from 'webpack-hot-middleware'

import config from './webpack.config.dev'

const app = express()
const compiler = webpack(config)
const PORT = 3000

app.use(webpackDevMiddleware(compiler, {
  publicPath: config.output.publicPath,
  noInfo: false,
  reload: true,
  stats: {
    colors: true
  }
}))

// hot
app.use(webpackHotMiddleware(compiler))

app.listen(PORT, 'localhost', (err) => {
  if (err) {
    console.error(err)
    return
  }
  console.log(`Listening at http://localhost:${PORT}`)
})

然而仍是不行, 最後研究了這個倉庫的配置
發現還有這樣的一個配置 target: 'electron-renderer',然而官方文檔上卻沒有說明。

Note: target: 'electron-renderer' 屬性是在 Webpack v1.12.15 版本中加入的 make electron-main and electron-renderer targets works in 1.x

爲了不更多人步我後塵,就去給 Webpack 文檔增長了說明 Compare: configuration

這時候熱替換的問題也就解決了,這個過程還能從提交歷史中看到 PupaFM

But...

當後來有時間再回顧這個問題的時候,一直在想第一種方式應該能解決纔對啊,
因此在第一種方式的配置上加了 target: 'electron-renderer',然而並無什麼軟用...

最後再一次查看了一遍 Webpack 的文檔,仔細的看了 output.publicPath 這個配置。

output.publicPath

The publicPath specifies the public URL address of the output files when referenced in a browser.

For loaders that embed <script> or <link> tags or reference assets like images,
publicPath is used as the href or url() to the file when it’s different then their location on disk (as specified by path).
This can be helpful when you want to host some or all output files on a different domain or on a CDN.
The Webpack Dev Server also takes a hint from publicPath using it to determine where to serve the output files from.
As with path you can use the [hash] substitution for a better caching profile.

那我是否是隻要把相對路徑改爲絕對地址,就能夠監聽到文件的更新了。

只要這樣就行了嘛 publicPath: 'http://localhost:3000/static/'...

而後寫了個 demo ,具體代碼可參考 Electron React Hot Boilerplate

果真...

仍是須要好好閱讀完文檔啊,雖然 Webpack 的文檔也略坑。

原文連接 http://xwartz.github.io/pupa/2016/06/electron-with-hmr/

相關文章
相關標籤/搜索