Sage Installation – Update for version 9

  • Update: 4-12-2018

For older versions of Sage see this post

https://github.com/roots/sage

https://roots.io/sage/docs

Changes in Sage 9

  • Laravel’s Blade as a templating engine.
    Learn about Blade. Check out the templates directory.

    You can opt-out of Blade templates by replacing them with regular PHP ones (you could copy over the templates from Sage 8 if you really wanted to).

  • Replaced gulp and Bower with Webpack and npm.
    Bower is dead and all packages should be available on npm.

    Webpack is responsible for:

    • Compiling assets
      • Sass to css with ccsnano
      • ES6 to JavaScript that can be run in today’s browsers with buble
    • Optimizing images with optipng, gifsicle, pngquant, and svgo
  • ES6 for Javascript
    Great resource for learning about ES6: Wes Bos’ ES6 for Everyone
    Convert existing JS to ES6 with Lebab
  • Bootstrap 4
    It’s still in alpha, but there’s so many improvements over Bootstrap 3.
  • PSR-2 coding standards.
    Roots projects switched to PSR-2 last year. Previously we had used a modified PSR-2 ruleset, but we stopped caring about 2-spaces in our PHP files and fully adopted PSR-2.
  • Restructured theme files.
    All theme templates are finally out of the theme root! Our implementation is a little hacky because a 7 year old WordPress Trac ticket still hasn’t landed, but we believe our implementation is the best we can do at this time.
  • Introduced Yarn.
    Yarn is a drop in npm client replacement. With Yarn, the installation of Node dependencies is quicker & the node_modules directory is smaller.

Theme Installation

  1. Make sure all dependencies have been installed before moving on:
    PHP >= 5.6.4 7.1.3 (with php-mbstring enabled)
    – Add the wamp php (at least 7.1.3) to Windows PATH (and no other php in the path).
    – make sure extension=php_mbstring.dll is enabled in the php.ini of the php version you are using (default= enabled)
    Composer (Dependency manager)
    Node.js >= 6.9.x
    – If necessary install Node (with npm). I used the Windows installer here (x64 version)
    Yarn
  2. From your WordPress themes directory, run the following composer command:
    composer create-project roots/sage your-theme-name dev-master

    During theme installation you will have the options to:

    – Update theme headers (theme name, description, author, etc.)
    – Select a CSS framework (Bootstrap, Foundation, none)
    – Add Font Awesome

    Update: Newest version of Sage9 (9.0.5 at the time of writing) gives the following error: 

    TTY mode is not supported on Windows platform

    Solution: run this from the theme directory

    ./vendor/bin/sage meta        # or edit style.css directly
    ./vendor/bin/sage config      # or edit resources/assets/config.json
    ./vendor/bin/sage preset      # Install css framework
  3. Navigate to the theme directory then run yarn, and yarn build (to refresh files):

    yarn && yarn build

    You now have all the necessary dependencies to run the build process.

    About dependencies:
    If you open package.json you’ll see both devDependencies and dependencies that Sage uses. devDependencies are used by the build process, whereas dependencies are packages that are used in the front-end theme assets.

    dependencies includes the front-end options you selected during install, such as Bootstrap and Font Awesome

    "dependencies": {
      "bootstrap": "^4.0.0-beta",
      "font-awesome": "~4.7",
      "jquery": "1.12.4 - 3",
      "popper.js": "~1.11"
    }

————————–

Install WordPress and activate plugins

Optionally import test data with WP Test. See here

Warning when activating i-themes Security:

When activiating this plugin, it will write to your wp-config.php.
This causes an error with the Bedrock config setup and make you website/admin unaccesible.
Solution:
– activate i-themes
– edit wp-config.php -> remove file permissions added by i-themes (we use config/application.php for that)
– WP admin should be accesible again
– Go to i-themes settings-> WordPress Tweaks -> File Editor -> uncheck the box

  • Test by running one of the build commands:
  • Build commands

    • yarn start — Compile assets when file changes are made, start Browsersync session
    • yarn build — Compile and optimize the files in your assets directory
    • yarn build:production — Compile assets for production
  • Additional commands

    • yarn run rmdist — Remove your dist/ folder
    • yarn run lint — Run ESLint against your assets and build scripts
    • composer test — Check your PHP for PSR-2 compliance with phpcs
  • To use BrowserSync you need to update devUrl at the bottom of assets/config.json to reflect your local development hostname.If your local development URL is https://project-name.dev, update the file to read:
    "devUrl": "https://project-name.dev",
  • If you are not using Bedrock, update publicPath to reflect your folder structure:
    "publicPath": "/wp-content/themes/sage/"
  • Problem: no update after blade template changes.  Fixed thanks to this comment:

    I was running into a similar problem, and adding the following lines to module.exports in webpack.config.watch.js solved it:

        devServer: {
            watchOptions: {
                poll: true,
            },
        },
    

    In my case, I believe the issue had to do with my OS’s ability to watch multiple files for changes in the way Webpack/BrowserSync wanted by default.

  • Problem: Console connection error after manual page reload/change. Also the page is switching quickly between unstyled and styled for a few seconds.

    The connection to http://localhost:3000/__webpack_hmr was interrupted while the page was loading.

    Installing a newer version of Node (10.x instead of 6.9) and subsequently node-sass seems to have made the problem far less worse. The unstyled page is only visible for a short moment now. Connection to webpack is still lost, but that might be expected behaviour

  • update: not sure if the text below is relevant anymore.
    By default, Browsersync will use webpack’s HMR, which won’t trigger a page reload in your browser.If you would like to force Browsersync to reload the page whenever certain file types are edited, then add them to watch in assets/config.json.
    ...
      "watch": [
        "assets/scripts/**/*.js",
        "templates/**/*.php",
        "src/**/*.php"
      ],
    ...

Customize Bootstrap 

Strip out Bootstrap scss:

  1. Open theme/node_modules/bootstrap/scss/bootstrap.scss
  2. Grab all the imports and paste them into main.scss in the theme, while commenting out the main Bootstrap import
  3. Search and replace @import with @import “~bootstrap/scss/ on the Bootstrap imports only
  4. Comment out/delete those lines you don’t need

quote: Reduced my compiled CSS from 195K to 142K.

Example, if you only want a reset and the grid:

// Import npm dependencies
@import "~bootstrap/scss/bootstrap-reboot";
@import "~bootstrap/scss/bootstrap-grid";

BS4 JS

scripts/autoload/_bootstrap.js imports all bootstrap with all functionalities at that location in main.scss.

To remove all Bootstrap 4 JS remove this line in main.js:

// Import everything from autoload
import './autoload/**/*'

loading individual components:

// Required
@import "~bootstrap/scss/functions";
@import "~bootstrap/scss/variables";
@import "~bootstrap/scss/mixins";

// Optional
@import "~bootstrap/scss/root";
@import "~bootstrap/scss/reboot";
@import "~bootstrap/scss/type";
@import "~bootstrap/scss/images";
@import "~bootstrap/scss/code";
@import "~bootstrap/scss/grid";
// @import "~bootstrap/scss/tables";
@import "~bootstrap/scss/forms";
@import "~bootstrap/scss/buttons";
// @import "~bootstrap/scss/transitions";
// @import "~bootstrap/scss/dropdown";
// @import "~bootstrap/scss/button-group";
// @import "~bootstrap/scss/input-group";
// @import "~bootstrap/scss/custom-forms";
@import "~bootstrap/scss/nav";
@import "~bootstrap/scss/navbar";
// @import "~bootstrap/scss/card";
// @import "~bootstrap/scss/breadcrumb";
// @import "~bootstrap/scss/pagination";
// @import "~bootstrap/scss/badge";
// @import "~bootstrap/scss/jumbotron";
// @import "~bootstrap/scss/alert";
// @import "~bootstrap/scss/progress";
// @import "~bootstrap/scss/media";
// @import "~bootstrap/scss/list-group";
@import "~bootstrap/scss/close";
@import "~bootstrap/scss/modal";
// @import "~bootstrap/scss/tooltip";
// @import "~bootstrap/scss/popover";
// @import "~bootstrap/scss/carousel";
@import "~bootstrap/scss/utilities";
// @import "~bootstrap/scss/print";

Documentation

https://roots.io/sage/docs

Editor Setup

Recommende packages for Sublime/ Atom etc:

  • Editorconfig ->  Sage and the other Roots projects use the .editorconfig file to help enforce spacing consistency.
    (EditorConfig plugins look for a file named .editorconfig in the directory of the opened file and in every parent directory).
  • Emmet – Improves HTML & CSS workflow
  • highlight-selected – Higlight current selected word everywhere it appears in the file (not a Sublime package)
  • language-blade (not a Sublime package) -> use Laravel Blade Highlighter instead

Coding standards:

  • Sage uses 4 spaces for PHP files, with the exception of template files, as it follows the PSR-2 coding standards.
  • Two spaces are used for everything else, including Sass, JavaScript, and JSON.
  • Mark Otto, the creator of Bootstrap, has a well-documented code guide for front-end developers at http://codeguide.co/ . Some examples:
    • Avoid superfluous parent elements when writing HTML
    • Keep classes lowercase and use dashes for class names
    • Keep classes as short and succinct as possible
    • Use meaningful names; use structural or purposeful names over presentational
    • Prefix classes based on the closest parent or base class
    • Use soft-tabs set to two spaces
    • Avoid unnecessary nesting

Javascript E6

  • Sage uses ES6 for the JavaScript that’s included in the theme. Since Sage strives to use the current best practices for
    modern front-end development, the theme allows the usage of ES6 and also enforces coding standards with ESLint.
  • The ESLint configuration is located at assets/build/.eslintrc, where you might want to make changes that fit your own
    coding styles.
  • We’ve picked Airbnb’s JavaScript standard as the basis for ours.
  • To disable the linting in a specific file or within a file, use inline comments:
    /* eslint-disable */
    alert('foo');
    /* eslint-enable */
  • I had to add this file to the project root to remove eslint warnings
    .jshintrc
    {
        'eslintversion': 6
    }

Theme Configuration and Setup

app/setup.php is used to enqueue stylesheets and scripts, register support for theme features with add_theme_support, and register navigation menus and sidebars.

NOTE: If you see Jquery not found errors in the console (I had this  problem with gravity forms), you might want to disable  the line with

add_theme_support('soil-jquery-cdn');

jQuery will then be put in the head and load before other plugins. A better solution is probable to properly enqueue the plugin assets?

NOTE:  If you don’t use Bedrock as your WordPress stack, you’ll want to add the following to your wp-config.php on your development installation:
define(‘WP_ENV’, ‘development’);Note: If WP_ENV is not defined WP_ENV will be set to production, which may be just what you want. See other post

Stylesheets and scripts

Manage your front-end theme assets from the app/setup.php file:

add_action('wp_enqueue_scripts', function () {
    wp_enqueue_style('sage/main.css', asset_path('styles/main.css'), false, null);
    wp_enqueue_script('sage/main.js', asset_path('scripts/main.js'), ['jquery'], null, true);
}, 100);

See theme assets for more on how these assets are built. asset_path is a helper function that returns versioned asset filenames from the dist/ directory.

Theme features

Soil

We recommend using the Soil Plugin with every WordPress install for additional features:

  • Load jQuery from the jQuery CDN*
  • Cleaner WordPress markup*
  • Cleaner HTML output of navigation menus*
  • Root relative URLs*
  • Nice search*
  • Google Analytics snippet from HTML5 Boilerplate
  • Move all JS to the footer
  • Disable trackbacks and pingbacks

∗If Soil is installed and activated on your WordPress install, Sage will enable these features by default.

Title tag support

add_theme_support('title-tag') is a feature added in WordPress 4.1 that allows themes and plugins to manage the document title. This means that there’s no <title> tag found in the head template since it’s automatically added by wp_head().

Register navigation menus

Sage registers a navigation menu called Primary Navigation. Additional menus should be added in the register_nav_menus locations array.

Post thumbnails

Post thumbnails are enabled with add_theme_support('post-thumbnails'), but they aren’t output on any of the default templates. Add custom post thumbnail sizes with add_image_size().

HTML5 markup

Sage enables HTML5 markup for captions, comment forms, comment lists, galleries, and the search form.

Editor stylesheet

The TinyMCE editor in WordPress allows loading a custom stylesheet which is registered with add_editor_style(). The editor stylesheet is automatically generated from your main theme stylesheet when you run the build script.

Register sidebars

Sage registers two sidebars by default: Primary & Footer. Add additional sidebars with register_sidebar().

Theme structure

themes/your-theme-name/   # → Root of your Sage based theme
├── app/                  # → Theme PHP
│   ├── controllers/      # → Controller files
│   ├── admin.php         # → Theme customizer setup
│   ├── filters.php       # → Theme filters
│   ├── helpers.php       # → Helper functions
│   └── setup.php         # → Theme setup
├── config/               # → Theme configuration
├── composer.json         # → Autoloading for `app/` files
├── composer.lock         # → Composer lock file (never edit)
├── dist/                 # → Built theme assets (never edit)
├── node_modules/         # → Node.js packages (never edit)
├── package.json          # → Node.js dependencies and scripts
├── resources/            # → Theme assets and templates
│   ├── assets/           # → Front-end assets
│   │   ├── config.json   # → Settings for compiled assets
│   │   ├── build/        # → Webpack and ESLint config
│   │   ├── fonts/        # → Theme fonts
│   │   ├── images/       # → Theme images
│   │   ├── scripts/      # → Theme JS
│   │   └── styles/       # → Theme stylesheets
│   ├── functions.php     # → Composer autoloader, theme includes
│   ├── index.php         # → Never manually edit
│   ├── screenshot.png    # → Theme screenshot for WP admin
│   ├── style.css         # → Theme meta information
│   └── views/            # → Theme templates
│       ├── layouts/      # → Base templates
│       └── partials/     # → Partial templates
└── vendor/               # → Composer packages (never edit)

Customizing templates

The resources/views/ directory contains files that you can further extend with the normal WordPress Template Hierarchy

Here’s what’s happening with these hooks: 

  1. WordPress detects theme in themes/sage/resources
  2. When we activate, we tell WordPress that the theme is actually in themes/sage/resources/views
  3. When we call get_template_directory() or get_template_directory_uri(), we point it back to themes/sage/resources

We do this so that the Template Hierarchy will look in themes/sage/resources/views for core WordPress themes, but functions.php, style.css, and index.php are all still located in themes/sage/resources.

This is not compatible with the WordPress Customizer theme preview prior to theme activation


Note that functions.php, screenshot.png and style.css exist in the  resources/ directory and not the theme root. This does currently come with some tradeoffs. sage-installer Issue #3 is tracking an option to move the required theme files back to the theme root folder. You’ll need to follow the instructions from dmgawel if allowing your theme to be uploaded via zip to the WordPress admin is a requirement.

Blade Templates

Sage uses Laravel’s Blade templating engine. Some of the benefits that come with using a templating engine include:

  • Template inheritance In previous versions of Sage we accomplished template inheritance with the theme wrapper.
  • Separation of data from views Pass your logic to template files instead of including PHP in your views files
  • Automatically escaped data When you include data with Blade, such as with {{ get_post_meta(get_the_ID(), 'example', true) }} (or {{ get_field('example') }} if you use ACF), the data is automatically escaped.
    This means that you don’t need to use esc_url or other sanitizing functions in WordPress when outputting data in templates.
  • Beautiful looking code The Blade syntax is pretty clean!

Template inheritance

One of the biggest benefits of using Blade templates is the ability to remove any repeated markup from individual templates and put it into a single file. This file, resources/views/layouts/app.blade.php, becomes the base layout file. By doing this we can put the focus entirely on the page specific markup and loop, simplifying our templates.

Passing data to templates

Sage includes a sage/template/{$class}/data filter that can be used to pass data to templates. This is the most simple way to pass data. The filter is based of body classes and can be used to target specific templates, for example:

  • sage/template/home/data — Home page
  • sage/template/about/data — About page
  • sage/template/page/data — All pages
  • sage/template/post-type-archive-event/data — event post type archive
  • sage/template/single-event/data — event single post template

Note: Sage comes ready for you to modify the body_class by editing the filter at the top of app/filters.php

In the example below we’re passing the the values of two ACF fields, header_image and header_content, to all pages:

add_filter('sage/template/page/data', function (array $data) {
$data['header_image'] = get_field('header_image');
$data['header_content'] = get_field('header_content');
return $data;
});

In your Blade templates for pages you can now use {{ $header_image }} and {{ $header_content }} to output the data.

404.blade.php
Error 404 page
index.blade.php
Archive page (used by blog page, category archives, author archives and more)
page.blade.php
Single page
search.blade.php
Search results page
single.blade.php
Single post page
template-custom.blade.php
An example single page template

All templates are wrapped by a base file in the layouts/ directory:

app.blade.php
The base template which wraps the base markup around all template files

These files include templates from the resources/views/partials/ directory which is where you’ll be making most of your customizations:

comments.blade.php
Markup for comments
content-page.blade.php
Markup included from resources/views/page.blade.php
content-search.blade.php
Markup included from resources/views/search.blade.php
content-single.blade.php
Markup included from resources/views/single.blade.php
content.blade.php
Markup included from resources/views/index.blade.php
entry-meta.blade.php
Post entry meta information included from resources/views/content-single.blade.php
footer.blade.php
Footer markup included from layouts/base.blade.php
head.blade.php
<head> markup included from layouts/base.blade.php
header.blade.php
Header markup included from layouts/base.blade.php
page-header.blade.php
Page title markup included from most of the files in the resources/views/ directory
sidebar.blade.php
Sidebar markup included from layouts/base.blade.php

Extending templates

The normal WordPress Template Hierarchy is still intact. Here’s some examples:

  • Copy index.blade.php to author.blade.php for customizing author archives
  • Copy index.blade.php to home.blade.php for customizing the Home page if you’re showing the latest posts (under Reading Settings) instead of a static front page
  • Copy index.blade.php to archive-gallery.blade.php for customizing the archive page for a custom post type registered as gallery
  • Copy page.blade.php to front-page.blade.php for customizing the static front page
  • Copy page.blade.php to page-about.blade.php for customizing a page called About

Blade Templates

Sage uses Laravel’s Blade templating engine.

Passing data to templates

Sage includes a sage/template/{$class}/data filter that can be used to pass data to templates. This is the most simple way to pass data.

add_filter('sage/template/page/data', function (array $data) {
    $data['header_image'] = get_field('header_image');
    $data['header_content'] = get_field('header_content');
    return $data;
});

Controller can also be used to pass data to templates.

WP-CLI utility

blade-generate is a WP-CLI package that can be used to compile, wipe, and clear Blade templates. Install blade-generate by running:

wp package install git@github.com:alwaysblank/blade-generate.git

After installing blade-generate you can run the following commands:

  • wp blade compile
  • wp blade clear
  • wp blade wipe

Theme Sidebar

Displaying the sidebar

The sage/display_sidebar filter can be used to define which conditions to enable the primary sidebar on.

add_filter('sage/display_sidebar', function ($display) {
    static $display;

    isset($display) || $display = in_array(true, [
      // The sidebar will be displayed if any of the following return true
      is_single(),
      is_404(),
      is_page_template('template-custom.php')
    ]);

    return $display;
});

Theme Functionality

The app/ directory contains all of the theme functionality. Since Sage is a starter theme, it’s okay for you to modify files within app/ to meet the needs of the site you’re building.

The PHP code in Sage is namespaced, so make sure to use namespaced functions and classes.

app/setup.php
Enqueue stylesheets and scripts, register support for theme features with add_theme_support, register navigation menus and sidebars. See Theme Configuration and Setup.
app/admin.php
Placeholder code for the WordPress theme customizer. You can also use this file for anything related to the WordPress admin.
app/filters.php

Add WordPress filters in this file. Filters included by default:

  • body_class — add <body> classes
  • excerpt_more — add “… Continued” to excerpts
  • template_include — enable the theme wrapper
  • Various filters for the Blade implementation
app/helpers.php

Helper functions used throughout the theme:

  • asset_path — used when enqueueing theme assets to provide the correct versioned asset filenames
  • display_sidebar — used to control displaying the sidebar
  • title — used to return page titles

Deployment:

  • These are the primary projects that make up the Sage workflow:
    • Webpack is used as a build tool for compiling stylesheets, checking for JavaScript errors, optimizing images, and concatenating and minifying files. In previous versions of the theme we used Grunt and Gulp as our build tools.
    • npm npm is a front-end package manager. Sage uses npm to pull in Bootstrap and jQuery as dependencies.
    • BrowserSync with Webpack Hot Module ReplacementBrowserSync with WHR keeps multiple browsers and devices synchronized while developing, along with injecting updated CSS and JS. In previous versions of the theme we used LiveReload for injecting assets.
  • the dist folder is gitignored by default. The reason for this is that it is good practice to never check compiled files into source control (it is called source control for a reason). The ideal setup would be a CI (continuous integration) server that builds the project after deployment and than pushes it onto the server. The next ideal solution is deployment on the production server itself. Of course you need to be able to install the dependencies on the server and take into account that building the project will put some strain on the server.The most straightforward solution is to built the project locally, push with Git and upload the compiled files (that are not in the Git repo) with src.
  • To deploy a Sage theme you’ll need to make sure two things are covered:
    1. Run composer install from the theme directory on the remote server (if possible)
    2. Copy over production theme assets
  • What (not) to ignore if you are not building anything on the server
    • Remove from .gitignore
      • The normal dependencies in vendor. But keep ignoring the dev-dependencies:
        •  
    • Add to the main .gitignore (but only for deployment. you need these files in your theme repo of course)
      • /composer.*
      • /vendor/composer/installers
      • /vendor/squizlabs
      • /vendor/roave
      • /*.md
      • wp-cli.yml
    • Add to the theme .gitignore
      • /resources/assets 
      • .editorconfig
      • .eslintrc
      • .travis.yml
      • LICENSE.md
      • package.json
      • yarn.lock
      • /vendor/roots/sage-installer

      • /vendor/squizlabs

      • /vendor/composer/installers

      • /.github

    • Optionally add plugins and WordPress to your gitignore, if you want to update these from the WP dashboard on the production site

Bootstrap Navwalker menu

Update Dec 2018:

All you need to do is include this composer package in your Sage theme and the navwalker will be available to use.

https://github.com/MWDelaney/sage-bootstrap4-navwalker

  • To install, run the following in your Sage9-based theme directory:
    composer require "mwdelaney/sage-bootstrap4-navwalker"

  • Include the navwalker in your wp_nav_menu function in the blade template for the header:
    {!! wp_nav_menu( array(
       'menu' => 'primary',
       'theme_location' => 'primary_navigation',
       'walker' => new wp_bootstrap4_navwalker(),
       'menu_class' => 'nav navbar-nav')

    ) !!}

  • At the top of the blade template add: 
    <?php namespace: app ?>

  • If you want to use the ‘clean walker’, just make sure you have soil installed and activated on your site. bootstrap navs work fine with just the clean walker as long as you don’t need dropdown support.

Theme assets

The config.json file in the assets directory controls the different theme assets that get built. By default, Sage builds two JS files and one CSS file:

  • assets/stylesheets/main.scss — primary theme CSS, barebones partials are imported to help get your styling started
  • assets/scripts/main.js — primary theme JS
  • assets/scripts/customizer.js — theme customizer JS, used only in the customizer

Look at entry in assets/config.json to see how they’re built:

"entry": {
  "main": [
    "./scripts/main.js",
    "./styles/main.scss"
  ],
  "customizer": [
    "./scripts/customizer.js"
  ]
}

To create additional CSS or JS files, you’ll need to:

  1. Create the files within the assets/scripts/ or assets/styles/ directories
  2. Open assets/config.json and add the new files to entry in a new array. In the example below we’ve added scripts/checkout.js:
    "entry": {
      "main": [
        "./scripts/main.js",
        "./styles/main.scss"
      ],
      "customizer": [
        "./scripts/customizer.js"
      ],
      "checkout": [
        "./scripts/checkout.js"
      ]
    }
  3. Enqueue the new file in src/setup.php In the example below we’ve added a conditional to only enqueue scripts/checkout.js on the checkout page:
    /**
     * Theme assets
     */
    add_action('wp_enqueue_scripts', function () {
        wp_enqueue_style('sage/main.css', asset_path('styles/main.css'), false, null);
        wp_enqueue_script('sage/main.js', asset_path('scripts/main.js'), ['jquery'], null, true);
    
        if (is_page('checkout')) {
            wp_enqueue_script('sage/checkout.js', asset_path('scripts/checkout.js'), ['jquery'], null, true);
        }
    }, 100);
  4. From the theme directory, run the build script:
    # web/app/themes/your-theme-name/
    $ yarn run build

3rd party packages

Example of how to add 3rd party packages* and have them included in the theme:

  1. From the theme directory, run:
    # @ themes/your-theme-name/
    $ yarn add <package name>
    
    # Install Slick carousel:
    $ yarn add slick-carousel
  2. Open up main.js and main.css to add the entry points for the package. If you’re using the Slick Carousel then your theme JS and CSS would look like:
    /** import external dependencies */
    import 'jquery';
    import 'bootstrap/dist/js/bootstrap';
    
    // Import Slick
    import 'slick-carousel/slick/slick.min';
    /* sage/assets/styles/main.scss */
    @import "common/variables";
    
    // Import npm dependencies
    @import "~bootstrap/scss/bootstrap";
    @import "~font-awesome/scss/font-awesome";
    // Import Slick
    @import "~slick-carousel/slick/slick.scss";
    @import "~slick-carousel/slick/slick-theme.scss";
  3. After running yarn run build from the theme directory, your package will be built with your theme assets. The distfolder will contain a _/node_modules/ directory that has any assets referenced from your packages. The compiled CSS and JS will reference these assets without having to manually edit paths. :sparkles:
  4. Running yarn run build:production will fail if 3rd party package’s relative paths are not configured before imported. In example to load Slick Carousel’s paths add the following line in your common/_variables.scss file:
    /* sage/assets/styles/common/_variables.scss */
    // Slick Carousel font path
    $slick-font-path: "~slick-carousel/slick/fonts/";
    
    // Slick Carousel ajax-loader.gif path
    $slick-loader-path: "~slick-carousel/slick/";

∗Note: WordPress Plugins are installed elsewhere or with Composer when using Bedrock

Additional examples

Font Awesome:

# @ themes/your-theme-name/
$ yarn add font-awesome
/* sage/assets/styles/main.scss */
@import "common/variables";

// Import Font Awesome from node_modules
@import "~font-awesome/scss/font-awesome.scss";

Images in template files

Use the @asset directive to call images from template files:

<img src="@asset('images/example.jpg')">

ES6

Tips:

  • If some plugin is causing problems because of lint errors, you can ignore it by putting this at the top of the file: /* jshint ignore:start */

Recommended Forks