patch: development environment

Add webpack dev server and hot module reloading to get live changes and reloads without reloading the whole electron app.

This patch also runs the development environment in development mode, which is much, much faster on builds and rebuilds.
This commit is contained in:
Zane Hitchcox 2021-04-21 09:43:39 -04:00
parent 33dd07c675
commit 1ee110bc95
8 changed files with 3060 additions and 16244 deletions

View File

@ -38,6 +38,7 @@ import * as exceptionReporter from './modules/exception-reporter';
import * as osDialog from './os/dialog'; import * as osDialog from './os/dialog';
import * as windowProgress from './os/window-progress'; import * as windowProgress from './os/window-progress';
import MainPage from './pages/main/MainPage'; import MainPage from './pages/main/MainPage';
import './css/main.css';
window.addEventListener( window.addEventListener(
'unhandledrejection', 'unhandledrejection',
@ -339,7 +340,7 @@ window.addEventListener('beforeunload', async (event) => {
} }
}); });
async function main() { export async function main() {
await ledsInit(); await ledsInit();
ReactDOM.render( ReactDOM.render(
React.createElement(MainPage), React.createElement(MainPage),
@ -356,5 +357,3 @@ async function main() {
}, },
); );
} }
main();

View File

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Etcher</title>
<link rel="stylesheet" type="text/css" href="index.css">
</head>
<body>
<main id="main"></main>
<script src="http://localhost:3030/gui.js"></script>
</body>
</html>

10
lib/gui/app/renderer.ts Normal file
View File

@ -0,0 +1,10 @@
// @ts-nocheck
import { main } from './app';
if (module.hot) {
module.hot.accept('./app', () => {
main();
});
}
main();

19166
npm-shrinkwrap.json generated

File diff suppressed because it is too large Load Diff

View File

@ -22,10 +22,10 @@
"test-shared": "electron-mocha --recursive --reporter spec --require ts-node/register --require-main tests/gui/allow-renderer-process-reuse.ts --full-trace --no-sandbox tests/shared/**/*.ts", "test-shared": "electron-mocha --recursive --reporter spec --require ts-node/register --require-main tests/gui/allow-renderer-process-reuse.ts --full-trace --no-sandbox tests/shared/**/*.ts",
"test": "npm run lint && npm run test-gui && npm run test-shared && npm run test-spectron && npm run sanity-checks", "test": "npm run lint && npm run test-gui && npm run test-shared && npm run test-spectron && npm run sanity-checks",
"sanity-checks": "bash scripts/ci/ensure-all-file-extensions-in-gitattributes.sh", "sanity-checks": "bash scripts/ci/ensure-all-file-extensions-in-gitattributes.sh",
"start": "./node_modules/.bin/ts-node scripts/start.ts", "start": "./node_modules/.bin/electron .",
"postshrinkwrap": "ts-node ./scripts/clean-shrinkwrap.ts", "postshrinkwrap": "ts-node ./scripts/clean-shrinkwrap.ts",
"webpack": "webpack", "webpack": "webpack",
"watch": "webpack --watch", "watch": "webpack serve --no-optimization-minimize --config ./webpack.dev.config.ts",
"concourse-build-electron": "npm run webpack", "concourse-build-electron": "npm run webpack",
"concourse-test": "npx npm@6.14.8 test", "concourse-test": "npx npm@6.14.8 test",
"concourse-test-electron": "npx npm@6.14.8 test" "concourse-test-electron": "npx npm@6.14.8 test"
@ -110,6 +110,7 @@
"sinon": "^9.0.2", "sinon": "^9.0.2",
"spectron": "^14.0.0", "spectron": "^14.0.0",
"string-replace-loader": "^3.0.1", "string-replace-loader": "^3.0.1",
"style-loader": "^2.0.0",
"styled-components": "^5.1.0", "styled-components": "^5.1.0",
"sudo-prompt": "github:zvin/sudo-prompt#7cdede2f0da28fbcc2db48402d7d935f3a825c91", "sudo-prompt": "github:zvin/sudo-prompt#7cdede2f0da28fbcc2db48402d7d935f3a825c91",
"sys-class-rgb-led": "^3.0.0", "sys-class-rgb-led": "^3.0.0",
@ -117,8 +118,10 @@
"ts-node": "^9.1.1", "ts-node": "^9.1.1",
"tslib": "^2.0.0", "tslib": "^2.0.0",
"typescript": "^4.2.2", "typescript": "^4.2.2",
"url-loader": "^4.1.1",
"uuid": "^8.1.0", "uuid": "^8.1.0",
"webpack": "^5.11.0", "webpack": "^5.11.0",
"webpack-cli": "^4.2.0" "webpack-cli": "^4.2.0",
"webpack-dev-server": "^3.11.2"
} }
} }

