nitropage
Version:
A free and open source, extensible visual page builder based on SolidStart.
219 lines (210 loc) • 6.74 kB
JavaScript
// src/build/start.ts
import { defineConfig as defineConfig_ } from "@solidjs/start/config";
import { uniq } from "es-toolkit";
import lazyPlusPlugin from "solid-lazy-plus/vite";
import { mergeConfig } from "vite";
// src/lib/server/path.ts
import { join, resolve } from "path";
import { fileURLToPath } from "url";
// src/lib/server/util/env.ts
var env = (key) => process.env[key] || void 0;
env.boolean = (key) => {
const v = env(key);
if (v == null) return;
return v === "1" || v === "true";
};
env.number = (key) => {
const v = Number(env(key));
if (Number.isNaN(v)) return;
return v;
};
// src/lib/server/path.ts
var devPublicPath = join(process.cwd(), "public");
var dirname = fileURLToPath(new URL(".", import.meta?.url));
var outputDir = dirname.slice(0, dirname.lastIndexOf("/server/"));
var publicPath = import.meta.env?.PROD ? resolve(outputDir, "public") : devPublicPath;
var runtimePath = env("NP_RUNTIME_PATH") ?? "./src/runtime";
// src/build/lib.ts
import chokidar from "chokidar";
import crypto from "crypto";
import { debounce } from "es-toolkit";
import { readFile, writeFile } from "fs/promises";
import { relative, resolve as resolve2 } from "path";
var resolveCwd = (...path) => resolve2(process.cwd(), ...path);
var fsWatcher;
var initVinxiReload = () => {
if (fsWatcher) fsWatcher.close();
fsWatcher = chokidar.watch(
[
resolveCwd(runtimePath, "server.config.ts"),
resolveCwd(runtimePath, "plugin.ts")
].filter(Boolean),
{
ignoreInitial: true,
persistent: true
}
);
fsWatcher.on("all", reloadVinxi);
};
var reloadVinxi = debounce(async () => {
const appConfigPath = resolveCwd("app.config.ts");
const content = await readFile(appConfigPath, "utf-8");
await writeFile(appConfigPath, content);
}, 250);
var hashCache = {};
var cwd = process.cwd();
var manualChunks = (id) => {
if (!id.endsWith("module.css")) {
return;
}
const relativeId = relative(cwd, id);
const hash = hashCache[id] ??= crypto.createHash("sha256").update(relativeId).digest("hex").slice(0, 10);
return hash;
};
// src/build/solidRealmsPatch.ts
import MagicString from "magic-string";
var isPlainObjectTmpl = `
function isPlainObject(obj) {
if (obj.constructor === undefined) return true;
const proto = obj.constructor.prototype;
if (typeof proto !== "object") return false;
if (proto.hasOwnProperty('isPrototypeOf') === false) return false;
return true;
};`;
var solidRealmsPatchPlugin = () => {
const regex = new RegExp("(solid-js/store/dist/store)|(solid-js_store)\\.js");
return {
name: "solid-realms-patch",
transform(code, id, options) {
if (options?.ssr) return;
if (!id.match(regex)) return;
const s = new MagicString(code);
s.replace("proto === Object.prototype", "isPlainObject(obj)");
if (!s.hasChanged) {
console.error("Failed to patch Solid isWrappable!");
return;
}
s.replace(
"function isWrappable",
`${isPlainObjectTmpl}
function isWrappable`
);
const newCode = s.toString();
if (!newCode.includes("function isPlainObject(obj)")) {
console.error("Failed to patch Solid isWrappable!");
return;
}
const result = {
code: newCode,
map: s.generateMap()
};
return result;
}
};
};
// src/build/start.ts
var defineConfig = (opts) => {
const { vite, ...optsRest } = opts;
const { plugins: serverPlugins, ...serverRest } = optsRest.server ??= {};
const isBuild = process.env.NODE_ENV === "production";
const isMonoRepo = import.meta.url.endsWith(
"packages/nitropage/dist/start/start.js"
);
if (!isBuild) {
initVinxiReload();
}
return defineConfig_({
middleware: resolveCwd(runtimePath, "middleware.ts"),
vite(params) {
const { router } = params;
const user = vite ? typeof vite === "function" ? vite(params) : vite : {};
const noOptimize = ["nitropage", "@npio/server"];
let internalLibraries = [
"@lufrai/quill",
"isobject",
"@paralleldrive/cuid2"
];
if (!isMonoRepo) {
internalLibraries = internalLibraries.map((v) => `nitropage > ` + v);
}
const optimizeOnClient = ["clsx", ...internalLibraries];
const solidLibraries = [
"@corvu/resizable",
"@kobalte/core",
"@modular-forms/solid",
"corvu",
"fela-plugin-multiple-selectors",
"fela-plugin-prefixer",
"serfu",
"solid-lazy-plus"
];
const serverLibraries = ["bcrypt", "fsevents", "minio", "sharp"];
const serverBundleLibraries = isBuild ? ["dotenv"] : [];
const userOutput = user.build?.rollupOptions?.output;
if (userOutput && !Array.isArray(userOutput) && userOutput.manualChunks) {
console.warn(
"Custom manualChunks is currently not supported and will be disabled!"
);
delete userOutput.manualChunks;
}
const merged = mergeConfig(
{
build: {
assetsInlineLimit: (path) => {
if (path.match(/\.(j|t)sx?$/)) {
return false;
}
return;
},
rollupOptions: {
output: {
manualChunks
}
}
},
resolve: {
alias: {
"#client": resolveCwd(
runtimePath,
router === "client" ? "client.config.hot.ts" : "client.config.tsx"
)
}
},
plugins: [solidRealmsPatchPlugin(), lazyPlusPlugin({ router })],
optimizeDeps: {
include: optimizeOnClient,
exclude: uniq([
...noOptimize,
...solidLibraries,
...serverLibraries
])
},
ssr: {
external: uniq([...serverLibraries, ...optimizeOnClient]),
noExternal: uniq([...serverBundleLibraries, ...solidLibraries])
}
},
user
);
return merged;
},
...optsRest,
server: {
plugins: serverPlugins ?? [resolveCwd(runtimePath, "plugin.ts")],
compressPublicAssets: false,
esbuild: {
options: {
// Building projects outside of the monorepo fails without this
// Nitro doesn't transpile typescript files in dependencies imported by plugins
// https://github.com/nitrojs/nitro/blob/231c516e866a43c7e437e651c97ac14218ce1300/src/rollup/plugins/esbuild.ts#L42
exclude: [/node_modules(?!\/(.pnpm\/)?(nitropage|@npio))/],
target: "esnext"
}
},
...serverRest
}
});
};
export {
defineConfig
};