@bleedingdev/modern-js-create 3.5.0-ultramodern.15 → 3.5.0-ultramodern.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -380,19 +380,21 @@ updating workspaces.
380
380
  | `ULTRAMODERN_ASSET_PREFIX` | UltraModern asset prefix fallback | Modern/Rspack-emitted asset URLs when `MODERN_ASSET_PREFIX` is unset |
381
381
  | `ULTRAMODERN_PUBLIC_URL_<APP_ID>` | Per-app deployment/proof URL | Cloudflare proof inputs and Module Federation remote URLs |
382
382
 
383
- Asset URLs use this precedence: `MODERN_ASSET_PREFIX` →
384
- `ULTRAMODERN_ASSET_PREFIX` → origin-relative `/`. `MODERN_PUBLIC_SITE_URL` is
385
- canonical/SEO-only and must not be used as an asset-prefix fallback.
383
+ Shell asset URLs use this precedence: `MODERN_ASSET_PREFIX` →
384
+ `ULTRAMODERN_ASSET_PREFIX` → origin-relative `/`. Module Federation remotes use
385
+ the same env precedence, then fall back to their per-app public origin:
386
+ configured public URL, inferred workers.dev URL, or local dev port.
387
+ `MODERN_PUBLIC_SITE_URL` is canonical/SEO-only and must not be used as an
388
+ asset-prefix fallback.
386
389
  SEO output uses `MODERN_PUBLIC_SITE_URL`; if it is unset, generated local and
387
390
  preview outputs remain non-public until deployment proof provides explicit
388
391
  public URLs.
389
392
 
390
- Without public URLs configured, asset paths are origin-relative (`/`), and the
391
- dev server uses `dev.assetPrefix: '/'` so apps work through tunnels and
392
- reverse proxies (ngrok, cloudflared) without triggering Chrome's Local Network
393
- Access prompt or mixed-content errors. Shell-only workspaces can set
394
- `MODERN_PUBLIC_SITE_URL` for SEO output without changing where assets load
395
- from.
393
+ Without public URLs configured, shell asset paths are origin-relative (`/`).
394
+ Remote dev manifests publish their own local origin so host shells load
395
+ `remoteEntry.js` and exposed chunks from the remote dev server. Shell-only
396
+ workspaces can set `MODERN_PUBLIC_SITE_URL` for SEO output without changing
397
+ where assets load from.
396
398
 
397
399
  ## Cloudflare And Zephyr Proof
398
400
 
@@ -76,6 +76,11 @@ function createAppModernConfig(scope, app) {
76
76
  (cloudflareDeployEnabled ? '/' : \`http://localhost:\${port}\`);
77
77
  const defaultRemoteAssetPrefix = \`\${remoteAssetOrigin.replace(/\\/+$/u, '')}/\`;
78
78
  const defaultAssetPrefix = defaultRemoteAssetPrefix;`;
79
+ const devAssetPrefixSource = 'shell' === app.kind ? ` // Keep shell dev assets origin-relative so the shell works through
80
+ // tunnels and local previews without rewriting its own chunks.
81
+ assetPrefix: '/',` : ` // Remote dev manifests must publish an absolute publicPath so host
82
+ // shells load remoteEntry.js and exposed chunks from this dev server.
83
+ assetPrefix,`;
79
84
  return `// @effect-diagnostics processEnv:off
80
85
  import {
81
86
  appTools,
@@ -177,9 +182,7 @@ ${bffConfig} ...(cloudflareDeployEnabled
177
182
  }
178
183
  : {}),
179
184
  dev: {
180
- // Keep dev assets origin-relative too; the default absolute
181
- // http://localhost:<port> prefix breaks pages served through tunnels.
182
- assetPrefix: '/',
185
+ ${devAssetPrefixSource}
183
186
  },
184
187
  html: {
185
188
  outputStructure: 'flat',
@@ -25,6 +25,11 @@ function createAppModernConfig(scope, app) {
25
25
  (cloudflareDeployEnabled ? '/' : \`http://localhost:\${port}\`);
26
26
  const defaultRemoteAssetPrefix = \`\${remoteAssetOrigin.replace(/\\/+$/u, '')}/\`;
27
27
  const defaultAssetPrefix = defaultRemoteAssetPrefix;`;
28
+ const devAssetPrefixSource = 'shell' === app.kind ? ` // Keep shell dev assets origin-relative so the shell works through
29
+ // tunnels and local previews without rewriting its own chunks.
30
+ assetPrefix: '/',` : ` // Remote dev manifests must publish an absolute publicPath so host
31
+ // shells load remoteEntry.js and exposed chunks from this dev server.
32
+ assetPrefix,`;
28
33
  return `// @effect-diagnostics processEnv:off
29
34
  import {
30
35
  appTools,
@@ -126,9 +131,7 @@ ${bffConfig} ...(cloudflareDeployEnabled
126
131
  }
127
132
  : {}),
128
133
  dev: {
129
- // Keep dev assets origin-relative too; the default absolute
130
- // http://localhost:<port> prefix breaks pages served through tunnels.
131
- assetPrefix: '/',
134
+ ${devAssetPrefixSource}
132
135
  },
133
136
  html: {
134
137
  outputStructure: 'flat',
@@ -26,6 +26,11 @@ function createAppModernConfig(scope, app) {
26
26
  (cloudflareDeployEnabled ? '/' : \`http://localhost:\${port}\`);
27
27
  const defaultRemoteAssetPrefix = \`\${remoteAssetOrigin.replace(/\\/+$/u, '')}/\`;
28
28
  const defaultAssetPrefix = defaultRemoteAssetPrefix;`;
29
+ const devAssetPrefixSource = 'shell' === app.kind ? ` // Keep shell dev assets origin-relative so the shell works through
30
+ // tunnels and local previews without rewriting its own chunks.
31
+ assetPrefix: '/',` : ` // Remote dev manifests must publish an absolute publicPath so host
32
+ // shells load remoteEntry.js and exposed chunks from this dev server.
33
+ assetPrefix,`;
29
34
  return `// @effect-diagnostics processEnv:off
30
35
  import {
31
36
  appTools,
@@ -127,9 +132,7 @@ ${bffConfig} ...(cloudflareDeployEnabled
127
132
  }
128
133
  : {}),
129
134
  dev: {
130
- // Keep dev assets origin-relative too; the default absolute
131
- // http://localhost:<port> prefix breaks pages served through tunnels.
132
- assetPrefix: '/',
135
+ ${devAssetPrefixSource}
133
136
  },
134
137
  html: {
135
138
  outputStructure: 'flat',
package/package.json CHANGED
@@ -21,7 +21,7 @@
21
21
  "engines": {
22
22
  "node": ">=20"
23
23
  },
24
- "version": "3.5.0-ultramodern.15",
24
+ "version": "3.5.0-ultramodern.16",
25
25
  "types": "./dist/types/index.d.ts",
26
26
  "main": "./dist/esm-node/index.js",
27
27
  "bin": {
@@ -77,7 +77,7 @@
77
77
  "@modern-js/codesmith": "2.6.9",
78
78
  "oxfmt": "0.56.0",
79
79
  "ultracite": "7.8.3",
80
- "@modern-js/i18n-utils": "npm:@bleedingdev/modern-js-i18n-utils@3.5.0-ultramodern.15"
80
+ "@modern-js/i18n-utils": "npm:@bleedingdev/modern-js-i18n-utils@3.5.0-ultramodern.16"
81
81
  },
82
82
  "devDependencies": {
83
83
  "@rslib/core": "0.23.1",
@@ -99,6 +99,6 @@
99
99
  "test": "rm -rf dist && rslib build -c rslibconfig.mts && rstest --passWithNoTests"
100
100
  },
101
101
  "ultramodern": {
102
- "frameworkVersion": "3.5.0-ultramodern.15"
102
+ "frameworkVersion": "3.5.0-ultramodern.16"
103
103
  }
104
104
  }
@@ -117,19 +117,21 @@ regenerating or updating the workspace.
117
117
  | `ULTRAMODERN_ASSET_PREFIX` | UltraModern compatibility asset prefix | Modern/Rspack-emitted asset URLs when `MODERN_ASSET_PREFIX` is unset |
118
118
  | `ULTRAMODERN_PUBLIC_URL_<APP_ID>` | Per-app deployment/proof URL | Cloudflare proof inputs and Module Federation remote URLs |
119
119
 
120
- Asset URLs use this precedence: `MODERN_ASSET_PREFIX` →
121
- `ULTRAMODERN_ASSET_PREFIX` → origin-relative `/`. `MODERN_PUBLIC_SITE_URL` is
122
- canonical/SEO-only and must not be used as an asset-prefix fallback.
120
+ Shell asset URLs use this precedence: `MODERN_ASSET_PREFIX` →
121
+ `ULTRAMODERN_ASSET_PREFIX` → origin-relative `/`. Module Federation remotes use
122
+ the same env precedence, then fall back to their per-app public origin:
123
+ configured public URL, inferred workers.dev URL, or local dev port.
124
+ `MODERN_PUBLIC_SITE_URL` is canonical/SEO-only and must not be used as an
125
+ asset-prefix fallback.
123
126
  SEO output uses `MODERN_PUBLIC_SITE_URL`; if it is unset, generated local and
124
127
  preview outputs remain non-public until deployment proof provides explicit
125
128
  public URLs.
126
129
 
127
- Without public URLs configured, asset paths are origin-relative (`/`), and the
128
- dev server uses `dev.assetPrefix: '/'` so apps work through tunnels and
129
- reverse proxies (ngrok, cloudflared) without triggering Chrome's Local Network
130
- Access prompt or mixed-content errors. Shell-only workspaces can set
131
- `MODERN_PUBLIC_SITE_URL` for SEO output without changing where assets load
132
- from.
130
+ Without public URLs configured, shell asset paths are origin-relative (`/`).
131
+ Remote dev manifests publish their own local origin so host shells load
132
+ `remoteEntry.js` and exposed chunks from the remote dev server. Shell-only
133
+ workspaces can set `MODERN_PUBLIC_SITE_URL` for SEO output without changing
134
+ where assets load from.
133
135
 
134
136
  ## Cloudflare Proof
135
137
 
@@ -486,7 +486,7 @@ const createAppConfigContract = app => ({
486
486
  'zephyrRspackPlugin',
487
487
  ],
488
488
  dev: {
489
- assetPrefix: '/',
489
+ assetPrefix: app.kind === 'shell' ? '/' : 'app-public-origin',
490
490
  },
491
491
  output: {
492
492
  assetPrefix: {
@@ -1967,9 +1967,9 @@ for (const vertical of fullStackVerticals) {
1967
1967
  assert(!verticalAssetPrefixExpression.includes('configuredSiteUrl') && !verticalAssetPrefixExpression.includes('MODERN_PUBLIC_SITE_URL'), `${vertical.id} asset prefix must not fall back to MODERN_PUBLIC_SITE_URL`);
1968
1968
  assert(modernConfig.includes(`envValue('ULTRAMODERN_PUBLIC_URL_${vertical.id.replace(/-/g, '_').toUpperCase()}')`), `${vertical.id} asset prefix must read its per-app public URL`);
1969
1969
  assert(modernConfig.includes('inferredCloudflareUrl'), `${vertical.id} asset prefix must support workers.dev origin inference`);
1970
- assert(modernConfig.includes("assetPrefix: '/'"), `${vertical.id} modern.config.ts must keep dev assets origin-relative`);
1970
+ assert(/dev:\s*\{\s*\/\/ Remote dev manifests must publish an absolute publicPath[\s\S]*?assetPrefix,\s*\}/u.test(modernConfig), `${vertical.id} modern.config.ts must publish dev assets from its own remote origin`);
1971
1971
  assert(modernConfig.includes('assetPrefix,'), `${vertical.id} modern.config.ts must wire output.assetPrefix to the derived asset prefix`);
1972
- assert(contractEntry?.config?.dev?.assetPrefix === '/', `${vertical.id} dev asset prefix must stay origin-relative`);
1972
+ assert(contractEntry?.config?.dev?.assetPrefix === 'app-public-origin', `${vertical.id} dev asset prefix must default to its app public origin`);
1973
1973
  assert(contractEntry?.config?.output?.assetPrefix?.default === 'app-public-origin', `${vertical.id} asset prefix must default to its app public origin`);
1974
1974
  assert(JSON.stringify(contractEntry?.config?.output?.assetPrefix?.envFallbackOrder) === JSON.stringify(['MODERN_ASSET_PREFIX', 'ULTRAMODERN_ASSET_PREFIX']), `${vertical.id} asset prefix env fallback order is incorrect`);
1975
1975
  assert(contractEntry?.config?.output?.disableTsChecker === false, `${vertical.id} must keep the framework TypeScript checker enabled`);