Skip to content
This repository has been archived by the owner on Feb 25, 2021. It is now read-only.

External content packages #247

Merged
merged 6 commits into from
Mar 13, 2018

Conversation

SteveSandersonMS
Copy link
Member

This is so we can have NuGet packages that, when installed, cause you to get extra static content in your dist dir, and automatically generate suitable <script> and <link> tags referencing any JS/CSS files that the package author nominates.

The net result is that people will be able to publish packages that:

Still to be done: E2E test

@SteveSandersonMS
Copy link
Member Author

@javiercn / @rynowak Could you have a look particularly at the MSBuild stuff I added in b170171 and e336713? Does this fit in with the incremental build features you added @javiercn?

The third commit you can ignore if you like as it's just a sample that I'll use in the E2E test when I add one.

<ItemGroup Label="Static content supplied by NuGet packages">
<_BlazorPackageContentOutput Include="@(BlazorPackageContentFile)" Condition="%(SourcePackage) != ''">
<TargetOutputPath>$(ProjectDir)$(OutputPath)$(BaseBlazorPackageContentOutputPath)%(SourcePackage)\%(RecursiveDir)\%(Filename)%(Extension)</TargetOutputPath>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure this does anything on custom items. I think this is a feature of Content. This is good for now, but in the future I think we should move users to use Content for this (as it has all the features). I would need to know more about what we are trying to do here to better judge it, but I'm going to make 2 assumptions.

  1. Content from 3rd party packages is immutable.
  2. Just needs to be copied to the output without any prior processing.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BlazorPackageContentFile items are those specifically nominated by the package for inclusion in the dist dir.

Content from 3rd party packages is immutable.

Yes

Just needs to be copied to the output without any prior processing.

