#1 Creation and Basic Setup
Tuesday, October 10, 2017
In this article we will perform the creation and basic setup for our project.
Parts
- Part 30: User Database
- Part 29: Canonical Url
- Part 28: Razor Page Handlers
- Part 27: Send Screen Finished
- Part 26: Stroke Dashoffset
- Part 25: Send Screen
- Part 24: Forgot Link Behaviour
- Part 23: Animating Controls (cont.)
- Part 22: Animating Controls
- Part 21: Hiding Control Groups
- Part 20: ModelState Errors (cont.)
- Part 19: ModelState Errors
- Part 18: Animating Info Pages (cont.)
- Part 17: Animating Info Pages
- Part 16: Keyboard Navigation
- Part 15: Accessing the DOM
- Part 14: All About the Username
- Part 13: CSRF Attacks
- Part 12: Http Requests
- Part 11: HMR
- Part 10: Color Inputs And Buttons
- Part 9: Animating Sub-Actions
- Part 8: Form Validation (cont.)
- Part 7: Form Validation
- Part 6: Form Group
- Part 5: Authenticator Validators
- Part 4: Authenticator Inputs
- Part 3: First Angular Component
- Part 2: Webpack
- Part 1: Beginning
Project Creation
This project begins as they all do using File -> New -> Project
in Visual Studio. You are of course free to use any
IDE/Text editor that you prefer but we will be using Visual Studio and Visual Studio Code throughout this series. Both are
available for free at Visual Studio Community and
Visual Studio Code. When starting a new project I more likely than not begin with creating a blank solution (a),
which at the time of the writing of this article will be targeting version 4.6.1 of the .Net Framework which I will name AspNetCoreAngularWebpack. Next we need to add a new project in our blank
solution again using File -> New -> Project
but this time we are going to create an ASP.NET Core Web Application (b),
which I have named WebUi. After clicking ok we are presented with another dialog which we use to select the specific template that we want to start with. After
making sure that the selection box at the top of the dialog says 'ASP.NET Core 2.0' we will select the 'Web Application' option with no authentication, we will
add authentication ourselves later, and click ok.



