Skip to content

Commit

Permalink
PRO-6775: External frontend support, docs cleanup (#4799)
Browse files Browse the repository at this point in the history
  • Loading branch information
myovchev authored Nov 8, 2024
1 parent 6d3d7b5 commit a966c53
Show file tree
Hide file tree
Showing 7 changed files with 47 additions and 10 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,14 @@
* Extra bundle detection when using external build module works properly now.
* Widget players are now properly invoked when they arrive later in the page load process.
* Fix permission grid tooltip display.
* Fixes a bug that crashes external frontend applications.
* Fixes a false positive warning for module not in use for project level submodules (e.g. `widges/module.js`) and dot-folders (e.g. `.DS_Store`).

### Adds

* It's possible now to target the HMR build when registering via `template.append` and `template.prepend`. Use `when: 'hmr:public'` or `when: 'hmr:apos'` that will be evaluated against the current asset `options.hmr` configuration.
* Adds asset module option `options.modulePreloadPolyfill` (default `true`) to allow disabling the polyfill preload for e.g. external front-ends.
* Adds `bundleMarkup` to the data sent to the external front-end, containing all markup for injecting Apostrophe UI in the front-end.

## 4.9.0 (2024-10-31)

Expand Down
7 changes: 7 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -699,11 +699,18 @@ async function apostrophe(options, telemetry, rootSpan) {
}
}
async function testDir(name) {
if (name.startsWith('.')) {
return;
}
// Projects that have different theme modules activated at different times
// are a frequent source of false positives for this warning, so ignore
// seemingly unused modules with "theme" in the name
if (!validSteps.includes(name)) {
try {
// It's a project level modules definition, skip it.
if (fs.existsSync(path.resolve(self.localModules, name, 'modules.js'))) {
return;
}
const submodule = await self.root.import(path.resolve(self.localModules, name, 'index.js'));
if (submodule && submodule.options && submodule.options.ignoreUnusedFolderWarning) {
return;
Expand Down
10 changes: 8 additions & 2 deletions modules/@apostrophecms/asset/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,10 @@ module.exports = {
// Force the HMR WS port when it operates on the same process as Apostrophe.
// Most of the time you won't need to change this.
hmrPort: null,
// Let the external build module inject a pollyfill for the module preload,
// adding the `modulepreload` support for the browsers that don't support it.
// Can be disabled in e.g. external front-ends.
modulePreloadPolyfill: true,
// Completely disable the asset runtime auto-build system.
// When an external build module is registered, only manifest data
// will be loaded and no build will be executed.
Expand Down Expand Up @@ -477,6 +481,7 @@ module.exports = {
// - `devServer`: if `false`, the dev server is disabled. Otherwise, it's a string
// (enum) `public` or `apos`. Note that if `hmr` is disabled, the dev server will be always
// `false`.
// - `modulePreloadPolyfill`: if `true`, a module preload polyfill is injected.
// - `types`: optional array, if present it represents the only entrypoint types (entrypoint.type)
// that should be built.
// - `sourcemaps`: if `true`, the source maps are generated in production.
Expand All @@ -494,15 +499,16 @@ module.exports = {
isTask: !argv['check-apos-build'],
hmr: self.hasHMR(),
hmrPort: self.options.hmrPort,
modulePreloadPolyfill: self.options.modulePreloadPolyfill,
sourcemaps: self.options.productionSourceMaps
};
options.devServer = !options.isTask && self.hasDevServer()
? self.options.hmr
: false;

// Skip all public and keep only the apos scenes.
// Skip prebundled UI and keep only the apos scenes.
if (!self.options.publicBundle) {
options.types = [ 'apos', 'bundled' ];
options.types = [ 'apos', 'index' ];
}

return options;
Expand Down
12 changes: 6 additions & 6 deletions modules/@apostrophecms/asset/lib/build/external-module-api.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,8 @@ module.exports = (self) => {
// Returns an array of objects with the following properties:
// - `name`: the entrypoint name. It's usually the relative to `ui` folder
// name(`src`, `apos`, `public`) or an extra bundle name.
// - `label`: the human-readable label for the entrypoint, used to print CLI messages.
// - `type`: (enum) the entrypoint type. It can be `index`, `apos`, `custom` (e.g. extra bundles) or
// `bundled` (e.g. `ui/public`). Every type has associated manager that provides handling for the entrypoint.
// - `useMeta`: if `true`, the entrypoint will be created based on the source metadata (see
// `computeSourceMeta()` method).
// - `bundle`: if `true`, the entrypoint should be bundled by the build module.
// - `index`: if `true`, the entrypoint processes only `{name}/index.{js,scss}` module files.
// - `apos`: if `true`, the entrypoint processes components, icons and apps.
// - `ignoreSources`: an array of sources that shouldn't be processed when creating the entrypoint.
// - `sources`: an object with `js` and `scss` arrays of extra sources to be included in the entrypoint.
// These sources are not affected by the `ignoreSources` configuration.
Expand All @@ -84,10 +79,15 @@ module.exports = (self) => {
// - `prologue`: a string with the prologue to be added to the entrypoint.
// - `condition`: the JS `module` or `nomodule` condition. Undefined for no specific condition.
// - `outputs`: an array of output extensions for the entrypoint (currently not fully utilized)
// - `inputs`: an array of input extensions for the entrypoint (currently not fully utilized)
// - `scenes`: an array of scenes to be in the final post-bundle step. The scenes are instructions
// for the Apostrophe core to combine the builds and release them. Currently supported scenes are
// `apos` and `public` and custom scene names equal to extra bundle (only those who should be
// loaded separately in the browser).
//
// Additonal properties added after entrypoints are processed by the core and the external build module:
// - `manifest`: object, see the manifest section of `configureBuildModule()` docs for more information.
// - `bundles`: a `Set` containing the bundle names that this entrypoint is part of (both css and js).
getBuildEntrypoints(types, recompute = false) {
if (!self.hasBuildModule()) {
return self.builds;
Expand Down
2 changes: 1 addition & 1 deletion modules/@apostrophecms/asset/lib/build/internals.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ module.exports = (self) => {
enhancedConfig.ignoreSources.push(...bundleConfig.scss);
}
// 2.3. Add the extra bundle configuration so that
// it only processes the configured `sources` (`useMeta: false`).
// it only processes the configured `sources`
if (!bundleConfig.main) {
entrypoints.push({
name: bundleName,
Expand Down
4 changes: 3 additions & 1 deletion modules/@apostrophecms/schema/lib/addFieldTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -861,7 +861,9 @@ module.exports = (self) => {

self.addFieldType({
name: 'object',
async convert(req, field, data, destination, { fetchRelationships = true, ancestors = {}, doc = {} } = {}) {
async convert(req, field, data, destination, {
fetchRelationships = true, ancestors = {}, doc = {}
} = {}) {
data = data[field.name];
const schema = field.schema;
const errors = [];
Expand Down
18 changes: 18 additions & 0 deletions modules/@apostrophecms/template/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -1054,6 +1054,24 @@ module.exports = {
data.template = template;
// For simple cases (not piece pages and the like)
data.module = moduleName;

// Provide the `apos` scene bundles to the exsternal front-end
if (self.apos.asset.hasBuildModule()) {
const modulePreload = new Set();
data.bundleMarkup = {
js: self.apos.asset.getBundlePageMarkup({
scene: 'apos',
output: 'js',
modulePreload
}),
css: self.apos.asset.getBundlePageMarkup({
scene: 'apos',
output: 'css'
})
};
data.bundleMarkup.js.push(...Array.from(modulePreload));
}

return data;
},

Expand Down

0 comments on commit a966c53

Please sign in to comment.