So... While trying to implement tag variable hoisting, we ran into some conceptual issues. What happens in these cases?
<my-input-range><div>${value}</div>
<my-input-range/value/>
<dims><div>
<dims/{ x, y }/>
</div>
Technical Marko discussion
[ ] Why Marko?Where it stands in the wider ecosystem
The problems that Marko solves
What makes the Tags API special
[ ] How to spend 5 years making a framework
And why did it take so long?! Michael, a software engineer at eBay and member of the Marko core team will walk through the challenges, design decisions and tradeoffs made while evolving the Marko framework used by hundreds of pages on ebay.com. Lots of interesting learnings and you'll get a look at the newly released Marko 6 which is open source and available to use for your own projects.
OutcomesLearn more about optimizing for the web
Tradeoffs made by various frontend frameworks
Performance
Streaming
High throughput
Targeted compilation
ResumabilityAvoid redoing server work
Avoid bundling server only operations
Fine grained reactivty
DX
Luke LaValva changed 5 months agoView mode Like Bookmark
Tags API docs (not good, here is the reference)
Marko is a superset over a subset of html.
The goal of Marko is to make HTML more strict (think a linter) while also extending HTML with the ability to represent declarative UI's with control flow and reactive data bindings. It does this by meshing JavaScript syntax features within html's semantics and introducing a few new syntaxes of it's own. Most HTML is valid Marko but there are some important deviations.
Attributes
The attributes of a tag in Marko come through to the child as an object (the object is available as a render scoped variable called input, more on that later).
Attribute values are JavaScript expressions meaning you can do cool things like:
Dylan Piercey changed 6 months agoView mode Like Bookmark
Syntax
Marko is roughly a superset of the HTML, reimagined as a language for building dynamic and reactive user interfaces. Most .html files can also compile as .marko files, but Marko also extends the language to provide tools which allow building modern applications in a declarative way.
ProTip
Marko also supports a beautiful concise syntax. If you'd prefer to see the documentation using this syntax, just click the "Switch Syntax" button in the corner of any Marko code sample.
Map of Marko's tag syntax:
renderBody
Dylan Piercey changed 6 months agoView mode Like Bookmark
Hoisting from Conditional Body
<if=show>
<const/hoisted = "hi"/>
</if>
-- ${hoisted}
hoisted is rendered once with undefined if show is falsy or hi if show is truthy.
<if=show>
<const/hoisted = "hi"/>
</if>
Luke LaValva changed 7 months agoView mode Like Bookmark
Why would we use JSX?
Familiarity with JSX coming from other frameworks that use itSolid probably owes some of its success to "looking like React"
Vue added JSX for this reason?
We get tooling for "free"
Tools we've had to build (and now maintain)typescript checker (mtc)
prettier
htmljs-parser
tmbundle (syntax highlighting)
The current implementation requires adding (and serializing) effects for every option in the select. And it makes sense, because every option could be doing something different on selectedValueChange
<select>
<option value="AL" selectedValue:=input.value>Alabama</>
<option value="AK" selectedValue:=input.value selectedValueChange() { console.log("too cold!") }>Alaska</>
<option value="AZ" selectedValue=input.value selectedValueChange() { console.log("too hot!") }>Arizona</>
<option value="AR" selectedValue:=input.value>Arkansas</>
<option value="CA">California</>
</>
We can't easily restrict all options to have the same selectedValueChange, because you'd be forced to hoist functions where you wouldn't otherwise. The following despite having the same implementation has a different instance of selectedValueChange for each iteration of the <for>
Scoping Rules
Tag Scope
Tag Variables follow similar scoping rules to JavaScript’s let and const, but instead of being block-scoped, Tag Variables <let> and <const> are tag-scoped.
Redeclaring
A Tag Variable cannot be declared more than once per scope:
<let/x = 0/>
<let/x = 1/> // SyntaxError: 'x' has already been declared in the current scope
<const/x = 1/> // Same error as above
Luke LaValva changed 9 months agoView mode Like Bookmark
TL;DR
Developer ExperienceFewer concepts to learn and less boilerplate
Encourages safer and more correct patterns
Optimized for colocation, refactoring and componentization
User Experience
Only interactive code is bundled for the browser
Server work is not re-executed on the browser
Performant fine-grained updates instead of vdom/diffing
Dylan Piercey changed 9 months agoView mode Like Bookmark
Uncontrolled components
Mostly work like native stateful HTML elements:
Own and manage their state (“self-controlled”)
May accept an initial state
May provide an imperative API to view/update their state
May emit events when their state changes
Controlled components
Receive their current state from parent
Luke LaValva changed 9 months agoView mode Like Bookmark
How can we return multiple tag variables with proper binding?
At first we thought we needed this every time:
<let/count=0 />
<let/message="hello" />
<return={
count,
countChange(newCount) {
count = newCount;
Dylan Piercey changed 9 months agoView mode Like Bookmark
Ryan wrote a lovely article about two-way data binding… but I do take a bit of issue with Marko getting lumped into the same category as Vue when it comes to its approach to data flow, so I wanted to set the record straight.
And maybe show a better path that other frameworks could adopt. 🤷
Recap: Problems with two-way binding
Ryan lays out the problem with two-way binding and it boils down to a handful of issues:
1. Unpredictable data flow
the creator of that state has no idea if and how the child will mutate it
—Ryan Carniato
Dylan Piercey changed 9 months agoView mode Like Bookmark
Step 0 - Ensure you're in a working state on the latest version of Marko 4
Before we start, you'll want to make sure that you are already on the latest 4.x release of marko.
# Upgrade using yarn
yarn upgrade marko@^4
# Upgrade using npm
npm install marko@^4
[!Warning]
Do not run npm install marko (without the @^4). This will put you on Marko 5 and we're not quite there yet.
Currently the <tag> tag has some aspects we do not love.
It requires mixing both tag parameters and tag variable syntaxes which can look daunting
It is currently able to be nested anywhere in the template and gives the variable to the render scope, but we would like to restrict that so that these tags are within the static scope of the template.
Because of the above it is impossible to export these tag tags which can be useful for some scenarios.
We are toying with the idea of re-using the attribute tag syntax for defining these tags/macros.
Essentially, top level attribute tags could automatically expose JavaScript identifiers which you can work with.
(Currently top level attribute tags are meaningless and a compile error).
Saulo Vallory changed a year agoView mode Like Bookmark
Directives are a syntax sugar for custom tags that adhere to a specific contract: they receive a value and (optional) var and return an object of attributes to spread into a tag.
Details
Basic Example
<onLongPress/attrs() {
console.log("hello")
}/>
<button ...attrs>Say Hello</button>
With the syntax sugar, this becomes:
Luke LaValva changed a year agoView mode Like Bookmark