README ¶
dp-renderer
A rendering library for Digital Publishing frontend microservices. dp-renderer
contains templates, localisations and model structs that are core to all dp-frontend
services.
dp-renderer
is intended to be used instead of calling dp-frontend-renderer
to generate HTML, which consequently means more explicit domain encapsulation of our frontend apps and the removal of a single point of failure within the DP frontend architecture.
Note: although the dp-frontend-renderer
is deprecated there is a transition period where updates will be needed in dp-renderer
and the dp-frontend-renderer
. See the README on the dp-frontend-renderer
for the migration status.
Installation
Other than dp-renderer
itself, you will need a utility that can combine service-specific and dp-renderer
assets. We currently use go-bindata
for this process.
dp-renderer
:go get github.com/ONSdigital/dp-renderer
You can specify a version of
dp-renderer
by appending a commit ID or semantic version number to this command. E.g.,go get github.com/ONSdigital/dp-renderer@31d8704
go-bindata
:go get github.com/kevinburke/go-bindata
Migrating from dp-frontend-renderer
and dp-frontend-models
to using dp-renderer
See the migration guide for step-by-step details.
Usage
Instantiation
Assuming you have go-bindata
set up to generate the relevant asset helper functions, you can instantiate the renderer with a default client (in this case, the default client is unrolled
).
rend := render.NewWithDefaultClient(asset.Asset, asset.AssetNames, cfg.PatternLibraryAssetsPath, cfg.SiteDomain)
You can also instantiate a Render
struct without a default client by using New()
. This requires a rendering client that fulfills the Renderer
interface to be passed in as well.
rend := render.New(rendereringClient, patternLibPath, siteDomain)
Mapping data and building a page
When mapping data to a page model, you can use NewBasePageModel
to instantiate a base page model with its PatternLibraryAssetsPath
and SiteDomain
properties auto-populated via the Render
struct:
basePage := rendC.NewBasePageModel()
mappedPageData := mapper.CreateExamplePage(basePage)
In order to generate HTML from a page model and template, use BuildPage
, passing in the ResponseWriter
, mapped data, and the name of the template:
rend.BuildPage(w, mappedPageData, "name-of-template-file-without-extension")
If an error occurs during page build, either because of an incorrect template name or incorrect data mapping, dp-renderer
will write an error via an errorResponse
struct.
Using design patterns or components in your service
See PATTERNS for details.
Using Sixteens for older pages
As Sixteens is in the process of being deprecated, dp-renderer is designed to use dp-design-system
by default.
If a page requires Sixteens instead of dp-design-system, then you need to set the FeatureFlag.SixteensVersion
to the relevant Sixteens commit ID. When this value is set, the main template will load Sixteens assets and styling instead of the design system's.
func CreateExamplePage(basePage coreModel.Page) model.ExamplePage {
p := model.ExamplePage{
Page: basePage
}
// Loads in specific version of Sixteens based on commit ID, instead of dp-design-system
p.FeatureFlags.SixteensVersion = "ba32e79"
return p
}
Referencing a local instance of dp-renderer in a docker container
If you are running and developing within a docker container that includes references to the dp-renderer, for example, the cantabular import journey. Follow these steps to use a local instance:
- Update the
go.mod
file in the relevant service to use thereplace statement
to point to your local dp-renderer instance e.g.
replace "github.com/ONSdigital/dp-renderer" => "/{yourPathToLocalGitDirectory}/dp-renderer"
- Add the volume of your local instance to the service's
.yaml
file in dp-compose e.g.
To modify the dp-frontend-dataset-controller to use a local dp-renderer instance in the cantabular import journey, modify dp-frontend-dataset-controller.yml
volumes to include your local instance
version: '3.3'
services:
dp-frontend-dataset-controller:
build:
context: ../../dp-frontend-dataset-controller
dockerfile: Dockerfile.local
command:
- reflex
- -d
- none
- -c
- ./reflex
volumes:
- ../../dp-frontend-dataset-controller:/dp-frontend-dataset-controller
- /{yourPathToLocalGitDirectory}/dp-renderer:/{yourPathToLocalGitDirectory}/dp-renderer
ports:
- 20200
restart: unless-stopped
environment:
BIND_ADDR: ":20200"
DOWNLOAD_SERVICE_URL: "http://dp-download-service:23600"
API_ROUTER_URL: "http://dp-api-router:23200/v1"
DOWNLOADER_URL: "http://dp-download-service:23400"
ENABLE_CENSUS_PAGES: "true"
Using the scripts
partial to load scripts specific to a route
If a frontend web app requires extra custom scripts to be loaded specific to a route
then you can use github.com/unrolled/render partial
nested templates.
For example, you could have a peer dependency npm package like mapbox-gl
& dynamically
load that only for pages displaying a map. Because we have defined a {{ partial "scripts" }}
in
the main.tmpl
file in this repo, we can use this partial in each frontend that declares a {{ define "scripts-<TEMPLATE_NAME>" }}
For example, in Area Profiles frontend web app /areas
endpoint renders a area-summary.tmpl
template file.
Therefore, we must use the partial name follwed by the the frontends tempalte name: "scripts-area-summary"
{{ define "scripts-area-summary" }}
<script src="/assets/dist/mapboxGL.bundle.js?v={{ .Version }}"></script>
<script src="/assets/dist/areaLanding.bundle.js?v={{ .Version }}"></script>
{{ end }}
Read more about the Unrolled's partial
function here
Contributing
See CONTRIBUTING for details.
License
Copyright © 2021, Office for National Statistics (https://www.ons.gov.uk)
Released under MIT license, see LICENSE for details.
Documentation ¶
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Render ¶
type Render struct {
PatternLibraryAssetsPath, SiteDomain string
// contains filtered or unexported fields
}
func New ¶
New returns a render struct and accepts any rendering client that satisfies the Renderer interface
func NewWithDefaultClient ¶
func NewWithDefaultClient(assetFn func(name string) ([]byte, error), assetNameFn func() []string, assetsPath, siteDomain string) *Render
NewWithDefaultClient returns a render struct with a default rendering client provided (default: unrolled/render)
When the siteDomain argument contains "localhost", then the rendering client will be instantiated in "development" mode. This means that templates are recompiled on request. Any updates made to your templates can then be viewed upon browser refresh, rather than having to restart the app.
func (*Render) BuildPage ¶
BuildPage resolves the rendering of a specific page with a given model and template name
func (*Render) NewBasePageModel ¶
NewBasePageModel wraps around the model package's NewPage function, but injects the assets path and site domain from the render struct. This is to negate the need for the caller to have to provide these values for every new page created in a frontend service