reactjs - .NET Core 2.X MVC、React、Typescript、Webpack 配置
问题描述
我正在努力改进我的 .NET Core 应用程序,但不确定我需要采取哪种方式。这是一个较旧的网站,最初是使用 Asp.NET 和 Razor 页面构建的,现在我正在尝试加快速度并更新 UI 以符合新的库和方法(React、Angular 等)。
由于重新编程整个 UI 不在允许的时间内,React 似乎是一个不错的选择。所以我创建了一个新的 React 应用程序使用
create-react-app client-app --scripts-version=react-scripts-ts
在 MVC 区域文件夹下(每个区域都必须有自己的应用程序),我可以通过 Power Shell 服务和构建客户端,一切都很好。
我遇到的问题是将生成的脚本的输出目录移动到 wwwroot 文件夹。我需要能够从 wwwroot 加载脚本,因为由于现有项目的路由、过滤器和其他问题,我无法使用 SPA 服务。
这是我第一次尝试使用 React,所以我认为更改文件的输出很容易,但我似乎无法弄清楚如何。
我更新tsconfig.json
以使用更改输出目录
"outDir": "../../../wwwroot/areas",
这似乎没有任何作用,我能够得到任何结果的唯一方法是使用弹出 React 项目npm run eject
,我得到一堆文件,包括 webpack.config.prod.ts 和 webpack.config。 dev.ts 文件。当我这样做时,我注意到该目录以wepack.config.ts
.
在网上寻找答案后,我注意到一些文章建议使用 webpack-cli 而不是npm
指定配置文件。但是当我这样做时,我得到了各种错误,说配置文件不在根目录中,所以我尝试将它移动到./src
目录中,然后我得到另一个错误,即找不到入口模块,因为它无法解决./src
目录,但我找不到它从哪里引用 src。
我能找到的大部分信息要么已经过时,要么根本不起作用。甚至 Typescript.org 网站仍在引用 .NET Core 1.X。
我确实找到了这个ReactJS.NET,但它看起来不是很最新,而且他们的示例无法加载,产生了大量错误。
有没有一种简单的方法可以为这个网站配置 React,或者我是否被迫依赖像 AngularJS 或 KnockOut 这样的旧库?是否可以将 React 设置为像这样提供服务并补充 UI,让我仍然可以使用 Razor 页面?
解决方案
我能够按照我需要的方式进行设置,包括 Webpack 热模块替换。
为了控制所需的配置,我需要react-client-app
通过运行来弹出:
`npm run eject`
这将在您的应用根目录下创建一些目录和文件,其中包含用于生产和调试的 webpack 配置。
对于我的项目,我不需要static/
文件夹,为了更改文件的输出,webpack.config 中有几个区域可以控制这些,例如:
webpack.config.js
output: {
...
filename: 'js/[name].js',
chunkFilename: 'js/[name].chunk.js',
...
},
....
// "url" loader works like "file" loader except that it embeds assets
// smaller than specified limit in bytes as data URLs to avoid requests.
// A missing `test` is equivalent to a match.
{
test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/, /\.svg$/],
loader: require.resolve('url-loader'),
options: {
limit: 10000,
name: 'media/[name].[ext]',
},
},
...
出于某种原因,默认的 React TS 模板 ( create-react-app <name> --typescript
) 没有引用tsconfig.json
. 实现这一目标的关键之一是安装tsconfig-paths-webpack-plugin
. 这使用中定义的路径tsconfig.json
来解析别名和路径,这使您可以从自定义路径中包含模块,而不是使用相对路径,例如:
import <name> from 'core/common/<name>';
下一项业务是在 中添加一个homepage
条目package.json
:
{
"name": "<AppName>",
"homepage": "/<AreaName>",
"version": "0.1.0",
...
}
这会将homepage
值附加到路径并将其指向正确的区域。我最初认为我必须手动构建客户端而不是使用 Javascript 服务 (Spa),但事实并非如此。在不同的区域使用 Spa 确实可以让事情变得整洁,没有理由输出到wwwroot
文件夹,因为SpaStaticFiles
可以设置为任何根和路径。下一步是更新 Startup.cs 以添加 Javascript 服务。
启动.cs
public IServiceProvider ConfigureServices(IServiceCollection services)
{
// In production, the Angular files will be served from this directory
services.AddSpaStaticFiles(configuration =>
{
// Adds the path to the React files
configuration.RootPath = "Areas/<AreaName>/ClientApp/build";
});
return services.ConfigureApplicationServices(Configuration);
}
application.UseSpaStaticFiles(new StaticFileOptions
{
// This is the key to getting things working, this is the path of the Area
RequestPath = "/<AreaName>",
});
application.UseSpa(spa =>
{
spa.Options.SourcePath = "Areas/<AreaName>/ClientApp";
if ( env.IsDevelopment() )
{
spa.UseReactDevelopmentServer(npmScript: "start");
}
});
React 应用程序现在由 Area 提供服务。无需将文件复制到 wwwroot,因为 Javascript Servies 会处理此问题,只需引用根目录中的任何文件,该homepage
值将附加到路径中。
最后,为了加载应用程序,我通过标准控制器/视图启动了应用程序,并使用编译后的 index.html 获取所需的导入以返回。
看法
@{
Layout = null;
}
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="shortcut icon" href="/<AreaName>/favicon.ico" />
<meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no" />
<meta name="theme-color" content="#000000" />
<link rel="manifest" href="/<AreaName>/manifest.json" />
<title>React App</title>
<!-- Webpack Styles -->
<link href="/<AreaName>/css/vendors~main.chunk.css" rel="stylesheet">
<link href="/<AreaName>/css/main.css" rel="stylesheet">
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!-- Webpack Scripts -->
<script src="/<AreaName>/js/vendors~main.chunk.js"></script>
<script src="/<AreaName>/js/main.js"></script>
</body>
</html>
为了让react-router-dom
MVC 及其路由正常运行,您需要HashRouter
使用BrowserRouter
.
注意:如果您npm run build
在启动开发会话之前使用生产构建文件,而不是调试编译文件。这将导致一些混乱,因为没有任何更新。要在进行更改时更新所有内容,只需删除./build
目录并重新启动即可。
我希望我包括所有内容,如果不只是发表评论,我会添加我错过的内容。
推荐阅读
- java - Why does my algorithm to output every digit of a sum fail In PTA?
- java - 为什么这个 JUnitTest 会失败?
- php - Code Igniter Welcome Page Does Not Appear (Internal Server Error)
- image - Matplotlib changes channels of image when saving
- javascript - 通过单击激活 Selectfield
- javascript - alert() 方法不适用于 NodeJS
- python - Linear Sorting of Lists with 2 Elements
- ios - SceneKit下显示相机的不同方法
- angularjs - 如何将 angularJS 指令转换为 Typescript?
- jenkins - jps命令不显示Jenkins的jvm进程