marko 5.17.10 → 5.19.0
Sign up to get free protection for your applications and to get access to all the features.
- package/docs/cloudflare-workers.md +34 -0
- package/docs/compiler.md +7 -0
- package/docs/custom-tags.md +15 -0
- package/docs/events.md +1 -1
- package/docs/express.md +26 -19
- package/docs/fastify.md +36 -26
- package/docs/http.md +10 -13
- package/docs/koa.md +9 -36
- package/docs/marko-json.md +1 -0
- package/docs/marko-vs-react.md +6 -11
- package/docs/rollup.md +168 -20
- package/docs/structure.json +4 -3
- package/docs/syntax.md +10 -0
- package/docs/troubleshooting-streaming.md +62 -0
- package/docs/vite.md +86 -0
- package/docs/webpack.md +158 -97
- package/package.json +4 -4
@@ -0,0 +1,34 @@
|
|
1
|
+
# Marko + Cloudflare Workers
|
2
|
+
|
3
|
+
See the [the cloudflare sample](https://github.com/marko-js/examples/tree/master/examples/vite-cloudflare)
|
4
|
+
project for a working example.
|
5
|
+
|
6
|
+
## Usage
|
7
|
+
|
8
|
+
When using Marko with [Cloudflare Workers](https://workers.cloudflare.com/) you need to make sure that Marko is loaded with a `worker` [export condition](https://nodejs.org/api/packages.html#conditional-exports). Most bundlers support the ability to define export conditions.
|
9
|
+
|
10
|
+
After that point the `template.stream` will now return a worker compatible [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream).
|
11
|
+
|
12
|
+
You can then simply respond with the returned stream.
|
13
|
+
|
14
|
+
```js
|
15
|
+
import template from "./index.marko";
|
16
|
+
|
17
|
+
addEventListener("fetch", event => {
|
18
|
+
event.respondWith(handleRequest(event.request));
|
19
|
+
});
|
20
|
+
|
21
|
+
async function handleRequest(request) {
|
22
|
+
return new Response(template.stream(), {
|
23
|
+
headers: {
|
24
|
+
status: 200,
|
25
|
+
headers: { "content-type": "text/html;charset=UTF-8" }
|
26
|
+
}
|
27
|
+
});
|
28
|
+
}
|
29
|
+
```
|
30
|
+
|
31
|
+
### BYOB (Bring your own bundler)
|
32
|
+
|
33
|
+
For the large portion of Marko's API a bundler is required. The example code above assumes that Marko templates can be loaded in your environment.
|
34
|
+
Marko supports a number of bundlers, [take a look through our supported bundlers](#bundler-integrations) and pick what works best for you.
|
package/docs/compiler.md
CHANGED
@@ -361,6 +361,13 @@ At this stage, you are given a fully parsed and migrated AST to do what you will
|
|
361
361
|
|
362
362
|
To hook into the `transform` stage you can use the `transform` option in the `marko.json` file.
|
363
363
|
|
364
|
+
### Analyze
|
365
|
+
|
366
|
+
Next up is the analyze stage. This stage is intended to do non mutative analysis of the entire AST in a way that is cached in memory.
|
367
|
+
Meta data should be stored on the `.extra` property of nodes and typically read in the [translate](#translate) stage, or using the child template analysis helpers.
|
368
|
+
|
369
|
+
To hook into the `analyze` stage you can use the `analyze` option in the `marko.json` file.
|
370
|
+
|
364
371
|
### Translate
|
365
372
|
|
366
373
|
Finally, we have the translation stage. This stage is Marko's "Rosetta Stone" and is responsible for turning your beautiful Marko code into the optimized JavaScript you'd rather avoid writing.
|
package/docs/custom-tags.md
CHANGED
@@ -184,3 +184,18 @@ The [`<macro>`](./core-tags.md#macro) tag allows you to create custom tags in th
|
|
184
184
|
<welcome-message name="Patrick"/>
|
185
185
|
<welcome-message name="Austin"/>
|
186
186
|
```
|
187
|
+
|
188
|
+
# From Variables
|
189
|
+
|
190
|
+
If no other tag would be discovered Marko will check for an in scope variable that matches the tag name.
|
191
|
+
|
192
|
+
```marko
|
193
|
+
import SomeTag from "./somewhere.marko"
|
194
|
+
|
195
|
+
$ const { renderBody } = input;
|
196
|
+
$ const MyTag = input.href ? "a" : "button";
|
197
|
+
|
198
|
+
<SomeTag/>
|
199
|
+
<MyTag/>
|
200
|
+
<renderBody/>
|
201
|
+
```
|
package/docs/events.md
CHANGED
package/docs/express.md
CHANGED
@@ -1,38 +1,40 @@
|
|
1
|
-
#
|
1
|
+
# Marko + Express
|
2
2
|
|
3
|
-
|
3
|
+
## Quick Start
|
4
|
+
|
5
|
+
```terminal
|
6
|
+
npm init marko -- --template vite-express
|
7
|
+
```
|
8
|
+
|
9
|
+
See the [the express sample](https://github.com/marko-js/examples/tree/master/examples/vite-express)
|
4
10
|
project for a working example.
|
5
11
|
|
6
|
-
##
|
12
|
+
## From Scratch
|
7
13
|
|
8
|
-
|
14
|
+
First install Marko and the express related dependencies:
|
9
15
|
|
10
|
-
```
|
11
|
-
npm install express --save
|
12
|
-
npm install marko --save
|
13
|
-
npm install @marko/express --save
|
16
|
+
```terminal
|
17
|
+
npm install marko @marko/express express --save
|
14
18
|
```
|
15
19
|
|
16
|
-
|
20
|
+
### Skip the view engine
|
17
21
|
|
18
|
-
The built in view engine for express may be asynchronous, but it doesn't support streaming (check out [Rediscovering Progressive HTML Rendering](http://www.ebaytechblog.com/2014/12/08/async-fragments-rediscovering-progressive-html-rendering-with-marko/) to see why this is so important). So instead we'll [bypass the view engine](https://strongloop.com/strongblog/bypassing-express-view-rendering-for-speed-and-modularity/).
|
22
|
+
The built in view engine for express may be asynchronous, but it doesn't support streaming (check out [Rediscovering Progressive HTML Rendering](http://www.ebaytechblog.com/2014/12/08/async-fragments-rediscovering-progressive-html-rendering-with-marko/) to see why this is so important). So instead we'll [bypass the view engine](https://strongloop.com/strongblog/bypassing-express-view-rendering-for-speed-and-modularity/) and use [`@marko/express`](https://github.com/marko-js/express/).
|
19
23
|
|
20
|
-
|
24
|
+
### Usage
|
21
25
|
|
22
|
-
|
26
|
+
The [`@marko/express`](https://github.com/marko-js/express/) adds a `res.marko` method to the express response object. This function works much like `res.render`, but doesn't impose the restrictions of the express view engine and allows you to take full advantage of Marko's streaming and modular approach to templates.
|
23
27
|
|
24
28
|
By using `res.marko` you'll automatically have access to `req`, `res`, `app`, `app.locals`, and `res.locals` from within your Marko template and custom tags. These values are added to `out.global`.
|
25
29
|
|
26
30
|
```javascript
|
27
|
-
|
31
|
+
import express from "express";
|
32
|
+
import markoPlugin from "@marko/express";
|
33
|
+
import template from "./template.marko";
|
28
34
|
|
29
|
-
|
30
|
-
var markoExpress = require("@marko/express");
|
31
|
-
var template = require("./template");
|
35
|
+
const app = express();
|
32
36
|
|
33
|
-
|
34
|
-
|
35
|
-
app.use(markoExpress()); //enable res.marko(template, data)
|
37
|
+
app.use(markoPlugin()); //enable res.marko(template, data)
|
36
38
|
|
37
39
|
app.get("/", function (req, res) {
|
38
40
|
res.marko(template, {
|
@@ -44,3 +46,8 @@ app.get("/", function (req, res) {
|
|
44
46
|
|
45
47
|
app.listen(8080);
|
46
48
|
```
|
49
|
+
|
50
|
+
### BYOB (Bring your own bundler)
|
51
|
+
|
52
|
+
For the large portion of Marko's API a bundler is required. The example code above assumes that Marko templates can be loaded in your environment.
|
53
|
+
Marko supports a number of bundlers, [take a look through our supported bundlers](#bundler-integrations) and pick what works best for you.
|
package/docs/fastify.md
CHANGED
@@ -1,37 +1,47 @@
|
|
1
|
-
#
|
1
|
+
# Marko + Fastify
|
2
2
|
|
3
|
-
|
4
|
-
project for a fully-working example.
|
3
|
+
## Quick Start
|
5
4
|
|
6
|
-
|
5
|
+
```terminal
|
6
|
+
npm init marko -- --template vite-fastify
|
7
|
+
```
|
8
|
+
|
9
|
+
See the [the fastify sample](https://github.com/marko-js/examples/tree/master/examples/vite-fastify)
|
10
|
+
project for a working example.
|
11
|
+
|
12
|
+
## From Scratch
|
7
13
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
npm install marko --save
|
14
|
+
First install Marko and the fastify related dependencies:
|
15
|
+
|
16
|
+
```terminal
|
17
|
+
npm install marko @marko/fastify fastify --save
|
12
18
|
```
|
13
19
|
|
14
|
-
|
20
|
+
### Usage
|
15
21
|
|
16
|
-
|
17
|
-
const fastify = require("fastify")();
|
22
|
+
The [`@marko/fastify`](https://github.com/marko-js/fastify/) adds a `reply.marko` decorator to the `reply` object. This function allows us to pass in a Marko template and supports Marko's streaming and modular approach to templates.
|
18
23
|
|
19
|
-
|
20
|
-
engine: {
|
21
|
-
marko: require("marko")
|
22
|
-
}
|
23
|
-
});
|
24
|
+
By using `reply.marko` you'll automatically have access to `app.locals`, and `reply.locals` from within your Marko template and custom tags. These values are added to `out.global`.
|
24
25
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
colors: ["red", "green", "blue"]
|
30
|
-
});
|
31
|
-
});
|
26
|
+
```javascript
|
27
|
+
import fastify from "fastify";
|
28
|
+
import markoPlugin from "@marko/fastify";
|
29
|
+
import Template from "./template.marko";
|
32
30
|
|
33
|
-
|
34
|
-
|
35
|
-
|
31
|
+
const app = fastify();
|
32
|
+
|
33
|
+
app.register(markoPlugin);
|
34
|
+
|
35
|
+
app.get("/", (request, reply) => {
|
36
|
+
// Streams Marko template into the response.
|
37
|
+
// Forwards errors into fa error handler.
|
38
|
+
reply.marko(Template, { hello: "world" });
|
36
39
|
});
|
40
|
+
|
41
|
+
await fastify.listen(3000);
|
37
42
|
```
|
43
|
+
|
44
|
+
### BYOB (Bring your own bundler)
|
45
|
+
|
46
|
+
For the large portion of Marko's API a bundler is required. The example code above assumes that Marko templates can be loaded in your environment.
|
47
|
+
Marko supports a number of bundlers, [take a look through our supported bundlers](#bundler-integrations) and pick what works best for you.
|
package/docs/http.md
CHANGED
@@ -1,27 +1,19 @@
|
|
1
1
|
# Marko + HTTP Server
|
2
2
|
|
3
|
-
See the [
|
3
|
+
See the [the http sample](https://github.com/marko-js/examples/tree/master/examples/vite-http)
|
4
4
|
project for a working example.
|
5
5
|
|
6
|
-
## Installation
|
7
|
-
|
8
|
-
```bash
|
9
|
-
npm install marko --save
|
10
|
-
```
|
11
|
-
|
12
6
|
## Usage
|
13
7
|
|
14
8
|
```js
|
15
|
-
|
16
|
-
|
17
|
-
const http = require("http");
|
18
|
-
const server = http.createServer();
|
9
|
+
import http from "http";
|
10
|
+
import template from "./index.marko";
|
19
11
|
|
20
12
|
const port = 8080;
|
21
|
-
const
|
13
|
+
const server = http.createServer();
|
22
14
|
|
23
15
|
server.on("request", (req, res) => {
|
24
|
-
|
16
|
+
template.render(
|
25
17
|
{
|
26
18
|
name: "Frank",
|
27
19
|
count: 30,
|
@@ -35,3 +27,8 @@ server.listen(port, () => {
|
|
35
27
|
console.log(`Successfully started server on port ${port}`);
|
36
28
|
});
|
37
29
|
```
|
30
|
+
|
31
|
+
### BYOB (Bring your own bundler)
|
32
|
+
|
33
|
+
For the large portion of Marko's API a bundler is required. The example code above assumes that Marko templates can be loaded in your environment.
|
34
|
+
Marko supports a number of bundlers, [take a look through our supported bundlers](#bundler-integrations) and pick what works best for you.
|
package/docs/koa.md
CHANGED
@@ -1,23 +1,22 @@
|
|
1
|
-
#
|
1
|
+
# Marko + Koa
|
2
2
|
|
3
|
-
See [the
|
3
|
+
See the [the koa sample](https://github.com/marko-js/examples/tree/master/examples/vite-koa)
|
4
|
+
project for a working example.
|
4
5
|
|
5
6
|
## Installation
|
6
7
|
|
7
|
-
```
|
8
|
+
```terminal
|
8
9
|
npm install koa marko --save
|
9
10
|
```
|
10
11
|
|
11
12
|
## Usage
|
12
13
|
|
13
14
|
```javascript
|
14
|
-
|
15
|
+
import Koa from "koa";
|
16
|
+
import template from "./index.marko";
|
15
17
|
|
16
|
-
const Koa = require("koa");
|
17
18
|
const app = new Koa();
|
18
19
|
|
19
|
-
const template = require("./index.marko");
|
20
|
-
|
21
20
|
app.use((ctx, next) => {
|
22
21
|
ctx.type = "html";
|
23
22
|
ctx.body = template.stream({
|
@@ -30,33 +29,7 @@ app.use((ctx, next) => {
|
|
30
29
|
app.listen(8080);
|
31
30
|
```
|
32
31
|
|
33
|
-
|
34
|
-
|
35
|
-
```javascript
|
36
|
-
require("@marko/compiler/register");
|
37
|
-
const zlib = require("zlib");
|
38
|
-
|
39
|
-
const Koa = require("koa");
|
40
|
-
const app = new Koa();
|
41
|
-
|
42
|
-
const template = require("./index.marko");
|
43
|
-
|
44
|
-
app.use((ctx, next) => {
|
45
|
-
ctx.type = "html";
|
46
|
-
ctx.body = template.stream({
|
47
|
-
name: "Frank",
|
48
|
-
count: 30,
|
49
|
-
colors: ["red", "green", "blue"]
|
50
|
-
});
|
51
|
-
|
52
|
-
ctx.vary("Accept-Encoding");
|
53
|
-
if (ctx.acceptsEncodings("gzip")) {
|
54
|
-
ctx.set("Content-Encoding", "gzip");
|
55
|
-
ctx.body = ctx.body.pipe(
|
56
|
-
zlib.createGzip({ flush: zlib.constants.Z_PARTIAL_FLUSH })
|
57
|
-
);
|
58
|
-
}
|
59
|
-
});
|
32
|
+
### BYOB (Bring your own bundler)
|
60
33
|
|
61
|
-
|
62
|
-
|
34
|
+
For the large portion of Marko's API a bundler is required. The example code above assumes that Marko templates can be loaded in your environment.
|
35
|
+
Marko supports a number of bundlers, [take a look through our supported bundlers](#bundler-integrations) and pick what works best for you.
|
package/docs/marko-json.md
CHANGED
@@ -113,6 +113,7 @@ Typically, you should let Marko find these files automatically, but here is a re
|
|
113
113
|
"parse": "./parse.js", // Used to augment parsing.
|
114
114
|
"migrate": "./migrate.js", // Used for migrating deprecated features.
|
115
115
|
"transform": "./transform.js", // Used to modify the AST before generating it.
|
116
|
+
"analyze": "./analyze.js" // Used to analyze metadata the entire ast before beginning to translate it.
|
116
117
|
"translate": "./translate.js" // Used to generate custom JS.
|
117
118
|
}
|
118
119
|
```
|
package/docs/marko-vs-react.md
CHANGED
@@ -737,28 +737,23 @@ the server or in the browser. For example, given the following template:
|
|
737
737
|
|
738
738
|
#### Compiled for the server:
|
739
739
|
|
740
|
-
```
|
740
|
+
```js
|
741
741
|
var marko_template = require("marko/html").t(__filename),
|
742
|
-
|
743
|
-
|
742
|
+
marko_helpers = require("marko/runtime/html/helpers"),
|
743
|
+
marko_escapeXml = marko_helpers.x;
|
744
744
|
|
745
745
|
function render(input, out) {
|
746
|
-
out.w("<div>Hello " +
|
747
|
-
marko_escapeXml(input.name) +
|
748
|
-
"!</div>");
|
746
|
+
out.w("<div>Hello " + marko_escapeXml(input.name) + "!</div>");
|
749
747
|
}
|
750
748
|
```
|
751
749
|
|
752
750
|
#### Compiled for the browser:
|
753
751
|
|
754
|
-
```
|
752
|
+
```js
|
755
753
|
var marko_template = require("marko/vdom").t(__filename);
|
756
754
|
|
757
755
|
function render(input, out) {
|
758
|
-
out.e("DIV", null, 3)
|
759
|
-
.t("Hello ")
|
760
|
-
.t(input.name)
|
761
|
-
.t("!");
|
756
|
+
out.e("DIV", null, 3).t("Hello ").t(input.name).t("!");
|
762
757
|
}
|
763
758
|
```
|
764
759
|
|
package/docs/rollup.md
CHANGED
@@ -1,22 +1,16 @@
|
|
1
1
|
# Marko + Rollup
|
2
2
|
|
3
|
-
|
3
|
+
# Installation
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
## Manual Installation
|
8
|
-
|
9
|
-
```bash
|
10
|
-
npm install rollup @rollup/plugin-commonjs @rollup/plugin-node-resolve @marko/rollup --save-dev
|
5
|
+
```console
|
6
|
+
npm install @marko/rollup rollup @rollup/plugin-node-resolve @rollup/plugin-commonjs -D
|
11
7
|
```
|
12
8
|
|
13
|
-
|
9
|
+
# Basic example config
|
14
10
|
|
15
|
-
The
|
11
|
+
**Note: The Marko runtime is authored in commonjs, this means the `@rollup/plugin-commonjs` is required!**
|
16
12
|
|
17
|
-
|
18
|
-
|
19
|
-
```js
|
13
|
+
```javascript
|
20
14
|
import nodeResolve from "@rollup/plugin-node-resolve";
|
21
15
|
import commonjs from "@rollup/plugin-commonjs";
|
22
16
|
import marko from "@marko/rollup";
|
@@ -24,12 +18,12 @@ import marko from "@marko/rollup";
|
|
24
18
|
export default {
|
25
19
|
...,
|
26
20
|
plugins: [
|
27
|
-
marko(),
|
21
|
+
marko.browser(),
|
28
22
|
nodeResolve({
|
29
23
|
browser: true,
|
30
24
|
extensions: [".js", ".marko"]
|
31
25
|
}),
|
32
|
-
// NOTE: Marko
|
26
|
+
// NOTE: The Marko runtime uses commonjs so this plugin is also required.
|
33
27
|
commonjs({
|
34
28
|
extensions: [".js", ".marko"]
|
35
29
|
}),
|
@@ -41,12 +35,166 @@ export default {
|
|
41
35
|
};
|
42
36
|
```
|
43
37
|
|
44
|
-
|
38
|
+
Likewise, if bundling the components for the server use `marko.server()` as the plugin.
|
39
|
+
|
40
|
+
# Linked config
|
41
|
+
|
42
|
+
If you use _both_ the `server` and `browser` plugins (in a [multi rollup config setup](https://rollupjs.org/guide/en/#configuration-files:~:text=export%20an%20array)) `@marko/rollup` will go into a _linked_ mode.
|
43
|
+
In the linked mode you will have access to the [`<rollup>` tag](#rollup-tag) on the server, and the browser config
|
44
|
+
will automatically have the [`input`](https://rollupjs.org/guide/en/#input) option set.
|
45
|
+
|
46
|
+
```javascript
|
47
|
+
export default [{
|
48
|
+
// Config object for bundling server assets.
|
49
|
+
input: "src/your-server-entry.js",
|
50
|
+
plugins: [
|
51
|
+
marko.server()
|
52
|
+
...
|
53
|
+
]
|
54
|
+
}, {
|
55
|
+
// Config object for bundling browser assets.
|
56
|
+
plugins: [
|
57
|
+
marko.browser()
|
58
|
+
...
|
59
|
+
]
|
60
|
+
}];
|
61
|
+
```
|
62
|
+
|
63
|
+
## `<rollup>` tag
|
64
|
+
|
65
|
+
In a [linked setup](#linked-config) you have access to the `<rollup>` tag which will provide two [tag parameters](https://markojs.com/docs/syntax/#parameters) that allow you to write out the asset links for your server rendered app.
|
66
|
+
|
67
|
+
The first parameter `entry` is the generated `input` name that the server plugin gave to the browser compiler.
|
68
|
+
You can use it to find the corresponding entry chunk from rollups build.
|
69
|
+
|
70
|
+
The second parameter `output` is an array of `AssetInfo | ChunkInfo` objects with most of the same properties returned from rollup's [`generateBundle` hook](https://rollupjs.org/guide/en/#generatebundle). Some properties have been stripped, notably `code` and `map` since they would be too large to inline directly. A `size` property is also available for all chunks to allow you to be able to filter out empty chunks, or inline chunks of certain size.
|
71
|
+
|
72
|
+
```marko
|
73
|
+
<head>
|
74
|
+
<rollup|entry, output|>
|
75
|
+
$ const entryChunk = output.find(chunk => chunk.name === entry);
|
76
|
+
|
77
|
+
<if(entryChunk.size /* skip scripts all together if empty js file */)>
|
78
|
+
<for|fileName| of=entryChunk.imports>
|
79
|
+
<link rel="modulepreload" href=fileName/>
|
80
|
+
</for>
|
81
|
+
|
82
|
+
<script async type="module" src=entryChunk.fileName/>
|
83
|
+
</if>
|
84
|
+
</rollup>
|
85
|
+
</head>
|
86
|
+
```
|
87
|
+
|
88
|
+
Ultimately it is up to you to map the chunk data (sometimes referred to as a manifest) into the `<link>`'s and `<script>`'s rendered by your application.
|
89
|
+
|
90
|
+
If your rollup browser config contains multiple `output` options, or you have multiple browser configs, all of the `chunks` for each `output` are passed into the `<rollup>` tag.
|
91
|
+
|
92
|
+
For example if you have an `esm` and `iife` build:
|
93
|
+
|
94
|
+
```javascript
|
95
|
+
{
|
96
|
+
plugins: [
|
97
|
+
marko.browser()
|
98
|
+
...
|
99
|
+
],
|
100
|
+
output: [
|
101
|
+
{ dir: 'dist/iife', format: 'iife' },
|
102
|
+
{ dir: 'dist/esm', format: 'esm' }
|
103
|
+
]
|
104
|
+
}
|
105
|
+
```
|
106
|
+
|
107
|
+
we could access the assets from both builds:
|
45
108
|
|
46
|
-
```
|
47
|
-
|
48
|
-
rollup
|
109
|
+
```marko
|
110
|
+
<head>
|
111
|
+
<rollup|entry, iifeOutput, esmOutput|>
|
112
|
+
$ const iifeEntryChunk = iifeOutput.find(chunk => chunk.name === entry);
|
113
|
+
$ const esmEntryChunk = esmOutput.find(chunk => chunk.name === entry);
|
49
114
|
|
50
|
-
|
51
|
-
|
115
|
+
<script async type="module" src=esmEntryChunk.fileName/>
|
116
|
+
<script nomodule src=iifeEntryChunk.fileName></script>
|
117
|
+
</rollup>
|
118
|
+
</head>
|
119
|
+
```
|
120
|
+
|
121
|
+
and _boom_ you now have a [`module/nomodule` setup](https://philipwalton.com/articles/using-native-javascript-modules-in-production-today/).
|
122
|
+
|
123
|
+
# Top level components
|
124
|
+
|
125
|
+
Marko was designed to send as little JavaScript to the browser as possible. One of the ways we do this is by automatically determining which templates in your app should be shipped to the browser. When rendering a template on the server, it is only necessary to bundle the styles and interactive components rendered by that template.
|
126
|
+
|
127
|
+
To send the minimal amount of Marko templates to the browser you can provide a Marko template directly as the `input`.
|
128
|
+
This will also automatically invoke code to initialize the components in the browser, so there is no need to call
|
129
|
+
`template.render` yourself in the browser.
|
130
|
+
|
131
|
+
> Note: if you are using _linked_ plugins then the server plugin will automatically tell the browser compiler which Marko templates to load.
|
132
|
+
|
133
|
+
```js
|
134
|
+
export default {
|
135
|
+
input: "./my-marko-page.marko",
|
136
|
+
plugins: [
|
137
|
+
marko.browser(),
|
138
|
+
...
|
139
|
+
],
|
140
|
+
...
|
141
|
+
}
|
142
|
+
```
|
143
|
+
|
144
|
+
## Options
|
145
|
+
|
146
|
+
Both the `server` and `browser` plugins can receive the same options.
|
147
|
+
|
148
|
+
### options.babelConfig
|
149
|
+
|
150
|
+
You can manually override the Babel configuration used by passing a `babelConfig` object to the `@marko/rollup` plugin. By default Babels regular [config file resolution](https://babeljs.io/docs/en/config-files) will be used.
|
151
|
+
|
152
|
+
```javascript
|
153
|
+
marko.browser({
|
154
|
+
babelConfig: {
|
155
|
+
presets: ["@babel/preset-env"]
|
156
|
+
}
|
157
|
+
});
|
158
|
+
```
|
159
|
+
|
160
|
+
### options.runtimeId
|
161
|
+
|
162
|
+
In some cases you may want to embed multiple isolated copies of Marko on the page. Since Marko relies on some `window` properties to initialize this can cause issues. For example, by default Marko will read the server rendered hydration code from `window.$components`. In Marko you can change these `window` properties by rendering with `{ $global: { runtimeId: "MY_MARKO_RUNTIME_ID" } }` as input on the server side.
|
163
|
+
|
164
|
+
This plugin exposes a `runtimeId` option produces output that automatically sets `$global.runtimeId` on the server side and initializes properly in the browser.
|
165
|
+
|
166
|
+
```js
|
167
|
+
const runtimeId = "MY_MARKO_RUNTIME_ID";
|
168
|
+
// Make sure the `runtimeId` is the same across all of your plugins!
|
169
|
+
marko.server({ runtimeId });
|
170
|
+
marko.browser({ runtimeId });
|
171
|
+
```
|
172
|
+
|
173
|
+
### options.serialize
|
174
|
+
|
175
|
+
This option is only available for the `browser` plugin. It allows you to transform the list of chunks serialzed in a [_linked config_](#linked-config) to include whatever you like.
|
176
|
+
For example if you _did_ want to include the `code` property from the rollup chunk, to say inline some content, the following would work:
|
177
|
+
|
178
|
+
```js
|
179
|
+
marko.browser({
|
180
|
+
serialize(output) {
|
181
|
+
return output.map(chunk =>
|
182
|
+
chunk.type === "asset"
|
183
|
+
? {
|
184
|
+
type: "asset",
|
185
|
+
fileName: chunk.fileName
|
186
|
+
}
|
187
|
+
: {
|
188
|
+
type: "chunk",
|
189
|
+
name: chunk.name,
|
190
|
+
isEntry: chunk.isEntry,
|
191
|
+
fileName: chunk.fileName,
|
192
|
+
code:
|
193
|
+
chunk.code.replace(/^\s+$/, "").length < 1024
|
194
|
+
? chunk.code
|
195
|
+
: undefined // only inline small code chunks
|
196
|
+
}
|
197
|
+
);
|
198
|
+
}
|
199
|
+
});
|
52
200
|
```
|
package/docs/structure.json
CHANGED
@@ -10,7 +10,8 @@
|
|
10
10
|
"Styles",
|
11
11
|
"Events",
|
12
12
|
"Body content",
|
13
|
-
"Marko 5 upgrade"
|
13
|
+
"Marko 5 upgrade",
|
14
|
+
"Troubleshooting Streaming"
|
14
15
|
]
|
15
16
|
},
|
16
17
|
{
|
@@ -30,11 +31,11 @@
|
|
30
31
|
},
|
31
32
|
{
|
32
33
|
"title": "Bundler Integrations",
|
33
|
-
"docs": ["Webpack", "Rollup", "Lasso"]
|
34
|
+
"docs": ["Vite", "Webpack", "Rollup", "Lasso"]
|
34
35
|
},
|
35
36
|
{
|
36
37
|
"title": "Server Integrations",
|
37
|
-
"docs": ["Express", "
|
38
|
+
"docs": ["Cloudflare Workers", "Express", "Fastify", "Koa", "HTTP"]
|
38
39
|
},
|
39
40
|
{
|
40
41
|
"title": "Tooling",
|
package/docs/syntax.md
CHANGED
@@ -358,6 +358,16 @@ _HTML Output:_
|
|
358
358
|
<button>Click me!</button>
|
359
359
|
```
|
360
360
|
|
361
|
+
As a shorthand if there is a variable in scope and [no other matching tag is discovered](#how-tags-are-discovered) the wrapping `${}` is unnecessary.
|
362
|
+
|
363
|
+
For example the following are equivalent:
|
364
|
+
|
365
|
+
```marko
|
366
|
+
$ const MyTag = href ? 'a' : 'button';
|
367
|
+
<${MyTag}/>
|
368
|
+
<MyTag/>
|
369
|
+
```
|
370
|
+
|
361
371
|
> **ProTip:**
|
362
372
|
> If you find that you have a wrapper element that is conditional, but whose body should always be rendered then you can use a null dynamic tag. For example, to only render a wrapping `<a>` tag if there is a valid URL then you could do the following:
|
363
373
|
>
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# Troubleshooting HTTP Streams
|
2
|
+
|
3
|
+
[The way Marko streams HTML](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Transfer-Encoding) is old and well-supported, but default configurations and assumptions by other software can foil it. This page describes some known culprits that may buffer your Node server’s output HTTP streams.
|
4
|
+
|
5
|
+
## Reverse proxies/load balancers
|
6
|
+
|
7
|
+
- Turn off proxy buffering, or if you can’t, set the proxy buffer sizes to be reasonably small.
|
8
|
+
|
9
|
+
- Make sure the “upstream” HTTP version is 1.1 or higher; HTTP/1.0 and lower do not support streaming.
|
10
|
+
|
11
|
+
- Some software doesn’t support HTTP/2 or higher “upstream” connections at all or very well — if your Node server uses HTTP/2, you may need to downgrade.
|
12
|
+
|
13
|
+
- Automatic gzip/brotli compression may have their buffer sizes set too high; you can tune their buffers to be smaller for faster streaming in exchange for slightly worse compression.
|
14
|
+
|
15
|
+
- Check if “upstream” connections are `keep-alive`: overhead from closing and reopening connections may delay responses.
|
16
|
+
|
17
|
+
### NGiNX
|
18
|
+
|
19
|
+
Most of NGiNX’s relevant parameters are inside [its builtin `http_proxy` module](http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_buffering):
|
20
|
+
|
21
|
+
```nginx
|
22
|
+
proxy_http_version 1.1; # 1.0 by default
|
23
|
+
proxy_buffering off; # on by default
|
24
|
+
```
|
25
|
+
|
26
|
+
### Apache
|
27
|
+
|
28
|
+
Apache’s default configuration works fine with streaming, but your host may have it configured differently. The relevant Apache configuration is inside [its `mod_proxy` and `mod_proxy_*` modules](https://httpd.apache.org/docs/2.4/mod/mod_proxy.html) and their [associated environment variables](https://httpd.apache.org/docs/2.4/env.html).
|
29
|
+
|
30
|
+
## CDNs
|
31
|
+
|
32
|
+
Content Delivery Networks (CDNs) consider efficient streaming one of their best features, but it may be off by default or if certain features are enabled.
|
33
|
+
|
34
|
+
- For Fastly or another provider that uses VCL configuration, check [if backend responses have `beresp.do_stream = true` set](https://developer.fastly.com/reference/vcl/variables/backend-response/beresp-do-stream/).
|
35
|
+
|
36
|
+
- Some [Akamai features designed to mitigate slow backends can ironically slow down fast chunked responses](https://community.akamai.com/customers/s/question/0D50f00006n975d/enabling-chunked-transfer-encoding-responses). Try toggling off Adaptive Acceleration, Ion, mPulse, Prefetch, and/or similar performance features. Also check for the following in the configuration:
|
37
|
+
|
38
|
+
```html
|
39
|
+
<network:http.buffer-response-v2>off</network:http.buffer-response-v2>
|
40
|
+
```
|
41
|
+
|
42
|
+
## Node.js itself
|
43
|
+
|
44
|
+
For extreme cases where [Node streams very small HTML chunks with its built-in compression modules](https://github.com/marko-js/marko/pull/1641), you may need to tweak the compressor stream settings. Here’s an example with `createGzip` and its `Z_PARTIAL_FLUSH` flag:
|
45
|
+
|
46
|
+
```js
|
47
|
+
const http = require("http");
|
48
|
+
const zlib = require("zlib");
|
49
|
+
|
50
|
+
const markoTemplate = require("./something.marko");
|
51
|
+
|
52
|
+
http
|
53
|
+
.createServer(function (request, response) {
|
54
|
+
response.writeHead(200, { "content-type": "text/html;charset=utf-8" });
|
55
|
+
const templateStream = markoTemplate.stream({});
|
56
|
+
const gzipStream = zlib.createGzip({
|
57
|
+
flush: zlib.constants.Z_PARTIAL_FLUSH
|
58
|
+
});
|
59
|
+
templateStream.pipe(outputStream).pipe(response);
|
60
|
+
})
|
61
|
+
.listen(80);
|
62
|
+
```
|
package/docs/vite.md
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
# Marko + Vite
|
2
|
+
|
3
|
+
# Installation
|
4
|
+
|
5
|
+
```console
|
6
|
+
npm install @marko/vite vite
|
7
|
+
```
|
8
|
+
|
9
|
+
# Example config
|
10
|
+
|
11
|
+
```javascript
|
12
|
+
import { defineConfig } from "vite";
|
13
|
+
import marko from "@marko/vite";
|
14
|
+
export default defineConfig({
|
15
|
+
plugins: [marko()]
|
16
|
+
});
|
17
|
+
```
|
18
|
+
|
19
|
+
# Linked Mode
|
20
|
+
|
21
|
+
By default this plugin operates in `linked` mode (you can disabled this by passing [`linked: false` as an option](#optionslinked)). In `linked` mode the plugin automatically discovers all of the entry `.marko` files while compiling the server, and tells `Vite` which modules to load in the browser.
|
22
|
+
|
23
|
+
With this you _do not_ create `.html` files for `Vite`, it's Marko all the way down!
|
24
|
+
Scripts, styles and other content that _would have_ been injected into the `.html` files is instead automatically injected into your `.marko` templates.
|
25
|
+
|
26
|
+
In this mode you must use the [Vite SSR API](https://vitejs.dev/guide/ssr.html#setting-up-the-dev-server).
|
27
|
+
|
28
|
+
Here's an example using `express`.
|
29
|
+
|
30
|
+
```js
|
31
|
+
import { createServer } from "vite";
|
32
|
+
|
33
|
+
const app = express();
|
34
|
+
let loadTemplate;
|
35
|
+
|
36
|
+
if (process.env.NODE_ENV === "production") {
|
37
|
+
// Use Vite's built asset in prod mode.
|
38
|
+
loadTemplate = () => import("./dist");
|
39
|
+
} else {
|
40
|
+
// Hookup the vite dev server.
|
41
|
+
const vite = await createViteServer({
|
42
|
+
server: { middlewareMode: true }
|
43
|
+
});
|
44
|
+
|
45
|
+
app.use(vite.middlewares);
|
46
|
+
loadTemplate = () => vite.ssrLoadModule("./template.marko");
|
47
|
+
}
|
48
|
+
|
49
|
+
app.get("/", async (req, res) => {
|
50
|
+
const template = (await loadTemplate()).default;
|
51
|
+
// When the template is loaded, it will automaticall have `vite` assets inlined.
|
52
|
+
template.render({ hello: "world" }, res);
|
53
|
+
);
|
54
|
+
|
55
|
+
app.listen(3000);
|
56
|
+
```
|
57
|
+
|
58
|
+
> For a more real world setup check out our [vite express](https://github.com/marko-js/examples/tree/master/examples/vite-express) example app.
|
59
|
+
|
60
|
+
# Options
|
61
|
+
|
62
|
+
### options.babelConfig
|
63
|
+
|
64
|
+
You can manually override Marko's Babel configuration by passing a `babelConfig` object to the `@marko/vite` plugin. By default Babel's regular [config file resolution](https://babeljs.io/docs/en/config-files) will be used.
|
65
|
+
|
66
|
+
```javascript
|
67
|
+
marko({
|
68
|
+
babelConfig: {
|
69
|
+
presets: ["@babel/preset-env"]
|
70
|
+
}
|
71
|
+
});
|
72
|
+
```
|
73
|
+
|
74
|
+
### options.runtimeId
|
75
|
+
|
76
|
+
In some cases you may want to embed multiple isolated copies of Marko on the page. Since Marko relies on some `window` properties to initialize this can cause issues. For example, by default Marko will read the server rendered hydration code from `window.$components`. In Marko you can change these `window` properties by rendering with `{ $global: { runtimeId: "MY_MARKO_RUNTIME_ID" } }` as input on the server side.
|
77
|
+
|
78
|
+
This plugin exposes a `runtimeId` option produces output that automatically sets `$global.runtimeId` on the server side and initializes properly in the browser.
|
79
|
+
|
80
|
+
```js
|
81
|
+
marko({ runtimeId: "MY_MARKO_RUNTIME_ID" });
|
82
|
+
```
|
83
|
+
|
84
|
+
### options.linked
|
85
|
+
|
86
|
+
Set this to `false` to opt out of [linked mode](#linked-mode). When this is false, the plugin will only handle resolving and transforming `.marko` files.
|
package/docs/webpack.md
CHANGED
@@ -1,144 +1,205 @@
|
|
1
1
|
# Marko + Webpack
|
2
2
|
|
3
|
-
|
3
|
+
# Installation
|
4
4
|
|
5
|
-
>
|
5
|
+
> `@marko/webpack` >= 7 Only supports Marko 5+.
|
6
|
+
> For Marko 4 support use `@marko/webpack@6`.
|
6
7
|
|
7
|
-
|
8
|
-
|
9
|
-
```
|
10
|
-
npm install marko
|
11
|
-
npm install webpack @marko/webpack --save-dev
|
8
|
+
```console
|
9
|
+
npm install @marko/webpack
|
12
10
|
```
|
13
11
|
|
14
|
-
|
12
|
+
### Loader: `@marko/webpack/loader`
|
15
13
|
|
16
|
-
|
14
|
+
The loader portion of this module can be used standalone and simply transforms your Marko templates into the appropriate JavaScript depending on your webpack target.
|
17
15
|
|
18
|
-
|
16
|
+
You can override the output by adding a `target` option to the loader of `target: "server" | "browser"`.
|
19
17
|
|
20
|
-
|
21
|
-
<h1>Hello ${input.name}</h1>
|
22
|
-
```
|
18
|
+
### Plugin: `@marko/webpack/plugin`
|
23
19
|
|
24
|
-
|
20
|
+
The plugin actually creates two separate webpack plugins, the `browser` plugin and the `server` plugin.
|
25
21
|
|
26
|
-
|
22
|
+
These are intended to be used in a isomorphic [webpack multi compiler](https://github.com/webpack/webpack/tree/master/examples/multi-compiler) where you are bundling both the server and the browser. The way it works is that the server plugin is going to analyze the top level Marko components in your server and automatically communicate with the browser compiler to retrieve the assets for that template.
|
27
23
|
|
28
|
-
|
29
|
-
import MyTemplate from "./hello.marko";
|
24
|
+
This plugin also analyzes the top level Marko templates and determines if it is possible for them to rerender (currently the heuristic is simply does the component have an associated `class` or `component.js`). The plugin will automatically skip sending down any unnecessary top level templates to the browser.
|
30
25
|
|
31
|
-
|
32
|
-
|
26
|
+
The end result is that you setup a multi compiler (as shown below) and you can simply import Marko templates, and all assets are automatically generated and inlined into an optimized server response. No need to keep track of a webpack manifest yourself!
|
27
|
+
|
28
|
+
### Tag: `<webpack-assets>`
|
33
29
|
|
34
|
-
|
30
|
+
The `<webpack-assets>` tag can be used along with the plugin in a multi-compiler setup. This tag allows you to inject `<script>`/`<style>` tags into a server-rendered template for the assets of an entry in the client compiler.
|
35
31
|
|
36
|
-
|
32
|
+
#### Example Usage
|
33
|
+
|
34
|
+
```marko
|
35
|
+
<webpack-assets entry="tracking"/>
|
36
|
+
```
|
37
|
+
|
38
|
+
#### Example Config
|
37
39
|
|
38
40
|
```js
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
41
|
+
// ...
|
42
|
+
export default [
|
43
|
+
{
|
44
|
+
entry: "./server.js",
|
45
|
+
plugins: [markoPlugin.server]
|
46
|
+
// ...
|
44
47
|
},
|
45
|
-
|
46
|
-
|
48
|
+
{
|
49
|
+
// ...
|
50
|
+
entry: {
|
51
|
+
tracking: "./tracking.js"
|
52
|
+
},
|
53
|
+
plugins: [markoPlugin.browser]
|
54
|
+
}
|
55
|
+
];
|
56
|
+
```
|
57
|
+
|
58
|
+
# Example
|
59
|
+
|
60
|
+
```javascript
|
61
|
+
import MarkoPlugin from "@marko/webpack/plugin";
|
62
|
+
|
63
|
+
const markoPlugin = new MarkoPlugin();
|
64
|
+
|
65
|
+
export default [
|
66
|
+
{
|
67
|
+
entry: "./server.js",
|
68
|
+
module: {
|
69
|
+
rules: [
|
70
|
+
{
|
71
|
+
test: /\.marko$/,
|
72
|
+
loader: "@marko/webpack/loader"
|
73
|
+
}
|
74
|
+
]
|
75
|
+
},
|
76
|
+
plugins: [markoPlugin.server]
|
47
77
|
},
|
48
|
-
|
78
|
+
{
|
49
79
|
rules: [
|
50
80
|
{
|
51
81
|
test: /\.marko$/,
|
52
82
|
loader: "@marko/webpack/loader"
|
83
|
+
},
|
84
|
+
// If using `style` blocks with Marko you must use an appropriate loader
|
85
|
+
{
|
86
|
+
test: /\.css$/,
|
87
|
+
use: ["style-loader", "css-loader"]
|
53
88
|
}
|
54
|
-
]
|
89
|
+
],
|
90
|
+
plugins: [markoPlugin.browser]
|
55
91
|
}
|
56
|
-
|
92
|
+
];
|
57
93
|
```
|
58
94
|
|
59
|
-
|
95
|
+
## Babel options (Marko 5+)
|
96
|
+
|
97
|
+
If you are using Marko 5 with this plugin you can manually override the Babel configuration used by passing a `babelConfig` object along side the `@marko/webpack/loader`. By default Babels regular [config file resolution](https://babeljs.io/docs/en/config-files) will be used.
|
98
|
+
|
99
|
+
```javascript
|
100
|
+
export default {
|
101
|
+
module: {
|
102
|
+
rules: [
|
103
|
+
{
|
104
|
+
test: /\.marko$/,
|
105
|
+
loader: "@marko/webpack/loader",
|
106
|
+
options: {
|
107
|
+
babelConfig: {
|
108
|
+
presets: [
|
109
|
+
["@babel/preset-env", { node: "current" }]
|
110
|
+
]
|
111
|
+
}
|
112
|
+
}
|
113
|
+
}
|
114
|
+
]
|
115
|
+
}
|
116
|
+
},
|
117
|
+
```
|
60
118
|
|
61
|
-
|
119
|
+
## Multiple client side compilers
|
62
120
|
|
63
|
-
|
64
|
-
<!DOCTYPE html>
|
65
|
-
<html>
|
66
|
-
<body>
|
67
|
-
<script src="static/bundle.js"></script>
|
68
|
-
</body>
|
69
|
-
</html>
|
70
|
-
```
|
121
|
+
Sometimes you need to have multiple compilers for your client side bundles. For example with [`i18n`](https://github.com/webpack/webpack/tree/master/examples/i18n) or [even shipping dynamic runtime bundles to the browser](https://github.com/eBay/arc/tree/master/packages/arc-webpack).
|
71
122
|
|
72
|
-
|
123
|
+
The Marko webpack browser plugin can be passed to multiple webpack compilers. At runtime you can provide a `$global.buildName` when rendering which will cause assets from the webpack compiler with that name to be included in the page.
|
73
124
|
|
74
|
-
|
125
|
+
For example with the webpack i18n plugin you might have a config like the following:
|
75
126
|
|
76
|
-
|
127
|
+
```js
|
128
|
+
import MarkoPlugin from "@marko/webpack/plugin";
|
129
|
+
import I18nPlugin from "i18n-webpack-plugin";
|
77
130
|
|
78
|
-
|
131
|
+
const languages = {
|
132
|
+
en: null,
|
133
|
+
de: require("./de.json")
|
134
|
+
};
|
79
135
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
136
|
+
const markoPlugin = new MarkoPlugin();
|
137
|
+
|
138
|
+
export default [
|
139
|
+
{
|
140
|
+
name: "Server",
|
141
|
+
entry: "./server.js",
|
142
|
+
module: {
|
143
|
+
rules: [
|
144
|
+
{
|
145
|
+
test: /\.marko$/,
|
146
|
+
loader: "@marko/webpack/loader"
|
147
|
+
}
|
148
|
+
]
|
149
|
+
},
|
150
|
+
plugins: [markoPlugin.server]
|
151
|
+
},
|
152
|
+
...Object.keys(languages).map(language => ({
|
153
|
+
name: `Browser-${language}`,
|
154
|
+
rules: [
|
155
|
+
{
|
156
|
+
test: /\.marko$/,
|
157
|
+
loader: "@marko/webpack/loader"
|
158
|
+
},
|
159
|
+
// If using `style` blocks with Marko you must use an appropriate loader
|
160
|
+
{
|
161
|
+
test: /\.css$/,
|
162
|
+
use: ["style-loader", "css-loader"]
|
163
|
+
}
|
164
|
+
],
|
165
|
+
plugins: [new I18nPlugin(languages[language]), markoPlugin.browser]
|
166
|
+
}))
|
167
|
+
];
|
168
|
+
```
|
169
|
+
|
170
|
+
With the above config you can render your top level Marko template server side with a `$global.buildName`, like so:
|
86
171
|
|
87
|
-
|
172
|
+
```javascript
|
173
|
+
template.render({ $global: { buildName: "Browser-de" } });
|
88
174
|
```
|
89
175
|
|
90
|
-
|
176
|
+
This will automatically send assets for the German language.
|
177
|
+
Of course in this case you'll want to conditionally send the appropriate assets given a users locale. This can be some simply, like so:
|
91
178
|
|
92
|
-
```
|
93
|
-
|
94
|
-
module: {
|
95
|
-
rules: [
|
96
|
-
//...
|
97
|
-
{
|
98
|
-
test: /\.less$/, // matches style.less { ... } from our template
|
99
|
-
use: ["style-loader", "css-loader", "less-loader"]
|
100
|
-
}
|
101
|
-
//...
|
102
|
-
];
|
103
|
-
}
|
104
|
-
//...
|
179
|
+
```javascript
|
180
|
+
template.render({ $global: { buildName: `Browser-${req.language}` } });
|
105
181
|
```
|
106
182
|
|
107
|
-
|
183
|
+
Note: If a bundle with the provided name does not exist an error will be thrown.
|
108
184
|
|
109
|
-
|
185
|
+
## Multiple copies of Marko
|
110
186
|
|
111
|
-
|
112
|
-
npm install mini-css-extract-plugin --save-dev
|
113
|
-
```
|
187
|
+
In some cases you may want to embed multiple isolated copies of Marko on the page. Since Marko relies on some `window` properties to initialize this can cause issues. For example, by default Marko will read the server rendered hydration code from `window.$components`. In Marko you can change these `window` properties by rendering with `{ $global: { runtimeId: "MY_MARKO_RUNTIME_ID" } }` as input on the server side.
|
114
188
|
|
115
|
-
|
189
|
+
This plugin exposes a `runtimeId` option produces output that automatically sets `$global.runtimeId` on the server side and initializes properly in the browser.
|
190
|
+
The `runtimeId` will default to the [`uniqueName` option](https://webpack.js.org/configuration/output/#outputuniquename) from the server compiler in the webpack config.
|
116
191
|
|
117
192
|
```js
|
118
|
-
|
193
|
+
import MarkoPlugin from "@marko/webpack/plugin";
|
119
194
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
extensions: [".js", ".marko"]
|
124
|
-
},
|
125
|
-
module: {
|
126
|
-
rules: [
|
127
|
-
{
|
128
|
-
test: /\.marko$/,
|
129
|
-
loader: "@marko/webpack/loader"
|
130
|
-
},
|
131
|
-
{
|
132
|
-
test: /\.(less|css)$/,
|
133
|
-
use: [CSSExtractPlugin.loader, "css-loader", "less-loader"]
|
134
|
-
}
|
135
|
-
]
|
136
|
-
},
|
137
|
-
plugins: [
|
138
|
-
// Write out CSS bundle to its own file:
|
139
|
-
new CSSExtractPlugin({
|
140
|
-
filename: "[name].css"
|
141
|
-
})
|
142
|
-
]
|
143
|
-
};
|
195
|
+
const markoPlugin = new MarkoPlugin({
|
196
|
+
runtimeId: "MY_MARKO_RUNTIME_ID" // default to webpack `output.uniqueName` option.
|
197
|
+
});
|
144
198
|
```
|
199
|
+
|
200
|
+
Note: This option will also override the default values for the `jsonpFunction`, `chunkCallbackName` and `hotUpdateFunction` webpack `output` options, which all use global variables, to be prefixed with the `runtimeId`.
|
201
|
+
|
202
|
+
## Dynamic public paths
|
203
|
+
|
204
|
+
When using the plugin, the server will automatically sync the runtime [`__webpack_public_path__`](https://webpack.js.org/guides/public-path/#on-the-fly) with the browser.
|
205
|
+
This means that you only need to setup the dynamic public path on the server side.
|
package/package.json
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
{
|
2
2
|
"name": "marko",
|
3
|
-
"version": "5.
|
3
|
+
"version": "5.19.0",
|
4
4
|
"license": "MIT",
|
5
5
|
"description": "UI Components + streaming, async, high performance, HTML templating for Node.js and the browser.",
|
6
6
|
"dependencies": {
|
7
|
-
"@marko/compiler": "^5.
|
8
|
-
"@marko/translator-default": "^5.
|
7
|
+
"@marko/compiler": "^5.19.0",
|
8
|
+
"@marko/translator-default": "^5.19.0",
|
9
9
|
"app-module-path": "^2.2.0",
|
10
10
|
"argly": "^1.2.0",
|
11
11
|
"browser-refresh-client": "1.1.4",
|
@@ -72,5 +72,5 @@
|
|
72
72
|
"index.js",
|
73
73
|
"node-require.js"
|
74
74
|
],
|
75
|
-
"gitHead": "
|
75
|
+
"gitHead": "07f5e26b79d46982caf0d1ed593675b4778877ac"
|
76
76
|
}
|