自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(170)
  • 收藏
  • 关注

原创 前端开发环境配置检查清单

Node.js进入官网,如果 Window 就下载 .msi ,Mac 下载 .pkg :https://nodejs.org/zh-cn/别着急安装最新版,先看看同事都用的是什么版本,如果同事都在用 12.x ,建议也装 12.x ,如果你装 16.x ,大概率安装依赖的时候会报错。推荐使用 nvm 管理 Node 版本,不过本人是 Window 环境,就不装了。然后确认你下载的是 LTS 版本,不要装奇数版或者已经不在维护的版本,这点在 Node.js 官网也有说明。https://no

2021-09-16 23:29:21 1151

原创 一个案例讲解 CSS 布局两个注意点

这篇文章回顾一下 CSS 基础布局中两个注意点。有如下布局:例如我们想给 main-wrapper 内部添加上下边距,让 content 不至于紧贴盒子边缘。一种可能的方案,给 content 设置 margin:我们添加了上下各 50px 的 margin 之后发现 content 与 main-wrapper 之间并没有出现边距,反而 main-wrapper 被顶下来了。这就是第一个问题:BFC 中的垂直外边距塌陷。在同一个 BFC 中,相邻两个盒子的上下外边距会合并(可以是并排关系,也可以是

2022-04-04 21:02:30 580

原创 从前端角度谈谈单页应用的 nginx 配置

有段时间没搞项目部署了,结果最近有同事在部署前端项目的时候,访问页面路由,响应都是 404,排查了半天,这里再总结一下。前端单页应用路由分两种:哈希模式和历史模式。哈希模式部署不会遇到啥问题,但是一般只用于本地调试,没人直接部署到生产环境。历史模式的路由跳转通过 pushState 和 replaceState 实现,不会触发浏览器刷新页面,不会给服务器发送请求,且会触发 popState 事件,因此可以实现纯前端路由。需要注意,使用历史模式的时候,还是有两种情况会导致浏览器发送请求给服务器:输入

2022-02-20 13:06:37 3165 1

原创 使用Docker高效部署前端应用

容器的每一个阶段都应该是短暂的通过 Dockerfile 构建的镜像所启动的容器应该尽可能短暂 (ephemeral)。短暂意味着可以很快地启动并且终止使用 .dockerignore 排除构建无关文件.dockerignore 语法与 .gitignore 语法一致。使用它排除构建无关的文件及目录,如 node_modules使用multistage构建多阶段构建可以有效减小镜像体积,特别是对于需编译语言而言,一个应用的构建过程往往如下安装编译工具安装第三方库依赖编译构建应用在前两步

2022-02-17 23:05:15 518

原创 深入源码分析 file-loader 哈希生成规则

我们知道,在 Webpack 中有三种哈希:hash:一次 compilation 总体的哈希,只要有一个文件修改,整个哈希就会发生变化chunk-hash:根据 chunk 生成的哈希,同一个 chunk 中所有文件的哈希相同content-hash:根据文件内容生成的哈希在 Vue-cli 默认 Webpack 配置中,对 JS 启用 chunk-hash,CSS 启用 content-hash,而图片和字体文件则是 hash。这样就产生一个问题,修改 JS 代码后,图片和字体的哈希是否会发

2022-02-05 22:56:55 952

原创 如何使用 express 和 webpack-dev-middleware 搭建开发服务器

在开发前端项目时,我们一般会选用 webpack-dev-server 作为开发服务器,例如:// webpack.config.jsmodule.exports = { // ... devServer: { static: './dist', },}// package.json{ "scripts": { "serve": "webpack serve --open", "build": "webpack" },}但实际上 Webpack

2022-02-05 20:53:16 1272

原创 如何用 Golang 实现一个 http server

先安装 gin 这个库:$ go get -u github.com/gin-gonic/gin如果直接下载请求超时,可以设置镜像源:$ go env -w GO111MODULE=on$ go env -w GOPROXY=https://goproxy.cn,https://goproxy.io,direct然后建一个 hello.go,添加如下代码:package mainimport ( "fmt" "github.com/gin-gonic/gin")func mai

2022-02-04 23:53:14 1848

原创 Golang 协程开销测试

在 Linux 中进程和线程的上下文切换开销,大约是 3-5us 之间。但是在高并发场景下,每秒钟数千万请求,即使 3-5us 的开销,如果上下文切换量特别大的话,仍然会显得性能低下。为避免频繁的上下文切换,有一种异步非阻塞的开发模型,就是用一个进程或线程去接受一大堆用户的请求,然后通过 IO 多路复用的方式来提高性能(进程或线程不阻塞,省去了上下文切换的开销)。Nginx 和 Node.js 就是这种模型的典型代表产品。但是这种编程模型的问题在于对开发不友好,于是在这个基础上就设计出了不需要进程/线程上下

2022-02-03 11:57:32 1288

原创 如何使用 chrome devtool 分析前端代码执行耗时和内存占用

如何分析代码执行耗时代码执行耗时这块,大家应该都知道使用 Performance 面板中的 火焰图,火焰图中每个方块的宽度代表执行耗时,方块叠加的深度代表调用栈的深度。通过火焰图可以很直观地展示出代码调用关系,当你不熟悉某个框架、源码中的代码逻辑,又不希望一行行去看源码,火焰图就是最好的工具。在分析性能的时候,为排除插件的影响,需要启用无痕模式此外我们还可以看到每一行代码执行的时间。在火焰图中找到长任务,点击顶部 Task,点击 Button-Up,这时候可以看到根据耗时列出的调用栈:找到那个

2022-01-31 13:11:30 3602

原创 如何使用 Map 实现 Set

关于 Map 和 Set 是两个抽象数据结构,Map 存储一个键值对集合,其中键不重复,Set 存储一个不重复的元素集合。本质上 Set 可以视为一种特殊的 Map,Set 其实就是 Map 中的键。这里我们用 TypeScript 使用 Map 来实现 Set。核心的思路非常简单,创建一个 Map,我们只要用 Map 的键就行,键对应的值全部填充 undefined:class NewSet<T extends unknown> { private collection: Map&lt

2022-01-23 12:38:24 973

原创 Nodejs 使用 Buffer 将图片转为 base64

一直以为图片转为 base64 很复杂,结果今天看了下 Docusaurus 的 plugin-ideal-image 插件源码,居然只要一行代码就完事了:const toBase64 = (extMimeType: string, data: Buffer): string => `data:${extMimeType};base64,${data.toString('base64')}`;这里说明下,这个插件使用 sharp 对图片进行处理,最后返回的是一个 Buffer 实例,我们先来

2022-01-22 23:33:30 6856

原创 如何编写一个 Vue 权限控制指令

在业务中经常会遇到权限管理的问题,例如按钮级别或者页面内操作权限的需求,我们可以编写一个全局自定义指令。例如我们可以将指令直接注册到 main.js 中:import Vue from "vue";import App from "./App.vue";Vue.directive("auth-key", { inserted(el, binding) { // ... }})new Vue({ render: h => h(App),}).$mount("#app");这

2022-01-16 20:38:19 435

原创 webpack-dev-server 如何配置代理

在 CRA 搭建的项目中,我们知道可以在 src/setupProxy.js 文件中写入代理配置:const proxy = require('http-proxy-middleware');module.exports = function(app) { app.use( proxy( '/course', { target: 'localhost:8080', changeOrigin: true, }, ),

2022-01-15 11:26:52 1248

原创 ES6 Set 和 Map 遍历操作

作为 ES2015 的新增特性,Set 和 Map 对象大家应该很熟悉了,例如 Set 在数组去重等场景中经常会用到:function unique(array = []) { return Array.from(new Set(array));}但是一般我们都是只在需要这种数据结构的时候才去创建它,在用完之后就转回数组。大家可能都认为,相比 Set 、Map 对象,还是数组操作更熟悉一些。但实际上它们本身也提供了一些遍历方法,下面我们一起来看下。Set 对象遍历操作Set 结构的实例有四个遍

2022-01-09 17:58:35 2110

原创 如何覆盖 CRA 默认 webpack 配置

在 CRA 创建的项目中,经常需要修改默认 webpack 配置。但是 CRA 不像 Vue-cli 可以提供自定义 webpack 配置,而 eject 又会把全部配置暴露出来,很麻烦。这种情况下可以使用 react-app-rewired 这个库:$ yarn add react-app-rewired -D在项目根目录创建一个 config-overrides.js 文件,添加自定义 webpack 配置:/* config-overrides.js */module.exports =

2022-01-09 12:43:57 994

原创 如何在 JB 全家桶中使用 VS Code 的快捷键

JB 全家桶,例如 IDEA、WebStorm、GoLand 等支持多种 keymap,如要使用 VS Code 的快捷键,只需要安装对应的 Keymap 即可:安装后应用即可:同理主题也可以安装,在 JB 全家桶中推荐使用 One Dark Theme,安装完成后点击 apply 即可:推荐安装的插件:Atom Material IconsGitToolBoxMaven HelperOne Dark ThemeSearch In RepositoryVSCode Keymap

2022-01-07 21:51:20 934

原创 ES 新语法:`Array.prototype.groupBy`

在开发中经常需要对数据进行分组,但是由于没有原生方法的支持,我们自己实现的数据分组函数通常都比较冗长而且难以理解。不过,告诉大家一个好消息,一个专门用来做数据分组的提案 Array.prototype.groupBy 已经到达 Stage 3 啦!在看这个提案,之前,我们先来回顾下我们以前在 JavaScript 里是怎么分组的。以前的方式假设我们有下面一组数据:const items = [ { type: 'clothes', value: '????', },

2021-12-27 22:38:48 693

原创 JS、Java、Go 实现反转一维数组

Java 实现:public class ReverseArray { public void reverse(int[] arr) { int i = 0, j = arr.length - 1; while (j > i) { int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; i++;

2021-12-25 18:17:46 632

原创 CSS 三条内容分享

1. 单行文本溢出隐藏这块老生常谈了,本人当初实习的时候,被抓的第一个 bug 就是这个。做起来比较简单:.header-title { white-space: nowrap; /* 文本默认会换行,这边不让文本换行 */ overflow: hidden; /* 文本溢出隐藏 */ text-overflow: ellipsis; /* 溢出展示省略 */}2. 毛玻璃背景设计师给的设计稿上经常会有毛玻璃背景,但假如直接从设计稿上复制 CSS 属性,一般都是用 backdrop-fi

2021-12-25 15:30:44 463

原创 记一次 Vue 项目代码优化

项目中有一个需求,在切换视频播放源之后,需要恢复之前设置的播放速率。经过试验发现,如果在切换播放源之后,立即设置播放速率是不生效的,需要在视频加载完成之后设置才生效,因此这边需要切换播放源的时候保存一个回调,在 onPlay 事件触发的时候设置播放速率:import bus from "EventBus";export default { data() { return { rateChangeEvent: null; } }, mounted() { bus.$on('onP

2021-12-16 20:52:26 95

原创 GitHub Pages 配合 GitHub Actions 实现文档网站自动部署

最近在用 docusaurus 做一个文档网站,通过 GitHub Pages 进行部署,每次部署的时候,需要在本地执行构建命令,然后将构建产物提交到 GitHub 上面,比较麻烦。因此这边用了 GitHub Action 实现持续集成。持续集成由很多操作组成,比如拉取代码、执行测试用例、登录远程服务器,发布到第三方服务等等。GitHub 把这些操作就称为 actions。我们先来了解一下一些术语:workflow(工作流程):持续集成一次运行的过程,就是一个 workflow。job(任务):一

2021-12-12 22:15:29 1725

原创 如何调试线上项目的代码

我们知道,通常生产环境的前端代码是经过混淆压缩的,代码本身难以阅读,但有时候排查线上 bug 需要对线上项目的代码进行调试。那么如何调试线上项目的代码呢?这边介绍两种方法。直接调试我们知道,生产环境通常会使用 uglifyJS 或者 terser 进行混淆压缩,但是这些压缩工具并不会做程序流分析,因此并不是所有的变量名、方法名都会被压缩。例如模块中有一个向外导出的方法,为确保其他模块能正常调用,这个方法名不会做混淆处理,只有该模块内部的变量名、方法名才会混淆压缩。或者在代码中的字符串字面量,也不会进行压

2021-12-11 21:34:15 1679

原创 “用 Promise.then 容易出现回调地狱,所以改用 async/await” 这个说法对吗

昨天周会同事做技术分享,讲到一点:“用 Promise.then 容易出现回调地狱,所以改用 async/await”。那么这个说法对吗?首先这个说法完全错误。“Promise.then 出现回调地狱”,完全是编码不规范的问题,而不是 api 的问题。来看下面这个例子:// 解析压缩包function parseZip(zip) { return new Promise( resolve => setTimeout(resolve, 1000, zip) );}// 从压缩

2021-12-11 14:50:39 1138

原创 浅谈 Vue3 中的 v-model 和 sync 修饰符

很多同学对 Vue 的第一印象就是“响应式”、“双向绑定”等特性,而 v-model 就是实现双向绑定的语法糖,用过 Vue 的小伙伴一定都非常熟悉。但是在 Vue3 中,v-model 发生了一些改动,使得它不再兼容 Vue2 的用法,具体是什么呢,我们一起来看看。非兼容:用于自定义组件时,v-model prop 和事件默认名称已更改:prop:value -> modelValue;事件:input -> update:modelValue;非兼容:v-bind 的 .sync

2021-12-06 23:53:36 7295

原创 Jest 单元测试快速入门

测试的类型单元测试集成测试端到端测试(E2E)测试 React 组件需要解决两个关键问题怎么渲染待测试组件;怎么测试渲染出来的组件;浅层渲染对于组件渲染,Airbnb 作为重度使用 React 的先驱,早就提出了专门的解决方案:Enzyme$ npm install enzyme enzyme-adapter-react-16Enzyme 提供的一个重要功能便是组件的浅层渲染(Shallow Rendering)。它允许我们在运行测试时,只渲染父组件而不渲染其所有的子组件。浅层

2021-11-17 16:31:32 573

原创 Webpack 模块方法——require.context

在 Webpack 中,除了可以使用 import 、export 等模块语法之外,还可以使用 Webpack 提供的模块方法。其中使用最多的是 require.context 。在项目中经常会遇到一个问题,组件库导入、路由注册等需要手写大量 import ,比较麻烦。这种情况下就可以使用 require.context 。require.context( (directory: String), // 检索目录 (includeSubdirs: Boolean), // 是否检索子文件夹,默认

2021-11-13 21:08:37 1110

原创 面试官:什么时候不能使用箭头函数

今天看到这个面试题,特别有意思。一般来说面试官应该问的是箭头函数和普通函数的区别,这样应该大多数人都能答得上来,但是现在反过来,考验逆向思维,很多人可能都一下子反应不过来。我们先来回顾一下箭头函数和普通函数的区别:箭头函数没有自己的 this ,没有 argument 对象,没有 prototype ,不能作为构造函数(用 new 调用会报错)。箭头函数会自动捕获上级词法作用域的 this ,并且箭头函数的 this 在声明的时候就已经确定了,不能通过 call 或者 apply 修改。因此以下场景不

2021-11-08 22:22:13 1175

原创 TS 实现简易的 tapable

type TapEvent = string;type Handler = () => void;type EventCenter = Record<TapEvent, Handler>;interface IHook { tap: (name: TapEvent, func: Handler) => void; call: (name?: TapEvent) => void;}class SyncHook implements IHook { pri

2021-11-04 20:28:56 163

原创 手写一个简单的静态资源服务器

写了一个简单的静态资源服务器,如果文件不存在或者路径是一个目录,则返回错误信息。这里有两个特点:使用 async-to-js 进行异常处理;使用 stream ,通过 pipe 方法将 Readable 写入到 Writable ,避免 Readfile 方法一次性将整个文件加载到内存中;后期需要在响应头中加上 Content-Type 。const http = require("http");const path = require("path");const fs = require(

2021-10-29 20:30:25 87

原创 如何给开源项目提 PR

1. fork 仓库首先需要 fork 仓库。然后把 fork 之后的仓库克隆到本地。等待数秒,仓库就fork好了,可以看到个人仓库名称的下面有一个:forked from DevUI/vue-devui2. 配置 SSH 公钥,clone 代码配置好SSH公钥,即可以clone代码啦。3. 设置upstream和同步源仓库最新代码查看远程仓库地址:$ git remote -v默认情况下clone的仓库有以下两个远程地址:$ git remote -vorigin gi

2021-10-28 10:37:48 541

原创 MacOS 安装 oh-my-zsh

新买了 MBP ,打开命令行输入 ll 居然提示 command not found ,突然反应过来没有装 oh-my-zsh ,这里介绍一下安装步骤。首先从 macOS Mojave 已经自带了 Zsh ,所以直接安装 oh-my-zsh 即可。可以先试一下官网推荐的下载方式:$ sh -c "$(curl -fsSL https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)"如果下载不下来

2021-10-26 22:34:43 438

原创 GitHub 如何 pull request

这里以添加 LICENSE 为例,讲解如何使用 pull request 。建一个测试仓库,点击 add file :点击 create new file ,进入如下界面,左边输入大写 LICENSE ,右边会出现一个按钮,点击一下:选择 MIT LICENSE :然后会生成一份协议模板,根据右边的值进行填充:生成最终协议,注意下面的选项,会创建一个新分支,然后自动发起 pull request ,点击 commit new file :这边进入 pull request 界面,ad

2021-10-24 22:55:35 2349

原创 程序员节日常吐槽

最近在一个“老项目”里面用了尤大的玩具框架 Petite-Vue ,结果被一个不懂前端的领导给怼了。领导:开源项目的协议随时有可能会变,用在商用项目里面有风险吐槽:说的跟你没用过开源项目一样,Vue 不是开源?React 不是开源?Antd 不是开源?Echarts 不是开源?Webpack 、Rollup 不是开源?各种 npm 包不是开源?假如担心这个问题,那就从头到尾都自己开发吧,顺便再自研编程语言,从源头上解决问题领导:这个框架还不够成熟,项目开发应该优先考虑业界最流行、成熟的方案吐槽:你特

2021-10-24 11:05:39 1238

原创 谈谈 React 自动批处理

使用 React Hooks 的时候很多人会遇到一个问题,调用 set 方法之后,立即获取状态发现还是老的状态:const App: React.FC<{}> = () => { const [count, setCount] = React.useState(0); const handleClick = () => { setCount(val => val + 1); console.log(count); // 0 } return ( &lt

2021-10-23 22:42:55 375

原创 你不知道的 JS 代码小技巧

总结了一些开发常用的 JS 小技巧,让你的代码更优雅!1. 通过条件判断给变量赋布尔值先来看一段代码:handleFormChange(e) { let isUpload; if (e.target.value === 'upload') { isUpload = true; } else { isUpload = false; }}在项目中很多同事都会这样写,但实际上 == 和 === 的表达式可以直接给变量赋值:handleFormChange(e) {

2021-10-19 20:29:27 100

原创 如何搭建一个 npm 私服

最近在开发一个脚手架工具,但是在开发调试阶段不能发布到 npm 官方仓库上,而且后期也只希望在部门内部使用,因此就有了搭建 npm 私服的需求。虽然 npm 官方提供收费的私有仓库,考虑到现在项目需求,使用 verdaccio 不仅免费而且还简单好用。如何安装使用下面的命令全局安装:# 使用 npm$ npm i verdaccio -g# 使用 yarn$ yarn global add verdaccio...

2021-10-16 18:43:08 555

原创 ubuntu 安装 LTS 版本 Node.js

今天在阿里云服务器上安装 Node.js ,用了下面的命令:$ sudo apt-get update$ sudo apt-get install nodejs结果看了下安装的版本居然是 10.x 的,现在 LTS 版本都是 14.x 了,怎么才能安装 LTS 版本呢?网上搜了下可以在安装的时候指定版本:$ sudo apt install nodejs=14.18.1但是执行却提示找不到版本:Version ‘14.18.1’ for ‘nodejs’ was not found又到

2021-10-16 17:34:08 847

原创 从 async/await 看 redux-saga 原理

最近看了一篇神光大佬的文章:为什么 redux-saga 不能用 async await 实现 ,看完之后深有体会。虽然这篇文章没有讲具体实现原理,但是总结了两个浅显易懂的道理:async/await 本质上是一个 generator 的自动执行器,没有 runtime 逻辑;saga 实际上也是实现了 generator 执行器,但是有自己的 runtime ,可以将异步过程抽离出来,便于测试;那么很显然,搞懂 async/await 原理,redux-saga 的原理自然也就搞清楚了。1.

2021-10-12 20:34:47 237

原创 你会用 markdown ,那你会部署文档网站吗

相信大家平时都会用 markdown 编写文档,特别是配合 Typora 使用非常方便。但很多时候我们不满足于本地文档,而是要把文档做成在线的形式,这样如果内容更新,团队成员都可以及时看到。那么其实用来生成静态网站的开源项目也有不少,例如 VuePress ,Docsify 等,特别是 VuePress 已经广泛用于 Vue 官方文档在内的各种文档的部署。但是 VuePress 是基于 Vue 的,而本人现在团队主要使用 React 技术栈,于是采用了和 VuePress 类似的由 facebook 团队

2021-10-10 17:02:57 1077

原创 Golang 快速入门(一):创建一个 Go 模块

在下面代码中,向任何调用者返回问候语:package greetingsimport "fmt"// Hello returns a greeting for the named person.func Hello(name string) string { // Return a greeting that embeds the name in a message. message := fmt.Sprintf("Hi, %v. Welcome!", name) ret

2021-10-07 15:34:02 326

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除