快速搭建Mac的web 开发环境

1/15/2025 MacOS

# 快速搭建 Mac 的 web 开发环境

# 安装 Node

检查当前 node 版本

node -v

建议安装最新正式版本 node 22.12.0

brew install node@22
# If you need to have node@22 first in your PATH, run:
echo 'export PATH="/opt/homebrew/opt/node@22/bin:$PATH"' >> ~/.zshrc

# For compilers to find node@22 you may need to set:
export LDFLAGS="-L/opt/homebrew/opt/node@22/lib"
export CPPFLAGS="-I/opt/homebrew/opt/node@22/include"

# 更新配置
source ~/.zshrc

# 检查版本
node -v

# 安装 Node 版本管理工具 NVM

安装步骤

# 安装命令
brew install nvm

# 创建nvm工作目录
mkdir ~/.nvm

# 将以下命令添加到 ~/.zshrc
# This loads nvm
export NVM_DIR="$HOME/.nvm"
    [ -s "$HOMEBREW_PREFIX/opt/nvm/nvm.sh" ] && \. "$HOMEBREW_PREFIX/opt/nvm/nvm.sh"
# This loads nvm bash_completion
 [ -s "$HOMEBREW_PREFIX/opt/nvm/etc/bash_completion.d/nvm" ] && \. "$HOMEBREW_PREFIX/opt/nvm/etc/bash_completion.d/nvm"

 # 更新配置
 source ~/.zshrc

 # 检查是否安装成功
 nvm -v
 nvm help

常用命令

nvm ls-remote --lts    查看所有正式版本
nvm install 版本号      安装指定版本
nvm uninstall 版本号    卸载指定版本
nvm current            当前最新版本
nvm list               显示已安装的列表
nvm use 版本号          使用指定版本
nmv root

# 安装 node 包管理工具 pnpm

brew install pnpm
pnpm -v

# 推荐安装 webStorm

在使用 vscode 发现跳转定义处功能非常不好用,建议使用 webStorm,快捷键和 Android Studio 一致,可以平滑过渡

淘宝 5 元激活

# 运行项目

cd 到项目根目录

pnpm install 安装依赖
pnpm run dev 运行服务

常用命令

pnpm view mockjs versions 查看可用版本
pnpm store path 查看缓存路径
pnpm store prune 清除缓存

# 项目报错

以上步骤都正确,但是项目首次就是跑不起来?

  1. 首先确认你的 node 版本
  2. 删掉 node_modules 和 pnpm-lock.yaml 文件
  3. pnpm store prune 清除 pnpm 缓存

# 安装 Google 拓展

搜索拓展 Vue.js devtools

# 入门必学

# 重要文件介绍

  • app.api.ts 声明 app 级别的 http 请求,例如 getAppConfig
  • message-service 解析 ws 消息的相关逻辑
  • src > object 存放 ws 消息相关的 model
  • src > model 存放 Http 请求相关的 model
  • src > const 存放枚举与常量
  • src > components 全局公用组件
  • src > pages > * > components 页面级别的组件
  • app.store.ts 存放 app 级别的对象、方法与状态,例如 language、token
  • socket.store.ts 存放 socket 对象、方法与状态

# 主题相关

# tailwind class 方式使用定义的主题颜色

<div class="tw-bg-primary">主题主色1</div>
    <div class="tw-bg-secondary">主题主色2</div>
    <div class="tw-text-font-title">标题颜色</div>
    <div class="tw-text-font-title-dark">深色背景标题颜色</div>
    <div class="tw-text-font-primary">字体主色</div>
    <div class="tw-text-font-primary-dark">深色背景字体主色</div>
    <div class="tw-text-font-secondary">字体次级主色</div>
    <div class="tw-text-font-prompt">字体提示色3</div>
    <div class="tw-text-font-prompt-dark">深色背景字体主色</div>
    <div class="tw-bg-warning">警告色</div>
    <div class="tw-bg-danger">提示色</div>
    <div class="tw-bg-stroke1">间隔/描边色1</div>
    <div class="tw-text-font-stroke1-dark">深色背景间隔/描边色</div>
    <div class="tw-bg-stroke2">间隔/描边色2</div>
    <div class="tw-bg-stroke3">间隔/描边色3</div>
    <div class="tw-bg-accent1">点缀色1</div>
    <div class="tw-bg-accent2">点缀色2</div>
    <div class="tw-bg-button1">按钮颜色1</div>
    <div class="tw-bg-button2">按钮颜色2</div>
    <div class="tw-bg-yellow1">黄色1</div>
    <div class="tw-bg-yellow1">黄色1</div>
    <div class="tw-bg-gradient1">渐变色1</div>
    <div class="tw-bg-gradient2">渐变色2</div>
    <div class="tw-bg-gradient3">渐变色3</div>
    <div class="tw-bg-gradient4">渐变色4</div>
    <div class="tw-bg-gradient5">渐变色5</div>
    <div class="tw-bg-gradient6">渐变色6</div>
    <div class="tw-bg-gradient7">渐变色7</div>
    <div class="tw-bg-gradient8">渐变色8</div>
    <div class="tw-bg-gradient9">渐变色9</div>
    <div class="tw-bg-gradient10">渐变色10</div>
    <div class="tw-bg-gradient11">渐变色11</div>
    <div class="tw-bg-gradient12">渐变色12</div>
    <div class="tw-bg-gradient13">渐变色13</div>
    <div class="tw-bg-gradient14">渐变色14</div>
    <div class="tw-bg-[var(--color-warning)]">
      颜色变量示例
    </div>
    <div class="tw-bg-gradient-to-t tw-from-[var(--color-warning)] tw-to-[var(--color-gradient5)] ">
      渐变色变量示例
    </div>
  </div>

