@wordpress/build 0.4.1-next.8b30e05b0.0 → 0.4.1-next.8fd3f8831.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.
- package/.cache/tsconfig.tsbuildinfo +1 -1
- package/README.md +54 -6
- package/package.json +6 -8
- package/src/build.mjs +175 -59
- package/src/dependency-graph.mjs +36 -110
- package/src/package-utils.mjs +45 -10
- package/src/php-generator.mjs +8 -3
- package/src/route-utils.mjs +13 -4
- package/src/wordpress-externals-plugin.mjs +78 -15
- package/templates/module-registration.php.template +1 -1
- package/templates/page-wp-admin.php.template +65 -28
- package/templates/page.php.template +2 -2
- package/templates/routes-registration.php.template +2 -2
- package/templates/script-registration.php.template +1 -1
- package/templates/style-registration.php.template +1 -1
package/src/dependency-graph.mjs
CHANGED
|
@@ -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 {
|
|
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(
|
|
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
|
|
26
|
+
* Get package dependencies from a package.json object.
|
|
40
27
|
*
|
|
41
|
-
* @param {
|
|
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(
|
|
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
|
|
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
|
|
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}
|
|
190
|
-
* @param {string
|
|
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,
|
|
117
|
+
function getReverseDependencies( packageName, workspacePackages ) {
|
|
194
118
|
const dependents = [];
|
|
195
119
|
|
|
196
|
-
for ( const pkg of
|
|
197
|
-
const deps = getDependencies(
|
|
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}
|
|
222
|
-
* @param {string
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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}
|
|
300
|
-
* @param {string
|
|
301
|
-
* @param {string}
|
|
302
|
-
* @param {string[]}
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
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,
|
package/src/package-utils.mjs
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* External dependencies
|
|
3
3
|
*/
|
|
4
|
-
import { readFileSync } from 'fs';
|
|
5
|
-
import {
|
|
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
|
|
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}
|
|
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
|
-
|
|
52
|
-
|
|
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
|
-
|
|
56
|
-
const
|
|
57
|
-
|
|
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
|
}
|
package/src/php-generator.mjs
CHANGED
|
@@ -15,10 +15,14 @@ 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
|
|
19
|
-
* @
|
|
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}}, {{VERSION_CONSTANT}}, {{BASE_URL}}.
|
|
20
21
|
*/
|
|
21
|
-
export async function getPhpReplacements(
|
|
22
|
+
export async function getPhpReplacements(
|
|
23
|
+
rootDir,
|
|
24
|
+
baseUrlExpression = "plugins_url( 'build', dirname( __FILE__ ) )"
|
|
25
|
+
) {
|
|
22
26
|
const rootPackageJson = getPackageInfoFromFile(
|
|
23
27
|
path.join( rootDir, 'package.json' )
|
|
24
28
|
);
|
|
@@ -36,6 +40,7 @@ export async function getPhpReplacements( rootDir ) {
|
|
|
36
40
|
'{{PREFIX}}': name,
|
|
37
41
|
'{{VERSION}}': version,
|
|
38
42
|
'{{VERSION_CONSTANT}}': versionConstant,
|
|
43
|
+
'{{BASE_URL}}': baseUrlExpression,
|
|
39
44
|
};
|
|
40
45
|
}
|
|
41
46
|
|
package/src/route-utils.mjs
CHANGED
|
@@ -30,9 +30,9 @@ export function getAllRoutes( rootDir ) {
|
|
|
30
30
|
|
|
31
31
|
/**
|
|
32
32
|
* @typedef {Object} RouteMetadata
|
|
33
|
-
* @property {string}
|
|
34
|
-
* @property {string}
|
|
35
|
-
* @property {string
|
|
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
|
-
|
|
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(
|
|
216
|
+
const packageJson = getPackageInfo(
|
|
217
|
+
packageName,
|
|
218
|
+
args.resolveDir
|
|
219
|
+
);
|
|
184
220
|
|
|
185
221
|
if ( ! packageJson ) {
|
|
186
222
|
return undefined;
|
|
@@ -220,6 +256,7 @@ export function createWordpressExternalsPlugin(
|
|
|
220
256
|
return {
|
|
221
257
|
path: args.path,
|
|
222
258
|
external: true,
|
|
259
|
+
sideEffects: !! packageJson.sideEffects,
|
|
223
260
|
};
|
|
224
261
|
}
|
|
225
262
|
|
|
@@ -280,17 +317,6 @@ export function createWordpressExternalsPlugin(
|
|
|
280
317
|
return;
|
|
281
318
|
}
|
|
282
319
|
|
|
283
|
-
// Merge discovered dependencies with extra dependencies
|
|
284
|
-
const allDependencies = new Set( [
|
|
285
|
-
...dependencies,
|
|
286
|
-
...extraDependencies,
|
|
287
|
-
] );
|
|
288
|
-
|
|
289
|
-
const dependenciesString = Array.from( allDependencies )
|
|
290
|
-
.sort()
|
|
291
|
-
.map( ( dep ) => `'${ dep }'` )
|
|
292
|
-
.join( ', ' );
|
|
293
|
-
|
|
294
320
|
// Format module dependencies as array of arrays with 'id' and 'import' keys
|
|
295
321
|
const moduleDependenciesArray = Array.from(
|
|
296
322
|
moduleDependencies.entries()
|
|
@@ -306,7 +332,44 @@ export function createWordpressExternalsPlugin(
|
|
|
306
332
|
? moduleDependenciesArray.join( ', ' )
|
|
307
333
|
: '';
|
|
308
334
|
|
|
309
|
-
|
|
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 );
|
|
310
373
|
|
|
311
374
|
const parts = [
|
|
312
375
|
`'dependencies' => array(${ dependenciesString })`,
|
|
@@ -19,7 +19,7 @@ if ( ! function_exists( '{{PREFIX}}_register_script_modules' ) ) {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
$modules = require $modules_file;
|
|
22
|
-
$base_url =
|
|
22
|
+
$base_url = {{BASE_URL}} . '/modules/';
|
|
23
23
|
$extension = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '.js' : '.min.js';
|
|
24
24
|
|
|
25
25
|
foreach ( $modules as $module ) {
|