Skip to content

Commit

Permalink
feat: Add store option for linked mode builds (#40)
Browse files Browse the repository at this point in the history
* feat: add store option for ssr-client state preservation

* fix: add test case

* fix: update readme

* fix: add store unit tests

* fix: remove non-supported entries option

* chore: add changeset
  • Loading branch information
rturnq authored Jan 5, 2023
1 parent 3dc1c00 commit 427c493
Show file tree
Hide file tree
Showing 24 changed files with 392 additions and 46 deletions.
5 changes: 5 additions & 0 deletions .changeset/dull-candles-brake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@marko/vite": patch
---

Add store option for linked mode builds
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,26 @@ marko({ runtimeId: "MY_MARKO_RUNTIME_ID" });
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.
### options.store
Storage mechanism to preserve data between SSR and client builds when building in linked mode. Two implementations are available:
- FileStore _(default)_
```js
import { FileStore } from "@marko/vite";
const store = new FileStore();
```
Reads/writes data to the file system. Use this when running the SSR and client builds in seperate processes such as when using Vite from the command line or npm scripts.
- MemoryStore
```js
import { MemoryStore } from "@marko/vite";
const store = new MemoryStore();
```
Reads/writes data to memory. This option can be used when building with Vite programatically.
## Code of Conduct
This project adheres to the [eBay Code of Conduct](./.github/CODE_OF_CONDUCT.md). By participating in this project you agree to abide by its terms.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<div
id="implicit"
>
<div
id="clickable"
>
Mounted: false Clicks: 0
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<div
id="implicit"
>
<div
id="clickable"
>
Mounted: true Clicks: 0
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<div
id="implicit"
>
<div
id="clickable"
>
Mounted: true Clicks: 1
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<div
id="implicit"
>
<div
id="clickable"
>
Mounted: false Clicks: 0
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<div
id="implicit"
>
<div
id="clickable"
>
Mounted: true Clicks: 0
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<div
id="implicit"
>
<div
id="clickable"
>
Mounted: true Clicks: 1
</div>
</div>
33 changes: 33 additions & 0 deletions src/__tests__/fixtures/isomorphic-memory-store/dev-server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// In dev we'll start a Vite dev server in middleware mode,
// and forward requests to our http request handler.

const { createServer } = require("vite");
const { join } = require("path");
const markoPlugin = require("../../..").default;

module.exports = (async () => {
const devServer = await createServer({
root: __dirname,
appType: "custom",
logLevel: "silent",
plugins: [markoPlugin()],
optimizeDeps: { force: true },
server: {
middlewareMode: true,
watch: {
ignored: ["**/node_modules/**", "**/dist/**", "**/__snapshots__/**"],
},
},
});
return devServer.middlewares.use(async (req, res, next) => {
try {
const { handler } = await devServer.ssrLoadModule(
join(__dirname, "./src/index.js")
);
await handler(req, res, next);
} catch (err) {
devServer.ssrFixStacktrace(err);
return next(err);
}
});
})();
11 changes: 11 additions & 0 deletions src/__tests__/fixtures/isomorphic-memory-store/server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// In production, simply start up the http server.
const path = require("path");
const { createServer } = require("http");
const serve = require("serve-handler");
const { handler } = require("./dist/index.mjs");
const serveOpts = { public: path.resolve(__dirname, "dist") };
module.exports = createServer(async (req, res) => {
await handler(req, res);
if (res.headersSent) return;
await serve(req, res, serveOpts);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
class {
onCreate() {
this.state = {
clickCount: 0,
mounted: false
};
}
onMount() {
this.state.mounted = true;
}
handleClick() {
this.state.clickCount++;
}
}

<div#clickable onClick("handleClick")>
Mounted: ${state.mounted}
Clicks: ${state.clickCount}
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
static {
if (typeof window === "object") {
document.body.firstElementChild.append("Loaded Implicit Component");
}
}

<div#implicit>
<class-component/>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
static {
if (typeof window === "object") {
document.body.firstElementChild.append("Loaded Layout Component");
}
}

<!DOCTYPE html>
<html lang="en">
<head>
<title>Hello World</title>
</head>
<body>
<${input.renderBody}/>
</body>
</html>
9 changes: 9 additions & 0 deletions src/__tests__/fixtures/isomorphic-memory-store/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import template from "./template.marko";

export function handler(req, res) {
if (req.url === "/") {
res.statusCode = 200;
res.setHeader("Content-Type", "text/html; charset=utf-8");
template.render({}, res);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
style {
div { color: green }
}

<layout-component>
<div#app>
<implicit-component/>
</div>
</layout-component>
9 changes: 9 additions & 0 deletions src/__tests__/fixtures/isomorphic-memory-store/test.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { MemoryStore, type Options } from "../../..";

export const ssr = true;
export async function steps() {
await page.click("#clickable");
}
export const options: Options = {
store: new MemoryStore(),
};
11 changes: 6 additions & 5 deletions src/__tests__/main.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { JSDOM } from "jsdom";
import { createRequire } from "module";
import * as playwright from "playwright";
import { defaultNormalizer, defaultSerializer } from "@marko/fixture-snapshots";
import markoPlugin from "..";
import markoPlugin, { type Options } from "..";

declare global {
const page: playwright.Page;
Expand Down Expand Up @@ -84,6 +84,7 @@ for (const fixture of fs.readdirSync(FIXTURES)) {
const config = requireCwd(path.join(dir, "test.config.ts")) as {
ssr: boolean;
steps?: Step | Step[];
options?: Options;
};
const steps: Step[] = config.steps
? Array.isArray(config.steps)
Expand All @@ -105,7 +106,7 @@ for (const fixture of fs.readdirSync(FIXTURES)) {
root: dir,
configFile: false,
logLevel: "silent",
plugins: [markoPlugin()],
plugins: [markoPlugin(config.options)],
build: {
write: true,
minify: false,
Expand All @@ -118,7 +119,7 @@ for (const fixture of fs.readdirSync(FIXTURES)) {
root: dir,
configFile: false,
logLevel: "silent",
plugins: [markoPlugin()],
plugins: [markoPlugin(config.options)],
build: {
write: true,
minify: false,
Expand Down Expand Up @@ -148,7 +149,7 @@ for (const fixture of fs.readdirSync(FIXTURES)) {
},
logLevel: "silent",
optimizeDeps: { force: true },
plugins: [markoPlugin({ linked: false })],
plugins: [markoPlugin({ ...config.options, linked: false })],
});

devServer.listen(await getAvailablePort());
Expand All @@ -161,7 +162,7 @@ for (const fixture of fs.readdirSync(FIXTURES)) {
root: dir,
configFile: false,
logLevel: "silent",
plugins: [markoPlugin({ linked: false })],
plugins: [markoPlugin({ ...config.options, linked: false })],
build: {
write: true,
minify: false,
Expand Down
Loading

0 comments on commit 427c493

Please sign in to comment.