审查自己项目的时候,发现自己一直用开的 UUID 库没有实际测试过性能,所以找了下网上的文章和库列表,就有了今天这一篇文章.

测试代码:

供使用参考,大量摘抄自 (Generating good unique ids in Go):

Package Id Format
github.com/segmentio/ksuid 0pPKHjWprnVxGH7dEsAoXX2YQvU 4 位时间 (单位秒) + 16 位随机数
github.com/rs/xid b50vl5e54p1000fo3gh0 4 位时间 (单位秒) + 3 位设备号 + 2 位进程号 + 3 位随机数
github.com/kjk/betterguid -Kmdih_fs4ZZccpx2Hl1 8 位时间 (单位毫秒) + 9 位随机数
github.com/sony/sonyflake 20f8707d6000108 ~6 位时间 (取 10 毫秒为一个单位) + 1 位顺序序列 + 2 位设备号
github.com/oklog/ulid 01BJMVNPBBZC3E36FJTGVF0C4S 6 位时间 (单位毫秒) + 8 位随机数
github.com/chilts/sid 1JADkqpWxPx-4qaWY47~FqI 8 位时间 (单位纳秒) + 8 位随机数
github.com/lithammer/shortuuid dwRQAc68PhHQh4BUnrNsoS UUID v4/5,支持自定义字符
github.com/satori/go.uuid 5b52d72c-82b3-4f8e-beb5-437a974842c UUID v1/2/3/4/5,符合 RFC 4122 和 DCE 1.1
github.com/google/uuid c01d7cf6-ec3f-47f0-9556-a5d6e9009a43 Google 公开的实现,符合 RFC 4122 和 DCE 1.1
github.com/matoous/go-nanoid Uakgb_J5m9g-0JDMbcJqLJ 更短的字符串,22 个字符,并且支持自定义字符和长度

引用:

Generating good unique ids in Go

近期遇到错误删除 Grub 启动分区,而引起无法启动的问题.

由于主分区用的是 Btrfs 格式,Grub 就需要将自己一个 core.img 嵌入到一个大小为 2M 左右的分区内.

修复步骤:

  1. gdisk 重新建立一个分区,大小为 2M 左右即可
  2. gdisk 修改分区 code 为 EF02
  3. grub-install /dev/SDA (SDA 为系统盘标识符),期间会自动识别 EF02 分区将 core.img 作为嵌入分区.
  4. 重启即可

引用:

Hugo 一个用于生成静态网站的框架,快速开始

Vercel 就是原来的 zeit.co 改名而来。

合并 Hugo 和 Vercel 的特性,可以快速部署一份自己的博客,而且费用全免。

第一步,建立自己的静态网站

直接参考 hugo 的快速开始即可:

# 安装 hugo
wget https://github.com/gohugoio/hugo/releases/download/v0.69.2/hugo_0.69.2_Linux-64bit.tar.gz
tar xf hugo_0.69.2_Linux-64bit.tar.gz hugo
chmod +x hugo

# 建立 MyBlog 网站项目
./hugo new site MyBlog
cd MyBlog

第二步,在 GitHub 上建立自己的私有项目

首先得有自己的 GitHub 账号,注册并登陆。

新建一个项目 MyBlog

  • Repository name: MyBlog
  • Private: You choose who can see and commit to this repository.

新建完毕后,获取项目地址: https://github.com/XXX/MyBlog 其中 XXX 就是 GitHub 账号名。

第三步,在 Vercel 建立并关联 MyBlog 项目

和 GitHub 一样,同样要先注册有 Vercel 账号。

引入 GitHub 的项目,先关联 GitHub 账号到 Vercel,并且选择 MyBlog 项目即可。

然后进去项目选择 Settings 配置 Build & Development Settings 的 FRAMEWORK RESET 为 Hugo,其他都不用修改。

第五步,提交自己的博客

这个时候就要将自己本地的 MyBlog 项目用 Git 进行管理。

# 回到第一步的终端内,紧跟着 cd MyBlog 命令后
git init
git remote add origin https://github.com/XXX/MyBlog # 此处为第二步得到的项目地址
git add archetypes config.toml content data layouts resources static themes
git commit -a -m 'init'
git push -u origin master

在 Vercel 项目 Deployments 页面可以看到等待 Vercel 进行努力编译 MyBlog 了~

