@wordpress/build 0.4.1-next.6deb34194.0 → 0.4.1-next.76cff8c98.0

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.
@@ -5,30 +5,17 @@
5
5
  * and determine the correct build order using topological sorting.
6
6
  */
7
7
 
8
- /**
9
- * External dependencies
10
- */
11
- import toposort from 'toposort';
12
-
13
- /**
14
- * Node dependencies
15
- */
16
8
  import path from 'path';
17
-
18
- /**
19
- * Internal dependencies
20
- */
21
- import { getPackageInfo, getPackageInfoFromFile } from './package-utils.mjs';
9
+ import { getPackageInfoFromFile } from './package-utils.mjs';
22
10
 
23
11
  /**
24
12
  * Check if a package is a script or script module.
25
13
  * A package is a script if it has wpScript or wpScriptModuleExports.
26
14
  *
27
- * @param {string} packageName The full package name (e.g., '@wordpress/blocks').
15
+ * @param {import('./package-utils.mjs').PackageJson|null|undefined} packageJson The package.json object.
28
16
  * @return {boolean} True if the package is a script or script module.
29
17
  */
30
- function isScriptOrModule( packageName ) {
31
- const packageJson = getPackageInfo( packageName );
18
+ function isScriptOrModule( packageJson ) {
32
19
  if ( ! packageJson ) {
33
20
  return false;
34
21
  }
@@ -36,13 +23,12 @@ function isScriptOrModule( packageName ) {
36
23
  }
37
24
 
38
25
  /**
39
- * Get package dependencies from a package.json file.
26
+ * Get package dependencies from a package.json object.
40
27
  *
41
- * @param {string} packageName The full package name (e.g., '@wordpress/blocks').
28
+ * @param {import('./package-utils.mjs').PackageJson|null|undefined} packageJson The package.json object.
42
29
  * @return {string[]} Array of package names this package depends on.
43
30
  */
44
- function getDependencies( packageName ) {
45
- const packageJson = getPackageInfo( packageName );
31
+ function getDependencies( packageJson ) {
46
32
  if ( ! packageJson ) {
47
33
  return [];
48
34
  }
@@ -52,78 +38,15 @@ function getDependencies( packageName ) {
52
38
  return Object.keys( deps );
53
39
  }
54
40
 
55
- /**
56
- * Build a dependency graph for the given packages.
57
- *
58
- * @param {string[]} packages Array of full package names to analyze.
59
- * @return {Array<[string, string]>} Array of [dependent, dependency] edges.
60
- */
61
- function buildDependencyGraph( packages ) {
62
- /** @type {Array<[string, string]>} */
63
- const edges = [];
64
- const packagesSet = new Set( packages );
65
-
66
- for ( const packageName of packages ) {
67
- const deps = getDependencies( packageName );
68
-
69
- // Only include edges where both packages are in our list
70
- for ( const dep of deps ) {
71
- if ( packagesSet.has( dep ) ) {
72
- edges.push( [ packageName, dep ] );
73
- }
74
- }
75
-
76
- // If package has no dependencies in our list, add a self-reference
77
- // This ensures it appears in the sorted output
78
- if ( deps.filter( ( dep ) => packagesSet.has( dep ) ).length === 0 ) {
79
- edges.push( [ packageName, packageName ] );
80
- }
81
- }
82
-
83
- return edges;
84
- }
85
-
86
- /**
87
- * Sort packages in topological order based on their dependencies.
88
- *
89
- * @param {string[]} packages Array of full package names to sort.
90
- * @return {string[]} Sorted array where dependencies come before dependents.
91
- */
92
- function topologicalSort( packages ) {
93
- const edges = buildDependencyGraph( packages );
94
-
95
- try {
96
- // toposort returns dependencies first, then dependents
97
- /** @type {Array<string>} */
98
- const sorted = toposort( edges );
99
-
100
- // Filter to only include packages in our input list
101
- // (toposort might include extra nodes)
102
- const packagesSet = new Set( packages );
103
- return sorted.filter( ( pkg ) => packagesSet.has( pkg ) );
104
- } catch ( error ) {
105
- if ( error instanceof Error && error.message.includes( 'cyclic' ) ) {
106
- console.error(
107
- '❌ Cyclic dependency detected in packages:',
108
- error.message
109
- );
110
- throw new Error(
111
- 'Cannot build packages due to cyclic dependencies'
112
- );
113
- }
114
- throw error;
115
- }
116
- }
117
-
118
41
  /**
119
42
  * Group packages by dependency depth level.
120
43
  * Packages at the same depth level can be built in parallel.
121
44
  *
122
- * @param {string[]} packages Array of full package names to group.
123
- * @return {string[][]} Array of arrays, where each inner array is a depth level.
45
+ * @param {Map<string, import('./package-utils.mjs').PackageJson>} packages Map of package names to package.json objects.
46
+ * @return {string[][]} Array of arrays, where each inner array is a depth level containing package names.
124
47
  */
125
48
  function groupByDepth( packages ) {
126
- const packagesSet = new Set( packages );
49
+ const packagesSet = new Set( packages.keys() );
127
50
  const depths = new Map();
128
51
  const visited = new Set();
129
52
 
@@ -145,7 +68,8 @@ function groupByDepth( packages ) {
145
68
 
146
69
  visited.add( packageName );
147
70
 
148
- const deps = getDependencies( packageName );
71
+ const packageJson = packages.get( packageName );
72
+ const deps = getDependencies( packageJson );
149
73
  const relevantDeps = deps.filter( ( dep ) => packagesSet.has( dep ) );
150
74
 
151
75
  if ( relevantDeps.length === 0 ) {
@@ -163,7 +87,7 @@ function groupByDepth( packages ) {
163
87
  }
164
88
 
165
89
  // Calculate depth for all packages
166
- for ( const packageName of packages ) {
90
+ for ( const packageName of packages.keys() ) {
167
91
  calculateDepth( packageName );
168
92
  }
169
93
 
@@ -172,7 +96,7 @@ function groupByDepth( packages ) {
172
96
  const maxDepth = Math.max( ...depths.values() );
173
97
 
174
98
  for ( let depth = 0; depth <= maxDepth; depth++ ) {
175
- const packagesAtDepth = packages.filter(
99
+ const packagesAtDepth = Array.from( packages.keys() ).filter(
176
100
  ( pkg ) => depths.get( pkg ) === depth
177
101
  );
178
102
  if ( packagesAtDepth.length > 0 ) {
@@ -186,15 +110,15 @@ function groupByDepth( packages ) {
186
110
  /**
187
111
  * Get packages that depend on a given package (reverse dependencies).
188
112
  *
189
- * @param {string} packageName The full package name to find dependents of.
190
- * @param {string[]} allPackages Array of all full package names to search.
113
+ * @param {string} packageName The full package name to find dependents of.
114
+ * @param {Map<string, import('./package-utils.mjs').PackageJson>} workspacePackages Map of workspace package names to package.json objects.
191
115
  * @return {string[]} Array of package names that depend on the given package.
192
116
  */
193
- function getReverseDependencies( packageName, allPackages ) {
117
+ function getReverseDependencies( packageName, workspacePackages ) {
194
118
  const dependents = [];
195
119
 
196
- for ( const pkg of allPackages ) {
197
- const deps = getDependencies( pkg );
120
+ for ( const [ pkg, packageJson ] of workspacePackages ) {
121
+ const deps = getDependencies( packageJson );
198
122
  if ( deps.includes( packageName ) ) {
199
123
  dependents.push( pkg );
200
124
  }
@@ -218,14 +142,15 @@ function getReverseDependencies( packageName, allPackages ) {
218
142
  * - D (script) depends on C
219
143
  * Result: Only C needs rebundling (D stops at C boundary)
220
144
  *
221
- * @param {string} changedPackage The full package name that changed.
222
- * @param {string[]} allPackages Array of all full package names.
145
+ * @param {string} changedPackage The full package name that changed.
146
+ * @param {Map<string, import('./package-utils.mjs').PackageJson>} workspacePackages Map of workspace package names to package.json objects.
223
147
  * @return {string[]} Array of script/module package names to rebundle.
224
148
  */
225
- function findScriptsToRebundle( changedPackage, allPackages ) {
149
+ function findScriptsToRebundle( changedPackage, workspacePackages ) {
226
150
  // If the changed package itself is a script/module, no need to find others
227
151
  // (it will be rebuilt by the regular watch logic)
228
- if ( isScriptOrModule( changedPackage ) ) {
152
+ const changedPackageJson = workspacePackages.get( changedPackage );
153
+ if ( isScriptOrModule( changedPackageJson ) ) {
229
154
  return [];
230
155
  }
231
156
 
@@ -244,13 +169,14 @@ function findScriptsToRebundle( changedPackage, allPackages ) {
244
169
  // Get all packages that depend on the current package
245
170
  const dependents = getReverseDependencies(
246
171
  currentPackage,
247
- allPackages
172
+ workspacePackages
248
173
  );
249
174
 
250
175
  for ( const dependent of dependents ) {
251
176
  // If this dependent is a script/module, add it to the result
252
177
  // but don't traverse further (stop at script boundaries)
253
- if ( isScriptOrModule( dependent ) ) {
178
+ const dependentPackageJson = workspacePackages.get( dependent );
179
+ if ( isScriptOrModule( dependentPackageJson ) ) {
254
180
  scriptsToRebundle.add( dependent );
255
181
  } else if ( ! visited.has( dependent ) ) {
256
182
  // If it's a bundled package, continue traversing
@@ -296,21 +222,22 @@ function getRouteDependencies( rootDir, routeName ) {
296
222
  * - home (route) depends on B
297
223
  * Result: Both C and home need rebuilding
298
224
  *
299
- * @param {string} changedPackage The full package name that changed.
300
- * @param {string[]} allPackages Array of all full package names.
301
- * @param {string} rootDir Root directory path.
302
- * @param {string[]} allRoutes Array of all route names.
225
+ * @param {string} changedPackage The full package name that changed.
226
+ * @param {Map<string, import('./package-utils.mjs').PackageJson>} workspacePackages Map of workspace package names to package.json objects.
227
+ * @param {string} rootDir Root directory path.
228
+ * @param {string[]} allRoutes Array of all route names.
303
229
  * @return {string[]} Array of route names to rebuild.
304
230
  */
305
231
  function findRoutesToRebuild(
306
232
  changedPackage,
307
- allPackages,
233
+ workspacePackages,
308
234
  rootDir,
309
235
  allRoutes
310
236
  ) {
311
237
  // If the changed package itself is a script/module, routes won't be affected
312
238
  // (routes depend on bundled packages, not scripts/modules)
313
- if ( isScriptOrModule( changedPackage ) ) {
239
+ const changedPackageJson = workspacePackages.get( changedPackage );
240
+ if ( isScriptOrModule( changedPackageJson ) ) {
314
241
  return [];
315
242
  }
316
243
 
@@ -337,14 +264,15 @@ function findRoutesToRebuild(
337
264
  // Get all packages that depend on the current package
338
265
  const dependents = getReverseDependencies(
339
266
  currentPackage,
340
- allPackages
267
+ workspacePackages
341
268
  );
342
269
 
343
270
  for ( const dependent of dependents ) {
344
271
  // If this dependent is a script/module, don't traverse further
345
272
  // (stop at script boundaries)
273
+ const dependentPackageJson = workspacePackages.get( dependent );
346
274
  if (
347
- ! isScriptOrModule( dependent ) &&
275
+ ! isScriptOrModule( dependentPackageJson ) &&
348
276
  ! visited.has( dependent )
349
277
  ) {
350
278
  // If it's a bundled package, continue traversing
@@ -358,8 +286,6 @@ function findRoutesToRebuild(
358
286
 
359
287
  export {
360
288
  getDependencies,
361
- buildDependencyGraph,
362
- topologicalSort,
363
289
  groupByDepth,
364
290
  isScriptOrModule,
365
291
  getReverseDependencies,
@@ -1,8 +1,9 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import { readFileSync } from 'fs';
5
- import { fileURLToPath } from 'url';
4
+ import { readFileSync, existsSync } from 'fs';
5
+ import { createRequire } from 'module';
6
+ import path from 'path';
6
7
 
7
8
  /**
8
9
  * Shared cache for package.json files to avoid redundant reads.
@@ -40,21 +41,55 @@ const packagePathCache = new Map();
40
41
  * @typedef {PackageJson & { route: { path: string; page?: string } }} RoutePackageJson
41
42
  */
42
43
 
44
+ /**
45
+ * Find the nearest package root directory by walking up from the given directory.
46
+ * Looks for a directory containing package.json.
47
+ *
48
+ * @param {string} startDir The directory to start searching from.
49
+ * @return {string} The package root directory, or the start directory if no package.json found.
50
+ */
51
+ function findPackageRoot( startDir ) {
52
+ let current = startDir;
53
+ const root = path.parse( current ).root;
54
+
55
+ while ( current !== root ) {
56
+ const packageJsonPath = path.join( current, 'package.json' );
57
+ if ( existsSync( packageJsonPath ) ) {
58
+ return current;
59
+ }
60
+ current = path.dirname( current );
61
+ }
62
+
63
+ // Fallback to the start directory if no package.json found
64
+ return startDir;
65
+ }
66
+
43
67
  /**
44
68
  * Get package.json info using Node's module resolution.
45
- * Resolves the package using import.meta.resolve and reads its package.json.
69
+ * Resolves packages from the appropriate context to support both workspace packages
70
+ * and external dependencies in pnpm/yarn/npm workspaces.
46
71
  *
47
- * @param {string} fullPackageName The full package name (e.g., '@wordpress/blocks').
72
+ * @param {string} fullPackageName The full package name (e.g., '@wordpress/blocks').
73
+ * @param {string|null} resolveDir Optional directory context for resolution (from esbuild).
48
74
  * @return {PackageJson|null} Package.json object or null if not found.
49
75
  */
50
- export function getPackageInfo( fullPackageName ) {
51
- if ( packageJsonCache.has( fullPackageName ) ) {
52
- return packageJsonCache.get( fullPackageName );
76
+ export function getPackageInfo( fullPackageName, resolveDir = null ) {
77
+ // Determine the package root for cache keying
78
+ const packageRoot = resolveDir
79
+ ? findPackageRoot( resolveDir )
80
+ : process.cwd();
81
+ const cacheKey = `${ fullPackageName }@${ packageRoot }`;
82
+
83
+ if ( packageJsonCache.has( cacheKey ) ) {
84
+ return packageJsonCache.get( cacheKey );
53
85
  }
54
86
 
55
- const resolved = import.meta.resolve( `${ fullPackageName }/package.json` );
56
- const result = getPackageInfoFromFile( fileURLToPath( resolved ) );
57
- packageJsonCache.set( fullPackageName, result );
87
+ // Resolve from the package root context to get correct versions
88
+ const contextPath = path.join( packageRoot, 'package.json' );
89
+ const require = createRequire( contextPath );
90
+ const resolved = require.resolve( `${ fullPackageName }/package.json` );
91
+ const result = getPackageInfoFromFile( resolved );
92
+ packageJsonCache.set( cacheKey, result );
58
93
 
59
94
  return result;
60
95
  }
@@ -15,10 +15,11 @@ const __dirname = path.dirname( fileURLToPath( import.meta.url ) );
15
15
  /**
16
16
  * Get PHP replacements from root package.json.
17
17
  *
18
- * @param {string} rootDir Root directory path.
19
- * @return {Promise<Record<string, string>>} Replacements object with {{PREFIX}}, {{VERSION}}, {{VERSION_CONSTANT}}.
18
+ * @param {string} rootDir Root directory path.
19
+ * @param {string} baseUrlExpression PHP expression for base URL (e.g. "includes_url( 'build' )").
20
+ * @return {Promise<Record<string, string>>} Replacements object with {{PREFIX}}, {{VERSION}}, {{BASE_URL}}.
20
21
  */
21
- export async function getPhpReplacements( rootDir ) {
22
+ export async function getPhpReplacements( rootDir, baseUrlExpression ) {
22
23
  const rootPackageJson = getPackageInfoFromFile(
23
24
  path.join( rootDir, 'package.json' )
24
25
  );
@@ -29,13 +30,11 @@ export async function getPhpReplacements( rootDir ) {
29
30
  // @ts-expect-error specific override to package.json
30
31
  const name = rootPackageJson.wpPlugin?.name || 'gutenberg';
31
32
  const version = rootPackageJson.version;
32
- const versionConstant =
33
- name.toUpperCase().replace( /-/g, '_' ) + '_VERSION';
34
33
 
35
34
  return {
36
35
  '{{PREFIX}}': name,
37
36
  '{{VERSION}}': version,
38
- '{{VERSION_CONSTANT}}': versionConstant,
37
+ '{{BASE_URL}}': baseUrlExpression,
39
38
  };
40
39
  }
41
40
 
@@ -30,9 +30,9 @@ export function getAllRoutes( rootDir ) {
30
30
 
31
31
  /**
32
32
  * @typedef {Object} RouteMetadata
33
- * @property {string} name Route name.
34
- * @property {string} path Route path.
35
- * @property {string|null} page Page slug this route belongs to.
33
+ * @property {string} name Route name.
34
+ * @property {string} path Route path.
35
+ * @property {string[]} pages Array of page slugs this route belongs to.
36
36
  */
37
37
 
38
38
  /**
@@ -54,10 +54,19 @@ export function getRouteMetadata( rootDir, routeName ) {
54
54
  return null;
55
55
  }
56
56
 
57
+ // Normalize page field to always be an array
58
+ // Supports both "page": "string" and "page": ["array"]
59
+ const pageField = routePackageJson.route.page;
60
+ /** @type {string[]} */
61
+ let pages = [];
62
+ if ( pageField ) {
63
+ pages = Array.isArray( pageField ) ? pageField : [ pageField ];
64
+ }
65
+
57
66
  return {
58
67
  name: routeName,
59
68
  path: routePackageJson.route.path,
60
- page: routePackageJson.route.page || null,
69
+ pages,
61
70
  };
62
71
  }
63
72
 
@@ -1,15 +1,46 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import { writeFile, mkdir } from 'fs/promises';
4
+ import { writeFile, mkdir, readFile } from 'fs/promises';
5
5
  import path from 'path';
6
6
  import { camelCase } from 'change-case';
7
+ import { createHash } from 'crypto';
7
8
 
8
9
  /**
9
10
  * Internal dependencies
10
11
  */
11
12
  import { getPackageInfo } from './package-utils.mjs';
12
13
 
14
+ /**
15
+ * Generate a content hash from file contents.
16
+ * Uses SHA256 algorithm for broad compatibility across Node.js versions.
17
+ *
18
+ * @param {string[]} filePaths - Absolute paths to files to hash
19
+ * @param {string} algorithm - Hash algorithm (default: 'sha256')
20
+ * @param {number} length - Hash length (default: 20)
21
+ * @return {Promise<string>} Content hash string
22
+ */
23
+ async function generateContentHash(
24
+ filePaths,
25
+ algorithm = 'sha256',
26
+ length = 20
27
+ ) {
28
+ const hashBuilder = createHash( algorithm );
29
+
30
+ // Sort paths for deterministic ordering
31
+ const sortedPaths = [ ...filePaths ].sort();
32
+
33
+ // Read and hash each file
34
+ for ( const filePath of sortedPaths ) {
35
+ const content = await readFile( filePath );
36
+ hashBuilder.update( content );
37
+ }
38
+
39
+ // Generate hash as hex string and truncate
40
+ const fullHash = hashBuilder.digest( 'hex' );
41
+ return fullHash.slice( 0, length );
42
+ }
43
+
13
44
  /**
14
45
  * Create WordPress externals plugin for esbuild.
15
46
  * This plugin handles WordPress package externals and vendor libraries,
@@ -33,12 +64,14 @@ export function createWordpressExternalsPlugin(
33
64
  * @param {string} assetName Base name for the asset file (e.g., 'index.min').
34
65
  * @param {string} buildFormat Build format: 'iife' for classic scripts, 'esm' for modules.
35
66
  * @param {Array<string>} extraDependencies Additional dependencies to include in the asset file.
67
+ * @param {boolean} generateAssetFile Whether to generate the .asset.php file. Default true.
36
68
  * @return {Object} esbuild plugin object.
37
69
  */
38
70
  return function wordpressExternalsPlugin(
39
71
  assetName = 'index.min',
40
72
  buildFormat = 'iife',
41
- extraDependencies = []
73
+ extraDependencies = [],
74
+ generateAssetFile = true
42
75
  ) {
43
76
  return {
44
77
  name: 'wordpress-externals',
@@ -180,7 +213,10 @@ export function createWordpressExternalsPlugin(
180
213
  const shortName = parts[ 1 ];
181
214
  const handle = `${ externalConfig.handlePrefix }-${ shortName }`;
182
215
 
183
- const packageJson = getPackageInfo( packageName );
216
+ const packageJson = getPackageInfo(
217
+ packageName,
218
+ args.resolveDir
219
+ );
184
220
 
185
221
  if ( ! packageJson ) {
186
222
  return undefined;
@@ -281,17 +317,6 @@ export function createWordpressExternalsPlugin(
281
317
  return;
282
318
  }
283
319
 
284
- // Merge discovered dependencies with extra dependencies
285
- const allDependencies = new Set( [
286
- ...dependencies,
287
- ...extraDependencies,
288
- ] );
289
-
290
- const dependenciesString = Array.from( allDependencies )
291
- .sort()
292
- .map( ( dep ) => `'${ dep }'` )
293
- .join( ', ' );
294
-
295
320
  // Format module dependencies as array of arrays with 'id' and 'import' keys
296
321
  const moduleDependenciesArray = Array.from(
297
322
  moduleDependencies.entries()
@@ -307,7 +332,44 @@ export function createWordpressExternalsPlugin(
307
332
  ? moduleDependenciesArray.join( ', ' )
308
333
  : '';
309
334
 
310
- const version = Date.now();
335
+ // Only generate asset file if requested
336
+ if ( ! generateAssetFile ) {
337
+ return;
338
+ }
339
+
340
+ // Merge discovered dependencies with extra dependencies
341
+ const allDependencies = new Set( [
342
+ ...dependencies,
343
+ ...extraDependencies,
344
+ ] );
345
+
346
+ const dependenciesString = Array.from( allDependencies )
347
+ .sort()
348
+ .map( ( dep ) => `'${ dep }'` )
349
+ .join( ', ' );
350
+
351
+ // Determine output file path from build config
352
+ let outputFilePath;
353
+ if ( build.initialOptions.outfile ) {
354
+ outputFilePath = build.initialOptions.outfile;
355
+ } else if ( build.initialOptions.outdir ) {
356
+ // Construct expected output filename from assetName
357
+ // e.g., assetName='index.min' -> 'index.min.js'
358
+ outputFilePath = path.join(
359
+ build.initialOptions.outdir,
360
+ `${ assetName }.js`
361
+ );
362
+ }
363
+
364
+ // Collect files to hash
365
+ const filesToHash = [];
366
+ if ( outputFilePath ) {
367
+ filesToHash.push( outputFilePath );
368
+ }
369
+
370
+ // Generate content-based version hash
371
+ const version =
372
+ await generateContentHash( filesToHash );
311
373
 
312
374
  const parts = [
313
375
  `'dependencies' => array(${ dependenciesString })`,
@@ -0,0 +1,14 @@
1
+ <?php
2
+ /**
3
+ * Plugin constants - Auto-generated by build process.
4
+ * Do not edit this file manually.
5
+ *
6
+ * Returns an array of constants for use in other templates.
7
+ *
8
+ * @package {{PREFIX}}
9
+ */
10
+
11
+ return array(
12
+ 'version' => '{{VERSION}}',
13
+ 'build_url' => {{BASE_URL}},
14
+ );
@@ -6,12 +6,6 @@
6
6
  * @package {{PREFIX}}
7
7
  */
8
8
 
9
- // Load version constant.
10
- $version_file = __DIR__ . '/version.php';
11
- if ( file_exists( $version_file ) ) {
12
- require_once $version_file;
13
- }
14
-
15
9
  // Load script module registration.
16
10
  $modules_file = __DIR__ . '/modules.php';
17
11
  if ( file_exists( $modules_file ) ) {
@@ -11,6 +11,8 @@ if ( ! function_exists( '{{PREFIX}}_register_script_modules' ) ) {
11
11
  * Register all script modules.
12
12
  */
13
13
  function {{PREFIX}}_register_script_modules() {
14
+ // Load build constants
15
+ $build_constants = require __DIR__ . '/constants.php';
14
16
  $modules_dir = __DIR__ . '/modules';
15
17
  $modules_file = $modules_dir . '/index.php';
16
18
 
@@ -19,7 +21,7 @@ if ( ! function_exists( '{{PREFIX}}_register_script_modules' ) ) {
19
21
  }
20
22
 
21
23
  $modules = require $modules_file;
22
- $base_url = plugins_url( 'build/modules/', dirname( __FILE__ ) );
24
+ $base_url = $build_constants['build_url'] . 'modules/';
23
25
  $extension = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '.js' : '.min.js';
24
26
 
25
27
  foreach ( $modules as $module ) {