Write the Code. Change the World.

9月 10
精选文章

该后台使用 vite + ts + pnpm + vue3 + element-plus + tailwindcss 等技术栈构成。没有添加任意可视化图标等插件。以最小功能,最基础功能展现。用户可以额外添加可使用的插件逻辑。

该后台后端使用 php8.2 + laravel 10 + mysql

该后台后端 go 语言版本开发中。将使用 gframe2.5.2

源码: https://github.com/vini123/simpleAdmin

在线体验: https://www.zeipan.com/admin

权限以及密码一键复位: https://v3test.yuepaibao.com/admin/api/reset

测试账号以及密码: zhoulin@xiangrong.pro、 111111 (如果发现登录不了,可一键复位谢谢)

阅读全文 >>

7月 25

原文: https://community.uwa4d.com/blog/detail?id=1638476203938906113

写在前面

本文我想写一下,一款游戏上线前需要做哪些事情,以保证项目上线后的稳定性。若你们公司之前没有大DAU游戏上线和运维经验,现在准备上线一款新游戏,可以按照这个RoadMap去做或者检查一遍自己游戏的上线准备工作。

本文不会写具体的操作,只是提供一个RoadMap,具体如何做大家可以自行查找相关文档。

所有的工作,都会存在一个工作量和收益的权衡。一般来说,对于大部分游戏,不需要做到100w以上的同时在线,也不需要做到100%的可用性。具体工作做到哪一步,项目根据自己的情况权衡即可,我在文中会介绍需要重点关注的地方。

这些工作,至少需要提前6个月以上的时间准备,至少需要一个资深服务端和一个靠谱的执行服务端。

阅读全文 >>

7月 01

webrtc

https://meet.livekit.io/

https://juejin.cn/post/7266417942182608955

https://github.com/wang1xiang/webrtc-tutorial/tree/master/04-one-to-one

log4js

https://blog.csdn.net/weixin_57208584/article/details/134188447

https://juejin.cn/post/7221445996135022653

日志使用:

先安装

pnpm add log4js

再创建和配置

import log4js from "log4js";

const config = {
  appenders: {
    console: { 
        type: "console",
        layout: {
            type: "pattern",
            pattern: "%d{yyyy-MM-dd hh:mm:ss} - %m", // 这里定义了时间格式
        },
    },
    file: {
      type: "dateFile",
      filename: "logs/log",
      encoding: 'utf-8',
      compress: true,
      numBackups: 7,
      keepFileExt: true,
      alwaysIncludePattern: true,
      pattern: "yyyy-MM-dd.log",
      fileNameSep: '-',
      layout: {
        type: "pattern",
        pattern: "%d{yyyy-MM-dd hh:mm:ss} - [%p] - %m", // 这里定义了时间格式
      },
    },
  },
  categories: {
    default: { appenders: ["console", "file"], level: "info" },
  },
};

let logger;
if (!logger) {
  log4js.configure(config);
  logger = log4js.getLogger();
}

export default logger;

阅读全文 >>

5月 29

fontawesome 字体。如果主题中直接引用 cdn 的字体,经常出现 404 等情况。可以将字体下载下来,放在主题目录下,使用本地的会更好。
https://fontawesome.dashgame.com/#google_vignette

获取当前主题的 url。比如存在某个主题 A,在主题 A 下有 ·/css/your-stylesheet.css 文件,就可以通过下边的方法来处理。这样渲染出来就是 https://xxx.com/xx/xx/css/your-stylesheet.css。 如果你的域名是 https://xxx.com 的话。这样就可以防止硬编码了。

<link rel="stylesheet" type="text/css" href="<?php echo get_template_directory_uri(); ?>/css/your-stylesheet.css">

自言自语

在 wordpress 中,我安装了一个主题,在这个主题的 header.php 中,我引用了该文件夹下的一个 css 文件,怎么获取当前的 css 文件的路径呢

阅读全文 >>

5月 27

vue3 项目,配置了 ts 来开发。如果某一些组件,不使用 ts,编译的时候会报错。有时候并不是不想用 ts,只是那些文件是第三方编写的,又耦合比较高。这个时候,允许这些文件继续使用 js 来编写是一个需求。

