Skip to main content
Ben Nadel at cf.Objective() 2010 (Minneapolis, MN) with: Gert Franz
Ben Nadel at cf.Objective() 2010 (Minneapolis, MN) with: Gert Franz ( @gert_railo )

GetBaseTagList() Behavior With Different ColdFusion Custom Tag Invocations And Engines

By on
Tags:

After realizing that the CFImport tag has serious performance implications in Lucee CFML, I've been racking my brain trying to come up with optimizations that I might apply to my ColdFusion custom tag DSL for HTML emails. One of the options I was considering is changing the way the custom tags are invoked. However, in doing so, I've stumbled upon the fact that the getBaseTagList() function changes based on the invocation technique and on the ColdFusion runtime engine: Adobe ColdFusion vs. Lucee CFML.

To demonstrate I've created two ColdFusion templates, outer.cfm, which is completely blank, and inner.cfm, which outputs the getBaseTagList() results:

<p>
	<cfset writeOutput( getBaseTagList() ) />
</p>
<cfexit method="exitTag" />

Then, I created a test page which invokes these two tags, nested, using the three approaches available in ColdFusion:

<!--- Using CFModule to invoke ColdFusion custom tags. --->
<cfmodule template="./outer.cfm">
	<cfmodule template="./inner.cfm">
</cfmodule>

<!--- Using CF_ syntax to invoke ColdFusion custom tags. --->
<cf_outer>
	<cf_inner>
</cf_outer>

<!--- Using CFImport to invoke ColdFusion custom tags. --->
<cfimport prefix="here" taglib="./" />

<here:outer>
	<here:inner>
</here:outer>

Before I ran into this issue - and before I wrote this test code - I would have expected all three of these approaches to render the same exact output. However, when we run this code in the two main ColdFusion engines, we get the following:

Lucee CFML 5.3.7.48

CFMODULE

CF_INNER, CF_OUTER

CF_INNER, CF_OUTER

Adobe ColdFusion 2018

CF_INNER

CF_INNER, CF_OUTER

CF_INNER, CF_OUTER

In these results, there are two things to note:

  • When invoking the ColdFusion custom tags using the <CFModule> tag, neither engines report the nesting inside the outer.cfm custom tag.

  • When invoking the ColdFusion custom tags using the <CFModule> tag, Lucee CFML does not report the name of the custom tag, just the native module invocation.

I was surprised to see how CFModule works. I guess this style of invocation is more about wrapping a ColdFusion template inside an encapsulated execution and less about having it work alongside other custom tag.

One of the problems with this behavior is that it means a no-go for any CFModule based optimizations in my ColdFusion custom tag DSL. My DSL relies heavily on the getBaseTagList() function, and the ability to reach up into parent tags to both read and write data. But, if I can't identify parent tags accurately with CFModule, any optimizations there are dead-on-arrival.

This issue, along with the file-check overhead in a Dockerized container, is really taking the wind out of my sails. I really don't want to go back to having to pre-compile email templates. But, I also need a solution that scales well.

Want to use code from this post? Check out the license.

Reader Comments

205 Comments

oh, because I've never used them...I would have approached this very differently. How would you do this without custom tags? Personally, I think I would have created a bunch of functions p(), ul(), li(), etc.

15,674 Comments

@Chris,

To be fair, I don't use custom tags very much at all - just with all the "HTML Email" stuff I've been digging into, it suddenly is very useful to have all this information bubbled-up in my brain.

It's funny that you mention using functions like p() and li() - when I was thinking about alternate ways to possibly approach this, that was something that floated through my head. I didn't try to actually put any of that thought into action (cause I was already kind of sold on the Custom Tag path); but, I was intrigued by the concept.

I think part of the hurdle that my brain couldn't get past was that I could see it working for the "core" elements, but I wasn't sure how to get custom elements to work. I guess you would just have to define custom functions?

A lot of this has just been rabbit-holing off in different directions.

I believe in love. I believe in compassion. I believe in human rights. I believe that we can afford to give more of these gifts to the world around us because it costs us nothing to be decent and kind and understanding. And, I want you to know that when you land on this site, you are accepted for who you are, no matter how you identify, what truths you live, or whatever kind of goofy shit makes you feel alive! Rock on with your bad self!
Ben Nadel