Getting started
This page presents the necessary steps required to start building a web app using Hydrofoil.
This is not a definitive guide as there are many ways to set up the different build steps using a variety of tools.
The recommended way is to set up a project using Open Web Components packages.
Project preparations (optional, recommended)
Be sure to read the open-wc quickstart to easily follow the instructions below and to discover alternative options
@open-wc
NPM templates are the quickest mean to bootstraping a development environment
fit for web components.
In any directory, run npm init @open-wc
. Answer the subsequent questions:
Scaffold a new project
- Choose
Application
- Select
Building
- Type in the name
Yes
<- confirm file structure- Install with Yarn or npm
Be careful to properly select with space
where instructed
This will create a new sub directory with the bare minimum, empty app.
At the time of writing the index.html
file is placed inside the source dir, which
results in weird address when served locally.
To "improve" the project structure, move the index to the root and adjust the path
in its <script>
tag, webpack.config.js
and the start
script in package.json
.
Create a shell element
You need to add the shell package.
npm i @hydrofoil/hydrofoil-shell
It contains the base element which we will extend to create the application centerpiece.
Here's a simplest possible implementation. As the element is itself abstract,
the implementor must override the loadResourceInternal
method which returns the
resource representation for the given URL.
import {HydrofoilShell} from '@hydrofoil/hydrofoil-shell/hydrofoil-shell'
import './views'
class PlainShellElement extends HydrofoilShell {
async loadResourceInternal(url) {
const response = await fetch(url)
return await response.text()
}
}
customElements.define('plain-shell', PlainShellElement)
Add the shell element to the app
Replace the default contents of the app element generated in by @open-wc
with the shell:
import { LitElement, html } from 'lit-element';
import './plain-shell'
class BuildingExample extends LitElement {
render() {
return html`
<plain-shell use-hash-urls></plain-shell>
`;
}
}
customElements.define('building-example', BuildingExample);
Why two elements?
Curious developer will think:
why not use the shell directly as the application root?
While nothing is actually stopping anyone from doing that, there are a few reasons to keeps the dual structure:
- The shell has properties and attributes which can be dynamically controlled by the app
- The shell may offer styling points which can be awkward to set up in an
index.html
- The shell may expose
slot
extension points. Again, building a rich DOM structure will be easier in the app element - The app element can do dynamic imports as necessary to build up the shell UI
Define rendering of your resources
Rendering of resource representations is done with a library called lit-any
. It divides the
entire process of rendering into smaller chunks it calls views. Each view is a effectively a function
which takes an object as input and returns a HTML
template string.
Here's the simplest possible renderer which will dump the text contents loaded by the shell
above, wrapped in a <pre>
tag.
import { ViewTemplates } from '@lit-any/views'
import {html} from 'lit-html';
ViewTemplates.default.when
.scopeMatches('hydrofoil-shell')
.renders(text => html`<pre>${text}</pre>`)
To learn more about lit-html
and its syntax and features go to its guide
Trying it out
Check out this repo, go to the building-example
directory and run
npm install
npm run start:dev
Now go to
http://localhost:8080/#/https://cors-anywhere.herokuapp.com/https://example.com/dummy
You should see the HTML contents of https://example.com
. A glorified "view source" if you will.
A note on addresses
See that the entire URL of the "back end" is visible in the link and your browser. In a real
application this will not be desirable. Instead the URL should be more like
http://localhost:8080/#/dummy
in this case. Hydrofoil and its component can be configured to
make that happen.
Also, the shell is configured with an use-hash-urls
attribute. To have your local environment
use HTML5 History API you will need to set up webpack dev server accordingly and remove that
attribute from the shell element.
More details can be found in the Routing section.