Definition
CFML (ColdFusion Markup Language) is the tag-based language used in Adobe ColdFusion and Lucee servers to build dynamic web applications. It looks and feels like HTML with special tags that start with cf, such as
CFScript is the script-style Syntax for writing ColdFusion code using statements and expressions similar to JavaScript or C-like languages (e.g., var x = 1; if (…) { … }). CFScript covers most of the same Features as CFML tags but in a more concise, code-oriented Syntax.
Put simply: CFML uses tags; CFScript uses code blocks. Both run on the same ColdFusion engine, can be mixed in the same file, and ultimately compile to the same bytecode.
How It Works
- Same engine, two syntaxes: Whether you write tags (
) or script (if (…) {}), the ColdFusion or Lucee engine compiles both into Java bytecode. Performance differences are negligible for most apps. - Mix-and-match: You can write HTML with CFML tags and drop into a
block for logic, or build entire components (.cfc) purely in CFScript. - Coverage parity (mostly): Modern ColdFusion and Lucee provide CFScript equivalents for nearly all tags, often via built-in functions (e.g., queryExecute()) or scriptable components (e.g., new http()).
- Server compatibility: Adobe ColdFusion and Lucee share the core language but have minor differences in built-ins and edge-case behaviors. Most everyday CFScript/CFML code is cross-compatible.
When to Choose CFML vs CFScript
-
Choose CFML (tag-based) when:
- You’re building HTML-heavy templates and prefer interleaving markup and dynamic output.
- You need tag conveniences like
, , with straightforward attributes. - You’re maintaining legacy codebases that are tag-centric.
-
Choose CFScript (script-based) when:
- You’re writing Business logic, services, or ColdFusion Components (CFCs).
- You prefer a JavaScript-like syntax and better IDE/linting support.
- You want cleaner, testable code with functions, closures, and structured Control flow.
Side-by-Side Syntax Examples
Variables and Output
CFML:
CFScript:
name = “World”;
writeOutput(“Hello ” & name);
Conditionals and Loops
CFML:
<cfif score gte 90>
CFScript:
if (score >= 90) {
writeOutput(“Grade: A”);
} else if (score >= 80) {
writeOutput(“Grade: B”);
} else {
writeOutput(“Grade: C or below”);
}
for (i = 1; i <= 3; i++) {
writeOutput(i);
}
Database Queries
CFML:
SELECT id, name
FROM users
WHERE status =
CFScript:
qUsers = queryExecute(
“SELECT id, name FROM users WHERE status = ?”,
[ { value=”active”, cfsqltype=”cf_sql_varchar” } ],
{ datasource=”myDSN” }
);
Iterating results safely:
queryEach(qUsers, function(row) {
writeOutput(row.name);
});
HTTP requests
CFML:
CFScript (scriptable HTTP component):
http = new http();
http.setUrl(“https://api.example.com/users“);
http.setMethod(“get”);
resp = http.send();
writeOutput(resp.fileContent);
Error handling
CFML:
CFScript:
try {
result = 100 / x;
} catch (any e) {
writeOutput(“Error: ” & e.message);
}
Components and Functions
CFML:
CFScript:
component output=false {
public numeric function add(required numeric a, required numeric b) {
return a + b;
}
}
Pros and cons
-
CFML (tag-based)
- Pros:
- Natural for templating with HTML/CSS.
- Quick to wire up built-in services via attributes.
- Easy for designers or tag-oriented teams.
- Cons:
- Can become verbose and harder to test for complex logic.
- Mixing heavy logic in tags can hurt readability.
- Pros:
-
CFScript (script-based)
- Pros:
- Concise, readable logic; familiar to JS/Java developers.
- Better for modular CFCs, Unit testing, and API services.
- Strong IDE/linting support; easier Control flow.
- Cons:
- Some legacy tag Features may need script alternatives or wrappers.
- Template-heavy pages can feel less “inline” than tag-based.
- Pros:
Real-World Use Case: Product Listing Page
A typical approach is to use CFScript for logic and CFML for the view:
- Controller (CFScript in Application.cfc or a handler): query the database, format data, handle errors.
- View (CFML .cfm template): render the HTML and iterate results.
Example snippet:
Controller (CFScript):
products = queryExecute(
“SELECT id, title, price FROM products WHERE active = 1 ORDER BY title”,
[],
{ datasource=”storeDSN” }
);
View (CFML):
- #products.title# – $#numberFormat(products.price, ‘9,999.99’)#
This separation keeps Business logic testable and templates clean, while leveraging the strengths of each syntax.
Best practices
- Favor CFScript for business logic and CFML for markup. Keep responsibilities clear.
- Use cfqueryparam (or parameterized queryExecute) to prevent SQL injection.
- Be explicit with variable scoping (e.g., local., variables., arguments., application.) to avoid collisions.
- Minimize broad
blocks; wrap only where output is needed, or use writeOutput sparingly. - Organize code into CFCs with public/private functions; avoid large monolithic templates.
- Keep a consistent style per file to improve readability; avoid excessive back-and-forth between tags and script.
- Log and handle errors with try/catch and the server’s logging facilities.
- For cross-engine compatibility (Adobe CF and Lucee), prefer standardized functions like queryExecute and avoid engine-specific extensions when possible.
Key Points
- Two syntaxes, one platform: CFML and CFScript are two ways to express ColdFusion logic; both compile to the same runtime.
- CFML excels at templating, CFScript excels at logic. Use both strategically.
- Parity is high: Most tags have script equivalents via functions or components.
- Maintainability matters: Pick a dominant style per layer (view vs service) and stick with it.
- Security and scoping are critical regardless of syntax.
Common Syntax Nuggets
- Comments:
- CFML: <!— comment —>
- CFScript: // single-line or / multi-line /
- String interpolation in CFScript: writeOutput(“Hi #name#”);
- Includes:
- CFML:
- CFScript: Use tags for includes or check engine support for include in script in your version.
- CFML:
- Date/time, lists, arrays, and structs share the same built-in functions across both syntaxes (e.g., now(), listToArray(), arrayMap(), structKeyExists()).
Comparison Table
| Aspect | CFML (Tags) | CFScript (Script) |
|---|---|---|
| Primary Use | Markup-heavy templates | Business logic, services, APIs |
| Readability | Clear with HTML | Clear with code |
| Verbosity | More verbose for logic | More concise for logic |
| Learning curve | Easy for HTML-centric devs | Easy for JS/Java devs |
| Tooling | Template-oriented | Strong code linting/IDE |
| Parity | Near-complete | Near-complete |
FAQ
What’s the Performance difference between CFML and CFScript?
For typical applications, no meaningful difference. Both compile to the same bytecode. Choose based on readability, maintainability, and team familiarity.
Can I mix CFML and CFScript in the same file?
Yes. It’s common to use
Modern engines (Adobe ColdFusion and Lucee) provide equivalent script features for nearly all tags, commonly via functions (e.g., queryExecute) or scriptable components (e.g., new http()). Check your engine/version docs for any edge cases.
Which should I use for new projects?
A practical pattern is: CFScript for business logic and CFCs, CFML for views. This keeps logic testable and views straightforward. If you’re building APIs or headless services, you can go mostly CFScript.
Is CFScript closer to JavaScript?
The syntax is JavaScript-like, with familiar constructs (if, for, try/catch, functions). While not identical to JS, developers with JS/Java backgrounds typically find CFScript intuitive and concise.
