I'm using electron-react-boilerplate to develop electron app (which uses electron-builder to pack apps).
I want to create tray, but it requires icon path or native image. The question is how to retrieve icon image from electron-builder or how to tell electron-builder to include icons dir into resources (without packing), so I can use:
appIcon = new Tray(iconPath | nativeImage)
I kind of struggled with a solution about non-packaged assets (such as media or JSON config files), mostly because I was not familiar with Electron until now. :)
I built a simple personal tray-only app and I didn't want to repackage every time I change an icon for instance.
If you too plan on using changing/dynamic assets you can distinguish between "development" and "production" using this property:
https://electronjs.org/docs/api/app#appispackaged-readonly
Make sure you have this in your package.json:
"build": {
...
"extraResources": [
"./assets/**"
],
}
https://www.electron.build/configuration/contents#extraresources
Then in your code you can have:
const assetsPath = app.isPackaged ? path.join(process.resourcesPath, "assets") : "assets";
Of course you can also use a different path for storing assets, independent of your packaged app folder, for example your user's home or user's documents:
https://electronjs.org/docs/api/app#appgetpathname
Electron v7.0.1
electron-builder 21.2.0
Firstly you need to tell electron-builder which extra files need copying into your output build. I copy over native drivers for each os like below, but you should be able to adapt this to your needs. The "to": "resources" means you'll be able to use the next code to find the files later.
"build": {
...
"extraFiles": [
{
"from": "resources/${os}/drivers",
"to": "resources",
"filter": [
"**/*"
]
}
],
Then to get access to that path from in electron you can use:
const path = require('path');
const imgPath = path.join(process.resourcesPath, 'image.png')
If you're in the main process you can omit the remote part.
You can then use nativeImage.createFromPath to get a native image:
const nativeImage = require('electron').nativeImage
let image = nativeImage.createFromPath(imgPath)
Thanks, Tim, your answer gave me a good thought. I reused it with some addition depending on how I run my app - form vs code using electron or from installed deb file:
"build": {
...
"extraFiles": [
{
"from": "assets",
"to": "resources",
"filter": [
"**/*"
]
}
]
...
}
And then:
let imgPath = process.env.DEV ? "assets/icon.png" : path.join(process.resourcesPath, "icon.png");
tray = new Tray(imgPath);
Related
Developed an Electron app using Vuejs and everything works fine in development, but when packaged I keep getting this pop-up after start up (NOTE: This is a sample image - mine doesn't say 'windowsdefender' but is otherwise the same).
Using electron-builder to create the application with the following build json, and it is installed on the PC:
{
"productName": "My App",
"appId": "com.mycompany.myapp",
"win": {
"icon": "build/icon.png",
"target": [
"nsis"
]
}
}
Though the app does open, there is no initial screen. However, I can open the dev tools but there are no errors displayed.
Any ideas on what is causing this or how to resolve?
After many tries, I finally figured it out (or at least I think I know what caused the issue).
The primary issue was that in using vue router (from an app ported from the web), it is important that you use 'hash' mode and not 'history. Add this to your router file:
const router = new VueRouter({
mode: process.env.IS_ELECTRON ? "hash" : "history",
routes
});
See this link for more details (common issues): Vue CLI plugin common issues
Second, I think there is a rights issue (i.e. having elevated rights to install) so I added this line along with the guid to my electron-builder.json file. The result was a build file like this:
{
"productName": "My App",
"appId": "com.abcco.my-app",
"win": {
"icon": "build/icon.png",
"target": "nsis",
"requestedExecutionLevel": "requireAdministrator"
},
"nsis": {
"guid": "6ee647a9-d5c6-46a9-a480-aa7d6d3d1c10",
"oneClick": false,
"allowToChangeInstallationDirectory": true
}
}
As I am developing only for Windows I was able to use material from this page (React but not that different with respect to Electron packaging):
Electron Build file help
The last thing I did was to remove all 'dist' files and uninstall the app entirely (previous versions). I think this cleared up a lot of the 'baggage' left over from testing.
Hopefully this helps others who may experience the same issue.
I have built an application with electron-builder. There was a video in media folder in the development area. But when I built the application I figure out the video folder replaced with asar file in a resource folder in C://Programs.
I want videos to have in media folder in production. How can I do that
You may want to try with asar: false in your package.json file. But, this is not the recommended way to do it.
The best you can do is to add the resources you want to keep outside the asar file with the extraResources directive:
"build": {
"extraResources": [
{
"from": "../media",
"to": "media",
"filter": [
"**/*",
"!*.mp3",
]
}
],
"asar": false,
}
The accepted answer did not work for me... What did work was to specify the directory whose contents I wanted to access post-build in the same format as specified for the files configuration.
electron-builder.json:
{
...
"extraResources": [
"src/assets/my-assets/*"
],
...
}
After the build, you will find your folder at the same location as the asar file (.../app/resources/src/assets/my-assets), under resources. There's no need to specify asar: false.
On the main process, if you use __dirname, it will end with app.asar. The assets can be accessed using:
// Removing 8 characters to remove "app.asar"
let strippedPath = __dirname.substring(0, __dirname.length - 8);
let execPath = '\"' + strippedPath + 'src\\assets\\my-assets' + '\"';
Now execPath can be appended to with whatever needs to be executed from the assets folder.
#angular/cli#7+ allows a customWebpackConfig to be specified to provide custom webpack configuration, such as:
"architect": {
"build": {
"builder": "#angular-builders/custom-webpack:browser",
"options": {
"customWebpackConfig": {
"path": "./build/custom-webpack.config.js",
"mergeStrategies": {
"externals": "prepend"
}
},
...
This file then technically allows you to prepend, append or replace any portion of the webpack configuration. Prior to upgrading to #angular#7.1.3 and #angular/cli#7.1.3 we had ejected the webpack configuration to make some additions. One such addition was the postcss-momentum-scrolling postcss-loader plugin that automatically enabled iOS momentum scrolling on all scrollable containers.
I am seeking support on figuring out how to generate the necessary custom webpack code to load this plugin via the supported customizations allowed by #angular/cli#7+.
Here is a sample of what I have tried in my custom-webpack.config.js file:
const postcssMomentumScrolling = require('postcss-momentum-scrolling');
module.exports = {
module: {
rules: [
{
test: /\.scss$|\.sass$/,
use: [
{
"loader": "postcss-loader",
"options": {
"plugins": [
postcssMomentumScrolling(),
]
}
}
]
},
],
},
};
As soon as I touch the scss chunk of the webpack config, it seems to do a replace instead of a merge or prepend, breaking the build.
I am wondering if anyone has a guide or suggestions on how to see what the initial webpack configuration that #angular/cli generates that is the starting point for modifications and a way to preview/peek at the code to be executed as debugging.
Also, an example of a similar customization would be great.
Thanks!
I think you need to tell to "customWebpackConfig" which portion to merge. Like this:
"mergeStrategies": {
"module.rules": "prepend"
}
In this way you're going to tell to merge with prepend strategy.
According to "custom-webpack" documentation it should default to "append" which doesn't seem the case in your example.
It's been a while since you've put the question but I wanted to actually ask if you have been able to fix it since I'm running in some issues getting my "module.rules" merged...it seems to work only if I set "replace" strategy.
Trying to figure out how to get the "X.Y.Z" substituted below when not every file will have that in the name. Simple filespec:
{
"files": [
{
"pattern": "artifacts/",
"target": "repository/project/X.Y.Z/"
}
]
}
Not all of the files have the full version number in them so I can't use a simple placeholder (per this solution). I was wondering if there was some other way to dynamically figure out the part to replace the "X.Y.Z" using some maybe-more-complex syntax?
Thinking about the problem a bit more it occurred to me that I could put the artifacts in a specially-named directory that I could then use to publish from.
{
"files": [
{
"pattern": "artifacts-(*)/",
"target": "repository/project/{1}/"
}
]
}
Tested, and that seemed to do the trick. It just required a little scripting at the end of the build to name that directory with the version number in it.
I'd appreciate it so much if someone could please tell me a good way to handle bundling bower components. I feel like I've tried everything... Although, I can't seem to find any gulp tasks that handle this already. Could it really not exist?
Let's say it doesn't exist. Worst case scenario is I have to specify the paths of each "dist" file from bower_components folder. (It is annoying that each component seems to have its own "dist" folder... nothing is standardized.)
So even if I do that, I've noticed some components like 'active-support' seem to have require('lodash') and such in them. I think that if I just simply copy that file, it will break because the requires won't resolve.
What am I missing? How do I simply take all bower_components and bundle into a "common.js"... is there a way or is it a clusterfluck?
Update
As pointed out by Alerty, the new Gulp policy seems to be: use bower directly and glob patterns (and hope that the packages maintainers have a proper "ignore" properties).
Previously
You can use main-bower-files or gulp-bower-src to get files from your bower components. They can also use "ignore" or "main" overrides in your own bower file.
This is how I managed it (but see gulpfile.js for project structure, it's not a single gigantic gulpfile) :
https://github.com/notbrain/viceroy/blob/master/gulp/tasks/bower.js
Would be a bit more modular to simply concat all bower deps and then do the uglify() and minifyCSS() tasks separately on dist/ source locations, based on dev/prod env targets, but will have to wait for future updates.
Use main-bower-files:
var gulp = require('gulp');
var mainBowerFiles = require('main-bower-files');
gulp.task('TASKNAME', function() {
return gulp.src(mainBowerFiles())
.pipe(/* what you want to do with the files */)
});
if you have folders like:
-app
-bower
-node_modules
Gulpfile.js
package.json
the solution are:
gulp.task("connect", function () {
connect.server({
root: ["app"],
livereload: true,
port: 8034,
middleware: function (connect) {
return [connect().use("/bower", connect.static("bower"))];
}
});
});
If your project use AMD specification.
You can use gulp-edp bundle the modules.
set module info at module.conf
{
"baseUrl": "src",
"paths": {},
"packages": [
{
"name": "etpl",
"location": "../bower_components/etpl/3.0.1/src",
"main": "main"
},
{
"name": "jquery",
"location": "../bower_components/jquery/1.9.1/src",
"main": "jquery.min"
}
],
"combine": {
"app": true
}
}
gulpfile.js
var gulp = require('gulp');
var edp = require('gulp-edp');
gulp.src(
[
'src/**/*.js'
'bower_components/**/*.js',
'!bower_components/**/{demo,demo/**}',
'!bower_components/**/{test,test/**}'
]
)
.pipe(edp({
getProcessors: function () {
var moduleProcessor = new this.ModuleCompiler();
return [moduleProcessor];
}
}))
.pipe(gulp.dest('dist'));
See EDP wiki for more features.