Everything the adaptive question bank can teach and test in Package Management, from foundations through advanced practice. Work through it in order, or start practising and let the questions find your level.
npm and Yarn lift shared dependencies to the top level so one copy serves many dependents
•
importing a package you never declared works only by accident of hoisting, and breaks on someone else's tree
•
incompatible ranges force a nested second copy, so two versions of one library coexist
•
two copies of a library means separate module state, so instanceof and singletons fail
I. Peer dependencies and peer conflicts
•
a plugin must share the host's single instance instead of bundling a second one
•
npm 7+ installs peers automatically; npm 6 only printed a warning
•
two packages demanding incompatible peer ranges is a real conflict, not a tooling bug
•
it restores the ignore-and-warn behavior and installs a pair that may genuinely not work together
•
the durable fix is a published peer range that covers the host version, not a local flag
J. Overrides, dedupe and aliases
•
npm's overrides forces a version onto a transitive dependency you do not directly control
•
npm overrides, Yarn resolutions and pnpm pnpm.overrides differ in syntax and scope
•
forcing a version can violate the dependent's declared range, so upgrading the parent is the real fix
•
moving duplicated packages up the tree so one copy satisfies several dependents
•
npm i x@npm:y@1 installs one package under a different local name, e.g. to run two majors side by side
K. Scripts and lifecycle hooks
•
npm run prepends node_modules/.bin, so a script calls a local CLI by bare name
•
pre<name> and post<name> run automatically around any script you define
•
prepare, prepublishOnly, prepack and postinstall fire on install and publish events, not on demand
•
on a local install and before packing, which is what builds a package installed straight from git
•
npm test and npm start need no run; every other script does
•
arguments after -- go to the script, not to npm itself
•
any installed package can execute code on your machine, and --ignore-scripts is the mitigation
L. bin, npx and executables
•
bin maps a command name to a file, which npm links into node_modules/.bin on install
•
a bin script needs a #!/usr/bin/env node line, and npm sets the executable bit when packing
•
npx runs the project-local binary when one exists and only then fetches into a temporary cache
•
a mistyped package name can silently execute a stranger's package; the confirmation prompt exists for that
M. Workspaces and monorepos
•
a glob list in the root manifest turns sibling folders into locally linked packages
•
the whole repo shares one lockfile and one install, which is what keeps versions aligned
•
a dependency on a sibling resolves to that folder, so an edit is live with no publish step
•
pnpm and Yarn's workspace:* refuses to resolve from the registry and is rewritten at publish time
•
-w <name> targets one workspace and --workspaces targets them all
•
two workspaces pinning different majors of one library reintroduces duplicate instances
N. npm, pnpm, Yarn and Corepack
•
one global store hard-linked into each project, so a second copy of a version costs almost no disk
•
only declared dependencies are linked into a package, so a phantom import fails loudly instead of working
•
PnP removes node_modules and resolves through a manifest, which breaks tools that walk real directories
•
"packageManager": "pnpm@9.1.0" pins the tool version the repo expects
•
Corepack proxies pnpm/yarn to the pinned version, so contributors do not silently use different tools
•
npm ci, pnpm install --frozen-lockfile and yarn --immutable are the same intent, spelled three ways
O. Publishing
•
npm pack --dry-run lists exactly what will ship, which is how you catch a missing dist or a leaked .env
•
a scoped package publishes restricted unless you pass --access public
•
the registry rejects a republish of an existing version, and npm version bumps and git-tags in one step
•
publishing moves the latest tag unless you publish under another tag, which is how a beta avoids becoming the default install
•
unpublishing is restricted after a short window, so npm deprecate is the tool for a bad release
•
a signed attestation ties the tarball to the CI run, repository and commit that built it
•
.npmrc carries the registry, per-scope registries and auth, so a leaked automation token is a publish
P. The exports field and dual packaging
•
once exports exists, any subpath it does not list is unimportable even though the file is in the tarball
•
import, require, node and default select a different file per consumer
•
conditions match top to bottom, so default must be last and types must come first
•
named subpaths and a ./* pattern replace publishing a browsable folder tree
•
#-prefixed specifiers give a package private internal aliases that only resolve inside itself
•
shipping CJS and ESM builds can load both copies at once, giving one library two separate states
•
bolting exports onto an existing package breaks every consumer that deep-imported a file
Q. CommonJS, ESM and interop failure modes
•
.mjs is always ESM and .cjs is always CommonJS, whatever "type" says
•
current Node can require() a synchronous ES module, so the classic ERR_REQUIRE_ESM no longer fires; a graph with top-level await still throws ERR_REQUIRE_ASYNC_MODULE, and publishing ESM-only remains a breaking change for older consumers
•
await import() is how CommonJS code loads an ESM-only dependency
•
module.exports = x surfaces as the default import, which is where the stray .default comes from
•
Node statically detects them, and detection fails on exports assigned dynamically
•
using it forces the whole module graph to ESM, which can be what makes a package unrequireable
R. Audit and vulnerability handling
•
it submits the resolved dependency tree to an advisory service and reports the advisories that match
•
a critical advisory in a build-only dev dependency may be unreachable from anything you ship
•
--force accepts semver-major upgrades, so it can break the build it claims to fix
•
a nested dependency cannot move until its parent's range moves, or you add an override
•
auditing production dependencies only is what tells you about your actual attack surface
•
when no fixed version exists, the options are a fork, an override, or removing the dependency
S. Supply-chain security
•
a near-miss package name banking on a mistyped install or a copy-pasted command
•
a public package matching an internal name can win resolution unless scopes and registries are pinned
•
disabling lifecycle scripts removes the most common install-time execution path
•
a committed lockfile with integrity hashes is what detects a tarball swapped after the fact
•
the common incident shape: a trusted name, a new patch version, a malicious install script
•
a generated CycloneDX or SPDX inventory is how you answer "do we ship the affected version?" in minutes
T. Bundling: what a bundler does and which tool does it
•
it walks the module graph from an entry point and emits fewer, loadable output files
•
build tools resolve exports too, adding conditions like browser, worker and development
•
the fast HMR path and the optimized build are different pipelines that can disagree
•
esbuild and SWC are fast transformers, Rollup targets libraries, webpack targets apps, Vite orchestrates
•
a library marks its peers external so the consuming app supplies exactly one copy
U. Tree shaking, code splitting and source maps
•
dead-code elimination depends on statically analyzable import/export, so a CJS build defeats it
•
"sideEffects": false lets a bundler drop unused modules, and mislabeling it makes an imported CSS file disappear
•
a re-export index can pull in a whole package when purity cannot be proven
•
a dynamic import() becomes its own chunk fetched on demand instead of up-front
•
splitting rarely-changing dependencies out so a deploy does not invalidate every cached file
•
minifying rewrites the code; gzip and brotli happen at transport and are not a substitute
•
they map generated code back to source, and shipping them publicly publishes your source
V. Transpilers, targets and Node versions
•
syntax is rewritten at build time, but a missing runtime API needs a polyfill shipped with the code
•
a lower target emits more helper code, so an over-conservative target costs bytes and speed
•
one shared query drives Babel, Autoprefixer and the bundler so they cannot disagree about support
•
output syntax, ambient API declarations and module format are three independent settings
•
TypeScript checks nothing at run time, and tsc emits files rather than bundling them
•
engines declares the supported Node and npm range, and strictness decides whether it is advice or a hard stop
•
an .nvmrc or equivalent pins the runtime itself, which engines only documents and does not install
Keentune is not affiliated with or endorsed by the organizations whose documentation informs these maps.
All exam, test, and product names and trademarks are the property of their respective owners and are used here for identification and reference only. Keentune is independent study practice — not affiliated with, authorized, or endorsed by any of these organizations.