Repository navigation
Description
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
amay settemplateUrl: 'package:b/some/template.html'pointing to packageb. As long as the package specifies a dependency on packagebinpackage.jsonorpubspec.yamlany 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.htmltopackages/a/lib/b.htmlvia 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 theyimportfiles.
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).
Activity
yjbanov commentedon Jul 10, 2015
/cc @matanlurey @andresaraujo @vicb @sigmundch @jelbourn
matanlurey commentedon Jul 10, 2015
👍 this works out of the box for me.
sigmundch commentedon Jul 10, 2015
👍
yjbanov commentedon Jul 11, 2015
/cc @TedSander
rolandjitsu commentedon Jul 12, 2015
In JS I do not see the need to enforce
package. Also, thetemplateUrlonly supports absolute paths anyway (not sure if relative paths have been successfully implemented or they are still in dev or have been dropped).Of topic, using a globally configured
baseUrlfor all components and then the component'stemplateUrlandstyleUrlsresolving at thatbaseUrl + templateUrl/baseUrl + styleUrlwould be nice.yjbanov commentedon Jul 13, 2015
@rolandjitsu
packagewould not be enforced, only recommended and would make things consistent across multiple interdependent packages distributed in source, and the idea is that we provide an implementation ofUrlResolverfor all popular environments out-of-the-box, such as pub&npm.templateUrlattribute by itself is just a string. You can put whatever you want in it, as long as you have a suitableUrlResolverthat knows what to do with it. We did attempt to implement relative paths, but were unsuccessful so far. We plan to come back to it at some point.As for global
baseUrl, you can already do that. Simply implement your ownUrlResolverthat does just that. However, unless your dependencies also follow the same convention it might be hard to reuse and share code.rolandjitsu commentedon Jul 14, 2015
@yjbanov ok, so I could use
UrlResolverto resolve components from the samebaseUrlpath. I'll try it out, though I am not sure what you mean when you say that it might be hard to reuse and share code.sigmundch commentedon Jul 14, 2015
@rolandjitsu - I think what @yjbanov was referring to is the problem of how different people can refer to each other's components in a consistent way. If people develop components separately, to refer from component A from component B, B's developer would need to know where to find A with respect to the
baseUrlof the app. At that point everyone needs to agree on a convention. For example, that all components will be underbaseUrl/components/.... This means that if another group of people follows a different convention, you may have trouble using their components.The
package:urls are not that different, but they allow us to separate the problem in two: the layout of a project is now separate from how the dependencies are written. In the example above, B can import A with apackage:URL (so A and B's developers don't need to know the layout of the app), but you can still use theUrlResolverto map those Urls to specific locations resolved from abaseUrl.Hope this clarifies the idea a bit.
6 remaining items
yjbanov commentedon Jul 20, 2015
Bumping to alpha-33. This won't make it into alpha-32.
yjbanov commentedon Jul 23, 2015
@robwormald thanks for the pointer. Yes, this proposal is very similar, although I'd like to try something that's package manager independent. We want to support pub and npm simultaneously already.
rolandjitsu commentedon Jul 31, 2015
@yjbanov does this change also apply to the apps that use TS or JS and not Dart?
yjbanov commentedon Jul 31, 2015
@rolandjitsu: #3215 only adds Dart support. JS support is tracked in #3257
angular-automatic-lock-bot commentedon Sep 6, 2019
This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.
Read more about our automatic conversation locking policy.
This action has been performed automatically by a bot.