Magnuss
you might be interested in this :
Iron Router + Blaze 3.0.2 Compatibility Issues & Solutions
This document describes the compatibility issues encountered when upgrading to Blaze 3.0.2 with Iron Router and the solutions implemented.
Root Causes
Issue 1: Loading Hook Template Rendering Conflict
Problem: Iron Router’s loading hook in /packages/ironrouter/lib/hooks.js was calling this.renderRegions() while showing the loading template. This created a conflict with Blaze 3.0.2’s template lifecycle when the route later became ready and tried to render templates to the same regions.
Symptoms:
-
Loading template (spinner) never disappears
-
Main content templates don’t render
-
Browser console shows subscriptions are ready, but UI remains stuck on loading
Issue 2: Named Yield Regions Not Working
Problem: Blaze 3.0.2 has compatibility issues with Iron Layout’s named yield syntax ({{>yield "header"}}). The regions are created in Iron Router’s layout object, but Blaze fails to properly render content to named yield placeholders in templates.
Symptoms:
-
Header templates render to Iron Router regions but don’t appear in the DOM
-
layout.regionKeys() shows correct regions, but {{>yield "header"}} doesn’t display content
-
Content gets rendered but appears in wrong locations or not at all
Solutions Implemented
Solution 1: Fix Iron Router Loading Hook
File: /packages/ironrouter/lib/hooks.js
Change:
// BEFORE (broken in Blaze 3.0.2)
Router.hooks.loading = function () {
if (this.ready()) {
this.next();
return;
}
var template = this.lookupOption('loadingTemplate');
this.render(template || defaultLoadingTemplate);
this.renderRegions(); // ← This line caused conflicts
};
// AFTER (fixed)
Router.hooks.loading = function () {
if (this.ready()) {
this.next();
return;
}
// Blaze 3.0.2 fix: Don't render loading template at all, just wait for ready
// The subscriptions will still load in the background, and when ready
// the action function will be called to render the proper templates
};
Result: Eliminates template rendering conflicts while preserving subscription loading behavior.
Solution 2: Replace Named Yields with Direct Template Inclusion
Problem Layout (MenuLayout):
<template name="MenuLayout">
{{>sAlert}}
{{>yield "header"}} ← Broken in Blaze 3.0.2
<div class="container-fluid p-0 calculatemaximumheight">
{{>yield}}
</div>
{{> tamtamFooter version=versionbuild}}
</template>
Solution Layout (CustomMenuLayout):
<template name="CustomMenuLayout">
{{>sAlert}}
{{> header}} ← Direct template inclusion instead of named yield
<div class="container-fluid p-0 calculatemaximumheight">
{{>yield}}
</div>
{{> tamtamFooter version=versionbuild}}
</template>
Route Changes:
// BEFORE (broken)
Router.route('/:tenant/login', {
layoutTemplate: 'MenuLayout',
action: function () {
this.render('header', { to: 'header' }); // ← Broken named yield
this.render('login');
}
});
// AFTER (fixed)
Router.route('/:tenant/login', {
layoutTemplate: 'CustomMenuLayout',
action: function () {
// Header included automatically in CustomMenuLayout
this.render('login'); // Only render main content
}
});
Migration Steps
Step 1: Fix Iron Router Loading Hook
-
Edit /packages/ironrouter/lib/hooks.js
-
Comment out this.renderRegions() call in the loading hook
-
Optionally remove template rendering entirely for cleaner behavior
Step 2: Create Custom Layout
-
Create CustomMenuLayout template that includes header directly
-
Keep {{>yield}} for dynamic main content
-
Import the new layout template
Step 3: Update Controllers
Update all controllers that used MenuLayout:
// Controllers to update:
authenticatedController = baseController.extend({
layoutTemplate: 'CustomMenuLayout', // Was 'MenuLayout'
});
authenticatedMgmtController = baseController.extend({
layoutTemplate: 'CustomMenuLayout', // Was 'MenuLayout'
});
authenticatedSUController = RouteController.extend({
layoutTemplate: 'CustomMenuLayout', // Was 'MenuLayout'
});
authenticatedStatsController = baseController.extend({
layoutTemplate: 'CustomMenuLayout', // Was 'MenuLayout'
});
Step 4: Update Individual Routes
Find routes with explicit layoutTemplate: 'MenuLayout' and change to CustomMenuLayout:
# Search for routes to update:
grep -n "layoutTemplate.*MenuLayout" client/main.js
Step 5: Remove Header Render Calls
Remove all this.render('header', { to: 'header' }) calls from route actions since header is now included automatically:
# Find calls to remove:
grep -n "this\.render('header', { to: 'header' })" client/main.js
Testing
Verify Fix Works
-
Navigate to routes that previously showed endless loading
-
Confirm header appears correctly
-
Verify main content renders without conflicts
-
Test route transitions work smoothly
Layouts That Don’t Need Changes
These layouts work fine with Blaze 3.0.2 (no named yields):
-
LoadLayout - Simple {{>yield}} only
-
RootLayout - Flexbox layout with {{>yield}}
-
NoMenuNoFooter - Minimal {{>yield}}
-
WebSales - Styled {{>yield}}
Key Insights
-
Named yields are the problem: {{>yield "regionName"}} doesn’t work reliably in Blaze 3.0.2
-
Simple yields work fine: {{>yield}} continues to work normally
-
Direct template inclusion works: {{> templateName}} is more reliable than named yields
-
Loading hook conflicts: Template rendering during loading phase conflicts with subsequent renders
Alternative Solutions Considered
Option 1: Fix Iron Layout Package
-
Pros: Would preserve existing route structure
-
Cons: Complex, requires deep understanding of Blaze internals
-
Result: Not attempted due to complexity
Option 2: Downgrade Blaze
-
Pros: Would preserve all existing code
-
Cons: Misses bug fixes and improvements in Blaze 3.0.2
-
Result: Not recommended for long-term maintenance
Option 3: Switch to Flow Router
-
Pros: Modern router designed for current Meteor versions
-
Cons: Major breaking change requiring extensive refactoring
-
Result: Out of scope for immediate fix
Impact
Routes Fixed: 50+ routes across 4 controllers + individual route declarations
Files Modified:
-
/packages/ironrouter/lib/hooks.js - Core loading hook fix
-
/imports/ui/customlayout.html - New layout template
-
/client/main.js - Route and controller updates
Compatibility: Solution maintains full backward compatibility while fixing Blaze 3.0.2 issues.
This solution was developed and tested with Meteor 3.3.1, Iron Router 2.0.0 (polygonwood:router), and Blaze 3.0.2.