From 06df698635c1ee7bd18d68e868a673d2de773864 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vinicius=20Louren=C3=A7o?= <12551007+H4ad@users.noreply.github.com> Date: Wed, 10 Apr 2024 12:51:58 -0300 Subject: [PATCH] fix(perf): lazy load glob on normalize.js (#89) Since npm run didn't call those steps, we can save some `ms` by lazy loading this dependency. Before: ![image](https://github.com/npm/package-json/assets/12551007/b4654691-85c8-4431-ba60-f7188363a125) After: ![image](https://github.com/npm/package-json/assets/12551007/f3b02669-2070-4171-aeda-90954c55f54d) The entire load time didn't change, still `13ms` before & after, but if we call `npm run` inside a project that didn't have workspaces, we will save some `ms`, like this one: ![image](https://github.com/npm/package-json/assets/12551007/0fe98367-4967-40f2-8d71-2a1b8c4eda55) But this will also require the PR https://github.com/npm/cli/pull/7360 to be merged. --- lib/normalize.js | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/lib/normalize.js b/lib/normalize.js index 0c7dc80..cd8d69c 100644 --- a/lib/normalize.js +++ b/lib/normalize.js @@ -1,11 +1,21 @@ const valid = require('semver/functions/valid') const clean = require('semver/functions/clean') const fs = require('fs/promises') -const { glob } = require('glob') const path = require('path') const log = require('proc-log') const hostedGitInfo = require('hosted-git-info') +/** + * @type {import('glob').glob} + */ +let _glob +function lazyLoadGlob () { + if (!_glob) { + _glob = require('glob').glob + } + return _glob +} + // used to be npm-normalize-package-bin function normalizePackageBin (pkg, changes) { if (pkg.bin) { @@ -206,7 +216,7 @@ const normalize = async (pkg, { strict, steps, root, changes, allowLegacyCase }) // add "install" attribute if any "*.gyp" files exist if (steps.includes('gypfile')) { if (!scripts.install && !scripts.preinstall && data.gypfile !== false) { - const files = await glob('*.gyp', { cwd: pkg.path }) + const files = await lazyLoadGlob()('*.gyp', { cwd: pkg.path }) if (files.length) { scripts.install = 'node-gyp rebuild' data.scripts = scripts @@ -273,7 +283,11 @@ const normalize = async (pkg, { strict, steps, root, changes, allowLegacyCase }) // populate "readme" attribute if (steps.includes('readme') && !data.readme) { const mdre = /\.m?a?r?k?d?o?w?n?$/i - const files = await glob('{README,README.*}', { cwd: pkg.path, nocase: true, mark: true }) + const files = await lazyLoadGlob()('{README,README.*}', { + cwd: pkg.path, + nocase: true, + mark: true, + }) let readmeFile for (const file of files) { // don't accept directories. @@ -304,7 +318,7 @@ const normalize = async (pkg, { strict, steps, root, changes, allowLegacyCase }) if (steps.includes('mans') && !data.man && data.directories?.man) { const manDir = data.directories.man const cwd = path.resolve(pkg.path, manDir) - const files = await glob('**/*.[0-9]', { cwd }) + const files = await lazyLoadGlob()('**/*.[0-9]', { cwd }) data.man = files.map(man => path.relative(pkg.path, path.join(cwd, man)).split(path.sep).join('/') ) @@ -317,7 +331,7 @@ const normalize = async (pkg, { strict, steps, root, changes, allowLegacyCase }) // expand "directories.bin" if (steps.includes('binDir') && data.directories?.bin && !data.bin) { const binsDir = path.resolve(pkg.path, path.join('.', path.join('/', data.directories.bin))) - const bins = await glob('**', { cwd: binsDir }) + const bins = await lazyLoadGlob()('**', { cwd: binsDir }) data.bin = bins.reduce((acc, binFile) => { if (binFile && !binFile.startsWith('.')) { const binName = path.basename(binFile)