diff --git a/.babelrc b/.babelrc
new file mode 100644
index 0000000..04b7e1d
--- /dev/null
+++ b/.babelrc
@@ -0,0 +1,12 @@
+{
+ "presets": ["next/babel"],
+ "plugins": [
+ [
+ "import",
+ {
+ "libraryName": "antd",
+ "style": true
+ }
+ ]
+ ]
+}
diff --git a/.env b/.env
new file mode 100644
index 0000000..1fe569f
--- /dev/null
+++ b/.env
@@ -0,0 +1,2 @@
+NODE_ENV=development
+CLIENT_BASE_API=/api
\ No newline at end of file
diff --git a/.env.pre b/.env.pre
new file mode 100644
index 0000000..2132d13
--- /dev/null
+++ b/.env.pre
@@ -0,0 +1,3 @@
+NODE_ENV=production
+CLIENT_BASE_API=/api
+TTT=pre
\ No newline at end of file
diff --git a/.env.prod b/.env.prod
new file mode 100644
index 0000000..6c80a77
--- /dev/null
+++ b/.env.prod
@@ -0,0 +1,3 @@
+NODE_ENV=production
+CLIENT_BASE_API=/api
+TTT=production
\ No newline at end of file
diff --git a/.env.release b/.env.release
new file mode 100644
index 0000000..45869d1
--- /dev/null
+++ b/.env.release
@@ -0,0 +1,3 @@
+NODE_ENV=production
+CLIENT_BASE_API=/api
+TTT=release
\ No newline at end of file
diff --git a/.env.test b/.env.test
new file mode 100644
index 0000000..c66c594
--- /dev/null
+++ b/.env.test
@@ -0,0 +1,3 @@
+NODE_ENV=production
+CLIENT_BASE_API=/api
+TTT=test
\ No newline at end of file
diff --git a/.eslintrc.js b/.eslintrc.js
new file mode 100644
index 0000000..61dde3a
--- /dev/null
+++ b/.eslintrc.js
@@ -0,0 +1,4 @@
+module.exports = {
+ extends: [],
+ rules: {},
+};
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..1437c53
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,34 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.js
+
+# testing
+/coverage
+
+# next.js
+/.next/
+/out/
+
+# production
+/build
+
+# misc
+.DS_Store
+*.pem
+
+# debug
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# local env files
+.env.local
+.env.development.local
+.env.test.local
+.env.production.local
+
+# vercel
+.vercel
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..37ad7a2
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,40 @@
+{
+ "editor.codeActionsOnSave": {
+ "source.fixAll.eslint": true
+ },
+ "eslint.validate": [
+ "javascript",
+ "react",
+ "typescript",
+ "typescriptreact",
+ "vue"
+ ],
+ "editor.formatOnSave": true,
+ "[typescriptreact]": {
+ "editor.defaultFormatter": null
+ },
+ "[javascript]": {
+ "editor.defaultFormatter": null
+ },
+ "[typescript]": {
+ "editor.defaultFormatter": null
+ },
+ "[javascriptreact]": {
+ "editor.defaultFormatter": null
+ },
+ "[json]": {
+ "editor.defaultFormatter": "esbenp.prettier-vscode"
+ },
+ "[less]": {
+ "editor.defaultFormatter": "esbenp.prettier-vscode"
+ },
+ "[scss]": {
+ "editor.defaultFormatter": "esbenp.prettier-vscode"
+ },
+ "[css]": {
+ "editor.defaultFormatter": "esbenp.prettier-vscode"
+ },
+ "[jsonc]": {
+ "editor.defaultFormatter": "esbenp.prettier-vscode"
+ }
+}
diff --git a/README.md b/README.md
index 161ddb4..d539424 100644
--- a/README.md
+++ b/README.md
@@ -1,34 +1 @@
-## 目前已有脚手架列表
-
-| 名称 | 说明 | 技术栈 |
-| ------- | --------------------------- | --------------------- |
-| nextJs | 基于 React 的服务端渲染方案 | nextJs + axios + antd |
-| ReactJs | 基于 React 的业务型脚手架 | umiJs + axios + antd |
-| TaroJs | 基于 React 的多端适配方案 | TaroJs 全家桶 |
-| Vue | 基于 Vue 的业务型脚手架 | vueJs 全家桶 |
-| Gulp | 基于 Gulp 的清凉型脚手架 | -- |
-
-## 快速上手
-
-### 1. 安装相关依赖
-
-```js
-// 推荐
-yarn global add @nicecode/cli
-
-// or
-// npm install @nicecode/cli -g
-```
-
-### 2. 运行命令
-
-```js
-// 查看脚手架版本号,是否安装成功
-nice - V
-```
-
-### 3. 创建项目
-
-```js
-nice create ${项目名称}
-```
+# nextjs-template
\ No newline at end of file
diff --git a/next-env.d.ts b/next-env.d.ts
new file mode 100644
index 0000000..7b7aa2c
--- /dev/null
+++ b/next-env.d.ts
@@ -0,0 +1,2 @@
+///
+///
diff --git a/next-less.config.js b/next-less.config.js
new file mode 100644
index 0000000..92ef1ea
--- /dev/null
+++ b/next-less.config.js
@@ -0,0 +1,67 @@
+const cssLoaderConfig = require('@zeit/next-css/css-loader-config');
+
+module.exports = (nextConfig = {}) => {
+ return Object.assign({}, nextConfig, {
+ webpack(config, options) {
+ if (!options.defaultLoaders) {
+ throw new Error(
+ 'This plugin is not compatible with Next.js versions below 5.0.0 https://err.sh/next-plugins/upgrade',
+ );
+ }
+
+ const { dev, isServer } = options;
+ const {
+ cssModules,
+ cssLoaderOptions,
+ postcssLoaderOptions,
+ lessLoaderOptions = {},
+ } = nextConfig;
+
+ options.defaultLoaders.less = cssLoaderConfig(config, {
+ extensions: ['less'],
+ cssModules,
+ cssLoaderOptions,
+ postcssLoaderOptions,
+ dev,
+ isServer,
+ loaders: [
+ {
+ loader: 'less-loader',
+ options: lessLoaderOptions,
+ },
+ ],
+ });
+
+ config.module.rules.push({
+ test: /\.less$/,
+ exclude: /node_modules/,
+ use: options.defaultLoaders.less,
+ });
+
+ // 我们禁用了antd的cssModules
+ config.module.rules.push({
+ test: /\.less$/,
+ include: /node_modules/,
+ use: cssLoaderConfig(config, {
+ extensions: ['less'],
+ cssModules: false,
+ cssLoaderOptions: {},
+ dev,
+ isServer,
+ loaders: [
+ {
+ loader: 'less-loader',
+ options: lessLoaderOptions,
+ },
+ ],
+ }),
+ });
+
+ if (typeof nextConfig.webpack === 'function') {
+ return nextConfig.webpack(config, options);
+ }
+
+ return config;
+ },
+ });
+};
diff --git a/next.config.js b/next.config.js
new file mode 100644
index 0000000..14b6bde
--- /dev/null
+++ b/next.config.js
@@ -0,0 +1,61 @@
+const withCSS = require('@zeit/next-css');
+const withLessExcludeAntd = require('./next-less.config');
+const lessToJS = require('less-vars-to-js');
+const fs = require('fs');
+const path = require('path');
+
+// Where your antd-custom.less file lives
+const modifyVars = lessToJS(
+ fs.readFileSync(
+ path.resolve(__dirname, './src/styles/antd-custom.less'),
+ 'utf8',
+ ),
+);
+
+require('dotenv').config();
+
+module.exports = withLessExcludeAntd(
+ withCSS({
+ cssModules: true,
+ cssLoaderOptions: {
+ importLoaders: 1,
+ localIdentName: '[local]___[hash:base64:5]',
+ },
+ lessLoaderOptions: {
+ javascriptEnabled: true,
+ modifyVars, // make your antd custom effective
+ },
+ webpack: (config, { isServer }) => {
+ if (isServer) {
+ const antStyles = /antd\/.*?\/style.*?/;
+ const origExternals = [...config.externals];
+ config.externals = [
+ (context, request, callback) => {
+ if (request.match(antStyles)) return callback();
+ if (typeof origExternals[0] === 'function') {
+ origExternals[0](context, request, callback);
+ } else {
+ callback();
+ }
+ },
+ ...(typeof origExternals[0] === 'function' ? [] : origExternals),
+ ];
+
+ config.module.rules.unshift({
+ test: antStyles,
+ use: 'null-loader',
+ });
+ }
+ // 别名
+ config.resolve.alias['@'] = path.resolve(__dirname, './src');
+ config.resolve.alias['@static'] = path.resolve(__dirname, './static');
+ return config;
+ },
+ env: {
+ CLIENT_BASE_API: process.env.CLIENT_BASE_API,
+ },
+ // 用上面的方式使用a[b]的取值取不到
+ publicRuntimeConfig: {
+ },
+ }),
+);
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..dbd98ca
--- /dev/null
+++ b/package.json
@@ -0,0 +1,58 @@
+{
+ "name": "nextjs-template",
+ "version": "1.0.0",
+ "private": true,
+ "scripts": {
+ "dev": "next dev",
+ "build": "dotenv -e .env next build",
+ "build:test": "dotenv -e .env.test next build",
+ "build:release": "dotenv -e .env.release next build",
+ "build:pre": "dotenv -e .env.pre next build",
+ "build:production": "dotenv -e .env.prod next build",
+ "start": "next start",
+ "lint": "eslint 'src/**/*.{js,jsx,tsx,ts}'",
+ "lint:fix": "eslint 'src/**/*.{js,jsx,tsx,ts}' --fix",
+ "prettier": "prettier --write 'src/**/*.{less,css,md,json}'"
+ },
+ "dependencies": {
+ "antd": "^100.0.1",
+ "axios": "^0.21.1",
+ "next": "10.0.4",
+ "normalize.css": "^8.0.1",
+ "react": "17.0.1",
+ "react-dom": "17.0.1"
+ },
+ "devDependencies": {
+ "@types/node": "^14.14.19",
+ "@types/react": "^17.0.0",
+ "@types/react-dom": "^17.0.0",
+ "@types/styled-components": "^5.1.7",
+ "@zeit/next-css": "^1.0.1",
+ "@zeit/next-less": "^1.0.1",
+ "babel-plugin-import": "^1.13.3",
+ "css-loader": "^5.0.1",
+ "dotenv": "^8.2.0",
+ "dotenv-cli": "^4.0.0",
+ "eslint": "^7.32.0",
+ "less": "3.13.1",
+ "less-vars-to-js": "^1.3.0",
+ "lint-staged": "^11.1.2",
+ "null-loader": "^4.0.1",
+ "prettier": "^2.3.2",
+ "typescript": "^4.4.2",
+ "yorkie": "^2.0.0"
+ },
+ "gitHooks": {
+ "pre-commit": "tsc --noEmit && lint-staged"
+ },
+ "lint-staged": {
+ "*.{js,jsx,ts,tsx}": [
+ "npm run lint:fix",
+ "git add ."
+ ],
+ "*.{less,css,md,json}": [
+ "npm run prettier",
+ "git add ."
+ ]
+ }
+}
diff --git a/public/favicon.ico b/public/favicon.ico
new file mode 100644
index 0000000..fb0271b
Binary files /dev/null and b/public/favicon.ico differ
diff --git a/src/assets/data/code.json b/src/assets/data/code.json
new file mode 100644
index 0000000..e69de29
diff --git a/src/components/Demo/index.less b/src/components/Demo/index.less
new file mode 100644
index 0000000..0c4bad1
--- /dev/null
+++ b/src/components/Demo/index.less
@@ -0,0 +1,3 @@
+.container {
+ width: 500px;
+}
diff --git a/src/components/Demo/index.tsx b/src/components/Demo/index.tsx
new file mode 100644
index 0000000..e72bbcd
--- /dev/null
+++ b/src/components/Demo/index.tsx
@@ -0,0 +1,15 @@
+import React from 'react';
+import { Button } from 'antd';
+import styles from './index.less';
+
+const Demo: React.FunctionComponent = () => {
+ return (
+
+
title
+
demo
+
+
+ );
+};
+
+export default Demo;
diff --git a/src/components/PageHeader/index.tsx b/src/components/PageHeader/index.tsx
new file mode 100644
index 0000000..2a054d3
--- /dev/null
+++ b/src/components/PageHeader/index.tsx
@@ -0,0 +1,22 @@
+import React from 'react';
+import Head from 'next/head';
+
+interface PageHeaderProps {
+ title?: string;
+}
+
+const PageHeader: React.FC = ({ title = 'Uni-Ubi' }) => {
+ return (
+
+
+
{title}
+
+
+
+ );
+};
+
+export default PageHeader;
diff --git a/src/interfaces/base.ts b/src/interfaces/base.ts
new file mode 100644
index 0000000..d4e6472
--- /dev/null
+++ b/src/interfaces/base.ts
@@ -0,0 +1,8 @@
+export interface IPagination {
+ total: number;
+ size: number;
+ index: number;
+ length: number;
+ beginIndex: number;
+ endIndex: number;
+}
diff --git a/src/layouts/BasicLayout/index.tsx b/src/layouts/BasicLayout/index.tsx
new file mode 100644
index 0000000..50abbc5
--- /dev/null
+++ b/src/layouts/BasicLayout/index.tsx
@@ -0,0 +1,14 @@
+import React from 'react';
+import PageHeader from '@/components/PageHeader';
+
+const BasicLayout: React.FC = ({ children }) => {
+ return (
+
+ );
+};
+
+export default BasicLayout;
diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx
new file mode 100644
index 0000000..41fa471
--- /dev/null
+++ b/src/pages/_app.tsx
@@ -0,0 +1,7 @@
+import 'normalize.css/normalize.css';
+
+function MyApp({ Component, pageProps }) {
+ return ;
+}
+
+export default MyApp;
diff --git a/src/pages/api/hello.ts b/src/pages/api/hello.ts
new file mode 100644
index 0000000..4d1188a
--- /dev/null
+++ b/src/pages/api/hello.ts
@@ -0,0 +1,6 @@
+// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
+
+export default (_, res) => {
+ res.statusCode = 200;
+ res.json({ name: 'John Doe' });
+};
diff --git a/src/pages/index.tsx b/src/pages/index.tsx
new file mode 100644
index 0000000..769813d
--- /dev/null
+++ b/src/pages/index.tsx
@@ -0,0 +1,11 @@
+import BasicLayout from '@/layouts/BasicLayout';
+import Demo from '@/components/Demo';
+
+export default function Home() {
+ return (
+
+ 标题
+
+
+ );
+}
diff --git a/src/services/index.ts b/src/services/index.ts
new file mode 100644
index 0000000..da93787
--- /dev/null
+++ b/src/services/index.ts
@@ -0,0 +1,16 @@
+import clientRequest from '@/utils/clientRequest';
+
+export interface HelloWordParams {
+ pageIndex?: number;
+ pageSize?: number;
+ keyword: string;
+}
+
+// 获取应用列表
+export const helloWordApi = (params: HelloWordParams): Promise =>{
+ return clientRequest({
+ url: '/test/helloWord',
+ params,
+ });
+}
+
diff --git a/src/styles/antd-custom.less b/src/styles/antd-custom.less
new file mode 100644
index 0000000..e69de29
diff --git a/src/styles/var.less b/src/styles/var.less
new file mode 100644
index 0000000..69f69b7
--- /dev/null
+++ b/src/styles/var.less
@@ -0,0 +1,90 @@
+// 颜色
+@S1: #25282a;
+@S2: #1c21b8;
+@S3: #2228e0;
+@S4: #4046ff;
+@S5: #9ca8ff;
+@S6: #c9d2ff;
+@M1: #000000;
+@M2: #4a4a4a;
+@M3: #7c7c7c;
+@M4: #959595;
+@M5: #c7c7c7;
+@M6: #e0e0e0;
+@M7: #f2f2f2;
+@M8: #f9f9f9;
+@M9: #ffffff;
+@D1: #fac105;
+@D2: #ffab24;
+@D3: #ff6952;
+@D4: #ff3c73;
+@D5: #ee62d5;
+@D6: #8475ff;
+@D7: #4f73ff;
+@D8: #148aff;
+@D9: #0cc0c9;
+@D10: #0cc991;
+@D11: #83d615;
+@D1-1: #fef8e5;
+@D2-1: #fff6e9;
+@D3-1: #fff0ed;
+@D4-1: #ffebf1;
+@D5-1: #fdeffa;
+@D6-1: #f2f1ff;
+@D7-1: #edf1ff;
+@D8-1: #e7f3ff;
+@D9-1: #e6f8f9;
+@D10-1: #e6f9f3;
+@D11-1: #f2fae7;
+@F-info: #4766ff;
+@F-success: #46cf84;
+@F-warning: #ffa42e;
+@F-red: #fa4646;
+
+/* 字体 */
+@Fs-1: 12px;
+@Fs-2: 14px;
+@Fs-3: 16px;
+@Fs-4: 18px;
+@Fs-5: 20px;
+@Fs-6: 22px;
+@Fs-7: 24px;
+@Fs-8: 28px;
+@Fs-9: 32px;
+
+/* 行高 */
+@Lh-1: 20px;
+@Lh-2: 22px;
+@Lh-3: 24px;
+@Lh-4: 26px;
+@Lh-5: 28px;
+@Lh-6: 30px;
+@Lh-7: 32px;
+@Lh-8: 36px;
+@Lh-9: 42px;
+
+// 间距
+@Sp-1: 2px;
+@Sp-2: 4px;
+@Sp-3: 8px;
+@Sp-4: 10px;
+@Sp-5: 12px;
+@Sp-6: 16px;
+@Sp-7: 20px;
+@Sp-8: 24px;
+@Sp-9: 30px;
+@Sp-10: 32px;
+@Sp-11: 40px;
+
+// 阴影
+@Sh-1: 0 0 8px 0 rgba(0, 0, 0, 0.05);
+@Sh-2: 0 2px 8px 0 rgba(0, 0, 0, 0.1);
+@Sh-3: 0 0 12px 0 rgba(0, 0, 0, 0.1);
+@Sh-4: -4px 0 20px 0 rgba(0, 0, 0, 0.1);
+@Sh-5: 0 2px 20px 0 rgba(0, 0, 0, 0.3);
+
+// 圆角
+@Ra-1: 2px;
+@Ra-2: 3px;
+@Ra-3: 6px;
+@Ra-4: 10px;
diff --git a/src/utils/clientRequest.ts b/src/utils/clientRequest.ts
new file mode 100644
index 0000000..7173c5c
--- /dev/null
+++ b/src/utils/clientRequest.ts
@@ -0,0 +1,50 @@
+import axios from 'axios';
+import { message } from 'antd';
+import { IPagination } from '@/interfaces/base';
+import codeMsg from '@/assets/data/code.json';
+
+export interface BaseResponse {
+ code: string;
+ msg: string;
+ memo?: string;
+ data: any;
+ page?: IPagination;
+ result: number;
+ success: boolean;
+}
+
+const DEFAULT_TIP_MESSAGE = '请求失败,请刷新重试';
+
+const handleError = (data: BaseResponse) => {
+ const msg = codeMsg[data.code] || data.msg || DEFAULT_TIP_MESSAGE;
+ message.error(msg);
+};
+
+// create an axios instance
+const service = axios.create({
+ baseURL: process.env.CLIENT_BASE_API, // api的base_url
+ method: 'GET',
+ // timeout: 5000, // request timeout
+});
+// request interceptor
+service.interceptors.request.use(
+ (config) => config,
+ (error) => Promise.reject(error),
+);
+
+// response interceptor
+service.interceptors.response.use(
+ (response) => {
+ const res = response.data;
+ if (!res.success) {
+ handleError(res);
+ }
+ return res;
+ },
+ (error) => {
+ handleError(error);
+ return Promise.reject(error);
+ },
+);
+
+export default service;
diff --git a/src/utils/serverRequest.ts b/src/utils/serverRequest.ts
new file mode 100644
index 0000000..58fe1c0
--- /dev/null
+++ b/src/utils/serverRequest.ts
@@ -0,0 +1,21 @@
+import axios from 'axios';
+
+// create an axios instance
+const service = axios.create({
+ timeout: 5000, // request timeout
+ withCredentials: true,
+});
+
+// request interceptor
+service.interceptors.request.use(
+ (config) => config,
+ (error) => Promise.reject(error),
+);
+
+// response interceptor
+service.interceptors.response.use(
+ (response) => response,
+ (error) => Promise.reject(error),
+);
+
+export default service;
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 0000000..d6f4863
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,24 @@
+{
+ "compilerOptions": {
+ "baseUrl": ".",
+ "paths": {
+ "@/*": ["src/*"],
+ "@static/*": ["static/*"]
+ },
+ "target": "es5",
+ "lib": ["dom", "dom.iterable", "esnext"],
+ "allowJs": true,
+ "skipLibCheck": true,
+ "strict": false,
+ "forceConsistentCasingInFileNames": true,
+ "noEmit": true,
+ "esModuleInterop": true,
+ "module": "esnext",
+ "moduleResolution": "node",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "jsx": "preserve"
+ },
+ "exclude": ["node_modules"],
+ "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"]
+}
diff --git a/typings.d.ts b/typings.d.ts
new file mode 100644
index 0000000..5681185
--- /dev/null
+++ b/typings.d.ts
@@ -0,0 +1,3 @@
+declare module '*.png';
+declare module '*.css';
+declare module '*.less';