这里以一个 LivePlayer 组件为例。

步骤

  1. 创建一个 src/components/LivePlayer/LivePlayer.vue。 部分代码如下。这里没有设置 lang='ts',也没有使用 ts 的强类型。
components<template>
    <div class="relative overflow-hidden shrink-0 w-[320px] h-[405px]">
        <div id="remoteVideo" class="w-[720px] h-[405px] ml-[-200px]"></div>
    </div>
</template>

<script setup>
import { ref, onMounted } from 'vue';

const playIng = false

const urls = ref([])

function play(value) {
    urls.push(value)

    playVideo()
}

function playVideo() {
    if (playIng) {
        return
    }

    const url = urls.shift()
    if (!url) {
        return
    }

    playIng = true
    // todo
}

defineExpose({ play })
</script>
  1. tsconfig.app.json 中加入黑名单,ts 编译器对这些文件不做处理。如:
{
  "extends": "@vue/tsconfig/tsconfig.dom.json",
  "include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
  "exclude": ["src/**/__tests__/*", "src/components/LivePlayer/LivePlayer.vue"],
  …
  1. 添加类型声明。在 typings 目录下,增加类型声明。typings 目录根据实际项目配置为准。
// 定义一个接口来描述暴露给模板的属性或方法  
interface LivePlayerExpose {  
    speakMessage: (value:string) => void
}

// 声明一个 Vue 组件实例类型,它扩展了 Vue 组件的基础类型,并添加了 LivePlayerExpose 接口  
declare type LivePlayerComponent = InstanceType<DefineComponent<{}, {}, {}, {}>> & LivePlayerExpose

declare module '@/components/LivePlayer/LivePlayer.vue' {  
    import { DefineComponent } from 'vue'

    const component: DefineComponent<{}, {}, {}, {}> & {  
        // 注意:这里我们并不直接导出 component,而是声明了它的类型  
        // 在实际使用时,Vue 会处理 component 的导出和注册  
    };  

    // 导出的是组件的实例类型,以便在模板或其他组件中引用时具有正确的类型  
    export default component
    // 导出组件实例类型以供外部使用  
    export type Instance = LivePlayerComponent
  }
  1. 项目中使用组件
components<template>
    <div class="w-full">
        <LivePlayer ref="livePlayerRef" />
    </div>
</template>

<script setup lang='ts'>
import { ref, onMounted } from 'vue';

const livePlayerRef = ref<InstanceType<typeof LivePlayer> | null>(null)

onMounted(() => {
    livePlayerRef.value?.play("xxx")
})
</script>

阅读全文 >>

5月 26

brotli 有很好的解压缩效率,但 nginx 默认又不包含 brotli 模块,只能额外搞了

步骤

  1. 准备 Dockerfile 文件
  2. 准备 nginx.conf 文件
  3. 准备 docker-compose.yaml 文件
  4. 生成镜像,构建容器

准备 dockerfile

# 创建一个 env 目录,基于该目录为项目根目录
mkdir env && cd env

# 下载 Dockerfile
curl -o docker/nginx/Dockerfile https://raw.githubusercontent.com/nginxinc/docker-nginx/master/modules/Dockerfile

准备 nginx.conf

https://github.com/google/ngx_brotli/blob/master/README.md

这里 nginx.conf 位于 ./conf/nginx/nginx.conf 中。

user  nginx;
worker_processes  auto;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

 load_module modules/ngx_http_brotli_filter_module.so;
 load_module modules/ngx_http_brotli_static_module.so;

events {
    worker_connections  1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;
     brotli on;
    include /etc/nginx/conf.d/*.conf;
}

准备 docker-compose.yaml 文件

docker-compose.yaml 文件直接就在项目根目录下。

…
nginx:
    build:
      context: ./docker/nginx
      args:
        ENABLED_MODULES: brotli
    image: xr-nginx-brotli
    container_name: xr-nginx-brotli
    restart: always
    privileged: false
    ports:
      - 80:80
      - 443:443
    volumes:
      - ./conf/nginx/nginx.conf:/etc/nginx/nginx.conf

生成镜像,构建容器

# 生成镜像
docker-compose build nginx

# 构建启动容器
docker-compose up

其实,可以直接执行 docker-compose up, 没有镜像的时候,会先去生成镜像的

检查

当你发起请求经过 nginx 时,返回的请求头中有 Accept-Encoding: br 表示 brotli 生效了。

相关文章

https://github.com/nginxinc/docker-nginx/tree/master/modules

https://github.com/google/brotli/

https://github.com/google/ngx_brotli

https://github.com/nginxinc/docker-nginx/issues/332

阅读全文 >>

5月 13

在 git 版本工具中,同一个公钥只允许配置一个。假如你有多个电脑,多个账号,多个项目需要进行代码上传下载。这个时候就处理不好。

有这样一个场景:
在 A 电脑,有一个 a 项目,上传到 a 账号的 github 上。
继续,在 A 电脑,有一个 b 项目,上传到 b 账号的 github 上。

如果想使用 ssh-key 的授权方式来上传代码。同一个 ssh-key 只能配置在一个账号里。也就是对于同一个 git 平台,同一个 ssh-key 只能有一份。于是,你就只能再去创建一个新的 ssh-key,然后配置另外一个账号里。

这样的确是可以配置进去了。但是,当你上传代码的时候,会提示授权不过。因为,git 没指定 ssk-key 的时候,会使用默认的公私钥,就是 id_rsa。这个时候,就需要在特定项目,指定也定的 ssh-key 就实现了。

生成 ssh-key

ssh-keygen -t rsa -C xxx@xx.com -f xxx-github

指定 ssh-key

方式一(到当前目录下):

git config core.sshCommand "ssh -i ~/.ssh/xxx-github"

方式二

# 添加
ssh-add ~/.ssh/xxx-github

# 删除
ssh-add -d ~/.ssh/xxx-github

# 查看
ssh-add -l

推荐使用方式一,这样每个项目都会对应好自己的 ssh-key,不会影响其他的项目。

历史

https://blog.vini123.com/1070

https://blog.vini123.com/1134

阅读全文 >>

5月 08

Laravel 11Laravel Reverb 现已发布。Reverb 是 Laravel 生态系统的最新成员,是第一方、可扩展的 WebSocket 服务器,旨在为用户的应用程序提供强大的实时功能。

Laravel 11 引入了:极简应用结构、默认使用 SQLite、实现 health routing、提供每秒速率限制、支持优雅的加密密钥轮换、改进队列测试、引入新的 Artisan 命令、添加 Resend 邮件传输、集成 Prompt validator、新的 Artisan commands、Model Casts 改进、The once function、改进了使用内存数据库进行测试时的性能、改进了对 MariaDB 的支持等等,

Laravel 11 使用的 PHP 版本最低要求是 PHP 8.2。

阅读全文 >>

5月 04

vite 支持自动处理 scss,less 等文件,但需要下载对应的包 https://cn.vitejs.dev/guide/features#css-pre-processors。 如果,你想单独写 scss 这些,可以在 vite.confit.ts 中进行配置

常规操作

1、先创建一个 vue3 项目

# 创建 vue 项目
pnpm add vue

pnpm format

pnpm dev

# 添加 git 版本控制
git init -b main
git add .

2、安装 sass

pnpm add sass

3、创建一个 scss 文件

touch ./src/assets/css/base.scss

# 填充下边内容
body {
    background-color: #f00;
}

4、在 vite.config.ts 中进行配置

import { fileURLToPath, URL } from 'node:url'

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import VueDevTools from 'vite-plugin-vue-devtools'

// https://vitejs.dev/config/
export default defineConfig({
  css: {
    preprocessorOptions: {
      scss: {
        additionalData: `@use "@/assets/css/base.scss";`
      }
    }
  },
  plugins: [vue(), VueDevTools()],
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url))
    }
  }
})

这个时候,发现 base.scss 中的样式不生效。真的很郁闷,查了一些文档和资料,就是这么写的,偏偏不行。还好在 segmentfault 上找到了一个解释。就是你必须至少在 .vue 文件里边至少使用 <style lang="scss"><style>。于是,手动这样加了一下,果真样式生效了。 当下用的是最新版本的 vite(vite5),依然存在这个问题。

参考

https://segmentfault.com/a/1190000041425201

阅读全文 >>