5

I've added the following code to my .csproj in order to minify the JS files that have changed when building the project:

<Target Name="BeforeBuild">
  <MSBuild Targets="CheckAndMinifyJS" Projects="$(MSBuildProjectFile)" />
</Target>
<ItemGroup>
  <JS Include="$(ProjectDir)\**\*.js" />
</ItemGroup>
<Target Name="CheckAndMinifyJS" Inputs="@(JS)" Outputs="@(JS->'$(ProjectDir)%(RecursiveDir)%(Filename).min.js')">
  <AjaxMin JsSourceFiles="@(JS)" JsSourceExtensionPattern="\.js$" JsTargetExtension=".min.js" />
</Target>
<UsingTask TaskName="AjaxMin" AssemblyFile="..\..\ThirdParty\AjaxMinTask.dll" />

This works great, but it has a side effect: when you look at the project in Visual Studio (2015), all the JS files appear duplicated (same path, but different build action):

Duplicate items

I would like to avoid having the item with "JS" build action appearing in the project. How can I do that?

Please note that the several developers are working with the project, so any proposed solution should be contained within the .csproj or the solution (eg: it is not acceptable to ask all developers to modify their registry to change the default build action for JS files).

Gyum Fox
  • 3,287
  • 2
  • 41
  • 71
  • Have you tried giving the Item `JS` a different name? Maybe '`JS` is 'reserved' by VS.. – stijn Aug 12 '15 at 18:24
  • @stijn yes I did try that... Whatever name I put, I get my files to appear in the project with a Build Action of the same name – Gyum Fox Aug 13 '15 at 07:09
  • I think my problem is that all my JavaScript files have already been added to the csproj as "Content". Adding a new "JS" item that targets them must be causing them to appear again as "JS". I probably need to be able to change my Inputs and Outputs in the "CheckAndMinifyJS" target so that I don't have to use that "JS" item. – Gyum Fox Aug 13 '15 at 08:40
  • ... or I need to make sure Visual Studio doesn't add my JavaScript files with "Build action = Content" – Gyum Fox Aug 13 '15 at 08:45
  • Could you please describe what is the desired set of build actions you want to see for your *.js items within the VS? JS, Content, or both .. ? I hope I understand correctly that you want to see each *.js file only once within the solution explorer, I just don't know what set of build actions you desire. – Michal Hosala Sep 04 '15 at 10:14
  • Also, if I correctly understand what you are trying to achieve then you may want to reconsider your approach and rather base it on [the following article](http://encosia.com/automatically-minify-and-combine-javascript-in-visual-studio/). – Michal Hosala Sep 04 '15 at 11:05
  • Can you please run your build with /verbosity:diag and post output log somewhere ? – Alexey Shcherbak Sep 05 '15 at 06:39
  • @MichalHosala, thanks for the link, but I'm trying to move away from the post build event (which I have already put in place). The reason is that the project (a web application) contains hundreds of JS files, and I don't want the minification to occur each time you build unless the content of the file has changed (that why I'm using Inputs and Outputs in my target). Regarding your other question, I don't mind which Build Action appears when you open the project in Visual, I just don't want to see 2 times the same JS file. – Gyum Fox Sep 07 '15 at 07:05
  • @AlexeyShcherbak: are you looking for something in particular? Not sure what you want to see. The behaviour I'm describing is consistent with what's in the csproj. Just trying to amend that csproj to file another solution to work around these duplicates. – Gyum Fox Sep 07 '15 at 07:07
  • I want to see who is adding that files with action JS. As I haven't used AjaxMin task before - I can't guess what is there but I suspect that it's AjaxMin task performing that inclusion. Want to see conditions evaluation checks that happens inside – Alexey Shcherbak Sep 07 '15 at 07:25
  • That's the code I posted, and in particular those 3 lines: – Gyum Fox Sep 07 '15 at 07:47
  • @GyumFox - I know this question is old, but if you are able to, kindly check whether my answer gets you the VS behavior you were seeking. – weir Jan 18 '17 at 16:52
  • @weir Thanks so much for answering. I will definitely have a look, but I can't tell you when (I switched to another project). I'll put a comment on the answer then. – Gyum Fox Jan 19 '17 at 08:47

1 Answers1

1

To hide your ItemGroup from Visual Studio, move it into an intermediate Target. In addition to that change, the following code filters the existing Content items rather than recursing the file system again. This ensures you don't pick up extraneous .js files (for example intermediate output files in obj\, or .min.js files generated by your script but not explicitly added to the project).

  <Target Name="BeforeBuild">
    <MSBuild Targets="CheckAndMinifyJS" Projects="$(MSBuildProjectFile)" />
  </Target>
  <Target Name="GetJSItems" BeforeTargets="CheckAndMinifyJS">
    <ItemGroup>
      <JS Include="@(Content)" Condition=" '%(Extension)' == '.js' " />
    </ItemGroup>
  </Target>
  <Target Name="CheckAndMinifyJS" Inputs="@(JS)" Outputs="@(JS->'$(ProjectDir)%(RecursiveDir)%(Filename).min.js')">
    <AjaxMin JsSourceFiles="@(JS)" JsSourceExtensionPattern="\.js$" JsTargetExtension=".min.js" />
  </Target>
  <UsingTask TaskName="AjaxMin" AssemblyFile="..\..\ThirdParty\AjaxMinTask.dll" />
weir
  • 4,521
  • 2
  • 29
  • 42