iwillberemovedaftertesting v0.0.2
ui.frontend-server
Overview
Fast, flexible and extensible web-server for Component-Based architecture/applications. Best for local development and quickly provide POC for business. Based on express.js web-server. Easy way to quickly setup and start server for frontend developers, who doesn't want to spend a lot of time to do it.
How to use
Install
1) Install node and npm. 2) Create simple package.json (npm init) 3) Install ui.frontend-server as dependency for you project:
npm i ui.frontend-server --save-dev
Quick Start
1) Create demo project(structure):
npx uifrontend-server create-demo-project
2) Start server:
npm run server
3) Easiest! You can make a coffee :)
Engine
Project based on express.js web server with simple, but useful middleware.
Template engine for pages: express-dot-engine with some improvements.
Default routing based on folder/file(see below) structure under ${PROJECT_ROOT}/server/views/pages/
.
Server supports pages, layouts, inheriting pages, partials, static resources, middleware, multiprojects and reusable components.
Configuration
Configuration object should be passed as a first argument into .start()
function (see server/start.js
).
See description and possible options in the source code: ${SERVER_SOURCE_CODE}/config/default.js
Routing based on file system
graph TD
ROOT{URL_PATH is empty or '/'?}
404(Render 'server/views/404.html')
ROOT --> |Yes| Redirect_to_defaultPageUrl( Redirect to '/index.html' )
ROOT --> |No| NoEmptyPath{URL_PATH contains '*.html?'}
NoEmptyPath --> |No| IsFolder{Folder 'server/views/pages/URL_PATH/' exists?}
IsFolder --> |No| 404
IsFolder --> |Yes| Redirect_to_defaultPageUrl_underFolder(Redirect to 'URL_PATH/index.html')
NoEmptyPath --> |Yes| Html{HTML File 'server/views/pages/URL_PATH' exists?}
Html --> |Yes| RenderPageHTML(Render it)
Html --> |No| IsIndex{Is request to 'index.html'?}
IsIndex --> |Yes| RenderIndex(Render 'server/views/index.html')
IsIndex --> |No| 404P(Render 'server/views/404.html')
Page
Overview
All server pages should be placed under server/views/pages/
folder. It can be used as a regular html page or can be generated but using built-in template engine.
Page template structure
HTML page structure contains 2 sections:
- Configuration section: YAML at the top. Configuration object(defined between ---) available as
layout
object. Best practice: use it for global layout configuration(title, body classes, scripts for injection). Default values better to defined in parent page (layout option). Properties are inheritable. layout property is reserved and used for showing what is html page to use as a parent.
Example:--- layout: '%%PATH_TO_VIEWS%%/layouts/html5.html' title: My Page bodyClass: my-page myCustomNumbers: [1, 2, 3] --- {{##myCustomBlock: <!-- I will available as "layout.myCustomBlock" --> #}} {{##body: <h1> {{! layout.title }} </h1> <div class="url"> {{= page.location.path }} </div> <ul class="nums"> {{~ layout.myCustomNumbers :num }} <li> {{! num }} </li> {{~}} </ul> #}}
- Definition Blocks Section: Section with page blocks. Best Practice: Split layout with important blocks(see:
server/views/layouts/
files). Each block available as property inlayout
global object. Example: for previous codelayout
object will contain:body
,myCustomBlock
,title
,bodyClass
,myCustomNumbers
properties. Minimum 1 definition block (between{{##blockName: #}}
) required.
Small overview about features you can find in Templates section.
API: Page object
page
object provide properties for current page rendition(request). That object available in all pages under server/views/
folder and for each component (in template).
page.renderComponent(componentName, componentOptions)
: Render component by name with component options. Example:{{= page.renderComponent('demo/hello-world', { data: 'example1' }) }}
will render componentsrc/demo/hello-world/
with datasrc/demo/hello-world/data-example1.json
and pass{ data: 'example1' }
as options.page.request
: Express request objectpage.response
: Express response objectpage.location
: Request url objectpage.getPageTitle(priorityTitle)
: Calculating page title by request url. IfpriorityTitle
defined, then it will be used. Best practice: definepriorityTitle
as a yaml property at the top of the page.page.resolveURL(url)
: Convert url from absolute to relative for request url. Example: request is:/my-project/examples/hi.html
.page.resolveURL('/images/log.png')
will return./../../images/log.png
.page.invokeController(controllerName, ...args)
: Run node JS file fromserver/controllers/${controllerName}.js
. Controller should export function.this
context will bepage
object.page.getFile(fileName)
: Read file. Path should be relative toserver/
folder.page.initComponent(componentName, componentOptions)
: The same aspage.renderComponent
, but doesn't generate html(it just create Component object).
Components
All components should be placed under src/
folder. Best practice: Place all files(related with your component) into component folder. No requirements regarding folder structure, but we recommend to use minimum 2 levels: src/${groupName}/${componentName}/
.
It will help in the future to customize existing components(example: will be created new version of buttons or product cards or new page will be created or redesign existing components).
Component folder structure
Only 1 required file is config.json
. It should be placed in component folder. We recommend to follow next structure:
/src
/${groupName}
/${componentName}
/ui <- we recommend put UI resources(js, css(less, scss), images, templates etc. what are using in browser) into "ui" folder
${componentName}.js (optional)
${componentName}.less (.scss) (optional)
${componentName}.hbs (template which is using in browser) (optional)
...
config.json <- JSON file with component configuration. Required.
data-***.json <- JSON files with predefined data. Helps to prevent copy/paste data between usages. Optional.
${componentName}.html <- Server side component template(component rendition). Any name can be used. See "config.json > view" property.
${componentName}Controller.js <- Any server side js logic related with component. Optional.
/${componentName2}
...
config.json
config.json
file reserved properties (see demo project: "/src/demo/header/config.json"):
view
:(required) Path to server side component html template.controller
:(optional) Path to js file with server side logic related with component. File should export object(will be prototype for your component object).init()
function is required, but you can add another methods for you component and then call them in template. See demo project: "/src/demo/header/HeaderController.js"data
:(optional. deprecated). Contains predefined data for component. Better to store data in data-***.json files.
API: Component object
component
object available in component server side templates. You can extend object with controller
property in config.json
file.
component.renderComponent(componentName, componentOptions)
: The same aspage.renderComponent(componentName, componentOptions)
. See: "API: Page Object" sectioncomponent.initComponent(componentName, componentOptions)
: The same aspage.initComponent(componentName, componentOptions)
. See: "API: Page Object" sectioncomponent.render()
: Generate HTML for component and fill with data.component._getFile(filePath)
: Get file content. Path should be relative to component folder.component.config
: JSON from "config.json". See description in: config.json section.component.data
: JSON from "data-*.json" file or "data" value (if object) from component options. See description in: Component options** section.component.name
: Component name.component.options
: Component options (second argument in call .renderComponent(componentName, componentOptions)). See description in: Component options section.component.mayCustomMethod(arg1, arg2, ...)
: Any method declared in object exported by js defined via "config.json > controller" property.
Component options
Any object can be passed. Reserved properties:
data
: Dataset for component(pre filled data). Can be string or object. Accessible viacomponent.data
property.string
: Dataset will be read from ${componentName}/data-${dataValue}.json file. You can use @extend: "path/to/data-parent.json" notation. It helps to prevent copy-past data between json files.object
: Will be used as it is.
Component view (template)
Currently our system allow to use only doT.js templates. Small overview you can find in Templates section.
Next objects are available in component view:
page
: page object. See: "API: Page Object" section.component
: component object. See: "API: Component Object" section.data
: Component data. Shortcut forcomponent.data
.options
: Component init options. Shortcut forcomponent.options
.partial(data)
: Function to inject HTML from another file.
Templates
Small overview what features can be used in our page & component templates(views). Full documentation you can find here.
{{ js_code }}
: Evaluate javascript code on server side. Example:
{{
let myFileContent = component._getFile('./my-file.txt');
console.log(`Request to: ${page.request.originalUrl}`);
const rndm = Math.random() * 1000;
}}
{{= expression }}
: Interpolation. Print expression result. Example:
File content: {{= myFileContent ))
Random number: {{= Math.random() }}
Button component: {{= page.randomComponent('demo/button', { data: { title: 'My button' } }) }}
{{! expression }}
: Interpolation with encoding. The same as regular interpolation, but safer(prevent script injection).{{? condition }}
: Conditionals. Example:
{{? data.image }} <img src="{{= data.image }}" alt="{{= data.alt}}" /> {{?}}
{{? Math.random() > 0.5 }}
<!-- if: number is bigger than 0.5 -->
{{??}}
<!-- else: (0.5 and lower) -->
{{?}}
{{~ arrayList :item:index }} ...iteration block... {{~}}
: Array iteration(arrayList.forEach(function (item, index) { ...iteration block... });
).item
andindex
can be any variables.
<ul>
{{~ ['hello', 'world', 'frontend'] :word:index }}
<li> {{! index }} {{! word }} </li>
{{~}}
</ul>
Command Line Interface
- create-demo-project: Create demo project.
FAQ
Will be updated. If you have any questions, you can ask with "Issues".
Features
- File-based routing
- Flexible templates
- Pages
- Layouts
- Components
- JSON data for components
- Controllers
- OOTB BrowserSync integration
- etc.
ui.frontend-server