Jump to content

RockFrontend 🚀🚀 The Powerful Toolbox for ProcessWire Frontend Development


bernhard

Recommended Posts

On 8/12/2023 at 11:28 AM, Stefanowitsch said:

Can you explain what this feature does?

Hey @Stefanowitsch thx for the question. I tried, but it's not so easy. The feature has been developed for RockCommerce where I ship a fully working checkout that is both easy to integrate and to customise. All files are in /site/modules/RockCommerce/frontend/... and can be overwritten by placing the same file in /site/templates/RockCommerce

I don't think that this will be very helpful to anybody else, so I thought it's better not to bloat the docs with that feature at the moment.

But I've added docs for the static rendering feature, which can be very helpful for many projects I think:

Static Rendering

Static Rendering is a convenient feature offered by RockFrontend that simplifies the process of developing new websites or features. It provides an alternative approach to generating markup by allowing developers to write static markup for specific pages or components, rather than utilizing multiple includes and delving into the intricacies of the entire project's architecture.

How it Works

If your project is already using RockFrontend's renderLayout() method to generate page layouts, integrating the Static Rendering feature is straightforward. All you need to do is create static markup files and place them within the designated folder: /site/templates/static.

When a user requests a particular page, RockFrontend's Static Rendering functionality kicks in. It examines the requested page's URL and checks whether there is a corresponding static file in the /site/templates/static directory that matches the URL's structure.

For example: If a user requests your.site/foo/bar, RockFrontend will search for a static file located at /site/templates/static/foo/bar.[php|latte].

Benefits

Static Rendering offers several benefits for developers, including:

  • Simplified Development: Writing static markup can be more straightforward than dealing with complex includes and understanding the project's full architecture.
  • Quick Prototyping: Static Rendering enables developers to quickly prototype ideas without the need to set up dynamic functionality.
  • Unique Custom Layouts: With Static Rendering, you can craft highly distinctive layouts for individual pages, allowing you to create designs that stand out from the rest of the website and cater to specific visual and functional requirements.
  • Isolation: Developers can work on specific pages or components in isolation without affecting the rest of the application.

Implementation Steps

  1. Create Static Files: Write the static markup for the desired pages or components and save them with filenames that match the URL structure. Place these files in the /site/templates/static directory.

  2. Access Static Rendered Pages: Once the static files are in place, RockFrontend will automatically use them for rendering when a user accesses the corresponding URLs.

  • Like 1
Link to comment
Share on other sites

Hi @bernhard is it possible to load a <script> tag or to load specific javascript file for only a specific page and/or template using Rockfrontend ? Right now _main.php is handling all scripts site-wide. Was wondering how granular this can go.

Thanks for such a great module.

Link to comment
Share on other sites

6 hours ago, protro said:

Hi @bernhard is it possible to load a <script> tag or to load specific javascript file for only a specific page and/or template using Rockfrontend ? Right now _main.php is handling all scripts site-wide. Was wondering how granular this can go.

Thanks for such a great module.

