Extract Package Versions Script

Why Its Needed Modified: 2025-Dec-03 09:08:52 UTC

package.json

"scripts": {
   "extract-versions": "node scripts/extract-package-versions",
   "prebuild": "npm run extract-versions",
   "predev": "npm run extract-versions"
}

Objective

Ensure the same versions of dependencies are used when dynamically loading modules in Netlify Edge Functions as when run locally in Node.js.

Overview

The extract-package-versions.js script is designed to copy all dependencies from package.json to data/packageDependencies.js so they can be exported during Edge Function runtime. It also, avoids adding them to Netlify Environment Variables, thereby respecing AWS Lambda's 4k size limitiation on the .env file.

How It Works

Sequence Diagram: Pre Build / Pre Dev

sequenceDiagram
participant prebuild/predev
participant extract-package-versions.js

    prebuild/predev ->> extract-package-versions.js: Run extract-versions script
    extract-package-versions.js ->> package.json: Read dependencies
    extract-package-versions.js ->> data/packageDependencies.js: Write dependencies
    extract-package-versions.js -->> prebuild/predev: Script execution complete

Script Details

Why the Script is Needed

The extract-package-versions.js script is essential for ensuring that all dependencies from package.json are accurately copied to data/package_dependencies.js. This is particularly important when dynamically loading modules in Netlify Edge Functions, as it ensures that the correct versions of dependencies are used. Running the script prior to running the build, will keep the versions in sync between the local development environment and the Edge Function runtime.

  1. Edge Functions Lack a Node.js Environment:

    • Edge Functions (like those in Netlify, Cloudflare Workers, etc.) do not run in a traditional Node.js environment. Instead, they operate in a browser-like environment where Node.js-specific features, like require(), import and npm package management, are unavailable.
    • As a result, you can't directly use your node_modules in Edge Functions. Instead, you must use dynamic imports to fetch modules from a CDN, like https://esm.sh.
  2. Ensuring Version Consistency:

    • When you dynamically import modules in an Edge runtime, you often use a URL like this:
      import { ChatOpenAI } from "https://esm.sh/@langchain/openai";
      Without specifying a version, the CDN (esm.sh) will return the latest version of the module, which could be different from the version you have installed locally with npm.
    • This can lead to version mismatches between your local development (running in Node.js) and your Edge Function runtime, which could cause unexpected behavior or errors.
    • By using a script to automatically fetch the exact version of the module from your package.json and append it to the CDN URL, you ensure that both the local and Edge environments use the same version of the package.
  3. Dynamically Importing the Correct Version:

    • For example, if you have @langchain/openai@0.3.2 installed locally via npm, the dynamic import URL in your Edge Function should include that specific version:
      import { ChatOpenAI } from "https://esm.sh/@langchain/openai@0.3.2";
    • This prevents version discrepancies between your local development and your Edge Function's runtime, which can lead to bugs and inconsistencies.

The Script’s Role

The script reads the package.json file prior to the build process and extracts the version of each dependency you are using locally. It then writes these versions to the data/package_dependencies.js file so that your Edge Functions can dynamically import the correct version of each module at runtime.

Why is This Important?

  1. Version Mismatch Prevention:

    • Without the script, your Edge Function could unintentionally import the latest version of a module from a CDN, while your local environment might use an older or different version installed via npm. This could introduce subtle differences in behavior and bugs that are hard to track down.
  2. Automating Version Management:

    • Manually updating the version in the CDN import URL every time you upgrade a package in package.json is prone to errors and is inefficient. The script automates this process by dynamically generating the correct URL with the matching version as part of the build process.
  3. Consistency Across Environments:

    • Ensuring that both your local Node.js environment (using npm) and your Edge runtime (using a CDN) are loading the same versions of packages helps maintain consistent behavior between development and production.

Example Workflow

  1. During Local Development:

    • You install your dependencies using npm, and those dependencies are stored in node_modules and listed in package.json.
    • For example, @langchain/openai@0.3.2 is installed locally:
      {
        "dependencies": {
          "@langchain/openai": "^0.3.2"
        }
      }
  2. At Build Time:

    • The script reads the package.json file and extracts the version of @langchain/openai (in this case, 0.3.2).
    • It then generates a URL for dynamic imports that ensures the version in the CDN matches the locally installed version:
      const langchainVersion = "0.3.2";
      const esmUrl = `https://esm.sh/@langchain/openai@${langchainVersion}`;
      const { ChatOpenAI } = await import(esmUrl);
  3. In Edge Function Deployment:

    • When your Edge Function runs, it dynamically imports @langchain/openai@0.3.2 from the CDN using the URL generated by the script.
    • This ensures that the same version of the module is used in both local development and the Edge runtime, preventing any potential issues caused by version mismatches.

How the Script Solves the Problem

  1. Reads package.json: The script reads the local package.json to find the exact versions of all installed packages.
  2. Generates Dynamic Import URLs: It creates URLs with the correct versions (e.g., https://esm.sh/@langchain/openai@0.3.2), ensuring the Edge runtime imports the same version as what was installed locally.
  3. Writes Dependencies Version: It updates the /data/package_dependencies.js file that is imported during the Edge Function's runtime to further ensure consistency.
  4. Automates the Process: This removes the need for manually managing versions between your local environment and Edge runtime, ensuring consistency and preventing bugs caused by version drift.

Conclusion

The script is necessary because Edge runtimes like Netlify Edge Functions rely on dynamic imports from a CDN instead of local node_modules. Without such a script, version mismatches between locally installed modules (via npm) and modules dynamically loaded in Edge Functions can easily occur. The script ensures that the URL used to dynamically load the module in the Edge runtime points to the same version installed locally, maintaining consistency and preventing bugs.