Skip to content

Commit ad173e9

Browse files
Add an option to bundle NPM packages while installing
1 parent d07269a commit ad173e9

File tree

6 files changed

+494
-45
lines changed

6 files changed

+494
-45
lines changed

npm/private/lifecycle/lifecycle-hooks.js

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ const path = require('path')
55
const { safeReadPackageJsonFromDir } = require('@pnpm/read-package-json')
66
const { runLifecycleHook } = require('@pnpm/lifecycle')
77

8+
//const esbuild = require('esbuild-wasm');
9+
const {rollup} = require('rollup');
10+
const {dts} = require('rollup-plugin-dts');
11+
const commonjs = require('@rollup/plugin-commonjs');
12+
const json = require('@rollup/plugin-json');
13+
814
async function mkdirp(p) {
915
if (p && !fs.existsSync(p)) {
1016
await mkdirp(path.dirname(p))
@@ -128,6 +134,89 @@ function isWindows() {
128134
return os.platform() === 'win32'
129135
}
130136

137+
138+
async function optimizePackage(destDir) {
139+
// We first copy the package to a temporary directory so that we don't have `node_modules`
140+
// in our name. Otherwise, `dts` will refuse to do anthing, since `respectExternals` defaults to false.
141+
// Setting that to true will inline _all_ externals (including dependencies), which
142+
// can break typechecking. Better to bundle the dependencies on their own.
143+
const tempDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'aspect_rules_js_'));
144+
await fs.promises.cp(destDir, tempDir, {recursive: true, force: true});
145+
146+
const packageJsonText = await fs.promises.readFile(path.join(tempDir, 'package.json'));
147+
const packageJson = JSON.parse(packageJsonText);
148+
149+
const typesMain = path.join(tempDir, packageJson.types);
150+
const cjsMain = path.join(tempDir, packageJson.main);
151+
//const esmMain = path.join(tempDir, packageJson.module);
152+
153+
async function bundleDts(input) {
154+
const result = await rollup({
155+
input,
156+
plugins: [dts()],
157+
});
158+
await result.write({
159+
file: input,
160+
format: 'esm',
161+
});
162+
}
163+
164+
async function bundle(input, format, plugins) {
165+
console.log("BUNDLING", input, format);
166+
const result = await rollup({
167+
input,
168+
output: {
169+
file: input,
170+
format,
171+
},
172+
plugins,
173+
});
174+
await result.write({
175+
file: input,
176+
format,
177+
});
178+
}
179+
180+
const bundlePromises = [];
181+
typesMain && bundlePromises.push(bundleDts(typesMain));
182+
cjsMain && bundlePromises.push(bundle(cjsMain, 'cjs', [commonjs(), json()]));
183+
//esmMain && bundlePromises.push(bundle(esmMain, 'esm'));
184+
185+
// Would be faster to use esbuild, but we cannot bundle esbuild itself :/
186+
/*cjsMain && bundlePromises.push(esbuild.build({
187+
entryPoints: [cjsMain],
188+
bundle: true,
189+
outfile: cjsMain,
190+
platform: 'node',
191+
format: 'cjs',
192+
}));
193+
esmMain && bundlePromises.push(esbuild.build({
194+
entryPoints: [esmMain],
195+
bundle: true,
196+
outfile: esmMain,
197+
platform: 'node',
198+
format: 'esm',
199+
}));*/
200+
201+
await Promise.all(bundlePromises);
202+
203+
await fs.promises.rm(destDir, {recursive: true, force: true});
204+
205+
async function rename(tmpPath, realPath) {
206+
const realDir = path.dirname(realPath);
207+
await fs.promises.mkdir(realDir, {recursive: true});
208+
await fs.promises.cp(tmpPath, realPath);
209+
}
210+
211+
const emitPromises = [];
212+
typesMain && emitPromises.push(rename(typesMain, path.join(destDir, packageJson.types)));
213+
cjsMain && emitPromises.push(rename(cjsMain, path.join(destDir, packageJson.main)));
214+
//esmMain && emitPromises.push(rename(esmMain, path.join(destDir, packageJson.module)));
215+
await Promise.all(emitPromises);
216+
217+
await fs.promises.writeFile(path.join(destDir, 'package.json'), packageJsonText);
218+
}
219+
131220
async function main(args) {
132221
if (args.length < 3) {
133222
console.error(
@@ -260,6 +349,10 @@ async function main(args) {
260349
// Run user specified custom postinstall hook
261350
await runLifecycleHook('custom_postinstall', rulesJsJson, opts)
262351
}
352+
353+
if (rulesJsJson.optimize_package) {
354+
await optimizePackage(outputDir);
355+
}
263356
}
264357

265358
// Copy contents of a package dir to a destination dir (without copying the package dir itself)

npm/private/lifecycle/min/index.min.js

Lines changed: 116 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)