Pretty much, but:

  1. We want to output it to dist, not just $(OutDir) (and don't want package authors to hardcode the notion of dist in their packages)
  2. We want to strongly guide package authors to give us their SourcePackage metadata so that we can drop content into dist/_content/(SourcePackage)/... to ensure there are no clashes across packages. The implementation here means you have to give a nonempty SourcePackage otherwise we won't include your item in dist.

</PropertyGroup>
<ItemGroup>
<!-- All files under "content" will be included with the Blazor app build output -->
<BlazorPackageContentFile Include="$(_ContentDir)**" SourcePackage="$(_PackageId)" />
Copy link
Member

@javiercn javiercn Mar 12, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For this I would use content and an Additional metadata attribute inside the content. That way you can piggyback on all the features of content.
The only reason I didn't do this for asmjs, wasm and other static content in the blazor core outputs is because it doesn't surface to the user.

That said, this is just a suggestion, you can give content a try or just leave it like this for now.

Another completely different option can be to just define stuff in the package as content and make it go into
(wwwroot|dist)/_blazorcontent/(js|css)/** in the consuming project and have blazor include anything under _blazorcontent/(js|css)/**.* in the index.html

That way as a package author you just have to care about putting stuff in the right folder and everything else happens automatically.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another completely different option can be to just define stuff in the package as content and make it go into

@javiercn I tried to do this at some length, by putting <PackageCopyToOutput>true</PackageCopyToOutput> on the <Content> items in the source package and using PackagePath to make them land in the correct place in the output directory. It works correctly at build time.

This would a be better way to do it, except for one severe problem, which is that all <Content> items appear in the consuming project's Solution Explorer tree as files (with little "link" icons). This makes the consuming project look messy, or at least adds totally unfamiliar items to the tree.

If you know of a way of using <Content> and not having the items show up in the consuming project, please let me know! I'm guessing it's not currently possible due to NuGet/Home#4856 still being unresolved.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do believe that you can use the false node in MSBuild to make them not show up in VS https://msdn.microsoft.com/en-us/library/bb629388.aspx

So my idea is that if you put the content on the right folder path then you can have msbuild in our targets that based on the path updates the metadata for the itemgroup. (And this can be just at the top level so it applies globally)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you talking about Visible="false"? I did try that, and although it hid the files, it did not hide the directories. It looked very weird. If you're able to make this work and hide both please let me know!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@SteveSandersonMS Yes. @rynowak This is also what you mentioned to me before, isn't it? To just use Content and use <Visible>false</Visible> do you know about the folders showing up?

@javiercn
Copy link
Member

@SteveSandersonMS MSBuild wise looks good. I have a few suggestions that might simplify things, but I'll let you decide what you think its best for now. We can revisit in the future if needed.

@SteveSandersonMS
Copy link
Member Author

For this I would use content and an Additional metadata attribute inside the content. That way you can piggyback on all the features of content.

@javiercn I'd like to do this if it's really possible, but I haven't found a way to do so. Can NuGet packages really preserve content file metadata when packed? As far as I can tell, the generated nuspec file doesn't even have a place to store that information. If you think this is possible, could you point me to some example?

@SteveSandersonMS SteveSandersonMS merged commit b404d2e into feature/0.1.0 Mar 13, 2018
@SteveSandersonMS SteveSandersonMS deleted the stevesa/external-content-packages branch March 13, 2018 11:28
SteveSandersonMS added a commit that referenced this pull request Mar 14, 2018
* On build, drop <BlazorPackageContentFiles> items into dist\_content\(PackageName)\

* Add <script> and <link> tags to generated index.html

* Add testapp coverage of external content package. Still need to add E2E tests that uses it.

* Add missing unit test update

* Add example of packaging an entire Blazor component including CSS and images

* Add E2E test for component from NuGet package
@LunicLynx
Copy link
Contributor

LunicLynx commented Mar 16, 2018

There is a Problem with this approach:

if every package has a props file that includes this:

  <PropertyGroup>
    <!-- Update this to match your package ID exactly -->
    <_PackageId>TestContentPackage</_PackageId>
    <_ContentDir>$(MSBuildThisFileDirectory)..\content\</_ContentDir>
  </PropertyGroup>

The Properties _PackageId and _ContentDir are reassigned, resulting in empty content.

Msbuild Output:

Property reassignment: $(_PackageId)="Microsoft.AspNetCore.Blazor.Browser.Storage" (previous value: "TestContentPackage") at C:\Users\...\Blazor\src\Microsoft.AspNetCore.Blazor.Browse
r.Storage\build\Microsoft.AspNetCore.Blazor.Browser.Storage.props (4,5)
Property reassignment: $(_ContentDir)="C:\Users\...\Blazor\src\Microsoft.AspNetCore.Blazor.Browser.Storage\build\..\dist\" (previous value: "C:\Users\...\B
lazor\test\testapps\TestContentPackage\build\..\content\") at C:\Users\...\Blazor\src\Microsoft.AspNetCore.Blazor.Browser.Storage\build\Microsoft.AspNetCore.Blazor.Browser.Storage.pro
ps (5,5)

This is at least a problem with the BasicTestApp when referencing from source. Maybe this is working differently via NuGet 🤷‍♂️ ?

@SteveSandersonMS

A temporary fix for me was to rename these properties.

@SteveSandersonMS
Copy link
Member Author

This is at least a problem with the BasicTestApp when referencing from source. Maybe this is working differently via NuGet 🤷‍♂️ ?

Yes, that's exactly it. It's only a problem because of the "reference from source" trick. For people referencing real extension packages, there would be no issue because the build context for the package is independent of the application that references it.

A temporary fix for me was to rename these properties.

If you want to have a project that references multiple other projects via the "reference from source" trick then yes, you'd need to make all the names different. In other cases you wouldn't have any issue with it.

@LunicLynx
Copy link
Contributor

LunicLynx commented Mar 17, 2018

@SteveSandersonMS i did some further testing and i don't think this is working. When going the nuget path both build imports are in the same build context.

I got this index.html completely missing the second nupkg:

<!DOCTYPE html>
<html>
...
<body>
    <app>Loading...</app>

    <script src="css/bootstrap/bootstrap-native.min.js"></script>
    <script src="_framework/blazor.js" main="WebApplication4.dll" entrypoint="WebApplication4.Program::Main" references="..."></script>
<script src="_content/Microsoft.AspNetCore.Blazor.Browser.Storage/storage.js" defer></script>
<script src="_content/Microsoft.AspNetCore.Blazor.Browser.Storage/storage.js" defer></script></body>
</html>

To try this i created a copy of my nupkg with another id. I attached both nupkg. I can't see anything wrong with them.

build.zip

@SteveSandersonMS
Copy link
Member Author

@LunicLynx Good point - thanks for this! We probably need to add TreatAsLocalProperty="_PackageId;_ContentDir" to the <Project> element at the top of the build\*.props file in the content packages. Or if that doesn't work we'll just inline the values.

SteveSandersonMS added a commit to SteveSandersonMS/BlazorMigration that referenced this pull request Nov 27, 2018
…net#247)

* On build, drop <BlazorPackageContentFiles> items into dist\_content\(PackageName)\

* Add <script> and <link> tags to generated index.html

* Add testapp coverage of external content package. Still need to add E2E tests that uses it.

* Add missing unit test update

* Add example of packaging an entire Blazor component including CSS and images

* Add E2E test for component from NuGet package
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants