Jump to content

RockFrontend 🚀🚀 Take your ProcessWire Frontend Development to the Next Level


bernhard
 Share

Recommended Posts

 

Modules Directory: https://processwire.com/modules/rock-frontend

Github: https://github.com/baumrock/RockFrontend

Ideas/Wishlist/Roadmap:

  • add support to merge/minify assets
  • add jsonld helper methods, for example $rockfrontend->jsonld->breadcrumbslist($page); Ideas? Help welcome!!

---

Please give feedback to the video in this thread: https://processwire.com/talk/topic/27419-feedback-for-my-youtube-videos/

Feedback/Questions to RockFrontend go here 🙂 

  • Like 20
  • Thanks 2
Link to comment
Share on other sites

BOOOOOOM 💥💥💥💥 Bernhard dropped the bomb.

I'm halfway through the video and so far love everything about it. Nice video setup and editing there too. Going back to the video now 😀

-------------------

Edit: Okay, I'm through and this is definitely super cool. Looking forward to trying it out. There are two things though that I'm not sure about and wanted to mention:

1. The name Alfred. While you've found a sweet acronym it (in my opinion) has the huge drawback that new developers looking at the code and seeing

alfred($page, ['fields' => 'gallery'])

will have absolutely zero clue what's going on. Most of us love ProcessWire because it's intuitive. With this name you have to first learn that alfred is an inline editor to understand what the code is supposed to be doing.

 

2. I'm not sure about this one, but adding assets to the header through hooks reminds me of dark Wordpress times. I like that with ProcessWire you are able to to see where things are coming from and you have total control over what's happening.

Edited by MrSnoozles
Removed the comment about simplifying the alfred() function. That was nonsense. Should have gone to sleep already :)
  • Like 3
Link to comment
Share on other sites

Hey @MrSnoozles thx for the input!! 🙂 

15 hours ago, MrSnoozles said:

1. The name Alfred. While you've found a sweet acronym it (in my opinion) has the huge drawback that new developers looking at the code and seeing

alfred($page, ['fields' => 'gallery'])

will have absolutely zero clue what's going on. Most of us love ProcessWire because it's intuitive. With this name you have to first learn that alfred is an inline editor to understand what the code is supposed to be doing.

Puh... I'm not sure 🙂 I agree with you that it's nice to understand code without having to look anything up. On the other hand I'm not sure what would be a better naming? In code and in the docs it is a huge benefit to just refer to it as ALFRED because it's short and crystal clear what is meant. In code for someone not knowing alfred that's surely not the case, but it would be just as simple to look it up and quickly find and understand what it is doing. Don't you think?

I could easily add an alias though. But I'm not sure if that is a good idea because it could cause name collisions with the core frontend editing?! What would be a good name in your opinion? What do others think about that?

15 hours ago, MrSnoozles said:

Edited 2 hours ago by MrSnoozles
Removed the comment about simplifying the alfred() function. That was nonsense. Should have gone to sleep already 🙂

I was looking for that statement as I think it was really a good hint! Thought I have been dreaming 😄 I have played around with my code a little and think that that we could really simplify alfred syntax even further! 

// edit current page
<div alfred>

// edit given page+fields (latte)
<div alfred="{$page}:title,gallery">
  
// php
<div alfred="<?= $page ?>:title,gallery">

That could work using the page::render hook for replacing the tags, so one wouldn't even have to think of using the |noescape filter any more!!

15 hours ago, MrSnoozles said:

2. I'm not sure about this one, but adding assets to the header through hooks reminds me of dark Wordpress times. I like that with ProcessWire you are able to to see where things are coming from and you have total control over what's happening.

Thx! I have removed that part from the video as it already got so long...

See this post that is using the old (alternative) syntax: https://processwire.com/talk/topic/27187-domid-labs-– microsite-for-a-museum-related-project/?do=findComment&comment=224750

This approach has major drawbacks IMHO:

  1. You need to add the scripts and styles tag manually to your markup, which is not what I call "zero-setup". I've had it working like this before I did the video, but then I realised that there's actually some steps to do to get everything working as it should. So I came up with the hook-based approach. And I really like that approach even if that means that it hides some parts away, which is a valid point...
  2. When injecting scripts or styles from your sections (or components, or modules) you need to make sure that those scripts are loaded BEFORE the scripts are rendered in the head. That's similar to the delayed output pattern of processwire. The markup would look like this:
<?php
// render layout first, so any of your sections can inject scripts or styles
$body = $rockfrontend->renderLayout($page);
?>
<html>
  <head>
  <?= $rockfrontend->styles()->add(...)->render() ?>
  <?= $rockfrontend->scripts()->add(...)->render() ?>
  </head>
  <body>
    <?= $body ?>
  </body>
</html>

The thing is that I really want ALFRED and livereloading work out of the box. Zero-Setup.

If you want to use the alternate syntax you can do so. RockFrontend is smart enough to see that you are rendering scripts/styles manually and will not inject them twice 🙂 

What do you think?

  • Like 1
Link to comment
Share on other sites

Wow! In general I think it's a huge benefit for the community to have a more opinionated way of doing frontend, so congrats on this is amazing module! I have no further comments until I try it fully but from what I see in the video it looks fantastic. 

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

3 hours ago, bernhard said:

Puh... I'm not sure

Neither am I. 🙂 It was just a thought that came while watching your video. rockFrontendEditing for example wouldn't sound as catchy, but would be clearer for newcomers.

 

3 hours ago, bernhard said:

I have played around with my code a little and think that that we could really simplify alfred syntax even further! 

I really like the new syntax. I wanted to suggest a Latte attribute first, but then decided to keep it simpler. Your approach looks nice. Imo it would b good to explain why and when this is needed instead of just using $page->edit('myfield')

 

3 hours ago, bernhard said:

f you want to use the alternate syntax you can do so. RockFrontend is smart enough to see that you are rendering scripts/styles manually and will not inject them twice 🙂

Perfect! So you get the best of both worlds.

 

I'm sick at home this weekend, hopefully I will find time to give it a try already.

  • Like 1
Link to comment
Share on other sites

Hey @MrSnoozles I've played around a little with the new alfred syntax. I've used WireMarkupRegions to modify the markup when an alfred attribute was found, which was great. But then I realised that this breaks the code icon with quicklinks to the latte file. Which is not great! I don't think that I can do anything about that, so I think it's best to stick with the function based solution (either via latte or via php).

Though I've just pushed an update that adds a short syntax for this:

<div {alfred($page, ['fields' => 'title,images'])|noescape}>

to also support that:

<div {alfred($page, 'title, images')|noescape}>

The old syntax is still supported for backwards compatibility and to support providing fields as array instead of a string.

RockFrontend will even check if the field exists, so that editing will not break when requesting non-existing fields like "title, images, doesnotexist"

Link to comment
Share on other sites

Thx, that is very strange!! The text you are seeing are just PHP comments in an empty array. Maybe a bug in the file compiler... I have moved the comment above the array. Can you try version 1.10.5 please?

Link to comment
Share on other sites

Tried it again within a fresh ProcessWire instance and the most recent version of RockFrontend from Github.

Installs without any issues. Doesn't even mention RockMigration anymore.

Thanks!

Edit: Another thing pops up now. Opened an issue on Github for it.

  • Thanks 1
Link to comment
Share on other sites

Thx @wbmnfktr the issue is fixed in version 1.13.3

I've also added the first WIP version of seo support 🤩

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <?= $rockfrontend->seo()
    ->title("{$page->title} | My Company")
    ->description(function($page) {
      if($page->template == 'foo') return $page->foo;
      return $page->body;
    })
    ->setValue('og:image', function($page) {
      if($page->template == 'boat') return $page->boatpic;
      return $page->images;
    })
  ?>
</head>

Tags can easily be set and truncation is as easy as adding an integer to the tag {value:160}

Va3XP6u.png

  • Like 2
Link to comment
Share on other sites

Thx to another request by @wbmnfktr and issues that I had on my own project I've improved asset handling, autoloading and debugging in v1.13.8

It also adds a new method to prepend() scripts and styles (like uikit.theme.less in the example below). Adding something like addAfter('mystyle.css', 'theme.css') is on my list...

A default <head> can now look like this (note all the html comments that should be quite helpful):

  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <!-- RockFrontend SEO by baumrock.com -->
  <title>Home</title>
  <meta property="og:title" content="Home">
  <meta name="description" content="Home">
  <meta property="og:description" content="Home">
  <meta property="og:image" content="">
  <meta property="og:image:type" content="">
  <meta property="og:image:width" content="">
  <meta property="og:image:height" content="">
  <meta property="og:image:alt" content="Home">
  <script>let rf_livereload_secret = 'rDksCMGEMFs87mNq3WrTaVug1tfeldQ0r9L4kUkfqghS'</script>
  <!-- DEBUG enabled! You can disable it either via $config or use $rf->styles()->setOptions(['debug'=>false]) -->
  <!-- autoloading of default scripts/styles enabled - disable using ->setOptions(['autoload'=>false]) -->
  <!--rockfrontend-styles-head-->
  <!-- loading /var/www/html/site/templates/uikit-3.15.2/src/less/uikit.theme.less -->
  <!-- loading /var/www/html/site/templates/layouts/_global.less -->
  <!-- loading /var/www/html/site/templates/sections/footer.less -->
  <!-- loading /var/www/html/site/templates/sections/hero.less -->
  <!-- loading /var/www/html/site/templates/sections/job-footer.less -->
  <!-- loading /var/www/html/site/templates/sections/menu.less -->
  <!-- loading /var/www/html/site/templates/sections/rocket.less -->
  <!-- loading /var/www/html/site/assets/RockMatrix/matrix/FactsBar.less -->
  <!-- loading /var/www/html/site/assets/RockMatrix/matrix/IconBox.less -->
  <!-- loading /var/www/html/site/assets/RockMatrix/matrix/IconRow.less -->
  <!-- loading /var/www/html/site/assets/RockMatrix/matrix/PagesGrid.less -->
  <!-- loading /var/www/html/site/assets/RockMatrix/matrix/QuoteSlider.less -->
  <!-- loading /var/www/html/site/assets/RockMatrix/matrix/Spacer.less -->
  <!-- loading /var/www/html/site/assets/RockMatrix/matrix/Team.less -->
  <link rel='stylesheet' href='/site/templates/bundle/head.css?m=1660204105'>
  <link href='/site/modules/RockFrontend/Alfred.css?m=1660124218'   rel='stylesheet'>
  <link href='https://use.typekit.net/zeg8qpc.css'   rel='stylesheet'>
  <link href='/site/templates/sections/foo.css?m=1660207177'   rel='stylesheet'>
  <!--rockfrontend-scripts-head-->
  <script src='/site/modules/RockFrontend/Alfred.js?m=1660123300'></script>
  <script src='/site/modules/RockFrontend/livereload.js?m=1660123300'></script>
  <script src='/site/templates/uikit-3.15.2/dist/js/uikit.min.js?m=1659941286' defer></script>
  <script src='/site/templates/uikit-3.15.2/dist/js/uikit-icons.min.js?m=1659941286' defer></script>
  <script src='/site/modules/RockFrontend/lib/alpine.min.js?m=1660123300' defer></script>
  <script src='/site/modules/RockFrontend/RockFrontend.js?m=1660203134' defer></script>
</head>

😎

v1.13.10 makes sure that LESS is forced to recompile on modules::refresh

  • Like 4
Link to comment
Share on other sites

What do you think about adding a feature to merge scripts and styles? Is that something we should have? Or is it even bad to have since HTTP2 can download multiple assets in parallel?

Link to comment
Share on other sites

7 hours ago, bernhard said:

What do you think about adding a feature to merge scripts and styles?

I personally use ProCache for that but it would still make an awesome feature.

7 hours ago, bernhard said:

Or is it even bad to have since HTTP2 can download multiple assets in parallel?

Multiple files or one single merged file... in the wrong hands both options can result in a slow loading site.

So... yes, no, maybe. It depends.

 

Link to comment
Share on other sites

v1.15.0 improves debugging even further and shows where the assets have been injected 😎

  <!-- loading /var/www/html/site/assets/RockMatrix/matrix/QuoteSlider.less --><!-- RockFrontend.module.php:365 -->
  <!-- loading /var/www/html/site/assets/RockMatrix/matrix/Spacer.less --><!-- RockFrontend.module.php:365 -->
  <!-- loading /var/www/html/site/assets/RockMatrix/matrix/Team.less --><!-- RockFrontend.module.php:365 -->
  <link rel='stylesheet' href='/site/templates/bundle/head.css?m=1660221858'><!-- less compiled by RockFrontend -->
  <link href='https://use.typekit.net/zeg8qpc.css'   rel='stylesheet'><!-- _main.php:5 -->
  <link href='/site/modules/RockFrontend/Alfred.css?m=1660215428'   rel='stylesheet'><!-- RockFrontend.module.php:152 -->

  <!-- DEBUG enabled! You can disable it either via $config or use $rf->scripts()->setOptions(['debug'=>false]) -->
  <!-- autoloading of default scripts enabled - disable using ->setOptions(['autoload'=>false]) -->
  <!-- rockfrontend-scripts-head -->
  <script src='/site/modules/RockFrontend/livereload.js?m=1660249767'></script><!-- RockFrontend.module.php:197 -->
  <script src='/site/templates/uikit-3.15.2/dist/js/uikit.min.js?m=1659941286' defer></script><!-- _main.php:8 -->
  <script src='/site/templates/uikit-3.15.2/dist/js/uikit-icons.min.js?m=1659941286' defer></script><!-- _main.php:9 -->
  <script src='/site/modules/RockFrontend/lib/alpine.min.js?m=1660215427' defer></script><!-- _main.php:10 -->
  <script src='/site/modules/RockFrontend/RockFrontend.js?m=1660215468' defer></script><!-- _main.php:11 -->
  <script src='/site/modules/RockFrontend/Alfred.js?m=1660250581'></script><!-- RockFrontend.module.php:151 -->

 

  • Like 1
Link to comment
Share on other sites

22 hours ago, bernhard said:

What do you think about adding a feature to merge scripts and styles? Is that something we should have? Or is it even bad to have since HTTP2 can download multiple assets in parallel?

HTTP/2 makes things more efficient, but it doesn't completely eliminate the overhead of downloading multiple files. As long as those files are the kind that "must always be loaded" (and "must always be loaded together"), I'd still say that the best practice is to merge and offer only one file to download.

Cases where merging makes little sense or might even have negative effect include scripts/styles that are only needed some of the time (e.g. big JS app related to single page/template, which the visitor may never encounter), JS/CSS that is intentionally split so that it gets loaded before other content (e.g. styles for the above the fold content), bundles where some parts are regularly updated while others remain as-is for long periods of time (i.e. having to invalidate cache for entire bundle unnecessarily often), etc.

If merging has to happen real-time, server resource usage / resulting delay would further diminish the benefits. So merged scripts/styles should preferably be served directly from disk, as static files.

Just my two cents. Not exactly a simple topic 🙂

  • Like 2
  • Thanks 1
Link to comment
Share on other sites

@bernhard So far I want to make use of the livereload feature only. I installed the module and set the reloading in my config file:

$config->livereload = 1;

But now it keeps reloading the page in intervals of 1 second continuously even when there are no changes made. 

Can you explain why this is the case?

Link to comment
Share on other sites

On 8/12/2022 at 9:20 PM, Spiria said:

As usual, everything you touch transforms into gold.

Thx @Spiria for your kind words 🙂 🙂 

19 hours ago, Stefanowitsch said:

Can you explain why this is the case?

I'd need more information for that... What OS are you using? What browser? What does the devtools say? etc... Are you working with DDEV? XAMPP? Laragon etc..?

  • Like 1
Link to comment
Share on other sites

50 minutes ago, bernhard said:

Thx @Spiria for your kind words 🙂 🙂 

I'd need more information for that... What OS are you using? What browser? What does the devtools say? etc... Are you working with DDEV? XAMPP? Laragon etc..?

Mac OS 11.2.3. Browser is Chrome 104.0.5112.79. I am using MAMP Pro 6.6

There is something going on in the dev tools. I've got the feeling that something keeps triggering the autorefresh. I excluded all scripts and CSS but it keeps on refreshing.

1309327304_Bildschirmfoto2022-08-15um13_18_13.thumb.png.575c1e2e744d6f1b480fcd5d474208b4.png

  • Like 1
Link to comment
Share on other sites

Yeah it got 5 changes in your example!

Can you try to exclude those files/paths in livereload.php in your pw root?

<?php namespace ProcessWire;
$exclude = [
  'your/path1',
  'your/path2',
];
include __DIR__."/site/modules/RockFrontend/livereload.php";

Does that work?

Link to comment
Share on other sites

2 hours ago, bernhard said:

Yeah it got 5 changes in your example!

Can you try to exclude those files/paths in livereload.php in your pw root?

<?php namespace ProcessWire;
$exclude = [
  'your/path1',
  'your/path2',
];
include __DIR__."/site/modules/RockFrontend/livereload.php";

Does that work?

Interesting. When excluding the sessions folder it stops from refreshing continuously.

But when I make a change to a php file for example the page start reloading again and again. Until I exclude the templates folder which is not what I want of course.

Link to comment
Share on other sites

Just added some docs about the render method as @wbmnfktr had troubles using it. Hope that helps:

The render() method

One of the fundamental concepts of RockFrontend is its render() method. Whenever you want to output markup just use render() and provide the file you want to render as first parameter:

<?= $rockfrontend->render('/path/to/your/file.php') ?>

If your file lives in /site/templates you can use short paths:

// will render /site/templates/sections/head.php
<?= $rockfrontend->render('sections/head.php') ?>

Your rendered files can be PHP or LATTE syntax. You can add other template engines easily (see below).

Variables in rendered files

All PW API variables will be available in your rendered files:

$rockfrontend->render('sections/foo.php');

// sections/foo.php
echo $page->title;
echo $config->httpHost;
echo $pages->get("/bar")->createdUser;
echo $user->isLoggedin();

Custom variables in rendered files

Note that render() works different than PHP's include or require! This is best explained by an example:

$foo = 'foo!';
include "path/to/your/file.php";

// file.php
echo $foo; // echos "foo!"

Whereas when using $rockfrontend->render() it works differently:

$foo = 'foo!';
echo $rockfrontend->render("path/to/your/file.php");

// file.php
Current page id: <?= $page->id ?> // this will work
Value of foo: <?= $foo ?> // foo is not defined!

But you can provide custom variables easily:

$foo = 'foo!';
echo $rockfrontend->render("path/to/your/file.php", [
  'foo' => $foo,
  'bar' => 'I am the bar value',
]);

// file.php
value of foo: <?= $foo ?> // outputs foo!
value of bar: <?= $bar ?> // outputs "I am the bar value"

You can also make all defined variables available in your rendered file, but note that this might overwrite already defined API variables (like $pages, $files, $config...) so use this technique with caution:

echo $rockfrontend->render('/path/to/your/file.php', get_defined_vars());
  • Like 3
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   1 member

×
×
  • Create New...