Skip to content

Commit

Permalink
docs
Browse files Browse the repository at this point in the history
  • Loading branch information
nksaraf committed Mar 2, 2024
1 parent b79fd7d commit f6e16f9
Show file tree
Hide file tree
Showing 4 changed files with 195 additions and 21 deletions.
80 changes: 68 additions & 12 deletions docs/guide/a-story.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,55 @@
# Build your server
# A story

## The beginning

Create a `app.config.js` file in the root of your project and add the following:
In a new directory, create a `package.json` for your project,

```json [package.json]
{
"name": "my-app",
"type": "module",
"private": true,
"scripts": {
"dev": "vinxi dev",
"build": "vinxi build",
"start": "vinxi start"
},
"dependencies": {
"vinxi": "0.3.8"
}
}
```

```ts [app.config.js]
And run `npm install` to install the dependencies.

```bash [npm]
npm install
```

Create a `app.config.ts` file in the root of your project and add the following:

::: code-group

```ts [app.config.ts]
import { createApp } from "vinxi";

export default createApp();
```

:::

You are ready to start your app in development mode now,

```bash [npm]
npm run dev
```

::: warning

You will see an error in the browser if you go to `http://localhost:3000/` right now. Your app doesn't have anything to show right now. Don't worry, we will get there.

:::

## A static file server

A simple web server typically serves static files from a directory on disk. Let's add a `public` directory and serve it's contents:
Expand Down Expand Up @@ -72,12 +112,14 @@ We need to add the script to the `index.html` file for the browser to actually f
</html>
```

info
::: info

Note how we can use `/app.js` to refer to the `/public/app.js` file from the `index.html` file. This is because we have set the `base` to `/` in the router config. This means that all the files in the `public` directory are served at the routes corresponding to their paths excluding the `public` part, `/public/app.js` is served at `/app.js`.

If we had set the `base` to `/static`, then the `/public/app.js` file would be served at `/static/app.js`. But so would the `public/index.html`, and that would be a problem. We will deal with that problem later. But its usually a good idea to set the `base` to `/` for the `static` mode. so that people's expectations are met regarding the routes of the files in the `public` directory.

:::

You can now open the browser console and see the message.

But still, there's nothing you can do on the app. Let's add a button.
Expand All @@ -91,7 +133,7 @@ But still, there's nothing you can do on the app. Let's add a button.
</head>
<body>
<h1>Hello World</h1>
<button id="my-buttton">Click Me</button>
<button id="my-button">Click Me</button>
<script src="/app.js"></script>
</body>
</html>
Expand Down Expand Up @@ -120,7 +162,7 @@ document.getElementById("my-button").addEventListener("click", () => {
</head>
<body>
<h1>Hello World</h1>
<button id="my-buttton">Click Me</button>
<button id="my-button">Click Me</button>
<script src="/app.js"></script>
</body>
</html>
Expand All @@ -138,7 +180,7 @@ Okay, this is getting fun. Lets add some styles.
</head>
<body>
<h1>Hello World</h1>
<button id="my-buttton">Click Me</button>
<button id="my-button">Click Me</button>
<script src="/app.js"></script>
</body>
</html>
Expand All @@ -161,7 +203,7 @@ Ahh, I don't like that background color. Needs more pop. Let's change it to a ni

```css [public/app.css]
body {
background-color: #0000ff;
background-color: #000022;
color: #fff;
}
```
Expand Down Expand Up @@ -208,7 +250,7 @@ Let's refresh the page again (I know, I know, it's annoying). Click the button.
</head>
<body>
<h1>Hello World</h1>
<button id="my-buttton">Click Me</button>
<button id="my-button">Click Me</button>
<script type="module" src="/app.js"></script>
</body>
</html>
Expand All @@ -229,7 +271,7 @@ Before we go down this path, I discovered some other problems faced here:
- If I want to write typescript, I need to add a transpile step for the browser to understand it.
- If I want to use React, Vue, etc. I need to add a transpile step for the browser to understand it.

This is just the tip of the iceberg for thr problems faced with working with bare HTML, CSS and JS. We want to write the code this way. But the browser only understands a certain way of doing things. We need to bridge the gap between the two. This is where Vite comes in. It's a tool that bridges the gap between the way we want to write code and the way the browser understands code. It does this by providing a development server runtime that transforms our code to a format the browser understands. It also provides a builder that transforms our code to a production ready format with a lot of optimizations. It also provides a plugin API that allows us to customize the development server and builder.
This is just the tip of the iceberg for thr problems faced with working with bare HTML, CSS and JS. We want to write the code this way. But the browser only understands a certain way of doing things. We need to bridge the gap between the two. This is where Vite comes in. It's a tool that bridges the gap between the way we want to write code and the way the browser understands code. It does this by providing a development server runtime that transforms our code to a format the browser understands. It also provides a builder that transforms our code to a production ready format with a lot of optimizations. And lasty, it provides a plugin API that allows us to customize the development server and builder.

`vinxi` comes with a built-in Vite development server and builder. Let's use it.

Expand All @@ -256,9 +298,23 @@ export default createApp({
});
```

