在 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/

相关文章
相关标签/搜索