Skip to content

Commit 557ca37

Browse files
committed
Optimize UMD wrapper
1 parent d2578bd commit 557ca37

File tree

1 file changed

+34
-22
lines changed

1 file changed

+34
-22
lines changed

esbuild.mjs

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { readFileSync, writeFileSync, mkdirSync } from 'node:fs';
1+
import { readFileSync, writeFileSync } from 'node:fs';
22
import { dirname } from 'node:path';
33
import { fileURLToPath } from 'node:url';
44
import * as esbuild from 'esbuild';
@@ -24,11 +24,13 @@ const external = {
2424
'@jridgewell/resolve-uri': 'resolveURI',
2525
};
2626

27+
const externalSpec = /^[^./]/;
28+
2729
/** @type {esbuild.Plugin} */
2830
const externalize = {
2931
name: 'externalize',
3032
setup(build) {
31-
build.onResolve({ filter: /^[^./]/ }, ({ path }) => {
33+
build.onResolve({ filter: externalSpec }, ({ path }) => {
3234
if (!external[path]) {
3335
throw new Error(`unregistered external module "${path}"`);
3436
}
@@ -38,20 +40,21 @@ const externalize = {
3840
};
3941

4042
// Babel still supports Node v6, which doesn't have getOwnPropertyDescriptors.
41-
const getOwnPropertyDescriptorsPolyfill = `if (!Object.getOwnPropertyDescriptors) Object.getOwnPropertyDescriptors = function(value) {
42-
return Reflect.ownKeys(value).reduce(function (acc, key) {
43-
Object.defineProperty(acc, key, Object.getOwnPropertyDescriptor(value, key))
44-
return acc;
45-
}, {});
46-
}`;
43+
const getOwnPropertyDescriptorsPolyfill = `
44+
(v) =>
45+
Reflect.ownKeys(v).reduce((o, k) =>
46+
Object.defineProperty(o, k, Object.getOwnPropertyDescriptor(value, k)), {})
47+
`
48+
.trim()
49+
.replace(/\n\s*/g, ' ');
4750

4851
/** @type {esbuild.Plugin} */
4952
const umd = {
5053
name: 'umd',
5154
setup(build) {
5255
const dependencies = Object.keys(packageJson.dependencies || {});
5356
const browserDeps = dependencies.map((d) => `global.${external[d]}`);
54-
const requireDeps = dependencies.map((d) => `require_keep('${d}')`);
57+
const requireDeps = dependencies.map((d) => `require('${d}')`);
5558
const amdDeps = dependencies.map((d) => `'${d}'`);
5659
const locals = dependencies.map((d) => `require_${external[d]}`);
5760
const browserGlobal = external[packageJson.name];
@@ -65,18 +68,29 @@ const umd = {
6568

6669
build.initialOptions.banner = {
6770
js: `
68-
(function (global, factory, e, m) {
69-
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, module${requireDeps}) :
70-
typeof define === 'function' && define.amd ? define(['exports', 'module'${amdDeps}], factory) :
71-
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(e = {}, m = { exports: e }${browserDeps}), global.${browserGlobal} = 'default' in m.exports ? m.exports.default : m.exports);
72-
})(this, (function (exports, module${locals}) {
73-
"use strict";
74-
${getOwnPropertyDescriptorsPolyfill}
71+
(function (global, factory, m) {
72+
typeof exports === 'object' && typeof module !== 'undefined' ? factory(module${requireDeps.join(', ')}) :
73+
typeof define === 'function' && define.amd ? define(['module'${amdDeps.join(', ')}], factory) :
74+
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(m = { exports: {} }${browserDeps.join(', ')}), global.${browserGlobal} = 'default' in m.exports ? m.exports.default : m.exports);
75+
})(this, (function (module${locals.join(', ')}) {
7576
`.trim(),
7677
};
7778
build.initialOptions.footer = {
7879
js: '}));',
7980
};
81+
82+
build.onResolve({ filter: externalSpec }, ({ path }) => {
83+
if (!external[path]) {
84+
throw new Error(`unregistered external module "${path}"`);
85+
}
86+
return { path, namespace: 'umd' };
87+
});
88+
89+
build.onLoad({ filter: /.*/, namespace: 'umd' }, ({ path }) => {
90+
return {
91+
contents: `module.exports = require_${external[path]}`,
92+
};
93+
});
8094
},
8195
};
8296

@@ -88,7 +102,7 @@ async function build(esm) {
88102
sourcemap: 'linked',
89103
sourcesContent: false,
90104
format: esm ? 'esm' : 'cjs',
91-
plugins: esm ? [externalize] : [externalize, umd],
105+
plugins: esm ? [externalize] : [umd],
92106
outExtension: esm ? { '.js': '.mjs' } : { '.js': '.umd.js' },
93107
target: tsconfig.compilerOptions.target,
94108
write: false,
@@ -100,19 +114,17 @@ async function build(esm) {
100114
}
101115
process.exit(1);
102116
}
103-
mkdirSync('dist', { recursive: true });
104117

105118
for (const file of build.outputFiles) {
106119
if (!file.path.endsWith('.umd.js')) {
107120
writeFileSync(file.path, file.contents);
108121
continue;
109122
}
110123

124+
const getOwnPropDescsHelper = '__getOwnPropDescs = Object.getOwnPropertyDescriptors';
111125
const contents = file.text.replace(
112-
/\brequire(_keep)?\(['"]([^'"]*)['"]\)/g,
113-
(_match, keep, spec) => {
114-
return keep ? `require('${spec}')` : `require_${external[spec]}`;
115-
},
126+
getOwnPropDescsHelper,
127+
`${getOwnPropDescsHelper} || (${getOwnPropertyDescriptorsPolyfill})`,
116128
);
117129
writeFileSync(file.path, contents);
118130
}

0 commit comments

Comments
 (0)