Skip to content

Commit

Permalink
add global styles and react app entry point; update README
Browse files Browse the repository at this point in the history
  • Loading branch information
Kallenju committed Dec 10, 2022
1 parent 9b2fd9a commit a5fbab5
Show file tree
Hide file tree
Showing 20 changed files with 162 additions and 14 deletions.
37 changes: 33 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,56 @@
# template-for-react-ts-ssr-hmr

Template for a project with React, TypeScript, SSR, HMR. Template imply using CSS Modules and Stylus. But it can be easily changed.
Template for a project with React, TypeScript, SSR, and HMR. The template implies the use of CSS Modules and Stylus.

## Quick start:
## Quick start:

To copy the template in an empty local folder without creating of a repo or in an existing repo use the following:

```shell
npx degit Kallenju/template-for-react-ts-ssr-hmr
```

Install packages and run development servers:
Install packages and run development servers:

```shell
npm install

npm run dev
```

## Structure of the template

### Structure of the source folder (`./src`)

- **assets**
- **styles**
- **body**
- **html**
- **root**
- **client**
- **server**
- **shared**
- **Header**
- **Layout**
- **types**

## How it works

`./src` contains `App.tsx`, which is the entry point of the React app. It imports components from `./src/shared` and global styles from `./assets/styles/`. `App.tsx` is in turn imported be server and client files in `./src/server/` and `./src/client/`, respectively.

The `app.get()` method specifies a callback function that will render to string React component from `App.tsx` and past it in a HTML template, whenever there is an HTTP GET request with a path ('/') relative to the site root. HTML template are in `./src/server`.

After the `load` event is fired, the client code `hydrate` obtained React component.

## What is used in the template?

### Hot module replacement
### Hot Module Replacement

- express server
- react-refresh-webpack-plugin
- React Fast Refresh
- Webpack modules and plugins (webpack-dev-middleware, webpack-hot-middleware, webpack.HotModuleReplacementPlugin)

### Server-Side Rendering

- express server
24 changes: 21 additions & 3 deletions config/webpack.client.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ const webpack = require('webpack');
const ReactRefreshPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');

const { NODE_ENV } = globalThis.process.env;
const { NODE_ENV } = process.env;
const MODULE_CODE_REGEXP = /\.[tj]sx?$/;
const MODULE_STYLES_REGEXP = /\.module\.styl$/;
const GLOBAL_STYLES_REGEXP = /\.global\.styl$/;

module.exports = {
entry: [
Expand All @@ -21,15 +24,16 @@ module.exports = {
module: {
rules: [
{
test: /\.[tj]sx?$/,
test: MODULE_CODE_REGEXP,
use: [
{
loader: 'babel-loader',
},
],
},
{
test: /\.styl$/,
test: MODULE_STYLES_REGEXP,
exclude: GLOBAL_STYLES_REGEXP,
use: [
{
loader: 'style-loader',
Expand Down Expand Up @@ -58,6 +62,20 @@ module.exports = {
},
],
},
{
test: GLOBAL_STYLES_REGEXP,
use: [
{
loader: 'css-loader',
},
{
loader: 'postcss-loader',
},
{
loader: 'stylus-loader',
},
],
},
],
},

Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "template-for-react-ts-ssr-hmr",
"version": "1.0.1",
"description": "Template for a project with React, TypeScript, SSR, HMR. Template imply using CSS Modules and Stylus. But it can be easily changed.",
"version": "1.1.0",
"description": "Template for a project with React, TypeScript, SSR, HMR. The template implies the use of CSS Modules and Stylus.",
"repository": {
"type": "git",
"url": "https://github.com/Kallenju/template-for-react-ts-ssr-hmr.git"
Expand Down
12 changes: 12 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React from 'react';
import { Layout } from './shared/Layout';
import { Header } from './shared/Header';
import './assets/styles/main.global.styl';

export default function App(): React.ReactElement {
return (
<Layout>
<Header />
</Layout>
);
}
8 changes: 8 additions & 0 deletions src/assets/styles/body/body.styl
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
body
margin 0
min-width 320px
font-family --font-family-primary, sans-serif
font-size --font-size_sm
font-weight --font-weight_xs
line-height --line-height_xs
background-color --color-white
1 change: 1 addition & 0 deletions src/assets/styles/body/index.styl
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@import 'body'
12 changes: 12 additions & 0 deletions src/assets/styles/html/html.styl
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
html
box-sizing border-box
font-size 0.625em

*
box-sizing inherit

&::before
box-sizing inherit

&::after
box-sizing inherit
1 change: 1 addition & 0 deletions src/assets/styles/html/index.styl
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@import 'html'
3 changes: 3 additions & 0 deletions src/assets/styles/main.global.styl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@import './root'
@import './html'
@import './body'
1 change: 1 addition & 0 deletions src/assets/styles/root/index.styl
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@import 'root';
52 changes: 52 additions & 0 deletions src/assets/styles/root/root.styl
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
--container-width = 1400px
--container-margins = 55px
--container-margins_md = 31px
--container-margins_sm = 27px
--container-margins_xs = 21px
--font-family-primary = 'Roboto'
--font-family-secondary = 'ttfirsneue'
--font-size_xxs = 1.20rem
--font-size_xs = 1.40rem
--font-size_sm = 1.60rem
--font-size_md = 1.80rem
--font-size_lg = 2.00rem
--font-size_xl = 2.40rem
--font-size_xxl = 3.40rem
--line-height_xs = 1.04
--line-height_sm = 1.17
--line-height_md = 1.29
--line-height_lg = 1.38
--line-height_xl = 1.75
--font-weight_xs = 400
--font-weight_sm = 500
--font-weight_md = 600
--font-weight_lg = 700
--font-weight_xl = 800
--warning-color-primary = #ff3030
--success-color-primary = #7cbc4a
--brend-color = #ff6e30
--background-color-primary = #ff5c00
--background-color-secondary = #202020
--color-focus-primary = #ff6e30
--color-hover-primary = #bc572b
--color-active-primary = #ce4307
--border-color-primary = #ff6e30
--border-color-secondary = #ce4307
--text-color-primary = #fff
--text-color-secondary = #202020
--form-text-color-primary = #202020
--color-dark-grey = #202020
--color-middle-grey = #999
--color-light-grey = #e9e9e9
--color-white = #fff
--color-black = #000
--transition-time_slow = 0.210s
--transition-time_fast = 0.100s

--breakpoint_xs = 40em
--breakpoint_sm = 56em
--breakpoint_md = 66em
--breakpoint_lg = 82em
--grid-columns = 12
--grid-gap = 3.00rem
--link_css-effects = 'plain'
4 changes: 2 additions & 2 deletions src/client/index.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import React from 'react';
import ReactDom from 'react-dom/client';
import Header from '../shared/Header';
import App from '../App';

window.addEventListener('load', () => {
const container: Element | null = document.querySelector('#react_root');

if (container) {
ReactDom.hydrateRoot(container, <Header />);
ReactDom.hydrateRoot(container, <App />);
}
});
4 changes: 2 additions & 2 deletions src/server/server.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import express from 'express';
import React from 'react';
import ReactDOMServer from 'react-dom/server';
import Header from '../shared/Header';
import App from '../App';
import indexTemplate from './indexTemplate';

const app = express();

app.use('/static', express.static('./dist/client'));

app.get('/', (req, res) => {
res.send(indexTemplate(ReactDOMServer.renderToString(<Header />)));
res.send(indexTemplate(ReactDOMServer.renderToString(<App />)));
});

app.listen(3000);
2 changes: 1 addition & 1 deletion src/shared/Header.tsx → src/shared/Header/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useState } from 'react';
import styles from './header.module.styl';

export default function Header(): React.ReactElement {
export function Header(): React.ReactElement {
const [count, setCount] = useState(0);
function handleClick() {
setCount(count + 1);
Expand Down
File renamed without changes.
1 change: 1 addition & 0 deletions src/shared/Header/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './Header';
9 changes: 9 additions & 0 deletions src/shared/Layout/Layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import React from 'react';

interface ILayoutProps {
children?: React.ReactNode;
}

export function Layout({ children }: ILayoutProps): React.ReactElement {
return <article>{children}</article>;
}
1 change: 1 addition & 0 deletions src/shared/Layout/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './Layout';
Empty file.
File renamed without changes.

0 comments on commit a5fbab5

Please sign in to comment.