As far as I know (and I haven't used this feature yet!) this should be possible (found here: https://processwire.com/modules/rock-frontend/)

You can make use of the addIf() function to load a script only under special circumstances.

Adding assets to your site (JS or CSS)


While you can always add custom <script> or <link> tags to your site's markup it is recommended that you use RockFrontend's AssetsArray feature:

$rockfrontend->scripts()
  ->add('/path/to/your/script.js')
  // you can add any custom flags to your $rockfrontend variable at runtime!
  ->addIf('/path/to/foo.js', $rockfrontend->needsFooScript)
  ->addIf('/path/to/slider.js', $page instanceof HomePage)
  ->addIf('/path/to/blogscript.js', $page->template == 'blogitem')
  ;
$rockfrontend->styles()
  ->add(...)
  ->addIf(...)
  ;

There are several reasons why this is preferable over adding custom script/style tags:

  • addIf() keeps your markup file cleaner than using if / echo / endif
  • It automatically adds timestamps of files for cache busting
  • You can inject scripts/styles from within other files (eg PW modules)

RockFrontend itself uses this technique to inject the styles and scripts necessary for frontend editing (ALFRED). Have a look at the module's init() method!

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

very helpful @Stefanowitsch thank you very much for pointing out those different conditions. Another awesome demonstration of Rockfrontend's capabilities 🙂

In my case I spoke too soon and what I was actually attempting to do was to inject code into the _main.php <head> if I was on a certain template / page / etc. But because I am using the ProcessWire $config->urls->templates method to obtain the url for the script via php, I can't do that by loading an external.js file via AddIf … for example:

<!-- threejs code -->
    	<script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script>
		<script type="importmap">
			{
				"imports": {
					"three": "<?php echo $config->urls->templates?>scripts/build/three.module.js",
					"three/addons/": "<?php echo $config->urls->templates?>scripts/jsm/"
				}
			}
		</script>

But then I came across a section of the Markup Regions in ProcessWire post which explained what I was attempting to do, and for me is a new discovery of ProcessWire 🙂

Quote

The above _main.php represents our common document markup, though if we need something entirely different for any particular templates (like our homepage, RSS feed, or the like) we can do so by editing the template settings in the ProcessWire admin to use a different file, or no file at all, when appropriate. (This is found in Setup > Templates > [template] > Files [tab]).

So what I did was create a _main_webgl.php file and specify in my template to ignore _main.php and load this one instead. Maybe not the most elegant solution, but it is separating the logic nicely and allowing me to not have to load unnecessary scripts depending on the page / template. Very nice!

  • Like 1
Link to comment
Share on other sites

49 minutes ago, protro said:

In my case I spoke too soon and what I was actually attempting to do was to inject code into the _main.php <head> if I was on a certain template / page / etc. But because I am using the ProcessWire $config->urls->templates method to obtain the url for the script via php, I can't do that by loading an external.js file via AddIf … for example:

I don't understand what you are saying here. And it sounds totally contrary to what you say afterwards.

RockFrontend's "addIf()" for adding single scripts depending on conditions is one thing, but replacing the whole markup is something totally different.

If you are trying to do the latter you have two options. One is what you describe and make ProcessWire NOT use the _main.php file.

Another option would be to be more explicit in _main.php and put something like this on top of the file:

<?php

if($page->template == 'foo') return $rockfrontend->render('my/custom/markupfile.[php|latte]');

...

// content of _main.php here that will be loaded for all templates except 'foo'

Another concept that RockFrontend provides is the renderLayout() method.

The concept is to put this in _main.php:

<html>
  <head>...</head>
  <body>
    <?= $rockfrontend->renderLayout() ?>
  </body>
</html>

Which will tell RockFrontend to load /site/templates/layouts/default.php by default and load /site/templates/layouts/foo.php for all pages with template "foo".

So you have lots of options 🙂 

  • Like 2
Link to comment
Share on other sites

  • 2 months later...
On 11/16/2022 at 6:29 AM, maetmar said:

Hi @bernhard

I found an issue with the livereload feature. When enabled, I get the following error message in chrome development console:

"EventSource's response has a MIME type ("text/html") that is not "text/event-stream". Aborting the connection."

https://stackoverflow.com/questions/53591954/eventsources-response-has-a-mime-type-text-html-that-is-not-text-event-str

It is reproducable, as soon as livereload is turned off, the error message is gone.
The message is not causing any issues, as far as I can tell, but I was spending now a lot of time just to find out it was caused by livereload.
So maybe you can check and make sure it gets fixed.

Hi @bernhard I recently acquired a new work machine and am getting this unexpected EventSource error every 2-3 saves with PW + Rockfrontend. It's driving me mad because I know you are seeking reproducible steps and I can't seem to pinpoint exactly what is causing it, except for editing CSS classes within pre-existing HTML markup is OKAY and livereload is triggered, but addition of new HTML syntax and/or Latte syntax throws the error.

pseudo-Reproducible Steps:

Hardware: MacBook with macOS 13.6.1
Software: VS Code 1.84.0, MAMP 6.8, ProcessWire 3.0.229, Rockfrontend 3.7.0, Chrome 119.0.6045.105

php no longer ships with new macOS versions so I installed via brew install php.
MAMP has its own php 8.2 binary, which I thought I needed to set VS Code's settings.json to:

php.validate.executablePath": "/Applications/MAMP/bin/php/php8.2.0/bin/php",

but that seems to have no effect. Either way, just wanted to bring this to your attention. I am quite perplexed.

Link to comment
Share on other sites

1 minute ago, protro said:

php no longer ships with new macOS versions so I installed via brew install php. MAMP has its own php 8.2 binary, which I thought I needed to set VS Code's settings.json to:

php.validate.executablePath": "/Applications/MAMP/bin/php/php8.2.0/bin/php",

but that seems to have no effect. Either way, just wanted to bring this to your attention. I am quite perplexed.

I fear I don't have any idea for you, but have you considered using DDEV? I think it would be worth trying, because it is such a great and hassle free dev environment and maybe your issue will be solved as well!

 

  • Like 1
Link to comment
Share on other sites

Thanks @bernhard I will check out DDEV.

One last thing I am seeing is this in the Inspector Application Tab


Deprecated:  Creation of dynamic property RockFrontend\LiveReload::$config is deprecated in /Applications/MAMP/htdocs/my-project/site/modules/RockFrontend/LiveReload.php on line 24

Link to comment
Share on other sites

11 minutes ago, protro said:

Deprecated:  Creation of dynamic property RockFrontend\LiveReload::$config is deprecated in /Applications/MAMP/htdocs/my-project/site/modules/RockFrontend/LiveReload.php on line 24

I'm not seeing this. Neither with 8.1 nor with 8.2..

Link to comment
Share on other sites

  • 1 month later...
  • 4 weeks later...
  • 2 months later...

This is a really nice update for RockFrontend available on the DEV branch!

You need a sitemap for your website? All you have to do is this in /site/ready.php:

rockfrontend()->sitemap();

Really, that's all!

Here are the docs with info about customisation and how it works: https://github.com/baumrock/RockFrontend/tree/dev/docs/seo#sitemapxml

SEO is not my expertise, so I'd appreciate input from the community in how to make SEO tools in RockFrontend even better! Maybe I can even merge input until I push everything on the main branch in April 🙂 

There are also some quick-checks on the settings page to not forget the basics:

4Szrlfl.png

  • Like 3
Link to comment
Share on other sites

  • 3 weeks later...

Just started using RockFrontend on a local site and I'm relly enjoying livereload when updating .latte templates.

In fact, as I work with my admin pages in a window on the left, and the site in a window on the right of my screen, I wanted to get livereload when saving pages in the admin - but only for the basic-page template. So here's a little hack. Adding this to site/templates/admin.php, before the line require($config->paths->core . "admin.php"); works great, and I now get livereload on page save or file changes. Not sure how well this will work with Alfred though as I'm not using that yet.

$pages->addHookAfter('saved', function($event) {
    $p = $event->arguments(0);
    if (in_array($p->template->name, ['basic-page'])) { // Update array as needed
        $touchfile = __DIR__ . "/.lastupdate";
        touch($touchfile);
    }
});
  • Like 1
Link to comment
Share on other sites

31 minutes ago, netcarver said:

Just started using RockFrontend on a local site and I'm relly enjoying livereload when updating .latte templates.

Great to hear that 🙂 

32 minutes ago, netcarver said:

In fact, as I work with my admin pages in a window on the left, and the site in a window on the right of my screen, I wanted to get livereload when saving pages in the admin - but only for the basic-page template. So here's a little hack. Adding this to site/templates/admin.php, before the line require($config->paths->core . "admin.php"); works great, and I now get livereload on page save or file changes. Not sure how well this will work with Alfred though as I'm not using that yet.

This is interesting. I've never really had the need for that - maybe because RockPageBuilder is doing that for me and I don't need it at all on frontend editing - but I'm wondering if a module setting could make sense. I could think of a checkbox "trigger frontend reload on page save", or maybe a config setting. A config setting could have a page selector that checks if the saved page matches the selector and only reloads if it's true.

But I'm also wondering how that feature would be used and by whom. Would it be a developer thing? Or could it maybe also be useful for regular site editors? So far Livereload was really only intended for local development, but the technique has been quite reliable and should work with any infrastructure as SSE + JS is available everywhere...

  • Like 1
Link to comment
Share on other sites

Hey @bernhard - I will be trying out RockPageBuilder on a project soon - but for now, I think a config setting for the livereload feature, that allows a superuser to configure which templates to livereload pages for, would be a neat feature for anyone who doesn't get RockPageBuilder.

Personally, I would only use this feature for local development though.

Link to comment
Share on other sites

On 4/8/2024 at 4:29 PM, netcarver said:

but for now, I think a config setting for the livereload feature, that allows a superuser to configure which templates to livereload pages for, would be a neat feature for anyone who doesn't get RockPageBuilder.

Hi @netcarver thx for the suggestion. Could you please explain why that would be useful and what that has to do with RockPageBuilder? I'm afraid I don't understand 🙂 

FYI @ everybody else: Next release will have improved debugging for Ajax endpoints thx to a request by @netcarver 🙂😍

68747470733a2f2f692e696d6775722e636f6d2f

https://www.baumrock.com/en/processwire/modules/rockfrontend/docs/ajax/

  • Like 2
Link to comment
Share on other sites

Hi @bernhard thanks for the recent improvements to the livereload feature! Please ignore my suggestion above - it was just a "I wonder if..." kind of thing. What you've done with adding things to the error and ajax pages are great.

  • Like 2
Link to comment
Share on other sites

  • 2 weeks later...

Hey @bernhard, just updated a site to Rockfrontend 3.13.1 and noticed that auto-loading assets via

$rockfrontend->styles()->add('foo.css');
$rockfrontend->scripts()->add('bar.js');

now has the order reversed in the generated markup.

<script src='bar.js?m=1712642262'></script>
<link href='foo.css?m=1713850912' rel='stylesheet'>

Which in case of using UIKit is probably not ideal, since in my understanding the CSS should be loaded before the JS. Can you reproduce this or is something messed up on my part?

Also, on a live site and with debug mode off, RF still renders a tag

<script>var RockFrontend = {"isDDEV":false}</script>

in the html head, wonder if that is necessary or what the purpose of that could be. Any pointers here? Not using RockFrontend.js if that's related in any way.

Greetings to Austria and thanks in advance! 🙂

  • Like 1
Link to comment
Share on other sites

Hey @Andi thx for your open eyes!

On 4/23/2024 at 5:17 PM, Andi said:

Also, on a live site and with debug mode off, RF still renders a tag

<script>var RockFrontend = {"isDDEV":false}</script>

I've just pushed a "fix" for this on the dev branch. The thing is that this JS markup is needed sometimes and therefore will be rendered as soon as RockFrontend has some variables set. This was the case for isDDEV and therefore you saw the output.

I don't see anything bad with having that markup on my sites. If anyone has good reasons to remove it let me know.

The idea is to have a central place to send settings from the backend to the frontend. Some of them are only necessary when logged in, but there might also be situations where a module wants to set something that the frontend consumes. For example the root url of the site, that is unfortunately not always "/" but could also be a subfolder like "/myproject". On the backend that's easy via $config->urls->root, but on the frontend there is no standard and so I added this global RockFrontend variable/object that can hold these kind of things.

On 4/23/2024 at 5:17 PM, Andi said:
$rockfrontend->styles()->add('foo.css');
$rockfrontend->scripts()->add('bar.js');

now has the order reversed in the generated markup.

<script src='bar.js?m=1712642262'></script>
<link href='foo.css?m=1713850912' rel='stylesheet'>

The order in which you call ->styles() or ->scripts() does not define the order of the output. This method defines it:

  private function injectAssets(string &$html): void
  {
    $assets = '';
    foreach ($this->autoloadScripts as $script) $assets .= $script->render();
    foreach ($this->autoloadStyles as $style) $assets .= $style->render();
    $html = str_replace("</head>", "$assets</head>", $html);
  }

That means scripts will always be rendered first, then styles.

I can change that if anyone has good reasons, though I think it does not make a difference. The more important thing is that you can or probably should add "defer" to your scripts, which makes the script load at a later point when the dom is ready.

With UIkit this can lead to problems though as it might cause FOUC, because uikit adds custom classes like "uk-grid" when using <div uk-grid> for example. If you are not using defer, then it will work without issues. If using defer, you'd had to add the class manually: <div class="uk-grid" uk-grid>

I'm simply loading these 47.8kB upfront to make my life easier.

  • Like 1
Link to comment
Share on other sites

Thanks for the insights @bernhard, so about the loading order

On 4/24/2024 at 5:50 PM, bernhard said:

That means scripts will always be rendered first, then styles.

That's the part I was wondering about, since it used to be the other way around in earlier version of RF, as far as I remember. I was wondering if that was an intentional change.

Just autoloading the UIKit CSS and JS files (without defer) in the current build gives me pretty bad FOUC and Firefox complaining

Quote

"Layout was forced before the page was fully loaded. If stylesheets are not yet loaded this may cause a flash of unstyled content."

If I reverse the order by disabling autoload and rendering the assets manually those Firefox warnings disappear, and I feel like the pages render a lot smoother in FF.

As for other libs I'm using on a regular basis, at least Leaflet is pretty specific about the loading order of CSS and JS, see here https://leafletjs.com/examples/quick-start/

Quote

Include Leaflet JavaScript file after Leaflet’s CSS

But I guess that too could be handled via the "defer" method you described earlier. Just need to keep it in mind 😄

Link to comment
Share on other sites

On 4/25/2024 at 7:05 PM, Andi said:

Just autoloading the UIKit CSS and JS files (without defer) in the current build gives me pretty bad FOUC and Firefox complaining

Quote

"Layout was forced before the page was fully loaded. If stylesheets are not yet loaded this may cause a flash of unstyled content."

If I reverse the order by disabling autoload and rendering the assets manually those Firefox warnings disappear, and I feel like the pages render a lot smoother in FF.

Hey @Andi I've just pushed a "fix" for this on the latest dev. I did some research and from what I read it should not make a difference, but if at all it might be better to load styles first and then scripts, so that's what I'm doing now.

The load order has always been scripts then styles. So nothing changed here in the past.

  • Like 1
Link to comment
Share on other sites

From latest Rock Monthly newsletter:

RockFrontend v3.14.0

  • LiveReload does now work on Tracy's bluescreen! That means if you introduce an error that throws an exception (like a typo that causes a call to undefined function...) you don't have to leave the IDE and reload the browser. Simply fix the bug and your browser will refresh!
  • The great AJAX Endpoints feature has been improved thx to @netcarver
  • We now have LiveReload on AJAX Endpoint debug screens!
  • We now support relative urls in the svgDom() method + improved docs.
  • Sitemap tools have been improved and multilang support has been added, see docs: https://tinyurl.com/ywflthta
  • SEO tools improved: canonical tag now by default!
  • Like 2
Link to comment
Share on other sites

@bernhard I have a question about the AJAX/HTMX Endpoints feature:

Is it possible to get access to the $page API variable inside my endpoint file to "see" from which page the request was sent? 

When submitting a form I want to include the title of the page form where the form was submitted into the E-Mail subject line.

The only way I see right now is to add the page ID as a parameter to the endpoint URL.

Link to comment
Share on other sites

The endpoints don't have a $page, because they are not a page 🙂 It's just an url hook behind the scenes. You can add the page url in a hidden field of the form.

  • Like 1
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
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...