Electron react app hot reloading from src folder not working - reactjs

I'm trying to use the hot reload feature in development mode of a react electron app.
It use to work well but I'm having issues with the latest electron version 15+.
I am able to run the app from the build folder but anytime I want to make a change I need to run the build command therefor the hot reloading is not working.
I have change the package.json path to use the public folder. But I get a blank page. however if I make a change to the main.js folder, the app reload but not when I make a change within the src folder of the app itself.
In my package.json if I use the public folder the app is not loading. It only loads when I use the build folder.
"version": "0.1.0",
"private": false,
"main": "build/main.js",
"homepage": "./",
"files": [
"public/**/*",
"node_modules/**/*"
],
"scripts": {
"electron-dev": "set ELECTRON_START_URL=http://localhost:3000 && electron . --overwrite --asar=true --platform=win --arch=x64 --icon=icons/icon.png --prune=true --out=build",
"electron": "electron .",
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"dist": "electron-builder --win"
},
"devDependencies": {
"electron": "15.3.0",
"electron-builder": "^22.13.1",
"electron-reload": "^2.0.0-alpha.1",
"electron-reloader": "^1.2.3"
}
In my public/main.js file;
require('electron-reloader')(module,
{
debug: true,
watchRenderer: true
});
const startUrl = url.format({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file:',
slashes: true
});
I can also see the watcher in the console;
Watched paths: {
'..': [
'public'
],
'.': [
'assets',
'favicon.ico',
'icon.png',
'index.html',
'logo-black.png',
'logo.png',
'logo.svg',
'main.js',
'manifest.json',
'package.json',
'preload.js',
'robots.txt'
],
assets: [...]
It seams like the public folder is not being watched at all. When ever I make a change to my app inside the src folder. nothing get's picked up. The src folder is not being watched/
What should I look for?
Please comment if you would like to see more code.
[UPDATE]
The start url is not getting picked up in the .env nor in the inline command.
As a temporary solution I am running the build & electron.
Very counter productive!

One potential hacky solution you could use is just using nodemon, and make it re-launch electron each time you change any content inside the src directory. In order to do this you would have to run npm install --save-dev nodemon. Then in your packages.json put in the following
"dev": "NODE_ENV=development nodemon --watch ./src/**/* --watch . --exec 'npm run electron'"
With respect to the actual question, why are you using electron-reloader over just using electron-reload. It is easy to setup, just by adding the following to your code
require('electron-reload')(__dirname, {
electron: path.join(__dirname, 'node_modules', '.bin', 'electron'),
hardResetMethod: 'exit'
});

Related

Problems to run Electron/React in development after adding Realm/webpack-node-externals libs

I'm developing a desktop application combining ElectronJs with ReactJS, more specifically create-react-app. Following the line of a mobile application that I had already developed for offline operation, I chose to use RealDB for data storage.
https://www.mongodb.com/docs/realm/sdk/node/integrations/electron-cra/
Following the documentation and its own recommendations, I added the lib. I had to make changes to my code, such as using an alternative craco within create-react-app, to use the webpack-node-externals library, but after the addition it has been boring to run my application for development i spend a lot of time on reloads or rebuilds.
The best alternative I found was to combine electronmon with nodemon, I use nodemon to detect changes in src files, rebuilt the code and so that I can reload electron when changes in the build folder are detected I use electronmon, but I still lose one considerable time and does not always work as expected
package.json:
{
"scripts": {
"start": "electron .",
"build": "craco build",
"electron:start": "concurrently -k \"nodemon --watch ./src --exec npm run build\" \"wait-on ./build/index.html && electronmon .\"",
"electron:package:mac": "npm run build && electron-builder -m -c.extraMetadata.main=build/electron.js",
"electron:package:win": "npm run build && electron-builder -w -c.extraMetadata.main=build/electron.js",
"electron:package:linux": "npm run build && electron-builder -l -c.extraMetadata.main=build/electron.js"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
"last 1 electron version"
],
"development": [
"last 1 electron version"
]
},
"electronmon": {
"patterns": [
"!default.realm.lock**",
"!default.realm**",
"!package.json**"
]
}
}
craco.config.js
const nodeExternals = require("webpack-node-externals");
module.exports = {
style: {
postcss: {
plugins: [require("tailwindcss"), require("autoprefixer")],
},
},
webpack: {
configure: {
externals: [
nodeExternals({
allowlist: [/webpack(\/.*)?/, "electron-devtools-installer"],
}),
],
},
},
};
I wanted to make it clear that the code is working normally, everything is ok, the realm worked, but my development performance was very harmed. I needed help to find some other way to make it run that didn't waste so much time for a reload of the application

