I thought I would finally do a bit of dabbling in ASP.NET Core and boy the onboarding experience is something isn’t it.
Firstly I had decided on a server side rendered experience instead of a SPA, and as I love TypeScript, that is what I will be doing any client-side scripting in.
I had already decided on only modern browser support and I dont want to complicate things with a slow and painful bundling experience using rollup or webpack which makes debugging an awful experience.
ASP.NET Core
So the first issue I noticed was the ugly URLs; capitalised url parts … really, urgh! I understand this is based on the file names, but I don’t want to rename the files to all lowercase as thats not the .net way.
After a fair amount of digging this is resolved with a routing option in your Startup.cs ConfigureServices
method:
services.AddRouting( options =>
{
options.LowercaseUrls = true;
} );
Why this is not the default I have no idea?!
Typescript
Ok, so now onto adding in TypeScript; again why is this not already setup in the default templates … maybe then they would have resolved all the pain which took many hours of messing about trying to resolve.
Also as I only want to target modern browsers (Edge, Firefox, Chrome, Safari) I want to be abke to use the latest features like modern Modules support and so on.
Ok, so this took me a while of mucking about and working around, but it seems that once you add in the TypeScript MSBuild package, Visual Studio 2019 automatically looks and finds tsconfig.json files … however what I wanted (and is normal) is to have a production and development configuration so that production does not include comments or map files.
After trying csproj conditions (which didn’t work and gave build errors), extending files in separate folders which also didn’t work, the only solution I found (so far) was to have the following setup, which I am not against, albeit not ideal:
- tsconfig.base.json - this contains my base options, include/exclude directories, module settings etc
- tsconfig.debug.bak - this extends the base and contains options specific to debug (see below)
- tsconfig.release.bak - like the debug.bak but with release options
tsconfig.base.json
{
"compilerOptions": {
"target": "ES2020",
"module": "ES2020",
"moduleResolution": "Classic",
"lib": [ "DOM", "ES2020" ],
"noImplicitAny": true,
"noEmitOnError": true,
"alwaysStrict": true,
"outDir": "wwwroot/js",
"allowUmdGlobalAccess": true,
"forceConsistentCasingInFileNames": true
},
"include": [
"scripts/**/*"
],
"exclude": [
"wwwroot/lib/**/*",
"wwwroot/js/**/*"
]
}
tsconfig.debug.bak
{
"extends": "./tsconfig.base.json",
"compilerOptions": {
"removeComments": false,
"sourceMap": true
}
}
tsconfig.release.bak
{
"extends": "./tsconfig.base.json",
"compilerOptions": {
"removeComments": true,
"sourceMap": false
}
}
The last piece of this little puzzle is to set a Pre-Build Event to rename the debug/release based on the current configuration:
del "tsconfig.json"
copy "tsconfig.$(ConfigurationName).bak" "tsconfig.json"
All the above now allows you to have modern TypeScript using imports in an asp.net core project.
The only caveat (which again is odd that there is no option for) is that your import statements need to have .js
added to the module name. This works in both TS compiles but also in the browser; and to include the main script as a module
.
Here are some examples.
app.ts
export class App {
constructor() {
}
public startup() {
// Initialise and start our application
}
}
site.ts
import { App } from './app.js';
$(document).ready(() => {
const app = new App();
app.startup();
});
_Layout.cshtml
<script src="~/js/site.js" asp-append-version="true" type="module"></script>
I hope this helps someone who might be discovering the same points as me.
Now available as a free Visual Studio Extension