Skip to content

Commit

Permalink
feat: Migrate into Next.js App Router (#353)
Browse files Browse the repository at this point in the history
* Migrate into app router

* Update tsconfig

* Configure export

* Fix lint config

* Move generateStaticParams

* Fix to return correct data

* Add missing peer dependencies

* Remove unused function

* Remove wrong peer

* Remove needless stylelint plugin

* Fix resolving conflict

* Fix title

* Remove passHref

* Wrap GoogleAnalytics with Suspense
  • Loading branch information
MikuroXina authored Oct 25, 2023
1 parent 4219ed8 commit ec340d6
Show file tree
Hide file tree
Showing 66 changed files with 512 additions and 531 deletions.
14 changes: 0 additions & 14 deletions .eslintrc

This file was deleted.

17 changes: 17 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module.exports = {
extends: ["next/core-web-vitals", "prettier"],
plugins: ["chakra-ui"],
parser: "@typescript-eslint/parser",
parserOptions: {
project: true,
tsconfigRootDir: __dirname,
},
rules: {
"sort-imports": "error",
"@next/next/no-img-element": "off",
"chakra-ui/props-order": "error",
"chakra-ui/props-shorthand": "error",
"chakra-ui/require-specific-component": "error",
},
ignorePatterns: [".eslintrc.js"],
};
1 change: 0 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ jobs:
- name: Run build
run: |
yarn build
yarn export
env:
NEXT_PUBLIC_BASE_URL: ${{ secrets.BASE_URL }}
NEXT_PUBLIC_GOOGLE_ANALYTICS_ID: ${{ secrets.GOOGLE_ANALYTICS_ID }}
Expand Down
6 changes: 1 addition & 5 deletions .stylelintrc
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
{
"extends": [
"stylelint-config-sass-guidelines",
"stylelint-config-recess-order",
"stylelint-config-prettier"
],
"extends": ["stylelint-config-sass-guidelines", "stylelint-config-recess-order"],
"rules": {
"order/properties-alphabetical-order": null
}
Expand Down
10 changes: 10 additions & 0 deletions next.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// @ts-check

/**
* @type {import('next').NextConfig}
*/
const nextConfig = {
output: "export",
};

module.exports = nextConfig;
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
"dev": "next dev",
"build": "next build",
"start": "next start",
"export": "next export",
"lint:code": "next lint",
"lint:code:fix": "next lint --fix",
"lint:style": "stylelint 'src/**/*.{css,scss}'",
Expand Down Expand Up @@ -44,6 +43,7 @@
"@types/node": "^18.11.10",
"@types/react": "^18.2.21",
"@types/react-test-renderer": "^18.0.0",
"@typescript-eslint/parser": "^6.7.5",
"@vitejs/plugin-react": "^3.1.0",
"eslint": "8.37.0",
"eslint-config-next": "13.5.3",
Expand All @@ -60,7 +60,6 @@
"react-test-renderer": "^18.2.0",
"sass": "^1.62.1",
"stylelint": "^15.10.3",
"stylelint-config-prettier": "^9.0.4",
"stylelint-config-recess-order": "^4.3.0",
"stylelint-config-sass-guidelines": "^10.0.0",
"ts-node": "^10.9.1",
Expand Down
20 changes: 20 additions & 0 deletions src/app/blog/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { BlogInfo, BlogInfos, getAllBlogInfos, getBlogFromId } from "../../lib/blog-fetch";
import { Metadata } from "next";
import { Post } from "./post";

export async function generateMetadata({ params }: { params: BlogInfo }): Promise<Metadata> {
const { title } = await getBlogFromId(params.id);
return { title: `ブログ - ${title}` };
}

export async function generateStaticParams(): Promise<BlogInfos> {
return getAllBlogInfos();
}

export default async function Page({ params }: { params?: BlogInfo }) {
if (params == null) {
throw new Error("invalid params");
}
const post = await getBlogFromId(params.id);
return <Post post={post} />;
}
34 changes: 7 additions & 27 deletions src/pages/blog/[id].tsx → src/app/blog/[id]/post.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Blog, BlogInfo, getAllBlogInfos, getBlogFromId } from "../../lib/blog-fetch";
"use client";

import { Container, Heading, Link, Text, VStack } from "@chakra-ui/react";
import type { GetStaticPaths, GetStaticProps, NextPage } from "next";
import { Blog } from "../../lib/blog-fetch";
import { DateString } from "../../components/date";
import { Layout } from "../../components/layout";
import MarkdownIt from "markdown-it";
import MarkdownItFootnote from "markdown-it-footnote";
import MarkdownItFrontMatter from "markdown-it-front-matter";
Expand All @@ -17,11 +17,11 @@ const md = MarkdownIt({
.use(MarkdownItFrontMatter)
.use(MarkdownItFootnote);

type BlogPostPageProps = {
export type BlogPostPageProps = {
post: Blog;
};

const BlogPostPage: NextPage<BlogPostPageProps> = ({ post }) => {
export const Post = ({ post }: BlogPostPageProps) => {
const prevNext = (
<PrevNextLink
prevLinkHref={post.prevId !== "" ? post.prevId : null}
Expand All @@ -30,7 +30,7 @@ const BlogPostPage: NextPage<BlogPostPageProps> = ({ post }) => {
);
const bodyHtml = md.render(emojify`${post.content}`);
return (
<Layout pageName={`限界開発鯖 - ブログ - ${post.title}`}>
<>
<VStack>
<Heading m={8} textAlign="center">
{post.title}
Expand All @@ -48,26 +48,6 @@ const BlogPostPage: NextPage<BlogPostPageProps> = ({ post }) => {
<div dangerouslySetInnerHTML={{ __html: bodyHtml }} />
</Container>
{prevNext}
</Layout>
</>
);
};

export const getStaticProps: GetStaticProps<BlogPostPageProps, BlogInfo> = async ({ params }) => {
if (params == null) {
throw new Error("invalid params");
}
console.dir(params);
const post = await getBlogFromId(params.id);
return {
props: {
post,
},
};
};

export const getStaticPaths: GetStaticPaths<BlogInfo> = async () => {
const paths = await getAllBlogInfos();
return { paths, fallback: false };
};

export default BlogPostPage;
50 changes: 50 additions & 0 deletions src/app/blog/blog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
"use client";
import {
Avatar,
Button,
Flex,
HStack,
Heading,
Link,
SimpleGrid,
Spacer,
VStack,
} from "@chakra-ui/react";
import { DateString } from "../components/date";
import { Metadata } from "../lib/blog-fetch";
import NextLink from "next/link";
import { Metadata as NextMetadata } from "next";
import type { NextPage } from "next";

export const metadata: NextMetadata = {
title: "限界開発鯖 - ブログ",
};

const BlogCard = ({ id, title, date, author, authorId }: Metadata): JSX.Element => (
<HStack borderColor="shadowed" borderRightWidth="1px" borderBottomWidth="2px">
<Avatar as={NextLink} flex="0 0 sm" href={`/blog/${id}`} name={title} />
<VStack alignItems="self-start" flex="1 1" p={2} spacing="0.5">
<NextLink href={`/blog/${id}`}>
<Heading as="h3" fontSize="lg">
{title}
</Heading>
</NextLink>
<Flex align="self-end" wrap="wrap" gap={2} w="100%">
<Link href={`https://github.com/${authorId}`}>{author}</Link>
<DateString dateString={date} />
<Spacer />
<Button as={NextLink} href={`/blog/${id}`} size="sm">
記事を読む &rarr;
</Button>
</Flex>
</VStack>
</HStack>
);

export const Blog: NextPage<{ blogs: Metadata[] }> = ({ blogs }) => (
<SimpleGrid gap={4} columns={1}>
{blogs.map((blog) => (
<BlogCard key={blog.id} {...blog} />
))}
</SimpleGrid>
);
7 changes: 7 additions & 0 deletions src/app/blog/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { Blog } from "./blog";
import { getSortedBlogMetadata } from "../lib/blog-fetch";

export default async function Page() {
const blogs = await getSortedBlogMetadata();
return <Blog blogs={blogs} />;
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { expect, it } from "vitest";
import { DateString } from "./date";
import { render } from "../utils/react-test";
import { render } from "../../utils/react-test";

it("renders correctly", () => {
const tree = render(<DateString dateString="2021-01-01" />);
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { expect, it } from "vitest";
import { Footer } from "./footer";
import { render } from "../utils/react-test";
import { render } from "../../utils/react-test";

it("renders correctly", () => {
const tree = render(<Footer />);
Expand Down
10 changes: 5 additions & 5 deletions src/components/footer.tsx → src/app/components/footer.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"use client";

import { Box, Link } from "@chakra-ui/react";

import NextLink from "next/link";
Expand All @@ -8,11 +10,9 @@ export const Footer = (): JSX.Element => {
const year = useContext(yearContext);
return (
<Box as="footer" p={4} textAlign="center" borderColor="shadowed" borderTopWidth="2px">
<NextLink href="/policy" passHref legacyBehavior>
<Link mr={2} color="highlighted" fontStyle="normal">
プライバシーポリシー
</Link>
</NextLink>
<Link as={NextLink} mr={2} color="highlighted" fontStyle="normal" href="/policy">
プライバシーポリシー
</Link>
- (c) {year} Approvers
</Box>
);
Expand Down
43 changes: 43 additions & 0 deletions src/app/components/google-analytics.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
"use client";

import { usePathname, useSearchParams } from "next/navigation";
import Script from "next/script";
import { useEffect } from "react";

export const GOOGLE_ANALYTICS_ID = process.env.NEXT_PUBLIC_GOOGLE_ANALYTICS_ID ?? "";

const notifyShowingPage = (url: string): void => {
(
window as unknown as { gtag(event: "config", id: string, options: { page_path: string }): void }
).gtag("config", GOOGLE_ANALYTICS_ID, {
page_path: url,
});
};

export const GoogleAnalytics = () => {
const pathname = usePathname();
const searchParams = useSearchParams();
useEffect(() => {
notifyShowingPage(`${pathname}?${searchParams}`);
}, [pathname, searchParams]);
return (
<>
<Script
strategy="afterInteractive"
src={`https://www.googletagmanager.com/gtag/js?id=${GOOGLE_ANALYTICS_ID}`}
/>
<Script strategy="afterInteractive" id="send-ga">
{`
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
gtag("js", new Date());
gtag("config", "${GOOGLE_ANALYTICS_ID}", {
page_path: window.location.pathname,
});
`}
</Script>
</>
);
};
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { expect, it } from "vitest";
import { Header } from "./header";
import { render } from "../utils/react-test";
import { render } from "../../utils/react-test";

it("renders correctly", () => {
const tree = render(<Header />);
Expand Down
18 changes: 18 additions & 0 deletions src/app/components/header.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Avatar, Center, Flex, Heading } from "@chakra-ui/react";
import NextLink from "next/link";

export const Header = (): JSX.Element => (
<Center as="header" w="100%" p={4} borderColor="shadowed" borderBottomWidth="2px">
<Flex as={NextLink} align="center" href="/">
<Avatar
w={8}
h={8}
mr={2}
borderRadius="37%"
name="Approversロゴ"
src="/android-chrome-192x192.png"
/>
<Heading as="span">Approvers</Heading>
</Flex>
</Center>
);
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { expect, it } from "vitest";
import { Navigation } from "./navigation";
import { render } from "../utils/react-test";
import { render } from "../../utils/react-test";

it("renders correctly", () => {
const tree = render(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"use client";

import {
Button,
Container,
Expand Down Expand Up @@ -29,11 +31,9 @@ const Links = ({ links }: LinksProps): JSX.Element => (
<VStack>
{links.map(({ name, url }) => (
<Container key={name}>
<NextLink href={url} passHref>
<Button as="a" minW="100%">
{name}
</Button>
</NextLink>
<Button as={NextLink} minW="100%" href={url}>
{name}
</Button>
</Container>
))}
</VStack>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { expect, it } from "vitest";
import { PrevNextLink } from "./prev-next-link";
import { render } from "../utils/react-test";
import { render } from "../../utils/react-test";

it("renders both prev and next correctly", () => {
const tree = render(
Expand Down
Loading

0 comments on commit ec340d6

Please sign in to comment.