在 Electron 中使用模块热替换

在 Electron 中使用模块热替换_第1张图片

Electron + React + Webpack 这个组合开发桌面应用还是挺爽的。

如果再搭上 Webpack 的 Hot Module Replacement 那简直完美,不用刷新就搞定。

关于 HMR 的演示可以看 Dan Abramov 的演讲视频 Hot Reloading with Time Travel。

Electron 中使用 HMR 碰到的问题是打开的文件是本地的,host 就变成了 file://

所以监听到变化之后,Webpack 尝试更新模块时,就查找不到 hot-update.json ,然后 Webpack 无法更新模块...

在 Electron 中使用模块热替换_第2张图片

当时这个问题搞疯了我,花了很长时间,所以这篇就是为了记录下当时的坑。

上图出现的情况,当时用的配置就是使用的比较官方的方式, 使用 webpack-dev-serverreact-hot-loader

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 试了一下,果然不出所料,还是没能成功。

原本以为问题就是出在 webpack-dev-server 上,所以就把精力集中在替换 webpack-dev-server 上了。

然后用 express + webpack-dev-middleware + webpack-hot-middleware 自己搭建服务。

'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

你可能感兴趣的:(在 Electron 中使用模块热替换)