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 ( +
+ + +
{children}
+
+ ); +}; + +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';