It is my first project in that I'm using electron, I'm dealing with a few problems creating standalone publish from the project.
Here's my electron main.js file:
const path = require("path");
const electron = require("electron");
const isDev = require("electron-is-dev");
// Module to control application life.
const app = electron.app;
// Module to create native browser window.
const BrowserWindow = electron.BrowserWindow;
const url = require("url");
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow;
function createWindow() {
// Create the browser window.
mainWindow = new BrowserWindow({ show: false });
// cm: open app in fullscreen mode
mainWindow.maximize();
mainWindow.show();
// cm: remove default menu bar
mainWindow.setMenuBarVisibility(false);
if (isDev) {
mainWindow.loadURL(
"http://localhost:3000"
);
} else {
mainWindow.loadFile("./dist/index.js");
}
// Open the DevTools.
mainWindow.webContents.openDevTools();
// Emitted when the window is closed.
mainWindow.on("closed", function () {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
mainWindow = null;
});
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on("ready", createWindow);
// Quit when all windows are closed.
app.on("window-all-closed", function () {
// On OS X it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== "darwin") {
app.quit();
}
});
app.on("activate", function () {
// On OS X it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (mainWindow === null) {
createWindow();
}
});
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.
And my package.json scripts are:
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"electron": "electron .",
"package-win": "electron-packager . IranFMCG --overwrite --platform=win32 --arch=ia32 --icon=assets/icons/win/icon.ico --prune=true --out=release-builds --version-string.CompanyName=CE --version-string.FileDescription=CE --version-string.ProductName=\"IranFMCG\"",
},
Everything is fine when the react application is running and I'm using "npm run electron" but after running "npm run package-win" and after that when I'm running exe file I am facing errors.
I think that is because I'm not running react app anymore, but I want to use react build files is it possible?
After installing the React app template from .NET Core 3.1 using dotnet new react the application works perfectly in Development and Production. The problem appears when trying to use Swagger or Hangfire dashboard endpoints.
After the app is created I add the package reference for Hangfire and for practical purposes the memory storage:
<PackageReference Include="Hangfire" Version="1.7.*" />
<PackageReference Include="Hangfire.MemoryStorage" Version="1.7.0" />
In Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddHangfire(config =>
config.SetDataCompatibilityLevel(CompatibilityLevel.Version_170)
.UseSimpleAssemblyNameTypeSerializer()
.UseDefaultTypeSerializer()
.UseMemoryStorage());
services.AddHangfireServer();
// In production, the React files will be served from this directory
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "ClientApp/build";
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/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.UseHttpsRedirection();
app.UseStaticFiles();
app.UseSpaStaticFiles();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapHangfireDashboard();
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller}/{action=Index}/{id?}");
});
app.UseSpa(spa =>
{
spa.Options.SourcePath = "ClientApp";
if (env.IsDevelopment())
{
spa.UseReactDevelopmentServer(npmScript: "start");
}
});
}
After publishing the application and run it, the app works fine except the Hangfire dashboard, and trying to access the route: /Hangfire causes the server return the SPA index.html
But if I refresh the page doing a hard reload, the dashboard loads fine.
Same thing occurs with Swagger.
Can someone give me a hand ?
After following Guilherme suggestion, unregistering the service worker solved the issue. Instead of ignoring the routes, I opted to unregister it.
Thank you very much !
The template's default structure has everything in one place, like this:
/
bin/
obj/
ClientApp/
myproject.csproj
Startup.cs
etc.
My structure has many libraries and angular apps - i.e. a monorepo - so it must be more organized:
/
libs
client
client2
server
bin/
obj/
myproject.csproj
Startup.cs
lib1
lib2
I edited various references to reflect this structure, most importantly Startup.cs:
services.AddSpaStaticFiles(configuration => {
configuration.RootPath = "../../../../client/dist";
});
// and
app.UseSpa(spa => {
spa.Options.SourcePath = "../../../../client";
});
But when running I get: InvalidOperationException: Failed to start 'npm'.
When I run the server and client separately, they work... so the problem is with how the "spa services" is configured. I tried both ../../../../client (from bin directory) and ../client (from server project's base directory).
How do I reconfigure the project structure? (Is there a working sample repo somewhere?)
You can't run your app in dist folder when you are in development mode because dist folder only use for production mode
Default settings is like this
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "ClientApp/dist";
});
app.UseSpa(spa =>
{
spa.Options.SourcePath = "ClientApp";
if (env.IsDevelopment())
{
spa.UseAngularCliServer(npmScript: "start");
}
});
So in order to run your app you must create folder in same root of default Startup.cs or ClientApp file like in your case is libs then it will be libs/client
Then modify the setting
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "libs/client/dist";
});
app.UseSpa(spa =>
{
spa.Options.SourcePath = "libs/client";
if (env.IsDevelopment())
{
spa.UseAngularCliServer(npmScript: "start");
}
});
Please note that you can only run 1 angular app with this setting if you want to run another angular app you need to manage it selft manually
I got it working like this:
1 changed to monorepo structure as shown in my question above
2 edited Server.csproj (paths are relative to server app's directory):
<!--<SpaRoot>ClientApp\</SpaRoot>-->
<SpaRoot>../client/</SpaRoot>
3 edited Startup.cs (paths are relative to workspace's directory):
services.AddSpaStaticFiles(configuration => {
//configuration.RootPath = "ClientApp/dist";
configuration.RootPath = "./libs/client/dist";
});
and
app.UseSpa(spa => {
//spa.Options.SourcePath = "ClientApp";
spa.Options.SourcePath = "./libs/client";
// etc.
});
I have been developing React and .net core 2.1 web api and have them separately. Now I would like to run tests on client side only and I am not sure if what I want to do is possible. I have create-react-app client side application and there's a single test that renders the entire application.
it("renders without crashing", () => {
const div = document.createElement("div");
ReactDOM.render(<App />, div);
});
When I try to run npm test in the terminal, I have the server running. (I tried running it in visual studio and in cmd with dotnet run. All it does is this error:
TypeError: Network request failed
at XMLHttpRequest.xhr.onerror (C:\Users\Tomas\source\repos\ReactGoalTrackingWebsite\ReactGoalTrackingWebsite\ClientApp\node_modules\whatwg-fetch\fetch.js:436:16)alTrackingWebsite\ClientApp\node_modules\whatwg-fetch\fetch.js:436:16) ingWebsite\ReactGoalTrackingWebsite\ClientApp\node_modules\jsdom\lib\jsdom\living\events\EventTarget-impl.js:289:32)
at XMLHttpRequest.callback.(anonymous function) (C:\Users\Tomas\source\repos\ReactGoalTrackkingWebsite\ClientApp\node_modules\jsdom\lib\jsdom\living\events\EventTarget-impl.js:219:27)ingWebsite\ReactGoalTrackingWebsite\ClientApp\node_modules\jsdom\lib\jsdom\living\events\EventTckingWebsite\ClientApp\node_modules\jsdom\lib\jsdom\living\events\EventTarget-impl.js:166:7)arget-impl.js:289:32) lTrackingWebsite\ClientApp\node_modules\jsdom\lib\jsdom\living\events\EventTarget-impl.js:122:7)
at invokeEventListeners (C:\Users\Tomas\source\repos\ReactGoalTrackingWebsite\ReactGoalTractGoalTrackingWebsite\ClientApp\node_modules\jsdom\lib\jsdom\living\events\EventTarget-impl.js:87:17)kingWebsite\ClientApp\node_modules\jsdom\lib\jsdom\living\events\EventTarget-impl.js:219:27) GoalTrackingWebsite\ClientApp\node_modules\jsdom\lib\jsdom\living\generated\EventTarget.js:61:35)
at invokeInlineListeners (C:\Users\Tomas\source\repos\ReactGoalTrackingWebsite\ReactGoalTrakingWebsite\ClientApp\node_modules\jsdom\lib\jsdom\living\xmlhttprequest.js:405:16)ckingWebsite\ClientApp\node_modules\jsdom\lib\jsdom\living\events\EventTarget-impl.js:166:7) ite\ClientApp\node_modules\jsdom\lib\jsdom\living\xhr-utils.js:315:13)
at EventTargetImpl._dispatch (C:\Users\Tomas\source\repos\ReactGoalTrackingWebsite\ReactGoakingWebsite\ClientApp\node_modules\jsdom\lib\jsdom\living\nodes\Document-impl.js:146:21)lTrackingWebsite\ClientApp\node_modules\jsdom\lib\jsdom\living\events\EventTarget-impl.js:122:7ite\ClientApp\node_modules\jsdom\lib\jsdom\browser\Window.js:362:29)) TrackingWebsite\ClientApp\node_modules\jest-environment-jsdom\build\index.js:44:19)
at EventTargetImpl.dispatchEvent (C:\Users\Tomas\source\repos\ReactGoalTrackingWebsite\ReackingWebsite\ClientApp\node_modules\jest\node_modules\jest-cli\build\runTest.js:102:17)tGoalTrackingWebsite\ClientApp\node_modules\jsdom\lib\jsdom\living\events\EventTarget-impl.js:87:17)
at XMLHttpRequest.dispatchEvent (C:\Users\Tomas\source\repos\ReactGoalTrackingWebsite\ReactGoalTrackingWebsite\ClientApp\node_modules\jsdom\lib\jsdom\living\generated\EventTarget.js:61:35) at XMLHttpRequest.abort (C:\Users\Tomas\source\repos\ReactGoalTrackingWebsite\ReactGoalTrackingWebsite\ClientApp\node_modules\jsdom\lib\jsdom\living\xmlhttprequest.js:405:16) at Object.abort (C:\Users\Tomas\source\repos\ReactGoalTrackingWebsite\ReactGoalTrackingWebsite\ClientApp\node_modules\jsdom\lib\jsdom\living\xhr-utils.js:315:13)
at RequestManager.close (C:\Users\Tomas\source\repos\ReactGoalTrackingWebsite\ReactGoalTrackingWebsite\ClientApp\node_modules\jsdom\lib\jsdom\living\nodes\Document-impl.js:146:21) at Window.close (C:\Users\Tomas\source\repos\ReactGoalTrackingWebsite\ReactGoalTrackingWebsite\ClientApp\node_modules\jsdom\lib\jsdom\browser\Window.js:362:29)
at JSDOMEnvironment.dispose (C:\Users\Tomas\source\repos\ReactGoalTrackingWebsite\ReactGoalTrackingWebsite\ClientApp\node_modules\jest-environment-jsdom\build\index.js:44:19) at Promise.resolve.then (C:\Users\Tomas\source\repos\ReactGoalTrackingWebsite\ReactGoalTrackingWebsite\ClientApp\node_modules\jest\node_modules\jest-cli\build\runTest.js:102:17)
at <anonymous> at process._tickCallback (internal/process/next_tick.js:188:7)
npm ERR! Test failed. See above for more details.
Here's my startup configuration:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
app.UseHttpsRedirection();
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");
}
});
}
Is my configuration incorrect?
When I try to run npm test in the terminal, I have the server running. (I tried running it in visual studio and in cmd with dotnet run. All it does is this error:
TypeError: Network request failed
at XMLHttpRequest.xhr.onerror (C:\Users\Tomas\source\repos\ReactGoalTrackingWebsite\ReactGoalTrackingWebsite\ClientApp\node_modules\whatwg-fetch\fetch.js:436:16)alTrackingWebsite\ClientApp\node_modules\whatwg-
The error happens because the components you rendered in test do not get a correct URL . Let's say :
Your ASP.NET Core listens on http://localhost:5001
Your React Dev Server listens on port 57301
When you run the test by npm test, it will render those react components. However, if your react components fetch requests from server when mounted, it has no idea about the correct server port and then throw an error of Network request failed .
To fix the bug , simply invoke the following command :
react-scripts test --env=jsdom --testURL=https://localhost:50001/
Or change the npm test script in your package.json into :
"scripts": {
"start": "rimraf ./build && react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom --testURL=https://localhost:50001/",
"eject": "react-scripts eject"
}
Update :
if you're using fetch api , don't forget to mock a fetch :
"devDependencies": {
"jest-fetch-mock": "^1.6.6"
}
setup :
global.fetch = require('jest-fetch-mock')
I would like to have proxy in my react client, my package.json contains:
...
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"proxy": {
"/auth/google": {
"target": "http://localhost:5000"
}
},
...
But when I ran it, I got error
When specified, "proxy" in package.json must be a string.
[1] Instead, the type of "proxy" was "object".
[1] Either remove "proxy" from package.json, or make it a string.
I tried to convert to string, no errors but proxy is not working
"proxy": "http://localhost:5000"
My App.js
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>hey there</p>
Sign In With Google
</header>
</div>
The issue that you are facing is because of CRA v2.
Firstly, you will not require any additional configuration if you are just using a plain string in your proxy. But the moment you use an object, you are using advanced configuration.
So, you would have to follow the steps listed below:
Install http-proxy-middleware by typing npm i --save http-proxy-middleware
Remove the entries from package.json:
"proxy": {
"/auth/google": {
"target": "http://localhost:5000"
}
}
Now create a setup file for your proxy. You should name it setupProxy.js in your src folder on the client side and type the following code:
const proxy = require('http-proxy-middleware');
module.exports = function(app) {
app.use(proxy('/auth/google',
{ target: 'http://localhost:5000/' }
));
}
for more info check this
I think it is "create-react-app" issue.
You can go to https://github.com/facebook/create-react-app/issues/5103
to migration to the new proxy handling method.
For short, you just need to install a new library called "http-proxy-middleware"
npm install http-proxy-middleware --save
And then create a new file "src/setupProxy.js", and type
const proxy = require('http-proxy-middleware');
module.exports = function(app) {
app.use(proxy('/auth/google', { target: 'http://localhost:5000/' }));
};
Hope this can solve your problem, happy hacking!
First, install http-proxy-middleware using npm or Yarn:
$ npm install http-proxy-middleware --save
$ # or
$ yarn add http-proxy-middleware
Next, create src/setupProxy.js and place the following contents in it:
const proxy = require('http-proxy-middleware')
module.exports = function(app) {
// ...
}
Now, migrate each entry in your proxy object one by one, e.g.:
"proxy": {
"/api": {
"target": "http://localhost:5000/"
},
"/*.svg": {
"target": "http://localhost:5000/"
}
}
Place entries into src/setupProxy.js like so:
const proxy = require('http-proxy-middleware')
module.exports = function(app) {
app.use(proxy('/api', { target: 'http://localhost:5000/' }))
app.use(proxy('/*.svg', { target: 'http://localhost:5000/' }))
}
You can also use completely custom logic there now!
I have got this working response from this link and hence sharing-https://github.com/facebook/create-react-app/issues/5103
For people in 2020,
Install http-proxy-middleware by typing npm i --save http-proxy-middleware inside the client folder.
Remove the entries from package.json:
"proxy": {
"/auth/google": {
"target": "http://localhost:5000"
}
}
Now create a setup file for your proxy. You should name it setupProxy.js in your src folder on the client side and type the following code:
const { createProxyMiddleware } = require("http-proxy-middleware");
module.exports = function (app) {
app.use(
createProxyMiddleware("/auth/google", { target: "http://localhost:5000/" })
);
};
PS: You don't need to include setupProxy.js anywhere in server.js or index.js. just copy and paste.
The following worked for me:
Remove "proxy" from your package.json.
Install 'http-proxy-middleware' in the client directory. To do this, cd into the client directory and run "npm i --save http-proxy-middleware". Then, create a new file in the src directory of your client called "setupProxy.js". Place the following code in this file:
const { createProxyMiddleware } = require('http-proxy-middleware');
const proxy = require('http-proxy-middleware');
module.exports = function(app) {
app.use(createProxyMiddleware('/api/', // replace with your endpoint
{ target: 'http://localhost:8000' } // replace with your target
));
}
restart the server, and you should be good to go.
Change the proxy to something like this and hope it will work as it worked for me.
"proxy": "http://localhost:5000/auth/google"
At this moment i'm using React 16.8.13 this works fine:
1- delete "proxy": {***} from package.json file
2- type npm install http-proxy-middleware
3- create the file src/setupProxy.js
4-insert the code as following:
const {createProxyMiddleware} = require('http-proxy-middleware');
module.exports = (app) => {
app.use(
createProxyMiddleware('/endpoint/*', {
target: 'http://address/',
secure: false,
}),
);
};
If you need to proxy requests and rewrite urls, for example localhost:3000/api/backend/some/method to https://api-server.example.com/some/method, you need to use pathRewrite option also:
const {createProxyMiddleware} = require("http-proxy-middleware");
module.exports = function(app) {
app.use(
"/api/backend",
createProxyMiddleware({
target: "https://api-server.example.com",
changeOrigin: true,
pathRewrite: {
"^/api/backend": "",
},
})
);
};
install "http-proxy-middleware" into your client, "not inside server".
Add setupProxy.js inside of your client/src/ directory.
(should be like this: client/src/setupProxy.js)
Add the below lines to it.
const proxy = require("http-proxy-middleware");
module.exports = app => {
app.use(proxy("/auth/google", { target: "http://localhost:5000/" }));
};
That's it, get inside of your google dev console and add localhost:3000/auth/google/callback to your project.
https://github.com/facebook/create-react-app/issues/5103
Move advanced proxy configuration to src/setupProxy.js
This change is only required for individuals who used the advanced proxy configuration in v1.
To check if action is required, look for the proxy key in package.json. Then, follow the table below.
I couldn't find a proxy key in package.json
No action is required!
The value of proxy is a string (e.g. http://localhost:5000)
No action is required!
The value of proxy is an object
Follow the migration instructions below.
If your proxy is an object, that means you are using the advanced proxy configuration.
Again, if your proxy field is a string, e.g. http://localhost:5000, you do not need to do anything. This feature is still supported and has the same behavior.
First, install http-proxy-middleware using npm or Yarn:
$ npm install http-proxy-middleware --save
$ # or
$ yarn add http-proxy-middleware
Next, create src/setupProxy.js and place the following contents in it:
const proxy = require('http-proxy-middleware')
module.exports = function(app) {
// ...
}
Now, migrate each entry in your proxy object one by one, e.g.:
"proxy": {
"/api": {
"target": "http://localhost:5000/"
},
"/*.svg": {
"target": "http://localhost:5000/"
}
}
Place entries into src/setupProxy.js like so:
const proxy = require('http-proxy-middleware')
module.exports = function(app) {
app.use(proxy('/api', { target: 'http://localhost:5000/' }))
app.use(proxy('/*.svg', { target: 'http://localhost:5000/' }))
}
You can also use completely custom logic there now! This wasn't possible before.
It's worked.
app.use(
'/api',
proxy({ target: 'http://www.example.org', changeOrigin: true })
);
changeOrigin:true
In my cases i didn't need src/setupProxy.js...
I do that with axios... Check About Axios Proxy
Check in node library if you have it or not: http-proxy-middleware is optional i didn't need it!!!
Just try to restart server side, and that's it!!!
Add to check:
componentDidMount(){
axios.get('/api/path-you-want').then(response=>{
console.log(response)
})
}
This is related to a bug in create-react-app version2.
Just run
$ npm install react-scripts#next --save
$ # or
$ yarn add react-scripts#next
Answer found at:
https://github.com/facebook/create-react-app/issues/5103
...
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"proxy": {
"/auth/google": {
"target": "http://localhost:5000"
}
},
...
When specified, "proxy" in package.json must be a string.
Just change `"proxy": "http://localhost:5000"` and you are good to go.
If that doesn't solve the problem then register your proxy using **http-proxy-middleware**
$ npm install http-proxy-middleware --save
$ # or
$ yarn add http-proxy-middleware
Then create setypProxy.js file under src directory the put the following code.
const proxy = require('http-proxy-middleware');
module.exports = app => {
app.use(
proxy('/auth/google', {
target: 'http://localhost:5000'
})
);
app.use(
proxy('/auth/facebook', {
target: 'http://localhost:6000'
})
);
};
Create a setupProxy.js file inside the src folder and copy-paste the below code.
const { createProxyMiddleware } = require("http-proxy-middleware");
module.exports = function (app) {
app.use(
createProxyMiddleware("/auth/google", {
target: "http://localhost:5000/",
})
);
};
This worked for me (just as several people have already replied). But I write this just in case someone asks whether this is still a valid answer in 2021.
Delete this from your package.json file:
"proxy": {
"/auth/google": {
"target": "http://localhost:5000"
}
Install proxy middleware by running npm install --save http-proxy-middleware.
Create setupProxy.js file in your src (right next to the index.js file) file on the frontend.
In that setupProxy.js file put:
const proxy = require('http-proxy-middleware');
module.exports = function(app) {
app.use(proxy('/auth/google',
{ target: 'http://localhost:5000/' }
));
Of course, your port can be anything. It does not have to be 5000. Where ever you are running your backend service at.
That is it. You do not have to import this file anywhere. It works as it is.
After creating a file in the client side (React app ) called
src/setupProxy.js make sure you restart the server. The package.json file needs to restarted since you were dealing with a file outside the source directory.