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

Scope: Allow developer to have more fine-grained control of app scope. #996

Open
hanguokai opened this issue Aug 17, 2021 · 20 comments
Open

Comments

@hanguokai
Copy link
Member

(I originally posted a related issue at manifest-incubations)

Although there is a scope concept in service worker and manifest file, for URLs in the scope, developers need a way to tell the browser which URLs can be regarded as the app and which URLs are not.

Why need to tell browser this information?
install
launch

As shown in the screenshots above, Chrome address bar has install/launch icon for installing and launching the app. But not all URLs in the origin/scope should be regarded as the app. For example, help pages of the app should be opened as web pages in the browser, rather than load them into the app.

A core concept: whether a URL in the scope should be treated as the app.

  • For a web page url, it should not be loaded in the (standalone installed) app, it should be opened in the browser.
  • For an app url, it can be loaded in the app.
@alancutter
Copy link
Contributor

Do you want a way to remove URL paths from the app scope?
Would it be reasonable to host those paths outside of the app scope instead?

@hanguokai
Copy link
Member Author

Do you want a way to remove URL paths from the app scope?
Would it be reasonable to host those paths outside of the app scope instead?

Simple answer: No

Chrome shows a launch icon in the address bar for all URLs in the scope after installation. I want to tell the browser which URLs can show, and which URLs can't show it.

The browser has a wrong assumption: all URLs in the scope can be opened in the installed app. The fact is:

  • Obviously, not all URLs are suitable for opening in the app.
  • Developers know all entry point of the app, but browser don't know.
  • For a better user experience, this launch icon should not be showed for some URLs.

For example:

  • index.html should be opened in browser, not in the app
  • app.html should be opened in the app, not in browser
  • a single resource file(js/css/img) should not be opened in the app

If the browser did not have this launch icon, I would not file this issue.

@alancutter
Copy link
Contributor

In that example it sounds like the scope should be app.html.

@hanguokai
Copy link
Member Author

My Test

I did some tests, focusing on how to control the install icon and launch icon in the address bar.

Assuming that service worker's scope is /, thus it can control all URLs. But /manifest.json scope is /app.

URL(File) Show Install Icon(before install) Show Launch Icon(after install)
index.html include manifest.json Yes No
index.html not include manifest.json No No
app.html include manifest.json Yes Yes
app.html not include manifest.json No Yes
app.js or app.css No Yes
app.js or app.css if manifest's scope is /app.html No No

My Goal

index.html must show the install icon, but don't show the launch icon because it is a landing page(not the app itself). And app.html can show both install icon and launch icon. The launch icon should only appear for app files, don't appear for other files(like index.html and app.js).

My Conclusions

Browser use manifest file to determines whether the install icon will appear, regardless of whether current URL is in the manifest's scope or not.

Browser use string prefix matching (like url.startsWith(manifest-scope)) determines whether the launch icon will appear. So if the app is a multiple files app(not single file app), all app files should have a same and unique prefix.

@alancutter Could you confirm that the spec can guarantee these?

@tomayac I rarely see articles or documents that explicitly say these. I think developers might be interested in these knowledge.

@alancutter
Copy link
Contributor

It should be noted that the install and launch icons mentioned here are behaviours of Chromium and aren't part of any spec.

My Goal

index.html must show the install icon, but don't show the launch icon because it is a landing page(not the app itself). And app.html can show both install icon and launch icon. The launch icon should only appear for app files, don't appear for other files(like index.html and app.js).

It sounds like you want your manifest.json to contain:

{
  "start_url": "app.html",
  "scope": "app.html"
}

@hanguokai
Copy link
Member Author

Thank you for your reply, but my purpose is not to solve a personal problem.

It should be noted that the install and launch icons mentioned here are behaviours of Chromium and aren't part of any spec.

Currently, on desktop OS, only Chromium-based browsers support to install a PWA. From developers' perspective, we care about the process of install and launch the app, and how to control it. When I transformed a web app to an installable PWA, I was thinking about:

  • Do I need to add manifest link(<link rel="manifest" href="/manifest.json">) to all html files? Or only files that need to show the install icon.
  • Do I need to add serviceWorker.register('/sw.js') code to all html files? Technically speaking, No. But adding it to all pages is usually not a problem.
  • How to determine manifest's scope? consistent with service worker's scope? Does it affect installation prompts?Considering browser's launch icon, ideally, only the entry points of the app should be in the scope. Because the scope is a single string, not an array of string and don't support wildcard character. That affects the structure of directories and file names.

As you said, the spec does not define these, so I think this part needs to be considered in the specification, especially from the developer's point of view.

@alancutter
Copy link
Contributor

alancutter commented Aug 20, 2021

That affects the structure of directories and file names.

You should put your app in a /app/ directory and make that the scope. /index.html can link the manifest and still be installable for the web app.
Example: https://mulberry-phase-leopon.glitch.me/

@hanguokai
Copy link
Member Author

hanguokai commented Aug 20, 2021

The core problem is that the behavior of the launch icon and its relationship with the manifest's scope is not clearly defined in the specification. And only chromium-based browsers have this behavior. The spec only defines launching the app with start_url or shortcut urls. It is undefined whether other URLs can be used by the browser to launch the app.

@hanguokai
Copy link
Member Author

I suggest that browser shows that launch icon in the address bar only when the current url is the start_url or shortcuts url. Because other URLs may not be appropriate to launch the app.

@hanguokai
Copy link
Member Author

The manifest's scope member is a string that represents the navigation scope of this web application's application context. - Manifest Spec

The manifest format assist with this problem by allowing you to specify a "URL scope" for your application. This scope sets a boundary for an app. It can either be a domain or a directory within that domain. - Manifest Explainer

From the definition above, the manifest's scope is not used to define which URLs can be used to launch the app, but to delimit the boundaries of the app. It does not say that all URLs in the scope can be used to launch the app. So the launch icon in current chromium browser is a misuse, sometimes it is right, sometimes it is wrong.

@alancutter
Copy link
Contributor

The core problem is that the behavior of the launch icon and its relationship with the manifest's scope is not clearly defined in the specification.

It sounds like you want to standardise manifest controls for Chromium's install/popout UI. The current title sounds like it's asking for the scope field.

@hanguokai
Copy link
Member Author

It sounds like you want to standardise manifest controls for Chromium's install/popout UI. The current title sounds like it's asking for the scope field.

They are essentially the same issue. It depends on how to solve the problem.

  • From the perspective of standard: there should be more explanations or notes for installation/launching related behaviors. At present, these behaviors are not clearly defined in the spec, and I think browser's implementation is immature.
  • From the perspective of browser implementation: I think it is wrong to assume that all URLs under the manifest's scope can be used to launch the app. The original intention of manifest's scope is used to determine whether the user has navigated outside the app.
  • From the perspective of developers: the manifest can provide a new item for developers to define which URLs can be used to launch the app, or an API to control these behaviors. I initially considered from this perspective.

@hanguokai
Copy link
Member Author

I just looked at URLPattern. It might solve this problem. If browsers really wants to supply an "open" icon for users to launch the app, the manifest could add a new "entry_points" item, that defines a URLPatternList by developers for all entry points of the app. When user navigate to a matched entry point, browser show the open icon.

@dmurph dmurph changed the title Control which parts of the URLs belong to the app and which parts are not Scope: Allow developer to have more fine-grained control of app scope. Oct 21, 2024
@dmurph
Copy link
Collaborator

dmurph commented Oct 21, 2024

See WICG/manifest-incubations#105 as well.

@dmurph
Copy link
Collaborator

dmurph commented Oct 21, 2024

For compatability with different OS's (where we need to tell the OS which urls are part of the installed app and which aren't), we likely cannot use URLPattern.

Based on my memory - Android supports basic 'patterns' and advanced 'patterns'. iOS allows some patterns, and also 'excludes'.

@LuHuangMSFT FYI - maybe a good manifest issue to work in for making better scope control

@benfrancis
Copy link
Member

benfrancis commented Oct 21, 2024

I see there's renewed interest in refining how navigation scope is defined.

It's a decade old now, but a long time ago I did a study of URL scope in web applications from what were then the top web sites/web apps on the Chrome Web Store, Firefox Marketplace and Alexa Top 20.

Whilst that study is now very out of date, the proposed solutions derived from that report may still be useful.

Some factors to think about:

  • Which URLs are included as part of the app
  • Which URLs are excluded as part of the app
  • Which URLs should result in navigations from outside the app being captured by the app
  • Which URLs should result in navigations from inside the app to stay in the app
  • What is used as the default scope when one is not provided

An example solution:

{
  "start_url”: “https://foo.com/foo",
  "scope": {
    "include": ["/foo", "/bar"],
    "exclude": ["/foo/baz", "/bar/qux"]
  },
  "stay_in_app": ["https://norf.com"]
}

@mkruisselbrink
Copy link

For compatability with different OS's (where we need to tell the OS which urls are part of the installed app and which aren't), we likely cannot use URLPattern.

I think this statement needs a bit more reasoning before we start inventing our own thing; one option would be to only allow some subset of the more generic URL pattern syntax (which is what the SW static routing API does as well, as that API does not want to allow arbitrary URLPatterns either). It is certainly possible that it doesn't make sense to describe the allowed scopes as a subset of URLPatterns, but I wouldn't dismiss URL pattern up front without first figuring out what functionality we actually want to support.

@dmurph
Copy link
Collaborator

dmurph commented Oct 22, 2024

@mkruisselbrink I agree - I haven't researched URLPattern closely enough to know if it is truly incompatible. Research is needed here, with an explainer, so we can see all options & what is possible per-OS, etc.

@mgiuca
Copy link
Collaborator

mgiuca commented Oct 23, 2024

When URLPattern was defined, we worked with @wanderview to ensure it would be usable in Web App Manifest eventually - that was always the plan. (That's why the URLPattern spec has a section about using it in JSON.)

Acknowledged the difficulty of communicating to the OS the exact scope, but I don't believe this should restrict the way app scope is defined, since the OS interaction (OS-level link capturing) is just a small part of its utility. I think of the scope as being much more about when you're inside the browser/webapp ecosystem, deciding whether a given link should open in the browser or webapp. For most purposes, scope can be fully implemented as a URLPattern.

When it comes to registering the URLPattern with the OS, you could define a subset of the syntax that's designed to work with OS link capturing, but let the full syntax be used for internal navigation. (Though there can't possibly be a guarantee about what URLs can be supported by all possible OSes; that is outside the jurisdiction of a web spec.)

Also note the (intentional) precedence here: in the Manifest Incubations spec we defined the tab mode home scope using URLPattern, with the intention that the main manifest scope would follow. A lot of the hard spec work (and implementation, in chromium) has already been done there and can be generalized. Albeit, tab mode home scope does not need to be registered with the OS.

@dmurph
Copy link
Collaborator

dmurph commented Oct 23, 2024

@mgiuca I expect that an explainer proposing the solutions/alternatives here will explore what it would look like to have a URLPattern, and how that would work with different OS's (and expand on what, exactly, each OS supports). Then we'll be able to make a more informed decision.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants