In this lab you will learn about the development of web sites that are structured as a single-page application.
The shell is the tool you use to issue shell commands. On Linux or MacOS this will be the Terminal and on Windows this is the Command Prompt. If you are on Windows you won't be able to run any git commands using Command Prompt but instead will need to use Git Bash instead.
To complete the lab you will need to ensure you have the correct software installed and have downloaded the source code.
To complete this lab you will need the following software installed:
- A standards-compliant browser (such as Chromium or Google Chrome).
- NodeJS (LTS, not the latest version).
- Git running in your shell.
- The Heroku CLI tool (instructions below).
Install the Heroku CLI tools, using the instructions on their website. You may need to restart your shell before continuing.
You will also need to register for a free developer account on the Heroku website.
There is a template available on the University GitHub server. This will be used for many labs.
You need to use the "Use this template" button each time you need a copy of the code. For the lab exercises (such as this one) you should store the copy of the code in your personal space. Do this now and call it single-page-app
.
If, for any reason, you are struggling to get the code in this manner an alternative is to click on the "Clone or download" button and use the Download ZIP option, renaming the directory single-page-app
.
Clone your repository and use your shell to navigate to the single_page_app/
directory created by the clone command. After installing all the module dependencies using npm install
, you can run the server using node index.js
. You should be able to point your browser to localhost:8080
to see the site.
Take a few minutes to see how it works, try registering and account and logging in. Press ctrl+c
to stop the server.
We will now cover how to host your SPA in the cloud.
Heroku is a cloud application platform, which is an example of a platform as a service (PaaS). It makes it very easy to deliver and deploy modern apps allowing you to focus on coding them. Deployment uses Git to upload the code to the server. When code is pushed, the server runs a pre-receive hook to provision the server and get your app up and running.
Make sure your shell is still in the single_page_app/
project directory created by the clone command. Now log into Heroku using the CLI (note this will make use of the browser):
$ heroku login
heroku: Press any key to open up the browser to login or q to exit
› Warning: If browser does not open, visit
› https://cli-auth.heroku.com/auth/browser/***
heroku: Waiting for login...
Logging in... done
Logged in as jdoe@example.com
Heroku uses the information in the application manifest package.json
to get your website running:
- It spins up a docker virtual machine container.
- It installs the version of NodeJS specified in the
engines.node
key. In the sample code we are specifying v12.14. - It then goes through all the packages listed in the
dependencies
object and installs the versions specified there. - To decide how to run the server it looks for the
start
key inside thescripts
object and executes what it finds.
For this reason it is absolutely vital that the application manifest is accurate and up-to-date.
After making sure you are in the correct project directory, run the following command:
$ heroku create
Creating app... done, ⬢ cryptic-depths-87792
https://cryptic-rain-52361.herokuapp.com/ | https://git.heroku.com/cryptic-rain-52361.git
Heroku generates a random name for your app, in this case cryptic-rain-52361
and provides both a link to the live server and to the git remote it has created for you. If you check your repository remotes you should see this alongside the origin remote on github:
$ git remote -v
heroku https://git.heroku.com/cryptic-rain-52361.git (fetch)
heroku https://git.heroku.com/cryptic-rain-52361.git (push)
origin https://github.coventry.ac.uk/bloggsj/myapp.git (fetch)
origin https://github.coventry.ac.uk/bloggs/myapp.git (push)
To deploy the app we simply have to push to this remote...
$ git push heroku master
Enumerating objects: 12, done.
Counting objects: 100% (12/12), done.
Delta compression using up to 4 threads
Compressing objects: 100% (7/7), done.
Writing objects: 100% (7/7), 1.41 KiB | 1.41 MiB/s, done.
Total 7 (delta 4), reused 0 (delta 0)
remote: Compressing source files... done.
remote: Building source:
remote: -----> Node.js app detected
remote: -----> Creating runtime environment
remote: -----> Installing binaries
remote: -----> Restoring cache
remote: -----> Installing dependencies
remote: -----> Build
remote: -----> Caching build
remote: -----> Pruning devDependencies
remote: -----> Build succeeded!
remote: -----> Discovering process types
remote: -----> Compressing...
remote: -----> Launching...
remote: https://cryptic-rain-52361.herokuapp.com/ deployed to Heroku
remote: Verifying deploy... done.
To https://git.heroku.com/cryptic-rain-52361.git
9fc3cc6..62ef6a3 master -> master
You should now be able to access your deployed app using the URL provided by heroku.
The server generates detailed logs that you should be checking on a regular basis:
heroku logs --tail
This gives you a live view of the logs. Run the command then try navigating the website. To quit you use the standard ctrl+c
key combination.
You can also log directly into the server bash shell:
$ heroku ps:exec
Running this command for the first time requires a dyno restart.
Do you want to continue? [y/n]:
Initializing feature... done
Restarting dynos... done
Waiting for web.1 to start... ⡿
Establishing credentials... done
Connecting to web.1 on ⬢ cryptic-depths-87792...
~ $
The prompt changes and you are now logged into the server via the shell and can run all standard bash commands. type exit
to quit. This returns you to the workstation prompt.
We will be working to improve the efficiency of the apps we will be producing. What do we mean by efficiency?
One key metric is concerned with how quicky and smoothly the page(s) load as this impacts the user experience.
If we are to understand the issues we are trying to resolve we need a suitable tool to both test our system under controlled conditions and to generate data which allows us to see the issues.
With the app running locally, open Chromium and, from the main menu (top-right) select More tools > Developer tools and position this at the bottom of the browser window. Open the Network tab and load the page http://localhost:8080
(or refresh the page if this is already being displayed). You should see something similar to the following:
This shows the sequence of steps that were needed to download and display the page, starting with the request for the base html page which then loads the stylesheet and script, etc.
Each bar is broken down into several bands:
The narrow bar is the request and the wide bar the response. You can see more metrics by hovering your mouse over each bar.
- White: STALLED, time the request spent waiting before it could be sent.
- Grey: REQUEST SENT, the http request was sent to the server.
- Green: TIME TO FIRST BYTE, includes 1 round trip of latency plus the time the server took to prepare the response.
- Blue: CONTENT DOWNLOAD, The browser is receiving the response.
Notice that HTTP/1.1 can only handle two http requests at one time. This limitation has been removed for HTTP/2 which we will be covering in a later lab.
Running your web app locally means you will never encounter major bandwidth or latency issues however your apps needs to be able to handle real-world conditions such as users accessing the app over the internet, possibly using an intermittent cellular connection.
Whilst you could take the time to walk around and try and find suitable conditions, ths is clearly not time-efficient or even feasible. because this type of testing is very common, there are tools build into modern web browsers to simulate these conditions.
Let's load the same page, this time over a slow 3G connection such as many mobile users will be limited to. Click on the dropdown link which will be displaying the label Online and change this to Slow 3G. You should also disable the cache by checking the Disable cache checkbox. Now reload the page, watching the browser window to see how the page loads.
A 3G network typically has a very high latency and this is clearly shown in the graph by a much longer TTFB time. This represents the delay between a request being sent from the browser and the first byte of data being received back in the response.
A key way we can improve the user experience is by ensuring that the controls and layout of our app are optimised for:
- The size of screen the user is viewing the app on.
- The mode of interaction (are they using a trackpad or a touchscreen?).
Responsive Web Design principles mean designing you page to change its layout and appearance depending on the type of device, measured by screen resolution and primary input device.
As you develop your responsive designs you will need to quickly test the changes. Whilst this can be carried out using different hardware this is often time consuming as you need to host the site and then take the time to physically use each device.
To help you during the development process Chromium includes a Device Mode which allows you to test how the app will look based on resolution and input device. Whilst these can never be completely accurate, they serve perfectly to iterate through the design, with final tests being carried out on actual devices.
If you click on this you will see the following:
Note if your view looks different from the screenshot above make sure you have the Responsive mode selected (see arrow) and have added the extra tools using the main menu button at the top-right of the screen (see arrow).
With the simulator open you can use the settings to simulate a wide range of devices.
- Screen Resolution
- You can use the handles along the edge of the screen (see arrow) to adjust the width and height in pixels. The ruler is calibrated in pixels.
- Primary Input Device
- The **Mobile** dropdown allows you to choose between desktop and mobile, each with a touchscreen and non-touchscreen option.
- Connectivity
- The **Online** dropdown lets you simulate high or low-end hardware or even simulate being disconnected from the Internet. This simulates a combination of slow CPU and slow network.
- Device Rotation
- The last button simulates switching from _landscape_ to _portrait_ mode.
It is also possible to simulate the hardware sensors on the device. By default this is hidden and needs to be accessed under Settings > More tools > Sensors.
This will open a new pane in the developer tools where you can simulate:
- Geolocation.
- The device orientation.
As you change the simulated location you should see the appropriate coordinates appear in the page footer!
The interface needs to be optimised for different screen resolutions and different types of input, for example a touch interface can't generate mouse events such as mouse-over and the controls should be of a size that is easy to interact with using a finger. An interface designed to be used with a trackpad or mouse can use much more precise controls.
If you look a the icon in the far left of the footer you should see a tablet-shaped icon. In the settings, switch from Mobile to Desktop. Notice that when you are simulating a desktop device the cursor changes to a desktop cursor but also the icon changes to a desktop screen!
The current page design is optimised for traditional computers using a mouse or trackpad, what changes would you make for it to work well for users using a touchscreen and finger?
Now drag the screen width wider and narrower in Responsive mode. As you do so keep an eye on the "led" indicator in the page footer. Notice that if you make the screen narrow it switches to red and, if you make the screen very wide it goes green. Above the simulated screen you should see a bar split into three levels (typically blue, green and brown). What happens as you drag the screen size between these zones?
You will have noticed that the page layout is optimised for the medium width screen. When it gets very narrow the navigation bars get squashed and the content starts to disappear off the edge of the screen. How could you redesign the layout to prevent the layout isses on small screens?
When the screen is wide you will notice that the list blocks become very wide with a lot of wasted space. How could you redesign the layout to make better use of larger screens?
It looks like the web app is detecting both whether the device supports a touchscreen and which width "zone" it is currently in and updating the "led" accordingly. How does it do this and how are the zones defined?
Open up the style.css
file and scroll to the bottom. You will see a series of @media
selectors, each containing a CSS selector. The first two detect whether the device is touch-screen with fingers (no hover and coarse pointing) or whether it is non-touchscreen controlled with a trackad or mouse (hover supported and fine-grained pointer). If the conditions match the css selectors inside are run. This is how we can adjust the interface based on touch support.
Underneath this are three additional @media
selectors that are triggered by the current screen width of the device. Again, once the conditions match the selectors are used.
Notice that the values in these are defined as min and max. These are used by Chrome to display the coloured bands. Try changing these and refreshing the browser.
Earlier in the lab you identified some layout issues when the screen was very narrow and also when it was very wide:
- Locate the media selector that detects the use of a touchscreen and add selectors to this to improve the design for touchscreen users.
- Locate the media selector that detects narrow screens and add selectors to prevent the layout issues you saw earlier in the lab. You might consider removing the absolute sizes and letting the elements fill the screen width.
- Locate the media selector that detects wide screens and change the layout so that the lists are presented as tiles that make use of the entire screen width.
Whilst you can do a lot of development work using Google Chrome's Device Mode final testing and tweaking will need to be done running on a browser on the target platform. There are emulators available for both iOS and Android phones and, once the design has been worked through using Device Mode you should load it into the emulators for final tweaking.
You should start by installing the latest version of Android Studio which provides access to the Android Virtual Device (AVD) tools that are used to install and manage the emulators.
Once Android Studio is installed, you should launch it and, from the launch screen choose Configure > AVD manager (see the screenshot below).
We are going to go through the steps on creating and running an emulator of the Nexus One. Once you have understood these steps you can repeat the process to create and run as many emulators as you need for testing. Note that each emulator takes up to 1GB storage and your system may struggle to run emulators for the latest phones.
- On the next screen choose Nexus One and click Next.
- The next screen is where you choose the system image (OS version) to install. We will choose Android 10.0, the latest version at the time of writing.
- The final screen asks you to choose a name for this AVD. You can choose anything you like.
To run the emulator simply click on the green "play" button on the main AVD screen as shown.
This will start up the emulator and you can run the web browser on the emulator and point it to your running server.
Note: you can only run iOS emulators if you are developing on MacOS.
You should start by installing the latest version of Xcode from the Mac App Store which provides access to the iOS simulators.
Launch Xcode and, without creating a project use the Xcode > Open Developer Tool > Simulator. If you look in the dock you will see it has an icon. Right-click, choose Options > Keep in dock. This will create a permanent dock icon which you can use to launch the simulator without needing to open Xcode.