rebuiltron 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +153 -0
- package/bin/index.js +14 -0
- package/buildApp.js +33 -0
- package/checkSetup.js +63 -0
- package/configurations/base.js +121 -0
- package/configurations/main.js +17 -0
- package/configurations/preloads.js +22 -0
- package/configurations/renderers.js +53 -0
- package/createDevServer.js +75 -0
- package/helpers/environment.js +6 -0
- package/helpers/logger.js +55 -0
- package/helpers/paths.js +22 -0
- package/helpers/spinnies.js +7 -0
- package/helpers/utils.js +48 -0
- package/loaders/images.js +24 -0
- package/loaders/javascript.js +28 -0
- package/loaders/style.js +98 -0
- package/package.json +60 -0
- package/rebuiltronConfig.js +18 -0
- package/scripts/build.js +48 -0
- package/scripts/start.js +29 -0
- package/webpack.config.js +7 -0
- package/webpackDevServer.config.js +32 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023-present Arkellys
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# Rebuiltron
|
|
2
|
+
|
|
3
|
+
A tool made to easily build an offline **React/Electron** app using webpack.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Why
|
|
8
|
+
|
|
9
|
+
The idea behind Rebuiltron was to migrate one of my project initially created with the deprecated [CRA](https://create-react-app.dev/) to a maintained tool configured with Electron in mind. As such, it has been developed using [react-scripts](https://github.com/facebook/create-react-app/tree/main/packages/react-scripts) as a base, but heavily edited and stripped of a lot of features.
|
|
10
|
+
|
|
11
|
+
> [!IMPORTANT]
|
|
12
|
+
> Since I made Rebuiltron specifically for one of my own projects, I only kept in the configuration what *this* project needed and nothing more. Except for the entry points and some SASS options, **Rebuiltron doesn't offer any configurable options**. If you are looking to create a new Electron/React app, or even migrating an existing CRA app, you should probably take a look at [electron-vite](https://electron-vite.org/) instead.
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
## Features
|
|
16
|
+
|
|
17
|
+
Rebuiltron uses webpack with [SWC](https://swc.rs/) to compile JavaScript instead of [Babel](https://babeljs.io/).
|
|
18
|
+
|
|
19
|
+
- Support for multiple windows and preloads
|
|
20
|
+
- Development server taking care of starting Electron
|
|
21
|
+
- Production bundler for React and Electron code
|
|
22
|
+
- Support for React, JSX, SASS, ICSS
|
|
23
|
+
|
|
24
|
+
> [!WARNING]
|
|
25
|
+
> Rebuiltron **doesn't support**: Typescript, Flow, CSS Modules, Jest, and proxying.
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
## Installation
|
|
29
|
+
|
|
30
|
+
```shell
|
|
31
|
+
yarn add rebuiltron -D
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
[**React**](https://react.dev/) and [**Electron**](https://www.electronjs.org/) are required dependencies you must install separately.
|
|
35
|
+
|
|
36
|
+
## Configuration
|
|
37
|
+
|
|
38
|
+
The following documentation assume you already have a basic knowledge of how to use React and Electron.
|
|
39
|
+
|
|
40
|
+
### Folder structure
|
|
41
|
+
|
|
42
|
+
Rebuiltron expects the following folder structure:
|
|
43
|
+
|
|
44
|
+
```js
|
|
45
|
+
my-app
|
|
46
|
+
├── electron/
|
|
47
|
+
│ └── // Main and preload files
|
|
48
|
+
├── public/
|
|
49
|
+
│ └── // Renderer HTML file(s)
|
|
50
|
+
├── src/
|
|
51
|
+
│ └── // Renderer JS file(s)
|
|
52
|
+
└── package.json
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Main entry
|
|
56
|
+
Set the main Electron entry in `package.json`:
|
|
57
|
+
|
|
58
|
+
```json
|
|
59
|
+
{
|
|
60
|
+
"main": "electron/main.js",
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Scripts
|
|
65
|
+
Add Rebuiltron scripts:
|
|
66
|
+
|
|
67
|
+
```json
|
|
68
|
+
{
|
|
69
|
+
"start": "rebuiltron start",
|
|
70
|
+
"build": "rebuiltron build",
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
The `build` command will bundle your code so it's ready for production, but **it will not package it into a working app**. For this task, you need to use a tool such as [Electron Forge](https://www.electronforge.io/) or [electron-builder](https://www.electron.build/index.html).
|
|
75
|
+
|
|
76
|
+
### Browserslist
|
|
77
|
+
|
|
78
|
+
Add your desired [browserslist](https://github.com/browserslist/browserslist) in `package.json`:
|
|
79
|
+
|
|
80
|
+
```json
|
|
81
|
+
{
|
|
82
|
+
"browserslist": "last 2 electron major versions",
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Configuration file
|
|
87
|
+
|
|
88
|
+
At the root of your project, create a `rebuiltron.config.js` file.
|
|
89
|
+
|
|
90
|
+
#### Options:
|
|
91
|
+
|
|
92
|
+
| Option | Type | Required | Description |
|
|
93
|
+
| --- | :---: | :---: | --- |
|
|
94
|
+
| `renderers` | `object` | ✔️ | Renderer entries. It takes the name of the entries as keys and their paths as values. |
|
|
95
|
+
| `preloads` | `object` | ✔️ | Preload entries. It takes the name of the entries as keys and their paths as values. |
|
|
96
|
+
| `sassOptions` | `object` | ❌ | Custom SASS options for `sass-loader`. |
|
|
97
|
+
| `sassOptions.additionalData` | `object` | ❌ | Configuration of `additionalData`. |
|
|
98
|
+
| `sassOptions.additionalData.data` | `string` | ❌ | Data to prepend to SASS files. |
|
|
99
|
+
| `sassOptions.additionalData.exclude` | `Regex` | ❌ | Regex matching the files to exclude from `additionalData`. This is necessary to prevent an `@import loop` error. |
|
|
100
|
+
|
|
101
|
+
#### Example:
|
|
102
|
+
|
|
103
|
+
```js
|
|
104
|
+
module.exports = {
|
|
105
|
+
renderers: {
|
|
106
|
+
index: "./src/index.js",
|
|
107
|
+
worker: "./src/worker.js"
|
|
108
|
+
},
|
|
109
|
+
preloads: {
|
|
110
|
+
worker: "./electron/preloads/worker.js"
|
|
111
|
+
},
|
|
112
|
+
sassOptions: {
|
|
113
|
+
additionalData: {
|
|
114
|
+
data: "@use \"styles/settings\" as *;",
|
|
115
|
+
exclude: /^src\\styles\\.*/
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
> [!NOTE]
|
|
122
|
+
> Your renderers entry file(s) will be automatically injected into your HTML file(s). Thus, make sure you have a corresponding HTML file in the `public` folder for each entry (using the same name).
|
|
123
|
+
|
|
124
|
+
### Environment variables
|
|
125
|
+
|
|
126
|
+
When the development server is running, Rebuiltron exposes a `DEV_LOCAL_URL` variable that you can access on your main process using `process.env.DEV_LOCAL_URL`.
|
|
127
|
+
|
|
128
|
+
```js
|
|
129
|
+
if(!app.isPackaged) {
|
|
130
|
+
appWindow.loadURL(`${process.env.DEV_LOCAL_URL}/index.html`);
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## Usage
|
|
135
|
+
|
|
136
|
+
To run the development server:
|
|
137
|
+
|
|
138
|
+
```shell
|
|
139
|
+
yarn start
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
To create the production build:
|
|
143
|
+
|
|
144
|
+
```shell
|
|
145
|
+
yarn build
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Contributing and feature requests
|
|
149
|
+
|
|
150
|
+
I made Rebuiltron specifically for a project of mine, and for that reason, **I have no plans to add new features nor to accept contributions**, unless required for this project in particular. If you wish to use Rebuiltron but need something that is not available in the current configuration, please feel free to create a fork and change the code to your needs.
|
|
151
|
+
|
|
152
|
+
## License
|
|
153
|
+
MIT
|
package/bin/index.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { exitProcessWithError } = require("../helpers/utils.js");
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
const args = process.argv.slice(2);
|
|
7
|
+
const [script] = args;
|
|
8
|
+
|
|
9
|
+
const scripts = {
|
|
10
|
+
start: () => require("../scripts/start.js"),
|
|
11
|
+
build: () => require("../scripts/build.js")
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
scripts[script]?.() || exitProcessWithError(`Unknown command: \`${script}\``);
|
package/buildApp.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
const fsExtra = require("fs-extra");
|
|
2
|
+
const clearConsole = require("react-dev-utils/clearConsole");
|
|
3
|
+
const webpack = require("webpack");
|
|
4
|
+
const formatWebpackMessages = require("react-dev-utils/formatWebpackMessages");
|
|
5
|
+
const { isEmpty, head } = require("lodash");
|
|
6
|
+
|
|
7
|
+
const paths = require("./helpers/paths");
|
|
8
|
+
const webpackConfig = require("./webpack.config");
|
|
9
|
+
const spinnies = require("./helpers/spinnies");
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
module.exports = (previousFileSizes) => {
|
|
13
|
+
fsExtra.emptyDirSync(paths.appBuild);
|
|
14
|
+
|
|
15
|
+
clearConsole();
|
|
16
|
+
spinnies.add("build", { text: "Creating production build" });
|
|
17
|
+
|
|
18
|
+
const compiler = webpack(webpackConfig);
|
|
19
|
+
|
|
20
|
+
return new Promise((resolve, reject) => {
|
|
21
|
+
compiler.run((error, stats) => {
|
|
22
|
+
const statsData = error
|
|
23
|
+
? { errors: [error?.message || error], warnings: [] }
|
|
24
|
+
: stats.toJson({ all: false, warnings: true, errors: true });
|
|
25
|
+
|
|
26
|
+
const { errors, warnings } = formatWebpackMessages(statsData);
|
|
27
|
+
|
|
28
|
+
return !isEmpty(errors)
|
|
29
|
+
? reject(["Failed to compile.\n", head(errors)])
|
|
30
|
+
: resolve({ stats, previousFileSizes, warnings });
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
};
|
package/checkSetup.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
const fs = require("fs");
|
|
2
|
+
|
|
3
|
+
const detect = require("detect-port");
|
|
4
|
+
|
|
5
|
+
const { isEnvProduction } = require("./helpers/environment");
|
|
6
|
+
const rebuiltronConfig = require("./rebuiltronConfig");
|
|
7
|
+
const { resolveApp } = require("./helpers/utils");
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Checks whether the default port is available, otherwise resolves with the next available port.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
const checkPort = new Promise(async (resolve) => {
|
|
14
|
+
if (isEnvProduction) resolve();
|
|
15
|
+
|
|
16
|
+
const defaultPort = 3000;
|
|
17
|
+
const nextAvailablePort = await detect(defaultPort);
|
|
18
|
+
|
|
19
|
+
resolve(nextAvailablePort);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Checks whether Electron's entry point is set.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
const checkEntryPoint = new Promise((resolve, reject) => {
|
|
27
|
+
const packageJsonPath = resolveApp("package.json");
|
|
28
|
+
const { main } = require(packageJsonPath);
|
|
29
|
+
|
|
30
|
+
if (!main) {
|
|
31
|
+
reject([
|
|
32
|
+
"No entry point found for Electron.",
|
|
33
|
+
"Please add a `main` field in `package.json`."
|
|
34
|
+
]);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
resolve();
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Checks whether Rebuiltron's config file exists and contains the required fields.
|
|
42
|
+
*/
|
|
43
|
+
|
|
44
|
+
const checkAppConfig = new Promise((resolve, reject) => {
|
|
45
|
+
const configPath = resolveApp(rebuiltronConfig.configFileName);
|
|
46
|
+
|
|
47
|
+
if (!fs.existsSync(configPath)) {
|
|
48
|
+
reject([
|
|
49
|
+
"Not configuration file found.",
|
|
50
|
+
`Please create a \`${rebuiltronConfig.configFileName}\` file.`
|
|
51
|
+
]);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const { preloads, renderers } = require(configPath);
|
|
55
|
+
|
|
56
|
+
if (!preloads) reject("Configuration error: `preloads` field is required.");
|
|
57
|
+
if (!renderers) reject("Configuration error: `renderers` field is required.");
|
|
58
|
+
|
|
59
|
+
resolve();
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
module.exports = Promise.all([checkPort, checkEntryPoint, checkAppConfig]);
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
const { createHash } = require("crypto");
|
|
2
|
+
|
|
3
|
+
const HtmlWebpackPlugin = require("html-webpack-plugin");
|
|
4
|
+
const CaseSensitivePathsPlugin = require("case-sensitive-paths-webpack-plugin");
|
|
5
|
+
const InlineChunkHtmlPlugin = require("react-dev-utils/InlineChunkHtmlPlugin");
|
|
6
|
+
const TerserPlugin = require("terser-webpack-plugin");
|
|
7
|
+
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
|
|
8
|
+
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
|
|
9
|
+
const ModuleNotFoundPlugin = require("react-dev-utils/ModuleNotFoundPlugin");
|
|
10
|
+
const ReactRefreshWebpackPlugin = require("@pmmmwh/react-refresh-webpack-plugin");
|
|
11
|
+
const CopyPlugin = require("copy-webpack-plugin");
|
|
12
|
+
|
|
13
|
+
const paths = require("../helpers/paths");
|
|
14
|
+
const { shouldUseSourceMap, isEnvDevelopment, isEnvProduction } = require("../helpers/environment");
|
|
15
|
+
const { emptyOr } = require("../helpers/utils");
|
|
16
|
+
const imageLoaders = require("../loaders/images");
|
|
17
|
+
const styleLoaders = require("../loaders/style");
|
|
18
|
+
const javascriptLoaders = require("../loaders/javascript");
|
|
19
|
+
const rebuiltronConfig = require("../rebuiltronConfig");
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
module.exports = {
|
|
23
|
+
stats: "errors-warnings",
|
|
24
|
+
bail: isEnvProduction,
|
|
25
|
+
output: {
|
|
26
|
+
path: paths.appBuild,
|
|
27
|
+
pathinfo: isEnvDevelopment,
|
|
28
|
+
publicPath: paths.basePath
|
|
29
|
+
},
|
|
30
|
+
cache: {
|
|
31
|
+
type: "filesystem",
|
|
32
|
+
version: createHash("md5").update(process.env.NODE_ENV.toString()).digest("hex"), // I don't know what I'm doing...
|
|
33
|
+
cacheDirectory: paths.appWebpackCache,
|
|
34
|
+
store: "pack",
|
|
35
|
+
buildDependencies: {
|
|
36
|
+
defaultWebpack: ["webpack/lib/"],
|
|
37
|
+
config: [__filename]
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
infrastructureLogging: {
|
|
41
|
+
level: "none"
|
|
42
|
+
},
|
|
43
|
+
resolve: {
|
|
44
|
+
modules: ["node_modules", paths.appNodeModules, paths.appSrc],
|
|
45
|
+
extensions: [".web.js", ".js", ".json", ".jsx", ".node"],
|
|
46
|
+
alias: {
|
|
47
|
+
src: paths.appSrc
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
optimization: {
|
|
51
|
+
minimize: isEnvProduction,
|
|
52
|
+
minimizer: [
|
|
53
|
+
new TerserPlugin({
|
|
54
|
+
terserOptions: {
|
|
55
|
+
parse: {
|
|
56
|
+
ecma: 8
|
|
57
|
+
},
|
|
58
|
+
compress: {
|
|
59
|
+
ecma: 5,
|
|
60
|
+
warnings: false,
|
|
61
|
+
comparisons: false,
|
|
62
|
+
inline: 2
|
|
63
|
+
},
|
|
64
|
+
output: {
|
|
65
|
+
ecma: 5,
|
|
66
|
+
comments: false
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}),
|
|
70
|
+
new CssMinimizerPlugin()
|
|
71
|
+
]
|
|
72
|
+
},
|
|
73
|
+
module: {
|
|
74
|
+
strictExportPresence: true,
|
|
75
|
+
rules: [
|
|
76
|
+
// Handles `node_modules` packages that contain sourcemaps
|
|
77
|
+
...emptyOr(shouldUseSourceMap, [{
|
|
78
|
+
enforce: "pre",
|
|
79
|
+
exclude: /@babel(?:\/|\\{1,2})runtime/,
|
|
80
|
+
test: /\.(js|mjs|jsx|ts|tsx|css)$/,
|
|
81
|
+
loader: require.resolve("source-map-loader")
|
|
82
|
+
}]),
|
|
83
|
+
{
|
|
84
|
+
oneOf: [
|
|
85
|
+
...imageLoaders,
|
|
86
|
+
...javascriptLoaders,
|
|
87
|
+
...styleLoaders,
|
|
88
|
+
{
|
|
89
|
+
// Makes sure the assets get served by `WebpackDevServer`
|
|
90
|
+
exclude: [/^$/, /\.(js|mjs|jsx|ts|tsx)$/, /\.html$/, /\.json$/],
|
|
91
|
+
type: "asset/resource"
|
|
92
|
+
}
|
|
93
|
+
]
|
|
94
|
+
}
|
|
95
|
+
]
|
|
96
|
+
},
|
|
97
|
+
plugins: [
|
|
98
|
+
...emptyOr(isEnvProduction, [
|
|
99
|
+
new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [/runtime-.+[.]js/]), // Injects scripts into HTML
|
|
100
|
+
new MiniCssExtractPlugin({
|
|
101
|
+
filename: `${rebuiltronConfig.buildDirs.css}/[name].[contenthash:8].css`,
|
|
102
|
+
chunkFilename: `${rebuiltronConfig.buildDirs.css}/[name].[contenthash:8].chunk.css`
|
|
103
|
+
}),
|
|
104
|
+
new CopyPlugin({
|
|
105
|
+
patterns: [{
|
|
106
|
+
from: paths.appPublic,
|
|
107
|
+
to: paths.appBuild,
|
|
108
|
+
globOptions: {
|
|
109
|
+
ignore: ["**/*.html"]
|
|
110
|
+
}
|
|
111
|
+
}]
|
|
112
|
+
})
|
|
113
|
+
]),
|
|
114
|
+
...emptyOr(isEnvDevelopment, [
|
|
115
|
+
new ReactRefreshWebpackPlugin({ overlay: false }),
|
|
116
|
+
new CaseSensitivePathsPlugin() // Detects case errors in import paths
|
|
117
|
+
]),
|
|
118
|
+
new ModuleNotFoundPlugin(paths.appPath) // Gives some necessary context to module not found errors
|
|
119
|
+
],
|
|
120
|
+
performance: false // Performance processing is already handled via `FileSizeReporter`
|
|
121
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const paths = require("../helpers/paths");
|
|
2
|
+
const rebuiltronConfig = require("../rebuiltronConfig");
|
|
3
|
+
const baseConfig = require("./base");
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
module.exports = {
|
|
7
|
+
...baseConfig,
|
|
8
|
+
mode: "production",
|
|
9
|
+
target: "electron-main",
|
|
10
|
+
entry: {
|
|
11
|
+
[rebuiltronConfig.buildFileNames.main]: paths.electronMain
|
|
12
|
+
},
|
|
13
|
+
output: {
|
|
14
|
+
...baseConfig.output,
|
|
15
|
+
filename: `${rebuiltronConfig.buildDirs.js}/[name].js`
|
|
16
|
+
}
|
|
17
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
const { mapKeys } = require("lodash");
|
|
2
|
+
|
|
3
|
+
const paths = require("../helpers/paths");
|
|
4
|
+
const rebuiltronConfig = require("../rebuiltronConfig");
|
|
5
|
+
const baseConfig = require("./base");
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
const { preloads } = require(paths.appConfig);
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
module.exports = {
|
|
12
|
+
...baseConfig,
|
|
13
|
+
mode: "production",
|
|
14
|
+
target: "electron-preload",
|
|
15
|
+
entry: mapKeys(preloads, (_value, entryName) => (
|
|
16
|
+
`${rebuiltronConfig.buildFileNames.preload}.${entryName}`)
|
|
17
|
+
),
|
|
18
|
+
output: {
|
|
19
|
+
...baseConfig.output,
|
|
20
|
+
filename: `${rebuiltronConfig.buildDirs.js}/[name].js`
|
|
21
|
+
}
|
|
22
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
const path = require("path");
|
|
2
|
+
|
|
3
|
+
const HtmlWebpackPlugin = require("html-webpack-plugin");
|
|
4
|
+
const { keys } = require("lodash");
|
|
5
|
+
|
|
6
|
+
const paths = require("../helpers/paths");
|
|
7
|
+
const { isEnvProduction, shouldUseSourceMap } = require("../helpers/environment");
|
|
8
|
+
const { emptyOr } = require("../helpers/utils");
|
|
9
|
+
const rebuiltronConfig = require("../rebuiltronConfig");
|
|
10
|
+
const baseConfig = require("./base");
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
const { renderers } = require(paths.appConfig);
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
module.exports = {
|
|
17
|
+
...baseConfig,
|
|
18
|
+
mode: isEnvProduction ? "production" : "development",
|
|
19
|
+
target: "browserslist",
|
|
20
|
+
devtool: shouldUseSourceMap && (isEnvProduction ? "source-map" : "cheap-module-source-map"),
|
|
21
|
+
entry: renderers,
|
|
22
|
+
output: {
|
|
23
|
+
...baseConfig.output,
|
|
24
|
+
filename: `${rebuiltronConfig.buildDirs.js}/${isEnvProduction ? "[name].[contenthash:8].js" : "[name].bundle.js"}`,
|
|
25
|
+
chunkFilename: `${rebuiltronConfig.buildDirs.js}/${isEnvProduction ? "[name].[contenthash:8].chunk.js" : "[name].chunk.js"}`,
|
|
26
|
+
assetModuleFilename: `${rebuiltronConfig.buildDirs.media}/[name].[hash][ext]`
|
|
27
|
+
},
|
|
28
|
+
plugins: [
|
|
29
|
+
...baseConfig.plugins,
|
|
30
|
+
...keys(renderers).map(renderer => (
|
|
31
|
+
new HtmlWebpackPlugin({
|
|
32
|
+
inject: true,
|
|
33
|
+
template: path.join(paths.appPublic, `${renderer}.html`),
|
|
34
|
+
filename: `${renderer}.html`,
|
|
35
|
+
chunks: [renderer],
|
|
36
|
+
...emptyOr(isEnvProduction, {
|
|
37
|
+
minify: {
|
|
38
|
+
removeComments: true,
|
|
39
|
+
collapseWhitespace: true,
|
|
40
|
+
removeRedundantAttributes: true,
|
|
41
|
+
useShortDoctype: true,
|
|
42
|
+
removeEmptyAttributes: true,
|
|
43
|
+
removeStyleLinkTypeAttributes: true,
|
|
44
|
+
keepClosingSlash: true,
|
|
45
|
+
minifyJS: true,
|
|
46
|
+
minifyCSS: true,
|
|
47
|
+
minifyURLs: true
|
|
48
|
+
}
|
|
49
|
+
})
|
|
50
|
+
})
|
|
51
|
+
))
|
|
52
|
+
]
|
|
53
|
+
};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
const { spawn } = require("child_process");
|
|
2
|
+
const path = require("path");
|
|
3
|
+
const fs = require("fs");
|
|
4
|
+
|
|
5
|
+
const webpack = require("webpack");
|
|
6
|
+
const WebpackDevServer = require("webpack-dev-server");
|
|
7
|
+
const clearConsole = require("react-dev-utils/clearConsole");
|
|
8
|
+
const { bold } = require("colorette");
|
|
9
|
+
|
|
10
|
+
const webpackConfig = require("./webpack.config");
|
|
11
|
+
const devServerConfig = require("./webpackDevServer.config");
|
|
12
|
+
const { exitProcessWithError } = require("./helpers/utils");
|
|
13
|
+
const spinnies = require("./helpers/spinnies");
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
let isElectronStarted = false;
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
const _startElectron = (port) => {
|
|
20
|
+
spinnies.add("electron", { text: "Starting Electron" });
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
const electronPath = require.resolve("electron");
|
|
24
|
+
const electronModulePath = path.dirname(electronPath);
|
|
25
|
+
const pathFile = path.join(electronModulePath, "path.txt");
|
|
26
|
+
const executablePath = fs.readFileSync(pathFile, "utf-8");
|
|
27
|
+
const electronExtPath = path.join(electronModulePath, "dist", executablePath);
|
|
28
|
+
|
|
29
|
+
const electronProcess = spawn(electronExtPath, ["."], {
|
|
30
|
+
stdio: "inherit",
|
|
31
|
+
env: {
|
|
32
|
+
...process.env,
|
|
33
|
+
DEV_LOCAL_URL: `http://localhost:${port}`
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
electronProcess.on("close", process.exit);
|
|
38
|
+
|
|
39
|
+
spinnies.succeed("devServer", { text: `Development server running on port ${bold(port)}` });
|
|
40
|
+
spinnies.succeed("electron", { text: "Electron started\n" });
|
|
41
|
+
|
|
42
|
+
isElectronStarted = true;
|
|
43
|
+
|
|
44
|
+
} catch (error) {
|
|
45
|
+
exitProcessWithError({
|
|
46
|
+
message: [
|
|
47
|
+
"An error occured while starting Electron.",
|
|
48
|
+
"Please make sure the dependencies `electron` is installed."
|
|
49
|
+
],
|
|
50
|
+
stack: error.stack || error
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
module.exports = (port) => {
|
|
56
|
+
const compiler = webpack(webpackConfig);
|
|
57
|
+
|
|
58
|
+
// Starting (re)compiling
|
|
59
|
+
|
|
60
|
+
compiler.hooks.invalid.tap("invalid", () => {
|
|
61
|
+
clearConsole();
|
|
62
|
+
spinnies.add("compile", { text: "Compiling..." });
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// Finished (re)compiling
|
|
66
|
+
|
|
67
|
+
compiler.hooks.done.tap("done", () => {
|
|
68
|
+
clearConsole();
|
|
69
|
+
spinnies.remove("compile");
|
|
70
|
+
|
|
71
|
+
if (!isElectronStarted) _startElectron(port);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
return new WebpackDevServer({ ...devServerConfig, port }, compiler);
|
|
75
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
const { red, green, yellow, black } = require("colorette");
|
|
2
|
+
const { isString } = require("lodash");
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @typedef {(string|string[])} LogMessage
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Formats a message into a single string.
|
|
11
|
+
* @param {LogMessage} message - Message to format
|
|
12
|
+
* @returns {string} Formatted message
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
const _formatMessage = (message) => {
|
|
16
|
+
if (isString(message)) return message;
|
|
17
|
+
return message.join("\n");
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Logs a message in red.
|
|
23
|
+
* @param {LogMessage} message - Message to log
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
const logError = (message) => console.log(red(`\n${_formatMessage(message)}\n`));
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Logs a message in green.
|
|
30
|
+
* @param {LogMessage} message - Message to log
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
const logSuccess = (message) => console.log(green(`\n${_formatMessage(message)}\n`));
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Logs a message in yellow.
|
|
37
|
+
* @param {LogMessage} message - Message to log
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
const logWarning = (message) => console.log(yellow(`\n${_formatMessage(message)}\n`));
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Logs a message in black.
|
|
44
|
+
* @param {string} message - Message to log
|
|
45
|
+
*/
|
|
46
|
+
|
|
47
|
+
const logInfo = (message) => console.log(black(`${message}\n`));
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
module.exports = {
|
|
51
|
+
error: logError,
|
|
52
|
+
success: logSuccess,
|
|
53
|
+
warning: logWarning,
|
|
54
|
+
info: logInfo
|
|
55
|
+
};
|
package/helpers/paths.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
const rebuiltronConfig = require("../rebuiltronConfig.js");
|
|
2
|
+
const { isEnvDevelopment } = require("./environment.js");
|
|
3
|
+
const { resolveApp } = require("./utils.js");
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
const packageJsonPath = resolveApp("package.json");
|
|
7
|
+
const packageJson = require(packageJsonPath);
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
module.exports = {
|
|
11
|
+
appConfig: resolveApp(rebuiltronConfig.configFileName),
|
|
12
|
+
electronMain: resolveApp(packageJson.main),
|
|
13
|
+
appPath: resolveApp("."),
|
|
14
|
+
appBuild: resolveApp(rebuiltronConfig.appDirs.build),
|
|
15
|
+
appPublic: resolveApp(rebuiltronConfig.appDirs.public),
|
|
16
|
+
appPackageJson: packageJsonPath,
|
|
17
|
+
appSrc: resolveApp(rebuiltronConfig.appDirs.appSrc),
|
|
18
|
+
electronSrc: resolveApp(rebuiltronConfig.appDirs.electronSrc),
|
|
19
|
+
appNodeModules: resolveApp("node_modules"),
|
|
20
|
+
appWebpackCache: resolveApp("node_modules/.cache"),
|
|
21
|
+
basePath: isEnvDevelopment ? "/" : "./"
|
|
22
|
+
};
|
package/helpers/utils.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
const path = require("path");
|
|
2
|
+
const fs = require("fs");
|
|
3
|
+
|
|
4
|
+
const { isArray } = require("lodash");
|
|
5
|
+
|
|
6
|
+
const log = require("./logger");
|
|
7
|
+
const spinnies = require("./spinnies");
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
const _appDirectory = fs.realpathSync(process.cwd());
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Resolves a path relative to the app directory.
|
|
15
|
+
* @param {string} relativePath - Path to resolve
|
|
16
|
+
* @returns {string} Resolved path
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
const resolveApp = (relativePath) => path.resolve(_appDirectory, relativePath);
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Logs error message and stack (if available) and exit the running process.
|
|
23
|
+
* @param {(Error|import("./logger").LogMessage)} error - Error to log
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
const exitProcessWithError = (error) => {
|
|
27
|
+
spinnies.stopAll("fail");
|
|
28
|
+
|
|
29
|
+
log.error(error?.message || error);
|
|
30
|
+
if (error.stack) log.info(error.stack);
|
|
31
|
+
|
|
32
|
+
process.exit(1);
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Returns the given value when the condition is truthy, otherwise an empty element of the same type.
|
|
37
|
+
* @param {any} condition - Condition determining if the value should be returned
|
|
38
|
+
* @param {(object|Array)} value - Value to return
|
|
39
|
+
* @returns {(object|Array)} Value or empty element
|
|
40
|
+
*/
|
|
41
|
+
|
|
42
|
+
const emptyOr = (condition, value) => {
|
|
43
|
+
const empty = isArray(value) ? [] : {};
|
|
44
|
+
return condition ? value : empty;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
module.exports = { resolveApp, exitProcessWithError, emptyOr };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module.exports = [
|
|
2
|
+
{
|
|
3
|
+
test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
|
|
4
|
+
type: "asset",
|
|
5
|
+
parser: {
|
|
6
|
+
dataUrlCondition: {
|
|
7
|
+
maxSize: 10000
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
test: /\.svg$/,
|
|
13
|
+
issuer: /\.jsx?$/,
|
|
14
|
+
use: [{
|
|
15
|
+
loader: require.resolve("@svgr/webpack"),
|
|
16
|
+
options: {
|
|
17
|
+
prettier: false,
|
|
18
|
+
svgo: false,
|
|
19
|
+
titleProp: true,
|
|
20
|
+
ref: true
|
|
21
|
+
}
|
|
22
|
+
}]
|
|
23
|
+
}
|
|
24
|
+
];
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
const paths = require("../helpers/paths");
|
|
2
|
+
const { shouldUseSourceMap, isEnvProduction } = require("../helpers/environment");
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
module.exports = [
|
|
6
|
+
{
|
|
7
|
+
test: /\.(js|jsx)$/,
|
|
8
|
+
exclude: [paths.appNodeModules],
|
|
9
|
+
use: {
|
|
10
|
+
loader: require.resolve("swc-loader"),
|
|
11
|
+
options: {
|
|
12
|
+
jsc: {
|
|
13
|
+
parser: {
|
|
14
|
+
jsx: true
|
|
15
|
+
},
|
|
16
|
+
transform: {
|
|
17
|
+
react: {
|
|
18
|
+
refresh: true,
|
|
19
|
+
runtime: "automatic"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
minify: isEnvProduction,
|
|
24
|
+
sourceMaps: shouldUseSourceMap
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
];
|
package/loaders/style.js
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
const path = require("path");
|
|
2
|
+
|
|
3
|
+
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
|
|
4
|
+
|
|
5
|
+
const paths = require("../helpers/paths");
|
|
6
|
+
const { shouldUseSourceMap, isEnvDevelopment, isEnvProduction } = require("../helpers/environment");
|
|
7
|
+
const { emptyOr } = require("../helpers/utils");
|
|
8
|
+
const rebuiltronConfig = require("../rebuiltronConfig");
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
const { sassOptions } = require(paths.appConfig);
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
const _publicPath = rebuiltronConfig.buildDirs.css
|
|
15
|
+
.split("/")
|
|
16
|
+
.reduce(path => (path + "../"), "");
|
|
17
|
+
|
|
18
|
+
const _getBaseStyleLoaders = () => ([
|
|
19
|
+
...emptyOr(isEnvDevelopment, [require.resolve("style-loader")]),
|
|
20
|
+
...emptyOr(isEnvProduction, [{
|
|
21
|
+
loader: MiniCssExtractPlugin.loader,
|
|
22
|
+
options: { publicPath: _publicPath } // Locates HTML files from bundled `.css`
|
|
23
|
+
}]),
|
|
24
|
+
{
|
|
25
|
+
loader: require.resolve("css-loader"),
|
|
26
|
+
options: {
|
|
27
|
+
importLoaders: 3,
|
|
28
|
+
sourceMap: shouldUseSourceMap,
|
|
29
|
+
modules: {
|
|
30
|
+
mode: "icss"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
loader: require.resolve("postcss-loader"),
|
|
36
|
+
options: {
|
|
37
|
+
postcssOptions: {
|
|
38
|
+
ident: "postcss",
|
|
39
|
+
config: false,
|
|
40
|
+
plugins: [
|
|
41
|
+
"postcss-flexbugs-fixes",
|
|
42
|
+
[
|
|
43
|
+
"postcss-preset-env",
|
|
44
|
+
{
|
|
45
|
+
autoprefixer: {
|
|
46
|
+
flexbox: "no-2009"
|
|
47
|
+
},
|
|
48
|
+
stage: 3
|
|
49
|
+
}
|
|
50
|
+
],
|
|
51
|
+
"postcss-normalize"
|
|
52
|
+
]
|
|
53
|
+
},
|
|
54
|
+
sourceMap: shouldUseSourceMap
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
]);
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
module.exports = [
|
|
61
|
+
{
|
|
62
|
+
test: /\.css$/,
|
|
63
|
+
use: _getBaseStyleLoaders({ importLoaders: 1 }),
|
|
64
|
+
sideEffects: true // https://github.com/webpack/webpack/issues/6571
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
test: /\.(scss|sass)$/,
|
|
68
|
+
use: [
|
|
69
|
+
..._getBaseStyleLoaders({ importLoaders: 3 }),
|
|
70
|
+
{
|
|
71
|
+
loader: require.resolve("resolve-url-loader"),
|
|
72
|
+
options: {
|
|
73
|
+
sourceMap: shouldUseSourceMap,
|
|
74
|
+
root: paths.appSrc
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
loader: require.resolve("sass-loader"),
|
|
79
|
+
options: {
|
|
80
|
+
sourceMap: true,
|
|
81
|
+
...emptyOr(sassOptions?.additionalData, {
|
|
82
|
+
additionalData: (content, loaderContext) => {
|
|
83
|
+
const { data, exclude } = sassOptions.additionalData;
|
|
84
|
+
const { resourcePath, rootContext } = loaderContext;
|
|
85
|
+
|
|
86
|
+
const relativeFilePath = path.relative(rootContext, resourcePath);
|
|
87
|
+
const isExcluded = relativeFilePath.match(exclude);
|
|
88
|
+
|
|
89
|
+
// Add `additionalData` on non-excluded files
|
|
90
|
+
return isExcluded ? content : data + content;
|
|
91
|
+
}
|
|
92
|
+
})
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
],
|
|
96
|
+
sideEffects: true // https://github.com/webpack/webpack/issues/6571
|
|
97
|
+
}
|
|
98
|
+
];
|
package/package.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "rebuiltron",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"author": "Arkellys",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"bin": {
|
|
7
|
+
"rebuiltron": "bin/index.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"lint": "eslint \"**/*.js\""
|
|
11
|
+
},
|
|
12
|
+
"devDependencies": {
|
|
13
|
+
"eslint-config-arklint": "^1.0.2"
|
|
14
|
+
},
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.3",
|
|
17
|
+
"@svgr/webpack": "^8.0.1",
|
|
18
|
+
"@swc/core": "^1.3.76",
|
|
19
|
+
"browserslist": "^4.18.1",
|
|
20
|
+
"case-sensitive-paths-webpack-plugin": "^2.4.0",
|
|
21
|
+
"colorette": "^2.0.20",
|
|
22
|
+
"copy-webpack-plugin": "^11.0.0",
|
|
23
|
+
"css-loader": "^6.5.1",
|
|
24
|
+
"css-minimizer-webpack-plugin": "^5.0.1",
|
|
25
|
+
"detect-port": "^1.5.1",
|
|
26
|
+
"fs-extra": "^11.1.1",
|
|
27
|
+
"html-webpack-plugin": "^5.5.0",
|
|
28
|
+
"lodash": "^4.17.21",
|
|
29
|
+
"mini-css-extract-plugin": "^2.4.5",
|
|
30
|
+
"postcss": "^8.4.4",
|
|
31
|
+
"postcss-flexbugs-fixes": "^5.0.2",
|
|
32
|
+
"postcss-loader": "^7.3.3",
|
|
33
|
+
"postcss-normalize": "^10.0.1",
|
|
34
|
+
"postcss-preset-env": "^9.1.1",
|
|
35
|
+
"react-dev-utils": "^12.0.1",
|
|
36
|
+
"react-refresh": "^0.14.0",
|
|
37
|
+
"resolve-url-loader": "^5.0.0",
|
|
38
|
+
"sass-loader": "^13.3.2",
|
|
39
|
+
"source-map-loader": "^4.0.1",
|
|
40
|
+
"spinnies": "^0.5.1",
|
|
41
|
+
"style-loader": "^3.3.1",
|
|
42
|
+
"swc-loader": "^0.2.3",
|
|
43
|
+
"terser-webpack-plugin": "^5.2.5",
|
|
44
|
+
"webpack": "^5.64.4",
|
|
45
|
+
"webpack-dev-server": "^4.6.0"
|
|
46
|
+
},
|
|
47
|
+
"peerDependencies": {
|
|
48
|
+
"electron": ">=25.0.0",
|
|
49
|
+
"react": ">=18.0.0",
|
|
50
|
+
"react-dom": ">=18.0.0"
|
|
51
|
+
},
|
|
52
|
+
"eslintConfig": {
|
|
53
|
+
"extends": "arklint"
|
|
54
|
+
},
|
|
55
|
+
"repository": {
|
|
56
|
+
"type": "git",
|
|
57
|
+
"url": "git+https://github.com/Arkellys/rebuiltron.git"
|
|
58
|
+
},
|
|
59
|
+
"homepage": "https://github.com/Arkellys/rebuiltron#readme"
|
|
60
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
configFileName: "rebuiltron.config.js",
|
|
3
|
+
buildDirs: {
|
|
4
|
+
js: "static/js",
|
|
5
|
+
media: "static/media",
|
|
6
|
+
css: "static/css"
|
|
7
|
+
},
|
|
8
|
+
buildFileNames: {
|
|
9
|
+
main: "electron.main",
|
|
10
|
+
preload: "electron.preload"
|
|
11
|
+
},
|
|
12
|
+
appDirs: {
|
|
13
|
+
public: "public",
|
|
14
|
+
electronSrc: "electron",
|
|
15
|
+
appSrc: "src",
|
|
16
|
+
build: "build"
|
|
17
|
+
}
|
|
18
|
+
};
|
package/scripts/build.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
process.env.BABEL_ENV = "production";
|
|
2
|
+
process.env.NODE_ENV = "production";
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
const { measureFileSizesBeforeBuild, printFileSizesAfterBuild } = require("react-dev-utils/FileSizeReporter");
|
|
6
|
+
const { isEmpty } = require("lodash");
|
|
7
|
+
const clearConsole = require("react-dev-utils/clearConsole");
|
|
8
|
+
|
|
9
|
+
const checkSetup = require("../checkSetup");
|
|
10
|
+
const paths = require("../helpers/paths");
|
|
11
|
+
const { exitProcessWithError } = require("../helpers/utils");
|
|
12
|
+
const log = require("../helpers/logger");
|
|
13
|
+
const spinnies = require("../helpers/spinnies");
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
process.on("unhandledRejection", exitProcessWithError);
|
|
17
|
+
|
|
18
|
+
const WARN_AFTER_BUNDLE_GZIP_SIZE = 512 * 1024;
|
|
19
|
+
const WARN_AFTER_CHUNK_GZIP_SIZE = 1024 * 1024;
|
|
20
|
+
|
|
21
|
+
checkSetup
|
|
22
|
+
.then(() => measureFileSizesBeforeBuild(paths.appBuild))
|
|
23
|
+
.then(previousFileSizes => {
|
|
24
|
+
const buildApp = require("../buildApp");
|
|
25
|
+
return buildApp(previousFileSizes);
|
|
26
|
+
})
|
|
27
|
+
.then(({ stats, previousFileSizes, warnings }) => {
|
|
28
|
+
spinnies.remove("build");
|
|
29
|
+
clearConsole();
|
|
30
|
+
|
|
31
|
+
isEmpty(warnings)
|
|
32
|
+
? log.success("Compiled successfully!")
|
|
33
|
+
: log.warning(["Compiled with warnings.\n", warnings.join("\n\n")]);
|
|
34
|
+
|
|
35
|
+
console.log("File sizes after gzip:\n");
|
|
36
|
+
|
|
37
|
+
printFileSizesAfterBuild(
|
|
38
|
+
stats,
|
|
39
|
+
previousFileSizes,
|
|
40
|
+
paths.appBuild,
|
|
41
|
+
WARN_AFTER_BUNDLE_GZIP_SIZE,
|
|
42
|
+
WARN_AFTER_CHUNK_GZIP_SIZE
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
console.log();
|
|
46
|
+
process.exit(0);
|
|
47
|
+
})
|
|
48
|
+
.catch(exitProcessWithError);
|
package/scripts/start.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
process.env.BABEL_ENV = "development";
|
|
2
|
+
process.env.NODE_ENV = "development";
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
const clearConsole = require("react-dev-utils/clearConsole");
|
|
6
|
+
|
|
7
|
+
const checkSetup = require("../checkSetup");
|
|
8
|
+
const { exitProcessWithError } = require("../helpers/utils");
|
|
9
|
+
const spinnies = require("../helpers/spinnies");
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
process.on("unhandledRejection", exitProcessWithError);
|
|
13
|
+
|
|
14
|
+
checkSetup.then(([port]) => {
|
|
15
|
+
const createDevServer = require("../createDevServer");
|
|
16
|
+
const devServer = createDevServer(port);
|
|
17
|
+
|
|
18
|
+
clearConsole();
|
|
19
|
+
spinnies.add("devServer", { text: "Starting the development server" });
|
|
20
|
+
|
|
21
|
+
devServer.start();
|
|
22
|
+
|
|
23
|
+
["SIGINT", "SIGTERM"].forEach((sig) => {
|
|
24
|
+
process.on(sig, () => {
|
|
25
|
+
devServer.close();
|
|
26
|
+
process.exit();
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
}).catch(exitProcessWithError);
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
const { isEnvDevelopment } = require("./helpers/environment");
|
|
2
|
+
const rendererConfig = require("./configurations/renderers");
|
|
3
|
+
const preloadConfig = require("./configurations/preloads");
|
|
4
|
+
const mainConfig = require("./configurations/main");
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
module.exports = isEnvDevelopment ? rendererConfig : [rendererConfig, mainConfig, preloadConfig];
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
const evalSourceMapMiddleware = require("react-dev-utils/evalSourceMapMiddleware");
|
|
2
|
+
const ignoredFiles = require("react-dev-utils/ignoredFiles");
|
|
3
|
+
const redirectServedPath = require("react-dev-utils/redirectServedPathMiddleware");
|
|
4
|
+
|
|
5
|
+
const paths = require("./helpers/paths");
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
module.exports = {
|
|
9
|
+
compress: true,
|
|
10
|
+
static: {
|
|
11
|
+
directory: paths.appPublic,
|
|
12
|
+
publicPath: [paths.basePath],
|
|
13
|
+
watch: {
|
|
14
|
+
ignored: ignoredFiles(paths.appSrc)
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
client: {
|
|
18
|
+
overlay: {
|
|
19
|
+
errors: true,
|
|
20
|
+
warnings: false
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
historyApiFallback: {
|
|
24
|
+
disableDotRule: true, // Supports route with dots
|
|
25
|
+
index: paths.basePath
|
|
26
|
+
},
|
|
27
|
+
setupMiddlewares: (middlewares, devServer) => ([
|
|
28
|
+
...middlewares,
|
|
29
|
+
evalSourceMapMiddleware(devServer), // Fetches source contents from webpack for the error overlay
|
|
30
|
+
redirectServedPath(paths.basePath) // Redirects to `basePath` if url not match
|
|
31
|
+
])
|
|
32
|
+
};
|