How do I Create Electron App from existing React Project without disturbing the React Project

I have existing React Apps which are published to production web servers but I want to run them from the desktop using Electron. However, I do not want to disturb the React App package.json. I attempted to decouple an existing online tutorial by paachu on Medium but was unsuccessful. It kept failing trying to locate "main...chunk.css" and other resources needed by the React App.
With that said, I have a working React App in directory ./projx/reactApp I would like to create an Electron App in ./projx/electronApp that will build and create a packaged executable using electron-builder. The dev environment is not necessary at this time in that I only need a release package to distribute. Here is a package.json that almost works:
{
"name": "wrappedReact",
"version": "1.0.0",
"main": "./src/electron.js",
"scripts": {
"preclean": "cross-env rm -rf build",
"react-prebuild": "cross-env cp -r ../reactApp/build build",
"build-tsapp": "tsc ./src/electron.ts",
"electron-prebuild": "mv ./src/*.js ../build",
"electron-build": "npm run electron-prebuild && electron-builder",
"build": "npm run preclean && npm run electron-build",
"startdev": "concurrently \"tsc ./src/electron.ts -w\" \"cross-env
NODE_ENV=dev nodemon --exec \"\"wait-on http://localhost:3000 &&
electron src/electron.js\"\""
},
"author": "sfanjoy",
"homepage": "./",
"electron-pack": "build --em.main=build/electron.js",
"build": {
"appId": "com.example.reactApp",
"productName": "ReactApp",
"copyright": "Copyright © 2019 sfanjoy",
"files": [
"build/**/*",
"node_modules/**/*"
],
"directories": {
"buildResources": "assets"
},
"win": {
"target": "portable",
"icon": "assets/app.ico"
}
},
"dependencies": {
"#types/electron": "^1.6.10"
},
"devDependencies": {
"#types/electron": "^1.6.10",
"concurrently": "^4.1.1",
"cross-env": "^5.2.1",
"electron-builder": "^21.2.0",
"electron-is-dev": "^1.1.0",
"nodemon": "^1.19.1",
"typescript": "^3.5.2",
"wait-on": "^3.2.0"
}
}
I think the solution is with electron-builder if it would allow you to inject the ./src/electron.js into the prebuilt reactApp\dist\win-unpacked\resources\app.asar. I could then copy the reactApp/build directory, inject into the asar, and call electron-builder.
This by far (IMO) is the best starting setup (Boilerplate) I have come accross:
https://github.com/nateshmbhat/electron-react-ts-starter/

HMR not working when using nodemon

I have an app that is using express to serve some API calls and webpack to server some static assets in development. All works ok until I bring nodemon into the setup.
When I run my app using nodemon I get this error when I update a file on the React side (client side).
GET http://localhost:3004/__webpack_hmr
net::ERR_INCOMPLETE_CHUNKED_ENCODING
If I run my app without nodemon the HMR works perfect and all updates and reloads the React modules.
In my package.json file I have the following scripts.
The start one works fine but the dev one using nodemon causes the error when a change is made to a React component.
"scripts": {
"start": "node server/app.js",
"dev": "nodemon server/app.js",
"build": "cross-env NODE_ENV=production webpack --config ./webpack/webpack.prod.config.js --progress --colors",
"heroku-postbuild": "npm run build"
},
Any ideas what might be causing this?
Here is my entry point in my webpack config file.
entry: [
`${ROOT_DIR}/js/index`,
'webpack-hot-middleware/client'
]
Here is my webpack setup with webpackHotMiddleware which I call in my app.js and pass in App to it. App being my express server.
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');
const webpackHotMiddleware = require('webpack-hot-middleware');
const webpackConfig = require('../../webpack/webpack.dev.config.js');
const compiler = webpack(webpackConfig);
const devOptions = {
noInfo: true,
publicPath: webpackConfig.output.publicPath,
stats: { colors: true },
historyApiFallback: true
}
// WEBPACK MIDDLEEWARE
function setupWebpackMiddleware( app ){
app.use(webpackHotMiddleware(compiler));
app.use(webpackDevMiddleware(compiler, devOptions));
}
module.exports = {setupWebpackMiddleware}
Using the following versions.
"webpack": "^2.2.1"
"webpack-dev-middleware": "^1.10.0",
"webpack-dev-server": "~1.16.2",
"webpack-hot-middleware": "^2.16.1"