经过漫长的几十秒编译后,你就得到第一个静态网站项目: MyBlog.XXX.now.sh 其中 XXX 就是你的用户名。

到此有更多可以处理的。

  1. 选择自己的域名绑定,相关内容在 Vercel 项目的 Settings / Domains 内
  2. 静态网站增加内容,默认建立的网站是一个完全空白的页面(当然啦,毕竟是自己的网站),新建一些内容吧:快速开始

快速解决 VSCode 和 Prettier 的交互。

vscode 版本:1.31.0

直接在项目里面建立一个文件 .prettierrc.js

// .prettierrc.js
module.exports = {
  semi: false,
  singleQuote: true,
  tabWidth: 4,
  trailingComma: 'es5',
};

// .eslintrc.js
module.exports = {
  env: {
    browser: true,
    es6: true,
  },
  extends: 'standard',
  parserOptions: {
    sourceType: 'module',
  },
  rules: {
    curly: [0],
    'prefer-const': [2],
    'space-before-function-paren': 'error',
    // Here to match our Prettier options
    semi: ['error', 'never'],
    quotes: ['error', 'single'],
    indent: ['error', 4],
    'comma-dangle': ['error', 'always-multiline'],
  },
};

其实就是一套配置,估计是 prettier 插件自己的默认配置不符合我的项目环境。

这段时间一直在各种 Angular 项目中挣扎,特别是上传让人措手不及。
索性直接编写一篇可以快速上手的实例,直接抄或者仿照都应该可以直接使用。

  • 新建一个服务

    $ng g s UploadService
    
  • 对服务添加依赖

    
    // http angular的标准HTTP服务
    constructor(private http: HttpClient) {}
    
    // 增加上传方法,参数暂时只有 file
    upload(file: File) {
    // 构建合适的数据表单
    const formData = new FormData();
    formData.append('file', file);
    
    // 构建请求体,因为要做上传进度,所以设置了 reportProgress 为真
    const req = new HttpRequest('POST', '/upload/file/path', formData, {
        reportProgress: true
    });
    
    // 上传重试两次,用了 rxjs 的操作
    return this.http.request(req).pipe(retry(2));
    }
    
    
  • 在 Component 增加上传的操作函数

    
    uploadButtonClicked(ev) {
    // 这里走的是模拟方法
    const elm = document.createElement('input');
    elm.type = 'file';
    elm.multiple = false; // 每次仅上传一个文件,所以直接设置为假
    
    // 监听改变
    elm.addEventListener('change', () => {
        if (elm.files.length > 0) {
            const file = elm.files[0];
    
            this.uploadService
                .upload(file)
                .subscribe((event) => {
                    switch (event.type) {
                        case HttpEventType.Sent:
                            console.info(`${file.name} 上传完毕`);
                            break;
    
                        case HttpEventType.UploadProgress:
                            const percentDone = Math.round(100 * event.loaded / event.total);
                            console.info(`${file.name} 上传进度: ${percentDone}%`)
                            break;
    
                        case HttpEventType.Response:
                            console.info(`远程有返回`)
                            break;
    
                        default:
                            this.logger.info(`"${file.name}" 其他状态: ${event.type}`);
                    }
                });
        }
    });
    elm.click();
    }
    
    

Gradle 国内设置
减少依赖 Google 和 JCenter,使用国内镜像,加速已经很慢的Gradle。

buildscript {
    repositories {
        // 屏蔽默认
        // google()
        // jcenter()
        // 补充国内镜像库
        // maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
        maven { url 'https://plugins.gradle.org/m2/' }
        maven { url 'http://maven.net.cn/content/groups/public/' }
        maven { url 'http://maven.aliyun.com/nexus/content/repositories/google' }
        maven { url 'http://maven.aliyun.com/nexus/content/repositories/jcenter'}
    }

    dependencies {
        classpath 'com.android.tools.build:gradle:3.2.1'
    }
}

allprojects {
    repositories {
        // 屏蔽默认
        // google()
        // jcenter()
        // 补充国内镜像库
        // maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
        maven { url 'https://plugins.gradle.org/m2/' }
        maven { url 'http://maven.net.cn/content/groups/public/' }
        maven { url 'http://maven.aliyun.com/nexus/content/repositories/google' }
        maven { url 'http://maven.aliyun.com/nexus/content/repositories/jcenter'}
    }
}

