惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

P
Proofpoint News Feed
Microsoft Azure Blog
Microsoft Azure Blog
Jina AI
Jina AI
博客园_首页
宝玉的分享
宝玉的分享
The Cloudflare Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
量子位
T
Tailwind CSS Blog
雷峰网
雷峰网
Blog — PlanetScale
Blog — PlanetScale
Last Week in AI
Last Week in AI
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Hugging Face - Blog
Hugging Face - Blog
月光博客
月光博客
罗磊的独立博客
F
Fortinet All Blogs
酷 壳 – CoolShell
酷 壳 – CoolShell
Stack Overflow Blog
Stack Overflow Blog
J
Java Code Geeks
V
V2EX
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
The GitHub Blog
The GitHub Blog
Apple Machine Learning Research
Apple Machine Learning Research
博客园 - 聂微东
U
Unit 42
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
D
Docker
阮一峰的网络日志
阮一峰的网络日志
I
InfoQ
Simon Willison's Weblog
Simon Willison's Weblog
D
DataBreaches.Net
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
I
Intezer
Scott Helme
Scott Helme
B
Blog
M
MIT News - Artificial intelligence
K
Kaspersky official blog
H
Help Net Security
V
Vulnerabilities – Threatpost
C
CXSECURITY Database RSS Feed - CXSecurity.com
Engineering at Meta
Engineering at Meta
博客园 - 【当耐特】
L
Lohrmann on Cybersecurity
P
Privacy & Cybersecurity Law Blog
Project Zero
Project Zero
The Hacker News
The Hacker News
B
Blog RSS Feed
T
Tor Project blog

Deno

Deno 2.8 | Deno Claw Patrol: an open-source security firewall for agents | Deno Fresh 2.3: Zero JS by default, View Transitions, and Temporal support | Deno Deno 2.7: Temporal API, Windows ARM, and npm overrides | Deno Build a dinosaur runner game with Deno, pt. 6 | Deno Build a dinosaur runner game with Deno, pt. 5 | Deno Deno Deploy is Generally Available | Deno Introducing Deno Sandbox | Deno Build a dinosaur runner game with Deno, pt. 4 | Deno Build a dinosaur runner game with Deno, pt. 3 | Deno Build a dinosaur runner game with Deno, pt. 2 | Deno React / Next.js Denial-of-Service Vulnerability: Deno Deploy users protected | Deno Deno 2.6: dx is the new npx | Deno Build a dinosaur runner game with Deno, pt. 1 | Deno React Server Functions / Next.js Vulnerability: Deno Deploy users protected | Deno My highlights from the new Deno Deploy | Deno Deno's Other Open Source Projects | Deno How Deno protects against npm exploits | Deno Help Us Raise $200k to Free JavaScript from Oracle | Deno Deno 2.5: Permissions in the config file | Deno Fresh 2.0 Graduates to Beta, Adds Vite Support | Deno Deno 2.4: deno bundle is back | Deno JavaScript™ Trademark Update | Deno What's coming to JavaScript | Deno A brief history of JavaScript | Deno Reports of Deno's Demise Have Been Greatly Exaggerated | Deno An Update on Fresh | Deno How Plaid migrated 100 services to a new database platform 5x faster with Deno | Deno Deno 2.3: Improved deno compile, local npm packages, and more | Deno Add JSR packages with pnpm and Yarn | Deno Zero-config Debugging with Deno and OpenTelemetry | Deno Exploring Art with TypeScript, Jupyter, Polars, and Observable Plot | Deno Deno v Oracle Update 3: Fighting the JavaScript Trademark | Deno Build a custom RAG AI agent in TypeScript and Jupyter | Deno How to get deep traces in your Node.js backend with OTel and Deno | Deno toranoana.deno #20 登録受付中(2025年3月14日) | Deno Node just added TypeScript support. What does that mean for Deno? | Deno The Dino 🦕, the Llama 🦙, and the Whale 🐋 | Deno Publish a lint rule, get a prize | Deno Deno 2.2: OpenTelemetry, Lint Plugins, node:sqlite | Deno If you're not using npm specifiers, you're doing it wrong | Deno How Deno's documentation is evolving | Deno Oracle justified its JavaScript trademark with Node.js—now it wants that ignored | Deno Introducing the JSR open governance board | Deno Intro to Wasm in Deno | Deno Announcing OpenAI on JSR | Deno Deno in 2024 | Deno Goodbye WinterCG, welcome WinterTC | Deno Build a SolidJS app with Deno | Deno Run your Next.js SSR app on Deno Deploy | Deno Solve Advent of Code 2024 with Deno and Win Prizes! | Deno Deno v. Oracle: Canceling the JavaScript Trademark | Deno Deno 2.1: Wasm Imports and other enhancements | Deno Build a Typesafe API with tRPC and Deno | Deno Self-contained Executable Programs with Deno Compile | Deno Build a Database App with Drizzle ORM and Deno | Deno Introducing your new JavaScript package manager: Deno | Deno Announcing Growthbook on JSR | Deno Build an Astro site with Deno | Deno How to convert CommonJS to ESM | Deno Announcing Deno 2 | Deno The Final Touches: What’s New In v2.0.0-rc.10 | Deno Announcing Stable V8 Bindings for Rust | Deno Deno 2.0 Release Candidate | Deno Secure, efficient private npm registries with Cloudsmith and Deno | Deno Painting the Plane as We Fly It: Designing JSR | Deno Introducing Web Cache API support on Deno Deploy | Deno Deno 1.46: The Last 1.x Release | Deno Protect your cloud spend with new Deno Deploy spend limits | Deno What we got wrong about HTTP imports | Deno Benchmarking AWS Lambda Cold Starts Across JavaScript Runtimes | Deno Announcing Supabase on JSR | Deno Deno 1.45: Workspace and Monorepo Support | Deno Introducing KV Backup for Deno Subhosting | Deno A Gentle Intro to TypeScript | Deno Announcing Hono on JSR | Deno How We Made the Deno Language Server Ten Times Faster | Deno How the Guardian uses Deno to audit accessibility and performance across their 2.7 million articles | Deno Introducing More Flexible Domain Association for Deno Subhosting | Deno The stabilization process of the Standard Library has begun | Deno Deno 1.44: Private npm registries, improved Node.js compat, and performance boosts | Deno How we built a secure, performant, multi-tenant cloud platform to run untrusted code | Deno The Deno Standard Library is now available on JSR | Deno How to document your JavaScript package | Deno Your Low Code Solution Needs an Escape Hatch | Deno Deno 1.43: Improved Language Server performance | Deno How Slack used Deno to save months of engineering effort in launching their new platform | Deno JSR Is Not Another Package Manager | Deno Announcing the Hookdeck SDK on JSR | Deno Announcing the Neon Serverless Driver on JSR | Deno An intro to TSConfig for JavaScript Developers | Deno How we built JSR | Deno How Netlify used Deno Subhosting to build a successful edge functions product | Deno Introducing Simpler Project Creation in Deno Deploy | Deno Deno 1.42: Better dependency management with JSR | Deno Introducing deployctl, the command line interface for Deno Deploy | Deno Introducing JSR - the JavaScript Registry | Deno How to add Monaco to a Next.js app and securely run untrusted user code | Deno Survey Results and Roadmap | Deno Deno 1.41: smaller deno compile binaries | Deno
Build Apps in Deno with Frameworks such as React, Vue, Express, and more. | Deno
Andy Jiang · 2022-11-16 · via Deno

There is no shortage of frameworks to build websites and apps in JavaScript. (In fact, as you are reading this, a new one just came out.) Since npm has become the main distribution platform for many things JavaScript, most require npm to use.

With Deno 1.28, you can now build with these JavaScript frameworks, such as Express, React, Vue, and more.

This blog post will show you how to get started with these JavaScript frameworks in Deno:

  • Express
  • React
  • Vue

Check out our Manual for more How To guides on using JavaScript frameworks with npm.

Write less code

Building with these frameworks will be faster, require less configuration, and use less boilerplate with Deno:

  • spend less time evaluating and building your own tools—Deno ships with a robust toolchain, which includes deno test, deno lint, deno fmt and more.
  • no package.json, .tsconfig, or node_modules subdirectory (by default), which can distract you from the code that matters
  • no separate npm install step—modules are cached once in a special global directory

In the examples below, we’ll show how easy it is to get started using npm with Deno.

Express

Express is a popular web framework known for being simple and unopinionated with a large ecosystem of middleware.

Let’s create a simple API using Express and Deno.

View source here.

Create main.ts

Let’s create main.ts:

touch main.ts

In main.ts, let’s create a simple server:


import express from "npm:express@4.18.2";

const app = express();

app.get("/", (req, res) => {
  res.send("Welcome to the Dinosaur API!");
});

app.listen(8000);

Let’s run this server:

deno run --allow-net main.ts

And point our browser to localhost:8000. You should see:

Welcome to the Dinosaur API!

Add data and routes

The next step here is to add some data. We’ll use this Dinosaur data that we found from this article. Feel free to copy it from here.

Let’s create data.json:

touch data.json

And paste in the dinosaur data.

Next, let’s import that data into main.ts. Let’s add this line at the top of the file:

import data from "./data.json" with { type: "json" };

Then, we can create the routes to access that data. To keep it simple, let’s just define GET handlers for /api/ and /api/:dinosaur. Add the below after the const app = express(); line:

app.get("/", (req, res) => {
  res.send("Welcome to the Dinosaur API!");
});

app.get("/api", (req, res) => {
  res.send(data);
});

app.get("/api/:dinosaur", (req, res) => {
  if (req?.params?.dinosaur) {
    const filtered = data.filter((item) => {
      return item["name"].toLowerCase() === req.params.dinosaur.toLowerCase();
    });
    if (filtered.length === 0) {
      return res.send("No dinosaurs found.");
    } else {
      return res.send(filtered[0]);
    }
  }
});

app.listen(8000);

Let’s run the server with deno run --allow-net main.ts and check out localhost:8000/api. You should see a list of dinosaurs:

