React-hot-loader 不适用于 React-router-dom
React-hot-loader doesn't work with React-router-dom
所以我终于设置了一个工作项目:
电子(2.0.2
)
反应 (16.4.0
)
React-router-dom (4.2.2
)
Webpack (4.11.0
)
React 热加载程序 (4.2.0
)
就在我开始开发一些 React 组件时,我注意到我的项目无法正确热重载。如果我在基础 url (/
) 上调整一些东西,它会正确更新,但如果我在辅助 url 上更新一些东西,比如 /test
webpack 编译,但我收到消息 Cannot GET /test
。
我已经尝试了很多,但我似乎无法弄清楚我做错了什么。我调查了 react-router-dom
,因为热重载在版本 3.x
中是一个问题,但他们说现在应该解决它(在 4.x
--> It works here.. 中)。另外我在我的 index.html
中添加了 <base href="/"/>
所以不是这样。
谁能告诉我我做错了什么?
Webpack.common.js(合并到Webpack.dev.js)
module.exports = {
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].bundle.js'
},
resolve: {
modules: [path.resolve(__dirname), 'node_modules']
},
module: {
rules: [
{
test: /\.jsx?$/,
loader: 'babel-loader',
exclude: /node_modules/,
options: {
cacheDirectory: true,
presets: ['env', 'react'],
plugins: ['transform-runtime'],
env: {
development: {
plugins: ['react-hot-loader/babel']
},
production: {
presets: ['react-optimize']
}
}
}
}
]
}
};
Webpack.dev.js
module.exports = merge(common, {
mode: 'development',
devtool: 'eval-source-map',
entry: {
'app': [
'babel-polyfill',
'react-hot-loader/patch',
path.join(__dirname, 'src', 'index.js')
]
},
plugins: [
new webpack.HotModuleReplacementPlugin() // Enable hot module replacement
]
});
Index.js
import React from "react";
import ReactDOM from "react-dom";
import { AppContainer } from "react-hot-loader";
import { App } from "./app";
const render = Component => {
ReactDOM.render(
<AppContainer>
<Component/>
</AppContainer>,
document.getElementById("root")
);
};
render(App);
if (module.hot) {
module.hot.accept("./app", () => {
render(App);
});
}
App.js(我的应用程序的主要入口点,因此我定义了我的基本路由)
import React, { Component } from 'react';
import { BrowserRouter, Route, NavLink } from 'react-router-dom';
import { Test } from './components/test';
import { Test2 } from './components/test2';
export class App extends Component {
render() {
return (
<BrowserRouter>
<div>
<NavLink to="/">Home</NavLink>
<NavLink to="/test">Test</NavLink>
<div>
<Route exact path="/" component={Test}/>
<Route path="/test" component={Test2}/>
</div>
</div>
</BrowserRouter>
);
}
}
组件 'test' 和 'test2' 只是带有 'hello world' 文本的简单反应组件。
有人看到我遗漏或做错了什么吗?
感谢 this tutorial 我找到了一种方法来调整我的项目并让热加载工作。它甚至让我的代码更简洁,我的构建脚本更简单。
Webpack.common.js
我需要更改的第一件事是 babel-loader。我从一些教程中偷了它,它起作用了,但我不知道它到底做了什么,所以我去掉了那个代码。我还通过 webpack.DllReferencePlugin
.
加快了代码的编译速度
这是更新后的 webpack.common.js:
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const AddAssetHtmlPlugin = require('add-asset-html-webpack-plugin');
module.exports = {
entry: {
app: [
'babel-polyfill',
'./src/index.js',
],
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.jsx?$/,
loader: 'babel-loader',
exclude: /node_modules/,
options: {
plugins: ['react-hot-loader/babel'],
cacheDirectory: true,
presets: ['env', 'react'],
},
}
],
},
plugins: [
new webpack.DllReferencePlugin({
context: path.join(__dirname),
manifest: require('../dist/vendor-manifest.json'),
}),
new HtmlWebpackPlugin({
title: '<my-app-name>',
filename: 'index.html',
template: './public/index.html',
}),
new AddAssetHtmlPlugin({
filepath: path.resolve(__dirname, '../dist/*.dll.js'),
includeSourcemap: false // add this parameter
})
],
};
AddAssetHtmlPlugin
是必需的,因为 index.html
是动态创建的(由 HtmlWebpackPlugin) for the dev server and you cannot hardcode the correct bundle import for the vendor.dll
and the app.bundle
(more here)。
webpack.dev.js
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
const webpack = require('webpack');
const path = require('path');
module.exports = merge(common, {
mode: 'development',
devtool: 'eval-source-map',
devServer: {
hot: true,
contentBase: path.resolve(__dirname, 'dist'),
historyApiFallback: true // Allow refreshing of the page
},
plugins: [
new webpack.HotModuleReplacementPlugin(), // Enable hot reloading
]
});
我改变了什么:
我将入口点移到了 webpack.common
。
我从 entry
中删除了 'react-hot-loader/patch'
(optional) 我已经为 webpack-dev-server
.
添加了一些配置选项
Index.js
这是导致热重载失败的文件。特别是 if(module.hot)
部分导致它失败。所以我将其更改为以下内容:
import React from 'react';
import ReactDOM from 'react-dom';
import { AppContainer } from 'react-hot-loader';
import { App } from './app';
const render = () => {
ReactDOM.render(
<AppContainer>
<App/>
</AppContainer>,
document.getElementById('app'),
);
};
render(App);
if (module.hot) {
module.hot.accept('./app', () => {
const NextApp = require('./app').default; // Get the updated code
render(NextApp);
});
}
它现在工作的原因是因为现在我获取新应用程序并替换旧应用程序,从而告诉热加载程序发生了变化。我也可以只使用 module.hot.accept()
,但这会使 react-hot-loader
无用(你使用 webpack hot-reloader)并且这样我也会在每次更新时丢失我的组件中的状态代码。
好了。我希望这会帮助任何人(除了我自己)。
所以我终于设置了一个工作项目:
电子(
2.0.2
)反应 (
16.4.0
)React-router-dom (
4.2.2
)Webpack (
4.11.0
)React 热加载程序 (
4.2.0
)
就在我开始开发一些 React 组件时,我注意到我的项目无法正确热重载。如果我在基础 url (/
) 上调整一些东西,它会正确更新,但如果我在辅助 url 上更新一些东西,比如 /test
webpack 编译,但我收到消息 Cannot GET /test
。
我已经尝试了很多,但我似乎无法弄清楚我做错了什么。我调查了 react-router-dom
,因为热重载在版本 3.x
中是一个问题,但他们说现在应该解决它(在 4.x
--> It works here.. 中)。另外我在我的 index.html
中添加了 <base href="/"/>
所以不是这样。
谁能告诉我我做错了什么?
Webpack.common.js(合并到Webpack.dev.js)
module.exports = {
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].bundle.js'
},
resolve: {
modules: [path.resolve(__dirname), 'node_modules']
},
module: {
rules: [
{
test: /\.jsx?$/,
loader: 'babel-loader',
exclude: /node_modules/,
options: {
cacheDirectory: true,
presets: ['env', 'react'],
plugins: ['transform-runtime'],
env: {
development: {
plugins: ['react-hot-loader/babel']
},
production: {
presets: ['react-optimize']
}
}
}
}
]
}
};
Webpack.dev.js
module.exports = merge(common, {
mode: 'development',
devtool: 'eval-source-map',
entry: {
'app': [
'babel-polyfill',
'react-hot-loader/patch',
path.join(__dirname, 'src', 'index.js')
]
},
plugins: [
new webpack.HotModuleReplacementPlugin() // Enable hot module replacement
]
});
Index.js
import React from "react";
import ReactDOM from "react-dom";
import { AppContainer } from "react-hot-loader";
import { App } from "./app";
const render = Component => {
ReactDOM.render(
<AppContainer>
<Component/>
</AppContainer>,
document.getElementById("root")
);
};
render(App);
if (module.hot) {
module.hot.accept("./app", () => {
render(App);
});
}
App.js(我的应用程序的主要入口点,因此我定义了我的基本路由)
import React, { Component } from 'react';
import { BrowserRouter, Route, NavLink } from 'react-router-dom';
import { Test } from './components/test';
import { Test2 } from './components/test2';
export class App extends Component {
render() {
return (
<BrowserRouter>
<div>
<NavLink to="/">Home</NavLink>
<NavLink to="/test">Test</NavLink>
<div>
<Route exact path="/" component={Test}/>
<Route path="/test" component={Test2}/>
</div>
</div>
</BrowserRouter>
);
}
}
组件 'test' 和 'test2' 只是带有 'hello world' 文本的简单反应组件。
有人看到我遗漏或做错了什么吗?
感谢 this tutorial 我找到了一种方法来调整我的项目并让热加载工作。它甚至让我的代码更简洁,我的构建脚本更简单。
Webpack.common.js
我需要更改的第一件事是 babel-loader。我从一些教程中偷了它,它起作用了,但我不知道它到底做了什么,所以我去掉了那个代码。我还通过 webpack.DllReferencePlugin
.
这是更新后的 webpack.common.js:
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const AddAssetHtmlPlugin = require('add-asset-html-webpack-plugin');
module.exports = {
entry: {
app: [
'babel-polyfill',
'./src/index.js',
],
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.jsx?$/,
loader: 'babel-loader',
exclude: /node_modules/,
options: {
plugins: ['react-hot-loader/babel'],
cacheDirectory: true,
presets: ['env', 'react'],
},
}
],
},
plugins: [
new webpack.DllReferencePlugin({
context: path.join(__dirname),
manifest: require('../dist/vendor-manifest.json'),
}),
new HtmlWebpackPlugin({
title: '<my-app-name>',
filename: 'index.html',
template: './public/index.html',
}),
new AddAssetHtmlPlugin({
filepath: path.resolve(__dirname, '../dist/*.dll.js'),
includeSourcemap: false // add this parameter
})
],
};
AddAssetHtmlPlugin
是必需的,因为 index.html
是动态创建的(由 HtmlWebpackPlugin) for the dev server and you cannot hardcode the correct bundle import for the vendor.dll
and the app.bundle
(more here)。
webpack.dev.js
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
const webpack = require('webpack');
const path = require('path');
module.exports = merge(common, {
mode: 'development',
devtool: 'eval-source-map',
devServer: {
hot: true,
contentBase: path.resolve(__dirname, 'dist'),
historyApiFallback: true // Allow refreshing of the page
},
plugins: [
new webpack.HotModuleReplacementPlugin(), // Enable hot reloading
]
});
我改变了什么:
我将入口点移到了
webpack.common
。我从
entry
中删除了 (optional) 我已经为
webpack-dev-server
. 添加了一些配置选项
'react-hot-loader/patch'
Index.js
这是导致热重载失败的文件。特别是 if(module.hot)
部分导致它失败。所以我将其更改为以下内容:
import React from 'react';
import ReactDOM from 'react-dom';
import { AppContainer } from 'react-hot-loader';
import { App } from './app';
const render = () => {
ReactDOM.render(
<AppContainer>
<App/>
</AppContainer>,
document.getElementById('app'),
);
};
render(App);
if (module.hot) {
module.hot.accept('./app', () => {
const NextApp = require('./app').default; // Get the updated code
render(NextApp);
});
}
它现在工作的原因是因为现在我获取新应用程序并替换旧应用程序,从而告诉热加载程序发生了变化。我也可以只使用 module.hot.accept()
,但这会使 react-hot-loader
无用(你使用 webpack hot-reloader)并且这样我也会在每次更新时丢失我的组件中的状态代码。
好了。我希望这会帮助任何人(除了我自己)。