Skip to content

Commit a966c53

Browse files
authored
PRO-6775: External frontend support, docs cleanup (#4799)
1 parent 6d3d7b5 commit a966c53

File tree

7 files changed

+47
-10
lines changed

7 files changed

+47
-10
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,14 @@
77
* Extra bundle detection when using external build module works properly now.
88
* Widget players are now properly invoked when they arrive later in the page load process.
99
* Fix permission grid tooltip display.
10+
* Fixes a bug that crashes external frontend applications.
11+
* 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`).
1012

1113
### Adds
1214

1315
* 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.
16+
* Adds asset module option `options.modulePreloadPolyfill` (default `true`) to allow disabling the polyfill preload for e.g. external front-ends.
17+
* Adds `bundleMarkup` to the data sent to the external front-end, containing all markup for injecting Apostrophe UI in the front-end.
1418

1519
## 4.9.0 (2024-10-31)
1620

index.js

+7
Original file line numberDiff line numberDiff line change
@@ -699,11 +699,18 @@ async function apostrophe(options, telemetry, rootSpan) {
699699
}
700700
}
701701
async function testDir(name) {
702+
if (name.startsWith('.')) {
703+
return;
704+
}
702705
// Projects that have different theme modules activated at different times
703706
// are a frequent source of false positives for this warning, so ignore
704707
// seemingly unused modules with "theme" in the name
705708
if (!validSteps.includes(name)) {
706709
try {
710+
// It's a project level modules definition, skip it.
711+
if (fs.existsSync(path.resolve(self.localModules, name, 'modules.js'))) {
712+
return;
713+
}
707714
const submodule = await self.root.import(path.resolve(self.localModules, name, 'index.js'));
708715
if (submodule && submodule.options && submodule.options.ignoreUnusedFolderWarning) {
709716
return;

modules/@apostrophecms/asset/index.js

+8-2
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,10 @@ module.exports = {
9898
// Force the HMR WS port when it operates on the same process as Apostrophe.
9999
// Most of the time you won't need to change this.
100100
hmrPort: null,
101+
// Let the external build module inject a pollyfill for the module preload,
102+
// adding the `modulepreload` support for the browsers that don't support it.
103+
// Can be disabled in e.g. external front-ends.
104+
modulePreloadPolyfill: true,
101105
// Completely disable the asset runtime auto-build system.
102106
// When an external build module is registered, only manifest data
103107
// will be loaded and no build will be executed.
@@ -477,6 +481,7 @@ module.exports = {
477481
// - `devServer`: if `false`, the dev server is disabled. Otherwise, it's a string
478482
// (enum) `public` or `apos`. Note that if `hmr` is disabled, the dev server will be always
479483
// `false`.
484+
// - `modulePreloadPolyfill`: if `true`, a module preload polyfill is injected.
480485
// - `types`: optional array, if present it represents the only entrypoint types (entrypoint.type)
481486
// that should be built.
482487
// - `sourcemaps`: if `true`, the source maps are generated in production.
@@ -494,15 +499,16 @@ module.exports = {
494499
isTask: !argv['check-apos-build'],
495500
hmr: self.hasHMR(),
496501
hmrPort: self.options.hmrPort,
502+
modulePreloadPolyfill: self.options.modulePreloadPolyfill,
497503
sourcemaps: self.options.productionSourceMaps
498504
};
499505
options.devServer = !options.isTask && self.hasDevServer()
500506
? self.options.hmr
501507
: false;
502508

503-
// Skip all public and keep only the apos scenes.
509+
// Skip prebundled UI and keep only the apos scenes.
504510
if (!self.options.publicBundle) {
505-
options.types = [ 'apos', 'bundled' ];
511+
options.types = [ 'apos', 'index' ];
506512
}
507513

508514
return options;

modules/@apostrophecms/asset/lib/build/external-module-api.js

+6-6
Original file line numberDiff line numberDiff line change
@@ -69,13 +69,8 @@ module.exports = (self) => {
6969
// Returns an array of objects with the following properties:
7070
// - `name`: the entrypoint name. It's usually the relative to `ui` folder
7171
// name(`src`, `apos`, `public`) or an extra bundle name.
72+
// - `label`: the human-readable label for the entrypoint, used to print CLI messages.
7273
// - `type`: (enum) the entrypoint type. It can be `index`, `apos`, `custom` (e.g. extra bundles) or
73-
// `bundled` (e.g. `ui/public`). Every type has associated manager that provides handling for the entrypoint.
74-
// - `useMeta`: if `true`, the entrypoint will be created based on the source metadata (see
75-
// `computeSourceMeta()` method).
76-
// - `bundle`: if `true`, the entrypoint should be bundled by the build module.
77-
// - `index`: if `true`, the entrypoint processes only `{name}/index.{js,scss}` module files.
78-
// - `apos`: if `true`, the entrypoint processes components, icons and apps.
7974
// - `ignoreSources`: an array of sources that shouldn't be processed when creating the entrypoint.
8075
// - `sources`: an object with `js` and `scss` arrays of extra sources to be included in the entrypoint.
8176
// These sources are not affected by the `ignoreSources` configuration.
@@ -84,10 +79,15 @@ module.exports = (self) => {
8479
// - `prologue`: a string with the prologue to be added to the entrypoint.
8580
// - `condition`: the JS `module` or `nomodule` condition. Undefined for no specific condition.
8681
// - `outputs`: an array of output extensions for the entrypoint (currently not fully utilized)
82+
// - `inputs`: an array of input extensions for the entrypoint (currently not fully utilized)
8783
// - `scenes`: an array of scenes to be in the final post-bundle step. The scenes are instructions
8884
// for the Apostrophe core to combine the builds and release them. Currently supported scenes are
8985
// `apos` and `public` and custom scene names equal to extra bundle (only those who should be
9086
// loaded separately in the browser).
87+
//
88+
// Additonal properties added after entrypoints are processed by the core and the external build module:
89+
// - `manifest`: object, see the manifest section of `configureBuildModule()` docs for more information.
90+
// - `bundles`: a `Set` containing the bundle names that this entrypoint is part of (both css and js).
9191
getBuildEntrypoints(types, recompute = false) {
9292
if (!self.hasBuildModule()) {
9393
return self.builds;

modules/@apostrophecms/asset/lib/build/internals.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ module.exports = (self) => {
8888
enhancedConfig.ignoreSources.push(...bundleConfig.scss);
8989
}
9090
// 2.3. Add the extra bundle configuration so that
91-
// it only processes the configured `sources` (`useMeta: false`).
91+
// it only processes the configured `sources`
9292
if (!bundleConfig.main) {
9393
entrypoints.push({
9494
name: bundleName,

modules/@apostrophecms/schema/lib/addFieldTypes.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -861,7 +861,9 @@ module.exports = (self) => {
861861

862862
self.addFieldType({
863863
name: 'object',
864-
async convert(req, field, data, destination, { fetchRelationships = true, ancestors = {}, doc = {} } = {}) {
864+
async convert(req, field, data, destination, {
865+
fetchRelationships = true, ancestors = {}, doc = {}
866+
} = {}) {
865867
data = data[field.name];
866868
const schema = field.schema;
867869
const errors = [];

modules/@apostrophecms/template/index.js

+18
Original file line numberDiff line numberDiff line change
@@ -1054,6 +1054,24 @@ module.exports = {
10541054
data.template = template;
10551055
// For simple cases (not piece pages and the like)
10561056
data.module = moduleName;
1057+
1058+
// Provide the `apos` scene bundles to the exsternal front-end
1059+
if (self.apos.asset.hasBuildModule()) {
1060+
const modulePreload = new Set();
1061+
data.bundleMarkup = {
1062+
js: self.apos.asset.getBundlePageMarkup({
1063+
scene: 'apos',
1064+
output: 'js',
1065+
modulePreload
1066+
}),
1067+
css: self.apos.asset.getBundlePageMarkup({
1068+
scene: 'apos',
1069+
output: 'css'
1070+
})
1071+
};
1072+
data.bundleMarkup.js.push(...Array.from(modulePreload));
1073+
}
1074+
10571075
return data;
10581076
},
10591077

0 commit comments

Comments
 (0)