[
  {
    "name": "Aardonyx",
    "description": "An early stage in the evolution of sauropods."
  },
  {
    "name": "Abelisaurus",
    "description": "\"Abel's lizard\" has been reconstructed from a single skull."
  },
  {
    "name": "Abrictosaurus",
    "description": "An early relative of Heterodontosaurus."
  },
...

And when we go to localhost:8000/api/aardonyx:

{
  "name": "Aardonyx",
  "description": "An early stage in the evolution of sauropods."
}

Awesome!

React

While Express is great for APIs and services, React is meant for user interfaces. It popularized a declarative approach towards designing interfaces, with a reactive data model. And due to its popularity, it’s not surprising that it’s the most requested framework when it comes to building web apps with Deno.

Let’s create an app that’ll display a list of dinosaurs. When you click on one, it’ll take you to a dinosaur page with more details.

View the source or follow the video guide.

Let’s use Vite to quickly scaffold a Deno and React app:

deno run --allow-read --allow-write --allow-env npm:create-vite-extra@latest

We’ll name our project “dinosaur-react-app”. Then, cd into the newly created project folder.

Add a backend

The next step is to add a backend API. We’ll create a very simple API that returns information about dinosaurs.

In the directory, let’s create an api folder. In that folder, we’ll create a main.ts file, which will run the server, and a data.json, which is the hard coded data.

mkdir api && touch api/data.json && touch api/main.ts

Copy and paste this json file into your api/data.json.

Then, let’s update api/main.ts:

import { Application, Router } from "https://deno.land/x/oak@v11.1.0/mod.ts";
import { oakCors } from "https://deno.land/x/cors@v1.2.2/mod.ts";
import data from "./data.json" with { type: "json" };

const router = new Router();
router
  .get("/", (context) => {
    context.response.body = "Welcome to dinosaur API!";
  })
  .get("/api", (context) => {
    context.response.body = data;
  })
  .get("/api/:dinosaur", (context) => {
    if (context?.params?.dinosaur) {
      const filtered = data.filter((item) =>
        item["name"].toLowerCase() === context.params.dinosaur.toLowerCase()
      );
      if (filtered.length === 0) {
        context.response.body = "No dinosaurs found.";
      } else {
        context.response.body = filtered[0];
      }
    }
  });

const app = new Application();
app.use(oakCors()); 
app.use(router.routes());
app.use(router.allowedMethods());

await app.listen({ port: 8000 });

This is a very simple API server using oak that will return dinosaur information based on the route. Let’s start the API server:

deno run --allow-env --allow-net api/main.ts

If we go to localhost:8000, we see:

json response of dinosaurs

Lookin’ good so far.

Add a router

Our app will have two routes: / and /:dinosaur.

We’ll use react-router-dom for our routing logic. Let’s add that to our dependencies in vite.config.mjs:

import { defineConfig } from "npm:vite@^3.1.3";
import react from "npm:@vitejs/plugin-react@^2.1";

import "npm:react@^18.2";
import "npm:react-dom/client@^18.2";
import "npm:react-router-dom@^6.4"; 


export default defineConfig({
  plugins: [react()],
});

Once we add the dependencies there, we can import them without npm: specifier throughout our React app.

Next, let’s go to src/App.jsx and add our routing logic:

import React from "react";
import {
  BrowserRouter as Router,
  Navigate,
  Route,
  Routes,
} from "react-router-dom";
import Index from "./pages/Index.jsx";
import Dinosaur from "./pages/Dinosaur.jsx";

export default function App(props) {
  return (
    <Router>
      <Routes>
        <Route exact path="/" element={<Index />} />
        <Route exact path="/:dinosaur" element={<Dinosaur />} />
        <Route path="*" element={<Navigate to="/" />} />
      </Routes>
    </Router>
  );
}

Next, let’s add the <Index> and <Dinosaur> pages.

Add pages

There will be two pages in this app:

  • src/pages/Index.jsx: our index page, which lists all of the dinosaurs
  • src/pages/Dinosaur.jsx: our dinosaur page, which shows details of the dinosaur

We’ll create a src/pages folder and create the .jsx files:

mkdir src/pages && touch src/pages/Index.jsx src/pages/Dinosaur.jsx

Let’s start with <Index>. This page will fetch at localhost:8000/api and render that through JSX.

import React, { useEffect, useState } from "react";
import { Link, useParams } from "react-router-dom";

const Index = () => {
  const [dinos, setDinos] = useState([]);
  useEffect(() => {
    fetch(`http://localhost:8000/api/`)
      .then(async (res) => await res.json())
      .then((json) => setDinos(json));
  }, []);

  return (
    <div>
      <h1>Welcome to the Dinosaur app</h1>
      <p>
        Click on a dinosaur below to learn more.
      </p>
      <div>
        {dinos.map((dino) => {
          return (
            <div>
              <Link to={`/${dino.name.toLowerCase()}`}>{dino.name}</Link>
            </div>
          );
        })}
      </div>
    </div>
  );
};

export default Index;

Next, in <Dinosaur>, we’ll do the same except for localhost:8000/api/${dinosaur}:

import React, { useEffect, useState } from "react";
import { Link, useParams } from "react-router-dom";

const Dinosaur = () => {
  const { dinosaur } = useParams();
  const [dino, setDino] = useState({});
  useEffect(() => {
    fetch(`http://localhost:8000/api/${dinosaur}`)
      .then(async (res) => await res.json())
      .then((json) => setDino(json));
  }, []);

  return (
    <div>
      <h1>{dino.name}</h1>
      <p>
        {dino.description}
      </p>
      <Link to="/">See all</Link>
    </div>
  );
};

export default Dinosaur;

Let’s start the React app:

deno task start

And click through the app:

demo of the app

Success!

For more information using React, please refer to their documentation.

Vue

Vue is a progressive front-end JavaScript framework, built for performance and versatility.

Let’s create the exact same app we did with React, but now in Vue.

View the source or follow the video guide.

We’ll use Vite to scaffold our Vue app:

deno run --allow-read --allow-write --allow-env npm:create-vite-extra@latest

Name your project, then select “deno-vue”.

Then, cd into your new project and run:

deno task dev

You should now be able to view your default Deno and Vue app in your browser:

default vue app

Add a backend

The next step is to add a backend API. We’ll create a very simple API that returns information about dinosaurs.

In the directory, let’s create an api folder. In that folder, we’ll create a main.ts file, which will run the server, and a data.json, which is the hard coded data.

mkdir api && touch api/data.json && touch api/main.ts

Copy and paste this json file into your api/data.json.

Then, let’s update api/main.ts:

import { Application, Router } from "https://deno.land/x/oak@v11.1.0/mod.ts";
import { oakCors } from "https://deno.land/x/cors@v1.2.2/mod.ts";
import data from "./data.json" with { type: "json" };

const router = new Router();
router
  .get("/", (context) => {
    context.response.body = "Welcome to dinosaur API!";
  })
  .get("/api", (context) => {
    context.response.body = data;
  })
  .get("/api/:dinosaur", (context) => {
    if (context?.params?.dinosaur) {
      const found = data.find((item) =>
        item.name.toLowerCase() === context.params.dinosaur.toLowerCase()
      );
      if (found) {
        context.response.body = found;
      } else {
        context.response.body = "No dinosaurs found.";
      }
    }
  });

const app = new Application();
app.use(oakCors()); 
app.use(router.routes());
app.use(router.allowedMethods());

await app.listen({ port: 8000 });

This is a very simple API server using oak that will return dinosaur information based on the route. Let’s start the API server:

deno run --allow-env --allow-net api/main.ts

If we go to localhost:8000/api, we see:

json response of dinosaurs

So far, so good.

Add Vue components

Let’s update src/components. We’ll add the following files:

  • HomePage.vue, the component for the home page
  • Dinosaurs.vue, the component that lists all dinosaur names as anchor links, and
  • Dinosaur.vue, the component that shows an individual dinosaur’s name and description
touch src/components/HomePage.vue src/components/Dinosaurs.vue src/components/Dinosaur.vue

Before we create the components, let’s add some state management.

Maintain state with store

In order to maintain state across our <Dinosaur> and <Dinosaurs> components, we’ll use Vue store. Note for more complex state management, check out the Vue-endorsed Pinia library.

Create a src/store.js file:

touch src/store.js

And in it, let’s add:

import { reactive } from "vue";

export const store = reactive({
  dinosaur: {},
  setDinosaur(name, description) {
    this.dinosaur.name = name;
    this.dinosaur.description = description;
  },
});

We’ll import store into both Dinosaurs.vue and Dinosaur.vue to set and retrieve dinosaur name and description.

Update Vue components

In Dinosaurs.vue, we’ll do three things:

  • send a GET request to our API and return that as dinosaurs
  • iterate through dinosaurs and render each dinosaur in <router-link> that points to the <Dinosaur> component
  • add store.setDinosaur() to @click on each dinosaur, which will set the store

Here is the complete code below:

<script>
import { ref } from 'vue'
import { store } from '../store.js'
export default ({
  async setup() {
    const res = await fetch("http://localhost:8000/api")
    const dinosaurs = await res.json();
    return {
      dinosaurs
    }
  },
  data() {
    return {
      store
    }
  }
})
</script>

<template>
  <div class="container">
    <div v-for="dinosaur in dinosaurs" class="dinosaur-wrapper">
      <span class="dinosaur">
        <router-link :to="{ name: 'Dinosaur', params: { dinosaur: `${dinosaur.name.toLowerCase()}` }}">
          <span @click="store.setDinosaur(dinosaur.name, dinosaur.description)">
            {{dinosaur.name}}
          </span>
        </router-link>
      </span>
    </div>
  </div>
</template>

<style scoped>
.dinosaur {
}
.dinosaur-wrapper {
  display: inline-block;
  margin: 0.15rem 1rem;
  padding: 0.15rem 1rem;
}
.container {
  text-align: left;
}
</style>

In Dinosaur.vue, we’ll add:

  • importing store
  • rendering store.dinosaur in the HTML
<script>
import { store } from '../store.js';
export default {
  data() {
    return {
      store
    }
  }
}
</script>

<template>
  Name: {{ store.dinosaur.name }}
  <br />
  Description: {{ store.dinosaur.description }}
</template>

Next, we’ll update HomePage.vue. Since the Dinosaurs component needs to fetch the data from the API, we’ll use <Suspense>, which manages async dependencies in a component tree.

<script>
import { ref } from 'vue'
import Dinosaurs from './Dinosaurs.vue'
export default {
  components: {
    Dinosaurs
  }
}
</script>

<template>
  <Suspense>
    <template #default>
      <Dinosaurs />
    </template>
    <template #fallback>
      <div>Loading...</div>
    </template>
  </Suspense>

  <p>
    Check out
    <a href="https://vuejs.org/guide/quick-start.html#local" target="_blank"
      >create-vue</a
    >, the official Vue + Vite starter
  </p>
  <p class="read-the-docs">Learn more about using Deno and Vite.</p>
</template>

<style scoped>
.read-the-docs {
  color: #888;
}
</style>

Tying it all together, let’s update src/App.vue:

<template>
  <router-view />
</template>;

Add routing

You’ll notice that we have used <router-link> and <router-view>. These components are part of the vue-router library, which we’ll have to setup and configure in another file.

First, let’s import vue-router in our vite.config.mjs file:

import { defineConfig } from "npm:vite@^3.1.3";
import vue from "npm:@vitejs/plugin-vue@^3.2.39";

import "npm:vue@^3.2.39";
import "npm:vue-router@4";


export default defineConfig({
  plugins: [vue()],
});

Next, let’s create a folder named router. In it, let’s create index.ts:

mkdir router && touch router/index.ts

In router/index.ts, we’ll create router, which contains information about each route and their component, and export it. For more information on using vue-router, check out their guide.

import { createRouter, createWebHistory } from "vue-router";
import HomePage from "../components/HomePage.vue";
import Dinosaur from "../components/Dinosaur.vue";

const routes = [
  {
    path: "/",
    name: "Home",
    component: HomePage,
  },
  {
    path: "/:dinosaur",
    name: "Dinosaur",
    component: Dinosaur,
    props: true,
  },
];

const router = createRouter({
  history: createWebHistory("/"),
  routes,
});

export default router;

Next, in our src/main.ts file, which contains all of the logic for the frontend app, we’ll have to import and use router:

import { createApp } from "vue";
import "./style.css";
import App from "./App.vue";
import router from "./router/index.ts";

const app = createApp(App);
app.use(router);
app.mount("#app");

Let’s run it and see what we get so far:

Clicking on a dinosaur to get to an individual dinosaur page

Awesome!

What’s next?

Hopefully, these examples showed how easy it is to get up and running with Deno and a JavaScript web framework. They are also starting points for building an app. From there, you could add proper data persistence, add additional routes, implement authentication, etc. Lastly, we plan to continue adding How To guides in our Manual.

We’re also excited to announce that we are hosting a livestream on our YouTube channel tomorrow, Thursday, November 17th, at 9am PT, where we’ll

  • discuss using npm with Deno,
  • answer any questions from the live chat or our Discord, and
  • do some live coding!

We hope you can join us!

Stuck? Get help on our Discord.