Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add exports so build can be consumed as a module #40

Merged
merged 5 commits into from
Apr 28, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ on:
push:
branches:
- main
pull_request:
pull_request:
workflow_dispatch:

# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
Expand Down Expand Up @@ -47,7 +47,7 @@ jobs:
with:
project: mononykus
entrypoint: https://deno.land/[email protected]/http/file_server.ts
root: src/_site/build
root: build

gh:
if: github.ref_name == 'main'
Expand Down
4 changes: 2 additions & 2 deletions deno.jsonc
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"tasks": {
"build": "deno run -A src/build.ts --site src/_site",
"dev": "deno run -A src/build.ts --site src/_site --dev --base=mononykus"
"build": "deno run -A src/build.ts --site_dir src/_site",
"dev": "deno run -A src/build.ts --site_dir src/_site --watch --base=mononykus"
},
"compilerOptions": {
"strict": true,
Expand Down
178 changes: 124 additions & 54 deletions src/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,52 @@ import { walk } from "https://deno.land/[email protected]/fs/walk.ts";
import { create_handler } from "./server.ts";
import { globToRegExp } from "https://deno.land/[email protected]/path/glob.ts";
import { copy } from "https://deno.land/[email protected]/fs/copy.ts";
import { normalize } from "https://deno.land/[email protected]/path/mod.ts";

const slashify = (path: string) => normalize(path.replace(/\/?$/, "/"));

type Options = {
base: string;
out_dir: string;
site_dir: string;
minify: boolean;
};

const flags = parse(Deno.args, {
string: ["site", "build", "base"],
boolean: ["dev"],
default: { site: "_site/", dev: false, base: "/" },
string: ["site_dir", "out_dir", "base"],
boolean: ["minify", "watch"],
default: {
site_dir: "_site",
out_dir: "build",
base: "/",
minify: false,
watch: false,
},
});

const site_dir = flags.site.replace(/\/?$/, "/");
const build_dir = (flags.build ?? `${site_dir}build/`).replace(/\/?$/, "/");
const base_path = flags.base.replace(/\/?$/, "/");
const options: Options = {
site_dir: slashify(flags.site_dir),
out_dir: slashify(flags.out_dir),
base: slashify(flags.base),
minify: !flags.watch || flags.minify,
};

// clean out old builds, if they exist
try {
await Deno.remove(build_dir, { recursive: true });
} catch (_error) {
// do nothing
}
const clean = async (out_dir: Options["out_dir"]) => {
try {
await Deno.remove(out_dir, { recursive: true });
} catch (_error) {
// do nothing
}

await ensureDir(out_dir);
};

export const get_svelte_files = async ({
site_dir,
dir,
}: {
site_dir: Options["site_dir"];
dir: "routes/" | "components/";
}) => {
const glob = (glob: string) => globToRegExp(glob, { globstar: true });
Expand All @@ -48,63 +73,108 @@ export const get_svelte_files = async ({
return files;
};

await ensureDir(build_dir);

const baseESBuildConfig = {
logLevel: "info",
format: "esm",
minify: !flags.dev,
bundle: true,
} as const satisfies Partial<esbuild.BuildOptions>;

const routesESBuildConfig: esbuild.BuildOptions = {
entryPoints: await get_svelte_files({ dir: "routes/" }),
write: false,
plugins: [
svelte_components(site_dir, base_path),
svelte_internal,
build_routes,
],
outdir: build_dir,
...baseESBuildConfig,
};
const copy_assets = (
{ site_dir, out_dir }: Partial<Options>,
) => copy(site_dir + "assets", out_dir + "assets", { overwrite: true });

const islandsESBuildConfig: esbuild.BuildOptions = {
entryPoints: await get_svelte_files({ dir: "components/" }),
write: true,
plugins: [
svelte_components(site_dir, base_path),
svelte_internal,
],
outdir: build_dir + "components/",
splitting: true,
...baseESBuildConfig,
};
const rebuild = async ({
base,
out_dir,
site_dir,
minify,
}: Options) => {
const baseESBuildConfig = {
logLevel: "info",
format: "esm",
minify: minify,
bundle: true,
} as const satisfies Partial<esbuild.BuildOptions>;

const routesESBuildConfig: esbuild.BuildOptions = {
entryPoints: await get_svelte_files({ site_dir, dir: "routes/" }),
write: false,
plugins: [
svelte_components(site_dir, base),
svelte_internal,
build_routes,
],
outdir: out_dir,
...baseESBuildConfig,
};

const copy_assets = async () =>
await copy(site_dir + "assets", build_dir + "assets", { overwrite: true });
const islandsESBuildConfig: esbuild.BuildOptions = {
entryPoints: await get_svelte_files({ site_dir, dir: "components/" }),
write: true,
plugins: [
svelte_components(site_dir, base),
svelte_internal,
],
outdir: out_dir + "components/",
splitting: true,
...baseESBuildConfig,
};

const rebuild = async () => {
await Promise.all([
return Promise.all([
esbuild.build(routesESBuildConfig),
esbuild.build(islandsESBuildConfig),
copy_assets(),
copy_assets({ site_dir, out_dir }),
]);
};

await rebuild();
export const build = async (
{
base: _base = options.base,
out_dir: _out_dir = options.out_dir,
site_dir: _site_dir = options.site_dir,
minify = options.minify,
}: Partial<Options> = {},
) => {
const base = slashify(_base);
const out_dir = slashify(_out_dir);
const site_dir = slashify(_site_dir);

clean(out_dir);

await rebuild({ base, out_dir, site_dir, minify });

esbuild.stop();
};

export const watch = async (
{
base: _base = options.base,
out_dir: _out_dir = options.out_dir,
site_dir: _site_dir = options.site_dir,
minify = options.minify,
}: Partial<Options> = {},
) => {
const base = slashify(_base);
const out_dir = slashify(_out_dir);
const site_dir = slashify(_site_dir);

clean(out_dir);

const _rebuild = () => rebuild({ base, out_dir, site_dir, minify });

await _rebuild();

serve(create_handler({ base: base, out_dir }), { port: 4507 });

if (flags.dev) {
const watcher = Deno.watchFs(site_dir);
serve(create_handler({ base: flags.base, build_dir }), { port: 4507 });
let timeout;
for await (const { kind, paths: [path] } of watcher) {
if (path && (kind === "modify" || kind === "create")) {
if (path.includes(build_dir)) continue;
if (path.includes(out_dir)) continue;
clearTimeout(timeout);
timeout = setTimeout(rebuild, 6);
timeout = setTimeout(_rebuild, 6);
}
}
} else {
Deno.exit(0);
};

if (import.meta.main) {
if (flags.watch) {
await watch(options);
} else {
await build(options);
}
}
6 changes: 3 additions & 3 deletions src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@ import { serveDir } from "https://deno.land/[email protected]/http/file_server.ts";

interface ServerOptions {
base?: string;
build_dir: string;
out_dir: string;
}

export const create_handler = (
{ base = "", build_dir }: ServerOptions,
{ base = "", out_dir }: ServerOptions,
): Handler => ((req) => {
const url = new URL(req.url);

if (url.pathname.startsWith("/" + base)) {
return serveDir(req, { fsRoot: build_dir, urlRoot: base });
return serveDir(req, { fsRoot: out_dir, urlRoot: base });
} else {
return Response.redirect(new URL(base + url.pathname, url.origin));
}
Expand Down