Webpack HMR 不重新加载导入的 TypeScript 模块
Webpack HMR not reloading imported TypeScript modules
我正在 运行创建一个 ASP.NET 核心网站,其中包含一个用 TypeScript 编写的 React 前端。我已经在后端中间件中设置了 HMR:
app.UseWebpackDevMiddleware(new Microsoft.AspNetCore.SpaServices.Webpack.WebpackDevMiddlewareOptions
{
HotModuleReplacement = true
});
我的 webpack.config.js
文件是这样的:
const path = require('path');
module.exports = {
mode: 'development',
entry: { main: './scripts/app.tsx' },
output: {
path: path.resolve(__dirname, './wwwroot/js/dist'),
filename: 'bundle.js',
publicPath: '/dist/'
},
resolve: {
extensions: ['*', '.js', '.jsx', '.tsx']
},
module: {
rules: [
{
test: /\.ts|\.tsx$/, include: /scripts/,
use: [
{
loader: 'babel-loader',
options: {
"plugins" : ['react-hot-loader/babel'],
"presets": ["@babel/preset-env", "@babel/preset-react", "@babel/preset-typescript"]
}
}
]
}
]
}
};
webpack 指向这个文件,app.tsx
:
import * as React from "react";
import * as ReactDOM from "react-dom";
import { Application } from "./Application";
ReactDOM.render(
<div><Application /></div>,
document.getElementById("example")
)
if (module.hot) {
module.hot.accept()
}
我在网页中使用了 bundle.js
文件。当我 运行 Web 服务器并浏览到该页面时,我会 [HMR] connected
登录到控制台。当我编辑并保存 app.tsx
文件时,我得到了预期的输出:
client.js:234 [HMR] bundle rebuilding
client.js:242 [HMR] bundle rebuilt in 69ms
process-update.js:39 [HMR] Checking for updates on the server...
process-update.js:112 [HMR] Updated modules:
process-update.js:114 [HMR] - ./scripts/app.tsx
process-update.js:119 [HMR] App is up to date.
但是,当我编辑并保存 application.tsx
时,(其中包括
module.hot.accept()
在底部)我什么也没得到——网络服务器和浏览器都没有任何输出。
我认为这可能是因为 HMR 配置为仅查看 app.tsx
文件:
[0] multi webpack-hot-middleware/client?path=__webpack_hmr&dynamicPublicPath=true ./scripts/app.tsx 40 bytes {main}
有人知道这里的问题是什么吗?它适用于在 webpack 配置文件中明确声明的文件,但不适用于它正在导入的模块 - 其他文件不应该自动包含吗?根据 https://webpack.js.org/guides/hot-module-replacement/ 我 认为 我已经正确设置了所有内容,但我无法使用它,因为使用 ASP.NET 核心中间件的配置不同.
提前致谢。
问题是 webpack.config.js 设置不正确,没有正确使用 react-hot-reloader。
webpack.config.js
const webpack = require("webpack");
const ForkTsCheckerWebpackPlugin = require("fork-ts-checker-webpack-plugin");
const path = require('path');
const CheckerPlugin = require('awesome-typescript-loader').CheckerPlugin;
const CleanWebpackPlugin = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = (env) => {
const isDevBuild = !(env && env.prod);
const outputDir = (env && env.publishDir)
? env.publishDir
: __dirname;
return [{
mode: isDevBuild ? 'development' : 'production',
devtool: 'inline-source-map',
stats: {modules: false},
entry: {
main: ['./scripts/app.tsx'],
},
watchOptions: {
ignored: /node_modules/
},
output: {
filename: "dist/bundle.js",
path: path.join(outputDir, 'wwwroot'),
publicPath: '/'
},
resolve: {
extensions: [".ts", ".tsx", ".js", ".jsx"]
},
devServer: {
hot: true
},
module: {
rules: [
{
test: /\.(j|t)sx?$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
cacheDirectory: true,
babelrc: false,
presets: [
"@babel/preset-env",
"@babel/preset-typescript",
"@babel/preset-react"
],
plugins: [['@babel/plugin-proposal-decorators', {legacy: true}],
['@babel/plugin-proposal-class-properties', {loose: true}],
"react-hot-loader/babel",
"@babel/plugin-transform-runtime"
]
}
}
}
]
},
plugins: [
new CleanWebpackPlugin(path.join(outputDir, 'wwwroot', 'dist')),
new ForkTsCheckerWebpackPlugin()
]
}];
};
scripts/app.tsx
import * as React from "react";
import * as ReactDOM from "react-dom";
import App from "./Application";
ReactDOM.render(<App/>, document.getElementById("rootComponent"));
Class 声明在 scripts/Application.tsx
:
class Application extends React.Component<any,any> { }
scripts/Application.tsx
的底部:
const App: FunctionComponent = () => <Application />;
export default hot(App);
如果其他人正在为此苦苦挣扎,我建议通读示例 GitHub 存储库,这些存储库用于使用 HMR、typescript 和 ASP.NET Core
我正在 运行创建一个 ASP.NET 核心网站,其中包含一个用 TypeScript 编写的 React 前端。我已经在后端中间件中设置了 HMR:
app.UseWebpackDevMiddleware(new Microsoft.AspNetCore.SpaServices.Webpack.WebpackDevMiddlewareOptions
{
HotModuleReplacement = true
});
我的 webpack.config.js
文件是这样的:
const path = require('path');
module.exports = {
mode: 'development',
entry: { main: './scripts/app.tsx' },
output: {
path: path.resolve(__dirname, './wwwroot/js/dist'),
filename: 'bundle.js',
publicPath: '/dist/'
},
resolve: {
extensions: ['*', '.js', '.jsx', '.tsx']
},
module: {
rules: [
{
test: /\.ts|\.tsx$/, include: /scripts/,
use: [
{
loader: 'babel-loader',
options: {
"plugins" : ['react-hot-loader/babel'],
"presets": ["@babel/preset-env", "@babel/preset-react", "@babel/preset-typescript"]
}
}
]
}
]
}
};
webpack 指向这个文件,app.tsx
:
import * as React from "react";
import * as ReactDOM from "react-dom";
import { Application } from "./Application";
ReactDOM.render(
<div><Application /></div>,
document.getElementById("example")
)
if (module.hot) {
module.hot.accept()
}
我在网页中使用了 bundle.js
文件。当我 运行 Web 服务器并浏览到该页面时,我会 [HMR] connected
登录到控制台。当我编辑并保存 app.tsx
文件时,我得到了预期的输出:
client.js:234 [HMR] bundle rebuilding
client.js:242 [HMR] bundle rebuilt in 69ms
process-update.js:39 [HMR] Checking for updates on the server...
process-update.js:112 [HMR] Updated modules:
process-update.js:114 [HMR] - ./scripts/app.tsx
process-update.js:119 [HMR] App is up to date.
但是,当我编辑并保存 application.tsx
时,(其中包括
module.hot.accept()
在底部)我什么也没得到——网络服务器和浏览器都没有任何输出。
我认为这可能是因为 HMR 配置为仅查看 app.tsx
文件:
[0] multi webpack-hot-middleware/client?path=__webpack_hmr&dynamicPublicPath=true ./scripts/app.tsx 40 bytes {main}
有人知道这里的问题是什么吗?它适用于在 webpack 配置文件中明确声明的文件,但不适用于它正在导入的模块 - 其他文件不应该自动包含吗?根据 https://webpack.js.org/guides/hot-module-replacement/ 我 认为 我已经正确设置了所有内容,但我无法使用它,因为使用 ASP.NET 核心中间件的配置不同.
提前致谢。
问题是 webpack.config.js 设置不正确,没有正确使用 react-hot-reloader。
webpack.config.js
const webpack = require("webpack");
const ForkTsCheckerWebpackPlugin = require("fork-ts-checker-webpack-plugin");
const path = require('path');
const CheckerPlugin = require('awesome-typescript-loader').CheckerPlugin;
const CleanWebpackPlugin = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = (env) => {
const isDevBuild = !(env && env.prod);
const outputDir = (env && env.publishDir)
? env.publishDir
: __dirname;
return [{
mode: isDevBuild ? 'development' : 'production',
devtool: 'inline-source-map',
stats: {modules: false},
entry: {
main: ['./scripts/app.tsx'],
},
watchOptions: {
ignored: /node_modules/
},
output: {
filename: "dist/bundle.js",
path: path.join(outputDir, 'wwwroot'),
publicPath: '/'
},
resolve: {
extensions: [".ts", ".tsx", ".js", ".jsx"]
},
devServer: {
hot: true
},
module: {
rules: [
{
test: /\.(j|t)sx?$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
cacheDirectory: true,
babelrc: false,
presets: [
"@babel/preset-env",
"@babel/preset-typescript",
"@babel/preset-react"
],
plugins: [['@babel/plugin-proposal-decorators', {legacy: true}],
['@babel/plugin-proposal-class-properties', {loose: true}],
"react-hot-loader/babel",
"@babel/plugin-transform-runtime"
]
}
}
}
]
},
plugins: [
new CleanWebpackPlugin(path.join(outputDir, 'wwwroot', 'dist')),
new ForkTsCheckerWebpackPlugin()
]
}];
};
scripts/app.tsx
import * as React from "react";
import * as ReactDOM from "react-dom";
import App from "./Application";
ReactDOM.render(<App/>, document.getElementById("rootComponent"));
Class 声明在 scripts/Application.tsx
:
class Application extends React.Component<any,any> { }
scripts/Application.tsx
的底部:
const App: FunctionComponent = () => <Application />;
export default hot(App);
如果其他人正在为此苦苦挣扎,我建议通读示例 GitHub 存储库,这些存储库用于使用 HMR、typescript 和 ASP.NET Core