T4MVC / R4MVC

R4MVC is a Roslyn code generator for ASP.NET Core MVC apps that creates strongly typed helpers that eliminate the use of literal strings in many places
Apache License 2.0
159 stars 48 forks source link

Generate Links.{xxx} constants #13

Closed kevinkuszyk closed 6 years ago

kevinkuszyk commented 9 years ago

We need to generate the Links.Content, Links.Scripts etc constants.

wwwlicious commented 9 years ago

with the new wwwroot in vnext projects and the new grunt/gulp pipeline (this does away with bundles right?), I've not yet got my head around how this will work as they files may be relocated, merged and transpiled during the build process.

Any constants or statics links would have to be aware of these potential changes to hold the correct relative paths.

T4MVC handled this by telling users to handroll a Bundles class which will probably do for v1 here too.

Going forward it may be possible to create a diagnosticanalyzer or similar to track the build pipeline looking for content and script mutations and generate corrected links on the fly.

kevinkuszyk commented 9 years ago

with the new wwwroot in vnext projects and the new grunt/gulp pipeline (this does away with bundles right?), I've not yet got my head around how this will work as they files may be relocated, merged and transpiled during the build process.

I'm not 100% sure about this, but my understanding is that grunt will compile .sass for example to .css as part of the build process. So there will always be a site.css on disk which is compiled from the site.sass.

I think we should still generate a Links.Content.Site_css and equivalent for .js files which can be used in views.

Any constants or statics links would have to be aware of these potential changes to hold the correct relative paths.

I think as long as we generate the correct relative url with the ~ for each stylesheet, JavaScript and image file on disk we will be ok.

T4MVC handled this by telling users to handroll a Bundles class which will probably do for v1 here too.

I suspect that the runtime bundling engine may be deprecated soon, now that bundling and minification is supported 1st class in the build process. For this reason I don't think we should invest too much effort in this area. Take this PR which I recently resurrected for T4MVC . I'm in no hurry to carry this forward in R4MVC as it looks like grunt pipeline will provide a better way to manage bundling and minification.

wwwlicious commented 9 years ago

I've been doing some experiments with generating the links constants.

I am going on the assumption that the static file locator will return an enumerable of static files, the important part of which is the uri which will be used to form the class nesting structure.

so /css/bootstrap/bootstrap.css will be accessible via Links.css.bootstrap.bootstrap_css

There are a few things that came up which I have made some progress on (but not enough for commits yet)

the first is input santisiation to ensure that no illegal characters are used when naming classes or fields. this will also apply to data not derived from code (i.e view names) and I think I have this worked out quite well in an extension method.

the second is that the staticfilegenerator should also use the Project.Webroot path to help create relative uri's.

the third is that there may be gaps in the uri paths between files e.g.

/css/bootstrap/bootstrap.css /css/site.css

t4mvc currently uses hashsets (for uniqueness) and some recursion to correctly generate the nested classes so it would create a 'bootstrap' class.

I think the creation of a Composite data structure is the cleanest way to handle the hierarchical nature of the uris. The enumerable of static files would be passed to a method or service to populate the composite structure and fill in the blanks. The generator can then just recursively loop through the child nodes creating the classes and fields in each level.

thoughts?

kevinkuszyk commented 9 years ago

All sounds good in principle.

A question though - can we just port over how this works in T4MVC and adapt it to use Project.Webroot to make the relative links?

@davidebbo - is there anything about the existing implementation in T4MVC that you think we should or should not port over to R4MVC?

wwwlicious commented 9 years ago

there are a couple of differences, one is the method of membername santisation t4mvc uses comes from the codeprovider in the codedom namespace, the second is the use of file and path statics.

I am avoiding using these at the moment so that custom implementations can generate whatever links they want, using whatever build process they want. They are just classes and string fields at the end of the day which together with the virtualpathprovider only need resolve uris at runtime, not during builds or deployment. It is more likely to cope with things like cdn's or resources shared between projects deployed separately etc, That's my take anyway.

kevinkuszyk commented 9 years ago

That makes sense. Also, I agree we should take a dependency on anything in the CodeDom namespace.

artiomchi commented 7 years ago

Tasks for this feature:

artiomchi commented 6 years ago

Instead of timestamping files, it might be better to adhere to existing asp.net mvc core approaches.

In this case, it seems like instead of adding a global setting to timestamp ALL scripts/files, this can easily be done with the existing mvc tag helper:

<script mvc-src="@Links.js.site_min_js" asp-append-version="true"></script>
artiomchi commented 6 years ago

The ProcessVirtualPathDelegate already exists. It doesn't remove the tilde from the url, since this is done by the tag helper, but it can still be used to add query string params