Skip to content

Commit

Permalink
feat: move away from tla
Browse files Browse the repository at this point in the history
  • Loading branch information
DylanPiercey committed Nov 30, 2023
1 parent 161b0c1 commit 1472478
Show file tree
Hide file tree
Showing 13 changed files with 468 additions and 427 deletions.
5 changes: 5 additions & 0 deletions .changeset/good-masks-float.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"arc-vite": minor
---

Move away from top level await which has limited browser support.
568 changes: 272 additions & 296 deletions package-lock.json

Large diffs are not rendered by default.

31 changes: 15 additions & 16 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,40 +37,39 @@
"lint": "npm run build && eslint -f unix && prettier . --check --log-level=warn && sort-package-json --quiet --check",
"prepare": "husky install",
"release": "npm run build && changeset publish",
"test": "tsx --test-reporter=spec --test ./src/tests/*.test.ts",
"test": "MARKO_DEBUG=true tsx --test-reporter=spec --test ./src/tests/*.test.ts",
"version": "changeset version && npm i --package-lock-only"
},
"dependencies": {
"arc-resolver": "^3.0.0",
"domelementtype": "^2.3.0",
"domhandler": "^5.0.3",
"dom-serializer": "^2.0.0",
"htmlparser2": "^9.0.0"
},
"devDependencies": {
"@changesets/changelog-github": "^0.4.8",
"@changesets/cli": "^2.26.2",
"@marko/compiler": "^5.33.8",
"@marko/vite": "^4.0.2",
"@playwright/test": "^1.39.0",
"@changesets/changelog-github": "^0.5.0",
"@changesets/cli": "^2.27.1",
"@marko/compiler": "^5.34.1",
"@marko/vite": "^4.1.1",
"@playwright/test": "^1.40.1",
"@types/estree": "^1.0.5",
"@types/node": "^20.9.0",
"@types/node": "^20.10.1",
"@types/serve-handler": "^6.1.4",
"@typescript-eslint/eslint-plugin": "^6.11.0",
"@typescript-eslint/parser": "^6.11.0",
"@typescript-eslint/eslint-plugin": "^6.13.1",
"@typescript-eslint/parser": "^6.13.1",
"c8": "^8.0.1",
"eslint": "^8.53.0",
"eslint": "^8.54.0",
"eslint-config-prettier": "^9.0.0",
"eslint-import-resolver-typescript": "^3.6.1",
"eslint-plugin-import": "^2.29.0",
"husky": "^8.0.3",
"lint-staged": "^15.1.0",
"marko": "^5.31.18",
"playwright": "^1.39.0",
"marko": "^5.32.0",
"playwright": "^1.40.1",
"prettier": "^3.1.0",
"serve-handler": "^6.1.5",
"sort-package-json": "^2.6.0",
"tsx": "^4.1.2",
"typescript": "^5.2.2",
"tsx": "^4.6.1",
"typescript": "^5.3.2",
"vite": "^4.5.0"
},
"peerDependencies": {
Expand Down
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type { Plugin } from "vite";
import { pluginBuildSSR } from "./plugins/build-ssr";
import { pluginBuildWeb } from "./plugins/build-web";
import { pluginServe } from "./plugins/serve";
import type { FlagSet } from "./utils/flags";
import { type Options, getInternalPluginOptions } from "./utils/options";

export { createFlagSets, hasFlags } from "./utils/flags";
Expand Down Expand Up @@ -35,6 +36,7 @@ declare module "rollup" {
arcSourceId?: string;
arcSourceCode?: string;
arcScanIds?: string[];
arcFlagSet?: FlagSet;
arcFS?: typeof import("fs");
}
}
11 changes: 8 additions & 3 deletions src/plugins/build-ssr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -209,16 +209,21 @@ function partsToString(parts, base, injectAttrs) {
}
}
} else if (isArcVirtualMatch(id)) {
const [arcSourceId, flagSet] = decodeArcVirtualMatch(id);
const [arcSourceId, arcFlagSet] = decodeArcVirtualMatch(id);
const { meta, moduleSideEffects, syntheticNamedExports } =
this.getModuleInfo(arcSourceId)!;
const code = meta.arcSourceCode as string;
const arcFS = getArcFS(flagSet);
const arcFS = getArcFS(arcFlagSet);
return {
code,
moduleSideEffects,
syntheticNamedExports,
meta: { ...meta, arcSourceId, arcFS },
meta: {
...meta,
arcSourceId,
arcFlagSet,
arcFS,
},
};
}

