Skip to content

Commit 54ae1ee

Browse files
authored
feat: add ignore option to ignore files from build (#68)
1 parent a217727 commit 54ae1ee

File tree

18 files changed

+184
-32
lines changed

18 files changed

+184
-32
lines changed

README.md

+26-10
Original file line numberDiff line numberDiff line change
@@ -50,23 +50,23 @@ pkg [options] <input>
5050

5151
Examples:
5252

53-
Makes executables for Linux, macOS and Windows
53+
- Makes executables for Linux, macOS and Windows
5454
$ pkg index.js
55-
Takes package.json from cwd and follows 'bin' entry
55+
- Takes package.json from cwd and follows 'bin' entry
5656
$ pkg .
57-
Makes executable for particular target machine
57+
- Makes executable for particular target machine
5858
$ pkg -t node16-win-arm64 index.js
59-
Makes executables for target machines of your choice
59+
- Makes executables for target machines of your choice
6060
$ pkg -t node16-linux,node18-linux,node16-win index.js
61-
Bakes '--expose-gc' and '--max-heap-size=34' into executable
61+
- Bakes '--expose-gc' and '--max-heap-size=34' into executable
6262
$ pkg --options "expose-gc,max-heap-size=34" index.js
63-
Consider packageA and packageB to be public
63+
- Consider packageA and packageB to be public
6464
$ pkg --public-packages "packageA,packageB" index.js
65-
Consider all packages to be public
65+
- Consider all packages to be public
6666
$ pkg --public-packages "*" index.js
67-
Bakes '--expose-gc' into executable
67+
- Bakes '--expose-gc' into executable
6868
$ pkg --options expose-gc index.js
69-
reduce size of the data packed inside the executable with GZip
69+
- reduce size of the data packed inside the executable with GZip
7070
$ pkg --compress GZip index.js
7171
```
7272

@@ -181,6 +181,22 @@ See also
181181
[Detecting assets in source code](#detecting-assets-in-source-code) and
182182
[Snapshot filesystem](#snapshot-filesystem).
183183

184+
### Ignore files
185+
186+
`ignore` is a list of globs. Files matching the paths specified as `ignore`
187+
will be excluded from the final executable.
188+
189+
This is useful when you want to exclude some files from the final executable,
190+
like tests, documentation or build files that could have been included by a dependency.
191+
192+
```json
193+
"pkg": {
194+
"ignore": [ "**/*/dependency-name/build.c" ]
195+
}
196+
```
197+
198+
To see if you have unwanted files in your executable, read the [Exploring virtual file system embedded in debug mode](#exploring-virtual-file-system-embedded-in-debug-mode) section.
199+
184200
### Options
185201

186202
Node.js application can be called with runtime options
@@ -413,7 +429,7 @@ printenv | grep NODE
413429

414430
## Advanced
415431

416-
### exploring virtual file system embedded in debug mode
432+
### Exploring virtual file system embedded in debug mode
417433

418434
When you are using the `--debug` flag when building your executable,
419435
`pkg` add the ability to display the content of the virtual file system

lib/index.ts

+3
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import walk, { Marker, WalkerParams } from './walker';
2727
import { Target, NodeTarget, SymLinks } from './types';
2828
import { CompressType } from './compress_type';
2929
import { patchMachOExecutable, signMachOExecutable } from './mach-o';
30+
import pkgOptions from './options';
3031

3132
const { version } = JSON.parse(
3233
readFileSync(path.join(__dirname, '../package.json'), 'utf-8'),
@@ -598,12 +599,14 @@ export async function exec(argv2: string[]) {
598599
let marker: Marker;
599600

600601
if (configJson) {
602+
pkgOptions.set(configJson?.pkg);
601603
marker = {
602604
config: configJson,
603605
base: path.dirname(config),
604606
configPath: config,
605607
};
606608
} else {
609+
pkgOptions.set(inputJson?.pkg);
607610
marker = {
608611
config: inputJson || {}, // not `inputBin` because only `input`
609612
base: path.dirname(input), // is the place for `inputJson`

lib/options.ts

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { PkgOptions } from './types';
2+
3+
class Options {
4+
private options: PkgOptions;
5+
6+
constructor() {
7+
this.options = {
8+
dictionary: {},
9+
};
10+
}
11+
12+
public set(options: PkgOptions): void {
13+
this.options = options ?? this.options;
14+
}
15+
16+
public get(): PkgOptions {
17+
return this.options;
18+
}
19+
}
20+
21+
const options = new Options();
22+
23+
export default options;

lib/types.ts

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export interface PkgOptions {
3636
scripts?: string[];
3737
log?: (logger: typeof log, context: Record<string, string>) => void;
3838
assets?: string[];
39+
ignore?: string[];
3940
deployFiles?: string[];
4041
patches?: Patches;
4142
dictionary: ConfigDictionary;

lib/walker.ts

+20-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import isCore from 'is-core-module';
66
import globby from 'globby';
77
import path from 'path';
88
import chalk from 'chalk';
9+
import { minimatch } from 'minimatch';
910

1011
import {
1112
ALIAS_AS_RELATIVE,
@@ -33,6 +34,7 @@ import {
3334
PackageJson,
3435
SymLinks,
3536
} from './types';
37+
import pkgOptions from './options';
3638

3739
export interface Marker {
3840
hasDictionary?: boolean;
@@ -450,6 +452,19 @@ class Walker {
450452
assert(typeof task.file === 'string');
451453
const realFile = toNormalizedRealPath(task.file);
452454

455+
const { ignore } = pkgOptions.get();
456+
if (ignore) {
457+
// check if the file matches one of the ignore regex patterns
458+
const match = ignore.some((pattern) => minimatch(realFile, pattern));
459+
460+
if (match) {
461+
log.debug(
462+
`Ignoring file: ${realFile} due to top level config ignore pattern`,
463+
);
464+
return;
465+
}
466+
}
467+
453468
if (realFile === task.file) {
454469
this.append(task);
455470
return;
@@ -747,7 +762,11 @@ class Walker {
747762

748763
const catchPackageFilter = (config: PackageJson, base: string) => {
749764
const newPackage = newPackages[newPackages.length - 1];
750-
newPackage.marker = { config, configPath: newPackage.packageJson, base };
765+
newPackage.marker = {
766+
config,
767+
configPath: newPackage.packageJson,
768+
base,
769+
};
751770
};
752771

753772
let newFile = '';

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
"globby": "^11.1.0",
3232
"into-stream": "^6.0.0",
3333
"is-core-module": "2.9.0",
34+
"minimatch": "9.0.4",
3435
"minimist": "^1.2.6",
3536
"multistream": "^4.1.0",
3637
"prebuild-install": "7.1.1",

test/test-10-pnpm/main.js

+6-5
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ if (utils.shouldSkipPnpm()) {
1313

1414
assert(__dirname === process.cwd());
1515

16+
const isWindows = process.platform === 'win32';
1617
const target = process.argv[2] || 'host';
1718
const input = './test.js';
1819
const output = './test-output.exe';
@@ -23,14 +24,14 @@ console.log('target = ', target);
2324
utils.vacuum.sync('./node_modules');
2425
utils.vacuum.sync('./pnpm-lock.yaml');
2526

27+
const npmlog = utils.exec.sync('npm install -g pnpm@8');
28+
console.log('npm log :', npmlog);
29+
2630
// launch `pnpm install`
2731
const pnpmlog = utils.spawn.sync(
28-
path.join(
29-
path.dirname(process.argv[0]),
30-
'npx' + (process.platform === 'win32' ? '.cmd' : ''),
31-
),
32+
path.join(path.dirname(process.argv[0]), 'npx' + (isWindows ? '.cmd' : '')),
3233
['pnpm', 'install'],
33-
{ cwd: path.dirname(output), expect: 0 },
34+
{ cwd: path.dirname(output), expect: 0, shell: isWindows },
3435
);
3536
console.log('pnpm log :', pnpmlog);
3637

test/test-11-pnpm/main.js

+6-5
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ if (utils.shouldSkipPnpm()) {
1414
console.log(__dirname, process.cwd());
1515
assert(__dirname === process.cwd());
1616

17+
const isWindows = process.platform === 'win32';
1718
const target = process.argv[2] || 'host';
1819
const input = './test.js';
1920
const output = './test-output.exe';
@@ -24,14 +25,14 @@ console.log('target = ', target);
2425
utils.vacuum.sync('./node_modules');
2526
utils.vacuum.sync('./pnpm-lock.yaml');
2627

28+
const npmlog = utils.exec.sync('npm install -g pnpm@8');
29+
console.log('npm log :', npmlog);
30+
2731
// launch `pnpm install`
2832
const pnpmlog = utils.spawn.sync(
29-
path.join(
30-
path.dirname(process.argv[0]),
31-
'npx' + (process.platform === 'win32' ? '.cmd' : ''),
32-
),
33+
path.join(path.dirname(process.argv[0]), 'npx' + (isWindows ? '.cmd' : '')),
3334
['pnpm', 'install'],
34-
{ cwd: path.dirname(output), expect: 0 },
35+
{ cwd: path.dirname(output), expect: 0, shell: isWindows },
3536
);
3637
console.log('pnpm log :', pnpmlog);
3738

test/test-50-ignore-files/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
!node_modules

test/test-50-ignore-files/main.js

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#!/usr/bin/env node
2+
3+
'use strict';
4+
5+
const path = require('path');
6+
const assert = require('assert');
7+
const utils = require('../utils.js');
8+
const standard = 'stdout';
9+
10+
assert(!module.parent);
11+
assert(__dirname === process.cwd());
12+
13+
const target = process.argv[2] || 'host';
14+
const output = './test-output.exe';
15+
16+
let left, right;
17+
utils.mkdirp.sync(path.dirname(output));
18+
19+
left = utils.spawn.sync('node', ['test-x-index.js']);
20+
21+
const inspect =
22+
standard === 'stdout'
23+
? ['inherit', 'pipe', 'inherit']
24+
: ['inherit', 'inherit', 'pipe'];
25+
26+
const log = utils.pkg.sync(
27+
['--target', target, '--output', output, '.', '--debug'],
28+
inspect,
29+
);
30+
31+
assert(
32+
log.indexOf('useless.c due to top level config ignore pattern') > 0,
33+
'useless.c file is not ignored',
34+
);
35+
assert(
36+
log.indexOf(
37+
'needed.c is added to queue',
38+
'needed.c file is not added to queue',
39+
),
40+
);
41+
42+
right = utils.spawn.sync('./' + path.basename(output), [], {
43+
cwd: path.dirname(output),
44+
});
45+
46+
assert.strictEqual(left, right);
47+
utils.vacuum.sync(output);

test/test-50-ignore-files/node_modules/delta/index.js

+3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/test-50-ignore-files/node_modules/delta/needed.c

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/test-50-ignore-files/node_modules/delta/package.json

+5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/test-50-ignore-files/node_modules/delta/useless.c

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"bin": "test-x-index.js",
3+
"license": "MIT",
4+
"dependencies": {
5+
"delta": "*"
6+
},
7+
"pkg": {
8+
"ignore": [
9+
"**/*/node_modules/delta/useless.c"
10+
]
11+
}
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
'use strict';
2+
3+
var dataPath = 'delta';
4+
require(dataPath);
5+
console.log(global.FOO);

test/test-80-compression-node-opcua/main.js

+9-11
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ const assert = require('assert');
1414
const utils = require('../utils.js');
1515
const pkgJson = require('./package.json');
1616

17+
const isWindows = process.platform === 'win32';
1718
const buildDir = 'build';
1819

1920
assert(!module.parent);
@@ -32,14 +33,14 @@ function clean() {
3233
// remove any possible left-over
3334
clean();
3435

36+
const npmlog = utils.exec.sync('npm install -g pnpm@8');
37+
console.log('npm log :', npmlog);
38+
3539
// launch `pnpm install`
3640
const pnpmlog = utils.spawn.sync(
37-
path.join(
38-
path.dirname(process.argv[0]),
39-
'npx' + (process.platform === 'win32' ? '.cmd' : ''),
40-
),
41+
path.join(path.dirname(process.argv[0]), 'npx' + (isWindows ? '.cmd' : '')),
4142
['pnpm', 'install'],
42-
{ cwd: path.dirname(__filename), expect: 0 },
43+
{ cwd: path.dirname(__filename), expect: 0, shell: isWindows },
4344
);
4445
console.log('pnpm log :', pnpmlog);
4546

@@ -54,7 +55,7 @@ assert(
5455
/* eslint-disable no-unused-vars */
5556
const input = 'package.json';
5657
const target = process.argv[2] || 'host';
57-
const ext = process.platform === 'win32' ? '.exe' : '';
58+
const ext = isWindows ? '.exe' : '';
5859
const outputRef = path.join(buildDir, 'test-output-empty' + ext);
5960
const outputNone = path.join(buildDir, 'test-output-None' + ext);
6061
const outputGZip = path.join(buildDir, 'test-output-GZip' + ext);
@@ -95,18 +96,15 @@ function pkgCompress(compressMode, output) {
9596

9697
function esbuildBuild(entryPoint) {
9798
const log = utils.spawn.sync(
98-
path.join(
99-
path.dirname(process.argv[0]),
100-
'npx' + (process.platform === 'win32' ? '.cmd' : ''),
101-
),
99+
path.join(path.dirname(process.argv[0]), 'npx' + (isWindows ? '.cmd' : '')),
102100
[
103101
'esbuild',
104102
entryPoint,
105103
'--bundle',
106104
'--outfile=' + path.join(buildDir, pkgJson.main),
107105
'--platform=node',
108106
],
109-
{ cwd: __dirname, expect: 0 },
107+
{ cwd: __dirname, expect: 0, shell: isWindows },
110108
);
111109

112110
console.log(log);

0 commit comments

Comments
 (0)