How do I change `src` folder to something else in create-react-app

I'd like to know if it's possible using react-script to rename src to something else like app folder
You can use react-app-rewired to override react paths configuration.
In my case, I can change the paths in config-overrides.js file
const path = require('path');
module.exports = {
paths: function (paths, env) {
paths.appIndexJs = path.resolve(__dirname, 'mysrc/client.js');
paths.appSrc = path.resolve(__dirname, 'mysrc');
return paths;
},
}
Not sure if this answers your question but I'll give it a shot. My directory structure looks like this:
/root
--/app
----/build
----/public
------index.html
----/src
------index.js
app.js
package.js
My /root/package.json has this in it:
"scripts": {
"build": "cd app && npm run build",
"start": "node app.js",
"serve": "cd app && npm run start"
},
"dependencies": {
"express": "^4.8.0",
"react": "^16.2.0",
"react-dom": "^16.2.0",
"react-router": "^4.2.0",
"react-router-dom": "^4.2.2",
"react-scripts": "^1.0.17"
},
and my /root/app/package.json looks like this:
"scripts": {
"build": "react-scripts build",
"start": "set PORT=3000 && react-scripts start"
},
"dependencies": {
"react-scripts": "^1.0.17"
}
To run the development version of Reactjs, in the /root I can just npm run serve to serve up the dev version.
I am using node and express, so to run the production version of Reactjs,
in the /root I can just npm run build to create the /root/app/build directory. I have a router that looks like this:
var options = {root : config.siteRoot + '/app/build'};
mainRte.all('/', function(req, res) {
console.log('In mainRte.all Root');
res.sendFile('index.html', options);
});
so when I run /root/app.js in node and surf to "/" it opens up /root/app/public/index.html and then /root/app/index.js.
Hopefully that helps.
react-app-rewired allows for this exact customization.
1
Install react-app-rewired as a dev dependency:
npm install --save-dev react-app-rewired
2
In package.json, change these lines
"scripts": {
"react-start": "react-scripts start",
"react-build": "react-scripts build",
"react-test": "react-scripts test",
...
}
to
"scripts": {
"react-start": "react-app-rewired start",
"react-build": "react-app-rewired build",
"react-test": "react-app-rewired test",
...
}
3
Create a config-overrides.json file in your project directory root with the following contents:
const paths = require('react-scripts/config/paths')
const path = require('path')
// Make the "app" folder be treated as the "src" folder
paths.appSrc = path.resolve(__dirname, 'app')
// Tell the app that "src/index.js" has moved to "app/index.js"
paths.appIndexJs = path.resolve(__dirname, 'app/index.js')
Now your app folder is the new src!
You can also customize many other things, such as the name of the "public" folder:
paths.appPublic = path.resolve(__dirname, 'subfolder/public')
paths.appHtml = path.resolve(__dirname, 'subfolder/public/index.html')
And you can also change the location of package.json and node_modules. See here for the full list.
I know this is an old question but I'm still gonna post my solution since it might help someone.
I got it working by doing the following:
Run npm run eject. This exposes some internal configuration stuff from create-react-app
Open your package.json and edit the respective regexes under jest.collectCoverageFrom and jest.testMatch to match your test path
Alter the paths for appSrc, appIndexJs and testsSetup in the config/paths.js file
T0astBread's answer is nearly perfect, but there's an additional reference to "src" that he missed inside modules.js.
Specifically:
return {
src: paths.appSrc,
};
needs to be changed to
return {
newSrcName: paths.appSrc,
};
This is a great question and a valid scenario for changing this folder name is when migrating old react projects to CRA.
Here's another approach I found that breaks less things:
Create a symlink with:
ls -s ./app src
Then add this in config-overrides.js, to allow webpack to process the symlink:
module.exports = (config, ...rest) => {
return { ...config, resolve: { ...config.resolve, symlinks: false } };
};
Then install react-app-rewired and add this to your package.json:
"start": "react-app-rewired start",
While Cong Dan Luong's answer is correct as far as renaming the folder goes, it will break testing with jest. You need to expand the config-overrides.js module.exports part with the following:
module.exports = {
jest: function(config) {
config.collectCoverageFrom = ['client/**/*.{js,jsx,ts,tsx}', '!client/**/*.d.ts'];
config.testMatch = [
'<rootDir>/client/**/__tests__/**/*.{js,jsx,ts,tsx}',
'<rootDir>/client/**/*.{spec,test}.{js,jsx,ts,tsx}',
];
config.roots = ['<rootDir>/client'];
return config;
},
// The paths config
paths: function(paths, env) {
paths.appIndexJs = path.resolve(__dirname, 'client/index.js');
paths.appSrc = path.resolve(__dirname, 'client');
return paths;
},
};
In my above example I am using 'client' instead of 'src'. npm test now works.
Perhaps a symbolic link might address your reasons for wanting to do this:
ln -s ./src/ ./app
The src folder will remain but you can work with it as if it was the app folder.
If, like me you're using vscode you can also do:
Cmd-shift-p search workspace settings, and add the following:
{
"files.exclude": {
"src/": true
}
}
You could do similarly with other editors
Create file in root of your project, insert this code and run.
const fs = require('fs');
const path = './node_modules/react-scripts/config/paths.js';
const folder = 'app';
fs.readFile(path, 'utf8', (err, data) => {
if (err) throw err;
data = data.replace(/src/g, folder);
fs.writeFile(path, data, 'utf8');
});

