Iso

Iso GitHub package.json version

GitHub package.json dependency version (prod) GitHub package.json dependency version (prod) GitHub package.json dependency version (prod)

Iso is starter-pack for creating isomorphic single-page application with using SSR technology on NodeJS.

Powered by ogarich89

Warning

For a comfortable development you will need the knowledge of React, Redux and Fastify.

Tech

ISO uses a number of open source projects to work properly:

  • Node.js - Open-source, cross-platform JavaScript runtime environment.
  • Typescript - JavaScript with syntax for types.
  • Fastify - Fast and low overhead web framework, for Node.js
  • React - JavaScript library for building user interfaces
  • Redux - A Predictable State Container for JS Apps
  • Rspack - Module bundler
  • HMR - Hot Module Replacement
  • Browsersync - Time-saving synchronised browser testing
  • SWC - Rust-based platform for the Web
  • ESLint - Statically analyzes your code to quickly find problems.
  • Loadable-components - React code splitting library.
  • Prisma - Next-generation Node.js and TypeScript ORM
  • react-i18next - Powerful internationalization framework for React / React Native which is based on i18next.
  • Etc. (See package.json)

And of course ISO itself is open source with a [public repository] on GitHub.

Usage

Install

ISO requires Node.js v20+ and Redis (optional) to run.

$ git clone https://github.com/ogarich89/iso.git <project name>
$ cd <project name>
$ yarn install

Development

1. Create configuration file

$ touch config/environment/development.json

2. Set params

{
 "port": 3000,
 "browserSyncPort": 3001,
 "api": "https://reqres.in",
 "withStatic": true,
 "inspect": true,
 "logger": true
}

port - Node.js server port
browserSyncPort - Development proxy server port with browserSync and HMR
api - Backend API hostname
sessionRedisDb - Redis database index
withStatic - Serve static files with NodeJS server
withRedis - Session with Redis store
inspect - Debugging Node.js with Chrome DevTools
logger - Fastify logger
analyze - Rsdoctor
sentryDSN - Error monitoring with Sentry
certificate - Optional object for run https server { "key": "/path/to/key.pem", "cert": "/path/to/cert.pem" }

If you want to use Prisma run the command

$ cp .env.example .env

and set DATABASE_URL environment variable

DATABASE_URL=postgresql://postgres:postgres@localhost:5432/iso?connect_timeout=1000

3. Run dev server

$ yarn dev

or run each command in a separate terminal tab

$ yarn watch:client
$ yarn watch:server
$ yarn server

Open in browser http://localhost:3001


Run without watch files, HMR, BrowserSync, Gulp

$ yarn start

Open in browser http://localhost:3000


Production

1. Building for source

For production release:

$ yarn production

Build mode (development | production) depending on NODE_ENV
Reading file config/environment/(staging | production).json depending on ENVIRONMENT

$ yarn build

2. Run Node.js server

$ node server/index.mjs

F.A.Q.

How to add page?

  1. Create file example.tsx in src/components/pages
  2. Connect the page in src/routes.ts
    const routes = [
      ...
      route({ 
     path: '/',
     layout: 'main',
     children: [
       { path: '/example', page: 'example' },
     ],
      }),
      ...
    ];
    

How to add nested page?

  1. Add Outlet component to example page
  2. Create file nested.tsx in src/components/pages
  3. Connect the page in src/routes.ts
    const routes = [
      ...
      route({ 
     path: '/',
     layout: 'main',
     children: [
       { 
         path: '/example', 
         page: 'example', 
         children: [
           {
             path: '/example/nested',
             page: 'nested'
           }
         ] 
       },
     ],
      }),
      ...
    ];
    

How to create initial action?

  1. Create file example.ts in src/store/actions
    export const exampleInitialAction = createAsyncThunk(
     'exampleInitialAction',
     async (req: { url: string }) => {
       const { data } = await request('example', $DATA, $PARAMS, req).catch((error) => {
         console.error(error);
         return { data: null };
       });
       return data;
     },
    );
    
  2. Add to page in src/components/pages
    const routes = [
      ...
      route({ 
     path: '/',
     layout: 'main',
     children: [
       { path: '/example', page: 'example', initialAction: exampleInitialAction },
     ],
      }),
      ...
    ];
    
  3. Configure the initial action on the client side

You can use hook useInitialState if initialAction return one state in array

const state = useInitialState(initialAction, exampleSelector, exampleResetAction);

or arrange the initialization of the state at your discretion