Skip to content

Commit

Permalink
Refactor, cleanup, and prepare for JSR (#81)
Browse files Browse the repository at this point in the history
* Refactor, cleanup, and prepare for JSR

* Cleanup and add notices about being a WIP

* Improve logging for build errors

* Make build use file path

* Use toFileUrl to bypass file:// replacement

* Fix default build/dev tasks
  • Loading branch information
KyleJune authored Jul 28, 2024
1 parent 64571c6 commit 16cf0f4
Show file tree
Hide file tree
Showing 49 changed files with 4,336 additions and 2,220 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ jobs:
DENO_DIR: ${{ needs.variables.outputs.DENO_DIR }}
steps:
- name: Clone repository
uses: actions/checkout@v3.3.0
uses: actions/checkout@v4
- name: Setup deno
uses: denoland/setup-deno@main
with:
Expand Down Expand Up @@ -110,7 +110,7 @@ jobs:
&& needs.variables.outputs.HAS_CODECOV_TOKEN
run: deno coverage --lcov cov > cov.lcov
- name: Upload coverage
uses: codecov/codecov-action@v3
uses: codecov/codecov-action@v4
with:
files: ${{ inputs.working-directory }}/cov.lcov
token: ${{ secrets.CODECOV_TOKEN }}
Expand Down
Empty file modified .github/workflows/main.yml
100755 → 100644
Empty file.
16 changes: 16 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
name: publish

on:
push:
branches:
- main

jobs:
publish:
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@v4
- run: npx jsr publish
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
# VSCode
.vscode/*.log

# WIP
test-utils.tsx
6 changes: 2 additions & 4 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,11 @@
"deno.lint": true,
"deno.unstable": false,
"deno.config": "./deno.jsonc",
"deno.importMap": "./import_map.json",
"deno.suggest.imports.hosts": {
"https://deno.land": true
},
"files.associations": {
"*.css": "tailwindcss"
},
"editor.formatOnSave": true,
"editor.defaultFormatter": "denoland.vscode-deno",
"editor.quickSuggestions": {
"strings": true
}
Expand Down
109 changes: 54 additions & 55 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
# Udibo React App

[![release](https://img.shields.io/badge/release-0.19.0-success)](https://github.com/udibo/react_app/releases/tag/0.19.0)
[![deno doc](https://doc.deno.land/badge.svg)](https://deno.land/x/[email protected])
[![CI/CD](https://github.com/udibo/react_app/actions/workflows/main.yml/badge.svg)](https://github.com/udibo/react_app/actions/workflows/main.yml)
[![codecov](https://codecov.io/gh/udibo/react_app/branch/main/graph/badge.svg?token=G5XCR01X8E)](https://codecov.io/gh/udibo/react_app)
[![license](https://img.shields.io/github/license/udibo/react_app)](https://github.com/udibo/react_app/blob/main/LICENSE)
[![JSR](https://jsr.io/badges/@udibo/react-app)](https://jsr.io/@udibo/react-app)
[![JSR Score](https://jsr.io/badges/@udibo/react-app/score)](https://jsr.io/@udibo/react-app)
[![CI/CD](https://github.com/udibo/react-app/actions/workflows/main.yml/badge.svg)](https://github.com/udibo/react-app/actions/workflows/main.yml)
[![codecov](https://codecov.io/gh/udibo/react-app/branch/main/graph/badge.svg?token=G5XCR01X8E)](https://codecov.io/gh/udibo/react-app)
[![license](https://img.shields.io/github/license/udibo/react-app)](https://github.com/udibo/react-app/blob/main/LICENSE)

**NOTICE**: This is a WIP, not ready for use yet.

A [React](https://reactjs.org/) Framework for [Deno](https://deno.land) that
makes it easy to create highly interactive apps that have server side rendering
with file based routing for both your UI and API.
makes it easy to create highly interactive applications that have server side
rendering with file based routing for both your UI and API.

Apps are created using [React Router](https://reactrouter.com),
[React Helmet Async](https://www.npmjs.com/package/react-helmet-async), and
Expand All @@ -29,57 +31,62 @@ Apps are created using [React Router](https://reactrouter.com),

## Usage

This module has 2 entry points.

- [mod.tsx](https://deno.land/x/[email protected]/mod.tsx): For use in code
that will be used both on the server and in the browser.
- [server.tsx](https://deno.land/x/[email protected]/server.tsx): For use
in code that will only be used on the server.

You can look at the [examples](#examples) and
[deno docs](https://deno.land/x/[email protected]) to learn more about
usage.
You can look at the [examples](#examples) and documentation on JSR.io to learn
more about usage.

### Examples

**NOTICE**: The examples in separate repositories have not been updated yet.

This repository contains one example for manually testing changes. To use it as
the base for a new project, you would need to update the `import_map.json` file
and deno.jsonc file to use udibo_react_app from the deno.land/x registry. The
deno task commands in `deno.jsonc` would need to also use your
`import_map.json`.
the base for a new project, you would need to update the `deno.jsonc` file to
use @udibo/react-app from the jsr.io. It's recommended to just fork one of the
many example repositories. The one linked below is the same as the one in the
example directory.

- [Example](https://github.com/udibo/react_app_example): A basic example of a
Udibo React App.
- [Example](https://github.com/udibo/react-app-example): A basic example.

The following examples are forks of the first example. They demonstate how easy
it is to extend Udibo React Apps. The README.md file in each of them describes
how it was done.

- [Twind Example](https://github.com/udibo/react_app_example_twind): A basic
example of a [Udibo React App](https://deno.land/x/udibo_react_app) using
[Twind](https://twind.style/) to add Tailwind v3 support.
- [React Query Example](https://github.com/udibo/react_app_example_react_query):
A basic example of a [Udibo React App](https://deno.land/x/udibo_react_app)
using [React Query](https://tanstack.com/query/latest) for asyncronous state
management.
- [Tailwindcss Example](https://github.com/udibo/react-app-example_tailwindcss):
A basic example using
[esbuild-plugin-postcss](https://github.com/deanc/esbuild-plugin-postcss) to
add Tailwindcss.
- [React Query Example](https://github.com/udibo/react-app-example-react-query):
A basic example using [React Query](https://tanstack.com/query/latest) for
asyncronous state management.

### Tasks

To run the tests, use `deno task test` or `deno task test-watch`.

To check formatting and run lint, use `deno task check`.

To create a build and to run the build, use `deno task build` and
`deno task run`. By default, the application builds and runs in development
mode. To build and run a production build, set the `APP_ENV` environment
variable to `production`.
The following 2 commands can be used for creating builds.

- `deno task build-dev`: Builds the application in development mode.
- `deno task build-prod`: Builds the application in production mode.

A build must be generated before you can run an application. You can use the
following 2 commands to run the application.

- `deno task run-dev`: Runs the application in development mode.
- `deno task run-prod`: Runs the application in production mode.

To run the application in development mode with live reloading, use
`deno task dev`.

When in development, identifiers are not minified and sourcemaps are generated
and linked.

The commands ending in `-dev` and `-prod` set the `APP_ENV` and `NODE_ENV`
environment variables. The `NODE_ENV` environment variable is needed for react.
If you use the `deno task build` or `deno task run` tasks, you should make sure
that you set both of those environment variables. Those environment variables
are also needed if you deploy to Deno Deploy.

### Deployment

The GitHub workflows in this project can be used to run the tests and deploy
Expand All @@ -103,8 +110,8 @@ of the example in this repository. The Helmet in the main route of a directory
will apply to all routes within the directory.

```tsx
import { Helmet } from "npm/react-helmet-async";
// ...
import { Helmet } from "react-helmet-async";

<Helmet
defaultTitle="Example"
titleTemplate="Example | %s"
Expand Down Expand Up @@ -175,8 +182,9 @@ parameters are stored on the context's params property. The key for wildcard
parameters will be "0".

```ts
import { Router } from "x/oak/mod.ts";
import { AppState } from "x/udibo_react_app/app_server.tsx";
import { Router } from "@udibo/react-app/server";

import { AppState } from "../state.ts";

export default new Router<AppState>()
.get("/", async (context) => {
Expand All @@ -200,7 +208,7 @@ Here is an example of an simple ErrorFallback. If you'd like to use it as is,
it's exported as DefaultErrorFallback.

```ts
import { FallbackProps } from "x/udibo_react_app/mod.tsx";
import { FallbackProps } from "@udibo/react-app";

// ...

Expand Down Expand Up @@ -269,23 +277,14 @@ routes directory. Those files are generated during the build process.
- `_main.tsx`: Exports a React Router route object that connects all your React
component files together.

### Import map

Deno has support for npm modules, however deno deploy doesn't yet. Because of
that, the import map currently imports all npm modules from esm.sh. To ensure
all npm dependencies are using the same version of react, they need to have
their version pinned. Once Deno Deploy has npm support, I'll switch from using
esm.sh to npm specifier imports.

### Disabling server side rendering

All pages will be rendered server side by default. If you have a component you
don't want to render on the server, you can disable it by having it return the
fallback on the server. You can use `isServer()` to determine if the code is
running on the server or in the browser. For example, in
[example/routes/blog](example/routes/blog), you could have it only get the post
when rendering in the browser by setting post to undefined when on the server
like shown below.
running on the server or in the browser. In the example's blog, you could have
it only get the post when rendering in the browser by setting post to undefined
when on the server like shown below.

```tsx
const post = isServer() ? undefined : getPost(id);
Expand Down Expand Up @@ -316,10 +315,10 @@ The actual example currently does render the post on the server.

To render a route that loads data on the server, you can add a matching Oak
router that will cache the information being fetched before rendering the
application. The example in this repository uses the AppContext to store the
cached responses but that's not the only way to do it. It's recommended that you
use a library like [React Query](https://tanstack.com/query/latest) to get your
data.
application. The example in this repository uses the application's initial state
to store the cached responses but that's not the only way to do it. It's
recommended that you use a library like
[React Query](https://tanstack.com/query/latest) to get your data.

## Contributing

Expand Down
Loading

0 comments on commit 16cf0f4

Please sign in to comment.