That helps you build faster and cleaner
It includes esbuild, React Router, server-side rendering, production server, and backend optimization.
Remix is a full-stack web framework that focuses on the user interface and works back through web fundamentals to deliver a fast, slick, and resilient user experience.
Since the formal release on October 2021, Remix has gained steam to be a widely adopted React framework.
Remix comes with a number of advantages:
- It performs dynamic server-side rendering.
- It knows when to refetch mutated data, as Remix oversees the whole workflow.
- It includes an end-to-end solution with React Router, server-side rendering, production server, and backend optimization.
Run the following command to install Remix:
% npx create-remix
npx: installed 210 in 10.198sR E M I X - v1.2.3💿 Welcome to Remix! Let's get you set up with a new project.? Where would you like to create your app? remix-app
? Where do you want to deploy? Choose Remix if you're unsure, it's easy to change deployment targets. Remix App Server
? Do you want me to run `npm install`? Yes
There are a few choices during the installation.
- The Remix framework is installed in the folder,
- There are a number of servers to choose from. The choices are
Remix App Server,
Architect (AWS Lambda),
Cloudflare Pages. We use the default,
Remix App Serverwhich is a full-featured Node.js server based on Express.
After the installation, the folder,
remix-applooks like this:
│ ├── entry.client.jsx
│ ├── entry.server.jsx
│ ├── root.jsx
│ └── routes
│ └── index.jsx
│ └── favicon.ico
app/root.jsx: It is the root component for the application. It is equivalent to Create React App’s
<LiveReload />(line 27) is explicitly coded, which is recommended for development.
app/routes: It is the directory that hosts all routes.
app/routes/index.jsx: It is the indexed route that is invoked by default.
public: It is the directory that hosts static assets and the production build.
public/favicon.ico: It is the Remix icon displayed for the browser tab and bookmark.
remix.config.js: It is the Remix configuration file.
The app can be executed in the develop mode:
npm run dev
It can also be executed in the production mode:
npm run build
Out of the box, we have React Router, server-side rendering, and production server.
The above official example has static links to external websites. Write
app/routes/index.jsx to link to internal pages.
Line 9 is a link to the route,
Line 12 is a link to the route,
The page looks fine.
But, clicking on either of the links shows a 404 error.
Remix Router uses the file system to define page routes. There are two ways to handle this. The recommended way is to implement the missing page inside the route directory as an index file, ie
Now the page works:
The second way is to name the file as the route, ie,
Here is the page:
Remix Router supports React Router, including nested routes and dynamic parameters.
In Remix, most of the routes are composed of APIs and UI components. APIs interact with the backend, while UI components are displayed in the browser. Remix APIs simplify and optimize interactions with the backend, including how to get data into components and when to perform data mutations.
loader function is a special API. It is exported to be called on the server before rendering. It typically fetches data from the backend.
Then, UI components render the page using the loaded data via the hook,
We have written an article, Set Up and Use MySQL in Create React App Environment. Let’s see how easy it is to set up and use MySQL in the Remix environment.
npm i mysql
mysql becomes part of
app/routes/index.jsx to be the following:
Lines 4–9 define the user configuration.
Lines 11–13 create MySQL connection using the user configuration. Line 12 enables multiple statements, which are disabled by default to avoid possible SQL injection attacks.
Lines 15–25 define the
loader function, which connects to the database to query the student table (line 16). If there is an error, the promise is resolved to
null (line 19). Otherwise, the first row of the MySQL table is returned (line 22), assuming that there is at least one row.
Line 28 calls
useLoaderData to retrieve the loaded data, which is rendered at line 33.
There is no need to restart the server.
npm run dev is similar to
nodemonwhich automatically monitors the code changes and rebuilds the changes.
However, there is an error on the browser console:
What a cryptic error message!
This error occurs when the server-side dependencies get bundled in the client scripts.
In order for Remix to run the app in both the server and browser environments, application modules and third-party dependencies you need to be careful about module side effects. The Remix compiler automatically removes server code from the browser bundles. In the above code, lines 11–13 create MySQL connection, which is the server code. The
loader is gone but the
mysql dependency stayed. The browser cannot handle the
mysql module properly.
To fix this, remove the side effect by simply moving the code inside the
loader function, along with the user configuration.
It works now.
But, are we going to create a MySQL connection every time the
loader function is called?
A better way is to create a MySQL connection inside
app/entry.server.jsx (lines 30–32):
app/routes/index.jsx simply imports the
connection (line 2):
<Form> component is a declarative way to perform data mutations: creating, updating, and deleting data. Remix’s
Form is an enhanced HTML form component. Instead of using React event handlers, such as
onClickthe route exports the
action function that is called upon form submission.
useState is not needed to maintain field values.
Similar to the
loader function, there is the
action function, which is invoked upon form submission. Similar to the hook,
userLoaderDatathere is a hook for the
useActionDatawhich captures the returned data from the
useActionData to build up our example with the ability of modifying the student’s grade.
Here is the adapted
Lines 17–33 define the
action function, which reads the form submission data (lines 18–19) and connects to the database to update the student table (line 22). If there is an error, the promise is resolved to an error message (line 26). Otherwise, it returns a successful message (line 28).
Line 37 calls
useActionData to retrieve the action result, which is rendered at line 50.
Form component is added at lines 44–49.
Save the changes, and type
4 in the input field. Upon hitting enter, the value is sent to
action to update the database. Remix detects data mutation and calls
loader to retrieve the latest value to be displayed.
If the input is invalid, the error message is displayed.
The flow between
Remix App Server and the backend is seamless. No boilerplate code is needed.
We have gone through how to use Remix. It has a lot of advantages, and the most noticeable one is speed — It is fast to load the page in the browser, and it is fast to develop the end-to-end application. Remix is a full-stack Web framework that includes esbuild, React Router, server-side rendering, production server, and backend optimization.
We have written about these features in a number of articles. With Remix, they are all available, boilerplate-free.
Any disadvantages to Remix?
Yes, Remix is still new. Error reporting needs improvement. For example, if we want a server on an occupied port, it does not report an error or suggest a different port. When it reports errors, some error messages are too cryptic.
Regardless, Remix has gained steam to be a widely adopted React framework.
Thanks for reading. I hope this was helpful.