HTTP DNS 不算新兴事物,不过肯定是好玩的东西。
国内直接提供的商就不认识了,不过还有国外出名的:Google, Cloudflare

这个就拿还能用的 Cloudflare 制作一个简单的例子。

先挖出自己的 JS 里面的 rRaw 函数里面实现,稍作修改就可以使用。

function rRaw(url, callback) {
  var r = new XMLHttpRequest();
  r.async = true;
  r.addEventListener('error', function(err) {
    console.error('[rRaw]', url, 'failed', err);
  });
  r.addEventListener('load', function() {
    console.info('[rRaw]', url, 'loaded');

    var dat = JSON.parse(this.responseText);
    if (callback !== undefined) {
      callback(dat);
    }
  });

  r.open('GET', url, true);

  r.send();
  console.info('[rRaw]', url);
}

Google

rRaw('https://dns.google.com/resolve?name=example', function(dat) {
  console.log(dat);
});

Cloudflare

rRaw('https://cloudflare-dns.com/dns-query?ct=application/dns-json&name=example.com&type=AAAA', function(dat) {
  console.log(dat);
});

Collect some icons project, Done right or MIT or CC0 or CC.

FontAwsome Free

Site: fontawesome.com

over 10,000 SVG icons

Site: leungwensen.github.io Github: leungwensen/svg-icon

Simple Icons

Site: simpleicons.org Github: simple-icons/simple-icons

Ionicons

Site: ionicons.com Github: ionic-team/ionicons

Material Icons

Site: material.io Github: marella/material-icons

Fontice

Site: fontice.com Github: UXWing/Fontice

让页面加载更快是每个网站都需要做的优化。

基础技术包括:

  • 最小化加载文件体积
  • 使用异步加载标签

这里仅作简易的指南,为了新人或者已经忘记初衷的人。


压缩 Compare, Minify

Javascript 压缩脚本推荐两个工具:

  1. Uglify 3? / Online
  2. Google 的 Closure / Online
  3. Yahoo YuiCompressor / Online

扩展阅读 The cost of transpiling es2015 in 2016

CSS 可以尝试下:

  1. CSSNano / Online
  2. CSSo / Online
  3. Yahoo YuiCompressor / Online

扩展阅读 Css Minification Benchmark 2017 report

HTML 优化:

  1. HTML Minifier / Online
  2. HTML Tidy 这个比较古旧,可是非常适合作为优化手段。

扩展阅读 Google’s Minify Resources (HTML, CSS, and JavaScript)

— 2018.04.03 夜深更新到此 —

提醒自己不要忘记前端更多是为了优化阅读体验。

— 2018.04.08 继续更新 —

异步化资源

通过对资源异步加载,将第一次屏显时间提高到最快。

  1. 特性: Preload link

    <link rel="preload" href="used-later.js" as="script" />
    <!-- ...other HTML... -->
    <script>
    // 最后通过Javascript再次将已经预加载到缓存的脚本执行
    var usedLaterScript = document.createElement("script");
    usedLaterScript.src = "used-later.js";
    document.body.appendChild(usedLaterScript);
    </script>
    

当然除了 script 也可以加载 style

<link rel="preload" href="custom.css" as="style" />

更进一步优化

<link rel="preload" href="custom.css" as="style" onload="this.rel='stylesheet'" />

这个 preload 优势就是浏览器本身加载,速度和加载时机都非常靠前,比起自己通过 Javascript 控制加载时机快多了。

注意,这个特性并不是每个浏览器都完整支持。

  1. 使用 Javascript 进行异步

这个是古老的方法,并且可行。可是问题出现在加载实际上。

因为本身 HTML 的顺序加载和解释方式上,一般只有在 HTML 尾部执行 Javascript 才能准确加载异步脚本。

如在 <html /> 后加载 <script />

<html>
  <head></head>
  <body></body>
</html>

<script>
  function rStyle(url) {
    var s = document.getElementsByTagName("head")[0];
    var link = document.createElement("link");
    link.rel = "stylesheet";
    link.type = "text/css";
    link.href = url;
    link.media = "all";
    link.addEventListener("error", function () {
      // handle error
    });
    link.addEventListener("load", function () {
      // handle load done
    });

    s.appendChild(link);
  }

  rStyle("https://iscys.com/js/utils.js");
</script>

在页面解释到此处就是插入一个对象到 DOM 树上,然后异步加载,比较适合业务脚本插入。