Skip to content

Instantly share code, notes, and snippets.

@guest271314
Created November 28, 2023 02:00
Show Gist options
  • Save guest271314/ccd53bfb82fd9181ab57e7b2543c531b to your computer and use it in GitHub Desktop.
Save guest271314/ccd53bfb82fd9181ab57e7b2543c531b to your computer and use it in GitHub Desktop.
Install Nodes.js packages and run Node.js scripts without npm or node - with Bun

I've been testing and experimenting over the past week or so with installing Node.js-specific packages - without using npm because somebody claimed Can this be used to create/download npm as a standalone executable? #3237

npm can’t be eliminated from the equation when you’re dealing with JavaScript ¯_(ツ)_/¯

Well, let's see about that...

First I had to get all of the dependencies from package.json and/or package-lock.json file. Turns out different packages can depend on different versions of the same named module. Ever hear about "callback hell"? Well, Node.js module dependency system can be dependency hell.

Fortunately for me, due to personal reasons I am evil now (TM) (Rebel Circus). So I fit right in in hell, hell I thrive in chaos.

I tried jsDelivr and UNPKG Ecmascript Module versions of the core dependencies I needed to build a program using a GitHub repository that uses CommonJS exclusively. Unfortunately, Rollup throws errors for read module SyntaxError: The requested module 'https://cdn.jsdelivr.net/npm/read@2.1.0/+esm' does not provide an export named 'default'.

package.json and package-lock.json are not the same animal.

https://www.reddit.com/r/node/comments/184hkw1/comment/kaxn88r/:

Because 1) Throwing away a package-lock.json and re-resolving/-installing everything can give a different result, and 2) package-lock.json stores the hoisted node_modules tree, not just resolved packages.

Take ajv as an example.

The package-lock.json contains 5 versions of it (6.12.6, 8.8.2, 8.10.0, 8.11.0, 8.11.2) but resolving again from the package.json now will give you 2 versions (6.12.6, 8.12.0), which is what npmgraph.js.org counts.

Also, your code actually counts ajv 6 times

ajv ajv-formats/node_modules/ajv copy-webpack-plugin/node_modules/ajv mini-css-extract-plugin/node_modules/ajv webpack-dev-middleware/node_modules/ajv webpack-dev-server/node_modules/ajv Because ajv-formats/node_modules/ajv and webpack-dev-server/node_modules/ajv are the exact same package (ajv@8.8.2) that appears twice in the filesystem. In the general case, it is not possible to perfectly dedupe packages in a node_modules tree.

I'm curious what you get using npm and/or yarn

For yarn v4 I got 542 packages. One of the reasons is that it treats node-gyp as an explicit dependency while npm treats it as implicit.

Didn't test with npm but they should match the two numbers you got depending on whether you use the lockfile or not

(Emphasis added)

And 496 Modules in

only 453
elements on page #185

Sure. Package lock files are basically a snapshot of a given-project's dependency tree. The exact content of a package.json file is a product of the order and timing in which modules are installed for any given project.

While lock files and package.json files are similar in some ways, they're different enough that supporting them is non-trivial. See also #148

I think I got more than enough of the dependencies with this, iterating package-lock.json.

