# Laravel Scripts

![npm (scoped)](https://img.shields.io/npm/v/@acanto/laravel-scripts?style=flat-square&color=EA2C65)

Frontend code resides by default in the `src` folder placed in the root of the project. Everything gets compiled and assembled in the standard Laravel folders `/resources` and `/public`, whose content is gitignored.

## Installation

It is recomended to start a project by running:

```bash
npx @acanto/create-laravel-app myproject
cd myproject
npm start
```

## Setup project

After `npm install` you can either run `npx acanto start` for full development of assets and templates or the lighter `npx acanto tpl` to just automatically watch and copy the template files to the destination theme folder. This latter command is thought to be used either by backend developers or to quickly do some _layout only_ changes. The command `npx acanto tpl` is limited to watch over template files (blade and php) and build them on change, allowing to develop a skeleton of the website without the whole compilation of the assets. This command is always run when launching the heavier `npx acanto start`.
Pages can be created at any time running `npx acanto route route-name` or `npx acanto route route-one,route-two` to add multiple routes, existing routes will not be overwritten, but be careful of using a new **unique route name**.

## Workflow commands

From your root folder run `npx acanto help` or `npm run help` to view the available commands and their description.

## CI

When deploying use the CI scripts:

```bash
# install dependencies
npm ci --loglevel silent

# build the production code ready for deployment
npx acanto deploy --env {dev|staging|production} --mode ftp --folder ./{myproject} --host {myhost} --username {myuser} --password {mypwd}
```

Note that to use `npm ci` you [must have](https://docs.npmjs.com/cli/ci.html#description) a `package-lock.json` file in your source repository.

## Configuration

All configuration is inside a standalone package `@acanto/laravel-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.

### package.json

Some shortcuts are automatically add to your `package.json`, for instance:

```json
  "scripts": {
    "start": "npx acanto start",
    "build": "npx acanto build",
    "test": "npx acanto test"
  }
```

Each project can override some basic configurations of the scripts from the `config` section of it `package.json`. The following configuration is required and automatically injected if missing, it can and should be customised accordingly to your specific project:

```json
  "config": {
    "favicons": {
      "background": "#fefefe"
    }
  }
```

### .env

This file (and its variants `env.example`, `.env.dev`, `.env.stage`, `.env.production`) will be autogenerated if not found trying to guess the values.

Some useful variables dependent on the environment are automatically made **always available to all** js and scss files.

Inside all SCSS files you have for instance:

```scss
$DEV: true; // or false
$ENV: "dev" | "stage" | "prod" | "preprod"; // as defined in the `APP_ENV` of the current .env file
$SRC_ASSETS: "../assets";
$URL_ASSETS: "https://myproject.com/themes/acanto/assets";
$SRC_FONTS: "../assets/fonts";
$URL_FONTS: "https://myproject.com/themes/acanto/assets/fonts";
$SRC_IMAGES: "../assets/images";
$URL_IMAGES: "https://myproject.com/themes/acanto/assets/images";
$SRC_SVGICONS: "../assets/svgicons";
```

Inside all JS files you have for instance:

```js
const __DEV__ = true; // or false
const __ENV__ = "dev" | "stage" | "prod" | "preprod"; // as defined in the `APP_ENV` of the current .env file
const __URL__ = "https://myproject.com";
const __API__ = "https://myproject.com/api";
const __ASSETS__ = "https://myproject.com/themes/acanto/assets";
const __FONTS__ = "https://myproject.com/themes/acanto/assets/fonts";
const __IMAGES__ = "https://myproject.com/themes/acanto/assets/images";
```

All `.js` files of your project will get automatically IDE support for these variables (at least in VScode):
![js-constants-autocomplete](https://raw.githubusercontent.com/kuus/acanto-static/master/acanto-workflow/js-constants-autocomplete.png)

## Folder structure

Each path used in the build scripts can be overridden in the specific project `package.json` file, but the ideal and default folder configuration assumed is the following:

```yaml
  src/ # sources of all the frontend that gets compiled
    assets
      images/ # all images (will be compressed)
      media/ # all video and audio files
      svgicons/ # svg images that will be turned automatically in an icon font
      fonts/ # custom fonts
      favicon.png # required image to automatically generate all favicons
    config/ # configuration files
      placeholders.scss # scss config (always accessible from any other file)
      mixins.scss # scss config (always accessible from any other file)
      variables.scss # scss config (always accessible from any other file)
      index.js # js config (globals, settings, ecc.)
    components/ # decoupled components to use across routes
      Mycomponent/ # component folder uses component name
        index.js # component script
        index.php # component php template part
        index.scss # component style
        index.twig # component twig template part
    routes # route specific and inlined in the corresponding template
      home
        index.js # route specific and scoped scripts
        index.php # route specific controller
        index.blade.php # route specific template
        index.scss # route specific and scoped styles
        index.json # route specific static json data
    layouts # usually just one for project, but more layouts can e created and used independently within the same project with their entrypoint assets separately compiled
      main # usually the standard layout to use in all templates
        index.js # entry point with all common js/scss imports for this layout
        index.scss # entry point with some simple scss for this layout
        index.blade.php # base template for this layout
    utils # folder to drop-in js/scss files, event templates can be here, these are copied automatically to the /resources/components/utils folder allowing usage with e.g. <x-utils-some-utility">
      some-utility.blade.php # will be copied to /partials/utils
      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
  public/
    assets/ # compiled static assets (scripts, styles, images, fonts, etc.) (.gitignored, DO NOT EDIT!)
  resources/ # (.gitignored, DO NOT EDIT!)
    translations/ # translated strings .csv files
    layouts/ # php layout views
    routes/ # php page views
      home/ # route folder example
        index.blade.php # page specific template
    components/ # all components, automated, core views and utils to use across pages. Only files from `src/components` will follow PascalCase <x-MyComponent> style syntax
      MyComponent.blade.php # component template
      MyComponent.php # component "controller" (optional)
      assets-body.php # automated views get copied here too
      seo-meta.php # core views get copied here too
```

Here in details:

### src/assets

This folders contains all static assets that gets manipulated, optimized and copied over the October's default `themes/acanto/assets` folder, they are divided as such:

- _src/assets/fonts_: all fonts files, they will get automatically optimized and content hashed. An `.htaccess` with long term expiration headers will be placed in this folder on build.
- _src/assets/images_: all static theme images, they will get automatically optimized and content hashed. An `.htaccess` with long term expiration headers will be placed in this folder on build.
- _src/assets/images/placeholder.png_: required image used as fallback for broken images.
- _src/assets/media_: all static theme video, audio and other files, their filenames will **not** be hashed. No `.htaccess` will be placed here.
- _src/assets/svgicons_: all svg icons that will be optimized and inlined in an automated component `<x-svgicons/>` to be usually included in `src/layouts/main/index.blade.php`. They will be later used in the templates by using the handy `core` `<x-icon glyph="arrow_left"/>` component
- _src/assets/favicon.png_: required png image (1024x1024 is the optimal resolution) used to automatically generate all needed favicons. The script build an automated `<x-favicons/>` component to be usually included in `src/layouts/main/index.blade.php`

### src/components

This folder conain **components** that are quite specific pieces of UI which are usually reused within the same project and can, but not necessarily need, to be reused accross different projects. They should be responsible of specific functionalities and should be configurable from outside enought to allow their reuse in the same project. Usual use cases for components are pieces of UI like the `Header`, the `Footer`, `Card`s, `Slider`s, ecc.

### src/config

The `scss` files here (`functions.scss`, `mixins.scss`, `variables.scss`, `placeholders.scss`) are always made automatically available to the whole project files. This is also the place where to put JavaScript global **configurations** such as breakpoints, various forms of data, URLs etc.

### src/routes

This folder contains **Routes** code that is always scoped and outputted only to its specific template. So by default JS and SCSS code written here cannot interfere with other routes (or pages).

### src/utils

Here we should put templates mostly `js/scss` **utilities** to use and import where needed from either `layouts`, `components` or `routes`. This is also a good place for tiny utils templates`.twig` if needed, they will be watched and copied over to the `partials` directory and therefore become available in templates to use with `<x-utils-my-util />`

### src/vendor

This is the folder where to put **custom vendor** files that cannot for various reasons be added and managed by `npm`. A common use case is the presence of the premium `gsap` package that cannot be installed from the public `npm` repository.

## Core sync

For **core** elements we mean components that are very generic and of common use case. They are usually included repeatedly in the same page and across the same website. Their flexibility should allow to use them even without alteration across different projects. They should be in fact responsible of basic and common elements and UI like `forms`, `images`, `buttons`, `typography`, ecc. These components' templates are always automatically syncronised from the library [`@acanto/core`](https://www.npmjs.com/package/@acanto/core) with the command `npx acanto core-sync` who places them directly in the gitignored `resources` folder.

## Github workflow

- On branch `master` resides the stable `dev`elopment code
- On branch `staging` resides the code deployed on the `staging` enviroment e.g. `myproject.acanto.net`
- On branch `production` is the production code publicly available at e.g. `myproject.com`
- Development happens initially on `master` and then, when more developers come in, specific work is done on specific branches branched from `master`. It is important to often pull from there with `git pull origin master` to avoid problematic merge conflicts.

## Caveats

### Windows

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 [source](https://stackoverflow.com/a/44389219)
- `C:\Program Files\nodejs` to run node scripts from the current directory

## Workflow features

- Hot Module Replacement
- JS/SCSS modules bundling with `webpack`
- SCSS compilation with `sass` and `postcss`
- SCSS optimization combining media queries with `postcss-sort-media-queries`
- ES6 syntax support with `babel`
- CSS and JS files automatic splitting and cache busting (content hashed), this allows to long term expire-headers in the `.htaccess`
- SCSS and JS sourcemaps
- Route and Layout specific JS/CSS through October's partials
- Assets minification
- Images minification and compression
- SVG inline icons automatic generation from `svg` images
- Favicons auto-generation from single image
- License banner for compiled `css` and `js` files
- Route and Component generator with `.js`, `.scss`, `.twig` and `.php` templates

## Development of this package

### Notes

About _assets inlining_, CSS is inlined if the file size is minor than 50kb, as the AMP specification suggest. JS inline threshold is set to just 2kb instead, see [this article](https://v8.dev/blog/cost-of-javascript-2019#guidance).

About _optimization_ evaluate the use of [compression-webpack-plugin](https://github.com/webpack-contrib/compression-webpack-plugin)

About _gzip compression_ see October's not-including-it-by-default reasons here https://github.com/octobercms/october/pull/1896, https://github.com/octobercms/october/pull/1885, https://github.com/octobercms/library/pull/201/commits/db2dec55ed7d42201f92b59e1de74b5c3196841c, https://github.com/octobercms/october/pull/1885/commits/86ca0c7e8d79a4a8f0662203b0b04cf549b6fc63, https://github.com/octobercms/october/issues/1847, https://octobercms.com/forum/post/assets-gzip-compression

About _polyfills_ babel and webpack see: https://github.com/babel/babel-loader#note-transform-runtime--custom-polyfills-eg-promise-library, https://github.com/zloirock/core-js#babel, https://babeljs.io/docs/en/next/babel-preset-env.html#how-does-it-work, https://www.npmjs.com/package/polyfill-library

### Bash utilities

- Run `start` with more RAM `node --max_old_space_size=8192 node_modules/@acanto/laravel-scripts/bin/laravel-scripts.js start` (@see [similar issue](https://github.com/angular/angular-cli/issues/13734))

### Todo

- [] Environments might be made configurable through a custom `config.environments` value in the package.json, where each key is the environment `name` and the value is its `branch`, the default values would be:

```json
  "config": {
    "environments": {
      "dev": "master",
      "staging": "staging",
      "production": "production"
    },
```

- [x] Run `php artisan view:clear && composer dump` after generate component and after `core-sync` (not needed with `ps-4` autoloading mechanism)
- [] autogenerate dummy `translations.csv` files based on cms api response in case they miss
- [] autogenerate `public` folder either if it miss or always (in case of it being gitignore..decide which one)
- [] autogenerate `storage` folder (just gitignore it completely)
- [] autogenerate `artisan` file (and gitignore it)
- [] `check` should check that there is a `/vendor` folder, otherwise run `composer install`
- [] Add this command somewhere to the end of your deploy script (I put it just after artisan up) `php artisan opcache:clear` [source](https://medium.com/appstract/make-your-laravel-app-fly-with-php-opcache-9948db2a5f93)

#### .htaccess

For a good explanation on how to manage redirects SEO friendly see [How to force https, www and a trailing slash with one redirect](https://www.danielmorell.com/guides/htaccess-seo/redirects/https-www-and-trailing-slash).

The following might need to be put at the top of the `.htaccess` to force http protocol for the endpoints called by the runners during deploy:

```htaccess
# Force http for deployer handler
RewriteCond %{HTTPS} on
RewriteCond %{THE_REQUEST} /deployer.php
RewriteCond %{THE_REQUEST} /_/hooks/deploy/end/
RewriteRule ^ http://%{HTTP_HOST}%{REQUEST_URI} [NE,END,L,R=301]
```