Folder Structure
-
WebUi
-
wwwroot
-
css
- site.css
-
images
- banner1.svg
- banner2.svg
- banner3.svg
- banner4.svg
- lib
-
js
- site.js
-
css
-
Source
-
sass
- 0-bourbon
- 1-neat
-
2-base
- _media-queries.scss
- _bourbon-neat.scss
-
sass
- .bowerrc
- bower.json
-
wwwroot
Now that our project is created we will add and remove a few files and folders. All the files and folders that are shown in red can be deleted. Once that is done
our next step is to create a 'Source' folder in the root of the project which will hold all of the files that we need to create the front-end of the application.
Inside of this folder we need to create a 'sass' folder, which as you have guessed will contain our styles outside of those pertaining to a particular component.
After creating a the Sass forlder we need to open a terminal inside of it execute
the following commands: bourbon install
, which will create a bourbon folder, neat install
, which will
create a neat folder and finally bitters install
which will create a base folder. What I like to do next is rename these folders
to keep them in a particular order so I rename them bourbon -> 0-bourbon
, neat -> 1-neat
, and
base -> 2-base
. I picked this convention up by watching YouTube videos from
DevTips. He has some very good we design tutorial videos and I highly encourage you to
check them out if you are interested. All three of the preceding install commands come from ruby gems which of course requires you to have ruby installed on your
machine which you can find at https://rubyinstaller.org/. The packages themselves were created by
thoughtbot and the documentation for each can be found at bourbon,
neat, and bitters. At the time of the writing of this
article the versions that we are using are bourbon: 5.0.0-beta.8, neat: 2.1.0, and bitters: 1.7.0. In order to make it easy for us to import the files from both
the 0-bourbon and 1-neat folders we will create a file called '_bourbon-neat.scss' (d) in the sass folder which will import the file from both folders that exports all
of their contents.
Note: This project will make use of the console for running our front-end build process and as such I very quickly became unhappy with the console available on Windows so I have installed a console emulator name ConEmu.
Note: All code blocks that appear, not including inline code, will have a copy button where if you press it the contents of the block will be copied to your clipboard allowing you to then paste it to your IDE/text editor.
There will already be several files inside of the 2-base folder but we need to create one more named '_media-queries.scss' (e). This file just contains a few mixins that
I like to use to make writing media queries a little bit easier and we will be writing a ton of them as the project progresses. This will allow us to write our
media queries like @include media-lt(768px)
which will be active when the screen is less than 768px wide and
@include media-gt(768px)
which will be active when the screen is greater than 768px wide. We also have the equivalent
mixins for less than or equal to, greater than or equal to and between a min and max value.
_bourbon-neat.scss
@import "0-bourbon/_bourbon.scss";
@import "1-neat/_neat.scss";
_media-queries.scss
@import "../_bourbon-neat.scss";
@mixin media-lt($max-width) {
@media screen and (max-width: $max-width - 1) {
@content;
}
}
@mixin media-lt-or-eq($max-width) {
@media screen and (max-width: $max-width) {
@content;
}
}
@mixin media-gt($max-width) {
@media screen and (min-width: $max-width + 1) {
@content;
}
}
@mixin media-gt-or-eq($min-width) {
@media screen and (min-width: $min-width) {
@content;
}
}
@mixin media-between($min-width, $max-width) {
@media screen and (min-width: $min-width) and (max-width: $max-width) {
@content;
}
}
Node Setup
Next we turn to setting up our Node.js environment by navigating our console to the root of the project and typing npm init -y
which
will create a default package.json file for us. I have changed the value of the name property from 'WebUi' to 'web-ui' the specification for the package.json file should
not contain capital letters and added to the scripts and dependencies. You can either install the packages yourself (f) or you can copy and paste the package.json file (g)
from here and run npm i
. One last thing we need is to either install TypeScript locally using npm or as I have it globally and then
create a link to it. To do that we need to run npm link typescript
at the root of our project.
npm install
npm install --save
@angular/common
@angular/compiler
@angular/core
@angular/forms
@angular/http
@angular/platform-browser
@angular/platform-browser-dynamic
@angular/router
@types/node
@types/web-animations-js
autoprefixer
classlist-polyfill
core-js
css-loader
extract-text-webpack-plugin
html-loader
lodash
node-sass
normalize.css
postcss-loader
pug-html-loader
raw-loader
rxjs
sass-loader
style-loader
ts-loader
uglifyjs-webpack-plugin
web-animations-js
webpack
webpack-bundle-analyzer
zone.js
{
"name": "web-ui",
"version": "1.0.0",
"description": "",
"main": "index.js",
"dependencies": {
"@angular/common": "^4.4.4",
"@angular/compiler": "^4.4.4",
"@angular/core": "^4.4.4",
"@angular/forms": "^4.4.4",
"@angular/http": "^4.4.4",
"@angular/platform-browser": "^4.4.4",
"@angular/platform-browser-dynamic": "^4.4.4",
"@angular/router": "^4.4.4",
"@types/lodash": "^4.14.77",
"@types/node": "^8.0.33",
"@types/web-animations-js": "^2.2.5",
"autoprefixer": "^7.1.5",
"classlist-polyfill": "^1.2.0",
"core-js": "^2.5.1",
"css-loader": "^0.28.7",
"extract-text-webpack-plugin": "^3.0.1",
"html-loader": "^0.5.1",
"lodash": "^4.17.4",
"node-sass": "^4.5.3",
"normalize.css": "^7.0.0",
"postcss-loader": "^2.0.6",
"pug-html-loader": "^1.1.5",
"raw-loader": "^0.5.1",
"rxjs": "^5.4.3",
"sass-loader": "^6.0.6",
"style-loader": "^0.19.0",
"ts-loader": "^2.3.7",
"uglifyjs-webpack-plugin": "^1.0.0-beta.3",
"web-animations-js": "^2.3.1",
"webpack": "^3.6.0",
"webpack-bundle-analyzer": "^2.9.0",
"zone.js": "^0.8.18"
}
"scripts": {
"build": "set NODE_ENV=development&&webpack --progress",
"build:production": "set NODE_ENV=production&&webpack --progress -p",
"test": "echo \"Error: no test specified\" && exit 1",
"watch": "set NODE_ENV=development&&webpack --progress --watch"
},
"keywords": [],
"author": "",
"license": "ISC"
}
Typescript Setup
-
WebUi
- tsconfig.json
- tslint.json
- WebUi.csproj
Speaking of TypeScript we need to add a couple of configuration files for the TypeScript compiler both of which will be created at the root of our project. The first file that we need to create is the 'tsconfig.json' file (h). This file will be used by the typescript loader when calling the typescript compiler to pass in the configuration options. A detailed explanation of the contents can be found at https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. Next create a file called 'tslint.json' (i) in the root of the project. This file will be used to configure the rules that should be followed in our typescript files. A detailed explanation of the contents can be found at https://palantir.github.io/tslint/usage/tslint-json.
If you are using Visual Studio we need to disable its built in behaviour for dealing with typescript files since we will be using webpack to transpile all of them. To do this we need to add an entry to our WebUi.csproj file by simply right clicking on the project in the solution explorer and selecting 'Edit WebUi.csproj' option which will open the file for us. Once it is open we need to add the property group (j) to it. This will prevent the transpiling of the typescript code when our solution is built.
tsconfig.json
{
"compileOnSave": false,
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": false,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"removeComments": false,
"noImplicitAny": true,
"suppressImplicitAnyIndexErrors": true,
"outDir": "wwwroot/js",
"lib": [ "es2017", "dom" ]
},
"exclude": [
"node_modules",
"wwwroot"
]
}
tslint.json
{
"extends": "tslint:latest",
"rules": {
"no-constructor-vars": true,
"no-string-literal": false
},
"rulesDirectory": [
]
}
WebUi.csproj
<PropertyGroup>
<TypeScriptCompileBlocked>True</TypeScriptCompileBlocked>
</PropertyGroup>
Odds and Ends
-
WebUi
-
Pages
- _Layout.cshtml
- Index.cshtml
-
Source
-
app
- vendor.ts
-
app
-
Pages
In our project we have plenty of third-party code that we do not want to include in each javascript bundle so we will create a separate file that we can call when we setup webpack to create a separate bundle. Start by creating a folder named 'app' under the Source folder and inside it create a file named 'vendor.ts' (k).
And we will reduce our _Layout.cshtml file to the code in block (l) and we will delete the contents of the Index.cshtml, In the next article we will setup webpack to process all of our scss and typescript files.
vendor.ts
import "core-js/es6";
import "core-js/es7/reflect";
import "zone.js/dist/zone";
if (process.env.ENV !== "production") {
Error["stackTraceLimit"] = Infinity;
require("zone.js/dist/long-stack-trace-zone");
}
import "@angular/platform-browser";
import "@angular/platform-browser-dynamic";
import "@angular/core";
import "@angular/common";
import "@angular/http";
import "@angular/router";
import "@angular/forms";
import "classlist-polyfill";
import "lodash";
import "rxjs";
import "web-animations-js";
_Layout.cshtml
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - WebUi</title>
<environment include="Development">
<link rel="stylesheet" href="~/css/main.bundle.css" />
</environment>
<environment exclude="Development">
<link rel="stylesheet" href="~/css/main.bundle.min.css" asp-append-version="true" />
</environment>
</head>
<body>
<div class="container body-content">
@RenderBody()
<hr />
<footer>
<p>© 2017 - WebUi</p>
</footer>
</div>
<environment include="Development">
<script src="~/js/vendor.bundle.js"></script>
<script src="~/js/main.bundle.js"></script>
</environment>
<environment exclude="Development">
<script src="~/js/vendor.bundle.min.js" asp-append-version="true"></script>
<script src="~/js/main.bundle.min.js" asp-append-version="true"></script>
</environment>
@RenderSection("Scripts", required: false)
</body>
</html>