-
Notifications
You must be signed in to change notification settings - Fork 15
/
Copy pathexternal.ts
142 lines (132 loc) · 6.68 KB
/
external.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
import type { Plugin } from 'esbuild';
import { isAlias } from "./alias";
import { encode } from "../util/encode-decode";
import { DEFAULT_CDN_HOST, getCDNUrl } from '../util/util-cdn';
import { CDN_RESOLVE } from './cdn';
import { parse as parsePackageName } from "parse-package-name";
/** External Plugin Namespace */
export const EXTERNALS_NAMESPACE = 'external-globals';
/** An empty export as a Uint8Array */
export const EMPTY_EXPORT = encode("export default {}");
/** List of polyfillable native node modules, you should now use aliases to polyfill features */
export const PolyfillMap = {
"console": "console-browserify",
"constants": "constants-browserify",
"crypto": "crypto-browserify",
"buffer": "buffer",
"Dirent": "dirent",
"vm": "vm-browserify",
"zlib": "browserify-zlib",
"assert": "assert",
// "child_process": "child_process",
// "cluster": "child_process",
"dgram": "browser-node-dgram",
// "dns": "dns",
"domain": "domain-browser",
"events": "events",
"http": "http-browserify",
"https": "https-browserify",
"module": "module",
"net": "net-browserify",
"path": "path-browserify",
"punycode": "punycode",
"querystring": "querystring",
"readline": "readline-browser",
// "repl": "repl",
"stream": "stream-browserify",
"string_decoder": "string_decoder",
// "sys": "sys",
"timers": "timers-browserify",
"tls": "browserify-tls",
"tty": "tty-browserify",
"url": "browserify-url",
"util": "util/util.js",
"_shims": "_shims",
"readable-stream/": "readable-stream/lib",
"readable-stream/duplex": "readable-stream/lib/duplex.js",
"readable-stream/readable": "readable-stream/lib/readable.js",
"readable-stream/writable": "readable-stream/lib/writable.js",
"readable-stream/transform": "readable-stream/lib/transform.js",
"readable-stream/passthrough": "readable-stream/lib/passthrough.js",
"_stream_duplex": "readable-stream/lib/duplex.js",
"_stream_readable": "readable-stream/lib/readable.js",
"_stream_writable": "readable-stream/lib/writable.js",
"_stream_transform": "readable-stream/lib/transform.js",
"_stream_passthrough": "readable-stream/lib/passthrough.js",
process: "process/browser",
fs: "memfs",
os: "os-browserify/browser",
// "v8": "v8",
// "node-inspect": "node-inspect",
"_linklist": "_linklist",
"_stream_wrap": "_stream_wrap",
};
/** Array of native node packages (that are polyfillable) */
export const PolyfillKeys = Object.keys(PolyfillMap);
/** API's & Packages that were later removed from nodejs */
export const DeprecatedAPIs = ["v8/tools/codemap", "v8/tools/consarray", "v8/tools/csvparser", "v8/tools/logreader", "v8/tools/profile_view", "v8/tools/profile", "v8/tools/SourceMap", "v8/tools/splaytree", "v8/tools/tickprocessor-driver", "v8/tools/tickprocessor", "node-inspect/lib/_inspect", "node-inspect/lib/internal/inspect_client ", "node-inspect/lib/internal/inspect_repl", "_linklist", "_stream_wrap"];
/** Packages `bundle` should ignore, including deprecated apis, and polyfillable API's */
export const ExternalPackages = ["pnpapi", "v8", "node-inspect", "sys", "repl", "dns", "child_process", "cluster", "chokidar", "yargs", "fsevents", "worker_threads", "async_hooks", "diagnostics_channel", "http2", "inspector", "perf_hooks", "trace_events", "wasi", ...DeprecatedAPIs, ...PolyfillKeys];
/** Based on https://github.com/egoist/play-esbuild/blob/7e34470f9e6ddcd9376704cd8b988577ddcd46c9/src/lib/esbuild.ts#L51 */
export const isExternal = (id: string, external: string[] = []) => {
return [...ExternalPackages, ...external].find((it: string): boolean => {
if (it === id) return true; // import 'foo' & external: ['foo']
if (id.startsWith(`${it}/`)) return true; // import 'foo/bar.js' & external: ['foo']
return false;
});
};
/**
* Esbuild EXTERNAL plugin
*
* @param external List of packages to marks as external
*/
export const EXTERNAL = (packageSizeMap = new Map<string, number>(), external: string[] = [], host = DEFAULT_CDN_HOST, polyfill = false): Plugin => {
return {
name: EXTERNALS_NAMESPACE,
setup(build) {
// Intercept import paths starting with "http:" and "https:" so
// esbuild doesn't attempt to map them to a file system location.
// Tag them with the "http-url" namespace to associate them with
// this plugin.
build.onResolve({ filter: /.*/ }, (args) => {
let path = args.path.replace(/^node\:/, "");
let { path: argPath } = getCDNUrl(path, host);
if (isExternal(argPath, external)) {
if (polyfill && isAlias(argPath, PolyfillMap) && !external.includes(argPath)) {
const pkgDetails = parsePackageName(argPath);
const aliasPath = PolyfillMap[pkgDetails.name as keyof typeof PolyfillMap];
return CDN_RESOLVE(packageSizeMap, host)({
...args,
path: aliasPath
});
}
return {
path: argPath,
namespace: EXTERNALS_NAMESPACE,
external: true
};
}
});
// When a URL is loaded, we want to actually download the content
// from the internet. This has just enough logic to be able to
// handle the example import from https://cdn.esm.sh/ but in reality this
// would probably need to be more complex.
//
// We also want to intercept all import paths inside downloaded
// files and resolve them against the original URL. All of these
// files will be in the "http-url" namespace. Make sure to keep
// the newly resolved URL in the "http-url" namespace so imports
// inside it will also be resolved as URLs recursively.
build.onLoad({ filter: /.*/, namespace: EXTERNALS_NAMESPACE }, (args) => {
return {
pluginName: EXTERNALS_NAMESPACE,
contents: EMPTY_EXPORT,
warnings: [{
text: `${args.path} is marked as an external module and will be ignored.`,
details: `"${args.path}" is a built-in node module thus can't be bundled by https://bundlejs.com (technically it can be supported but...it's currently disabled. If you'd like this functionallity, please reach out at https://github.com/okikio/bundlejs), sorry about that.`
}]
};
});
},
};
};