Publishing an Angular project’s node_modules folder in an ASP.NET project from Visual Studio

This is a quick guide to a huge source of frustration over the last few months, with a way to solve it. This assumes that your Angular project is based on the angular quickstart project, that your Angular project is hosted inside an ASP.NET web app, and that you’re working in Visual Studio.

To skip the exposition, head to the “How it works” section.

Background

An angular project depends on certain JavaScript libraries in order to run. These libraries are loaded from 2 locations (that I’ve discovered) in the angular quickstart project:

  1. src/index.html, in the <head> section. See: https://github.com/angular/quickstart/blob/master/src/index.html
  2. src/systemjs.config.js, in the map section. See: https://github.com/angular/quickstart/blob/master/src/systemjs.config.js

In the angular quickstart project, the libraries in these sections are by default located in the node_modules/ folder. However, the node_modules/ folder is gigantic (like 120MB and 17,000 files in my case), and all of those files don’t need to be deployed to the production server to run the angular app.

Publishing setup

To publish the site to my IIS server, I’m using Visual Studio’s built-in publishing support. Thus, to push the site to a server, you right-click the ASP.NET website project, click “Publish”, and go from there.

Now, clicking “Publish” will only publish the files that exist in the project. Since node_modules/ is humongous, we don’t track it in our VS project. Therefore, the node_modules/ folder isn’t published to the web server. At the beginning of our project, we manually copied the node_modules/ folder over to the web server to fix this. But no longer!

How it works

  1. Create a dist/ folder somewhere in the website project.
  2. Set up an MSBuild task to, after every build, copy the JavaScript dependencies over into the dist/ folder.
  3. After every dependency has been copied into the dist/ folder, update all references to JS dependencies in the project to point to the dist/ folder, rather than node_modules
  4. In Visual Studio, add all of the dependencies in the dist/ folder to the solution, under a corresponding dist/ folder.

Why do this?

  • You don’t have to track the entire node_modules/ folder in the solution.
  • You don’t have to publish the entire node_modules/ folder to the web server.
  • Since updating the dist/ folder happens after every build, anytime you update your npm modules, the updated libraries will be copied to the dist/ folder.

Walkthrough

Create dist/ folder

Create a folder structure which is something like this:

dist folder setup

dist contents.PNG

Setup MSBuild tasks

Here’s the set of MSBuild tasks I’m using [this should look much nicer pasted into a text editor…darn blog formatting]:

<PropertyGroup>
    <NodeModulesRoot>./node_modules</NodeModulesRoot>
    <DistRoot>./dist</DistRoot>
</PropertyGroup>
<ItemGroup>
    <RxJsFilesInclude=”.\node_modules\rxjs\**\*.js”/>
</ItemGroup>
<TargetName=”AfterBuild”>
    <!– Move NPM modules into our dist/ folder. –>
    <CopySourceFiles=”$(NodeModulesRoot)/core-js/client/shim.min.js”DestinationFolder=”$(DistRoot)/core-js/client/”/>
    <CopySourceFiles=”$(NodeModulesRoot)/zone.js/dist/zone.js”DestinationFolder=”$(DistRoot)/zone.js/dist/”/>
    <CopySourceFiles=”$(NodeModulesRoot)/systemjs/dist/system.src.js”DestinationFolder=”$(DistRoot)/systemjs/dist/”/>
    <CopySourceFiles=”$(NodeModulesRoot)/@angular/core/bundles/core.umd.js”DestinationFolder=”$(DistRoot)/@angular/core/bundles/”/>
    <CopySourceFiles=”$(NodeModulesRoot)/@angular/common/bundles/common.umd.js”DestinationFolder=”$(DistRoot)/@angular/common/bundles/”/>
    <CopySourceFiles=”$(NodeModulesRoot)/@angular/compiler/bundles/compiler.umd.js”DestinationFolder=”$(DistRoot)/@angular/compiler/bundles/”/>
    <CopySourceFiles=”$(NodeModulesRoot)/@angular/platform-browser/bundles/platform-browser.umd.js”DestinationFolder=”$(DistRoot)/@angular/platform-browser/bundles/”/>
    <CopySourceFiles=”$(NodeModulesRoot)/@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js”DestinationFolder=”$(DistRoot)/@angular/platform-browser-dynamic/bundles/”/>
    <CopySourceFiles=”$(NodeModulesRoot)/@angular/http/bundles/http.umd.js”DestinationFolder=”$(DistRoot)/@angular/http/bundles/”/>
    <CopySourceFiles=”$(NodeModulesRoot)/@angular/router/bundles/router.umd.js”DestinationFolder=”$(DistRoot)/@angular/router/bundles/”/>
    <CopySourceFiles=”$(NodeModulesRoot)/@angular/forms/bundles/forms.umd.js”DestinationFolder=”$(DistRoot)/@angular/forms/bundles/”/>
    <CopySourceFiles=”@(RxJsFiles)”DestinationFolder=”.\dist\rxjs\%(RecursiveDir)”/>
