asp.net 核心 2.1 Webpack 4 React 无法正确启动

asp.net core 2.1 Webpack 4 React not starting correctly

无法弄清楚,为什么当我只是从命令行 运行 npm run start 时,项目启动并且一切似乎都正常..但是如果我试图启动它来自 Visual studio 的 IIS 启动浏览器 window(超时 "The create-react-app server did not start listening for requests within the timeout period of 50 seconds")。 几秒钟后,它会在新端口上启动第二个浏览器选项卡,根据需要加载我的项目..

我非常相信我的 StartUp.cs 有问题,只是想不通,在哪里以及为什么..

如果需要,我可以提供任何其他需要的信息。

我的项目结构:

 web
    |
    bin-
    ClientApp
        |
        dist-
        node_modules-
        public- index.html
        src - index.tsx
        package.json
        tsconfig.json
        tslint.json
        webpack.config.js
    Controllers-
    obj
    Pages
    Properties
    appsettings.Development.json
    appsettings.json
    Program.cs
    Startup.cs

额外的屏幕截图,具有精确的结构

webpack.config.js

 const HtmlWebPackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
    entry: "./src/index.tsx",
    output: {
        filename: "[name].bundle.js",
        path: __dirname + '/dist',
    },
    devtool: 'source-map',
    resolve: {
        extensions: ['.js', '.json', '.ts', '.tsx'],
    },
    module: {
        rules: [{
                test: /\.(ts|tsx)$/,
                loader: 'awesome-typescript-loader',
            },
            {
                test: /\.html$/,
                use: [{
                    loader: "html-loader",
                    options: {
                        minimize: true
                    }
                }]
            },
            {
                test: /\.css$/,
                use: [{
                    loader: 'style-loader',
                }, {
                    loader: 'css-loader',
                }, ],
            },
        ]
    },
    plugins: [
        new HtmlWebPackPlugin({
            template: "./public/index.html",
            filename: "./index.html"
        }),
        new MiniCssExtractPlugin({
            filename: "[name].css",
            chunkFilename: "[id].css"
        })
    ]
};

package.json

{
  "name": "ClientApp",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "webpack-dev-server --mode development --open",
    "build": "webpack --mode production"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.1.0",
    "@babel/preset-env": "^7.1.0",
    "@babel/preset-react": "^7.0.0",
    "awesome-typescript-loader": "^5.2.1",
    "babel-loader": "^8.0.2",
    "css-loader": "^1.0.0",
    "html-loader": "^0.5.5",
    "html-webpack-plugin": "^3.2.0",
    "install": "^0.12.1",
    "mini-css-extract-plugin": "^0.4.2",
    "react": "^16.5.1",
    "react-dom": "^16.5.1",
    "style-loader": "^0.23.0",
    "tslint": "^5.11.0",
    "typescript": "^3.0.3",
    "webpack": "^4.19.1",
    "webpack-cli": "^3.1.0",
    "webpack-dev-server": "^3.1.8"
  },
  "dependencies": {
    "@types/react": "^16.4.14",
    "@types/react-dom": "^16.0.7"
  }
}

Program.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;

namespace Web
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateWebHostBuilder(args).Build().Run();
        }

        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>();
    }
}

Startup.cs

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SpaServices.ReactDevelopmentServer;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace Web
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

            services.AddSpaStaticFiles(configuration =>
            {
                configuration.RootPath = "ClientApp/build";
            });
        }

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
            }

            app.UseStaticFiles();
            app.UseSpaStaticFiles();

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller}/{action=Index}/{id?}");
            });

            app.UseSpa(spa =>
            {
                spa.Options.SourcePath = "ClientApp";

                if (env.IsDevelopment())
                {
                    spa.UseReactDevelopmentServer(npmScript: "start");
                }
            });
        }
    }
}

tsconfig.json

