Skip to content

Instantly share code, notes, and snippets.

@AndrewIngram
Created December 31, 2019 00:25
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save AndrewIngram/860389dcb116a1a5d40b64400033529f to your computer and use it in GitHub Desktop.
Save AndrewIngram/860389dcb116a1a5d40b64400033529f to your computer and use it in GitHub Desktop.
Next.js serverless dynamic routing with centralised routes
// bin/extract-pages-core.js
// This needs to be modified to also handle _app.js, _error.js and _document.js, as well as any API routes.
// But the principle here works fine.
import path from "path";
import routes from "../src/routes";
import fs from "fs-extra";
console.log("Creating page imports");
console.log(" - Removing existing imports");
fs.removeSync(path.resolve("./pages"));
console.log(" - Creating new imports");
routes.forEach(route => {
try {
const page = route.page;
const srcPath = require.resolve(path.join("..", "src/pages", page));
const srcRelative = path.relative(path.join(process.cwd(), "src"), srcPath);
const params = route.keyNames.reduce((acc, key) => {
acc[key] = `[${key}]`;
return acc;
}, {});
const name = `${route.toPath(params)}index`;
const dstRelative = path.format({
root: "./pages",
name: decodeURI(name),
ext: ".js",
});
const importParsedPath = path.parse(
path.relative(
path.parse(path.join(process.cwd(), dstRelative)).dir,
srcPath,
),
);
const importPath = `${importParsedPath.dir}/${importParsedPath.name}`;
const content = `export { default } from "${importPath}";\n`;
const fileToCreate = path.join(process.cwd(), dstRelative);
fs.outputFileSync(fileToCreate, content, function(err) {});
} catch (err) {
console.warn(`Couldn't find page module ${route.page}`);
}
});
// bin/extract-pages.js
require("@babel/register")({
presets: ["@babel/preset-env"],
extensions: [".es6", ".es", ".jsx", ".js", ".mjs", ".ts", ".tsx"],
});
require("./extract-pages-core");
// src/pages/Homepage.tsx
import React from "react";
export default function Homepage() {
return <div>Homepage/div>;
}
// src/pages/PostDetail.js
import React from "react";
export default function PostDetail({ slug }) {
return <div>{slug}</div>;
}
PostDetail.getInitialProps = async context => {
return context.query;
};
// src/routes.js
import { compileRoutes } from "next-route-resolver";
export default compileRoutes([
{
path: "/",
name: "homepage",
page: "Homepage",
},
{
path: "/posts/:slug/",
name: "post-detail",
page: "PostDetail",
},
]);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment