Trellis + webpack without Sage

webpack

#1

Hi there friends, this is my first post.

I have migrated a client’s ancient old theme onto a Trellis site with Bedrock structure, for the purposes of using Composer to admin their plugins and to give a good deployment process. Thanks so much for making this great set of tools available. I have it deployed on a DO droplet and locally in vagrant to assist with development of a quite complex plugin that will supply new features to the admin area of their site.

I’d like very much to start using webpack and React for the UI I am coding up. But because it’s all admin-area functionality, I have not pitched to rewrite their theme at this stage (even though it is not responsive and overdue to be replaced).

My question is, without moving to Sage, how can I get webpack, yarn and all the goodness onto my server without adding manual steps to my deployment process (ie, using just Trellis hooks)?

I have looked in build-before.ymlbut that assumes one is using Sage and that yarn is already installed on the server. Once I have those tools provisioned then I could presumably use a modified version of build-before.yml to run webpack etc on my plugin files.

I’m happy to get my hands into the ansible scripts if necessary to do this, but as Trellis works so well off the bat I haven’t had to so far, so I’m not sure where to start.

Thanks again for the tooling!

Julian


#2

Ok, so yarn runs on the host machine, not the target server, hence the name build-before.yml, I get that now :slight_smile: I think I’m making headway with thanks to this article on DeliciousBrains. Onwards!


#3

You could drop Laravel Mix into the project. It’s an “elegant wrapper” for Webpack. I’ve done this for a number of non-Sage themes I’ve inherited — one of which I’ve recently built a React component for. Also, this is what Sage will eventually be moving to for its own frontend workflow (roots/sage#2011).

I usually set the names of the scripts (in package.json) to follow Sage’s naming (since yarn start feels so much better than yarn dev):

  "scripts": {
    "build": "NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
    "build:production": "NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
    "start": "NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
  }

Then I believe if you were using the build-before hook in Trellis to for deploying the assets, for the most part, you wouldn’t need to change much. When configuring Mix (which is super easy), make sure the built assets are being written to the dist directory. I’m assuming the theme you are working with wouldn’t include any Composer dependencies, so you could leave out that task.


If you are interested, here is a quick dump of what I’ve done when in a similar situation:

package.json
{
  "devDependencies": {
    "laravel-mix": "^2.1.11"
  },
  "scripts": {
    "build": "NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
    "build:production": "NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
    "start": "NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
  }
}
Laravel Mix Configuration

This may or may not work — had to adapt it for the sake of this example. It gives you the general idea anyway.

// webpack.mix.js

let mix = require('laravel-mix');

mix.setPublicPath('./dist')
  .copyDirectory('src/images', 'dist/images')
  .js('src/scripts/main.js', 'dist/scripts/') // Main script
  .sass('src/styles/main.scss', 'dist/styles/') // Main stylesheet
  .version(); // See functions.php for automatic versioning function

if (!mix.inProduction()) {
  mix.browserSync('example.test');
}
Asset Versioning Helper

A modest recreation of the asset_path() function in Sage. Again, had to adapt somethings for the sake of example — so I wasn’t able to test it.

// functions.php — or wherever

/**
 * Versioned Asset Helper
 *
 * Grabs the latest verion from the Mix Manifest
 *
 * Inspired by Sage
 */
function asset_path($asset)
{
    $manifest = get_stylesheet_directory() . '/dist/mix-manifest.json';

    return get_stylesheet_directory_uri() . '/dist' . json_decode(file_get_contents($manifest), true)['/' . $asset];
}

/**
 * Enqueue scripts and styles.
 */
add_action('wp_enqueue_scripts', function() {
    wp_enqueue_style('not-sage-style', asset_path('styles/main.css'), false, null);
    wp_enqueue_script('not-sage-script', asset_path('scripts/main.js'), false, null, true);
}, 100);


#4

Hey, great to have those examples. I am not currently doing much on the theme side of things (it’s all plugin dev at present). But there will be a public-facing form that needs to tie back to the plugin, it will be great to know I can use React for that without messing around with the old theme too much. I will let the community go how I get on once I reach that stage (a few weeks off yet I’d say).

Thanks heaps.

Julian