I'm new to Electron, and trying to help maintain an application whose developer has left. The resources/app folder consists of (at least) three things:
The app/lib/bundle.js, which contains the entire application, bundled and minified. This is what the app seems to actually run.
Node modules for all the code written by the developer. These are in TypeScript, and are in the structure node_modules/#mainmodule/submodule/src/.../something.ts. Each of these also has a node_modules/#mainmodule/submodule/package.json and node_modules/#mainmodule/submodule/tsconfig.json
Finally, for each of these, a corresponding lib folder: node_modules/#mainmodule/submodule/src/.../something.js. The lib folder has Javascript corresponding to each of the TypeScript, as well as map files showing how they correspond. It is these Javascript files that are minified and included in the bundle, which is actually run.
The source TypeScript is relatively clear and I can follow most of it. But to really understand it I need to set breakpoints on it and run it in a debugger (e.g. VS Code). However, when running the app, Electron doesn't run it from the TypeScript (in src), or even the individual Javascript (in lib), but rather from bundle.js. Bundle.js is a giant file that, besides being minified, is too big to even load properly in my editor.
My question
How can I tell Electron to run the app not from the bundle.js, but from the individual src/...ts TypeScript, or, failing that, from the individual src/...js JavaScript?
If that's not possible, what is the proper way to use a debugger, given the source, when the Electron application is bundled? I have full source but, when I invoke Electron, it runs out of the bundle: how I can change this?
I'm new to Electron and Node, so if I'm making an elementary mistake, please clarify.
Update with progress so far
I've made a lot of progress in getting down to source, but not all the way there.
The Electron app starts with electron-main.js, which loads things like server.js and other files. These all run from source.
Eventually, it creates a minimal window with the following code:
<head>
...
<script type="text/javascript" src="./bundle.js" charset="utf-8"></script>
</head>
bundle.js is then loaded in the window. The files is far too big and unscrutable (minified) to be of much use. But, as I said, the source is all available too.
However, bundle.map.js contains is complete: it contains sources, names, mappings, sourcesContent, which is enough, in principle, to reconstruct everything. Moreover, for almost all of the sources, the corresponding source file is available and obvious.
I believe I need to replace the <script type="text/javascript" src="./bundle.js" charset="utf-8"></script> with a includer.js which:
Includes all files for which I can figure out their matching source file
Uses the sourcesContent for anything else
/Progress to date...
Since the project is set up to run things from a bundle at the moment, it's likely that the project can only run things from the bundle, unless you change the config (which can only be done if you have some idea of what the overall structure is in the first place, which you're trying to get a grasp on to begin with). In other words, the most likely approach to look at how things are interlocking and to analyze and change the logic in the application will be to generate a new bundle.
Very often, the process of generating a new bundle will be contained in the project's root folder's package.json. If you have:
the-big-app/node_modules
then you can probably look at
the-big-app/package.json
and look at the scripts contained within it. There will probably be something along the (very general) lines of:
{
"name": "the-big-app",
"scripts": {
"lint": "eslint .",
"build": "webpack && tsc --build tsconfig.node.json",
"watch": "nodemon --exec npm run start -e ts,tsx,scss,html",
"run": "npx electron build/node/main.js",
"start": "npm run build && npm run run"
},
Each of these properties refers to a runnable NPM script. You're likely to have a build script - if you have such a script and type npm run build, it should then generate a new bundle, which can then be executed. If there is no build script, look around to see which other scripts look like they might do something useful, and execute them. (Back up the existing bundle and other files in the directory first, just in case.)
Look at the values for each NPM script property so you can do further research into what they do and how they might relate to turning the source code into something that runs. Just for example, above, doing
"build": "webpack && tsc --build tsconfig.node.json",
in my app, will
(1) Run Webpack to construct a bundle for the renderer process
(2) Run tsc to compile the TypeScript code inside the-big-app/src/main-process/ into JavaScript that can then be executed by Electron
Look for something similar in your package.json to see what's happening, which will inform you on how it can be tweaked and debugged.
As Electron's docs say, the browser code can be debugged via the devtools. Debugging the main process is harder - you may need to call Electron with the inspect flag, among others.
As for the question of if/how things can be run directly from source TypeScript and not from a bundle - it's possible to do this for the main process with ts-node (2). I don't think it's possible for a renderer process, because the "page" needs to see a plain .js file, like any webpage - and, similarly, can't run TypeScript directly, also like normal browsers and webpages can't run TypeScript directly.
To add to the above answer, I have a Typescript React app that uses Webpack, which you can compare against. You can step through its code for both the main and renderer processes:
VSCode Config
Webpack Code
You also need to build with sourcemaps enabled. Once done you can step through Typescript code line by line.
Related
tl,dr:
Here's what I got:
Electron
React
Webpack
electron-builder
electron-edge
node-fibers
some static assets (.png, .svg etc.)
Here's what I want:
A crossplatform autoupdating installer for the software
The long version and the problems:
I can get Electron, React, Electron Edge, node-fibers, webpack and the static assets to run perfectly when I start the webpackserver in dev mode.
However, how can I integrate this into electron-builder?
I'm new to this whole build process and I just took this boilerplate to get started:
Github of the boilerplate
To me, the dev debug process seems to go like this:
Have webpack create a bundle.js and an index.html out of my src folder
Start a webpackserver with hot mode that serves these files
However, how should I tell electron-builder where to get the different files from? There is no package.json nor node_modules/ inside dist/ and node-fibers isn't getting bundled as well (because webpack seems to fck with __dirname or smth, so I excluded it).
Whenever I launch the generated .exe file (that's not the installer, just an exe file that's supposed to launch the program), a message appears that main.js can't be found in the app.asar file. I tried extracting it, but it fails before it gets to extract the whole package. Main.js is never needed anyway though, because that was the whole point of having webpack transpile it or am I missing something here?
I have searched all over the internet for hours now, but I don't get all the concepts ..
Could anyone here explain what's wrong with my setup and what I can do to fix that?
I recommend you to use https://github.com/chentsulin/electron-react-boilerplate
If you don't want to use boilerplate for react app, consider to use https://github.com/electron-userland/electron-webpack (but boilerplate is strongly recommended).
I ended up with this boilerplate:
https://github.com/szwacz/electron-boilerplate
I couldn't get HMR to work and had to fix some es6 stuff, but at least it's doing its job.
I could not find any explanation regarding the work of "npm run build",
It is simple and easy to use and i get the "build" folder that works great,
But, in create-react-app, what happens exactly behind the scene?
Is it a complete different use of a build tool?
If not, is it utilizing other build tools?
Developers often break JavaScript and CSS out into separate files. Separate files let you focus on writing more modular chunks of code that do one single thing. Files that do one thing decrease your cognitive load as maintaining them is a quite cumbersome task.
What happens exactly behind the scene?
When it’s time to move your app to production, having multiple JavaScript or CSS files isn’t ideal. When a user visits your site, each of your files will require an additional HTTP request, making your site slower to load.
So to remedy this, you can create a “build” of our app, which merges all your CSS files into one file, and does the same with your JavaScript. This way, you minimize the number and size of files the user gets. To create this “build”, you use a “build tool”. Hence the use of npm run build.
As you have rightly mentioned that running the command (npm run build) creates you a build directory. Now suppose you have a bunch of CSS and JS files in your app:
css/
mpp.css
design.css
visuals.css
...
js/
service.js
validator.js
container.js
...
After you run npm run build your build directory will be:
build/
static/
css/
main.css
js/
main.js
Now your app has very few files. The app is still the same but got compacted to a small package called build.
Final Verdict:
You might wonder why a build is even worth it, if all it does is save your users a few milliseconds of load time. Well, if you’re making a site just for yourself or a few other people, you don’t have to bother with this. Generating a build of your project is only necessary for high traffic sites (or sites that you hope will be high traffic soon).
If you’re just learning development, or only making sites with very low traffic, generating a build might not be worth your time.
It's briefly explained here: https://github.com/facebookincubator/create-react-app#npm-run-build-or-yarn-build.
It correctly bundles React in production mode and optimizes the build for the best performance.
The build is minified and the filenames include the hashes.
Behind the scenes, it uses babel to transpile your code and webpack as the build tool to bundle up your application.
I have web pack application and want to build output multiple files not a single javascript file. for example if I have such folder structure
components
1.js
2.js
actions
1.js.
2.js
my webpack build have to compile files in same folder structure. How i can achieve that?
I tried babel cli:
babel ./src --out-dir ./lib --source-maps --presets es2015,react --plugins babel-plugin-add-module-exports,babel-plugin-transform-decorators-legacy,babel-plugin-transform-class-properties --watch
It outputs files as I wanted but getting error
Cannot resolve module
Because it does not know anything about webpack resolve.
Any suggestions?
Getting webpack to output multiple files is possible but it does have limitations. First it's important to understand how this works. Webpack actually provides a runtime script that can load code "chunks" as they are needed, this is important for large applications so the user doesn't have to download the javascript for the entire app just to see the homepage. But webpack needs to keep track of these chunks and what they're named at build time to be able to load them correctly at run time. For that reason it has it's own file naming conventions to enable this functionality. See more here: https://webpack.js.org/guides/code-splitting/. So you can require.ensure all of your deps, but they won't be named and foldered they way you describe as webpack's runtime wouldn't be able to find them in that case.
The other thing that's important to consider is that webpack is a bundler, so it's meant to bundle files. Essentially your saying you don't want to bundle your files. So if that's the case, you should probably look into using require.js. Many people have moved from require to bundlers such as Wepback and Browserify as typically it's not efficient to download every little module seperately. But, every app is different so you may in fact have a good reason to not bundle.
If you do in fact want to do some bundling but want to optimize how it's done, then I can help with that as well, and webpack is certainly a great tool for that. But I'll need to understand your use case a little more to give the best advice.
I'm trying to follow this page https://github.com/feross/simple-peer
1) Install npm simple-peer (check)
2) create an html page: bundle.js is missing?
3) the next code window doesn't indicate what it is at all.
Is it the JS for the html file, or the code in node. no idea.. as browserify (if I understand correctly) allows you to use require() in the browser...
Can someone clarify?
The document given is a little incomplete and assumes you have knowledge of module bundling, which many people dont. Anyways, to get this working, you would have to use a module bundler (like browserify or webpack).
To get started, consider bootstrapping your app using this yeoman generator.
After bootstrapping your app, add the script given in the above documentation in the source file (in src/index.js), after installing dependancies with npm install
Run npm start
Open localhost:8080 and you should see the result you want.
bundle.js which is mentioned the the above module is the resultant javascript file after all node modules have been bundled into one browser compatible file.
As part of my build/CI process on TeamCity, I would like to specify a set of JavaScript files referenced in my HTML and combine them into one.
In other words, this is what I would like to accomplish.
Before:
<script src="1.js" />
<script src="2.js" />
After
<script src="combined.js" />
I am looking for a commandline tool to concatenate 1.js and 2.js into combined.js. Then, a commandline tool (or maybe the same tool) to replace the references in the HTML file to this new file. Please tell me how I could accomplish this.
What I have tried so far:
I have been looking at grunt-usemin which looks good, but requires the build server to perform an npm install on each build to get the dependencies, then run it. That takes too long and isn't a nice solution, because we build+deploy very frequently.
I know I could also add my node_modules folder to git but this is also undesirable. It would be nice if grunt could run these modules installed globally but it is not the grunt way (unless I am mistaken, grunt wants everything installed locally).
Someone also suggested running grunt on the developer machines. Again, undesirable as we have transient VMs and this would break the development flow.
It would be nice if I could run grunt-usemin locally without grunt!
For combining the files you can just use cat
cat 1.js 2.js > combined.js
To replace the chunk of html you could use sed
sed -i "s/<script src=\"1.js\">\n<script src=\"2.js\">/<script src=\"combined.js\">/g" *.html
This is a rather general solution, but it seems a bit clunky to me. If you're rendering this html in node you might consider replacing it in javascript if the combined file exists.
if (fs.existsSync('combined.js')) {
res.end(html_contents.replace('<script src="1.js"/>\n<script src="2.js"/>','<script src="combined.js">'));
} else {
res.end(html_contents);
}
for better performance you can of course use the asynchronous version of fs.exists
I ended up creating my own: https://npmjs.org/package/hashcat
npm install -g hashcat
#gustavohenke's recommendation was close but ultimately h5bp was proving to be too problematic for use on a build server. Ultimately creating this module did not take long and serves my needs for now. I will mark this as the answer until a better answer comes along in the future.