将 webpack 构建与 ASP.NET Core 3.0 集成的最佳方式?
Best way to integrate webpack builds with ASP.NET Core 3.0?
我正在将我的 ASP.NET 核心应用程序升级到 V3,并使用 Visual Studio 2019 进行开发/调试。除了这个之外,这个过程一直很顺利:
public void Configure(…..
app.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions
{
HotModuleReplacement = false,
ReactHotModuleReplacement = false
});
UseWebpackDevMiddleware 不再存在:https://github.com/aspnet/AspNetCore/issues/12890 .
我现在正在寻找了解每次调试时使用 VS 运行 webpack 的最佳方法,最好只在已更改的 JS 代码上。这是我从 UseWebpackDevMiddleware
获得的值。我的应用程序是一个 React 应用程序,如果您的应用程序是从 CreateReactApp 启动的,那么它似乎有一些新的替代品,但我的不是。 (我相信从这里声明但随后分开的应用程序称为 "ejected.")即使我的应用程序不利用 CreateReactApp,我是否仍然可以利用该设施的某种方式?另外,CreateReactApp 在引导您的新 React 应用程序之后的作用是什么?一开始我还以为它只会用来膨胀模板代码呢
Microsoft.AspNetCore.SpaServices.Extensions 在这一切中的作用是什么?
我不需要热更换模块;我不需要服务器端预渲染。我真的只是想了解如何让我的 JS 透明地构建(通过 Webpack)作为我调试过程的一部分。这是我可以连接到 MSBuild 的东西吗?我想其他人在升级时也会面临同样的问题。
感谢您的任何建议。
你说的是VS。我的解决方案适用于 Visual Studio,但不适用于 VS Code。
我使用 WebPack Task Runner:https://marketplace.visualstudio.com/items?itemName=MadsKristensen.WebPackTaskRunner
这会将 webpack.config.js 任务添加到 Visual Studio 中的 "Task Runner Explorer" 中,然后您可以将这些任务绑定到事件,例如 "Before Build" 或 "After Build"
因此,我将 UseWebpackDevMiddleware
用于 HMR 以实现更流畅的开发过程 - 最后我恢复使用 webpack-dev-server
步骤:
1) 添加包到 package.json: "webpack-dev-server": "3.8.2",
2) 添加 webpack.development.js
const merge = require('webpack-merge');
const common = require('./webpack.config.js');
const ExtractCssPlugin = require('mini-css-extract-plugin');
const webpackDevServerPort = 8083;
const proxyTarget = "http://localhost:8492";
module.exports = merge(common(), {
output: {
filename: "[name].js",
publicPath: '/dist/'
},
mode: 'development',
devtool: 'inline-source-map',
devServer: {
compress: true,
proxy: {
'*': {
target: proxyTarget
}
},
port: webpackDevServerPort
},
plugins: [
new ExtractCssPlugin({
filename: "[name].css",
chunkFilename: "[id].css"
})
]
});
请注意,此处的代理设置将用于代理到 ASP.Net 核心以进行 API 调用
修改launchSettings.json
指向webpack-dev-server:
"profiles": {
"VisualStudio: Connect to HotDev proxy": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "http://localhost:8083/",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "http://localhost:8492/"
}
}
(我在 webpack 中配置正确位置时也遇到了一些问题,发现 this 很有用
此外,还需要启动 webpack-dev-server,这可以通过 npm 脚本完成:
"scripts": {
"build:hotdev": "webpack-dev-server --config webpack.development.js --hot --inline",
然后这是自举的
app.UseSpa(spa =>
{
spa.Options.SourcePath = "ClientApp";
if (env.IsDevelopment())
{
spa.UseReactDevelopmentServer(npmScript: "build:hotdev");
}
});
(或者你可以安装 npm task runner 扩展和:
"-vs-binding": {
"ProjectOpened": [
"build:hotdev"
]
}
或者我知道你可以使用以下方式代理其他方式 - 这样任何对 "dist" 的请求都会被推送到代理 webpack-dev-server
app.UseSpa(spa =>
{
spa.Options.SourcePath = "dist";
if (env.IsDevelopment())
{
// Ensure that you start webpack-dev-server - run "build:hotdev" npm script
// Also if you install the npm task runner extension then the webpack-dev-server script will run when the solution loads
spa.UseProxyToSpaDevelopmentServer("http://localhost:8083");
}
});
然后你就不需要再从后面代理了,可以只提供 /dist/ 内容
- 像这样使用 as web.config.js 进行热编译和供应商预编译:
module.exports = merge(common(), {
output: {
filename: "[name].js",
publicPath: '/dist/',
},
mode: 'development',
devtool: 'inline-source-map',
devServer: {
compress: true,
port: 8083,
contentBase: path.resolve(__dirname,"wwwroot"),
},
plugins: [
new ExtractCssPlugin({
filename: "[name].css",
chunkFilename: "[id].css"
})
]
});
在我看来,Kram 的回答应该标记为已接受,因为它确实提供了所需的内容。我最近花了一些时间建立一个 .NET Core/React/Webpack 项目,但我无法让 spa.UseReactDevelopmentServer
工作,但 spa.UseProxyToSpaDevelopmentServer
工作得很好。谢谢克拉姆!
以下是我的一些陷阱,它们可能会对某人有所帮助:
webpack.config.js(节选):
const path = require('path');
const webpack = require('webpack');
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'build.[hash].js',
},
devServer: {
contentBase: path.resolve(__dirname, 'public'),
publicPath: '/dist',
open: false,
hot: true
},
plugins: [
new webpack.HotModuleReplacementPlugin()
]
DevServer通过publicPath
属性设置其root,完全忽略root中的output.path
属性。因此,即使您的输出文件(用于 prod)将转到 dist 文件夹,但在 webpack 服务器下,默认情况下它们将在根目录下提供。如果要保留相同的 url,则必须设置 publicPath: '/dist'
。
这意味着您的默认页面将位于 http://localhost:8083/dist 下。我想不出一种方法将资产放在子文件夹下,同时将索引保留在根目录中(除了硬编码资产的路径)。
您需要 HotModuleReplacementPlugin
才能使用观看模式,还需要 hot: true
在 devServer 配置中进行设置(或在启动时将其作为参数传递)。
如果您(像我一样)使用 open: true
(默认为 false)复制一些开发服务器配置,您将在应用程序启动时打开两个浏览器,而另一个浏览器由启动设置 "launchBrowser": true
。一开始有点意外
此外,您必须为您的项目启用 CORS,否则您的后端调用将被阻止:
Startup.cs(节选):
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy(name: "developOrigins",
builder =>
{
builder.WithOrigins("http://localhost:8083");
});
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
app.UseCors("developOrigins");
}
如果我想到其他任何事情,我会更新答案,希望这对某人有所帮助。
Webpack 5 更新
webpack-dev-server
命令不再有效。使用:
"build:hotdev": webpack serve --config webpack.config.development.js
您可能还需要将 target: 'web'
添加到 Webpack 5 中的 webpack.config.js
以启用热模块重新加载:
module.exports = {
target: 'web'
}
或者,您可能需要创建浏览器列表文件。希望这个问题尽快得到解决。
分机在这里:AspNetCore.SpaServices.Extensions
您可以在这里找到示例:https://github.com/RimuTec/AspNetCore.SpaServices.Extensions
使用核心 3.1 或 5.0
与 webpack 反应
使用:spaBuilder.UseWebpackDevelopmentServer(npmScriptName: "start");
我正在将我的 ASP.NET 核心应用程序升级到 V3,并使用 Visual Studio 2019 进行开发/调试。除了这个之外,这个过程一直很顺利:
public void Configure(…..
app.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions
{
HotModuleReplacement = false,
ReactHotModuleReplacement = false
});
UseWebpackDevMiddleware 不再存在:https://github.com/aspnet/AspNetCore/issues/12890 .
我现在正在寻找了解每次调试时使用 VS 运行 webpack 的最佳方法,最好只在已更改的 JS 代码上。这是我从 UseWebpackDevMiddleware
获得的值。我的应用程序是一个 React 应用程序,如果您的应用程序是从 CreateReactApp 启动的,那么它似乎有一些新的替代品,但我的不是。 (我相信从这里声明但随后分开的应用程序称为 "ejected.")即使我的应用程序不利用 CreateReactApp,我是否仍然可以利用该设施的某种方式?另外,CreateReactApp 在引导您的新 React 应用程序之后的作用是什么?一开始我还以为它只会用来膨胀模板代码呢
Microsoft.AspNetCore.SpaServices.Extensions 在这一切中的作用是什么?
我不需要热更换模块;我不需要服务器端预渲染。我真的只是想了解如何让我的 JS 透明地构建(通过 Webpack)作为我调试过程的一部分。这是我可以连接到 MSBuild 的东西吗?我想其他人在升级时也会面临同样的问题。
感谢您的任何建议。
你说的是VS。我的解决方案适用于 Visual Studio,但不适用于 VS Code。
我使用 WebPack Task Runner:https://marketplace.visualstudio.com/items?itemName=MadsKristensen.WebPackTaskRunner
这会将 webpack.config.js 任务添加到 Visual Studio 中的 "Task Runner Explorer" 中,然后您可以将这些任务绑定到事件,例如 "Before Build" 或 "After Build"
因此,我将 UseWebpackDevMiddleware
用于 HMR 以实现更流畅的开发过程 - 最后我恢复使用 webpack-dev-server
步骤:
1) 添加包到 package.json: "webpack-dev-server": "3.8.2",
2) 添加 webpack.development.js
const merge = require('webpack-merge');
const common = require('./webpack.config.js');
const ExtractCssPlugin = require('mini-css-extract-plugin');
const webpackDevServerPort = 8083;
const proxyTarget = "http://localhost:8492";
module.exports = merge(common(), {
output: {
filename: "[name].js",
publicPath: '/dist/'
},
mode: 'development',
devtool: 'inline-source-map',
devServer: {
compress: true,
proxy: {
'*': {
target: proxyTarget
}
},
port: webpackDevServerPort
},
plugins: [
new ExtractCssPlugin({
filename: "[name].css",
chunkFilename: "[id].css"
})
]
});
请注意,此处的代理设置将用于代理到 ASP.Net 核心以进行 API 调用
修改launchSettings.json
指向webpack-dev-server:
"profiles": {
"VisualStudio: Connect to HotDev proxy": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "http://localhost:8083/",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "http://localhost:8492/"
}
}
(我在 webpack 中配置正确位置时也遇到了一些问题,发现 this 很有用
此外,还需要启动 webpack-dev-server,这可以通过 npm 脚本完成:
"scripts": {
"build:hotdev": "webpack-dev-server --config webpack.development.js --hot --inline",
然后这是自举的
app.UseSpa(spa =>
{
spa.Options.SourcePath = "ClientApp";
if (env.IsDevelopment())
{
spa.UseReactDevelopmentServer(npmScript: "build:hotdev");
}
});
(或者你可以安装 npm task runner 扩展和:
"-vs-binding": {
"ProjectOpened": [
"build:hotdev"
]
}
或者我知道你可以使用以下方式代理其他方式 - 这样任何对 "dist" 的请求都会被推送到代理 webpack-dev-server
app.UseSpa(spa =>
{
spa.Options.SourcePath = "dist";
if (env.IsDevelopment())
{
// Ensure that you start webpack-dev-server - run "build:hotdev" npm script
// Also if you install the npm task runner extension then the webpack-dev-server script will run when the solution loads
spa.UseProxyToSpaDevelopmentServer("http://localhost:8083");
}
});
然后你就不需要再从后面代理了,可以只提供 /dist/ 内容 - 像这样使用 as web.config.js 进行热编译和供应商预编译:
module.exports = merge(common(), {
output: {
filename: "[name].js",
publicPath: '/dist/',
},
mode: 'development',
devtool: 'inline-source-map',
devServer: {
compress: true,
port: 8083,
contentBase: path.resolve(__dirname,"wwwroot"),
},
plugins: [
new ExtractCssPlugin({
filename: "[name].css",
chunkFilename: "[id].css"
})
]
});
在我看来,Kram 的回答应该标记为已接受,因为它确实提供了所需的内容。我最近花了一些时间建立一个 .NET Core/React/Webpack 项目,但我无法让 spa.UseReactDevelopmentServer
工作,但 spa.UseProxyToSpaDevelopmentServer
工作得很好。谢谢克拉姆!
以下是我的一些陷阱,它们可能会对某人有所帮助:
webpack.config.js(节选):
const path = require('path');
const webpack = require('webpack');
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'build.[hash].js',
},
devServer: {
contentBase: path.resolve(__dirname, 'public'),
publicPath: '/dist',
open: false,
hot: true
},
plugins: [
new webpack.HotModuleReplacementPlugin()
]
DevServer通过
publicPath
属性设置其root,完全忽略root中的output.path
属性。因此,即使您的输出文件(用于 prod)将转到 dist 文件夹,但在 webpack 服务器下,默认情况下它们将在根目录下提供。如果要保留相同的 url,则必须设置publicPath: '/dist'
。 这意味着您的默认页面将位于 http://localhost:8083/dist 下。我想不出一种方法将资产放在子文件夹下,同时将索引保留在根目录中(除了硬编码资产的路径)。您需要
HotModuleReplacementPlugin
才能使用观看模式,还需要hot: true
在 devServer 配置中进行设置(或在启动时将其作为参数传递)。如果您(像我一样)使用
open: true
(默认为 false)复制一些开发服务器配置,您将在应用程序启动时打开两个浏览器,而另一个浏览器由启动设置"launchBrowser": true
。一开始有点意外
此外,您必须为您的项目启用 CORS,否则您的后端调用将被阻止:
Startup.cs(节选):
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy(name: "developOrigins",
builder =>
{
builder.WithOrigins("http://localhost:8083");
});
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
app.UseCors("developOrigins");
}
如果我想到其他任何事情,我会更新答案,希望这对某人有所帮助。
Webpack 5 更新
webpack-dev-server
命令不再有效。使用:
"build:hotdev": webpack serve --config webpack.config.development.js
您可能还需要将 target: 'web'
添加到 Webpack 5 中的 webpack.config.js
以启用热模块重新加载:
module.exports = {
target: 'web'
}
或者,您可能需要创建浏览器列表文件。希望这个问题尽快得到解决。
分机在这里:AspNetCore.SpaServices.Extensions
您可以在这里找到示例:https://github.com/RimuTec/AspNetCore.SpaServices.Extensions
使用核心 3.1 或 5.0 与 webpack 反应
使用:spaBuilder.UseWebpackDevelopmentServer(npmScriptName: "start");