Expand Down
142 changes: 91 additions & 51 deletions src/plugins/build-web.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@ import { indexToId } from "../utils/index-to-id";
import { isCssFile } from "../utils/is-css-file";
import {
type DocManifest,
generateDocManifest,
generateInputDoc,
generatManifest,
generateHTML,
} from "../utils/manifest";
import { type Matches } from "../utils/matches";
import { type InternalPluginOptions } from "../utils/options";
import { stripEntryScript } from "../utils/strip-entry-script";
import { toPosix } from "../utils/to-posix";
import {
decodeArcVirtualMatch,
getVirtualMatches,
Expand All @@ -23,10 +25,10 @@ import {

const arcPrefix = "\0arc-";
const arcJsSuffix = ".mjs";
const arcProxyPrefix = `${arcPrefix}proxy:`;
const arcInitPrefix = `${arcPrefix}init:`;
const arcHTMLChunkReg = /(.+)\.arc(?:\.(.+))?\.html$/;

const arcProxyPrefix = `${arcPrefix}proxy:`;
const emptyScriptReg = /^[\s;]+$/;
const arcChunkFileNameReg = /(.+)\.arc(?:\.(.+))?\.html$/;
export function pluginBuildWeb({
runtimeId,
flagSets,
Expand All @@ -36,9 +38,12 @@ export function pluginBuildWeb({
const adaptiveImporters = new Map<string, Map<string, string>>();
const adaptiveMatchesForId = new Map<string, Matches>();
const bindingsByAdaptiveId = new Map<string, Set<string> | true>();
const resolvedAdaptiveImportsForChunk = new Map<
const metaForAdaptiveChunk = new Map<
string,
Map<string, string>
{
entryId: string;
adaptiveImports: Map<string, string>;
}
>();
const apply: Plugin["apply"] = (config, { command }) =>
command === "build" && !config.build?.ssr;
Expand All @@ -62,7 +67,7 @@ export function pluginBuildWeb({
adaptiveImporters.clear();
adaptiveMatchesForId.clear();
bindingsByAdaptiveId.clear();
resolvedAdaptiveImportsForChunk.clear();
metaForAdaptiveChunk.clear();
},
async resolveId(source, importer, options) {
if (importer) {
Expand Down Expand Up @@ -111,9 +116,9 @@ export function pluginBuildWeb({
}

return resolved;
} else if (resolvedAdaptiveImportsForChunk.has(source)) {
} else if (metaForAdaptiveChunk.has(source)) {
return source;
} else if (options.isEntry) {
} else if (options.isEntry && !isArcId(source)) {
const resolved = await this.resolve(source, importer, {
...options,
skipSelf: true,
Expand Down Expand Up @@ -205,10 +210,10 @@ export function pluginBuildWeb({
flagSet.length ? `.${flagSet.join(".")}` : ""
}.html`;

resolvedAdaptiveImportsForChunk.set(
id,
resolvedAdaptiveImports,
);
metaForAdaptiveChunk.set(id, {
entryId: resolved.id,
adaptiveImports: resolvedAdaptiveImports,
});
return id;
}),
);
Expand Down Expand Up @@ -273,27 +278,25 @@ export function pluginBuildWeb({
},

async load(id) {
const resolvedAdaptiveImports = resolvedAdaptiveImportsForChunk.get(id);
if (resolvedAdaptiveImports) {
let code = "";
const adaptiveChunkMeta = metaForAdaptiveChunk.get(id);

for (const [adaptiveImport, adaptedImport] of [
...resolvedAdaptiveImports,
].reverse()) {
if (adaptiveChunkMeta) {
let code = "";
const adaptiveImports = [...adaptiveChunkMeta.adaptiveImports];
for (let i = adaptiveImports.length; i--; ) {
const [adaptiveImport, adaptedImport] = adaptiveImports[i];
code += `import ${JSON.stringify(
encodeArcInitId(adaptiveImport, adaptedImport),
)};\n`;
}

code = generateInputDoc(code);
code = generateHTML(code);

return {
code,
moduleSideEffects: false,
moduleSideEffects: "no-treeshake",
};
}

if (isArcProxyId(id)) {
} else if (isArcProxyId(id)) {
id = decodeArcProxyId(id);

if (isCssFile(id)) {
Expand Down Expand Up @@ -360,47 +363,79 @@ export function pluginBuildWeb({
moduleSideEffects: "no-treeshake",
};
} else if (isArcVirtualMatch(id)) {
const [arcSourceId, flagSet] = decodeArcVirtualMatch(id);
const [arcSourceId, arcFlagSet] = decodeArcVirtualMatch(id);
const { meta, moduleSideEffects, syntheticNamedExports } =
this.getModuleInfo(arcSourceId)!;
const code = meta.arcSourceCode as string;
const arcFS = getArcFS(flagSet);
const arcFS = getArcFS(arcFlagSet);
return {
code,
moduleSideEffects,
syntheticNamedExports,
meta: { ...meta, arcSourceId, arcFS },
meta: {
...meta,
arcSourceId,
arcFlagSet,
arcFS,
},
};
}

return null;
},
transformIndexHtml(html, { chunk }) {
if (!chunk?.facadeModuleId) return;
if (arcChunkFileNameReg.test(chunk.facadeModuleId)) {
return [
{
injectTo: "head-prepend",
tag: "script",
children: `${runtimeId}={}`,
},
];
}

banner(chunk) {
if (chunk.isEntry) {
return stripEntryScript(basePath, chunk.fileName, html);
},
generateBundle(_, bundle) {
const facadeModuleIdToEntryName = new Map<string, string>();
for (const fileName in bundle) {
const chunk = bundle[fileName];
if (
chunk.type === "chunk" &&
chunk.isEntry &&
chunk.facadeModuleId &&
arcHTMLChunkReg.test(chunk.facadeModuleId)
!arcChunkFileNameReg.test(chunk.facadeModuleId) &&
!emptyScriptReg.test(chunk.code)
) {
return `window.${runtimeId}={};`;
facadeModuleIdToEntryName.set(chunk.facadeModuleId, chunk.fileName);
}

return `window.${runtimeId}_d || await new Promise(r => window.${runtimeId}_d = r);`;
}

return "";
},

footer(chunk) {
if (
chunk.isEntry &&
chunk.facadeModuleId &&
arcHTMLChunkReg.test(chunk.facadeModuleId)
) {
return `window.${runtimeId}_d?.();\nwindow.${runtimeId}_d = true;`;
for (const fileName in bundle) {
const chunk = bundle[fileName];
if (
chunk.type === "chunk" &&
chunk.isEntry &&
chunk.facadeModuleId &&
arcChunkFileNameReg.test(chunk.facadeModuleId)
) {
const adaptiveChunkMeta = metaForAdaptiveChunk.get(
chunk.facadeModuleId,
);
if (adaptiveChunkMeta) {
const originalEntryName = facadeModuleIdToEntryName.get(
adaptiveChunkMeta.entryId,
);
if (originalEntryName) {
chunk.imports.push(originalEntryName);
chunk.code += `;import ${JSON.stringify(
toRelativeImport(chunk.fileName, originalEntryName),
)}`;
}
}
}
}

return "";
},
},
{
Expand Down Expand Up @@ -431,16 +466,13 @@ export function pluginBuildWeb({
for (const fileName in bundle) {
const chunk = bundle[fileName];
if (chunk.type === "asset") {
const arcHTMLChunkMatch = arcHTMLChunkReg.exec(chunk.fileName);
const arcHTMLChunkMatch = arcChunkFileNameReg.exec(chunk.fileName);
if (!arcHTMLChunkMatch) continue;
delete bundle[fileName];
const [, entryName, flagSetStr] = arcHTMLChunkMatch;
const flaggedManifest = {
flags: (flagSetStr ? flagSetStr.split(".") : []) as FlagSet,
manifest: await generateDocManifest(
basePath,
chunk.source.toString(),
),
manifest: generatManifest(basePath, chunk.source.toString()),
};
const flaggedAssetsForEntry = flaggedManifestByEntry.get(entryName);
if (flaggedAssetsForEntry) {
Expand Down Expand Up @@ -554,3 +586,11 @@ function decodeArcInitId(id: string) {
: path.join(adaptiveImport, "..", relativeAdaptedImport);
return [adaptiveImport, adaptedImport];
}

function toRelativeImport(from: string, to: string) {
const relative = path.relative(path.dirname(toPosix(from)), toPosix(to));
if (relative[0] !== ".") {
return `./${relative}`;
}
return relative;
}
1 change: 0 additions & 1 deletion src/tests/basic.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@ async function assertHasDesktopContent(page: Page) {
}

async function assertHasMobileContent(page: Page) {
await page.pause();
await expect(page.locator("body")).toHaveCSS(
"background-color",
"rgb(0, 255, 255)",
Expand Down
1 change: 0 additions & 1 deletion src/tests/marko-scan-files.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ t.test("marko-scan-files", async (t) => {

await t.test("FLAGS=mobile", async (t) => {
await page.goto("/?mobile");
await page.pause();
await t.test("has mobile content", async () => {
await assertHasMobileContent(page);
});
Expand Down
1 change: 0 additions & 1 deletion src/tests/marko.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@ async function assertHasDesktopContent(page: Page) {
}

async function assertHasMobileContent(page: Page) {
await page.pause();
await expect(page.locator("body")).toHaveCSS(
"background-color",
"rgb(0, 255, 255)",
Expand Down
9 changes: 5 additions & 4 deletions src/utils/flags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,17 +62,18 @@ export function compareFlagSets(a: FlagSet, b: FlagSet) {
if (aLen === bLen) {
for (let i = aLen; i--; ) {
const compared = compareFlags(a[i], b[i]);
if (compared === 0) continue;
return compared;
if (compared !== 0) return compared;
}
}

return bLen - aLen;
}

export function normalizeFlagSets(rawFlagSets: string[][]): FlagSet[] {
if (!rawFlagSets.length) return rawFlagSets as FlagSet[];
const sortedFlagSets = rawFlagSets.map(normalizeFlagSet).sort();
if (!rawFlagSets.length) return [[]] as unknown as FlagSet[];
const sortedFlagSets = rawFlagSets
.map(normalizeFlagSet)
.sort(compareFlagSets);
let prev = sortedFlagSets[0];
const uniqueFlagSets = [prev];
for (let i = 1; i < sortedFlagSets.length; i++) {
Expand Down
Loading

0 comments on commit 1472478

Please sign in to comment.