Make sure you have Node v.11 or above installed.
npm install
Copy .env.default
to .env
if it exists.
To build an optimized version of the application in /dist/
use command:
gulp build:production
or just use shortcut:
gulp
Deploy the app and start the middleware server with live reload:
gulp serve
Build settings located in config.development.js
and config.production.js
.
Webpack configuration located in webpackConfig.development.js
and webpackConfig.production.js
.
The locale can be switched using the pug.locale
parameter in build config and can override with FORCE_LOCALE
environment variable.
The configuration files can be switched using the NODE_ENV
environment variable.
├── /dist/ # Production directory (minified, optimized and compiled files)
└── /src/ # The source code of the application
├── /icons/ # SVG icons
├── /js/ # JavaScript source
├── /locales/ # JSON localizations strings
├── /pug/ # Pug templates
└── /_includes/ # Pug partials
├── /scss/ # SCSS styles
└── /templates/ # SCSS templates for generator tasks (icons, sprites, etc..)
└── /generates/ # Generated styles
├── /sprites/ # Sprite raster images
├── /static/ # Root of static files (fonts, images, videos, etc..)
├── /tmp/ # Temporary served files
├── .env # Environment variables
├── .editorconfig # IDE style configuration
├── babel.config # Babel config
├── config.development.js # Development build configuration
├── config.production.js # Production build configuration
├── webpackConfig.development.js # Webpack development configuration
├── webpackConfig.production.js # Webpack production configuration
├── package.json # Project meta and dependencies
gulp serve
deploy the app and start middleware server with live reload
gulp build
build the app in /dist/
with current environment
gulp build:production
build the app to /dist/
with force production environment
gulp pug
compile Pug files
gulp sass
compile Sass files
gulp js
build JS with Webpack + Babel
gulp sprites
make spritesheet based on sprites in /src/sprites/
gulp svgsprite
make svg spritesheet based on icons in /src/icons/
gulp copy:static
copy static files from /src/static/
to /dist/
gulp browsersync
start browser sync server
gulp watch
start watching stream
gulp clean
remove temporary files
gulp clean:dist
clean directory /dist/
Boilerplate use Pug as an HTML Preprocessor.
The following options are available in the build configuration:
parameter | type | description |
---|---|---|
locale |
string |
default locale |
ext |
string |
extension of .html files |
pugOptions |
object |
compiler options |
fetch |
function |
callable to fetch external data |
templates |
array |
templates map |
The following constants are available in each template:
variable | type | description |
---|---|---|
__ |
object |
current locale data |
$$ |
object |
fetched data (only if use fetch) |
ENV |
object |
environment variables |
NODE_ENV |
string |
current NODE_ENV |
PACKAGE |
object |
package.json contents |
LOCALE |
string |
current locale |
$ |
string |
current page key (only in templates) |
All locales should be stored in ./src/locales/{LANG}/*.json
.
Builder merges all .json
files from current locale directory into one object, and you can access it from __
constant in each template.
The locale can be switched using locale
parameter in build config and can override with FORCE_LOCALE
environment variable.
###Styles
Boilerplate use Sass as an CSS Preprocessor.
Autoprefixer, clean-css and RTLCSS (disabled by default in config) is also included. Clean-css disabled by default in the development environment to increase assembly speed.
Entrypoint by default: ./src/scss/main.scss
.
The following options are available in the build configuration:
parameter | type | description |
---|---|---|
maps |
boolean |
use Sourcemap |
autoprefixer |
boolean |
use Autoprefixer |
rtl |
boolean |
use RTLCSS |
cleanCss |
boolean |
use clean-css |
sassOptions |
object |
node-sass options |
cleanCssOptions |
object |
clean-css options |
autoprefixerOptions |
object |
Autoprefixer options |
Styles are written in .scss file format.
A sass-mq
library is used to generate media query mixins. The breakpoints are defined in _variables.scss
, in the $mq-breakpoints
object. Media queries use mobile-first approach. Check sass-mq documentation for more info.
Example use:
@include mq(laptop) { // wider than 'laptop' breakpoint
background-color: red;
}
@include mq($until: tablet) { // narrower than 'tablet' breakpoint
background-color: yellow;
}
@include mq($from: tablet, $until: desktop) { // between 'tablet' and 'desktop' breakpoints
background-color: green;
}
Use CSS Grid for your grid needs. There is nothing special about the way we use it except Jumpstart provides to predefined variables called $gutter-small
and $gutter-big
. Use these to keep the grid gaps consistent throughout the modules.
Example use:
.my-module__items {
display: grid;
gap: $gutter-small;
grid-template-columns: minmax(100px, 1fr);
@include mq(desktop) {
gap: $gutter-big;
grid-template-columns: repeat(2, minmax(100px, 1fr)) 2fr;
}
}
All svg icons should be stored in ./src/icons/
.
Make sure the shapes do not use a fill
and stroke
properties, so that you can dynamically change the color in css.
To directly compile svg spritesheet use command:
gulp svgsprite
Spritesheet stored in:
{WORKDIR}/assets/img/sprites/svgsprites.svg
.
Svg sprites also generated scss:
./src/scss/generated/svgsprites.scss
Make sure to include it in ./src/scss/main.scss
.
To use icon in Pug use mixin:
+svgicon("ICON_NAME", insertinline = true | false)
All sprites should be stored in ./src/sprites/
. @2x (retina)
icons also supported.
To directly compile png spritesheet use command:
gulp sprites
Spritesheet stored in:
{WORKDIR}/assets/img/sprites/sprites.png
.
{WORKDIR}/assets/img/sprites/[email protected]
.
Sprites also generated scss:
./src/scss/generated/svgsprites.scss
Make sure to include it in ./src/scss/main.scss
.
To use sprites in pug:
.my-sprite.-NAME
The scripts system is based on vanilla javascript and vue.js. By default vue.js is disabled and has to be enabled by uncommenting all the lines that are anotated with "Uncomment to enable Vue.js components"
scripts
directory is split into four main sections:
Folder | Description |
---|---|
bootstrap |
Code used to initiate the system and register all components |
components |
Vanilla and Vue.js components |
models |
Model files containing a reusable logic used in the components |
store |
A vuex store instance to define global variable storage |
Dev talks video: Scripts - Introduction
Example load-content.js
file from the video: load-content.js
Use init
folder to register your components and global models.
Each component (vanilla or vue) can be registered as a static or async component. Async components will be downloaded as separate files which helps to keep the main.js filesize down but results in a longer time until the script is initiated, so choose what's the best option on a case-by-case basis.
Most of the models will be imported in one of the components, as they are mostly used to add a logic layer to the component. In case you need a model that's not connected to any component but it's required to run at the page load - you may import it in the init/global-models.js
file.
Use vendor
folder to register all the external dependencies, like polyfills or global libraries.
This is where most of your code will live - you can decide if you want to create a vanilla js or vue.js component. Whenever possible use vanilla.js as it will usually provide better performance. Use vue.js for more complicated components.
Components are only instantiated when there is a DOM element that triggers them. To instantiate a component on a DOM element add this data attribute: data-component='{"component": "component-name"}'
. In case of vue components an existence of data-component
is enough, as the component name is derived from the DOM node name and the default value for the factory
setting is vue
.
Example of vanilla script instantiation:
<div data-component='{"component": "vanilla-example-one"}'></div>
Example of vue.js script instantiation (follow next step to enable them in your project):
<vue-example-one data-component='{"factory": "vue"}'></vue-example-one>
Component is by default initialised when the browser has free resources, which can cause some delay in the component load time. If you want to force the component initialisation as soon as possible for critical components - use a "immediate": true
parameter, i.e.:
<div data-component='{"component": "header", "immediate": true}'></div>
If you want to ignore the component initialisation on page load (i.e. because you want to manually initialise it later) - use a "ignoreOnPageLoad": true
parameter, i.e.:
<div data-component='{"component": "map", "ignoreOnPageLoad": true}'></div>
If you want to initialise previously unintialized components inside a specific container, use following method:
import { parse } from 'models/utils/app';
// ...
function initalize () {
parse(containerEl);
}
To enable Vue.js components in your project search for the following string in your scripts
directory: "Uncomment to enable Vue.js components".
Then uncomment all three occurences of the code next to that string.
There is an icon
component prepared to display the icon on the page.
Example use (inline mode):
<template>
<div class="vue-example-one">
<icon class="vue-example-one__icon" type="inline" v-html="checkmarkInlineIconSvg"></icon>
</div>
</template>
import checkmarkInlineIcon from 'InlineIcons/checkmark-inline.svg';
export default {
data () {
return {
checkmarkInlineIconSvg: checkmarkInlineIcon,
};
},
};
Example use (symbol mode):
<template>
<div class="vue-example-two">
<icon class="vue-example-two__icon" name="checkmark-symbol" type="symbol"></icon>
</div>
</template>
Models serve as a logic layer for components, which means you can reuse the same logic no mather what the component is (components serve as a "view" layer and models as "logic" layer).
I.e. a articles
model can contain a method to fetch a list of articles from a remote server and return the list in a sorted order. This logic can now be shared by article-teasers
and featured-articles
components that provide a completely different layout but rely on the same underlying data. If the model exports a fetchAndSortArticles
method it can be used in the component in a following way:
import { fetchAndSortArticles } from 'models/articles';
...
function getArticles () {
let articles = fetchAndSortArticles();
}
Models should be used to store the logic and make keep the component code clean even if the logic is not planned to be reused by other components.
Store provides a way to share data between various components and models in the system. The store is not included in the final script package until at least one script imports it to it's scope (import store from Store
).
The store system is based on the vuex
package. Check vuex documentation for more details.
System provides directory aliases for import
statements in order to simplify the import structure.
I.e. you can use import { fetchAndSortArticles } from 'Models/articles';
instead of import { fetchAndSortArticles } from '/templates/src/assets/scripts/models/articles';
Alias | Path |
---|---|
Scripts | templates/src/assets/scripts |
Models | templates/src/assets/scripts/models |
Components | templates/src/assets/scripts/components |
Bootstrap | templates/src/assets/scripts/bootstrap |
Store | templates/src/assets/scripts/store |
InlineIcons | templates/src/assets/icons/inline |
A full overlay (popup) system
Trigger overlay from HTML:
With target="_top"
attribute:
<a href="your-popup-content.php" target="_top">Open overlay</a>
With js-overlay__link
class:
<a href="your-popup-content.php" class="js-overlay__link">Open overlay</a>
Trigger overlay from JS:
import { openOverlay } from 'Models/overlay';
...
openOverlay(url);
openOverlay
can take a couple of parameters. The first one called contentHolder
can be:
- url
- element (if the string starts with "#"). I.e. "#id-of-dom-block"
- html (you can supply html that should be displayed). In that case specify a second parameter as
'html'
.
The overlay component has some more options. Please check the overlay.js
file directly to check how it works in detail.
The content of the overlay should be wrapped in a following div:
<div class="overlay__content overlay__content--default js-overlay__content">
...
</div>
where the --default
modifier sets the width of the content box. Add your additional sizes in the css file.
If you want to show a "x" button in top right corner add this element in the overlay content area:
echo generate_component_icon([
'name' => 'close',
'type' => 'symbol',
'class' => 'overlay__close js-overlay__close'
]);
To simplify wrapping the overlay content in the html syntax described above there is a helper component called overlay-wrapper
.
Example use:
echo generate_component_overlay_wrapper([
'content' => $content, // html inside the overlay
'close_icon' => false, // default: true
'size' => 'narrow', // default: 'default'
]);
Dev talks video: Scripts - Overlay system
emit-debounced-events.js
model emits a window-resized
event that is debounced. Listen to this event instead of the generic window.onResize
event.
breakpoints.js
model allows you to:
- get list of currently active media query breakpoints (
currentlyActiveBreakpoints
) - listen to a
active-breakpoints-change
event that is triggered every time window width is reaching a new breakpoint. A list of active breakpoints is transmitted as a detail object of that event.
Instead of using fetch
directly use the call
function imported from http-request
model.
Example:
import { call } from 'models/http-request';
...
try {
const response = await call(url);
if (response.status === 'success') {
...
} else {
...error handling
}
} catch (e) {
console.error(e);
...error handling
}
Show/hide a preloader inside an element
import { showPreloader, hidePreloader } from 'models/preloader';
...
const options = {
size: 'small',
color: 'primary'
}
showPreloader(myDomElement, options)
options
parameter is an object which can specify additional color
and size
parameters.
This will add classes to the main element, like so: preloader--your-color
and preloader--your-size
that you can later style in your _preloader.scss
file.
Dim page (i.e. when you show a side drawer)
import { dimPage, undimPage } from 'models/dimmer';
...
dimPage();
...
undimPage();
Lock page scrolling (i.e. when you show a side drawer)
import { lockPage, unlockPage } from 'models/locker';
...
lockPage();
...
unlockPage();
By default Front-End Jumpstart supports only modern browsers. If you need to support IE11 open templates/src/assets/scripts/bootstrap/vendor/index.js
file and uncomment the lines with IE11
at the end.
Browsersync creates a small server for local development with live reloading. If Browsersync detects changes in code, it makes a local rebuild and reloads the page (complete or partial).
To start a project on a local web server with enabled livereload services use command:
gulp serve
To start the server without building the project, use the command:
gulp browsersync
In build configuration you can configure browsersync options.