-
Notifications
You must be signed in to change notification settings - Fork 3
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
Client-side bundle #8
Comments
I tried hard to make https://parceljs.org/ work, but the reality is that server-rendering this is easy (done!), but Parcel makes it very difficult to do a server+client build. diff --git a/package.json b/package.json
index b1eb7c7..bb5ab4a 100644
--- a/package.json
+++ b/package.json
@@ -26,6 +26,7 @@
"@types/microrouter": "^3.1.0",
"@types/node": "^12.0.4",
"@types/ora": "^3.2.0",
+ "@types/parcel-bundler": "^1.12.0",
"@types/webpack-env": "^1.13.9",
"np": "^5.0.3"
},
@@ -42,6 +43,7 @@
"micro": "^9.3.4",
"microrouter": "^3.1.3",
"ora": "^3.4.0",
+ "parcel-bundler": "^1.12.3",
"prism-react-renderer": "^0.1.6",
"react": "^16.8.6",
"react-dom": "^16.8.6",
diff --git a/src/app.tsx b/src/app.tsx
index cdf5b8f..b7c5c63 100644
--- a/src/app.tsx
+++ b/src/app.tsx
@@ -1,13 +1,15 @@
+// import fse from "fs-extra";
import { ServerResponse } from "http";
import { send } from "micro";
import { router, get } from "microrouter";
+import Bundler from "parcel-bundler";
import path from "path";
// @ts-ignore
import serve from "serve-handler";
-import { defaultContentDir } from "./utils/defaults";
+import { defaultContentDir, defaultOutputDir } from "./utils/defaults";
import getPage from "./utils/getPage";
-import renderPage from "./utils/renderPage";
+// import renderPage from "./utils/renderPage";
export default router(
get("(:folder)", async req => {
@@ -19,16 +21,77 @@ export default router(
}
const { folder } = req.params;
- const page = await getPage(
- path.join(defaultContentDir, folder, "index.mdx")
- );
+ const pagePath = path.join(defaultContentDir, folder, "index.mdx");
+ const page = await getPage(pagePath);
// Ignore folders without markup
if (!page) {
return;
}
- return renderPage(page);
+ const bundler = new Bundler(pagePath, {
+ cache: false,
+ hmr: false,
+ outDir: defaultOutputDir,
+ watch: true
+ });
+
+ // ! This is to test i it's a valid plugin
+ // require("./parcel-plugin");
+ bundler.addAssetType("mdx", require.resolve("./parcel-plugin"));
+
+ // ! This is to ensure we serve the file, not the folder
+ await bundler.bundle();
+
+ // ! This is a fallback for testing Parcel's output
+ await bundler.serve();
+
+ return;
+
+ // return renderPage(page);
+
+ // const targetHTML = path.join(
+ // defaultOutputDir,
+ // "__src",
+ // folder,
+ // "index.html"
+ // );
+
+ // const targetJS = path.join(defaultOutputDir, "__src", folder, "page.js");
+ // const output = await renderPage(page);
+
+ // await fse.mkdirp(path.dirname(targetHTML));
+ // await fse.writeFile(targetHTML, output, "utf8");
+
+ // await fse.copyFile(
+ // targetPage,
+ // path.join(defaultOutputDir, "__src", folder, "index.mdx")
+ // );
+
+ // fse.writeFile(targetJS, `console.log("${folder}");`, "utf8");
+
+ // const bundler = new Bundler(targetHTML, {
+ // outDir: defaultOutputDir
+ // });
+
+ // console.log(await bundler.bundle());
+
+ // bundler.addAssetType("mdx", require.resolve("./parcel-plugin"));
+ // // Included for HRM
+ // require("./parcel-plugin");
+
+ // return new Promise((resolve, reject) => {
+ // // @ts-ignore
+ // bundler.middleware()(req, res, (err: Error, data: any) => {
+ // if (err) {
+ // return reject(err);
+ // }
+
+ // console.log({ data });
+
+ // resolve(data);
+ // });
+ // });
}),
get("/*", async (req, res) => {
@@ -37,7 +100,7 @@ export default router(
res,
{
directoryListing: false,
- public: "public",
+ public: defaultOutputDir,
renderSingle: true
},
{
diff --git a/src/bin/mdx-site.tsx b/src/bin/mdx-site.tsx
index 572ae29..65cfc81 100644
--- a/src/bin/mdx-site.tsx
+++ b/src/bin/mdx-site.tsx
@@ -63,7 +63,19 @@ switch (command) {
require("../build");
break;
case "start":
- require("../server");
+ const Bundler = require("parcel-bundler");
+
+ const bundler = new Bundler("content/**/*.mdx", {
+ cache: false,
+ hmr: true,
+ outDir: defaultOutputDir,
+ watch: true
+ });
+
+ bundler.addAssetType("mdx", require.resolve("../parcel-plugin"));
+ bundler.serve();
+
+ // require("../server");
break;
default:
throw new Error(
diff --git a/src/parcel-plugin.js b/src/parcel-plugin.js
new file mode 100644
index 0000000..fcb3835
--- /dev/null
+++ b/src/parcel-plugin.js
@@ -0,0 +1,87 @@
+// @ts-check
+
+const mdx = require("@mdx-js/mdx");
+const fse = require("fs-extra");
+
+const { default: getPage } = require("./utils/getPage");
+const { default: renderPage } = require("./utils/renderPage");
+
+const Asset = require("parcel-bundler/src/Asset");
+const HTMLAsset = require("parcel-bundler/src/assets/HTMLAsset");
+const path = require("path");
+
+module.exports = class MDXAsset extends HTMLAsset {
+ constructor(name, options) {
+ super(name, options);
+
+ // console.log(this);
+
+ // this.type = "html";
+ // this.hmrPageReload = true;
+ }
+
+ async parse(code) {
+ const page = await getPage(this.name);
+ const html = await renderPage(page);
+
+ return super.parse(html);
+ }
+
+ async generate() {
+ const parts = await super.generate();
+
+ // console.log({ parts });
+
+ console.log(this);
+ return parts;
+ }
+
+ // @ts-ignore
+ // async generate() {
+ // const { options, resolver, ...rest } = this;
+ // console.log("COnstructed", rest);
+
+ // this.parentBundle = this;
+
+ // const page = await getPage(this.name);
+
+ // // console.log(this);
+
+ // // this.addURLDependency(this.name, this.name, {
+ // // includedInParent: true
+ // // });
+
+ // return super.generate(await renderPage(page));
+ // if (this.type === "html") {
+ // }
+
+ // const pageJS = path.relative(
+ // process.cwd(),
+ // path.join(this.options.outDir, "index.js")
+ // );
+
+ // await fse.writeFile(
+ // pageJS,
+ // `
+ // console.log(${JSON.stringify(folder)})
+ // `,
+ // "utf8"
+ // );
+
+ // this.addDependency(this.name, {
+ // includedInParent: true
+ // });
+
+ // await fse.writeFile(
+ // path.join(folder, "page.js"),
+ // `
+ // /* @jsx mdx */
+ // import React from "react";
+ // import { mdx } from "@mdx-js/react"
+
+ // ${compiled}
+ // `,
+ // "utf8"
+ // );
+ // }
+};
diff --git a/src/utils/renderPage.tsx b/src/utils/renderPage.tsx
index 1ff9abb..37b6816 100644
--- a/src/utils/renderPage.tsx
+++ b/src/utils/renderPage.tsx
@@ -20,8 +20,8 @@ interface Page {
readonly raw: string;
}
-export default async function renderPage(page: Page) {
- const { attributes, body, props } = page;
+export default async function renderPage(page: Page, variables = {}) {
+ const { attributes = {}, body, props } = page;
const { title } = attributes;
const components = await getComponents(defaultComponentsDir);
@@ -49,7 +49,8 @@ export default async function renderPage(page: Page) {
const html = await renderTemplate({
title: title || defaultTitle,
description,
- markup
+ markup,
+ ...variables
});
if (process.env.NODE_ENV !== "production") {
diff --git a/template/public/index.html b/template/public/index.html
index 4abedc5..4775fe4 100644
--- a/template/public/index.html
+++ b/template/public/index.html
@@ -14,6 +14,7 @@
%MARKUP%
</body>
+<script src="./index.mdx" type="application/javascript"></script>
<script src="https://unpkg.com/[email protected]/dist/quicklink.umd.js"></script>
</html> Based on my research, I think the best possible solution would be similar to https://github.com/zeit/next.js/tree/canary/packages/next-mdx that would, instead:
Put another way, |
The bad news with this approach is that the intelligent usage of layouts & components would go away. The good news is, this could possibly be an example in the Next.js repo, which could then be created via: npx create-next-app --example mdx-site my-site
|
I did this as a Next.js app, but the JS payload was huge and creating I think the next step would be to use |
To support client-side rendering, I'm thinking:
${folder}/index.html
frompublic/index.html
.${folder}/index.js
from theindex.mdx
+index.tsx
The text was updated successfully, but these errors were encountered: