{"id":16498344,"url":"https://github.com/geekskai/next-admin-demo","last_synced_at":"2025-10-29T05:06:47.486Z","repository":{"id":224231592,"uuid":"762773055","full_name":"geekskai/next-admin-demo","owner":"geekskai","description":"2024年最新的从0～1搭建一个完整而健全的Next.ts项目的架构！","archived":false,"fork":false,"pushed_at":"2024-07-13T14:58:01.000Z","size":306,"stargazers_count":1,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-07-13T16:14:06.403Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/geekskai.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-02-24T16:46:27.000Z","updated_at":"2024-07-13T14:58:05.000Z","dependencies_parsed_at":"2024-07-13T16:06:05.813Z","dependency_job_id":"5082c112-3696-47e0-b34c-1ae8f3bf4d88","html_url":"https://github.com/geekskai/next-admin-demo","commit_stats":null,"previous_names":["geekskai/next-admin-demo"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/geekskai%2Fnext-admin-demo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/geekskai%2Fnext-admin-demo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/geekskai%2Fnext-admin-demo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/geekskai%2Fnext-admin-demo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/geekskai","download_url":"https://codeload.github.com/geekskai/next-admin-demo/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":219860415,"owners_count":16556017,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-11T14:48:11.447Z","updated_at":"2025-10-28T00:30:34.008Z","avatar_url":"https://github.com/geekskai.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 2024年最新的从0～1搭建一个完整而健全的Next.ts项目的架构\n\n## Getting Started\n\n### 请确保node版本在 `v20.8.0` 以上,使用 [pnpm](https://pnpm.io/next/installation) 作为包管理工具\n\n初次运行请先安装项目依赖：\n\n```bash\npnpm install\n```\n\n运行本地开发环境：\n\n```bash\npnpm dev\n```\n\n打包部署,生成`out`文件夹，注意：_需要先确保本地dev是关闭的情况下_ 运行下面的命令:\n\n```bash\npnpm build\n```\n\n如果想预览打包之后的代码，可以在本地起一个服务器：\n\n```bash\ncd ./out\n\nnpx http-server [path] [options]\n```\n\n### feature\n\n⚡ Next.js with App Router support\n\n🔥 Type checking TypeScript\n\n💎 Integrate with Tailwind CSS\n\n✅ Strict Mode for TypeScript and React 18\n\n📏 Linter with ESLint (default NextJS, NextJS Core Web Vitals, Tailwind CSS and Airbnb configuration)\n\n💖 Code Formatter with Prettier\n\n🦊 Husky for Git Hooks\n\n🚫 Lint-staged for running linters on Git staged files\n\n🚓 Lint git commit with Commitlint\n\n📓 Write standard compliant commit messages with Commitizen\n\n🎁 Automatic changelog generation with Semantic Release\n\n🗂 VSCode configuration: Debug, Settings, Tasks and Extensions\n\n🦺 Unit Testing with Jest and React Testing Library\n\n🧪 Integration and E2E Testing with Playwright\n\n🌐 Multi-language (i18n) with next-intl and Crowdin\n\n☂️ Code coverage with Codecov\n\n### 代码规范\n\n#### 代码检查工具 ESLint\n\n使用 create-next-app 创建的 Next.js 项目已经配置好了 ESLint，只需要按照项目需要修改对应配置即可。这里我们加上 prettier 的配置，让 ESLint 和 Prettier 能够更和谐的一起工作。参照[文档](https://prettier.io/docs/en/install#eslint-and-other-linters)\n\n1. eslint-plugin-prettier: 这是一个 ESLint 插件，将 Prettier 作为 ESLint 规则运行。这意味着你可以使用 ESLint 运行 Prettier 的格式化功能。当代码不符合 Prettier 的格式化规则时，eslint-plugin-prettier 会报告格式化错误。这样做的好处是可以在一个命令中同时运行 ESLint 的代码质量检查和 Prettier 的代码格式化，简化了开发流程。\n2. eslint-config-prettier: 这是一个 ESLint 配置，用于关闭所有不必要的或可能与 Prettier 冲突的 ESLint 规则。当同时使用 ESLint 和 Prettier 时，一些 ESLint 规则可能与 Prettier 的格式化规则冲突，导致不一致的代码风格。通过使用 eslint-config-prettier，可以确保 ESLint 的规则不会干扰 Prettier 的代码格式化，从而保持代码风格的一致性。\n\n```bash\npnpm add --save-dev eslint-plugin-prettier eslint-config-prettier eslint-plugin-react-hooks\n```\n\n`.eslintrc.json`\n\n```json\n{\n  \"extends\": [\n    \"next/core-web-vitals\",\n    \"plugin:prettier/recommended\",\n    \"plugin:react-hooks/recommended\"\n  ],\n  \"plugins\": [\n    \"prettier\", // 确保\"prettier\"插件已被添加\n    \"react-hooks\"\n  ],\n  \"rules\": {\n    // 可以在这里覆盖特定的规则设置\n    \"prettier/prettier\": [\"error\", { \"endOfLine\": \"auto\" }], // 或者使用\"warn\"，这样Prettier的错误将以警告的形式展示 hooks 的规范\n    \"react-hooks/rules-of-hooks\": \"error\",\n    \"react-hooks/exhaustive-deps\": \"warn\"\n  }\n}\n```\n\n\"extends\": [\"plugin:prettier/recommended\"]做了三件事：\n\n1. 启用 `eslint-plugin-prettier`：这实际上将 `Prettier` 作为 `ESLint` 规则运行。这意味着任何 `Prettier` 发现的格式问题都会作为 `ESLint` 问题报告出来。\n2. 添加 `prettier` 到 `ESLint` 的配置中：这确保了 `Prettier` 的规则优先级最高，有助于解决其他 `ESLint` 规则可能与 `Prettier` 冲突的问题。\n3. 禁用与 `Prettier` 冲突的 `ESLint` 规则：通过内部使用 `eslint-config-prettier`，它自动关闭所有不必要的或可能与 `Prettier` 冲突的 `ESLint` 规则。\n\n#### 代码风格工具 Prettier\n\n```bash\npnpm add -D prettier prettier-plugin-organize-imports prettier-plugin-tailwindcss\n\n```\n\n我们使用了 `Tailwind CSS` 推荐额外安装 `prettier-plugin-tailwindcss`，可以帮忙自动排序 `className`。\n并且我们额外安装可以帮助排序 `import` 的插件：`prettier-plugin-organize-imports`\n\n接着在 `.prettierrc.json` 文件中配置如下：\n\n```json\n{\n  \"plugins\": [\n    \"prettier-plugin-organize-imports\",\n    \"prettier-plugin-tailwindcss\"\n  ],\n  \"tailwindFunctions\": [\"classNames\"],\n  \"singleQuote\": true\n}\n```\n\n### 同步编辑器设置和扩展\n\n在项目中加上 `.vscode` 文件夹，配置编辑器的扩展和自动校验和修复的设置，让其他同学接入项目也能快速上手和使用相同的配置、扩展。\n\n`.vscode/extensions.json`\n\n```json\n{\n  \"recommendations\": [\n    // Linting / Formatting\n    \"esbenp.prettier-vscode\",\n    \"dbaeumer.vscode-eslint\",\n    \"bradlc.vscode-tailwindcss\"\n  ]\n}\n```\n\n`.vscode/settings.json`\n\n```json\n{\n  // 默认情况下，对所有语言使用 Prettier 进行格式化\n  \"editor.defaultFormatter\": \"esbenp.prettier-vscode\",\n  \"editor.formatOnSave\": true,\n  \"editor.codeActionsOnSave\": {\n    \"source.fixAll.eslint\": true\n  },\n  // 使用 Prettier 格式化 JavaScript，覆盖 VSCode 默认设置。\n  \"[javascript]\": {\n    \"editor.defaultFormatter\": \"esbenp.prettier-vscode\"\n  },\n  // 使用 ESLint 进行代码校验。\n  \"eslint.validate\": [\n    \"javascript\",\n    \"javascriptreact\",\n    \"typescript\",\n    \"typescriptreact\"\n  ],\n  // 启用文件嵌套。\n  \"explorer.fileNesting.enabled\": true,\n  \"explorer.fileNesting.patterns\": {\n    \"*.ts\": \"$(capture).test.ts, $(capture).test.tsx\",\n    \"*.tsx\": \"$(capture).test.ts, $(capture).test.tsx\"\n  },\n  \"[typescriptreact]\": {\n    \"editor.defaultFormatter\": \"esbenp.prettier-vscode\"\n  }\n}\n```\n\n### git规范\n\nGit 有很多的 `hooks`, 让我们在不同的阶段,对代码进行不同的操作,控制提交到仓库的代码的规范性,和准确性, 以下只是几个常用的钩子\n\n#### 提交的代码规范 Husky\n\n安装husky\n\n```bash\npnpm add --save-dev husky\n```\n\n初始化 `Husky`，通过`git`钩子函数`pre-commit`判断提交的代码是否符合规范\n\n```bash\npnpm exec husky init\n```\n\n#### 提交的信息规范 commitlint\n\n通过钩子函数`commit-msg`,判断 `commit` 信息是否符合规范\n\n```bash\npnpm add -D @commitlint/config-conventional @commitlint/cli\n```\n\n可以在 `package.json` 内创建一个脚本：\n\n```bash\nnpm pkg set scripts.commitlint=\"commitlint --edit\"\necho \"npm run commitlint \\${1}\" \u003e .husky/commit-msg\n```\n\n注意：如果在windows下面出现报错，请删除`commit-msg`文件，然后重新手动创建，将代码`npm run commitlint ${1}`复制进去\n\n或者使用下面这个方式也行：\n\n```bash\necho \"npx --no -- commitlint --edit \\$1\" \u003e .husky/commit-msg\n```\n\n在根目录下新建`commitlint.config.js`文件，写入如下代码：\n\n```js\nmodule.exports = {\n  extends: [\"@commitlint/config-conventional\"],\n  rules: {\n    \"subject-case\": [0],\n    \"type-enum\": [\n      2,\n      \"always\",\n      [\n        \"feat\", // 新功能 feature\n        \"fix\", // 修复 bug\n        \"docs\", // 更新文档注释\n        \"style\", // 美观化代码，修改代码格式(非CSS样式修改,不影响代码运行的变动)\n        \"refactor\", // 重构代码(既不增加新功能，也不是修复bug)\n        \"perf\", // 修改提高性能的代码\n        \"test\", // 增加测试用例\n        \"chore\", // 构建过程或辅助工具的变动,修改构建流程,依赖管理\n        \"revert\", // 回退代码\n        \"release\", // 发布新版本\n        \"build\", // 打包代码\n      ],\n    ],\n  },\n};\n```\n\n特别注意提交信息的格式，不符合规范的提交信息将无法提交, 每种提交类型(`chore: `)的冒号之后必须要有空格，例如：\n\n```bash\ngit commit -m \"chore: Update build process\"\n```\n\n### lint-staged\n\n使用 `husky` 和 `lin-staged` 可以在 `Git` 提交代码时对提交的部分进行 `ESLint` 的代码校验和 `prettier` 的格式化，避免有些新同事编辑器中没有装对应插件和开启自动修复。安装配置也十分简单。\n\n```bash\npnpm add --save-dev lint-staged\n```\n\n修改`.husky/pre-commit` 文件中的内容为：\n\n```bash\nnpx lint-staged\n```\n\n新建`.lintstagedrc.js`的配置如下\n\n```js\nconst path = require(\"path\");\n\nconst buildEslintCommand = (filenames) =\u003e\n  `next lint --fix --file ${filenames\n    .map((file) =\u003e path.relative(process.cwd(), file))\n    .join(\" --file \")}`;\n\nmodule.exports = {\n  \"*.{js,jsx,ts,tsx}\": [buildEslintCommand], // 这些格式的文件在提交时交给 ESLint 校验\n  \"**/*.{js,jsx,tsx,ts,less,md,json}\": [\"prettier --write\"], // 这些格式的文件在提交时让 prettier 格式化\n};\n```\n\n❌ 特别注意提交信息的格式，不符合规范的提交信息将无法提交, 每种提交类型的冒号之后必须要有英文的空格(`fix: `)，例如一个合格的提交：\n\n✅ `git commit -m \"chore: Update build process\"`\n\n### Release It! 🚀\n\n```bash\npnpm install -D release-it @release-it/conventional-changelog\n\n```\n\n安装完成之后，将 `release` 的配置添加到 `package.json`的`scripts`中:\n\n```json\n{\n  \"scripts\": {\n    \"dev\": \"next dev\",\n    \"build\": \"next build\",\n    \"start\": \"next start\",\n    \"release\": \"release-it\"\n  }\n}\n```\n\n使用`@release-it/conventional-changelog`可根据提交信息获取建议的 bump,此外，它还可以生成常规的变更日志，并可以选择在此过程中更新 `CHANGELOG.md` 文件。\n\n添加`.release-it.json`配置：\n\n```json\n{\n  \"hooks\": {\n    \"after:bump\": \"echo 更新版本成功! 🚀\"\n  },\n  \"github\": {\n    \"release\": false,\n    \"releaseName\": \"Release ${version}\",\n    \"releaseNotes\": null,\n    \"autoGenerate\": false,\n    \"preRelease\": false,\n    \"draft\": false,\n    \"tokenRef\": \"GITLAB_TOKEN\",\n    \"assets\": null,\n    \"host\": null,\n    \"timeout\": 0,\n    \"proxy\": null,\n    \"skipChecks\": false,\n    \"web\": false,\n    \"comments\": {\n      \"submit\": false,\n      \"issue\": \":rocket: _This issue has been resolved in v${version}. See [${releaseName}](${releaseUrl}) for release notes._\",\n      \"pr\": \":rocket: _This pull request is included in v${version}. See [${releaseName}](${releaseUrl}) for release notes._\"\n    }\n  },\n  \"gitlab\": {\n    \"release\": false,\n    \"releaseName\": \"Release ${version}\",\n    \"releaseNotes\": null,\n    \"milestones\": [],\n    \"tokenRef\": \"GITLAB_TOKEN\",\n    \"tokenHeader\": \"Private-Token\",\n    \"certificateAuthorityFile\": null,\n    \"assets\": null,\n    \"origin\": null,\n    \"skipChecks\": false\n  },\n  \"git\": {\n    \"changelog\": \"git log --pretty=format:\\\"* %s (%h)\\\" ${from}...${to}\",\n    \"requireCleanWorkingDir\": true,\n    \"requireBranch\": false,\n    \"requireUpstream\": true,\n    \"requireCommits\": false,\n    \"requireCommitsFail\": true,\n    \"commitsPath\": \"\",\n    \"addUntrackedFiles\": false,\n    \"commit\": true,\n    \"commitMessage\": \"release: Release ${version}\",\n    \"commitArgs\": [],\n    \"tag\": true,\n    \"tagExclude\": null,\n    \"tagName\": null,\n    \"tagMatch\": null,\n    \"getLatestTagFromAllRefs\": false,\n    \"tagAnnotation\": \"Release ${version}\",\n    \"tagArgs\": [],\n    \"push\": true,\n    \"pushArgs\": [\"--follow-tags\"],\n    \"pushRepo\": \"\"\n  },\n  \"npm\": {\n    \"publish\": false,\n    \"publishPath\": \".\",\n    \"publishArgs\": [],\n    \"tag\": null,\n    \"otp\": null,\n    \"ignoreVersion\": false,\n    \"allowSameVersion\": false,\n    \"versionArgs\": [],\n    \"skipChecks\": false,\n    \"timeout\": 10\n  },\n  \"plugins\": {\n    \"@release-it/conventional-changelog\": {\n      \"infile\": \"CHANGELOG.md\",\n      \"ignoreRecommendedBump\": true,\n      \"strictSemVer\": true,\n      \"preset\": {\n        \"name\": \"conventionalcommits\",\n        \"types\": [\n          {\n            \"type\": \"feat\",\n            \"section\": \"✨添加新功能\"\n          },\n          {\n            \"type\": \"fix\",\n            \"section\": \"🐛修复bug\"\n          },\n          {\n            \"type\": \"docs\",\n            \"section\": \"📚更新文档\"\n          },\n          {\n            \"type\": \"chore\",\n            \"section\": \"🔧修改配置文件\"\n          },\n          {\n            \"type\": \"style\",\n            \"hidden\": \"true\",\n            \"section\": \"🎨修改样式\"\n          },\n          {\n            \"type\": \"test\",\n            \"section\": \"✅测试代码\",\n            \"hidden\": true\n          },\n          {\n            \"type\": \"refactor\",\n            \"section\": \"🔨重构代码\"\n          },\n          {\n            \"type\": \"perf\",\n            \"section\": \"⚡优化性能\",\n            \"hidden\": true\n          },\n          {\n            \"type\": \"release\",\n            \"section\": \"📌发布版本\",\n            \"hidden\": true\n          }\n        ]\n      }\n    }\n  }\n}\n```\n\n💥 先提交本地所有更改过的代码之后，执行：\n\n```bash\npnpm run release\n```\n\n## 添加测试\n\n```bash\npnpm install -D jest jest-environment-jsdom @testing-library/react @testing-library/jest-dom ts-node @types/jest jest-fail-on-console\n```\n\n通过运行以下命令生成基本的 Jest 配置文件：\n\n```bash\npnpm create jest@latest\n```\n\n在`jest.config.ts`中：\n\n```js\nimport type { Config } from \"jest\";\nimport nextJest from \"next/jest\";\n\nconst createJestConfig = nextJest({\n  // Provide the path to your Next.js app to load `next.config.js` and `.env` files in your test environment\n  dir: \"./\",\n});\n\n// Add any custom config to be passed to Jest\nconst config: Config = {\n  moduleNameMapper: {\n    // Handle module aliases (this will be automatically configured for you soon)\n    \"^@/(.*)$\": \"\u003crootDir\u003e/src/$1\",\n    \"^@/public/(.*)$\": \"\u003crootDir\u003e/public/$1\",\n  },\n  setupFilesAfterEnv: [\"\u003crootDir\u003e/jest.setup.ts\"],\n  clearMocks: true,\n  collectCoverage: true,\n  // The directory where Jest should output its coverage files\n  coverageDirectory: \"coverage\",\n  collectCoverageFrom: [\n    \"./src/**/*.{js,jsx,ts,tsx}\",\n    \"!./src/**/_*.{js,jsx,ts,tsx}\",\n    \"!./src/**/*.stories.{js,jsx,ts,tsx}\",\n    \"!**/*.d.ts\",\n    \"!**/node_modules/**\",\n  ],\n  coverageThreshold: {\n    global: {\n      branches: 0,\n      functions: 0,\n      lines: 0,\n      statements: 0,\n    },\n  },\n  testEnvironment: \"jest-environment-jsdom\",\n  testPathIgnorePatterns: [\"\u003crootDir\u003e/node_modules/\"],\n};\n\n// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async\nexport default createJestConfig(config);\n\n```\n\n在`jest.setup.ts`中：\n\n```js\nimport \"@testing-library/jest-dom\";\n\nimport failOnConsole from \"jest-fail-on-console\";\n\nfailOnConsole();\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgeekskai%2Fnext-admin-demo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgeekskai%2Fnext-admin-demo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgeekskai%2Fnext-admin-demo/lists"}