# 在 less 中使用

<div class="var-color" > 在less中使用</div > .var-color {
  // 使用变量
  color: var(--bg-primary);
}

# 添加新的主题色

src > styles > tailwind.css

@layer base {
  // 浅色主题
  .light {
    --my-color: #000000;
  }

  // 深色主题
  .dark {
    --my-color: #ffffff;
  }
}

src > tailwind.config.js

theme: {
 		...
    extend: {
    	...
      colors: {
        'my-color': 'var(--my-color)',
      },
    },
  }

使用

<div class="tw-bg-my-color">新颜色修饰背景色</div>
<div class="tw-text-my-color">新颜色修饰字体</div>

// 同上面效果一样
<div class="tw-bg-[var(--my-color)]">新颜色修饰背景色</div>
<div class="tw-text-[var(--my-color)]">新颜色修饰字体</div>

// less中 .my-color { // 使用变量 color: var(--my-color); }

# 声明一个 Http 的 api

src > api > ***.api.ts

export const findMiniApp = post<MiniAppResponse, MiniAppRequest>(
  "/openapi/client/miniapp/find"
);

src > model > ***.request.d.ts

export interface MiniAppRequest {
  name: string;
  page: number;
  limit: number;
  channelId: number;
}

src > model > ***.response.d.ts

export interface MiniAppResponse {
  apps: App[];
  count: number;
  total: number;
}

export interface App {
  description: string;
  downloadUrl: string;
  favoriteAt: number;
  flag: number;
  icon: string;
  iconGaussian: string;
  id: number;
  lastLoginAt: number;
  miniappCreatedAt: number;
  name: string;
  screen: string;
  sessionCreatedAt: number;
  typ: number;
  version: number;
}

使用

onMounted(async () => {
  example.fetchAppConfig();
  const { apps } = await findMiniApp({
    name: "",
    page: 1,
    limit: 10,
    channelId: 3,
  });
  miniApps.value = apps;
  console.log("miniApps", miniApps.value[0].name);
});

声明其他 model 请在与 response、request 同级目录下

# 声明一个 ws 请求

src > services > service.ts

import { generateRequestId } from "@/utils";
import { useAppStore } from "@/stores/app.store";
import { useSocketStore } from "@/stores/socket.store";
import { putRequestId } from "@/services/message-service";

/** 进入 */
const enter = () => {
  const app = useAppStore();
  const message = {
    action: "enter",
    id: app.currentId,
    requestId: generateRequestId(),
  };

  const socket = useSocketStore();
  const map = new Map(Object.entries(message));
  putRequestId(map);
  socket.send(JSON.stringify(message));
};

export { enter };

# 如何将 ws 的消息转为驼峰 Model

import "reflect-metadata";
import { Expose, Type } from "class-transformer";

export class NewRound {
  appid: string = "";
  @Type(() => Current)
  current: Current = new Current();
  @Expose({ name: "round_id" })
  roundId: string = "";
  @Expose({ name: "round_name" })
  roundName: string = "";
  @Type(() => Last)
  last: Last = new Last();
}

export class Current {
  @Expose({ name: "closure_time" })
  closureTime: number = 0;
  round: string = "";
  @Expose({ name: "server_time" })
  serverTime: number = 0;
  @Expose({ name: "simple_round" })
  simpleRound: string = "";
  @Expose({ name: "start_time" })
  startTime: number = 0;
}

export class Last {
  @Expose({ name: "main_result" })
  mainResult: string[] = [];
  @Type(() => Result)
  result: Result[] = [];
  round: string = "";
  @Expose({ name: "simple_round" })
  simpleRound: string = "";
}

export class Result {
  value: string = "";
}

// ws消息
const wsMessage = { appid: "xxxx" };

// 转换完就可以 . 出来
const newRound = plainToInstance(NewRound, data);
console.log("---newRound---", newRound.roundName);
Last Updated: 1/15/2025, 7:57:03 AM
강남역 4번 출구
Plastic / Fallin` Dild