This tutorial makes use of following bits and bobs: VS Code, NPM, Yarn, Typescript, SASS, WebPack, Bootstrap (V4) and of course the mighty Aurelia. I created this as a record of some basic steps I go through to get a SPA up and running.
There are a few things that could be a little better, the reference to bootstraps js files isn't great and really needs to be included in the webpack configuration. I am still getting to grips with webpack so if anyone can advise please do so. I am also not totally sure that all the dependencies are in the right place in the package.json.
- Install VS Code from here or Insider version here.
- Install NPM from here.
- Install Yarn from here.
- Install WebPack from here.
- Create a project folder for your code.
- Create a src folder for your source code.
a. I typically create test, docs folder next to the src, but not for this tutorial. - Open the project folder in VS Code.
- Open a terminal in VS Code using Ctrl+' keystroke.
- Change dir to src folder using cd src.
- Initialise a project using yarn init follow prompts.
a. This creates the package.json.
b. Open the package.json in VS Code.
c. Delete the main: index.js line. - Add the dependencies using yarn add aurelia-bootstrapper [email protected] bootstrap-sass bootstrap-sass-loader
- Add the dev dependecies using yarn add aurelia-webpack-plugin css-loader html-loader node-sass sass-loader style-loader ts-loader typescript webpack webpack-dev-server url-loader file-loader –dev
- Add to the package.json, after the devDependencies to following.
"scripts": {
"web": "webpack-dev-server --config webpack.config.js --hot --inline"
}
- The next 4 files and src folder are all added next to the package.json in the src folder.
- . Add a tsconfig.json file with the following.
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"lib": [ "es6", "dom" ],
"experimentalDecorators": true
}
}
- Add a webpack.config.json file with the following.
const path = require("path");
const { AureliaPlugin } = require("aurelia-webpack-plugin");
module.exports = {
entry: "main",
output: {
path: path.resolve(__dirname, "dist"),
publicPath: "/dist/",
filename: "bundle.js",
},
devtool: "eval-source-map",
resolve: {
extensions: [".ts", ".js"],
modules: ["src", "node_modules"].map(x => path.resolve(x)),
},
module: {
rules: [
{ test: /\.scss$/i, use: ["style-loader", "css-loader", "sass-loader"] },
{ test: /\.ts$/i, use: "ts-loader" },
{ test: /\.html$/i, use: "html-loader" },
]
},
plugins: [
new AureliaPlugin({ includeAll: "src" })
],
};
- Add a index.html with the following (note dodgy js references).
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
</head>
<body>
<div aurelia-app="main">
<script src="/node_modules/jquery/dist/jquery.min.js"></script>
<script src="/node_modules/bootstrap/dist/js/bootstrap.min.js"></script>
<script src="/dist/bundle.js"></script>
</div>
</body>
</html>
- Add a site.scss with the following.
$primary-color: #8484ff;
body{
background-color: $primary-color;
}
- Add the src folder.
- The next 3 and 2 folders files are added in the newly create src folder.
- Add a main.ts with the following.
import 'bootstrap/scss/bootstrap.scss';
import '../site.scss';
import 'aurelia-bootstrapper';
import { Aurelia } from 'aurelia-framework';
export function configure(aurelia: Aurelia){
aurelia.use
.standardConfiguration()
.developmentLogging();
aurelia.start().then(() => aurelia.setRoot());
}
- Add a app.ts with the following.
import { AppRouter, RouterConfiguration } from 'aurelia-router';
export class App{
testMessage: string;
title: string;
router: AppRouter;
constructor(){
this.testMessage = "Set in the constructor of App class";
this.title = "TODO"
}
configureRouter(config: RouterConfiguration, router: AppRouter){
this.router = router;
config.title = this.title;
config.map([
{route: ['','home'], name: 'home', title: 'Home', moduleId: 'home/home', nav: true},
//{route: 'about', name: 'about', title: 'About', moduleId: 'about/about', nav: true}
]);
}
}
- Add a app.html with the following.
<template>
<require from="./shared/main-nav.html"></require>
<require from="./shared/main-footer.html"></require>
<div class="container-fluid container-content-header">
<div class="container px-0">
<main-nav router.bind="router" title.bind="title"></main-nav>
</div>
</div>
<div class="container-fluid">
<div class="container container-content pt-3">
<router-view></router-view>
</div>
</div>
<div class="container-fluid">
<div class="container container-content-footer">
<main-footer></main-footer>
</div>
</div>
</template>
- Add the home folder.
- Add the shared folder.
- The next 2 files are added to home folder.
- Add the home.ts with the following.
export class Home{
testMessage: string;
constructor(){
this.testMessage = 'Home Placeholder';
}
}
- Add the home.html with the following.
<template>
${testMessage}
</template>
- The next 2 files are added to the shared folder.
- Add a main-nav.html with the following.
<template bindable="router,title">
<nav class="navbar navbar-main navbar-toggleable-md navbar-light bg-transparent py-0">
<button class="navbar-toggler navbar-toggler-right"
type="button"
data-toggle="collapse"
data-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent"
aria-expanded="false"
aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<a class="navbar-brand" href="#">${title}</a>
<div class="collapse navbar-collapse"
id="navbarSupportedContent">
<ul class="navbar-nav">
<li repeat.for="nav of router.navigation"
class="nav-item nav-item ${nav.isActive ? 'active' : ''}">
<a class="nav-link ${nav.isActive ? 'active' : ''}"
href.bind="nav.href">${nav.title}</a>
</li>
</ul>
</div>
</nav>
</template>
- Add a footer-nav.html with the following.
<template>
<h3>placeholder for footer</h3>
</template>
- In the terminal run webpack to check webpack transpiles correctly.
- In the terminal run npm run web.
- Open your browser to http://localhost:8080.
- Enjoy!