View File

@ -1,16 +0,0 @@
import { watch } from 'fs/promises';
import { spawn } from 'child_process';
const startElectron = () =>
spawn('./node_modules/.bin/electron', ['.'], {
stdio: 'inherit',
});
(async () => {
const watcher = watch('./generated', { recursive: true });
let electronProcess = startElectron();
for await (const _event of watcher) {
electronProcess.kill();
electronProcess = startElectron();
}
})();

View File

@ -17,7 +17,6 @@
import * as CopyPlugin from 'copy-webpack-plugin'; import * as CopyPlugin from 'copy-webpack-plugin';
import { readdirSync } from 'fs'; import { readdirSync } from 'fs';
import * as _ from 'lodash'; import * as _ from 'lodash';
import * as MiniCssExtractPlugin from 'mini-css-extract-plugin';
import * as os from 'os'; import * as os from 'os';
import outdent from 'outdent'; import outdent from 'outdent';
import * as path from 'path'; import * as path from 'path';
@ -158,7 +157,12 @@ const commonConfig = {
rules: [ rules: [
{ {
test: /\.css$/, test: /\.css$/,
use: 'css-loader', use: ['style-loader', 'css-loader'],
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
loader: 'file-loader',
options: { name: renameNodeModules },
}, },
{ {
test: /\.svg$/, test: /\.svg$/,
@ -348,10 +352,18 @@ const guiConfig = {
__filename: true, __filename: true,
}, },
entry: { entry: {
gui: path.join(__dirname, 'lib', 'gui', 'app', 'app.ts'), gui: path.join(__dirname, 'lib', 'gui', 'app', 'renderer.ts'),
}, },
plugins: [ plugins: [
...commonConfig.plugins, ...commonConfig.plugins,
new CopyPlugin({
patterns: [
{ from: 'lib/gui/app/index.html', to: 'index.html' },
// electron-builder doesn't bundle folders named "assets"
// See https://github.com/electron-userland/electron-builder/issues/4545
{ from: 'assets/icon.png', to: 'media/icon.png' },
],
}),
// Remove "Download the React DevTools for a better development experience" message // Remove "Download the React DevTools for a better development experience" message
new BannerPlugin({ new BannerPlugin({
banner: '__REACT_DEVTOOLS_GLOBAL_HOOK__ = { isDisabled: true };', banner: '__REACT_DEVTOOLS_GLOBAL_HOOK__ = { isDisabled: true };',
@ -390,42 +402,4 @@ const childWriterConfig = {
}, },
}; };
const cssConfig = { export default [guiConfig, etcherConfig, childWriterConfig];
mode: 'production',
optimization: {
minimize: false,
},
module: {
rules: [
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, 'css-loader'],
},
{
test: /\.(woff|woff2|eot|ttf|otf|svg)$/,
loader: 'file-loader',
options: { name: renameNodeModules },
},
],
},
plugins: [
new MiniCssExtractPlugin({ filename: '[name].css' }),
new CopyPlugin({
patterns: [
{ from: 'lib/gui/app/index.html', to: 'index.html' },
// electron-builder doesn't bundle folders named "assets"
// See https://github.com/electron-userland/electron-builder/issues/4545
{ from: 'assets/icon.png', to: 'media/icon.png' },
],
}),
],
entry: {
index: path.join(__dirname, 'lib', 'gui', 'app', 'css', 'main.css'),
},
output: {
publicPath: '',
path: path.join(__dirname, 'generated'),
},
};
module.exports = [cssConfig, guiConfig, etcherConfig, childWriterConfig];

22
webpack.dev.config.ts Normal file
View File

@ -0,0 +1,22 @@
import configs from './webpack.config';
import { WebpackOptionsNormalized } from 'webpack';
import * as fs from 'fs';
const [
guiConfig,
etcherConfig,
childWriterConfig,
] = (configs as unknown) as WebpackOptionsNormalized[];
configs.forEach((config) => {
config.mode = 'development';
});
guiConfig.devServer = {
hot: true,
port: 3030,
};
fs.copyFileSync('./lib/gui/app/index.dev.html', './generated/index.html');
export default [guiConfig, etcherConfig, childWriterConfig];