想要获得招聘人员的关注?只需⌚ 5​​ 分钟即可构建这个🔥项目🚀,打造你的作品集!入门指南🚀 依赖项⚠️ 文件夹设置🎪 服务器设置🌀!创建路由器⚡!创建控制器⚡!数据模型❄️!前端👀!总结🙏

2025-05-24

想要吸引招聘人员的注意?只需⌚ 5​​ 分钟即可构建这个🔥项目,🚀 丰富你的作品集!

入门🚀

依赖项⚠️

文件夹设置🎪

服务器设置🌀!

创建路由器⚡!

创建控制器⚡!

数据模型❄️!

前端👀!

摘要🙏

准备好创建作品集却苦于没有灵感了吗?这里有一个绝佳的创意,可以展示你的全栈技能,给潜在雇主留下深刻印象!💥

入门🚀

mkdir url-shortener
cd url-shortener
npm init -y
Enter fullscreen mode Exit fullscreen mode

在这里,我们创建一个目录来存储我们的项目,并用npm初始化它。

依赖项⚠️

npm install dotenv express mongoose nanoid
Enter fullscreen mode Exit fullscreen mode

我们安装了一些将在整个项目中使用的依赖项:

  • dotenv(利用环境变量的库)
  • express(Express.js 用于创建我们的服务器应用程序)
  • mongoose(ODM 将我们的 URL 存储在我们的 MongoDB 数据库中)

文件夹设置🎪

我们需要确保我们的项目看起来像这样:

url-shortener/
├── package.json
├── client
│   ├── app.js
│   ├── index.html
│   └── style.css
└── server
    ├── controllers
    │   └── url.controller.js
    ├── index.js
    ├── models
    │   └── url.model.js
    └── routes
        └── url.routes.js
Enter fullscreen mode Exit fullscreen mode

我们将代码拆分为路由、控制器和模型。通过关注点分离,使代码更易于维护!

服务器设置🌀!

在我们的文件中server/index.js,添加以下内容:

const express = require('express');
const mongoose = require('mongoose');
require('dotenv').config();

const urlRouter = require('./routes/url.routes');

const PORT = process.env.PORT || 8080;
const DB_URL = process.env.DB_URL || 'mongodb://localhost:27017/db';

const db = mongoose.connect(DB_URL, {
                useCreateIndex: true,
                useNewUrlParser: true,
                useUnifiedTopology: true
            }
        ).
        then(res => res)
        .catch(err => console.log(err));

const app = express();

app.use(express.json());
app.use(express.static('client'));
app.use('/url', urlRouter);

app.listen(PORT, () => {
    console.log(`Server listening at http://localhost:${PORT}`);
});
Enter fullscreen mode Exit fullscreen mode

在这里,我们导入expressmongoose

然后导入即将创建的路由器来处理我们的URL

然后初始化我们的数据库连接来存储我们的数据。

接下来我们创建我们的express 应用程序并使用我们的中间件(express.json()、express.static() 和我们的路由器)

创建路由器⚡!

在我们的文件中server/routes/url.routes.js,添加以下内容:

const express = require('express');
const urlRoutes = express.Router();

const controller = require('../controllers/url.controller');

urlRoutes.get('/:slug', 
        controller.getUrl);

urlRoutes.post('/new',
        controller.postUrl);


module.exports = urlRoutes;
Enter fullscreen mode Exit fullscreen mode

在这里,我们导入express并创建一个express 路由器来连接我们的路由。

然后,我们导入控制器来处理调用的请求。

最后,我们创建GETPOST请求来处理检索创建缩短的URL

创建控制器⚡!

现在我们需要一个控制器来处理这些路线!

在我们的文件中server/controllers/url.controller.js,添加以下内容:

const UrlModel = require('../models/url.model');
const {nanoid} = require('nanoid');

exports.getUrl = async (req, res) => {
    const {slug} = req.params;
    // check if slug exists
    const foundSlug = await UrlModel.findOne({slug});
    // if no slug exists, create one
    if(!foundSlug || foundSlug.length == 0) {
        let fullUrl = req.protocol + '://' + req.get('Host') + req.originalUrl;
        res.status(404).json({message: "URL not found.", body:{slug, url: fullUrl}});

    } else {
        res.status(302).redirect(foundSlug.url);
    }
}

exports.postUrl = async (req, res) => {
    let {url, slug} = req.body;
    // check if slug provided, create new one if not.
    if(!slug) {
        slug = nanoid(5);
    }
    slug = slug.toLocaleLowerCase();
    // check if slug exists
    const foundSlug = await UrlModel.find({slug});
    // if no slug exists, create one
    if(!foundSlug || foundSlug.length == 0) {
        const newUrl = new UrlModel(
            {
                slug,
                url
            }
        );
        const response = await newUrl.save();
        res.status(200).json({message: "Creation successful!", body:response});

    } else {
        res.status(409).json({message: "Resource already exists.", body:{slug: "", url:""}});
    }
}
Enter fullscreen mode Exit fullscreen mode

这就是我们使用依赖项nanoid 的地方。

什么是纳米粒子?

nanoid是一个用于生成短 ID 字符串的库。我们将生成一个短 ID 字符串作为我们的短 URL!

GET请求

GET请求get url中检索slug 值并尝试从数据库中检索匹配的条目:slug

如果找到匹配的 slug,那么我们将重定向到找到的 slug 的URL 。

如果没有找到 slug,我们会以 404 状态通知用户未找到所需的 URL。

POST请求

POST请求POST请求正文中检索url 和 slug如果没有提供 slug,我们将使用nanoid生成长度为 5 的随机slug 。

这样用户就可以创建自定义短 URL

示例请求:

POST http://localhost:8080/url/new HTTP/1.1
content-type: application/json

{
        "slug": "abcde",
        "url": "https://www.google.com"
}
Enter fullscreen mode Exit fullscreen mode

这将创建一个 URL,http://localhost:8080/abcde
将用户重定向到https://www.google.com

我们检查数据库中是否已经存在具有所需 slug 的条目。

如果不存在条目,我们将新文档保存到数据库并返回创建的条目。

如果 slug 存在,我们将返回 409 响应,通知用户资源已存在。

数据模型❄️!

为我们的后端构建的最后一件事是 mongoose 将用于我们的 MongoDB 数据库的数据模型。

在我们的文件中server/models/url.model.js,添加以下内容:

const mongoose = require('mongoose');

const UrlModel = mongoose.model('Url', 
    mongoose.Schema(
        {
            slug: {
                type: String,
                minlength: [5, 'Slug does not contain enough characters (Minimum 5).'],
                maxlength: [5, 'Slug contains too many characters (Maximum 5).'],
                trim: true,
                validate: {
                    validator : (slug) => {
                        return /[\w\-]/.test(slug);
                    },
                    message: props => `${props.value} is not a valid slug.`
                }
            },
            url: {
                type: String,
                required: [true, 'A valid URL must be provided.'],
                trim: true
            }
        },
        {timestamps: true}
    )
);

module.exports = UrlModel;
Enter fullscreen mode Exit fullscreen mode

在这个脚本中,我们首先导入 mongoose来创建我们的mongoose 模型

然后我们创建一个具有两个参数的UrlModel Schema

  • slug(缩短的 URL 的字符串值)
  • url(要重定向到的 URL 的字符串值)

我们使用正则表达式为 slug创建一些基本验证,以确保 slug 仅包含字母数字字符连字符(-)。

后端就完成了👏!是时候构建我们​​的前端了!

前端👀!

我们的客户端目录应包含以下文件:

client/
├── app.js
├── index.html
└── style.css
Enter fullscreen mode Exit fullscreen mode

index.html 文件

在我们的文件中index.html,添加以下表单:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="style.css">
    <title>MicroUrl</title>
</head>
<body>
    <main>
        <h1>MicroUrl</h1>
    </main>
    <section>
        <form action="javascript:;" onsubmit="createUrl(displayResponse)">
            <label for="url">Url to shorten:</label>
            <input type="url" name="url" id="url" required>
            <label for="slug">Optional. Custom micro url:</label>
            <input type="text" name="slug" id="slug">
            <input type="submit" value="Create">
        </form>
    </section>
    <section id="response">
    </section>
    <script src="app.js"></script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

我们的表单包含两个输入(一个用于缩短URL ,另一个用于潜在的自定义 slug

style.css 文件

在我们的文件中style.css,添加以下表单:

body {
    margin-top: 20vh;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    color: #84613D;
    font-family: "Lucida Console", Monaco, monospace;
    background: #FDF9EA;
}

body > * {
    width: 40vw;
    height: auto;
}

form {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: stretch;
    margin: 1rem 0;
}

form > * {
    margin: .5rem 0;
    padding: 1rem;
}

form > button {
    padding: 0;
}
Enter fullscreen mode Exit fullscreen mode

我们的网站现在应该包含一个有吸引力的、响应迅速的表格!
替代文本

最后要做的是添加 Javascript 来创建我们的 URL 并显示响应!

app.js 文件

在我们的文件中app.js,添加以下表单:

const createUrl = async (callback=null) => {
    this.preventDefault;
    let response = await fetch('/url/new', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json;charset=utf-8'
        },
        body: JSON.stringify(
            {
            url:this.url.value, 
            slug:this.slug.value
        })
      });
      let result = await response.json();
      console.log(result);
      if(callback) {
        callback("response", result);
      }
}

const displayResponse = (elementKey, data) => {
  const {message, body} = data;

  const parentElement = document.getElementById(elementKey);
  parentElement.innerHTML = "";

  let divElement = document.createElement('div');

  let pElement = document.createElement('p');
  pElement.appendChild(document.createTextNode(message));

  let aElement = document.createElement('a');
  if(body.slug) {
    aElement.appendChild(document.createTextNode(`${window.location.href}url/${body.slug}`));
    aElement.href = `${window.location.href}url/${body.slug}`;
  } else {
    aElement.appendChild(document.createTextNode(""));
  }

  divElement.appendChild(pElement);
  divElement.appendChild(aElement);
  parentElement.appendChild(divElement);
}
Enter fullscreen mode Exit fullscreen mode

我们有两个功能:

  • 创建Url
  • 显示响应

createUrl接受回调作为参数,在处理完此表单的提交后执行。

这可以称为callback design pattern

createUrl函数用于表单数据POST到服务器。完成后,我们使用displayResponse函数显示新创建的短 URL:fetch

替代文本

提交后:
替代文本

摘要🙏

如果你已经完成了这一步,恭喜你!🎉
你在这个项目中学到了很多东西。API 创建、数据验证、前端设计。现在你应该已经准备好创建一个🔥作品集了!

如果您喜欢本教程,请随时关注我并查看我的一些社交媒体!
Twitter
Github

文章来源:https://dev.to/brandonkylebailey/want-recruiters-attention-build-this-project-in-5-minutes-to-your-portfolio-1l6h
PREV
关于贪婪算法、分治法和动态规划算法的免费电子书如何将您的名字添加到贡献者贪婪算法使用贪婪算法计算变化Dijkstra算法分治动态规划背包问题
NEXT
Why I Stopped Interviewing with Companies That Require a Coding Test