Skip to content

Commit

Permalink
feat: @hono/vite-build (#177)
Browse files Browse the repository at this point in the history
* feat: `@hono/vite-build`

* `statiRoot`

* add adapters

* update

* tweak

* remove not used files

* vitest/globals

* update readme

* add changeset

* add CI

* look dist dir

* update gitignore

* update readme

* make it as `major` release
  • Loading branch information
yusukebe committed Sep 15, 2024
1 parent 3e7b78c commit 1ceb957
Show file tree
Hide file tree
Showing 27 changed files with 1,465 additions and 3 deletions.
5 changes: 5 additions & 0 deletions .changeset/honest-adults-complain.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@hono/vite-build': major
---

Initial release
38 changes: 38 additions & 0 deletions .github/workflows/ci-build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: ci-build
on:
push:
branches: [main]
paths:
- 'packages/build/**'
pull_request:
branches: ['*']
paths:
- 'packages/build/**'

jobs:
ci:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./packages/build
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20.x
- run: yarn install
- run: yarn build
- run: yarn test

ci-windows:
runs-on: windows-latest
defaults:
run:
working-directory: ./packages/build
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20.x
- run: yarn install
- run: yarn test
221 changes: 221 additions & 0 deletions packages/build/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
# @hono/vite-build

`@hono/vite-build` is a set of Vite plugins for building Hono applications with Vite. It supports multiple runtimes and platforms, allowing you to build a project that includes JavaScript files for these platforms from a Hono app.

Here are the modules included:

- `@hono/vite-build/base`
- `@hono/vite-build/cloudflare-pages`
- `@hono/vite-build/cloudflare-workers`
- `@hono/vite-build/bun`
- `@hono/vite-build/node`

## Usage

### Install

You can install `vite` and `@hono/vite-build` via the npm.

```bash
npm i -D vite @hono/vite-build
```

Or you can install them with Bun.

```bash
bun add -D vite @hono/vite-build
```

### Settings

Add `"type": "module"` to your package.json. Then, create `vite.config.ts` and edit it. The following is for Bun.

```ts
import { defineConfig } from 'vite'
import build from '@hono/vite-build/bun'
// import build from '@hono/vite-build/cloudflare-pages'
// import build from '@hono/vite-build/cloudflare-workers'
// import build from '@hono/vite-build/node'

export default defineConfig({
plugins: [
build({
// Defaults are `src/index.ts`,`./src/index.tsx`,`./app/server.ts`
entry: './src/index.tsx',
}),
],
})
```

### Build

Just run `vite build`.

```bash
npm exec vite build
```

Or

```bash
bunx --bun vite build
```

### Run

Run with the command on your runtime. For examples:

Cloudflare Pages:

```bash
wrangler pages dev ./dist
```

Bun:

```bash
cd ./dist
bun run ./index.js
```

Node.js:

```bash
cd ./dist
node ./index.js
```

## Common Options

```ts
type BuildOptions = {
entry?: string | string[]
output?: string
outputDir?: string
external?: string[]
minify?: boolean
emptyOutDir?: boolean
}
```
Default values:
```ts
export const defaultOptions = {
entry: ['src/index.ts', './src/index.tsx', './app/server.ts'],
output: 'index.js',
outputDir: './dist',
external: [],
minify: true,
emptyOutDir: false,
staticPaths: [],
}
```

## Platform specific things

### Cloudflare Pages

This plugin generates `_routes.json` automatically. The automatic generation can be overridden by creating a `public/_routes.json`. See [Create a `_routes.json` file](https://developers.cloudflare.com/pages/functions/routing/#create-a-_routesjson-file) on Cloudflare Docs for more details.

## Example project

`src/index.tsx`:

```tsx
import { Hono } from 'hono'

const app = new Hono()

app.get('/', (c) => {
return c.html(
<html>
<head>
<link href='/static/style.css' rel='stylesheet' />
</head>
<body>
<h1>Hello!</h1>
</body>
</html>
)
})

export default app
```

`public/static/style.css`:

```css
h1 {
font-family: Arial, Helvetica, sans-serif;
}
```

The project with those file will be built to the following files with `@hono/vite-build/bun`:

```txt
dist
├── index.js
└── static
└── style.css
```

## Build a client

If you also want to build a client-side script, you can configure it as follows.

```ts
export default defineConfig(({ mode }) => {
if (mode === 'client') {
return {
build: {
rollupOptions: {
input: './src/client.ts',
output: {
dir: './dist/static',
entryFileNames: 'client.js',
},
},
copyPublicDir: false,
},
}
} else {
return {
plugins: [build()],
}
}
})
```

The build command:

```bash
vite build --mode client && vite build
```

`import.meta.env.PROD` is helpful in detecting whether it is in development or production mode if you are using it on a Vite dev server.

```tsx
app.get('/', (c) => {
return c.html(
<html>
<head>
{import.meta.env.PROD ? (
<script type='module' src='/static/client.js'></script>
) : (
<script type='module' src='/src/client.ts'></script>
)}
</head>
<body>Hello!</body>
</html>
)
})
```

## Authors

- Yusuke Wada <https://github.com/yusukebe>

## License

MIT
85 changes: 85 additions & 0 deletions packages/build/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
{
"name": "@hono/vite-build",
"description": "Vite plugin to build your Hono app",
"version": "0.0.0",
"types": "dist/index.d.ts",
"module": "dist/index.js",
"type": "module",
"scripts": {
"test": "vitest --run",
"build": "rimraf dist && tsup && publint",
"watch": "tsup --watch",
"prerelease": "yarn build",
"release": "yarn publish"
},
"files": [
"dist"
],
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js"
},
"./bun": {
"types": "./dist/adapter/bun/index.d.ts",
"import": "./dist/adapter/bun/index.js"
},
"./node": {
"types": "./dist/adapter/node/index.d.ts",
"import": "./dist/adapter/node/index.js"
},
"./cloudflare-pages": {
"types": "./dist/adapter/cloudflare-pages/index.d.ts",
"import": "./dist/adapter/cloudflare-pages/index.js"
},
"./cloudflare-workers": {
"types": "./dist/adapter/cloudflare-workers/index.d.ts",
"import": "./dist/adapter/cloudflare-workers/index.js"
}
},
"typesVersions": {
"*": {
"types": [
"./dist/types"
],
"bun": [
"./dist/adapter/bun/index.d.ts"
],
"node": [
"./dist/adapter/node/index.d.ts"
],
"cloudflare-pages": [
"./dist/adapter/cloudflare-pages/index.d.ts"
],
"cloudflare-workers": [
"./dist/adapter/cloudflare-workers/index.d.ts"
]
}
},
"author": "Yusuke Wada <[email protected]> (https://github.com/yusukebe)",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/honojs/vite-plugins.git"
},
"publishConfig": {
"registry": "https://registry.npmjs.org",
"access": "public"
},
"homepage": "https://github.com/honojs/vite-plugins",
"devDependencies": {
"glob": "^10.3.10",
"hono": "^4.6.1",
"publint": "^0.1.12",
"rimraf": "^5.0.1",
"tsup": "^7.2.0",
"vite": "^5.4.5",
"vitest": "^2.1.1"
},
"peerDependencies": {
"hono": "*"
},
"engines": {
"node": ">=18.14.1"
}
}
32 changes: 32 additions & 0 deletions packages/build/src/adapter/bun/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import type { Plugin } from 'vite'
import type { BuildOptions } from '../../base.js'
import buildPlugin from '../../base.js'
import { serveStaticHook } from '../../entry/serve-static.js'

export type BunBuildOptions = {
staticRoot?: string | undefined
} & BuildOptions

const bunBuildPlugin = (pluginOptions?: BunBuildOptions): Plugin => {
return {
...buildPlugin({
...{
entryContentBeforeHooks: [
async (appName, options) => {
// eslint-disable-next-line quotes
let code = "import { serveStatic } from 'hono/bun'\n"
code += serveStaticHook(appName, {
filePaths: options?.staticPaths,
root: pluginOptions?.staticRoot,
})
return code
},
],
},
...pluginOptions,
}),
name: '@hono/vite-build/bun',
}
}

export default bunBuildPlugin
Loading

0 comments on commit 1ceb957

Please sign in to comment.