README
October scripts
Installation
First go into the project root directory cd myproject
, then:
npm i @acanto/october-scripts --save-dev
Usage
First you need to add to your project's package.json
the following:
"scripts": {
"start": "october-scripts start",
"test": "october-scripts test",
"page": "october-scripts page",
"comp": "october-scripts component",
"build": "october-scripts build",
"setup": "october-scripts setup",
"clean": "october-scripts clean",
"deploy": "october-scripts deploy"
}
Then from your root folder you can run:
# install dependencies
npm install
# run local development server with live reload
npm start
# generate a template, style and script for a specific page
npm run page my-page-name
# generate a template, style and script for a specific component
npm run comp my-component-name
# build the production code and start a local server running it
npm run test
# build the production code
npm run build
# clear OctoberCMS caches
npm run clean
# extract class names from page template and generate .scss file
october-scripts extract-page my-page-name
CI
When deploying run:
# install dependencies
npm install
# build the production code ready for deployment
npm run deploy
Configuration
All gulp configuration is inside a standalone package @acanto/october-scripts
published on npm, the project just uses its package.json
file to configure and run the scripts. In this way a project have only one devDependency
and the scripts can be updated separately from each project, so that every project can benefit from the updates.
.env
This file will be autogenerated if not found trying to guess the values (execpt for the db username and password)
APP_URL=http://localhost/acanto/myproject
# BROWSER_SYNC_HOST=http://myproject.test
DB_HOST=myproject.acanto.net
DB_DATABASE=myproject_db
# DB_USERNAME=myuser
# DB_PASSWORD=mypassword
package.json
Each project needs to set the homepage
entry and can override some basic configurations of the scripts from the config
section of it package.json
. The following configuration is required and needs to change accordingly to your specific project:
"homepage": "https://myproject.com",
"config": {
"favicons": {
"background": "#fefefe"
}
}
Windows caveats
To run the script on windows you might need to go to System Properties
and on Advanced -> Add to Environment variables -> Users -> Path
append the following variables:
C:\Program Files\Git\cmd
in order to be able to install npm packages directly from git remotes instead that from published versions git must be in the path sourceC:\Program Files\nodejs
to run node scripts from the current directory
Features
- Live reload
- JS/SCSS modules bundling with
webpack
- SCSS compilation with
node-sass
andpostcss
- SCSS optimization combining media queries with
css-mqpacker
- ES6 syntax support with
babel
- CSS and JS files automatic splitting and cache busting
- SCSS and JS sourcemaps
- Page specific CSS inlining through October's partials
- Assets minification
- Images minification with
imagemin
- SVG inline icons automatic generation from
svg
images - Favicons auto-generation from single image with favicons
- License banner for compiled
css
andjs
files - Page generator,
.js
,.scss
and.htm
templates - TODO: Prettier for
.htm
templates
Folder structure
Each path used in the gulp tasks can be overridden in the specific project package.json
file (see notes below), but the ideal and default folder configuration assumed is the following:
themes/
acanto/
assets/ # compiled files (.gitignored, DO NOT EDIT!)
layouts/ # twig layout templates
pages/ # twig page templates
home.htm # page specific template
partials/ # twig partials
automated/ # compiled partials (.gitignored, DO NOT EDIT!)
components/ # decoupled components to use across pages
MyComponent.htm # component template
src/ # sources of the assets that gets compiled
components/ # decoupled components to use across pages
MyComponent/ # component folder uses component name
index.scss # component style
index.js # component script
config/ # conguration files
index.scss # scss config (variables, mixins, functions, ecc.)
index.js # js config (globals, settings, ecc.)
pages # page specific and inlined in the corresponding template
home.scss # page specific and scoped styles
home.js # page specific and scoped scripts
utils # utils generic components
animations.scss # utils like styles
animations.js # utils simple script
vendor # custom vendor imports
package-name.js # customised vendor import script
package-name.scss # customised vendor import styles
images/ # all images (will be compressed)
icons/ # svg images that will be turned automatically in an icon font
fonts/ # custom fonts for the specific theme
theme.js # entry point with all js/scss imports
Dev notes
Environment variables
October has a built-in functionality to subsititute the config variables with dotenv-ready code, you can run php artisan october:env
from the root. These change some local configuration files, what we are interested in are config/app.php
, config/database.php
and config/environment.php
.
Cache issues
lftp
manual page. One option would be to use thelftp
option--transfer-all
but that would probably take more time than thetouch
gulp task.- Related to October CMS caching issue see: https://github.com/octobercms/october/issues/446, https://octobercms.com/forum/post/caching-of-partials, https://octobercms.com/forum/post/cached-view-partials-can-not-clear?page=1
CSS/JS inlining
To inline the shared js/css chunks in the HTML we could simply do this:
==
use Cms\Classes\Theme;
function onStart() {
...
$appCssPath = themes_path(Theme::getActiveThemeCode() . "/assets/styles") . "/theme.css";
$this['appCssRelativePath'] = '../assets/styles/theme.css';
$this['appCssFilesize'] = filesize($appCssPath) / 1024;
}
==
{% if appCssFilesize < 52 %}
<style>{{ source(appCssRelativePath) }}</style>
{% else %}
<link href="{{ 'assets/styles/theme.5f616e7af5a515c60829.css'|theme }}" rel="stylesheet" />
{% endif %}
but the fonts relative path breaks, we should give the fonts an absolute path depending on the environment. Plus we should generate a non hashed file with webpack and be careful because with this approach we assume there is only one shared/common chunk, but there might be more with js dynamic imports.