143 lines
5.9 KiB
JavaScript
143 lines
5.9 KiB
JavaScript
'use strict';
|
|
/*
|
|
This is a hack to get around the issues with electron-builder not including nested node_modules.
|
|
We do this by simply making the asar ourselves using the parameters from the build.
|
|
This takes the asar file that we have created, unpacks it, then copies in the nested node_modules
|
|
directories from the app directory.
|
|
|
|
This also preserves any asar unpacked files that you may have had in the build, and unpacks any
|
|
nested node_modules files that might have been unpacked as well.
|
|
|
|
This also assumes that you have some sort of beforeBuild hook that already trims and massages the
|
|
nested node_modules files to be what you want; if not, you may have some bloat (and some potential
|
|
breakage)
|
|
*/
|
|
|
|
// Make sure you have these in your devDependencies in your root project.
|
|
const glob = require('fast-glob');
|
|
const fs = require('fs-extra');
|
|
const { promisify } = require('util')
|
|
const rimraf = promisify(require('rimraf'))
|
|
const asar = require('asar');
|
|
const micromatch = require("micromatch")
|
|
const { join } = require("path")
|
|
|
|
const commonExclude = [
|
|
"!**/{test,__tests__,tests,powered-test,example,examples,CHANGELOG.md,README.md,README,readme.md,readme}",
|
|
"!**/*.d.ts",
|
|
"!**/.bin",
|
|
"!**/*.{iml,o,hprof,orig,pyc,pyo,rbc,swp,csproj,sln,xproj}",
|
|
"!**/{.DS_Store,.git,.hg,.svn,CVS,RCS,SCCS,.gitignore,.gitattributes}",
|
|
"!**/{__pycache__,thumbs.db,.flowconfig,.idea,.vs,.nyc_output}",
|
|
"!**/{appveyor.yml,.travis.yml,circle.yml}",
|
|
"!**/{npm-debug.log,yarn.lock,.yarn-integrity,.yarn-metadata.json}"
|
|
]
|
|
|
|
function concatUnique(a,b) {
|
|
if (!Array.isArray(a) || !Array.isArray(b)){
|
|
throw Error("both parameters must be arrays")
|
|
}
|
|
let arr = a.concat(b)
|
|
let seen = {};
|
|
return arr.filter(function(item) {
|
|
return seen.hasOwnProperty(item) ? false : (seen[item] = true);
|
|
});
|
|
}
|
|
|
|
// we're using the platform-specific parameters over the global parameters.
|
|
function globalOrPlatformParam(local,global){
|
|
if (typeof local != 'undefined' && local.length != 0){
|
|
return local;
|
|
} else if (typeof global != 'undefined' && global.length != 0){
|
|
return global;
|
|
}
|
|
return undefined;
|
|
}
|
|
|
|
function globalOrPlatformArrayParam(local, global){
|
|
let param = globalOrPlatformParam(local, global) || []
|
|
if (typeof param == "string"){
|
|
param = [param]
|
|
}
|
|
return param;
|
|
}
|
|
|
|
exports.default = async function afterPackHook(context){
|
|
// Get build parameters from the context.
|
|
const appDir = context.packager.info._appDir
|
|
const platform = context.packager.platform.nodeName
|
|
const globalFilesParam = context.packager.info._configuration.files;
|
|
const platformFilesParam = context.packager.platformSpecificBuildOptions.files
|
|
const globalUnpackAsarParam = context.packager.info._configuration.asarUnpack;
|
|
const platformUnpackAsarParam = context.packager.platformSpecificBuildOptions.asarUnpack;
|
|
|
|
let resourcesDir = join(context.appOutDir, "resources")
|
|
// exception for resources dir for mac; win and linux use the same directory.
|
|
if (platform == "darwin"){
|
|
resourcesDir = join(context.appOutDir, context.packager.appInfo.productFilename + ".app", "Contents", "Resources")
|
|
}
|
|
|
|
const asarAppUnpackedDir = join(resourcesDir, "app.asar.unpacked")
|
|
|
|
// The Platform-specific build options override the common config, so attempt to use those first.
|
|
let globPatterns = globalOrPlatformArrayParam(platformFilesParam, globalFilesParam)
|
|
|
|
// electron-builder automatically adds this to the files parameter, so we have to too
|
|
if (!globPatterns.includes("**/*")){
|
|
globPatterns.push("**/*")
|
|
}
|
|
|
|
// Add the common exclusions to the patterns
|
|
globPatterns = concatUnique(globPatterns,commonExclude);
|
|
|
|
// Find all the nested node_modules files in the app directory
|
|
let nestedNMFiles = glob.sync("+(**/node_modules/**/*|!node_modules/**/*)", {cwd: appDir, dot:true})
|
|
|
|
// filter out the ones not matched by the file globs in the builder config
|
|
let filteredNestedFiles = micromatch(nestedNMFiles, globPatterns, {matchBase:true})
|
|
|
|
// This is the directory we're copying everything to, to create the asar
|
|
let asarAppDir = join(resourcesDir, "app")
|
|
|
|
// Get a listing of all the files in the app.asar.unpacked dir, so we can create a franken-glob
|
|
// to pass to asar when packing.
|
|
let unpackedFileList = glob.sync("**/*", {cwd:asarAppUnpackedDir, dot:true})
|
|
let unpackPattern = "{"
|
|
unpackedFileList.forEach((file,idx,arr)=>{
|
|
unpackPattern += join(asarAppDir, file) + ','
|
|
})
|
|
|
|
// Get any user-defined asarUnpack patterns in case we need to unpack some hoisted node_modules,
|
|
// and add any to the pattern.
|
|
let userUnpackGlob = globalOrPlatformArrayParam(platformUnpackAsarParam, globalUnpackAsarParam)
|
|
let nestedFilesToUnpack = micromatch(nestedNMFiles, userUnpackGlob, {matchBase:true})
|
|
nestedFilesToUnpack.forEach((file)=>{
|
|
unpackPattern += join(asarAppDir, file) + ','
|
|
})
|
|
// trailing commas don't matter in this pattern.
|
|
unpackPattern += '}'
|
|
|
|
// Combine the nested files to unpack with the filtered nested files, as electron-builder
|
|
// sometimes does weird things when file globs and the asarUnpack globs are used together;
|
|
// Files that don't match the file globs but do match the asarUnpack glob are included in the build.
|
|
let nestedFilesToCopy = concatUnique(filteredNestedFiles, nestedFilesToUnpack);
|
|
|
|
// Now we have the necessary file lists, create the asar.
|
|
|
|
// Unpack everything in app.asar to the resources/app dir.
|
|
// This also copies all the files in 'app.asar.unpacked' to here as well.
|
|
asar.extractAll(join(resourcesDir, "app.asar"), asarAppDir)
|
|
await rimraf(join(resourcesDir, "app.asar"))
|
|
await rimraf(asarAppUnpackedDir)
|
|
|
|
// Copy the nested node_modules files to the extracted directory.
|
|
nestedFilesToCopy.forEach((file)=>{
|
|
fs.copySync(join(appDir, file), join(asarAppDir, file))
|
|
})
|
|
// build the asar
|
|
await asar.createPackageWithOptions(asarAppDir, join(resourcesDir, "app.asar"), {unpack: unpackPattern})
|
|
await rimraf(asarAppDir)
|
|
|
|
return true
|
|
};
|