4

Brand new to Craft here. I'm trying to port across my gulp workflow to Craft and basically everything has gone super smooth. Just one last obstacle due to my lack of knowledge of the Twig templating engine and some of the internal workings of Craft.

Basically, for production, I run gulp with a --production flag. This appends a string of numbers and letters to the asset's file name (as well as removing source maps etc.), such as main-5449f384.css, to help with caching. A list of the resulting asset filenames is stored in a JSON file at public/dist/assets.json. The contents of the file is akin to:

{
  "main.css": "main-5449f384.css",
  "modernizr.js": "modernizr-45f0e1f4.js",
  "jquery.js": "jquery-e735354d.js",
  "main.js": "main-b7e504b0.js"
}

Separately, in my general.php config file, I've set up environment variables so I can use local asset paths in local and dev environments and a CDN based path in production:

return array(
    '*' => array(
        'appId' => 'example',
        'omitScriptNameInUrls' => true,
    ),

    'example.com' => array(
        'devMode' => false,
        'assetUrl' => 'https://cdn.example.com/',
    ),

    'craft' => array(
        'devMode' => true,
        'local' => true,
        'assetUrl' => 'http://craft:8888/',
    )
);

I had figured that to finalise the whole workflow, my head section within craft/templates/_layout.html would look something like (using a if statement to get the current environment):

Local

<script src="{{ craft.config.assetUrl }}dist/scripts/main.js"></script>

Live (pseudocode)

<script src="{{ craft.config.assetUrl }}dist/scripts/{{ assets.json.main.js }}"></script>

Is there a way to either set an environment variable based on the contents of the JSON file or to access to JSON file contents directly from within the template file? Or perhaps there's a much better way of doing this altogether (I'd quite like to keep the currently gulp workflow as is if possible)!

4

You could write some PHP at the top of your general.php file that reads the JSON manifest in your public root directory, and add its keys/values to the config array. I wouldn't use environment variables here, personally – just add the manifest to the returned array in general.php:

// In general.php:

$assetsManifest = @json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'].'/assets/assets.json')) ?: [];

return array(
    '*' => array(
        ...
        'assets' => (array)$assetsManifest,
    ),
);

...and in your template:

<script src="{{ craft.config.assets['main.js'] ?? 'main.js' }}"></script>

Be advised that the null-coalescing operator (??) was just added in Craft 2.6 – if you haven't updated yet, you can use the default filter instead:

<script src="{{ craft.config.assets['main.js']|default('main.js') }}"></script>

Another approach for getting revved asset filenames in templates, is to use a plugin which adds either a custom template variable method or Twig filter/function to Craft. For an example of the latter, see Viget Labs' Gulp Rev Craft plugin, which is bundled with their awesome Gulp Starter repo. Here's how revving works using this particular plugin:

<script src="{{ 'main.js'|gulp_rev }}"></script>

For me, individual asset filenames in the config feels a bit off and the custom filter option seems a lot cleaner, so I'm personally going with that approach.

| improve this answer | |
  • What an amazing helpful reply. Answered my question and gave me an even better alternative whilst explaining why it's a better idea. I've had a quick play and first method works great and I'm now going to give your second suggestion a go. Thanks for taking the time to answer :) – lotech Apr 5 '16 at 14:18
  • No problem, @lotech – very cool that I was able to help you out! – Mats Mikkel Rummelhoff Apr 6 '16 at 6:17
1

Thanks for this it helped a lot! I am using grunt-assets-versioning and took me some time to get it to work properly, so let me share my approach.

So grunt-assets-versioning creates the file /public/css/app.json

[{
  "version":"b2ff9f",
  "originalPath":"public/css/app.css",
  "versionedPath":"public/css/app.b2ff9f.css"
 }]

The trick is to use @json_decode(path, true) , so add this to your general.php

$appCSS = @json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'].'/css/app.json'), true) ?: [];

return array(
    ...
    'appCSS' => str_replace('public', '', $appCSS[0]['versionedPath'])
);

Remove the word 'public' so the final path will be "/css/app.b2ff9f.css"

Now you can call the file from your template.

<link rel="stylesheet" href="{{ craft.config.vendorCSS ?? '/css/vendor.css' }}">
| improve this answer | |
1

So while this is not a direct answer the the questions asked here, I think these resources (which weren't written at the time of the posted question) might be useful to someone else in the same situation.

Re: using Gulp with Craft:

If you're interested in using a modern webpack setup to for the same:

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.