</Target>

 

This should, after every build, copy all JS dependencies to the dist/ folder.

Update JS dependency references

systemjs.config.js

Something like this:

systemjs.PNG

default.aspx (or index.html, etc)

Something like this:

index.PNG

Add dist/ folder to solution

Solution explorer.PNG

And that’s it! Now if you Publish the site, the dist/ folder should be copied to the IIS server, and the site should use the files in that folder.

For comparison:

  • dist/ folder: 4.08MB, with 356 files
  • node_modules/ folder: 118MB, with 13,015 files
Advertisements

Why are programs written with plain text?

Currently, we write programs by typing text into files, and running a compiler over those files to interpret the text we typed. This seems like it should be a historical accident.

A programming language is structured. Writing invalid code is rejected by the compiler. However, text files are inherently unstructured. Structure has to be imposed on the text file by external tools – compilers, IDEs, etc.

Why not represent programs as databases of statements/functions/etc? This would lead to a ton of benefits. For one, invalid programs would be impossible. This saves a huge amount of time where programmers currently fix typos in code, saves resources where compilers/static analysis tools read those files to find errors, etc.

It seems like we’re approaching the problem from the wrong angle. Right now, we write down a program in an unstructured format, and build tools to see if the thing we wrote down is valid. Instead of all of that, we should just write the programs in a structured format (read: database/something else which isn’t a text file) in the first place. This is akin to writing a bunch of instructions in a Word document, then writing tools to parse that Word document and produce a program, rather than just designing a program which lets you directly generate programs.

Gratitude

People often mention that it’s good to be grateful for what you have in life, etc. This isn’t a topic I spend much time thinking about. What use is there in noting what you think is good about the world, when that time could be spent experiencing the world/making it better? However, today I had a thought: Instead of appealing to vague statements like, “Be happy you’re alive”, etc, I think the notion of gratitude is a lot more impactful when you consider the size of the universe.

The universe is ridiculously large. In the universe, there is a gigantic number of atoms. My body represents an extremely small fraction of all atoms in the universe. Based on my (layman’s) understanding of current science, it should be assumed that intelligent life (read: life which can perceive the universe, reflect on it, etc) also represents a tiny fraction of all atoms in the universe.

My atoms could just as easily be a blade of grass, a spec of dirt, or a chip of porcelain on a toilet. The odds that any given atom is going to be part of a being which can perceive the universe are (I’d assume – I haven’t done an actual calculation) very, very low.

The odds of being a perceiving entity are overwhelmingly low. Any day in which a person is alive, sensing, and perceiving the universe, is a day that their atoms are not hanging around as a motionless clump of stone. And that’s something to be very grateful for.

Visual Studio Object reference error when viewing DataSet properties in an RDLC

System/software used:

  • Visual Studio 2015 Enterprise Update 2 (14.0.25123.00)
  • Windows 7 Enterprise

In Visual Studio, if there is an “Object reference not set to an instance of an object” messagebox displayed when opening an RDLC file -> Dataset properties, open the
Package Manager Console, and fix any errors.

To reproduce:

  • Open an RDLC file in Visual Studio.
  • Open the “Report Data” panel.
  • Right-click a Dataset in the “Report Data” panel -> “Dataset Properties”.
  • Object reference error pops up.

To fix it:

  • I had to uninstall the Powershell Tools for Visual Studio 2015 add-on. That’s probably not the best option, but it solved this problem at least.

This is a weird error. Why would the Powershell Tools extension have anything to do with an RDLC dataset’s properties? *shrugs shoulders* This should probably be moved/reported to the Powershell Tools extension team.

Querying 2D and 3D space

In programming, we have the ability to query databases. We can say, “Show me all customers born after 1980”, and get back a set of customers matching those conditions.

A thought occurred to me that: we don’t seem to have a simple, default ability to query 2D or 3D space. For example: assume we have a virtual world, such as a 2D map in a videogame. As a user, I should be able to say, “Highlight/retrieve all regions in this 2D map that have R >= 200, G >= 250, B >= 250”, or “Highlight/retrieve all polygons in this 3D environment with a certain color, and a certain shape”.

What prompted this? A recent article discussing 3D maps used for self-driving cars. It would be useful to query all 3D maps across the world for cases of specifically-shaped stop signs or stop lights, and annotate them on a map, for example.

Maybe it’s time to write a new SQL? Space Query Language?

Maybe the way to solve this is to build game engines on top of relational databases, and use the underlying database for querying? It kind of sounds like a montrosity, but it’s kind of intriguing also…

Using an X220i keyboard in a T410

NOTE: DON’T BLAME ME IF THIS BREAKS YOUR COMPUTER. THIS IS AN ANECDOTE, NOT EXTENSIVELY TESTED.

With that disclaimer: recently I had a problem where part of my Lenovo T410’s keyboard stopped working. I have a spare Lenovo X220i available, which is built almost identically to the T410. So I decided to swap out the keyboards. So far, this has worked – no problems. Posting this in case someone else has this situation in the future.