|
1 | | -# Using Marko 5 and Marko 6 together |
| 1 | +# Using Multiple Marko Versions |
2 | 2 |
|
3 | | -All Marko 5 apps are equipped to use tags API components without any changes. To use both Marko 5 and Marko 6 together, ensure that Marko 5 is installed at the project root. |
| 3 | +> [!TLDR] |
| 4 | +> - `marko@6` is _not_ backward compatible |
| 5 | +> - `marko@5` is **forward compatible** |
| 6 | +> - In Marko 5, heuristics determine runtime version per-tag |
| 7 | +
|
| 8 | +[Marko 5](https://v5.markojs.com/) uses the [Class API](https://v5.markojs.com/docs/class-components/), and current versions use the [Tags API](../reference/language.md). Marko 6 is _not_ backwards compatible, so if `marko@6` is installed an application cannot use class components out of the box. Instead, Marko 5 is **forward compatible**. To use multiple versions of Marko together, ensure that Marko 5 is installed at the project root. |
| 9 | + |
| 10 | +Marko 5 and 6 use runtimes which are **interoperable** but **distinct**. As such, the compiler determines which runtime to use based on a set of heuristics. Switching _between_ the two runtimes should be avoided as often as possible, so it is preferable to ensure that Tags API components mostly reference other Tags API components. |
| 11 | + |
| 12 | +## Tags/Class API Heuristics |
| 13 | + |
| 14 | +The Marko 5 compiler uses a set of heuristics to determine which runtime a template should be compiled to. |
| 15 | + |
| 16 | +> [!NOTE] |
| 17 | +> These rules are listed in order of precedence, so once _one_ is satisfied none of the others are checked. |
| 18 | +
|
| 19 | +### Directory Name |
| 20 | + |
| 21 | +In Marko 5 and below custom tags were [auto-discovered](../reference/custom-tag.md#relative-custom-tags) from `/components` directories, but in Marko 6 they are discovered from `/tags`. Since `/tags` is new to Marko 6, `.marko` files under `/tags` **must** use the Tags API. |
| 22 | + |
| 23 | +### Comment Opt-In |
| 24 | + |
| 25 | +Files can be explicitly marked to use a specific API with a `/* use [api] */`comment. Any comment type is acceptable, and the comment can be anywhere in the file. |
| 26 | + |
| 27 | +```marko |
| 28 | +// use class |
| 29 | +<h1>Class API</h1> |
| 30 | +``` |
| 31 | + |
| 32 | +```marko |
| 33 | +<!-- use tags --> |
| 34 | +<h1>Tags API</h1> |
| 35 | +``` |
| 36 | + |
| 37 | +> [!TIP] |
| 38 | +> These explicit opt-ins are only necessary if a `.marko` file _isn't_ an [auto-discovered tag](#directory-name) and its contents are ambiguous (i. e. none of the following heuristics apply) so in practice they are rarely needed except for sometimes in [Marko Run](../marko-run/file-based-routing.md)'s `+page.marko` and `+layout.marko`. |
| 39 | +
|
| 40 | +### Class API Syntax |
| 41 | + |
| 42 | +If an otherwise ambiguous file contains any of the following syntax, it is detected as Class API (Marko 5): |
| 43 | + |
| 44 | +- A [`class {}` block](https://v5.markojs.com/docs/class-components/#single-file-components) |
| 45 | +- A [`style {}` block](https://v5.markojs.com/docs/class-components/#styles) |
| 46 | +- Inline JS in a [`$ scriptlet;`](https://v5.markojs.com/docs/syntax/#inline-javascript) |
| 47 | +- An [Attribute argument](https://v5.markojs.com/docs/syntax/#arguments) (`<button onClick("handleClick")>`) |
| 48 | +- An attribute modifier ([`:scoped`](https://v5.markojs.com/docs/class-components/#scoped) or [`:no-update`](https://v5.markojs.com/docs/class-components/#no-update_1)) |
| 49 | +- Any of [these tags](https://github.com/marko-js/marko/blob/main/packages/runtime-tags/src/translator/interop/feature-detection.ts#L182-L190): |
| 50 | + - `<await-reorderer>` `<class>` `<include-html>` `<include-text>` `<init-components>` `<macro>` `<module-code>` `<while>` |
| 51 | + |
| 52 | +### Tags API Syntax |
| 53 | + |
| 54 | +If an otherwise ambiguous file contains any of the following syntax, it is detected as Tags API (Marko 6): |
| 55 | + |
| 56 | +- A [tag variable](../reference/language.md#tag-variables) (`<div/var>`) |
| 57 | +- The [bind shorthand](../reference/language.md#shorthand-change-handlers-two-way-binding) (`:=`) |
| 58 | +- Any of [these tags](https://github.com/marko-js/marko/blob/main/packages/runtime-tags/src/translator/interop/feature-detection.ts#L191-L200): |
| 59 | + - `<const>` `<debug>` `<define>` `<id>` `<let>` `<lifecycle>` `<log>` `<return>` `<try>` |
| 60 | + |
| 61 | +```marko |
| 62 | +<let/count=0> |
| 63 | +<button onClick() { count++ }>${count}</button> |
| 64 | +``` |
| 65 | + |
| 66 | +### Exclusive Tag Library |
| 67 | + |
| 68 | +If a file is otherwise ambiguous but _all_ tags found by the [tag discovery mechanism](../reference/custom-tag.md#relative-custom-tags) are in a `tags/` directory and no `components/` directories are discovered, the file falls back into Tags API. |
| 69 | + |
| 70 | +All ambiguous files here use the tags API, because there are no `components/`. |
| 71 | + |
| 72 | +``` |
| 73 | +src/ |
| 74 | + +page.marko // Tags API |
| 75 | + tags/ |
| 76 | + some-tag.marko |
| 77 | +``` |
| 78 | + |
| 79 | +Even _one_ `components/` directory will default all ambiguous files to prefer Class API if there are no [`// use tags` comments](#-use-api) or [tag syntax heuristics](#tags-api-syntax). |
| 80 | + |
| 81 | +``` |
| 82 | +src/ |
| 83 | + components/ |
| 84 | + some-component.marko |
| 85 | + some-page/ |
| 86 | + +page.marko // Class API |
| 87 | + tags/ |
| 88 | + another-tag.marko |
| 89 | + tags/ |
| 90 | + some-tag.marko |
| 91 | +``` |
0 commit comments