Repository: ProjectEvergreen/greenwood (js)

Issue:
bundled static assets from node_modules not getting uploaded to Cloudflare
### What happened?

Noticed in https://github.com/thescientist13/www.owenascode.dev/issues/24 and confirmed by https://github.com/cloudflare/workers-sdk/issues/3615 that any files starting with _node_modules/_ in the public build directory are not getting uploaded, as in this case above, the bundled font files were missing in production deployments 

![Image](https://github.com/user-attachments/assets/59a6ab17-6d3a-4b18-b8cd-d955ac97efaf)

### Steps to reproduce

1. Link to a file in _node_modules_ from a CSS file added a `<link>` tag in a page
    ```css
    @font-face {
      font-family: "Ubuntu";
      src: url("../../node_modules/@fontsource/ubuntu/files/ubuntu-latin-500-normal.woff2")
        format("truetype");
    }
    ```
1. Deploy to Cloudflare Pages

### Environment

- Greenwood - v0.30.0
- Cloudflare pages

### Additional Context

A simple patch test shows that if we just rename the start of the file to _node-modules_ it will work - https://github.com/thescientist13/www.owenascode.dev/pull/25/files#diff-bf1bd480967a87e8817935ffb2315dc10544aadc91f01fac86207af3dcb29e2f

![Image](https://github.com/user-attachments/assets/b0395577-f392-406d-bb37-b9bb687c1909)

This might be a general consideration for other hosting platforms, so can't hurt to add this to the CLI since it's a simple enough fix.

Pull request description:
bug/issue 1431 obfuscate names of bundled node_modules static assets
<!--
## Submitting a Pull Request
We love contributions and appreciate any help you can offer!
-->

## Related Issue

resolves #1431 

## Documentation 

N / A

## Summary of Changes

1. Rename _node_modules_ -> _node-modules_ for bundled static assets

Patch:
diff --git a/packages/cli/src/plugins/resource/plugin-standard-css.js b/packages/cli/src/plugins/resource/plugin-standard-css.js
index a38eded9..e0d8dac3 100644
--- a/packages/cli/src/plugins/resource/plugin-standard-css.js
+++ b/packages/cli/src/plugins/resource/plugin-standard-css.js
@@ -112,6 +112,9 @@ function bundleCss(body, sourceUrl, compilation, workingUrl) {
             const ext = resolvedUrl.pathname.split(".").pop();
 
             finalValue = finalValue.replace(`.${ext}`, `.${hash}.${ext}`);
+            // "obfuscate" these file names since some hosting platforms may ignore node_modules within the build folder
+            // https://github.com/ProjectEvergreen/greenwood/issues/1431
+            finalValue = finalValue.replace("/node_modules/", "/node-modules/");
 
             fs.mkdirSync(new URL(`.${path.dirname(finalValue)}/`, outputDir), {
               recursive: true,


Test patch:
diff --git a/packages/cli/test/cases/build.config.optimization-default/build.config-optimization-default.spec.js b/packages/cli/test/cases/build.config.optimization-default/build.config-optimization-default.spec.js
index 5b07aecc..daf2c388 100644
--- a/packages/cli/test/cases/build.config.optimization-default/build.config-optimization-default.spec.js
+++ b/packages/cli/test/cases/build.config.optimization-default/build.config-optimization-default.spec.js
@@ -156,7 +156,7 @@ describe("Build Greenwood With: ", function () {
 
       describe("bundled URL references in CSS files", function () {
         describe("node modules reference", () => {
-          const fontPath = "node_modules/geist/dist/fonts/geist-sans";
+          const fontPath = "node-modules/geist/dist/fonts/geist-sans";
           let dom;
 
           before(async function () {
diff --git a/packages/cli/test/cases/build.default.import-node-modules/build.default.import-node-modules.spec.js b/packages/cli/test/cases/build.default.import-node-modules/build.default.import-node-modules.spec.js
index bd135b2e..7bcb20dd 100644
--- a/packages/cli/test/cases/build.default.import-node-modules/build.default.import-node-modules.spec.js
+++ b/packages/cli/test/cases/build.default.import-node-modules/build.default.import-node-modules.spec.js
@@ -187,7 +187,7 @@ describe("Build Greenwood With: ", function () {
       it("should have the expected number of font files referenced in vendor CSS file in the output directory", async function () {
         expect(
           await glob.promise(
-            path.join(this.context.publicDir, "node_modules/font-awesome/fonts/*"),
+            path.join(this.context.publicDir, "node-modules/font-awesome/fonts/*"),
           ),
         ).to.have.lengthOf(5);
       });
@@ -200,7 +200,7 @@ describe("Build Greenwood With: ", function () {
 
         expect(
           contents.indexOf(
-            "@font-face {font-family:'FontAwesome';src:url('/node_modules/font-awesome/fonts/fontawesome-webfont.139345087.eot?v=4.7.0');",
+            "@font-face {font-family:'FontAwesome';src:url('/node-modules/font-awesome/fonts/fontawesome-webfont.139345087.eot?v=4.7.0');",
           ) > 0,
         ).to.equal(true);
       });