Angular2 load script conditionally using Angular CLI?

Can I load scripts conditionally using Angular CLI???
In this file, I want to load one script depending on the enviroment or a variable. So In production I want to load a script while in develop not.
Is there a way to do that? How?
angular-cli.json
...
"styles": [
"../node_modules/bootstrap/dist/css/bootstrap.css",
"../node_modules/font-awesome/css/font-awesome.min.css",
],
"scripts": [
"../node_modules/jquery/dist/jquery.js",
"../node_modules/ion-rangeslider/js/ion.rangeSlider.js",
"../node_modules/web-animations-js/web-animations.min.js",
<---- LOAD HERE ONE SCRIPT DEPENDING ON ENVIRONMENT OR VARIABLE
],
"environments": {
"source": "environments/environment.ts",
"dev": "environments/environment.ts",
"prod": "environments/environment.prod.ts"
}
...
While #yuzuri suggested a very eleegnat solution - it requires you to edit a node module which is not a good idea..
Here is simple workaround:
You can edit your "scripts" section under package.json file to have that:
"start": "cp angular-cli-dev.json angular-cli.json && ng serve"
"build": "cp angular-cli-prod.json angular-cli.json && ng build"
Then you should rename your angular-cli.json file to angular-cli-dev.json and angular-cli-prod.json
Each should have different configuration - in my case, different scripts in "scripts" section.
Hope that helps while we wait for an official solution
The .angular-cli.json supports configuration for multiple apps. Therefore we can put completely different configuration with different scripts/styles for the same app.
"apps": [
{
"styles": [
"styles.css"
],
"scripts": [ ],
"environmentSource": "environments/environment.ts",
"environments": {
"dev": "environments/environment.ts",
"prod": "environments/environment.prod.ts",
"local": "environments/environment.local.ts"
}
},
{
"styles": [
"styles.css",
"../node_modules/select2/dist/css/select2.min.css"
],
"scripts": [
"../node_modules/jquery/dist/jquery.min.js",
"../node_modules/select2/dist/js/select2.full.min.js"
],
"environmentSource": "environments/environment.ts",
"environments": {
"dev": "environments/environment.ts",
"prod": "environments/environment.prod.ts",
"local": "environments/environment.local.ts"
}
}
To serve the default app:
$ ng serve --app=0
or
$ ng serve --app 0
To serve the app with local environment:
$ ng serve --app=1 --env=local --port=8091

Resources