Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .buildkite/pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ env:

steps:
- label: ':react: Build React App'
command: make build REFRESH_L10N=1
command: make build REFRESH_L10N=1 REFRESH_JS_BUILD=1
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ensure CI tasks always rebuild the JavaScript to avoid unexpectedly stale builds.

plugins: &plugins
- $CI_TOOLKIT_PLUGIN
- $NVM_PLUGIN
Expand All @@ -21,7 +21,7 @@ steps:

- label: ':android: Publish Android Library'
command: |
make build REFRESH_L10N=1
make build REFRESH_L10N=1 REFRESH_JS_BUILD=1
echo "--- :android: Publishing Android Library"
./android/gradlew -p ./android :gutenberg:prepareToPublishToS3 $(prepare_to_publish_to_s3_params) :gutenberg:publish
agents:
Expand Down
13 changes: 8 additions & 5 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,9 @@ make build
# - ios/Sources/GutenbergKit/Gutenberg/
# - android/Gutenberg/src/main/assets/

# By default, dependencies and translations are only installed if their directories don't exist
# Force refresh of dependencies and translations
make build REFRESH_DEPS=1 REFRESH_L10N=1
# By default, the build is skipped if output directories already exist
# Force refresh of dependencies, translations, and JS build
make build REFRESH_DEPS=1 REFRESH_L10N=1 REFRESH_JS_BUILD=1

# Clean build artifacts
make clean # Clean both dist and translations
Expand All @@ -98,10 +98,13 @@ npm run clean:l10n # Clean only translations directory

```bash
# Build Swift package
swift build
make build-swift-package
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reinstates directives for Claude to prefer the make targets.


# Build Swift package (force refresh of npm deps/translations/build if needed)
make build-swift-package REFRESH_DEPS=1 REFRESH_L10N=1 REFRESH_JS_BUILD=1

# Run Swift tests
swift test
make test-swift-package
```

### Android Development
Expand Down
23 changes: 14 additions & 9 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -68,15 +68,20 @@ clean: ## Remove build artifacts and translation string files

.PHONY: build
build: npm-dependencies prep-translations ## Build the project for all platforms (iOS, Android, web)
@echo "--- :node: Building Gutenberg"

npm run build

# Copy build products into place
@echo "--- :open_file_folder: Copying Build Products into place"
rm -rf ./ios/Sources/GutenbergKit/Gutenberg/ ./android/Gutenberg/src/main/assets/
cp -r ./dist/. ./ios/Sources/GutenbergKit/Gutenberg/
cp -r ./dist/. ./android/Gutenberg/src/main/assets
# Skip unless...
# - dist doesn't exist
# - REFRESH_JS_BUILD is set to true or 1
# - build was invoked directly
@if [ ! -d "dist" ] || [ "$(REFRESH_JS_BUILD)" = "true" ] || [ "$(REFRESH_JS_BUILD)" = "1" ] || echo "$(MAKECMDGOALS)" | grep -q "^build$$"; then \
echo "--- :node: Building Gutenberg"; \
npm run build; \
echo "--- :open_file_folder: Copying Build Products into place"; \
rm -rf ./ios/Sources/GutenbergKit/Gutenberg/ ./android/Gutenberg/src/main/assets/; \
cp -r ./dist/. ./ios/Sources/GutenbergKit/Gutenberg/; \
cp -r ./dist/. ./android/Gutenberg/src/main/assets; \
else \
echo "--- :white_check_mark: Skipping JS build (dist already exists). Use REFRESH_JS_BUILD=1 to force refresh."; \
fi

.PHONY: build-swift-package
build-swift-package: build ## Build the Swift package for iOS
Expand Down
2 changes: 1 addition & 1 deletion bin/release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ build_project() {
return
fi

make build REFRESH_DEPS=1 REFRESH_L10N=1 STRICT_L10N=1
make build REFRESH_DEPS=1 REFRESH_L10N=1 REFRESH_JS_BUILD=1 STRICT_L10N=1
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ensure the release script always creates fresh JavaScript builds.

print_success "Build completed successfully"
}

Expand Down
76 changes: 45 additions & 31 deletions docs/preloading.md
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This existing documentation was formatted via the projects' make format script.

Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ The preloading system consists of several interconnected components:
The `EditorService` actor coordinates fetching all editor dependencies concurrently:

**Swift**

```swift
let service = EditorService(configuration: config)
let dependencies = try await service.prepare { progress in
Expand All @@ -50,40 +51,43 @@ let dependencies = try await service.prepare { progress in
```

**Kotlin**

```kotlin
// TBD
```

The `prepare` method fetches these resources in parallel:
- Editor settings (theme styles, block settings)
- Asset bundles (JavaScript and CSS files)
- Preload list (API responses for editor initialization)

- Editor settings (theme styles, block settings)
- Asset bundles (JavaScript and CSS files)
- Preload list (API responses for editor initialization)

### EditorPreloadList

The `EditorPreloadList` struct contains pre-fetched API responses that are serialized to JSON and injected into the editor's JavaScript runtime:

| Property | API Endpoint | Description |
|----------|--------------|-------------|
| `postData` | `/wp/v2/posts/{id}?context=edit` | The post being edited (existing posts only) |
| `postTypeData` | `/wp/v2/types/{type}?context=edit` | Schema for the current post type |
| `postTypesData` | `/wp/v2/types?context=view` | All available post types |
| `activeThemeData` | `/wp/v2/themes?context=edit&status=active` | Active theme information |
| `settingsOptionsData` | `OPTIONS /wp/v2/settings` | Site settings schema |
| Property | API Endpoint | Description |
| --------------------- | ------------------------------------------ | ------------------------------------------- |
| `postData` | `/wp/v2/posts/{id}?context=edit` | The post being edited (existing posts only) |
| `postTypeData` | `/wp/v2/types/{type}?context=edit` | Schema for the current post type |
| `postTypesData` | `/wp/v2/types?context=view` | All available post types |
| `activeThemeData` | `/wp/v2/themes?context=edit&status=active` | Active theme information |
| `settingsOptionsData` | `OPTIONS /wp/v2/settings` | Site settings schema |

### EditorURLCache

The `EditorURLCache` provides disk-based caching for API responses, keyed by URL and HTTP method. It supports three cache policies via `EditorCachePolicy`:

| Policy | Behavior |
|--------|----------|
| `.ignore` | Never use cached responses (force fresh data) |
| Policy | Behavior |
| ----------------------- | --------------------------------------------------- |
| `.ignore` | Never use cached responses (force fresh data) |
| `.maxAge(TimeInterval)` | Use cached responses younger than the specified age |
| `.always` | Always use cached responses regardless of age |
| `.always` | Always use cached responses regardless of age |

Example:

**Swift**

```swift
// Cache responses for up to 1 hour
let service = EditorService(
Expand All @@ -93,6 +97,7 @@ let service = EditorService(
```

**Kotlin**

```kotlin
// TBD
```
Expand Down Expand Up @@ -158,12 +163,16 @@ The `GBKitGlobal` struct packages all configuration and preload data, then injec

```javascript
window.GBKit = {
siteURL: "https://example.com",
siteApiRoot: "https://example.com/wp-json",
authHeader: "Bearer ...",
preloadData: { /* serialized EditorPreloadList */ },
editorSettings: { /* theme styles, colors, etc. */ },
// ... other configuration
siteURL: 'https://example.com',
siteApiRoot: 'https://example.com/wp-json',
authHeader: 'Bearer ...',
preloadData: {
/* serialized EditorPreloadList */
},
editorSettings: {
/* theme styles, colors, etc. */
},
// ... other configuration
};
```

Expand All @@ -174,11 +183,11 @@ The `@wordpress/api-fetch` package includes a preloading middleware that interce
```javascript
// In src/utils/api-fetch.js
export function configureApiFetch() {
const { preloadData } = getGBKit();
const { preloadData } = getGBKit();

apiFetch.use(
apiFetch.createPreloadingMiddleware(preloadData ?? defaultPreloadData)
);
apiFetch.use(
apiFetch.createPreloadingMiddleware( preloadData ?? defaultPreloadData )
);
}
```

Expand All @@ -193,8 +202,8 @@ When Gutenberg makes an API request:

Only certain headers are preserved in preload responses to match WordPress core's behavior:

- `Accept` - Content type negotiation
- `Link` - REST API discovery and pagination
- `Accept` - Content type negotiation
- `Link` - REST API discovery and pagination

This filtering is performed by `EditorURLResponse.asPreloadResponse()`.

Expand All @@ -205,20 +214,23 @@ This filtering is performed by `EditorURLResponse.asPreloadResponse()`.
`EditorService` automatically cleans up old asset bundles once per day:

**Swift**

```swift
try await onceEvery(.seconds(86_400)) {
try await self.cleanup()
}
```

**Kotlin**

```kotlin
//tbd
```

### Manual Cache Control

**Swift**

```swift
// Clear unused resources (keeps most recent)
try await service.cleanup()
Expand All @@ -228,6 +240,7 @@ try await service.purge()
```

**Kotlin**

```kotlin
//tbd
```
Expand Down Expand Up @@ -261,11 +274,11 @@ that contain everything the editor needs, the progress bar will never be display

`EditorDependencies` contains all pre-fetched resources needed to initialize the editor instantly.

| Property | Type | Description |
|----------|------|-------------|
| `editorSettings` | `EditorSettings` | Theme styles, colors, typography, block settings |
| `assetBundle` | `EditorAssetBundle` | Cached JavaScript/CSS for plugins/themes |
| `preloadList` | `EditorPreloadList?` | Pre-fetched API responses |
| Property | Type | Description |
| ---------------- | -------------------- | ------------------------------------------------ |
| `editorSettings` | `EditorSettings` | Theme styles, colors, typography, block settings |
| `assetBundle` | `EditorAssetBundle` | Cached JavaScript/CSS for plugins/themes |
| `preloadList` | `EditorPreloadList?` | Pre-fetched API responses |

### Obtaining Dependencies

Expand Down Expand Up @@ -326,3 +339,4 @@ class PostListViewController: UIViewController {
navigationController?.pushViewController(editor, animated: true)
}
}
```