Visual Studio React Typescript webpack-dev-server 热重载不适用于组件更改
[英] Visual Studio React Typescript webpack-dev-server hot reload not working for component changes
本文介绍了Visual Studio React Typescript webpack-dev-server 热重载不适用于组件更改的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我将 .Net Core 3.1 与 React、Typescript 和 webpack 一起用于 SPA.我有多个反应模块,我将它们加载到 Asp.Net 核心应用程序的不同页面/视图上.
我遇到了自动刷新或热重载的问题.当我更改从模块传递给组件的参数时,热重载按预期工作,但是如果我对组件进行任何更改,那么这些将没有反映在浏览器中.
如果我浏览 https://localhost:5010/webpack-dev-server,我可以在那里看到 home.bundle.js.此外,如果更改msg"的值HomeModule.tsx 中 HomeComponent 的 param/prop,我可以看到为 home.bundle.js 生成的新包带有新的哈希码,更改也反映到浏览器 https://localhost:5010/home/BUT如果我确实更改为 HomeComponent.tsx 例如:如果我更改Home component"到家庭组件123"此更改未反映,无论是在 https://localhost:5010/home 上还是在 https://localhost:5010/webpack-dev-server 上都未生成的新包.
这是我的项目结构和文件,包括配置文件.任何帮助将不胜感激.
更新:我将 HotModuleReplacementPlugin 添加到 webpack.dev.config.js,现在当我修改组件 HomeComponent.tsx 中的某些内容时,我在 https://localhost:5010/webpack-dev-server 中看到一个新条目,类似于;5f80de77a97d48407bd9.hot-update.json".如果我打开这个文件,它的内容就像 {"h":"0dce1f9e44bff4d47fb4","c":{}}
除此之外,另一个问题是当我从 Visual Studio 使用 F5 运行应用程序时,加载网站需要几秒钟,直到浏览器显示无法访问此站点"
项目结构
解决方案解决方案- AspNetCore.Web- 节点模块- wwwroot- js- 控制器- 意见- 脚本(反应)- 成分- HomeComponent.tsx- 模块- HomeModule.tsx- 包.json- tsconfig.json- webpack.config.js- webpack.dev.js- 其他 .Net Core 项目
Package.json
<代码>{版本":1.0.0",名称":aspnetcore-react",私人":真的,脚本":{"build": "webpack serve --config webpack.dev.config.ts",测试":回声\"错误:未指定测试\"&&出口 1"},依赖关系":{axios":^0.21.1",反应":^16.13.1",react-dom":^16.13.1",反应路由器":^ 5.2.0";},开发依赖":{@babel/core":^7.14.3",@babel/plugin-transform-runtime":^7.14.3",@babel/preset-env":^7.14.2",@babel/preset-react":^7.13.13",@babel/preset-typescript":^7.13.0",@babel/runtime":^7.14.0",@popperjs/core":^2.2.1",@types/react":^16.9.35",@types/react-dom":^16.9.8",@types/webpack":^4.41.25",@types/webpack-dev-server":^3.11.1",自动前缀":^9.7.6",babel-core":^6.26.3",babel-loader":^8.2.2",引导程序":^4.4.1",clean-webpack-plugin":^4.0.0-alpha.0",css-loader":^3.5.1",文件加载器":^6.0.0",jquery":^3.6.0",节点-sass":^4.14.1",postcss-loader":^3.0.0",resolve-url-loader":^3.1.3",sass-loader":^8.0.2",样式加载器":^1.1.3",ts-loader":^7.0.2",ts-node":^10.0.0",打字稿":3.8.3",url-loader":^4.1.0",vue-loader":^15.9.2",webpack":^5.11.1",webpack-cli":^4.3.1",webpack-dev-server":^3.11.1",webpack-merge":^5.7.3"}}
tsconfig.json
<代码>{编译器选项":{库":[dom",dom.iterable",esnext"],allowJs":真,allowSyntheticDefaultImports":真,skipLibCheck":真,esModuleInterop":真,严格":真实,forceConsistentCasingInFileNames":真,模块分辨率":节点",resolveJsonModule":真,isolatedModules":真,noEmit":真,jsx":反应",},排除":[wwwroot/js",节点模块"],包括":[./Scripts/**/*"]}
webpack.dev.config.ts
从路径"导入路径;从webpack"导入 webpack;从 'fs' 导入 * 作为 fs;const modulePath = './Scripts/modules/'常量条目 = {家:modulePath +HomeModule.tsx",编辑器:modulePath +EditorModule.tsx";};const 配置:webpack.Configuration = {模式:发展",输出: {文件名:[名称].bundle.js",公共路径:/js",},条目:条目,模块: {规则: [{测试:/\.(ts|js)x?$/i,排除:/node_modules/,用: {装载机:babel-loader",选项: {预设:[@babel/preset-env",@babel/preset-react",@babel/preset-typescript",],},},},{测试:/\.(scss)$/,用: [{//通过注入 `<style>` 标签将 CSS 添加到 DOM装载机:'风格装载机'},{//像 `import/require()` 一样解释 `@import` 和 `url()` 并解析它们装载机:'css-装载机'},{加载器:解析网址加载器";},{//webpack 的加载器以使用 PostCSS 处理 CSSloader: 'postcss-loader',选项: {插件:函数(){返回 [要求('自动前缀')];}}},{//加载一个 SASS/SCSS 文件并将其编译为 CSSloader: 'sass-loader'}]},{测试:/\.(png|jpe?g|gif|webp)(\?.*)?$/,用: [{loader: 'url-loader',选项: {限制:4096,倒退: {加载器:'文件加载器',选项: {name: 'assets/[name].[hash:8].[ext]'}}}}]},{测试:/\.(svg)(\?.*)?$/,用: [{加载器:'文件加载器',选项: {name: 'assets/[name].[hash:8].[ext]'}}]},{测试:/\.(woff|woff2|eot|ttf|otf)$/,用: [{加载器:'文件加载器',选项: {name: 'assets/[name].[hash:8].[ext]'}}],},{测试:/\.html$/,用: [{加载器:html-加载器",选项: {最小化:真}}]}],},解决: {扩展名:[.tsx"、.jsx"、.ts"、.js"]、},插件: [],开发工具:内联源映射",开发服务器:{contentBase: path.join(__dirname, build"),historyApiFallback: 真,端口:5010,打开:假,热:真的,https:{密钥:fs.readFileSync('./Scripts/generated/webpack_cert.key'),证书:fs.readFileSync('./Scripts/generated/webpack_cert.crt'),}}};导出默认配置;
HomeModule.tsx
import * as React from 'react';import * as ReactDom from 'react-dom';从 '../components/HomeComponent' 导入 HomeComponent;const homeRoot = document.getElementById('home');ReactDom.render(<HomeComponent msg={'Hello World!!!'}/>, homeRoot);
HomeComponent.tsx
import * as React from 'react';导出接口 IHomeComponentProps {消息:字符串}导出接口 IHomeComponentState {}导出默认类 HomeComponent 扩展 React.Component{构造函数(道具:IHomeComponentProps){超级(道具);this.state = {}}公共渲染(){返回 (<div><h2>主页组件</h2><p><b>{this.props.msg}</b></p>
);}}
Views/Home/Index.cshtml
@{ViewData[标题"] =主页";ViewBag.NoContainer = true;}<div class="home-header"><h2 class="home-header-subtitle">欢迎来到</h2><h1 class="home-header-title">AspnetCoreReact</h1><div class="home-header-actions"><a class="btn btn-primary home-header-button";asp区域="asp-controller=编辑器"asp-action=Index">尝试演示</a>
<div id="home">
<script src="~/js/home.bundle.js";类型=模块"></script>
Startup.cs
命名空间 AspnetCoreReact.Web{公开课启动{...public void ConfigureServices(IServiceCollection 服务){服务.AddApplication();services.AddInfrastructure(Configuration, Environment);services.AddScoped();services.AddHttpContextAccessor();services.AddHealthChecks().AddDbContextCheck();配置Cookie设置(服务);//添加内存缓存服务services.AddMemoryCache();//要做:稍后改成分布式缓存services.Configure(options => options.LowercaseUrls = true);服务.AddMvc();services.AddControllersWithViews();services.AddRazorPages();services.AddHttpContextAccessor();}公共无效配置(IApplicationBuilder 应用程序,IWebHostEnvironment 环境){如果 (env.IsDevelopment()){app.UseDeveloperExceptionPage();app.UseDatabaseErrorPage();}别的{app.UseExceptionHandler("/Home/Error");//默认的 HSTS 值为 30 天.您可能希望针对生产场景更改此设置,请参阅 https://aka.ms/aspnetcore-hsts.app.UseHsts();}app.UseHealthChecks("/health");//app.UseHttpsRedirection();app.UseStaticFiles();app.UseSpaStaticFiles();app.UseRouting();app.UseCookiePolicy();app.UseAuthentication();app.UseAuthorization();app.UseEndpoints(endpoints =>{endpoints.MapControllerRoute(名称:区域",模式:{area:exists}/{controller=Home}/{action=Index}/{id?}");endpoints.MapControllerRoute(名称:默认",模式:{controller=Home}/{action=Index}/{id?}");端点.MapRazorPages();});app.UseSpa(spa =>{spa.Options.SourcePath = 脚本";如果 (env.IsDevelopment()){spa.UseReactDevelopmentServer(npmScript: "build:hotdev");}});}}}
launchSettings.json
<代码>{iis设置":{windowsAuthentication":假,匿名身份验证":真,iisExpress":{applicationUrl":http://localhost:53158",sslPort":44329}},个人资料":{IIS Express":{命令名称":IISExpress",launchBrowser":真,环境变量":{ASPNETCORE_ENVIRONMENT":开发"}},AspnetCore-反应":{命令名称":项目",launchBrowser":真,环境变量":{ASPNETCORE_ENVIRONMENT":开发",ASPNETCORE_HOSTINGSTARTUPASSEMBLIES":Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation"},applicationUrl":https://localhost:5001;http://localhost:5000"}}}
解决方案
我终于能够通过将 UseReactDevelopmentServer 替换为 UseProxyToSpaDevelopmentServer 来解决该问题.
新代码块(工作中)
app.UseSpa(spa =>{spa.Options.SourcePath = 脚本";如果 (env.IsDevelopment()){//确保你启动了 webpack server - npm run buildstring webpackDevServer = "https://localhost:5010/";spa.UseProxyToSpaDevelopmentServer(webpackDevServer);}});
旧代码块(不工作)
app.UseSpa(spa =>{spa.Options.SourcePath = 脚本";如果 (env.IsDevelopment()){spa.UseReactDevelopmentServer(npmScript: "build:hotdev");}});
I am using .Net Core 3.1 with React, Typescript and webpack for an SPA. I have multiple modules in react which I load on different page/view of Asp.Net core application.
I am facing issue with auto refresh or hot reload. When I change a parameter which I am passing from module to a component hot reload works as expected BUT if I do any change in component then those are not getting reflected in browser.
If I browse https://localhost:5010/webpack-dev-server I can see home.bundle.js there. Also if change value of "msg" param/prop of HomeComponent in HomeModule.tsx, I can see new bundle generated for home.bundle.js with fresh hashcode and change also reflects to browser on https://localhost:5010/home/ BUT If I do change to HomeComponent.tsx ex: if I change "Home component" to "Home component 123" this change not getting reflected neither on https://localhost:5010/home nor the new bundle NOT generating on https://localhost:5010/webpack-dev-server.
Here is my project structure and files including configuration files. Any help will be highly appreciated.
Update: I added HotModuleReplacementPlugin to webpack.dev.config.js and now when I modify something in component HomeComponent.tsx I see a new entry in https://localhost:5010/webpack-dev-server something like "5f80de77a97d48407bd9.hot-update.json". If I open this file it's content is like {"h":"0dce1f9e44bff4d47fb4","c":{}}
Apart from this another issue is when I run application with F5 from Visual Studio it takes couple of seconds to load website until than browser shows "This site can't be reached"
Project stucture
Solution
Solution
- AspNetCore.Web
- node_modules
- wwwroot
- js
- Controllers
- Views
- Scripts (React)
- components
- HomeComponent.tsx
- modules
- HomeModule.tsx
- package.json
- tsconfig.json
- webpack.config.js
- webpack.dev.js
- Other .Net Core projects
Package.json
{
"version": "1.0.0",
"name": "aspnetcore-react",
"private": true,
"scripts": {
"build": "webpack serve --config webpack.dev.config.ts",
"test": "echo \"Error: no test specified\" && exit 1"
},
"dependencies": {
"axios": "^0.21.1",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-router": "^5.2.0"
},
"devDependencies": {
"@babel/core": "^7.14.3",
"@babel/plugin-transform-runtime": "^7.14.3",
"@babel/preset-env": "^7.14.2",
"@babel/preset-react": "^7.13.13",
"@babel/preset-typescript": "^7.13.0",
"@babel/runtime": "^7.14.0",
"@popperjs/core": "^2.2.1",
"@types/react": "^16.9.35",
"@types/react-dom": "^16.9.8",
"@types/webpack": "^4.41.25",
"@types/webpack-dev-server": "^3.11.1",
"autoprefixer": "^9.7.6",
"babel-core": "^6.26.3",
"babel-loader": "^8.2.2",
"bootstrap": "^4.4.1",
"clean-webpack-plugin": "^4.0.0-alpha.0",
"css-loader": "^3.5.1",
"file-loader": "^6.0.0",
"jquery": "^3.6.0",
"node-sass": "^4.14.1",
"postcss-loader": "^3.0.0",
"resolve-url-loader": "^3.1.3",
"sass-loader": "^8.0.2",
"style-loader": "^1.1.3",
"ts-loader": "^7.0.2",
"ts-node": "^10.0.0",
"typescript": "3.8.3",
"url-loader": "^4.1.0",
"vue-loader": "^15.9.2",
"webpack": "^5.11.1",
"webpack-cli": "^4.3.1",
"webpack-dev-server": "^3.11.1",
"webpack-merge": "^5.7.3"
}
}
tsconfig.json
{
"compilerOptions": {
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"allowSyntheticDefaultImports": true,
"skipLibCheck": true,
"esModuleInterop": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react",
},
"exclude": [
"wwwroot/js",
"node_modules"
],
"include": [
"./Scripts/**/*"
]
}
webpack.dev.config.ts
import path from "path";
import webpack from "webpack";
import * as fs from 'fs';
const modulePath = './Scripts/modules/'
const entries = {
home: modulePath + "HomeModule.tsx",
editor: modulePath + "EditorModule.tsx"
};
const config: webpack.Configuration = {
mode: "development",
output: {
filename: "[name].bundle.js",
publicPath: "/js",
},
entry: entries,
module: {
rules: [
{
test: /\.(ts|js)x?$/i,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: [
"@babel/preset-env",
"@babel/preset-react",
"@babel/preset-typescript",
],
},
},
},
{
test: /\.(scss)$/,
use: [
{
// Adds CSS to the DOM by injecting a `<style>` tag
loader: 'style-loader'
},
{
// Interprets `@import` and `url()` like `import/require()` and will resolve them
loader: 'css-loader'
},
{
loader: "resolve-url-loader"
},
{
// Loader for webpack to process CSS with PostCSS
loader: 'postcss-loader',
options: {
plugins: function () {
return [
require('autoprefixer')
];
}
}
},
{
// Loads a SASS/SCSS file and compiles it to CSS
loader: 'sass-loader'
}
]
},
{
test: /\.(png|jpe?g|gif|webp)(\?.*)?$/,
use: [
{
loader: 'url-loader',
options: {
limit: 4096,
fallback: {
loader: 'file-loader',
options: {
name: 'assets/[name].[hash:8].[ext]'
}
}
}
}
]
},
{
test: /\.(svg)(\?.*)?$/,
use: [
{
loader: 'file-loader',
options: {
name: 'assets/[name].[hash:8].[ext]'
}
}
]
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
use: [
{
loader: 'file-loader',
options: {
name: 'assets/[name].[hash:8].[ext]'
}
}
],
},
{
test: /\.html$/,
use: [{
loader: "html-loader",
options: {
minimize: true
}
}]
}
],
},
resolve: {
extensions: [".tsx", ".jsx", ".ts", ".js"],
},
plugins: [
],
devtool: "inline-source-map",
devServer: {
contentBase: path.join(__dirname, "build"),
historyApiFallback: true,
port: 5010,
open: false,
hot: true,
https: {
key: fs.readFileSync('./Scripts/generated/webpack_cert.key'),
cert: fs.readFileSync('./Scripts/generated/webpack_cert.crt'),
}
}
};
export default config;
HomeModule.tsx
import * as React from 'react';
import * as ReactDom from 'react-dom';
import HomeComponent from '../components/HomeComponent';
const homeRoot = document.getElementById('home');
ReactDom.render(<HomeComponent msg={'Hello World!!!'} />, homeRoot);
HomeComponent.tsx
import * as React from 'react';
export interface IHomeComponentProps {
msg: string
}
export interface IHomeComponentState {
}
export default class HomeComponent extends React.Component<IHomeComponentProps, IHomeComponentState> {
constructor(props: IHomeComponentProps) {
super(props);
this.state = {
}
}
public render() {
return (
<div>
<h2>Home component</h2>
<p><b>{this.props.msg}</b></p>
</div>
);
}
}
Views/Home/Index.cshtml
@{
ViewData["Title"] = "Home Page";
ViewBag.NoContainer = true;
}
<div class="home-header">
<h2 class="home-header-subtitle">Welcome to the</h2>
<h1 class="home-header-title">AspnetCoreReact</h1>
<div class="home-header-actions">
<a class="btn btn-primary home-header-button" asp-area="" asp-controller="Editor" asp-action="Index">Try the demo</a>
</div>
<div id="home">
</div>
</div>
<script src="~/js/home.bundle.js" type="module"></script>
Startup.cs
namespace AspnetCoreReact.Web
{
public class Startup
{
...
public void ConfigureServices(IServiceCollection services)
{
services.AddApplication();
services.AddInfrastructure(Configuration, Environment);
services.AddScoped<ICurrentUserService, CurrentUserService>();
services.AddHttpContextAccessor();
services.AddHealthChecks()
.AddDbContextCheck<AspNetReactDbContext>();
ConfigureCookieSettings(services);
// Add memory cache services
services.AddMemoryCache(); // To do: Change to distributed cache later
services.Configure<RouteOptions>(options => options.LowercaseUrls = true);
services.AddMvc();
services.AddControllersWithViews();
services.AddRazorPages();
services.AddHttpContextAccessor();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHealthChecks("/health");
//app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseSpaStaticFiles();
app.UseRouting();
app.UseCookiePolicy();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "areas",
pattern: "{area:exists}/{controller=Home}/{action=Index}/{id?}");
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
endpoints.MapRazorPages();
});
app.UseSpa(spa =>
{
spa.Options.SourcePath = "Scripts";
if (env.IsDevelopment())
{
spa.UseReactDevelopmentServer(npmScript: "build:hotdev");
}
});
}
}
}
launchSettings.json
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:53158",
"sslPort": 44329
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"AspnetCore-React": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation"
},
"applicationUrl": "https://localhost:5001;http://localhost:5000"
}
}
}
解决方案
I finally able to resolve the issue by replacing UseReactDevelopmentServer with UseProxyToSpaDevelopmentServer.
New code block (Working)
app.UseSpa(spa =>
{
spa.Options.SourcePath = "Scripts";
if (env.IsDevelopment())
{
// Ensure that you start webpack server - npm run build
string webpackDevServer = "https://localhost:5010/";
spa.UseProxyToSpaDevelopmentServer(webpackDevServer);
}
});
Old code block (Not working)
app.UseSpa(spa =>
{
spa.Options.SourcePath = "Scripts";
if (env.IsDevelopment())
{
spa.UseReactDevelopmentServer(npmScript: "build:hotdev");
}
});
这篇关于Visual Studio React Typescript webpack-dev-server 热重载不适用于组件更改的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!