{
    "compilerOptions": {
        "noImplicitAny": true,
        "sourceMap": true,
        "target": "es6",
        "jsx": "react",
        "moduleResolution":"node",
        "allowSyntheticDefaultImports": true,
        "module": "ESNext",
    },
    "exclude": [
        "node_modules"
    ],    
}

我使用上面的配置创建了一个新的反应模板,发现 当命令 npm run build 失败或 npm start 失败时,或者当 AspNetCore 找不到正确的 URL 到 Webpack Dev Server ,它会抱怨与您描述的相同的错误 :

which gets timed out "The create-react-app server did not start listening for requests within the timeout period of 50 seconds"

快速修复

如错误所述,react-scripts 似乎有问题。但是,当我查看 package.json 文件时,我发现根本没有配置任何 create-react-app 依赖项。

所以我通过npm i react-scripts --save-dev

添加了一个react-scripts依赖
    "react-scripts": "^1.1.5",

并用 :

替换你的 npm start 和 build
"scripts": {
    "start": "rimraf ./build && react-scripts start",
    "build": "react-scripts build"
},

现在在 Visual Studio 中启动时可以正常工作。

在没有 react-scripts

的情况下启动

既然你说 npm start 效果很好。我想原因是 ASP.NET Core 找不到正确的 URL 服务于 Webpack 开发服务器。

所以我用你的 package.json 创建了另一个新的 React 项目:

"scripts": {
    "start": "webpack-dev-server --port 3000 --mode development --open",
    "build": "webpack --mode production"
},

由于开发服务器默认监听3000端口,contentBase是/public,所以我在你的webpack.config.js:

中添加了一个配置
devServer: {
    contentBase: __dirname + "/public/",
    inline: true,
    port: 3000,
},

我注意到你对 babel 有依赖,所以我添加了一个 .babelrc 配置和对 @babel/plugin-proposal-class-properties 的依赖:

{
    "plugins": [
        [
          "@babel/plugin-proposal-class-properties",
          {
            "loose": true
          }
        ]
    ],
    "presets":["@babel/env","@babel/react"]
}

另外,我不知道你有没有jsx的文件,所以我就在webpack.config.js:

上加了一条规则
{
    test:/\.jsx?/,
    loaders:['babel-loader']
},

因为我已经有一个index.html(由模板生成),所以我删除了HtmlWebPackPlugin配置:

plugins: [
    // new HtmlWebPackPlugin({
    //     // template: "public/index.html",
    //     // // filename: "index.html"
    // }),
    new MiniCssExtractPlugin({
        filename: "[name].css",
        chunkFilename: "[id].css"
    })
]

当我测试默认的 React 模板(将默认的 package.json 替换为您的)时,它现在工作正常。

create-react-app服务器在50秒的超时时间内没有开始监听请求

这只在我启动时发生,所以我添加了 spa.Options.StartupTimeout:

 app.UseSpa(spa =>
            {
                spa.Options.SourcePath = "ClientApp";

                if (env.IsDevelopment())
                {
                    spa.Options.StartupTimeout = TimeSpan.FromSeconds(120);
                    spa.UseReactDevelopmentServer(npmScript: "start");
                }
            });

正如错误消息所暗示的,Asp.NET Core 的 React 开发服务器中间件与 create-react-app 相关联。直接调用 Webpack 开发服务器时将不起作用。它扫描脚本的输出以查找特定于 create-react-app 的文本 "Starting the development server"。

您可以通过在 package.json 中设置启动命令来绕过它,如下所示:

"start": "echo Starting the development server && node node_modules/webpack-dev-server/bin/webpack-dev-server.js --port %PORT% --mode development"

这让 Asp.Net 核心中间件很高兴,也让开发服务器监听正确的端口。

或者,您可以尝试转换您的设置以摆脱完整的 Webpack 设置并使用 create-react-app。

请注意,itminus 提供的答案似乎有问题。第二部分,在没有反应脚本的情况下启动,无法工作,因为 create-react-app "Starting the development server" 不会在那里。