极客时间《设计模式之美》手把手带你还原访问者模式诞生的思维过程

需求 假设我们从网站上爬取了很多资源文件,它们的格式有三种:PDF、PPT、Word。我们现在要开发一个工具来处理这批资源文件。这个工具的其中一个功能是,把这些资源文件中的文本内容抽取出来放到 txt 文件中。如果让你来实现,你会怎么来做呢? 第一版 public abstract class ResourceFile { protected String filePath; public ResourceFile(String filePath) { this.filePath = filePath; } public abstract void extract2txt(); } public class PPTFile extends ResourceFile { public PPTFile(String filePath) { super(filePath); } @Override public void extract2txt() { //…省略一大坨从PPT中抽取文本的代码… //…将抽取出来的文本保存在跟filePath同名的.txt文件中… System.out.println("Extract PPT."); } } public Read more…

自定义分词起始规则实现关键词全词高亮项目实战(全语种通吃)

背景 最近有BU给我们这边提了一个需求,希望我们能改进现有的内容关键词匹配功能,希望能支持英文的全词匹配。 目前前端页面是会对后台配置的关键词进行高亮显示的,只不过算是模糊匹配了,也就是说如果关键词配的是book,内容中的booked中的book也会高亮,而这并不是BU希望的。 现状 我看了下原来高亮功能的具体实现 export function escapeHtml(text) { var map = { '&': '&', '<': '<', '>': '>', '"': '"', "'": '&#039;', }; return text.replace(/[&<>"']/g, function(m) { return map[m]; }); } // 搜索html关键字并高亮 export function htmlKeyWordHighlight(parentNode, keyWards, color = 'yellow') { if (keyWards === void 0 || !parentNode) return; Read more…

nodejs爬虫superagent爬取gb2312编码网页中文乱码

今天爬取某个古老的网站的数据,发现中文乱码。 这个网站从外观上看也够古老的,是偏政企类网页,这种项目一般也都是外包出去的,技术更新速度也是可想而知,里面竟然还是写死的gb2312,还有三层table嵌套。 在网上搜了下,有的不少文章说的可能方法是过时,反正我实测没效果。 在npm上搜了下superagent,发现官方就提到了一个charset插件superagent-charset,superagent-charset的官方github上就给出来示例代码。 const should = require('should') const request = require('superagent') require('superagent-charset')(request) // install charset describe('Basic Test', function() { it('it works', function(done) { request.get('http://www.sohu.com/') .charset('gbk') .end((err, res) => { res.text.should.match(/搜狐/) done(err) }) }) }) 果然,搞定了。 const superagent= require('superagent'); require('superagent-charset')(superagent) const cheerio = require('cheerio'); function getResponse(url, charset = 'utf8') { Read more…

了解网页性能指标(getTTFB,getFCP,getLCP,getFID,getCLS)的含义,通过实战理解各指标影响因素

Google公司的Web Vitals旨在为质量信号提供统一的指导,方便一个网站量化用户体验的性能指标,其中常用的指标有TTFB,FCP,LCP,FID,CLS。 npm包 import {getTTFB, getFCP, getLCP, getFID, getCLS} from 'web-vitals'; getTTFB(console.log); getFCP(console.log); getLCP(console.log); getFID(console.log); getCLS(console.log); 如果我们想以CDN的形式使用web-vitals <body> <script type="module"> import {getTTFB, getFCP, getLCP, getFID, getCLS} from 'https://unpkg.com/web-vitals@2.1.4/dist/web-vitals.js?module'; getTTFB(console.log); getFCP(console.log); getLCP(console.log); getFID(console.log); getCLS(console.log); </script> </body> 接下来的内容里面我们用express+ejs模板来模拟测试这几个指标变化。 指标详解 TTFB(Time to First Byte )首字节时间 TTFB衡量您的服务器对访问者浏览器请求的响应能力。换句话说,它是用户到达网页和服务器识别它之间所花费的时间,俗称“白屏时间”。 浏览器从服务器接收首字节数据所需的时间越长,意味着加载页面所需的时间就越长,并且因为TTFB是最初的交互,很长的首字节时间意味着页面的其余部分甚至无法开始加载,所以这是一个很基础,也很致命的指标。 评级 200毫秒以下 好 200毫秒和500毫秒之间 需要改进 超过600毫秒 Read more…

Jetbrains旗下IDEA系列产品将于2022.10.1起涨价,最多一次性购买三年

官方的涨价声明原文 Increased Subscription Pricing for IDEs, .NET Tools, and the All Products Pack 想想自己也算使用过不少编辑器,最开始用的是记事本、UltraEdit、EditPlus、Notepad++,在几年前开始做开发之后就跟着同事使用Sublime text了,然后被公司来的一个新同事认识了VS Code和Webstorm,瞬间感觉自己之前用编辑器,VS Code和Webstorm算是IDE了。 入行那家公司电脑配置太低,跑Webstorm还是很吃力的,等换了新公司就开始主要使用Webstorm了,自从发现它的Local History功能后更是爱不释手了,Diff、Refactor都是很棒的功能,合并代码时解决冲突也是相当方便。 惭愧的是自己一直使用的破解版的,使用过如下的破解方式: Licence server 直接用一个jar包破解的 用Eval reset插件的方式 自己几年前还弄个一次学生优惠。。。 今天心血来潮想支持下Jetbrains公司的正版产品,就买个最便宜的Webstorm吧,三年141美元,说干就干,没必要等到9月30日那天再出手。IDEA的需求不强烈,省点银子吧,暂不考虑了。 Jetbrains公司主要是指望企业用户盈利了,还是给很多群体可以免费使用的资质的,还是当学生好,以前怎么没发现有这么优惠可以呢。。。 希望后面能靠自己获得Jetbrains公司给予的免费使用资质吧。 等付完费想起自己的Macbook也是8月份买的,查了查之前的订单,发现居然也是8月19号下单的,好巧。 自己近期有些颓废,工作之余写代码较之前有所减少,这可不行啊,现在开始安心用几年正版吧,疯狂打码吧!

React执行调度流程梳理笔记

触发更新 我们最常见的触发更新的方式就是更新state了,可以分别从类组件和函数组件看看这时会发生什么。 类组件之 setState: 当触发setState本质上是调用enqueueSetState。 enqueueSetState(inst,payload,callback){ const update = createUpdate(eventTime, lane); enqueueUpdate(fiber, update, lane); const root = scheduleUpdateOnFiber(fiber, lane, eventTime); } 函数组件之 useState 再看一下 hooks 的useState。 function dispatchAction(fiber, queue, action) { var lane = requestUpdateLane(fiber); scheduleUpdateOnFiber(fiber, lane, eventTime); } 可以看出来useState,setState最后都是调用scheduleUpdateOnFiber方法。 看看scheduleUpdateOnFiber方法的原理吧 export function scheduleUpdateOnFiber(fiber,lane,eventTime){ if (lane === SyncLane) { if Read more…

amh.sh免费泛域名https证书 自动续期

自己的网站一直使用的https,用ssl证书就是在腾讯云免费申请的,有限期一年,过期了可以再次申请。腾讯云说是有50个免费名额,个人觉得还是够用的。 要说缺点的话也是有的 不能自动续期 不支持泛域名(比如*.daozhao.com),每个二级域名就需要自己申请了 自己在网上搜了下,有说可以免费使用泛域名ssl证书的,就是利用 Let’s Encrypt来实现的,有效期3个月。 我是直接借助的amh.sh的功能(其实也是Let’s Encrypt) amh.sh官网手动生成ssl证书 打开https://amh.sh/ssl.htm 这里需要使用dns验证 在自己的域名解析那里添加一条叫_acme-challenge的txt记录 等截图中的两处都验证通过后,界面上就会显示生成的证书的key和crt了,这是就可以把内容复制出来直接使用了。 使用amh.sh脚本自动续期 如果选择的是mysql8的话,对主机的性能要求较高,并且安装时长预估是73分钟,我是试了两次都没成功,直接把主机给整挂了。。。 反正我只是想使用自动续期功能,根本不使用这里面的mysql,所以现在了mysql5.x,二十几分钟就行了。 在自己的主机执行wget http://dl.amh.sh/amh.sh && bash amh.sh nginx-1.20,mysql-5.5,php-7.4,根据提示安装成功后,页面会给出AMH和mysql的初始账号和密码,可以使用8888端口来访问,记得在防火墙出开启8888端口的访问权限。

axios请求https网站报错Unable to verify the first certificate

今天在使用axios出现了一个错误Unable to verify the first certificate,就感觉是证书的问题,自己手动在浏览器中输入https的网站没问题啊,但是在用axios请求的时候还是出问题了,最后之后看看能不能屏蔽掉这个检测了。 可以采用下列任意一个方法解决 方法一:直接使用忽略了ssl检测的axios实例 const https = require("https"); const axios = require("axios"); const ignoreSSLAxios = axios.create({   httpsAgent: new https.Agent({     rejectUnauthorized: false,   }), }); ignoreSSLAxios.get("http://example.com/getData.do", { httpsAgent: agent }).then((res) => res.data); 以后直接用实例ignoreSSLAxios发送请求了 方法二:单次请求的时候忽略ssl检测 // 在 axios 请求时,选择性忽略 SSL const https = require("https"); const Read more…

web新开窗口场景降低加载耗时实战

背景 在PC端web项目中经常会出现要开新窗口打开某个页面的场景,一般来说这个新窗口(窗口B)很可能跟之前的窗口(窗口A)功能基本一致,只不过之前的窗口A打开的是a页面,新窗口B打开的B页面,其实两个窗口的内容是同一个应用,它们都是可以打开a页面和b页面的,既然是同一个应用的话,新开窗口B是不是就不必全部调用相同的接口了,我们是不是可以优化一下。 我这边的邮件项目就有类似的需求,它一个套着electron壳的web mpa项目,主窗口打开邮件页面,需要像outlook类似,能够将列表中的邮件以独立窗口形式打开,打开的这个新窗口也具备完整的邮件功能,所以它也会重新调用一系列的权限、配置接口,然后开始打开对应的邮件。 操作场景 客服在主窗口编辑邮件时可以点击切换至独立窗口,然后在独立窗口中继续进行内容编辑。 切换至独立窗口继续编辑过程请求链路示意图 优化过程 现状 客服点击切换后主窗口调用接口保存当前编辑内容为草稿,待接口保存成功后再打开独立窗口调用接口读取该草稿并加载至编辑器中,也就是借助服务端完成窗口切换过程中编辑内容的存取。 独立窗口同时还需要完成处理邮件流程必要的配置信息相关接口调用。 优化思路 客服点击切换后主窗口直接存储编辑内容至本地即可打开独立窗口,独立窗口直接加载本地存储内容至编辑器中,也就是直接通过本地完成窗口切换过程中编辑内容的存取。 主窗口处理邮件需要的配置信息接口数据之前在调用后完成本地存储,独立窗口加载时也直接从本地读取对应内容。 技术实现 尽量避免在各个业务逻辑中加入切换存取的代码侵入,决定将该切换过程放至ajax调用层 在主窗口发送ajax时直接对特定接口数据进行本地缓存 启动独立窗口时发送ajax时判断是直接返回上次的缓存数据,还是http请求数据 优化后接口请求流程示意图 数据统计 从主窗口编辑切换至独立窗口编辑主要经历以下流程 主窗口保存草稿 启动独立窗口 独立窗口读取配置、读取内容 目前第2点启动独立窗口不可控,仅对本地存储优化的第1和第3个节点进行耗时统计 阶段对比 主窗口 独立窗口 总耗时 FCP TTFB LCP FID CLS 优化前第一次采样 194.174 1907.0 2101.2 899.65 34.945 3041.814 0.37 0.000211 优化前第二次采样 209.383 1989.0 2198.4 892.2 36.875 1832.875 Read more…

记录CKEditor4删除文本引起文本分割而升级版本的经历

背景 前段时间对接了一个electron壳提供功能————拼写检查,也就是在输入的英文有问题的时候,给予红色波浪线提示,邮件的时候能出现候选词,选择候选词后进行替换。 在功能上线当天上午产品经理发现邮件的富文本编辑器CKEditor内部分场景无法正常简写拼写替换。。。 问题复现 我们输入正确的英文单词Successfully,此时不会有红色波浪线,符合预期,但是如果此时在中间删掉一个字母(比如u),使其变成错误的单词Successflly,这时能出现波浪线,但是在点击右键,准备读取候选词的时候会出现错误。 考虑到写完单词后再进行删除这一操作还算是个很平常的使用场景,加上临近上线了,决定先暂停右键菜单里面的拼写检查入口。 我们是在最后面的单词y那里点击邮件的,此时自动选中的只有后面的lly,而不是预期的Successflly,因此右键菜单里面的候选词也就不符合预期了,因为候选词是根据此时选中词lly给出的。 因为拼写检查的大部分功能我们都不可控,都是chrome提供的,我们需要看下为什么引起chrome自动选词“错误”。 经查发现原来是我们在删除字母u的时候,编辑器将之前的单词由一个文本分成了两个文本节点。虽然在表象上看是一个文本Successflly,但实际上是Success和flly两个文本。 所以我们chrome在自动选词的时候就只选择了后面的lly,如果我们在前面的波浪线处,点击鼠标右键,这时就只会选中前面的。 这类问题多半是由编辑器底层的机制决定的,所以我们首先去官网看看,看看官网的demo里面的编辑器是不是也有类似的问题,试了下并没有,再看版本,官网的是最新版本4.19.0,我们项目中用的是4.17.0,下载4.17.0的官网版本试试,也有类似的问题,据此我们尝试升级自己项目的CKEditor版本为4.19.0,最后问题解决。 总结 对于这类我们使用第三方库发现问题的场景,建议大家也安装类似的步骤排障和解决问题 官网验证确认官方是否存在该问题 官网没问题就验证项目当前版本(一般可能会比官网的版本低)对应的官网版本是否存在该问题 逐步验证是否是自己的插件或其它改动引起的问题 自己尝试修复或者给官方提Issue