Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add metadata manager provider APIs v2 #926

Merged
merged 13 commits into from
Oct 14, 2024

Conversation

davidlj95
Copy link
Owner

@davidlj95 davidlj95 commented Oct 11, 2024

Issue or need

Current APIs to help providing metadata managers are a bit convulated and not very developer friendly. Issues:

  • makeMetadataManagerProviderFromSetterFactory is a quite long name 😆
  • Option short names (d for deps, jP for JSON Path...) do not provide a good development experience either
  • JSON Path is needed in most cases in order to resolve the metadata value. However, it has to be provided as a mandatory option. This forces users to always have to provide the options object. Instead of being a positional argument for instance.
    • It could be optional though. For instance if the value isn't provided by a JSON object, but by another means 🤔
  • Naming also doesn't use provideX convention, which is the usual in Angular to create a provider

All of the above lead to an improvable development experience when providing a custom metadata manager:

const CUSTOM_TITLE_METADATA_MANAGER_PROVIDER = makeMetadataManagerProviderFromSetterFactory(
  (metaElementsService: NgxMetaElementsService) => 
    metaElementsService.set(
      withNameAttribute('custom:title'), 
      withContentAttribute(value),
    ), 
  {
    d: [NgxMetaElementsService],
    jP: ['custom', 'title'],
    g: 'title' satisfies keyof GlobalMetadata,
  }
)

Proposed changes

Add a new set of APIs to create metadata managers. This way old ones keep working, but a new & friendlier way is provided.

Here's how providing a custom metadata manager looks like now:

export const provideCustomMetadataManager = () =>
  provideNgxMetaManager<string | undefined>(
    'custom.title',
    (metaElementsService: NgxMetaElementsService) => (value) => {
      metaElementsService.set(
        withNameAttribute('custom:title'),
        withContentAttribute(value),
      )
    },
    withOptions(withManagerDeps(NgxMetaElementsService)),
  )

Name uses provide prefix. Library name is added to avoid clashes.

Tried using ES2015 imports/exports to create a namespace like: Manager.provide. But this is not good for tree shaking. All members of the namespace are included in the bundle size even if unused. As long as one is used, all of them are included. Also it's the convention of the library for now. So if changing those, all APIs would have to be renamed in the sake of consistency. See evanw/esbuild#1420 . What could be done is export all APIs under the same namespace NgxMeta. Though that's a whole other story.

JSON Path is moved to first argument as right now using a JSON object to specify metadata values is the most common way. The param could be made optional or pass an empty string if another way is used. Anyway, not a use case right now. This way is very clear that the metadata value will come from the custom.title JSON Path of the JSON object containing the metadata values.

Final and greatest improvement comes with the option to specify manager options. Options can be provided using functions instead of remembering the option name in the object. For instance: withManagerDeps, withManagerGlobal... Notice the NgxMeta name has been avoided in there to avoid long names. Manager prefix is added to avoid name clashes, discoverability & they also get nicely organized together in the API report.

withOptions is used as a small util that grabs all objects passed as arguments and joins them using the spread operator. It's named without any prefixes as this can be useful for many purposes. Not only the manager options. Avoids library name because of same reason just stated plus previous reasons in the previous case of withX APIs.

Internal part of new APIs was moved to #927 so that coverage doesn't go down. As given those APIs are unused here and they're untested, they're not covered by tests.

The implementation has gone through several rounds of optimizations to improve uncompressed bundle size:

Following bundle size optimizations were thought of, but weren't performed:

  • JSON Path to be an array instead of a string. Avoids the utility to convert to it (plus then having to split it back). But nothing much else. Would save 10 bytes. But having first argument as a string is more developer friendly. Worth those 10 bytes.

Quick reminders

  • 🤝 I will follow Code of Conduct
  • No existing pull request already does almost same changes
  • 👁️ Contributing docs are something I've taken a look at
  • 📝 Commit messages convention has been followed
  • 💬 TSDoc comments have been added or updated indicating API visibility if API surface has changed.
  • 🧪 Tests have been added if needed. For instance, if adding new features or fixing a bug. Or removed if removing features.
  • ⚙️ API Report has been updated if API surface is altered.

Copy link
Owner Author

davidlj95 commented Oct 11, 2024

This stack of pull requests is managed by Graphite. Learn more about stacking.

Join @davidlj95 and the rest of your teammates on Graphite Graphite

Copy link

codecov bot commented Oct 11, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 98.16%. Comparing base (479fe2b) to head (bdf0527).
Report is 4 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #926      +/-   ##
==========================================
+ Coverage   98.11%   98.16%   +0.04%     
==========================================
  Files          83       85       +2     
  Lines         372      382      +10     
  Branches       70       70              
==========================================
+ Hits          365      375      +10     
  Misses          3        3              
  Partials        4        4              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link

github-actions bot commented Oct 11, 2024

📦 Bundle size (Angular v17)

Git ref: bdf0527478f4ada7a53cd59c358646a53e23a431

