Skip to content

Implement standard universal absolute schema for Angular 2 resource URI #2991

@yjbanov

Description

@yjbanov

While support for relative URIs proved to be difficult we should be able to implement a standard absolute URI schema. Here's how:

Background

JS

In JS world Angular 2 components will be distributed via two methods:

Bundles

A bundle contains all components in a single JS file. In this model HTML templates and CSS would be inlined into the JS code and therefore no URL resolution would be required.

NPM source

Any resource in an NPM source package can be identified using two pieces of information:

  • package name
  • path to a file within the package

Dart

In Dart it is most common to distribute in source. Bundles are not used. Just like with NPM, any resource can be identified via the package name and path within the package (relative to the /lib).

Considerations

Certain projects, such as angular2_material target both JS and Dart. It is therefore desirable to have a URI schema that is language-agnostic.

In Dart (and eventually in JS) applications may run in two modes: dynamic and static. In dynamic mode URLs are resolved in the browser. In static mode URLs are resolved on the server by a transformer without actually running the application. We want the URIs to work inside as well as outside the browser.

Dart has lib and web folders. Resources in web cannot be imported by 3rd-party packages. Therefore web resource do not have to be covered by this proposal. For web we want to use either relative URLs or page-relative URLs (starting with /), which is outside the scope of this proposal.

Proposal

Adopt the following absolute URI schema:

package:{PACKAGE_NAME}/{PATH_TO_RESOURCE}

For example, the material button component will use the following templateUrl:

@View({
  templateUrl: 'package:angular2_material/src/components/button/button.html'
})
export class MdButton {
  ...
}

Advantages

  • unambiguous
  • ability to reuse templates from a 3rd-party packages, e.g. a component from package a may set templateUrl: 'package:b/some/template.html' pointing to package b. As long as the package specifies a dependency on package b in package.json or pubspec.yaml any tool can unambiguously locate the template.
  • works across languages: both npm and pub could support it, and it's likely that any other package manager would support this as well.
  • works inside and outside the browser: in Dart case in-browser resolver would turn package:a/b.html to packages/a/lib/b.html via the existing pub convention; the transformer would do the same translation and locate the resource via the file system.
  • it will be instantly familiar to TypeScript and Dart developers as {PACKAGE_NAME}/{PATH_TO_RESOURCE} is exactly how they import files.

Disadvantages

  • the need for package: prefix adds boilerplate.

Alternatives

Why package: prefix?

It makes it very clear that the resolution is done relative to a package (npm or pub). If the prefix is dropped, it is not clear whether the first part of the path refers to a package or is simply the first part of a relative path. We do want to implement relative paths at some point in the future and we will use prefix-less schema for that.

How about {PACKAGE_NAME}:{PATH_TO_RESOURCE}? Isn't it shorter?

This could work, but it would be misusing the intent behind the schema part of the URI. There is usually a limited number of possible values for schema, e.g. "http", "ftp". Putting package name as schema means that schema can take unlimited number of values. We might want to support more than just "package" schemas in the future (perhaps support "http" URL as well).

See also

#2945
#2593
#2383

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions