Universal Scripts is a highly flexible framework for React projects, offering advanced features such as Server-Side Rendering (SSR) and internationalization (i18n). It allows you to extend or override existing configuration easily, giving you complete control over your setup.
- Server-Side Rendering.
- TypeScript support including custom aliases.
- Internationalization with
react-intl
, - Metadata management with
react-helmet-async
. - Redux state management with
redux-toolkit
and types support. - Integrated with
ruse-fetch
to provide a modern way of fetching data withSuspense
. - Use
SWC
for better performance. - Hot Reload in Server and Client, including .env file.
You can use the pre-built templates, such as the TypeScript template, or create your own to match your preferences. Below are the main folders defined in the default template:
-
src/locales
: Store your translations, the first key inindex.ts
is the default language. -
src/routes
: The index file serves as the root component, where you can define your application routes withreact-router
. -
src/static
: Contains static assets like images, fonts, etc. These files will be copied to the build. -
src/store
: Add your slices and place them inside the slices folder. -
src/styles
: The main entry point for global styles.
These are the default folders, but you can create additional ones such as components, hooks, contexts, and more. Additionally, the tsconfig file includes predefined aliases, which you can customize or extend as needed.
In Universal, you have the flexibility to use pre-built plugins or develop your own. These plugins are designed to work seamlessly without requiring any additional configuration—just install them, and they are ready to use. This allows for a more efficient development process, enabling you to extend functionality effortlessly while maintaining a clean and modular project structure.
This documentation describes the configuration of the following universal pre-installed plugins in a project:
This plugin introduces configuration for react-helmet-async
, enabling efficient metadata management in React applications.
- Enables full functionality of react-helmet-async.
- Allows dynamic <head> management in a React application.
- Improves SEO optimization and accessibility.
- Enables customizable social sharing with dynamic Open Graph metadata.
This plugin configures Jest
, to run your test suites.
- Configures Jest for unit and integration testing.
- Use SWC for better performance.
In addition to the pre-installed plugins, you can create your own plugins or use other existing ones, such as the universal-plugin-sass
for Sass support.
If you want to use for example universal-plugin-sass
you just have to install this as a dependency. And universal will recognize them without any configuration.
yarn add universal-plugin-sass
If using npm
npm install universal-plugin-sass
Universal is already configured to use ruse-fetch
, making data fetching simple and efficient.
import { useFetch } from 'ruse-fetch'
const Users = () => {
const users = useFetch('https://reqres.in/api/users')
return (
<ul>
{users.data.map((u) => (
<li key={u.id}>u.first_name</li>
))}
</ul>
)
}
const Home = () => {
return (
<section>
...
<Suspense fallback={<span>Loading...</span>}>
<Users>
</Suspense>
...
</section>
)
}
To maintain a structured and scalable Redux store in your application, follow this setup.
Inside the store directory, use the slices folder where all your Redux slices will be stored. Then, import all slices into the central reducers file.
This ensures that Universal will automatically recognize all slice types and include them in the store, providing full type safety.
With useAppSelector
, you can access the fully-typed Redux store, including elements provided by Universal.
import { updateIntl, useAppDispatch, useAppSelector } from 'universal-scripts'
import locales from 'src/locales'
function SelectLanguage() {
const locale = useAppSelector((state) => state.intl.lang)
const dispatch = useAppDispatch()
const changeLang = (event) => {
const lang = event.target.value
dispatch(
updateIntl({
lang,
messages: locales[lang]
})
)
}
return (
<select value={locale} onChange={changeLang}>
{Object.keys(locales).map((lang) => (
<option key={lang} value={lang}>
{lang.toUpperCase()}
</option>
))}
</select>
)
}
Environment variables are declared in the .env file. These variables are not included in the generated build by default, ensuring that sensitive information is not stored in the build. The variables are read during the application startup and are sent from the server to the client. Only variables that start with PUBLIC_
are passed from the server to the client. If server-side rendering (SSR) is disabled, the variables are still sent to the client in the same way.
If you modify the .env
file in development, Universal will automatically perform a hot reload with the updated variable values. In production mode, you only need to restart the app to apply the new variables—there’s no need to rebuild the app to see the changes.
This section explains how the main folders work in Universal. The core is built around js.conf.d
, which allows us to split the configuration into multiple files. This approach makes it possible to create new configurations or even override the built-in ones.
-
build.conf.d
– Contains everything related to the Webpack bundling process. -
runtime.conf.d
– Manages configurations related to the runtime of the application, such as redux, render.... -
lib
– Provides common functionality and utilities. -
scripts
– Contains scripts defined in thescripts
section ofpackage.json
, used for automation and task execution. -
server
– The main entry point for the server, containing all configurations for Express and middleware setup. -
client
– The main entry point for the client-side application.
With this structure configurations in this way, Universal enables modular, maintainable, and customizable setups. 🚀
Check out the documentation to explore all features or follow the getting started guide.
For common use cases, support has been added to define configuration in a universal.config.mjs
file located at the root of your application.
You can export a plugins
object to customize specific plugin options, and a default
export for the main Universal configuration.
Currently, the following options are supported:
-
noSsr
: Disables server-side rendering. The server will return a minimal HTML file that only loads the client scripts. -
extraBuilds
: An array of strings representing the names of additional builds to include.