Skip to content

Template for quickly starting a SSR Node.js application with vite, react, effector, and fastify

License

Notifications You must be signed in to change notification settings

effector/vike-react-template

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Effector SSR Vike Application Template

This project is a template for quickly starting a Server-Side Rendering (SSR) Node.js application, combining a powerful set of vite, react, effector, and fastify.

Features

  • File-system routing implemented by Vike;
  • Effector to cover state management cases;
  • React.js to use the giant ecosystem of UI components;

Used Tools

Requirements

  • Node.js 18.6+
  • corepack enabled (but can be used without)

Use this template

  1. Press "Use this template" to create a copy of repository.

  2. Clone your repository:

git clone https://github.com/effector/vike-react-template my-app
# OR
gh repo clone effector/vike-react-template my-app
  1. Navigate to the project directory:
cd my-app
  1. Install package manager and dependencies:
corepack enable
corepack prepare
pnpm install

Usage

  1. Run in development mode:
pnpm dev
  1. Build for production:
pnpm build
  1. Run production version:
pnpm start

Project Structure

Strongly recommend to carefully review each file in this repository, before using it in production.

This project inherites Vike project structure:

dist/
pages/
public/
renderer/
server/
src/
  • dist contains result of pnpm build, it is production build;
  • pages is a Vike's filesystem routing;
  • public is a static files directory;
  • renderer is a react + effector integration hooks;
  • server is a fastify server, builds with tsc, runs with ts-node;
  • src is a FSD basis, with code imported into pages, and renderer;

pages/

pages/+Wrapper.tsx

It is a data provider for logic uses effector.

pages/+Layout.tsx

To wrap up components with some layout use +Layout.tsx.

Also, you can nest multiple layouts.

pages/index/+pageStarted.ts

This vike hook describes what event Vike should call on server when page logic can be started.

Usually looks like this:

import { createPageStart } from "~/shared/init";

export const pageStarted = createPageStart();

// pageStarted has type:
pageStarted: EventCallable<{
  params: Record<string, string>;
  data: void;
}>;

params looks like { id: "foo" } for route pages/example/@id and pathname /example/foo.

Url Route params
/ pages/index {}
/example/100 pages/example/@id { id: "100" }

pages/index/+Page.tsx

This is a page component. It can import model.ts and all from src using ~/ alias.

Use export default and named functions:

export default function PageHome() {
  return <h1>Hello World</h1>;
}

pages/index/model.ts

This is a logic file written in effector. It can import +pageStarted.ts and all from src using ~/ alias.

import { createEffect, sample } from "effector";

import { pageStarted } from "./+pageStarted";

const helloFx = createEffect((name: string) => {
  console.info(`Hello ${name}`);
});

sample({
  clock: pageStarted,
  fn: () => "World",
  target: helloFx,
});

When user opened http://localhost:3000, pageStarted fired, then sample with clock: pageStarted reacts and triggers helloFx with "World" argument.

In our dynamic and event driven kind of environment, this is the powerful way to describe logic. Without needing to deal with React, Hooks, Rerenders, StrictMode, Next.js, etc.

pages/example/@id

Let's talk about data loading.

You can always use simple createEffect to load data in Browser, just react on user actions, not pageStarted nor appStarted.

Until, you read Data Fetching article from Vike.dev. It will works until Client-Side Routing. Vike has +data.ts hook to fetch data on client and server navigation.

In case of refetch data using triggering some event on client side, or changing filters in user interface consider making client navigation with query parameters.

pages/example/@id/+data.ts

Declare your data fetcher. Name of the exported function must be data. Use this as starting point:

import type { PageContextServer } from "vike/types";

export async function data(pageContext: PageContextServer) {
  const { routeParams } = pageContext;
  const { id } = routeParams;

  // await api.someItems.getById(id)

  return {
    sampleData: { id: id ?? "<empty>" },
  };
}

Consider placing all reusable API requests into src/shared/api. Using barrel file pattern is optional but very useful.

pages/example/@id/+pageStarted.ts

In case of data loading, hook pageStarted should be modified:

import { createPageStart } from "~/shared/init";

import type { data } from "./+data";

export const pageStarted = createPageStart<Awaited<ReturnType<typeof data>>>();

You need just bind resulting type of your data loader function. Vike passes result of data() call into pageStarted like { params: { id }, data }.

pages/example/@id/model.ts

So, you can access data from model like this:

import { createStore, sample } from "effector";

import { pageStarted } from "./+pageStarted";

sample({
  clock: pageStarted,
  fn: ({ data, params: { id } }) => data,
  target: insertHereAnyUnit,
});
// you can actually use `source, filter` in sample

pages/_error

Component created as pages/_error/+Page.tsx is used to show error page.

renderer/

Here described exact integration of vike, react, and effector. You may need to read this before changing:

server/

server/config.ts

Contains resolvers of configuration variables.

export const CONFIG = {
  get SERVER_PORT() {
    return Number.parseInt(globalThis.process.env.SERVER_PORT ?? "3000", 10);
  },
};

This is the only way it works on Cloudflare Workers. If you have a better solution please Leave an issue.

server/directory-root.ts

Declares project root directory, to resolve static assets from.

server/index.ts

Creates instance of server/server, handles signals SIGINT, SIGTERM.

server/server.ts

Creates fastify instance, configures plugins, read cookies, renders using vike/server.

You can modify any part of this and any other files. Please, explore documentation before.

server/tsconfig.json

Used here to describe different environment for files in this directory.

It builds for production with tsc -p server. It runs for development with ts-node ESM-loader.

There is no hot reload in server/ directory. Restart manually after changing these files.

src/

Consider using Feature-Sliced Design structuring this directory.

src/vike.d.ts

Handles pageContext typings.

src/vite-env.d.ts

Handles Vite client types.

Customization

What kind of customizations needs to be described? integration with supabase? Leave an issue.

Use different Package Manager

First of all, delete pnpm-lock.yaml, dist, and node_modules:

rm pnpm-lock.yaml
rm -rf node_modules dist

Node.js v18.x:

Set exact version into packageManager field of package.json:

// package.json
{
  "packageManager": "npm@10.8.2" // "yarn@3.8.4",
}

Save and navigate to your terminal into the project directory:

# Enable corepack for your shell
corepack enable

# Install package manager for your project
corepack prepare

# Install dependencies
npm install

Node.js v20+:

Node.js v20 has different version of corepack, so we can use corepack use.

# Enable corepack for your shell
corepack enable

# Install package manager for your project
corepack use npm@latest # yarn@3

# Install dependencies
npm install

# Check packageManager field in package.json
jq .packageManager package.json
#> "yarn@3.8.4+sha256.1ee0e26fb669143425371ab8727fe4c5841640a2fd944863a8e8c28be966aca2"
# It's OK

Supported OS and Node.js

This template has been tested on:

  • macOS Sonoma 14.5, Node.js v20.10.0

Contributing

We welcome contributions to the project! Please read our contribution guidelines before submitting a pull request.

License

This project is licensed under the MIT License - see the LICENSE file for details.

About

Template for quickly starting a SSR Node.js application with vite, react, effector, and fastify

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published