We will move the files from the `public` directory to the root of the project. Let's run the dev server again.
We will move the files from the `public` directory to the root of the project. Refresh again now.

Some of our problems have now been solved. Change something in the JavaScript file. The browser will automatically reload. Install a `npm` package and use it in your code. The browser will know what to do. Change to typescript, install React, Vue, etc. The browser will know what to do. Because vite tells it.

For the CSS to be processed by vite, we need to import it in the javascript file. Let's do that.

```ts [app.js]
import confetti from "canvas-confetti";

import "./app.css";

document.getElementById("my-button").addEventListener("click", () => {
confetti();
});
```

All our problems have now been solved. Change something in the CSS. or the JavaScript file. The browser will automatically reload. Install a node-module and use it in your code. The browser will know what to do. Change to typescript, install React, Vue, etc. The browser will know what to do. Because vite tells it.
Now, changes in the CSS file will be instantly reflected in the browser without a refresh.

Okay now that we all this power, lets thing bigger. What if we sent an email when the button is clicked. We can use the `nodemailer` package to do that. Let's install it.

Expand Down
110 changes: 109 additions & 1 deletion docs/guide/add-to-existing-vite-app.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,111 @@
# Add to existing Vite app

(Coming Soon)
While vite is amazing as a devkit for client-side web applications, it requires some setup to use the server in the same application. The funny part is that there is a server running both in dev and prod, its just that you don't get access to it.

Vinxi gives you the ability to add server-side functionality (SSR) to an existing Vite app.

A typical `vite` app is a single-page application, with an `index.html` file, a `public` directory and a `vite.config.ts` file.

Lets install `vinxi` to get started:

```bash [npm]
npm install vinxi
```

The first step is to make your `vite` app into a `vinxi` app. You don't need to create any new files. Vinxi works with `vite.config.ts` files too. You just need to change what you export from the file.

Here is an example of a `vite.config.ts` file that exports the same `vite` app as a `vinxi` app:

```ts twoslash
import { createApp } from "vinxi";
import { config } from "vinxi/plugins/config";

export default createApp({
routers: [
{
name: "public",
type: "static",
dir: "./public",
},
{
name: "client",
type: "spa",
handler: "./index.html",
base: "/",
plugins: () => [
config("custom", {
// additional vite options
}),
// additional vite plugins
],
},
],
});
```

Now running `npm run dev` will start the Vinxi dev server and you will get the same experience as you did with `vite`.

The only difference is that you can now add server-side functionality to your app, and much more. Let's see how.

Let's imagine we need to send an email when a user submits a form. We can use the `nodemailer` package to do that. Let's install it.

```bash[npm]
npm install nodemailer
```

```bash[yarn]
yarn add nodemailer
```

```bash[pnpm]
pnpm add nodemailer
```

But `nodemailer` is not something you can use in the browser. You need to run it in `node` (on the server). So we need some kind of API routes. In `vinxi`, you can add a server handler for an API to your app.

```ts
import { createApp } from "vinxi";

export default createApp({
routers: [
{
name: "public",
type: "static",
dir: "./public",
},
{
name: "client",
type: "spa",
handler: "./index.html",
base: "/",
plugins: () => [
config("custom", {
// additional vite options
}),
// additional vite plugins
],
},
{
name: "api",
type: "http",
handler: "./api.ts",
base: "/api",
},
],
});
```

```ts [api.ts]
import nodemailer from "nodemailer";
import { eventHandler } from "vinxi/http";

export default eventHandler(async (event) => {
await nodemailer.sendMail({
from: "",
});

return "done";
});
```

You can now hit `http://localhost:3000/api` from your frontend to send an email.
2 changes: 2 additions & 0 deletions docs/guide/create-your-first-app.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Create your first app

Vinxi helps you build the full spectrum of applications with javascript, be it a static site, SPA, just an API or a fully featured SSR'ed and hydrated application.

### React SSR

```ts
Expand Down
24 changes: 16 additions & 8 deletions packages/vinxi/bin/cli.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,13 @@ const command = defineCommand({
watcher.on("all", async (ctx, path) => {
log(c.dim(c.green("change detected in " + path)));
log(c.dim(c.green("reloading app")));
const newApp = await loadApp(configFile, args);
if (!newApp) return;
restartDevServer(newApp);
try {
const newApp = await loadApp(configFile, args);
if (!newApp) return;
restartDevServer(newApp);
} catch (e) {
console.error(e)
}
});
}
async function createKeypressWatcher() {
Expand Down Expand Up @@ -155,12 +159,16 @@ const command = defineCommand({
fsWatcher.on("all", async (path) => {
log(c.dim(c.green("change detected in " + path)));
log(c.dim(c.green("reloading app")));
const newApp = await loadApp(configFile, args);
if (!newApp) return;
try {
const newApp = await loadApp(configFile, args);
if (!newApp) return;

fsWatcher.close();
createWatcher();
restartDevServer(newApp);
fsWatcher.close();
createWatcher();
restartDevServer(newApp);
} catch (e) {
console.error(e)
}
});
return;
}
Expand Down

0 comments on commit f6e16f9

Please sign in to comment.