let nodePackageDependencies = [
  ...new Set(
    Object.entries(
      (await (await fetch(
        "./package-lock.json",
      )).json()).packages,
    ).map((
      [key, { dependencies = {}, devDependencies = {} }],
    ) => [
      key.replace(/^node_modules\//, ""),
      ...Object.keys(dependencies),
      ...Object.keys(devDependencies),
    ]).flat().filter(Boolean),
  ),
];

Wait a minute... I've got bun right there next to deno and node in ~/bin. Let's see what bun has to say about this controversy...

install  Install dependencies for a package.json (bun i)

Alright... I don't have npm installed. So Bun folks must have figured something out about how to fetch Node.js packages.

Here you go (npm is not deliberately installed on my machine. If bun uses npm it's under the hood)

$  bun install

Installs packages listed in package.json to ~/.bun/install/cache. Initially complained about the package-lock.json file not being veriosn 3, so I removed the package-lock.json file from the directory and proceeded testing.

$ bun install
bun install v1.0.14 (d8be3e51)
error: Please upgrade package-lock.json to lockfileVersion 3

Run 'npm i --lockfile-version 3 --frozen-lockfile' to upgrade your lockfile without changing dependencies.
user@user:~/telnet-client-web-ext$ bun install
bun install v1.0.14 (d8be3e51)
 + @typescript-eslint/eslint-plugin@5.62.0 (v6.13.0 available)
 + @typescript-eslint/parser@5.62.0 (v6.13.0 available)
 + clean-webpack-plugin@4.0.0
 + copy-webpack-plugin@11.0.0
 + css-loader@6.8.1
 + dotenv@16.3.1
 + eslint@8.54.0
 + eslint-config-google@0.14.0
 + gh-pages@4.0.0 (v6.1.0 available)
 + html-loader@3.1.2 (v4.2.0 available)
 + html-webpack-plugin@5.5.3
 + mini-css-extract-plugin@2.7.6
 + style-loader@3.3.3
 + ts-loader@9.5.1
 + typescript@4.9.5 (v5.3.2 available)
 + wbn-sign@0.1.0 (v0.1.2 available)
 + webbundle-webpack-plugin@0.1.3
 + webpack@5.89.0
 + webpack-cli@4.10.0 (v5.1.4 available)
 + webpack-dev-server@4.15.1
 + webpack-merge@5.10.0
 + xterm@4.19.0 (v5.3.0 available)
 + xterm-addon-fit@0.5.0 (v0.8.0 available)

 494 packages installed [5.67s]
user@user:~/telnet-client-web-ext$ bun run build
$ webpack --config webpack.wbn.js
Setting the empty headerOverrides to IWA defaults. To bundle a non-IWA, set `integrityBlockSign { isIwa: false }` in your plugin configs. Defaults are set to:
 {"content-security-policy":"base-uri 'none'; default-src 'self'; object-src 'none'; frame-src 'self' https: blob: data:; connect-src 'self' https:; script-src 'self' 'wasm-unsafe-eval'; img-src 'self' https: blob: data:; media-src 'self' https: blob: data:; font-src 'self' blob: data:; require-trusted-types-for 'script'; frame-ancestors 'self';","cross-origin-embedder-policy":"require-corp","cross-origin-opener-policy":"same-origin","cross-origin-resource-policy":"same-origin"}
assets by path *.js 4.34 KiB
  asset main.js 3.05 KiB [emitted] [minimized] (name: main)
  asset runtime.js 910 bytes [emitted] [minimized] (name: runtime)
  asset sw.js 361 bytes [emitted] [from: assets/sw.js] [copied] [minimized]
  asset worker.js 50 bytes [emitted] [from: assets/worker.js] [copied] [minimized]
assets by path images/ 21.2 KiB
  asset images/icons-512.png 14.2 KiB [emitted] [from: assets/images/icons-512.png] [copied]
  asset images/icons-192.png 5.14 KiB [emitted] [from: assets/images/icons-192.png] [copied]
  asset images/icons-vector.svg 1.89 KiB [emitted] [from: assets/images/icons-vector.svg] [copied]
asset telnet.swbn 32.6 KiB [emitted]
asset manifest.webmanifest 721 bytes [emitted] [from: assets/manifest.webmanifest] [copied]
asset index.html 253 bytes [emitted]
Entrypoint main 3.94 KiB = runtime.js 910 bytes main.js 3.05 KiB
runtime modules 2.48 KiB 3 modules
./src/index.js 4.74 KiB [built] [code generated]

LOG from webbundle-webpack-plugin
<i> isolated-app://<ID>/

webpack 5.89.0 compiled successfully in 1500 ms
user@user:~/telnet-client-web-ext$ npm --help
Command 'npm' not found, but can be installed with:
sudo apt install npm

So, we can rack that spurious claim up as false.

Have a great day!

@guest271314
Copy link
Author

Part0_4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment