Tnf, the north face, the next framework. Tnf is focused on simple, performance and developer experience. Framework should be simple. CSR development should be simple. Type safety should be built-in.
Please consider following this project's author, sorrycc, and consider starring the project to show your ❤️ and support.
- Simple, performance and developer experience focused.
- Type safety built-in.
- TanStack Router built-in.
- Conventional global style with
src/global.{less,css}
. - Less, CSS Modules support built-in.
- Tailwind CSS support built-in.
- Framework unified plugin system which is compatible with umi and other frameworks.
- Mock.
- Conventional client entry with
src/client.tsx
. - Security built-in. Including doctor rules which is used in Ant Group.
- Support SSR.
- Support API routes and server functions.
- AI based generator and other features.
- Rust based for heavy computation tasks.
- Easy to integrate with popular libraries.
Create a new project with the following command:
$ pnpm create tnf myapp --template=simple
$ cd myapp
$ pnpm i
Then you can generate a page with the following command.
$ npx tnf generate page foo
Then you can start the development server or build the project. After building, you can preview the product locally.
$ pnpm dev
$ pnpm build
$ pnpm preview
tnf build
: Build the project.tnf config list/get/set/remove [name] [value]
: Manage the config.tnf dev
: Start the development server.tnf doctor
: Check the project for potential issues.tnf generate/g <type> <name>
: Generate a new page (or component and other types in the future).tnf preview
: Preview the product after building the project.tnf sync --mode=<mode>
: Sync the project to the temporary directory.
@umijs/tnf
: The entry of tnf, includingdefineConfig
, ...@umijs/tnf/router
: The router module, reexported from@tanstack/react-router
.@umijs/tnf/ssr
: The ssr module, includingMeta
,Client
andServer
.@umijs/tnf/ai
: The ai module, includingtools
.
Config is loaded from .tnfrc.ts
by default.
- Type:
[string, string][]
- Default:
[]
Alias is used to replace the values in import
statements. These values are passed to bundlers and TypeScript automatically.
export default {
alias: [
['foo', './src/foo'],
],
}
NOTICE: You will need to run tnf dev
to have the alias configuration in tsconfig.json
automatically generated.
- Type:
'webpack' | 'mako'
- Default:
'mako'
The bundler to use.
NOTICE: webpack bundler is not implemented yet.
- Type:
{ editor?: 'vscode' | 'vscode-insiders' | 'cursor' } | false
- Default:
false
Click the component to open in the editor.
- Type:
{ port?: number; host?: string; https?: { hosts?: string[] }; ip?: string }
- Default:
{ port: 8000, host: 'localhost' }
The development server configuration.
- Type:
{ phantomDeps?: { exclude?: string[] } }
- Default:
{}
The doctor configuration.
- Type:
Record<string, string>
- Default:
{}
An object that maps package names to their corresponding paths.
- Type:
{ modifyVars?: Record<string, string>; globalVars?: Record<string, string>; math?: 'always' | 'strict' | 'parens-division' | 'parens' | 'strict-legacy' | number; sourceMap?: any; plugins?: (string | [string, Record<string, any>])[];}
- Default:
{}
The configuration passed to lessLoader.
- Type:
{ delay?: string | number }
- Default:
{ delay: 0 }
In addition to supporting numbers, delay also supports string ranges, such as delay: '500-1000', which randomly selects a value between 500ms and 1000ms.And allowing the configuration to be overridden by the url parameter, such as /api/users?delay=3000.
- Type:
string
- Default:
'root'
The mount element id.
- Type:
Plugin[]
- Default:
[]
The plugins configuration. Checkout plugin.md for more details.
- Type:
string
- Default:
/
The publicPath configuration.
- Type:
{ target?: '17' | '18' | '19'; sources?: (filePath: string) => boolean }
- Default:
false
Enable react compiler for better performance.
- Type:
{}
- Default:
false
Enable react scan to detects performance issues in your React code.
- Type:
{ defaultPreload?: 'intent' | 'render' | 'viewport'; defaultPreloadDelay?: number; devtool?: { options?: { initialIsOpen?: boolean; position?: 'bottom-left' | 'bottom-right' | 'top-left' | 'top-right' }; } | false; convention?: any }
- Default:
{ defaultPreload: 'intent', defaultPreloadDelay: 100 }
The router configuration. Checkout @tanstack/router-generator for convention config.
- Type:
{ renderMode?: 'stream' | 'string' }
- Default:
{ renderMode: 'stream' }
The ssr configuration.
Environment variables are used to override the config.
PORT
: The port to use.HOST
: The host to use.
You can use redirect
function in loader to specify a redirect route.
import { redirect, createFileRoute } from '@umijs/tnf/router';
const Route = createFileRoute('/foo')({
loader: async () => redirect({ to: '/bar' }),
});
First, define parent route with beforeLoad
.
const parentRoute = createFileRoute('/foo')({
beforeLoad: () => ({ foo: 'foo' }),
});
If it's root route, you can use createRootRouteWithContext
instead.
const rootRoute = createRootRouteWithContext<{ root: string }>()({
beforeLoad: () => ({ root: 'root' }),
});
Second, fetch the loader data in child route with context
.
const childRoute = createFileRoute('/foo/bar')({
// context: { root: 'root', foo: 'foo' },
loader: async ({ context }) => ({ ...context }),
});
This project is inspired by:
- @tanstack/router for the router and ssr.