nathanjhood / esbuild-scripts

esbuild-flavoured 'react-scripts'.
Other
0 stars 0 forks source link

pkgroll bundler output: consider using 'export default' for internal functions to bundle them instead of export them #10

Closed nathanjhood closed 2 months ago

nathanjhood commented 2 months ago

issue:

solution:

blockers:

plan:

nathanjhood commented 2 months ago

Steps taken:

Result:

Overview:

in a hypothetical, new React project (as created by, for example, the npm create-react-app package), here called "consumer":

// package.json
{
  "name": "consumer",
  "dependencies": {
  "@nathanjhood/esbuld-scripts": "./packages/@nathanjhood/esbuld-scripts",
  "react": "18.2.0",
  "react-dom": "18.2.0",
  // etc... 
  },
  "scripts": {
  "build": "esbuild-scripts build"
  }
}

The esbuild-scripts repository is located at <projectRoot>/packages/@nathanjhood/esbuld-scripts, as described in the above package.json. It has been pre-built, meaning that it already contains it's own node_modules and dist/*.js, in order to isolate any issues with the underlying mechanisms before worrying too much about where to find the files.

In the "consumer" project root directory, call the aliased esbuild-scripts build command via Yarn, observe output result:

$ yarn build
Starting @nathanjhood/esbuild-scripts v0.1.0 
┊
├──┐  
/***/consumer
[ '/***/.config/nvm/versions/node/v20.16.0/bin/node' ]
[ 'build' ]
[ '/***/.config/nvm/versions/node/v20.16.0/bin/node' ]
[ 'build' ]
│  │  
│  └─ Recieved Script: build
│     │  
node:internal/modules/cjs/loader:1148
  throw err;
  ^

Error: Cannot find module '../config/esbuild/getBuildOptions'
Require stack:
- /***/consumer/node_modules/@nathanjhood/esbuild-scripts/dist/pkgroll_create-require-tKTPlRJW.js
- /***/consumer/node_modules/@nathanjhood/esbuild-scripts/dist/scripts/build.js
    at Module._resolveFilename (node:internal/modules/cjs/loader:1145:15)
    at Module._load (node:internal/modules/cjs/loader:986:27)
    at # etc....

Node.js v20.16.0
│     └─ build time taken: 499.561ms
│  
├─ @nathanjhood/esbuild-scripts time taken: 578.619ms
┊
Done in 1.47s.

It would be wise to continue development of esbuild-scripts from this point forward from the context of a consumer project.

Tests should only be developed in the context of the top-level project; thus I'll need to probably generate some very basic tests in the esbuild-scripts project context, and then dive over to the "consumer" project to see which further issues might arise - and need tests for.

nathanjhood commented 2 months ago

Update:

The good:

Screenshot from 2024-09-24 23-41-19

see: esbuild-scripts is listed

The bad:

see: `getClientis also listed, and so isbuild`*

The interesting:

$ yarn getClientEnvironment

The unfortunate:

So we've arrived at an interesting and unforseen choice;

  1. we can allow the helpers to be executable for consumers by keeping the current import/export syntax, but flattening the project directories such that all exectables are in one, flat directory, fixing all import path resolutions
  2. we can instead resort to the OG plan by only symlinking the CLI part into node_modules/bin, and having it bundle in all the helper functions it needs by changing the import/export syntaxes, and removing the helpers from package.json#bin

Rather than make a supposedly "logical" decision now, I'd quite like to experiment with this briefly to investigate usage cases, potential issues, paths of least resistance (pun intended) and so forth.

nathanjhood commented 2 months ago

Progress:

Result:

Screenshot from 2024-09-25 01-00-00

note: the unwanted symlinks to the helpers and build script are gone

The CLI successfully locates the build script, but that script fails due to not resolving a helper function.

Could it be as simple as changing the import statement in the script...?

nathanjhood commented 2 months ago

Progress:

Screenshot from 2024-09-25 02-08-30

So, to take this PR home, I need to set up these exports correctly such that the output, as found in "consumer/node_modules/...." is runnable.

That's a milestone of a bigger milestone - one cornerpiece of the 0.0.1 baseline, in view.

nathanjhood commented 2 months ago

Update:

It's done.

The "consumer" project is building and all is correct. Results are serving as per above, but without any modifications to the node_modules contents. I added the copyPublicFolder function to finish the job.

Main takeaway from this PR was to shim every file with a createRequire(__filename) - __filename, not import.meta.url!!! - so that each one can resolve themselves and their relative imports/requires correctly.

* any mention of import.meta.url automatically converts the file to a module, per NodeJS docs - despite not mentioning the __filename workaround anywhere...

Later, I will probably do something like this in the package.json#exports:

"exports": {
  "src/process/parseArgs.ts": {
    "require": {
      "types": "./dist/process/parseArgs.d.cts",
      "default": "./dist/process/parseArgs.cjs"
    },
    "import": {
      "types": "./dist/process/parseArgs.d.mts",
      "default": "./dist/process/parseArgs.mjs"
    }
  }
  // and all the rest....
}

Just needed to puth the template somewhere so I can use it later to get that done.