What is the purpose of buildResources folder in electron-builder building process? - electron

I'm reading through electron and electron-builder docs, but I still do not quite understand what is the purpose of the buildResources folder?
Here's what a configuration doc for electron-builder says:
buildResources = build String - The path to build resources.
Kind of self-explanatory... But how or when they are involved in the build process, especially having that:
...build resources is not packed into the app. If you need to use some
files, e.g. as tray icon, please include required files explicitly
Can we simply put those icon files in an arbitrary folder and then copy over into the app/ manually (since we need to include buildResources manually anyway)?

TL;DR:
As far as I can tell from a quick glance at the source code, the buildResources folder is used to hold additional scripts, plugins, etc. that can be used by the package building software. Electron-builder doesn't generate the packages itself, it uses tools like NSIS.
Explanation:
I've had the same question and unfortunately find an answer for this isn't very straight-forward. The docs entry is pretty useless. I found out that someone asked about it in the GitHub issues but never got an answer.
I decided to dig in the code a bit myself to find out what it does. In NsisTargets.ts, you can see that the buildResources folder can contain custom includes and plugins for NSIS.
// NsisTargets.ts
taskManager.add(async () => {
const userPluginDir = path.join(packager.info.buildResourcesDir, pluginArch)
const stat = await statOrNull(userPluginDir)
if (stat != null && stat.isDirectory()) {
scriptGenerator.addPluginDir(pluginArch, userPluginDir)
}
})
// [...]
taskManager.add(async () => {
const customInclude = await packager.getResource(this.options.include, "installer.nsh")
if (customInclude != null) {
scriptGenerator.addIncludeDir(packager.info.buildResourcesDir)
scriptGenerator.include(customInclude)
}
})
and in pkg.ts it's used to load additional scripts to the pkg builder:
// pkg.ts
if (options.scripts != null) {
args.push("--scripts", path.resolve(this.packager.info.buildResourcesDir, options.scripts))
}
It appears as though buildResources can contain assets/scripts specifically used for the build process. That also explains why the contents of buildResources aren't included in the resulting app.asar file.

So, I'm going to say straight away that the documentation for this option is just awful.
Files included in buildResources will appear in the asar file which you can find documentation about on electron's website.
The option files will include files such as pictures which are not accessible in the asar file.
I.E.
given I have a folder called assets in my build folder I want to include with my app.
"files": [
"./build/**/*"
],
"directories": {
"buildResources": "assets"
}
This will put all folders inside build into the asar file, which you can then unpack by including,
"asarUnpack": "**/assets/*"
This will put the folder assets into the build folder in the app directory.

Related

Is there any way of loading local resource files in dart? (not flutter)

I want to load the bytes of a file into a variable while testing my flutter application.
I can't use the assets directory as those are bundled with the app and require WidgetsFlutterBinding.ensureInitialized();
I tried searching the file manually with the path package, but this did not seem to work and was rather hacky. That is why i'm searching for a more official approach.
I was thinking way to complicated ...
As Chuck Batson commented, you can just use the path from the projects root for passing it into the (dart:io) File:
File loadResource(String relativePath) {
final filePath = path.join("test", "resources", relativePath);
return File(filePath);
}
(Notice: The above code makes use of the path package for constructing a file path.)

Storing css an graphics outside .asar

I have an Electron App that - when used - needs to be packed as asar. On the other Hand CSS and graphics sometimes need to be changed while in use. Therefore I need to exclude some of the Files from packaging via --ignoreparameter and copy the unpacked Files manually into the Folder so I can change them easily. For that all of the Paths to my CSS need to be rewritten of course.
But then the App does not work in my development environment because those paths do not exist if not packed.
Does anybody know a Solution where I can access my CSS and graphic files in both environments - packed and unpacked?
You could use electron-is-dev to check if the app is running in a development environment or if it's in production. You would then use the file path that corresponds.
Something along the lines of:
const isDev = require('electron-is-dev')
if (isDev) {
//use development path (unpacked)
} else {
// use production path (packed)
}

Using StealJS to load Bower components lacking a bower.json file

I am using the StealJS + Bower integration in my application, but a couple of my Bower components (including es6-collections) do not contain a bower.json file. Because es6-collections is one of the dependencies in my project's bower.json file, StealJS tries to load the es6-collections component's bower.json file, cannot find it because it does not exist, and complains: Unable to load the bower.json for es6-collections. I tried using System.config({ path: { 'es6-collections': '...' } }) to notify StealJS of the path to the script to use when loading es6-collections, but that does not help. What can I do to get StealJS to load this component?
Assumptions
So I am going to make a few assumptions:
you are using steal from bower
you are "bower install"'ing es6-collections from github directly
you are implicitly using the system-bower plugin by using the HTML <script src="bower_components/steal/steal.js" main="main"></script> to load your "main" file
If these things seem mostly true-ish then you may just have to add some configuration in your bower.json file to silence the error/warning and have everything work as expected.
Explanation:
So because the system-bower plugin (which you are using implicitly because steal detects it is being loaded from a bower_components directory) uses the components bower.json files to determine entry points, so in this case the error/warning comes from not being able to find es6-collections bower.json file.
Solution:
So we just need to tell System (used by steal) where to find that module and that it can stop looking for it's bower.json file.
We can do that by adding a "system" property to the bower.json and adding some configuration data like this...
"system": {
"paths": {
"es6-collections": "bower_components/es6-collections/index.js"
},
"bowerIgnore": ["es6-collections"],
"meta": {
"es6-collections": {
"format": "global"
}
}
}
The paths configuration there, tells System where to find the module
The bowerIgnore array tells system-bower to not look for the bower.json for that module
and the meta config is there to tell System to treat this module like it's a script that is going to add to the global object (window in the browser), which you should probably do for this particular module because of the way es6-collections was written: it exports an empty object if it has nothing to pollyfill so you can't use the exported object, best to just use it as if it was a global module.
For more information on all these things...
http://stealjs.com/docs/bower.html
https://github.com/systemjs/systemjs/wiki/Meta-Configuration
http://stealjs.com/docs/steal.html
Just to have a working example here https://gist.github.com/BigAB/c108bb0860c9cfee3d6a are three files you can copy-paste/clone and then do a bower install and see it working.

How to efficiently manage and process Bower packages with Gulp? (VS2015, Visual Studio 2015)

Background:
Visual Studio 2015 has introduced Gulp and Bower for client side package management. .Net previously had a very efficient method of bundling / minification and package management, but for an unspecified reason this has been removed in ASP.Net 5 / MVC 6, and the advice is to use Gulp and Bower instead.
I have a number of vendor files that I wish to use in my project, including jquery.appear, isotope, owl-carousel etc, etc; some are simple JavaScript files, others have CSS, still others have assets such as fonts, images.
Scenario:
At the moment I am evaluating how to best utilise Bower to manage versions of packages, while using Gulp to extract only the necessary files from bower_components, and uglify / minify / concat them into bundles.
I am currently using CDN available versions of scripts, but best practice would suggest I implement fail-over to local copies - IF I can find a way to manage them using Bower / Gulp OR just download them locally, and forgo package management.
Package management would be my preferred approach, but not if this is high maintenance in terms of scripts, configurations, overrides etc.
What I have tried:
I have looked at Gulp packages such as bower-main-files, gulp-bower-src (which apparently is blacklisted by Gulp), and I am currently using gulp-concat-vendor; with this I can process basic packages which contain only single JavaScript files (i.e. not CSS, not related assets such as images).
Problems:
Some of the bower packages do not include correct information for exporting their main files (some have no main declarations at all).
Some of the packages download dependencies into bower_components at the top level, which becomes cluttered with files I do not need (I want only the main (core) exported files, and the dependencies are usually already met elsewhere). These additional packages need yet more configuration to exclude them from being processed as part of 'Bower Main Files'.
In general, Bower 'standards' are loose, and are not adhered to, even for popular packages.
During concatenation, sometimes a specific order needs to be achieved. I have been unable to find an elegant way to do this automatically - I have created an array of source files, but this is not ideal, as it requires manually checking and editing for each package, which mostly negates the whole concept of package management.
Questions:
Do experienced front-end developers attempt to follow the same approach as I am attempting (using bower_components as a source), or simply manually copy required files from GitHub?
If you do use bower-components, can you please outline the workflow with Gulp, and what plug-ins you use to filter out only the files you need.
Is it possible to prevent unneeded dependencies, tests, etc from being downloaded by Bower in the first place?
When processing files that include relative references (e.g. CSS containing a reference to an image), is it possible to correct the relative path, to be relative to the specified output directory for such assets?
Yes.
See below.
Well, bower package is package, you get whats included. For your build you either rely on components bower.json which specifies main files or do filtering yourself. It is simple enough.
You can use filter = require('gulp-filter') to filter files like that:
var gulp = require('gulp'),
bower = require('gulp-main-bower-files'),
filter = require('gulp-filter'),
concat = require('gulp-concat'),
rename = require('gulp-rename'),
srcmaps = require('gulp-sourcemaps'),
jsminify = require('gulp-uglify')
cssminify = require('gulp-csso'),
del = require('del');
var src = {
js: 'app/**/*.js',
css: 'app/**/*.css',
content: ['app/**/*.jpg', 'app/**/*.svg', 'app/**/*.png', 'app/**/*.ico', 'app/**/*.html']
}
var dst = {
pub: 'pub/',
lib: 'pub/lib/'
}
gulp.task('bower', ['start-build'], function () {
var jsfilter = filter('**/*.js')
var cssfilter = filter('**/*.css')
return gulp.src('bower.json')
.pipe(bower())
.pipe(jsfilter)
.pipe(concat('lib.min.js'))
.pipe(jsminify())
.pipe(gulp.dest(dst.lib))
.pipe(jsfilter.restore())
.pipe(cssfilter)
.pipe(concat('lib.min.css'))
.pipe(cssminify())
.pipe(gulp.dest(dst.lib))
.pipe(cssfilter.restore())
.pipe(rename(function (path) {
if (~path.dirname.indexOf('fonts')) {
path.dirname = '/fonts'
}
}))
.pipe(gulp.dest(dst.lib));
})
gulp.task('js', ['start-build'], function () {
return gulp.src([src.js])
.pipe(srcmaps.init())
.pipe(concat('app.min.js'))
.pipe(jsminify())
.pipe(srcmaps.write())
.pipe(gulp.dest(dst.pub));
})

how to set the path to where aapt add command adds the file

I'm using aapt tool to remove some files from different folders of my apk. This works fine.
But when I want to add files to the apk, the aapt tool add command doesn't let me specify the path to where I want the file to be added, therefore I can add files only to the root folder of the apk.
This is strange because I don't think that developers would never want to add files to a subfolder of the apk (res folder for example). Is this possible with aapt or any other method? Cause removing files from any folder works fine, and adding file works only for the root folder of the apk. Can't use it for any other folder.
Thanks
The aapt tool retains the directory structure specified in the add command, if you want to add something to an existing folder in an apk you simply must have a similar folder on your system and must specify each file to add fully listing the directory. Example
$ aapt list test.apk
res/drawable-hdpi/pic1.png
res/drawable-hdpi/pic2.png
AndroidManifest.xml
$ aapt remove test.apk res/drawable-hdpi/pic1.png
$ aapt add test.apk res/drawable-hdpi/pic1.png
The pic1.png that will is added resides in a folder in the current working directory of the terminal res/drawable-hdpi/ , hope this answered your question
There is actually a bug in aapt that will make this randomly impossible. The way it is supposed to work is as the other answer claims: paths are kept, unless you pass -k. Let's see how this is implemented:
The flag that controls whether the path is ignored is mJunkPath:
bool mJunkPath;
This variable is in a class called Bundle, and is controlled by two accessors:
bool getJunkPath(void) const { return mJunkPath; }
void setJunkPath(bool val) { mJunkPath = val; }
If the user specified -k at the command line, it is set to true:
case 'k':
bundle.setJunkPath(true);
break;
And, when the data is being added to the file, it is checked:
if (bundle->getJunkPath()) {
String8 storageName = String8(fileName).getPathLeaf();
printf(" '%s' as '%s'...\n", fileName, storageName.string());
result = zip->add(fileName, storageName.string(),
bundle->getCompressionMethod(), NULL);
} else {
printf(" '%s'...\n", fileName);
result = zip->add(fileName, bundle->getCompressionMethod(), NULL);
}
Unfortunately, the one instance of Bundle used by the application is allocated in main on the stack, and there is no initialization of mJunkPath in the constructor, so the value of the variable is random; without a way to explicitly set it to false, on my system I (seemingly deterministically) am unable to add files at specified paths.
However, you can also just use zip, as an APK is simply a Zip file, and the zip tool works fine.
(For the record, I have not submitted the trivial fix for this as a patch to Android yet, if someone else wants to the world would likely be a better place. My experience with the Android code submission process was having to put up with an incredibly complex submission mechanism that in the end took six months for someone to get back to me, in some cases with minor modifications that could have just been made on their end were their submission process not so horribly complex. Given that there is a really easy workaround to this problem, I do not consider it important enough to bother with all of that again.)

Resources