mirror of
https://github.com/Aviortheking/next-template.git
synced 2025-04-22 10:42:10 +00:00
Updated
Signed-off-by: Avior <florian.bouillon@delta-wings.net>
This commit is contained in:
parent
21eba2d473
commit
54d8217133
@ -6,3 +6,8 @@ indent_size = 4
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.md]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
trim_trailing_whitespace = false
|
||||
|
39
.eslintrc.js
39
.eslintrc.js
@ -7,7 +7,7 @@ module.exports = {
|
||||
extends: [
|
||||
"eslint:recommended",
|
||||
"plugin:react/recommended",
|
||||
"plugin:@typescript-eslint/eslint-recommended"
|
||||
"plugin:@typescript-eslint/recommended"
|
||||
],
|
||||
globals: {
|
||||
Atomics: "readonly",
|
||||
@ -42,10 +42,17 @@ module.exports = {
|
||||
],
|
||||
|
||||
quotes: "off",
|
||||
"@typescript-eslint/quotes": ["error", "single", { avoidEscape: true }],
|
||||
"@typescript-eslint/quotes": [
|
||||
"error",
|
||||
"single",
|
||||
{ avoidEscape: true }
|
||||
],
|
||||
|
||||
semi: "off",
|
||||
"@typescript-eslint/semi": "error",
|
||||
"@typescript-eslint/semi": [
|
||||
"error",
|
||||
"never"
|
||||
],
|
||||
|
||||
"no-unused-expressions": "off",
|
||||
"@typescript-eslint/no-unused-expressions": ["error", { "allowTernary": true }],
|
||||
@ -57,8 +64,8 @@ module.exports = {
|
||||
default: 'generic'
|
||||
}
|
||||
],
|
||||
"@typescript-eslint/explicit-module-boundary-types": "off",
|
||||
"@typescript-eslint/ban-types": "error",
|
||||
"@typescript-eslint/class-name-casing": "error",
|
||||
"@typescript-eslint/consistent-type-assertions": "error",
|
||||
"@typescript-eslint/consistent-type-definitions": "error",
|
||||
"@typescript-eslint/explicit-member-accessibility": [
|
||||
@ -92,36 +99,16 @@ module.exports = {
|
||||
"@typescript-eslint/prefer-for-of": "error",
|
||||
"@typescript-eslint/prefer-function-type": "error",
|
||||
"@typescript-eslint/prefer-namespace-keyword": "error",
|
||||
"@typescript-eslint/quotes": [
|
||||
"error",
|
||||
"single",
|
||||
{
|
||||
avoidEscape: true
|
||||
}
|
||||
],
|
||||
"@typescript-eslint/semi": [
|
||||
"error",
|
||||
"never"
|
||||
],
|
||||
|
||||
"@typescript-eslint/triple-slash-reference": "error",
|
||||
"@typescript-eslint/type-annotation-spacing": "error",
|
||||
"@typescript-eslint/unified-signatures": "error",
|
||||
"arrow-body-style": "error",
|
||||
"arrow-parens": [
|
||||
"error",
|
||||
"as-needed"
|
||||
"always"
|
||||
],
|
||||
|
||||
camelcase: "off",
|
||||
"@typescript-eslint/camelcase": ["error", {
|
||||
properties: "never",
|
||||
allow: ["^[A-Za-z][a-zA-Za-z]+_[A-Za-z]+$"]
|
||||
}],
|
||||
|
||||
"comma-dangle": [
|
||||
"error",
|
||||
"always-multiline"
|
||||
],
|
||||
complexity: "off",
|
||||
"constructor-super": "error",
|
||||
curly: "error",
|
||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -23,3 +23,5 @@
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
dist/
|
||||
|
13
Dockerfile
Normal file
13
Dockerfile
Normal file
@ -0,0 +1,13 @@
|
||||
FROM node:alpine
|
||||
|
||||
# instal yarn
|
||||
RUN apk -q add yarn
|
||||
|
||||
# Go to user home
|
||||
WORKDIR /home/tcgdex
|
||||
|
||||
COPY . .
|
||||
|
||||
RUN yarn && yarn build && yarn sitemap
|
||||
|
||||
CMD ["yarn", "server"]
|
46
README.md
46
README.md
@ -2,33 +2,21 @@
|
||||
|
||||
## Folders
|
||||
|
||||
## __tests__
|
||||
|
||||
Test files to test webpage or single components
|
||||
|
||||
### Components
|
||||
|
||||
Folder where you put your React components
|
||||
|
||||
### libs
|
||||
|
||||
Serverside Internal libs
|
||||
|
||||
### pages
|
||||
|
||||
NextJS Pages
|
||||
|
||||
### public
|
||||
|
||||
Static files
|
||||
|
||||
### Scripts
|
||||
|
||||
Scripts used by the project
|
||||
|
||||
### styl
|
||||
|
||||
Stylus files location
|
||||
- \__tests__: Test files to test webpage or single components
|
||||
- docker: Docker files to launch in a Container
|
||||
- public: Static files
|
||||
- assets: Generally used for Static assets like Pictures
|
||||
- uploads: used for user uploaded files
|
||||
- scripts: Contains scripts to quicky make actions (take look in each file to see what it does)
|
||||
- src: Source folder
|
||||
- client: Client-side Elements
|
||||
- components: Components used in pages
|
||||
- libs: Code used by the Client
|
||||
- styl: Stylus file location
|
||||
- modules: Stylus module location
|
||||
- common: Elements used by both Client-side and Server-side code
|
||||
- pages: Contains your NextJS pages
|
||||
- server: Custom server folder (if you are doing a basic NextJS app you can freely delete this folder)
|
||||
|
||||
## TODO list
|
||||
|
||||
@ -48,6 +36,9 @@ Stylus files location
|
||||
- [ ] Support both Stylus CSS modules and purge CSS
|
||||
- [ ] Support typed stylus files
|
||||
|
||||
## Custom Server
|
||||
|
||||
If you want to have a Custom server you simply have to start editing `src/server/server.ts` and after that to dev run `yarn cs-dev`
|
||||
|
||||
## Packages
|
||||
|
||||
@ -83,3 +74,4 @@ Stylus files location
|
||||
- eslint-plugin-react: ESLint React Plugin
|
||||
- jest: Jest tessting framework
|
||||
- react-test-renderer: Test React components
|
||||
- ts-node-dev: Start the developpement server and restart it on changes (remove this dev-deps if you're not using a custom server)
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React from 'react'
|
||||
import renderer from 'react-test-renderer'
|
||||
import HelloWorld from '../../components/HelloWorld'
|
||||
import HelloWorld from '../../src/client/components/HelloWorld'
|
||||
|
||||
/**
|
||||
* Example Test
|
||||
|
18
docker/docker-compose.override.yml
Normal file
18
docker/docker-compose.override.yml
Normal file
@ -0,0 +1,18 @@
|
||||
version: "3"
|
||||
services:
|
||||
tcgdex:
|
||||
volumes:
|
||||
- ../:/home/tcgdex
|
||||
command: "yarn dev"
|
||||
tty: true
|
||||
ports:
|
||||
- "3000:3000"
|
||||
phpmyadmin:
|
||||
image: phpmyadmin/phpmyadmin
|
||||
ports:
|
||||
- 8081:80
|
||||
networks:
|
||||
- network
|
||||
env_file:
|
||||
- .env
|
||||
- .env.local
|
6
docker/docker-compose.prod.yml
Normal file
6
docker/docker-compose.prod.yml
Normal file
@ -0,0 +1,6 @@
|
||||
version: "3"
|
||||
services:
|
||||
tcgdex:
|
||||
restart: "always"
|
||||
ports:
|
||||
- "127.0.0.1:4567:3000"
|
5
docker/docker-compose.test.yml
Normal file
5
docker/docker-compose.test.yml
Normal file
@ -0,0 +1,5 @@
|
||||
version: "3"
|
||||
services:
|
||||
tcgdex:
|
||||
ports:
|
||||
- "3000:3000"
|
28
docker/docker-compose.yml
Normal file
28
docker/docker-compose.yml
Normal file
@ -0,0 +1,28 @@
|
||||
version: "3"
|
||||
services:
|
||||
tcgdex:
|
||||
build:
|
||||
context: ../
|
||||
dockerfile: Dockerfile
|
||||
networks:
|
||||
- network
|
||||
depends_on:
|
||||
- db
|
||||
env_file:
|
||||
- .env
|
||||
- .env.local
|
||||
|
||||
db:
|
||||
image: mysql
|
||||
command: --default-authentication-plugin=mysql_native_password
|
||||
env_file:
|
||||
- .env
|
||||
- .env.local
|
||||
networks:
|
||||
- network
|
||||
volumes:
|
||||
- ./.storage/mysql/:/var/lib/mysql
|
||||
|
||||
networks:
|
||||
network:
|
||||
external: false
|
22
package.json
22
package.json
@ -4,7 +4,9 @@
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
"cs-dev": "ts-node --project tsconfig.server.json src/server/server.ts --respawn --transpileOnly --prefer-ts --watch next.config.js,.env --ignore-watch .next --ignore-watch src/pages --ignore-watch src/client --ignore-watch scripts src/server/server.ts",
|
||||
"build": "next build && tsc --project tsconfig.server.json",
|
||||
"cs-server": "NODE_ENV=production node --experimental-modules dist/server/server.js",
|
||||
"server": "next start",
|
||||
"export": "next export && node scripts/generateSitemap",
|
||||
"serve": "serve out",
|
||||
@ -14,7 +16,9 @@
|
||||
"test": "jest --config jext.config.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@sentry/browser": "^5.15.5",
|
||||
"@zeit/next-stylus": "^1.0.1",
|
||||
"express": "^4.17.1",
|
||||
"glob": "^7.1.6",
|
||||
"next": "^9.3.3",
|
||||
"next-compose-plugins": "^2.2.0",
|
||||
@ -32,16 +36,18 @@
|
||||
"@babel/core": "^7.8.7",
|
||||
"@babel/preset-env": "^7.8.6",
|
||||
"@babel/preset-react": "^7.8.3",
|
||||
"@types/express": "^4.17.6",
|
||||
"@types/jest": "^25.1.3",
|
||||
"@types/node": "^13.1.4",
|
||||
"@types/node": "^14.0.0",
|
||||
"@types/react": "^16.9.17",
|
||||
"@types/react-test-renderer": "^16.9.2",
|
||||
"@typescript-eslint/eslint-plugin": "^2.19.0",
|
||||
"@typescript-eslint/parser": "^2.19.0",
|
||||
"babel-jest": "^25.1.0",
|
||||
"eslint": "^6.8.0",
|
||||
"@typescript-eslint/eslint-plugin": "^3.0.0",
|
||||
"@typescript-eslint/parser": "^3.0.0",
|
||||
"babel-jest": "^26.0.0",
|
||||
"eslint": "^7.1.0",
|
||||
"eslint-plugin-react": "^7.18.3",
|
||||
"jest": "^25.1.0",
|
||||
"react-test-renderer": "^16.13.0"
|
||||
"jest": "^26.0.0",
|
||||
"react-test-renderer": "^16.13.0",
|
||||
"ts-node-dev": "^1.0.0-pre.44"
|
||||
}
|
||||
}
|
||||
|
@ -1,21 +0,0 @@
|
||||
import App from 'next/app'
|
||||
import Head from 'next/head'
|
||||
import React from 'react'
|
||||
|
||||
import '../styl/index.styl'
|
||||
|
||||
export default class CApp extends App {
|
||||
|
||||
public render() {
|
||||
const { Component, pageProps } = this.props
|
||||
|
||||
return(
|
||||
<>
|
||||
<Head>
|
||||
<title>Next Template Hello World !</title>
|
||||
</Head>
|
||||
<Component {...pageProps} />
|
||||
</>
|
||||
)
|
||||
}
|
||||
}
|
0
public/uploads/.gitkeep
Normal file
0
public/uploads/.gitkeep
Normal file
3
scripts/dev
Executable file
3
scripts/dev
Executable file
@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env sh
|
||||
cd ..
|
||||
docker-compose -f docker/docker-compose.yml -f docker/docker-compose.override.yml up
|
3
scripts/test
Executable file
3
scripts/test
Executable file
@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env sh
|
||||
cd ..
|
||||
docker-compose -f docker/docker-compose.yml -f docker/docker-compose.test.yml up --build
|
3
scripts/upgrade
Executable file
3
scripts/upgrade
Executable file
@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env sh
|
||||
cd ..
|
||||
docker-compose -f docker/docker-compose.yml -f docker/docker-compose.prod.yml up -d --build
|
@ -1,5 +1,5 @@
|
||||
import React, { SyntheticEvent } from 'react'
|
||||
import css from './Image.module.styl'
|
||||
import css from '@smd/Image.module.styl'
|
||||
|
||||
interface Props {
|
||||
defaultHeight?: number
|
||||
@ -50,7 +50,7 @@ const getMimeType = (img: string) => {
|
||||
|
||||
type evType<T = HTMLImageElement> = SyntheticEvent<T, Event>
|
||||
|
||||
export default class Image extends React.Component<Props, {}> {
|
||||
export default class Image extends React.Component<Props> {
|
||||
|
||||
private ref: React.RefObject<HTMLImageElement> = React.createRef()
|
||||
private plchldr: React.RefObject<HTMLDivElement> = React.createRef()
|
0
src/client/libs/.gitkeep
Normal file
0
src/client/libs/.gitkeep
Normal file
0
src/client/styl/modules/.gitkeep
Normal file
0
src/client/styl/modules/.gitkeep
Normal file
0
src/common/libs/.gitkeep
Normal file
0
src/common/libs/.gitkeep
Normal file
11
src/pages/404.tsx
Normal file
11
src/pages/404.tsx
Normal file
@ -0,0 +1,11 @@
|
||||
import React from 'react'
|
||||
import Error from './_error'
|
||||
|
||||
export default class E404 extends React.Component {
|
||||
|
||||
public render() {
|
||||
return(
|
||||
<Error statusCode={404} />
|
||||
)
|
||||
}
|
||||
}
|
50
src/pages/_app.tsx
Normal file
50
src/pages/_app.tsx
Normal file
@ -0,0 +1,50 @@
|
||||
import App from 'next/app'
|
||||
import Head from 'next/head'
|
||||
import React from 'react'
|
||||
import * as Sentry from '@sentry/browser'
|
||||
import ErrorPage from './_error'
|
||||
|
||||
import '@styl/index.styl'
|
||||
|
||||
Sentry.init({
|
||||
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN
|
||||
})
|
||||
|
||||
interface States {
|
||||
errorId?: string
|
||||
}
|
||||
|
||||
export default class CApp extends App<Record<string, unknown>, Record<string, unknown>, States> {
|
||||
|
||||
public componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
|
||||
console.log('catching error', error, errorInfo)
|
||||
Sentry.withScope((scope) => {
|
||||
Object.keys(errorInfo).forEach((key) => {
|
||||
scope.setExtra(key, (errorInfo as any)[key])
|
||||
})
|
||||
const id = Sentry.captureException(error)
|
||||
console.log(id)
|
||||
this.setState({
|
||||
errorId: id
|
||||
})
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
public render() {
|
||||
const { Component, pageProps } = this.props
|
||||
|
||||
return(
|
||||
<>
|
||||
<Head>
|
||||
<title>Next Template Hello World !</title>
|
||||
</Head>
|
||||
{this.state && this.state.errorId && (
|
||||
<ErrorPage statusCode={500} eventId={this.state.errorId} />
|
||||
) || (
|
||||
<Component {...pageProps} />
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
}
|
25
src/pages/_document.tsx
Normal file
25
src/pages/_document.tsx
Normal file
@ -0,0 +1,25 @@
|
||||
import React from 'react'
|
||||
import Document, { Html, Head, Main, NextScript } from 'next/document'
|
||||
import * as Sentry from '@sentry/browser'
|
||||
|
||||
process.on('unhandledRejection', (err) => {
|
||||
Sentry.captureException(err)
|
||||
})
|
||||
|
||||
process.on('uncaughtException', (err) => {
|
||||
Sentry.captureException(err)
|
||||
})
|
||||
|
||||
export default class CDocument extends Document {
|
||||
public render() {
|
||||
return (
|
||||
<Html>
|
||||
<Head />
|
||||
<body>
|
||||
<Main />
|
||||
<NextScript />
|
||||
</body>
|
||||
</Html>
|
||||
)
|
||||
}
|
||||
}
|
31
src/pages/_error.tsx
Normal file
31
src/pages/_error.tsx
Normal file
@ -0,0 +1,31 @@
|
||||
import React from 'react'
|
||||
|
||||
import { NextPageContext } from 'next'
|
||||
import * as Sentry from '@sentry/browser'
|
||||
|
||||
interface Props {
|
||||
statusCode: number
|
||||
eventId?: string
|
||||
}
|
||||
|
||||
export default class Error extends React.Component<Props> {
|
||||
|
||||
public static async getInitialProps({res, err}: NextPageContext): Promise<Props> {
|
||||
const statusCode = res?.statusCode || err?.statusCode || 500
|
||||
return {
|
||||
statusCode
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public render() {
|
||||
return(
|
||||
<>
|
||||
<h1>An Error Occured ! {this.props.statusCode}</h1>
|
||||
{this.props.eventId && (
|
||||
<button onClick={() => Sentry.showReportDialog({ eventId: this.props.eventId })}>Report Error</button>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
}
|
@ -1,11 +1,23 @@
|
||||
import React from 'react'
|
||||
import '../styl/index.styl'
|
||||
import HelloWorld from '../components/HelloWorld'
|
||||
import Image from '../components/Image'
|
||||
import HelloWorld from '@cp/HelloWorld'
|
||||
import Image from '@cp/Image'
|
||||
|
||||
function isWindow() {
|
||||
try {
|
||||
window.isNaN(1)
|
||||
return true
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
export default class Index extends React.Component {
|
||||
|
||||
public render() {
|
||||
if (isWindow()) {
|
||||
throw new Error('Test')
|
||||
}
|
||||
|
||||
return(
|
||||
<>
|
||||
<HelloWorld>Hello World</HelloWorld>
|
||||
@ -13,7 +25,7 @@ export default class Index extends React.Component {
|
||||
max={{height:400,width:200}}
|
||||
default={{width:200,height:100}}
|
||||
deleteOnError={true}
|
||||
src="https://source.unusplash.com/random/800x600"
|
||||
src="https://source.unsplash.com/random/800x600"
|
||||
/>
|
||||
<HelloWorld>Hello World</HelloWorld>
|
||||
</>
|
22
src/server/server.ts
Normal file
22
src/server/server.ts
Normal file
@ -0,0 +1,22 @@
|
||||
// Base Server Config
|
||||
// https://nextjs.org/docs/advanced-features/custom-server
|
||||
import { createServer } from 'http'
|
||||
import { parse } from 'url'
|
||||
import next from 'next'
|
||||
|
||||
const dev = process.env.NODE_ENV !== 'production'
|
||||
const app = next({ dev })
|
||||
const handle = app.getRequestHandler()
|
||||
|
||||
;(async () => {
|
||||
await app.prepare()
|
||||
createServer((req, res) => {
|
||||
// Be sure to pass `true` as the second argument to `url.parse`.
|
||||
// This tells it to parse the query portion of the URL.
|
||||
const parsedUrl = parse(req.url || '', true)
|
||||
|
||||
handle(req, res, parsedUrl)
|
||||
}).listen(parseInt(process.env.PORT || '3000', 10), () => {
|
||||
console.log('> Ready on http://localhost:3000')
|
||||
})
|
||||
})()
|
@ -16,7 +16,13 @@
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"jsx": "preserve"
|
||||
"jsx": "preserve",
|
||||
"baseUrl": "./src",
|
||||
"paths": {
|
||||
"@styl/*": ["client/styl/*"],
|
||||
"@cp/*": ["client/components/*"],
|
||||
"@smd/*": ["client/styl/modules/*"],
|
||||
}
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
@ -25,7 +31,7 @@
|
||||
],
|
||||
"include": [
|
||||
"next-env.d.ts",
|
||||
"styl/stylus.d.ts",
|
||||
"src/client/styl/stylus.d.ts",
|
||||
"**/*.ts",
|
||||
"**/*.tsx"
|
||||
]
|
||||
|
13
tsconfig.scripts.json
Normal file
13
tsconfig.scripts.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"outDir": "scripts-dist",
|
||||
"target": "es2017",
|
||||
"isolatedModules": false,
|
||||
"noEmit": false
|
||||
},
|
||||
"include": [
|
||||
"scripts/**/*.ts"
|
||||
]
|
||||
}
|
15
tsconfig.server.json
Normal file
15
tsconfig.server.json
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"outDir": "dist",
|
||||
"target": "es2017",
|
||||
"isolatedModules": false,
|
||||
"noEmit": false,
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true
|
||||
},
|
||||
"include": [
|
||||
"src/server/**/*.ts"
|
||||
]
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user