Electron
+ React
+ Webpack
这个组合开发桌面应用仍是挺爽的。html
若是再搭上 Webpack
的 Hot Module Replacement 那简直完美,不用刷新就搞定。react
关于 HMR
的演示能够看 Dan Abramov 的演讲视频 Hot Reloading with Time Travel。webpack
在 Electron
中使用 HMR
碰到的问题是打开的文件是本地的,host
就变成了 file://
,git
因此监听到变化以后,Webpack
尝试更新模块时,就查找不到 hot-update.json
,而后 Webpack
没法更新模块...github
当时这个问题搞疯了我,花了很长时间,因此这篇就是为了记录下当时的坑。web
上图出现的状况,当时用的配置就是使用的比较官方的方式, 使用 webpack-dev-server
和 react-hot-loader
。express
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
这个配置。
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/