Skip to content

Commit

Permalink
update to experimental 3d-web-experience-server version and make buil…
Browse files Browse the repository at this point in the history
…d more stable under concurrent rebuilds
  • Loading branch information
deej-io committed Aug 5, 2024
1 parent c4f8d1c commit 6732c30
Show file tree
Hide file tree
Showing 8 changed files with 382 additions and 256 deletions.
528 changes: 308 additions & 220 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions packages/playground/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.build
70 changes: 48 additions & 22 deletions packages/playground/build.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,41 @@
import { v5 as uuidv5 } from "uuid";
import lockfile from "proper-lockfile";
import path, { relative, resolve, join } from "node:path";
import fs from "node:fs";
import fsp from "node:fs/promises";
import crypto from "node:crypto";

import { rimrafSync } from "rimraf";

import * as esbuild from "esbuild";

const buildMode = "--build";
const watchMode = "--watch";

const helpString = `Mode must be provided as one of ${buildMode} or ${watchMode}`;

const jsExt = /\.js$/;

function rmEmptyDirs(dir: string, log?: (...args: any[]) => void) {
if (!fs.statSync(dir).isDirectory()) {
function cleanupJS(path: string, log?: (...args: any[]) => void) {
const stat = fs.statSync(path);
const isJS = stat.isFile() && jsExt.test(path);
if (isJS) {
fs.rmSync(path);
return;
}
if (!stat.isDirectory()) {
return;
}
let files = fs.readdirSync(dir);
let files = fs.readdirSync(path);
if (files.length > 0) {
for (const file of files) {
rmEmptyDirs(join(dir, file), log);
cleanupJS(join(path, file), log);
}
// re-evaluate files; after deleting subfolder
// we may have parent folder empty now
files = fs.readdirSync(dir);
files = fs.readdirSync(path);
}

if (files.length == 0) {
log?.("Removing:", dir);
fs.rmdirSync(dir);
log?.("Removing:", path);
fs.rmdirSync(path);
return;
}
}
Expand Down Expand Up @@ -68,9 +73,8 @@ function mmlPlugin({
): esbuild.Plugin {
const log = verbose ? (...args: any[]) => console.log("[mml]:", ...args) : () => { };

const results: esbuild.BuildResult[] = [];

const importStubs: Record<string, string> = {};
let results: esbuild.BuildResult[] = [];
let importStubs: Record<string, string> = {};

// We create a new non-root instance of the plugin anytime we need to run a child build process
// This signifies to the the child plugin that it should store its result in the `results` array
Expand All @@ -82,6 +86,22 @@ function mmlPlugin({
build.initialOptions.metafile = true;
const outdir = resolve(__dirname, build.initialOptions.outdir ?? "build");

build.onStart(async () => {
if (isRoot) {
log("onStart: acquiring lock on build directory");
fs.mkdirSync(outdir, { recursive: true });
try {
lockfile.lockSync(outdir);
} catch (error) {
return {
errors: [{ text: "failed to acquire lock on build directory", detail: error }]
}
}
results = [];
importStubs = {};
}
});

// Main entry point for any imports that are prefixed with "mml:".
// We strip the prefix and resolve the path with esbuild before handing off to
// an mml loader.
Expand Down Expand Up @@ -113,6 +133,7 @@ function mmlPlugin({
return { contents: importStub, loader: "text" };
});


// Any raw HTML files should just be copied to the build directory.
// TODO: These could contain script tags with references to local files,
// we may want to consider loading and embedding them directly into the HTML.
Expand Down Expand Up @@ -144,22 +165,26 @@ function mmlPlugin({

Object.assign(result, combinedResults);

if (result.errors.length > 0) {
log("onEnd: errors in build, releasing lock on build directory");
lockfile.unlockSync(outdir);
return;
}

// If we have a any js files, that do not have a corresponding HTML file,
// we need to create one and embed the JavaScript into a <script> tag.
// Then we can delete the JavaScript file as it is no longer needed.
const jsExt = /\.js$/;
const outputs = result.metafile!.outputs;
for (const [jsPath, meta] of Object.entries(outputs)) {
if (jsExt.test(jsPath)) {
const htmlPath = jsPath.replace(/\.js$/, ".html");
if (!(htmlPath in outputs)) {
delete outputs[jsPath]
const js = await fsp.readFile(jsPath, { encoding: "utf8" });
const html = `<body></body><script>${js}</script>`;
await fsp.writeFile(htmlPath, html);
outputs[htmlPath] = { ...meta, bytes: meta.bytes + 30 };
}
fsp.rm(jsPath)
delete outputs[jsPath]
}
}

Expand All @@ -181,7 +206,7 @@ function mmlPlugin({
}
}

rmEmptyDirs(outdir, log);
cleanupJS(outdir, log);

// Now we go through all of the output files and rewrite the import stubs to
// correct output path.
Expand All @@ -196,7 +221,11 @@ function mmlPlugin({
await fsp.writeFile(output, contents);
});

log("onEnd", result);

log("onEnd: releasing lock on build directory");
lockfile.unlockSync(outdir);

log("onEnd", JSON.stringify(result, undefined, 2));
});
},
})
Expand All @@ -206,9 +235,6 @@ function mmlPlugin({

const outdir = path.join(__dirname, "build")

// TODO: put this behind a flag?
rimrafSync(outdir);

const buildOptions: esbuild.BuildOptions = {
entryPoints: ["./src/playground/index.tsx"],
outdir,
Expand All @@ -217,7 +243,7 @@ const buildOptions: esbuild.BuildOptions = {
write: true,
assetNames: "[dir]/[name]",
entryNames: "[dir]/[name]",
plugins: [mmlPlugin()],
plugins: [mmlPlugin({ verbose: false })],
};

const args = process.argv.splice(2);
Expand Down
4 changes: 3 additions & 1 deletion packages/playground/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"private": true,
"scripts": {
"build": "tsx ./build.ts --build",
"iterate": "tsx --watch=./build.ts ./build.ts --watch",
"iterate": "tsx ./build.ts --watch",
"type-check": "tsc --noEmit",
"lint": "eslint -c ./.eslintrc.cjs \"./src/**/*.{js,jsx,ts,tsx}\" --max-warnings 0",
"lint:fix": "eslint -c ./.eslintrc.cjs \"./src/**/*.{js,jsx,ts,tsx}\" --fix"
Expand All @@ -15,7 +15,9 @@
"react-dom": "18.3.1"
},
"devDependencies": {
"@types/proper-lockfile": "^4.1.4",
"@types/uuid": "^10.0.0",
"proper-lockfile": "^4.1.2",
"uuid": "^10.0.0"
}
}
4 changes: 2 additions & 2 deletions packages/playground/src/duck/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ import { flushSync } from "react-dom";
import { createRoot } from "react-dom/client";

function Duck() {
return (
return (<>
<m-model id="duck" src="/assets/duck.glb" sx="2" sy="2" sz="2">
<m-attr-anim attr="ry" start="0" end="360" duration="4000"></m-attr-anim>
</m-model>
);
</>);
}

const container =
Expand Down
9 changes: 8 additions & 1 deletion packages/playground/src/examples/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,11 @@ import positionProbe from "mml:./position-probe.html";
import videoPlayer from "mml:./videoplayer.html";
import weather from "mml:./weather.html";

export { collisionEvents, dice, movingPlatform, positionProbe, videoPlayer, weather };
export {
collisionEvents,
dice,
movingPlatform,
positionProbe,
videoPlayer,
weather
};
16 changes: 8 additions & 8 deletions packages/server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,23 @@
"lint:fix": "eslint \"./src/**/*.{ts,}\" --fix"
},
"dependencies": {
"@mml-io/3d-web-experience-server": "0.18.0",
"networked-dom-server": "0.15.0",
"@mml-io/3d-web-experience-server": "^0.0.0-experimental-4934217-20240805",
"canvas": "2.11.2",
"web-client": "file:../web-client",
"chokidar": "3.6.0",
"cors": "2.8.5",
"dotenv": "16.4.5",
"express": "4.19.2",
"express-ws": "5.0.2",
"cors": "2.8.5",
"ws": "8.17.0",
"dotenv": "16.4.5"
"networked-dom-server": "0.15.0",
"web-client": "file:../web-client",
"ws": "8.17.0"
},
"devDependencies": {
"@types/express": "4.17.21",
"@types/cors": "2.8.17",
"@types/jsdom": "21.1.6",
"@types/express": "4.17.21",
"@types/express-ws": "3.0.4",
"@types/http-proxy": "1.17.14",
"@types/jsdom": "21.1.6",
"@types/node": "20.12.12",
"nodemon": "3.1.0"
}
Expand Down
6 changes: 4 additions & 2 deletions packages/server/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ const PORT = process.env.PORT || 8080;
const webClientBuildDir = path.join(dirname, "../../web-client/build/");
const assetsDir = path.join(dirname, "../../assets/");
const indexContent = fs.readFileSync(path.join(webClientBuildDir, "index.html"), "utf8");
const MML_DOCUMENT_PATH = path.join(dirname, "../../playground/build/");
const MML_DOCUMENT_ROOT = path.join(dirname, "../../playground/build/");
const MML_DOCUMENT_WATCH_PATTERN = "**/*.html";

// Specify the avatar to use here:
const characterDescription: CharacterDescription = {
Expand Down Expand Up @@ -54,8 +55,9 @@ const networked3dWebExperienceServer = new Networked3dWebExperienceServer({
networkPath: "/network",
userAuthenticator,
mmlServing: {
documentsWatchPath: MML_DOCUMENT_PATH,
documentsWatchPath: MML_DOCUMENT_WATCH_PATTERN,
documentsUrl: "/",
documentsDirectoryRoot: MML_DOCUMENT_ROOT,
},
webClientServing: {
indexUrl: "/",
Expand Down

0 comments on commit 6732c30

Please sign in to comment.