adams85 / bundling

A library for optimizing and bundling web assets of ASP.NET Core applications.
MIT License
42 stars 7 forks source link

Render individual includes #12

Closed larshjohannesson closed 3 years ago

larshjohannesson commented 3 years ago

Is there a way to configure the bundling to render each file individually like classic ASP.NET bundling when using <compilation debug="true" /> in the web.config?

adams85 commented 3 years ago

No, this is not supported currently.

I assume you want this behavior in your development environment. As a workaround you may achieve something like this by using the environment tag helper:

<environment include="Development">
  <!-- include your individual files here -->    
</environment>
<environment exclude="Development">
  <!-- include the bundle consisting of the files above -->
</environment>

This should work but obviously it's far from optimal as you need to list your files at two locations.

I'll leave this issue open and give some more thought to it. I may come up with a better solution for this in a future version.

larshjohannesson commented 3 years ago

Thanks. Yes it's a feature we use in the development of our currently .NET framework based platform and it will be missed and prevent our adoption of .NET (core) version until it is somehow replaced.

I will look into utilizing our current logic for building bundles to render the individual files but if it is not too complicated I might make a pull request to this library instead.

I have started familiarizing myself with the code and so far found that a change like this possibly could be implemented somewhere in ViewHelper.GenerateUrlCoreAsync but in my preliminary assessment I've found that I'd need access to protected and private contents and classes in the class FileBundleSourceModel to pull it of and that seems to go against the general idea of the library.

adams85 commented 3 years ago

I've explored this a bit and could come up with a refined solution which you can find here. Using this approach you don't need to list your input files at two places any more:

<environment include="Development">
    @await Html.RenderIndividualBundleStylesAsync("~/bundles/site.css")
</environment>
<environment exclude="Development">
    @await Styles.RenderAsync("~/bundles/site.css")
</environment>

This is possible by purely extending the currently available version of the library. You just need to copy over the CustomBundleManagerFactory, CustomBundleManager and HtmlHelperExtensions classes and add an extra line to your Startup.ConfigureServices to make it work.

This approach has only one bigger shortcoming: when capturing the list of input files, FileBundleSourceModel also pre-loads the content of files. In this case this is undesired but cannot be avoided without changing the library code. But, since you would use this feature in dev environments anyway, maybe it's still acceptable.

Of course, in a future version this annoyance can be removed. Moreover, if you're satisfied with this approach, we can even bake in the whole thing in the library. At least, I don't think a significantly better solution is possible without introducing massive breaking changes.

larshjohannesson commented 3 years ago

Great, it is working. Thank you very much!

We can certainly live with scripts and stylesheets being loaded at time of application startup. Though since this is a dev/test environment feature it would be really cool with hot reload of changes. That would allow frontend devs to make changes without having to trigger an application restart.

sparkybg commented 3 years ago

Adam, is this available in the last NuGet package?

adams85 commented 3 years ago

Adam, is this available in the last NuGet package?

No, the latest version (3.4.1) doesn't include this. However, it may be included in a future version so I re-open the issue.

For now, if you want this feature in your project, you'll need a bit of manual setup as shown by the CustomBundleManager sample:

You just need to copy over the CustomBundleManagerFactory, CustomBundleManager and HtmlHelperExtensions classes and add an extra line to your Startup.ConfigureServices to make it work.

sparkybg commented 3 years ago

Thanks for the fast answer.

I'll make a fork and take a look at the source. Maybe I will be able to help a bit with this... I will let you knmow if...

adams85 commented 3 years ago

@larshjohannesson @sparkybg FYI, this feature got included in v3.5.0:

If you call UseDefaults in your configuration, you don't have anything more to do. In development environments, the source items will be included by default (if possible). The default behavior can be overridden using the EnableSourceIncludes method on the builder. For more details, see the Settings reference.

However, please note that the workaround presented above won't work as of v3.5.0. The implementation required some breaking changes to the internals. Among others, the IBundleManager interface had to be changed, so the CustomBundleManager sample may not compile at all against the new version.