Module file Size Base size Difference
ngx-meta-core.mjs 2982 bytes (3.0KiB) 2978 bytes (3.0KiB) .13%: 4 bytes (4B)
ngx-meta-json-ld.mjs 220 bytes (220B) 220 bytes (220B) No change
ngx-meta-open-graph.mjs 985 bytes (985B) 985 bytes (985B) No change
ngx-meta-routing.mjs 394 bytes (394B) 394 bytes (394B) No change
ngx-meta-standard.mjs 907 bytes (907B) 907 bytes (907B) No change
ngx-meta-twitter-card.mjs 534 bytes (534B) 534 bytes (534B) No change
Total 6022 bytes (5.9KiB) 6018 bytes (5.9KiB) .06%: 4 bytes (4B)

Copy link

github-actions bot commented Oct 11, 2024

📦 Bundle size (Angular v18)

Git ref: bdf0527478f4ada7a53cd59c358646a53e23a431

Module file Size Base size Difference
ngx-meta-core.mjs 2982 bytes (3.0KiB) 2978 bytes (3.0KiB) .13%: 4 bytes (4B)
ngx-meta-json-ld.mjs 220 bytes (220B) 220 bytes (220B) No change
ngx-meta-open-graph.mjs 985 bytes (985B) 985 bytes (985B) No change
ngx-meta-routing.mjs 394 bytes (394B) 394 bytes (394B) No change
ngx-meta-standard.mjs 907 bytes (907B) 907 bytes (907B) No change
ngx-meta-twitter-card.mjs 534 bytes (534B) 534 bytes (534B) No change
Total 6022 bytes (5.9KiB) 6018 bytes (5.9KiB) .06%: 4 bytes (4B)

Copy link

github-actions bot commented Oct 11, 2024

📦 Bundle size (Angular v16)

Git ref: bdf0527478f4ada7a53cd59c358646a53e23a431

Module file Size Base size Difference
ngx-meta-core.mjs 3386 bytes (3.4KiB) 3386 bytes (3.4KiB) No change
ngx-meta-json-ld.mjs 370 bytes (370B) 370 bytes (370B) No change
ngx-meta-open-graph.mjs 1284 bytes (1.3KiB) 1284 bytes (1.3KiB) No change
ngx-meta-routing.mjs 572 bytes (572B) 572 bytes (572B) No change
ngx-meta-standard.mjs 1054 bytes (1.1KiB) 1054 bytes (1.1KiB) No change
ngx-meta-twitter-card.mjs 679 bytes (679B) 679 bytes (679B) No change
Total 7345 bytes (7.2KiB) 7345 bytes (7.2KiB) No change

Copy link

github-actions bot commented Oct 11, 2024

📦 Bundle size (Angular v15)

Git ref: bdf0527478f4ada7a53cd59c358646a53e23a431

Module file Size Base size Difference
ngx-meta-core.mjs 3346 bytes (3.3KiB) 3346 bytes (3.3KiB) No change
ngx-meta-json-ld.mjs 355 bytes (355B) 355 bytes (355B) No change
ngx-meta-open-graph.mjs 1254 bytes (1.3KiB) 1254 bytes (1.3KiB) No change
ngx-meta-routing.mjs 557 bytes (557B) 557 bytes (557B) No change
ngx-meta-standard.mjs 1039 bytes (1.1KiB) 1039 bytes (1.1KiB) No change
ngx-meta-twitter-card.mjs 664 bytes (664B) 664 bytes (664B) No change
Total 7215 bytes (7.1KiB) 7215 bytes (7.1KiB) No change

@davidlj95 davidlj95 force-pushed the stacked/feat-add-metadata-manager-provider-apis-v2 branch from 1c48014 to e02ec1d Compare October 13, 2024 15:50
@davidlj95 davidlj95 force-pushed the stacked/feat-add-metadata-manager-provider-apis-v2 branch from 3b959cc to d27fae4 Compare October 14, 2024 10:46
@davidlj95 davidlj95 force-pushed the stacked/feat-add-metadata-manager-provider-apis-v2 branch from 8cc3a37 to e2de376 Compare October 14, 2024 16:48
@davidlj95 davidlj95 marked this pull request as ready for review October 14, 2024 16:48
@davidlj95 davidlj95 force-pushed the stacked/feat-add-metadata-manager-provider-apis-v2 branch from e2de376 to bdf0527 Compare October 14, 2024 16:54
@davidlj95 davidlj95 enabled auto-merge (squash) October 14, 2024 16:54
@davidlj95 davidlj95 merged commit 8e3e58c into main Oct 14, 2024
34 checks passed
@davidlj95 davidlj95 deleted the stacked/feat-add-metadata-manager-provider-apis-v2 branch October 14, 2024 16:59
Copy link

🎉 This PR is included in version 1.0.0-beta.20 🎉

The release is available on:

Your semantic-release bot 📦🚀

davidlj95 added a commit that referenced this pull request Oct 14, 2024
* refactor: use manager provider APIs v2 for Open Graph

* refactor: use manager provider APIs v2 for JSON-LD

* refactor: use manager provider APIs v2 for standard

* refactor: use manager provider APIs v2 for Twitter Card

* fix: use with options API around

* refactor: use same name global API around

* refactor: use manager provider APIs v2 for example apps

* perf: remove unneeded array initialization

* refactor: use new module manager API scope arg around

* chore: bring internal module manager APIs from #926

* refactor: rename same name global API to add prefix

* chore: remove istanbul ignore now that API is used

* feat: upgrade manager provider APIs v2 to public

* docs: update custom metadata docs

* chore: remove unneeded scenario for coverage

* perf: inline function to shave bundle size

* chore: update API report
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant