徐伟晋徐伟晋徐伟晋徐伟晋
  • 徐伟晋日常问题解决办法汇总2年前评论数:0
    certbot ImportError: cannot import name constants解决方案
    ## 前因 今天ssl证书要到期,登录服务器准备用certbot更新一下,结果执行certbot指令的时候报了下面的错: ```shell [root@VM-0-12-centos /]# certbot --version An unexpected error occurred: ImportError: cannot import name constants ``` 按照提示查看 `/tmp/tmpLYYslI/log`,错误信息如下: ```shell 2021-09-10 10:06:38,511:DEBUG:certbot._internal.log:Exiting abnormally: Traceback (most recent call last): File "/usr/bin/certbot", line 9, in <module> load_entry_point('certbot==1.11.0', 'console_scripts', 'certbot')() File "/usr/lib/python2.7/site-packages/certbot/main.py", line 15, in main return internal_main.main(cli_args) File "/usr/lib/python2.7/site-packages/certbot/_internal/main.py", line 1383, in main plugins = plugins_disco.PluginsRegistry.find_all() File "/usr/lib/python2.7/site-packages/certbot/_internal/plugins/disco.py", line 236, in find_all plugin_ep = cls._load_entry_point(entry_point, plugins, with_prefix=False) File "/usr/lib/python2.7/site-packages/certbot/_internal/plugins/disco.py", line 254, in _load_entry_point plugin_ep = PluginEntryPoint(entry_point, with_prefix) File "/usr/lib/python2.7/site-packages/certbot/_internal/plugins/disco.py", line 56, in __init__ self.plugin_cls = entry_point.load() File "/usr/lib/python2.7/site-packages/pkg_resources/__init__.py", line 2405, in load return self.resolve() File "/usr/lib/python2.7/site-packages/pkg_resources/__init__.py", line 2411, in resolve module = __import__(self.module_name, fromlist=['__name__'], level=0) File "/usr/lib/python2.7/site-packages/certbot_nginx/configurator.py", line 16, in <module> from certbot import constants as core_constants ImportError: cannot import name constants ``` 从错误信息中可以看到是最后一行 `certbot_nginx` 报的错 ## 解决方案 首先我们执行下面的指令查看一下certbot的版本 ```shell [root@VM-0-12-centos /]# rpm -qa|grep certbot certbot-1.11.0-1.el7.noarch python2-certbot-1.11.0-1.el7.noarch ``` 可以看到只有`certbot` 和 `python2-certbot` 两个插件,并没有`certbot-nginx`这个插件,我们是在`nginx`环境上安装证书,所以还需要 `python2-certbot-nginx` 插件,通过以下指令安装: ```shell yum install python2-certbot-nginx ``` 安装完成后再执行certbot就不会报错了。 ## 更新证书 我们先执行 `certbot --nginx` ,然后根据提示输入自己的网站域名,结果发现报如下错: ```shell Client with the currently selected authenticator does not support any combination of challenges that will satisfy the CA. You may need to use an authenticator plugin that can do challenges over DNS. ``` 这是因为我们的服务器不支持这种dns认证方式,我们换一种方式: ```shell certbot certonly --preferred-challenges dns --manual -d *.xuweijin.com --server https://acme-v02.api.letsencrypt.org/directory ``` 执行后,它会让我们去域名后台添加一条txt认证记录,添加完成后直接回车,可以看到新的ssl证书已经生成了。 ```shell Before continuing, verify the record is deployed. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Press Enter to Continue Waiting for verification... Cleaning up challenges IMPORTANT NOTES: - Congratulations! Your certificate and chain have been saved at: ``` 之后我们重启nginx,新的证书就生效了。
  • 徐伟晋读书笔记2年前评论数:0
    《小狗钱钱》读后感
    首先是慕名而来,被网上的评价吸引的,可以说是入门理财必读书了。 内容是以童话的形式展开的,所以其实更适合小朋友读。而且关于理财的方面讲得比较浅,通篇下来没有深奥的理财知识。讲得更多的是关于做人方面的道理。 钱钱是一条会说话的小狗,小主人公吉娅在钱钱的指引下,一点点的改变,并最终帮助爸爸妈妈解决经济危机。里面的一些方法确实很值得借鉴。很多道理也都感同身受,因此记录下来,时时回顾。 72小时定理。当你决定要做一件事的时候,一定要在72小时内完成它,否则你可能永远都不会再做了。这个真的深有感触。每次想到一个好的idea,总是不能第一时间去执行,而是觉得自己手头事情太多,等手头事情完成,再去实施,可几乎都没有下文了。着手做一件事情的时候,不要想着尝试去做,这样就给了你退路,有了退路,你就不会尽全力地去做,自然也就没有好的结果。要在一开始就破釜沉舟全力以赴,即使最后真的没能完成,也问心无愧。 要有梦想。写出自己想要的10件事,最后留下对你来说最重要的3个,并为了这个目标,持之不懈地努力。有了目标才有努力的方向。 写成功日记。这个其实很好理解,也不难执行,每天写下几件你觉得值得骄傲的事情,小到受到某人的表扬,大到获得某个荣誉。可能每天抽出5分钟的时间就能完成。一方面可以用来记录,另一方面当你遇到挫折的时候,翻出来看看,喝碗自己的鸡汤,相信什么困难都不在话下。 要有自己的“鹅”。这里的鹅说的不是会咬人的大鹅,而是会为带来收益的本金。文中提倡大家按5-4-1的比例分配自己的收入。50%的收入用来当鹅,下“金蛋”,40%的收入当自己的梦想基金,10%的收入自由支配。只有有了自己的鹅,让鹅不停地为自己下蛋,财富才会越来越多。当我们年化收益达到10个点的时候,只需要7年,我们拥有的财富就能翻倍。 要听从专业人士的指导和意见。文中的金先生和海瑞女士都是在某一方面拥有极其专业的知识和智慧。小主人公遇到问题向他们请教的时候,总是能得到最恰当的指导,因此也少走了很多弯路。 有7条人生准则要时刻铭记,这将会使我们收益终生。 - 友好亲和 - 勇于承担 - 善待他人 - 帮助给予 - 感恩之心 - 勤学不辍 - 值得信赖 如果能在为人处世中时时做到以上7条,即使我们没有很多财富,但我们也能提升自己的内在,让别人在跟我们相处时感到愉悦。 最后,虽说想从这本书中学会高深的投资之道几乎没有可能,但用来作为理财新手入门还是一个很不错的选择,书中对于如何分配自己的财产,如何选择合适的基金都有相应的描述。 对我个人最大的收益其实并不是如何理财,而是让我学到了很多做人的道理,我也希望自己能在日后的学习工作中,践行这些原则,时刻警醒自己,不断进步。
  • 徐伟晋日常问题解决办法汇总3年前评论数:1
    NextJs api 处理formdata文件
    ### 前言 最近在使用nextjs开发一个小工具时,用到的一个处理文件的库需要在node环境中使用,根据next文档,通过api-router接收文件,可是却不能取出我想要的文件类型。 ### 现象 后台拿到的文件格式如下 ```bash ------WebKitFormBoundaryJtq2NXST1auONfqf Content-Disposition: form-data; name="file"; filename="basic.xlsx" Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet PK �N�@ docProps/P�N�@�{4SdocProp ``` 我需要的是file文件或者stream,因此这个格式就不能满足我的需求 ### 原因 查阅官方文档,解释如下: > bodyParser Enables body parsing, you can disable it if you want to consume it as a Stream: ```js export const config = { api: { bodyParser: false, }, } ``` 所以需要我们关闭默认的bodyParser,然后自己去选择解析的库,我这里用的是node自带的formidable。 ### 解决方案及代码实现 前端上传文件代码如下: ```js const upload = async e => { const file = e.target.files[0] const formData = new FormData() formData.append('file', file) fetch('/api/hello', { method: 'post', body: formData }).then(res => res.json()). then(data => { // doing something... }) } ``` 后端接收处理代码如下: ```js import { IncomingForm } from 'formidable' // 关闭next默认的bodyParser处理方式 export const config = { api: { bodyParser: false, } } export default async (req, res) => { const form = new IncomingForm() const data = await new Promise((res, rej) => { form.parse(req, function(err, fields, files) { if(err) rej(err) res({fields, files}) }) }) const {fields, files} = data // doing something... res.status(200).json({code: 200, msg: 'success'}) } ```
  • 徐伟晋个人总结3年前评论数:0
    2020年终总结
    弹指一挥间,2020年就这么过去了。有过快乐,有过痛苦,有过绝望,有过期盼。无论过程无何,那些经历的事,那么相遇的人,都成为记忆中的一份子。手指搭上键盘,思绪万千,想写的话想记录的事很多,可又不知从何写起。那就想到哪写到哪吧。 ### 1. 开篇 2020年是六十年一遇的庚子年,回顾历史,200年以来,每一个甲子年对中国来说都不太平。 - 1840年,第一鸦片战争,西方列强用大炮轰开了这个古老封闭的满清王朝,为百年屈辱史拉开了序幕。 - 1900年,八国联军侵华,签订了辛丑条约,需赔偿白银4亿5千万两,史称庚子赔款。 - 1960年,3年大饥荒最严重的一年,饿死人数达上千万。 - 2020年,还没到农历新年,新冠疫情爆发,武汉封城。为了阻断病毒传播,所有人都在家隔离。整个中国仿佛按下了暂停键。 ### 2. 生活 - 富人的生活千姿百态,穷人的生活千篇一律。 虽然穷,但也不能对生活失去希望,挑出今年比较有意义的两件事记录一下。 1. 学做饭 印象中,自己除了下面条,好像就什么也不会做了。唯一一次炒菜是在初中的时候,中午家里没人,自己炒了个茄子,结果盐放多了。虽然齁咸,但毕竟是自己第一次炒菜,还是含泪给吃完了。时隔多年,再次颠勺,想想还有点激动。 到北京的第一天,就在京东上买了米饭油盐酱醋等,下了个下厨房,里面的教程还是挺详细的。后面也学会了很多家常菜,只要是炒的,基本上都会做了。但是对处理鸡鸭鱼这些,到今天也没有尝试。。做的最复杂的一道菜,应该是可乐鸡翅了。虽然卖相不怎么样,但吃起来还不错。 2. 增驾D照,买摩托 电动车买了2年了,电池容量缩减严重,已经沦落到一天一充了。住的地方不让充电,周末想出门买个东西都不敢骑,怕上班了电池撑不到公司。买摩托的想法就越来越强烈。5月的一天,我去驾校报了名,先增驾。咱是遵纪守法良民,肯定不能无证驾驶。 D照比C照简单,先看题考科一,轻松过关。然后是场地实车练习,别的项目都没问题,就是单边桥这个项目,频频出现失误,看不准教练给定的线,靠自己感觉也靠不住,3次大概会有一次失败。一共练了2天,由于没做好防晒,脸都晒脱皮了。2天练完,还是会在单边桥出现失误。只能赶鸭子上架了,科二科三是同一天考试。幸运的是,考试当天,居然一遍就过了。接下里就是科四了,也没什么难度,最终顺利增驾成功。 考驾照的时候就在看车了,我的主要需求是通勤,周末偶尔出去转转。既然是通勤,自然是风雨无阻,所以踏板更合适,下雨可以穿雨衣,冬天可以装挡风披。所以就敲定踏板,预算不是很充足,在1w5以内,最终上网看各种测评口碑,最终选中今年最火的通勤踏板铃木uy125。火到什么程度呢,我足足等了一个月车才到店里。立马请了一天假去车管所办手续。办好之后,又找车行老板给上了盗抢险,事实证明这是个多么英明的决定。交完尾款,我就骑着小黑回家了。 从此以后,我的通勤方式就从电动车升级到摩托车,虽然外观看起来差别不大,虽然操作方式完全一样,都是给油就走,但它给我带来的快乐真的不是电动车能比的。再也没有了里程焦虑症,再也不用每天充电,周末想去哪,说走就走,喝奶茶,买糕点,自取外卖。。甚至每天早上上班也不痛苦了,因为可以骑车,哈哈哈哈就是这么快乐! 感受到了骑车的快乐,我甚至注册了美团账号,周末送起了外卖!害怕超时也不想太赶,万一着急忙慌出了事故太不值当,所以我每次只接一单。送了几次,觉得没意思了,而且受不了美团的压榨,就把众包给卸载了。 快乐是短暂的,9月22号,我的小黑被偷了。晚上下班,在楼前楼后找了好几遍,才确定被人偷走了。报警,填资料,等消息,一气呵成。然而直到现在,也没有任何消息传来。幸好我之前买了盗抢险,也算是挽回了大半损失。本来想着再买一辆,但眼看着天冷了,最后决定先不买了。明年开春,等我! ### 3. 工作 因为疫情,上半年公司的业务有些停滞,大家都是在家办公,由于沟通成本以及每个人的情况,工作效率也不是很高。种种原因,最终在今年9月份入职了新的公司。 1. 中博的结束 > 2018.5.30 - 2020.9.4 老实说,我是一个很恋旧的人,直到办完了离职手续,还是有很多留恋。 两个领导都是很随和的人,没有一点领导架子。同事间氛围也都很好,从没跟谁红过脸闹过别扭。每天上班,敲敲代码打打闹闹,下午一块出去转转,透透气,一天就过去了。 工作内容呢由于我负责的是教学中心,是给公司内部员工使用的,迭代很慢,工作压力自然也不大。今年大半年的时候,就做了两个稍大的需求,其他时间都是在优化或者是小的调整。我自制力也差,几乎不会去主动找活干,所以没需求的情况下,几乎没有任何进步。 今年6月份,有天跟我对象聊起我的工作近况,我说我有些迷茫,不知道到底该不该换工作。其实我内心也有些换工作的想法,只是个人实在难以下定决心。最后在她的鼓舞下,我更新了简历,放到了招聘平台上。也看了几篇面试,背了些面试题,然后就开始了我佛系的求职。被动地回复hr的招呼,离得远不去,规模小不去,初面不能在线面试不去。。 由于我很不主动,所以面试机会并不多。京东、58、360、火花思维等,可惜因为自己能力不足,几乎都挂在了初面上。接连几次的失败,也彻底打击了我的积极性和自信,我开始怀疑自己,是不是自己工作了这么多年,还是毫无长进。虽然心里这么觉得,但还是不愿付诸行动,白天上班敲业务代码,晚上回家打游戏,根本没把面试这回事放心上。后面面试的成功率越来越低。一直到8月份,面试迎来了转机,我接到了vipkid的面试邀请。因为跟我当前的业务很接近,都是做教育的,我面试表现的也还行,一共经历了4面,最终拿到了offer。 上网查了查,觉得这个公司还不错,薪资也还算满意,就跟领导提了离职。领导象征性地挽留了一下,也就同意了。当时手上还有一个需求没做完,就跟领导定到半个月后办离职手续。在中博的最后一天,我跟几个要好的同事约了下班一块吃散伙饭。下午办完了离职手续。晚上6点半,下班了,想着下周一就要去入职了,可是hr背调结果还没有给我,我觉得应该没什么问题,之前hr跟我说如果背调有问题,会提前通知我。为了保险起见,我还是给hr发了微信,过了会,他语音打过来了,跟我说背调没过,说自己太忙,忘了通知我了。 ![https://img.xuweijin.com/16097678870201img.png](https://img.xuweijin.com/16097678870201img.png) 我已经不知道当时是怎么挂的语音,脑海中只有一个念头,**我失业了**。 已经跟同事约好了去吃饭,也不想临时扫了他们的兴,心事重重地吃完饭后,互道珍重,就各自回家了。 中博彻底成了我的老东家,很感谢领导的栽培和同事的帮助,很多感谢的话当面没说,真的就再也没机会了。 2. 找工作那些事儿 回顾自己的打工生涯,自打工作开始,居然没有请过一天事假。对别人说是请假也没事干,说白了就是穷,舍不得一天几百块的工资。 由于背调没过,被迫失业在家,沉沦了一天。怕爸妈担心,就跟他们说暂时不去那家公司入职,想再找找看有没有更合适的。小时候有了一点委屈,受了一点挫折,总是第一时间想让爸妈知道,从他们那得到安慰。长大后,无论好坏,总是报喜不报忧,这就是每个异地打工人的现状吧。 这是我工作以来第一次失业,之前换工作都是无缝衔接。因此找工作的心态也发生了很大变化。要考虑的事还有很多,比如社保公积金断缴。跟之前佛系找工作不同,一天不入职就意味着职业断层更大,所以周日在家看了看面试题。周一投了一天的简历,所幸面试邀约还不少,不管大公司小公司,先去面试再说,正好现在没工作,不用担心请不掉假。最终一边面试一边投简历,4天大概面了近20家。 ![https://img.xuweijin.com/16097679995802img.png](https://img.xuweijin.com/16097679995802img.png) 上面是我的面试排期,几乎每天都有5家。而且大多都是现场面试。我尽可能把地方相近的公司排在一天面试,缩减我的通勤时间。虽然每天要跑好几个地方,但我一点也不觉得累。9月份秋高气爽,不冷不热,骑上我的小黑,真的非常惬意。那几天确实过足了骑车的瘾。 面试第一天有两家面试的公司在同一栋楼,一家是上午的一家是下午的,上午的面试结束的很快,挂了。。然后给下午那家打电话,问能不能上午就面试,可惜面试官在开会,没办法,只能等到下午再面。然后我骑车在周围找地方吃了个饭,吃完饭后在楼下找了个阴凉地,拿出电脑,看面试题。看不进去,想着每天这么骑车出去走走转转,好像也不错。 ![https://img.xuweijin.com/16097680458183img.png](https://img.xuweijin.com/16097680458183img.png) 躺车上小憩会儿 也只是一瞬间的想法,摇了摇头,赶走这个不切实际的想法,继续投递简历&赶赴面试的轮回。好在功夫不负有心人,也许是我面试的排期很满,总会有那么三两家合胃口的,所以也陆陆续续接到了几个offer。本来还想再面一周,可是想到9月15号前不入职社保就是断缴,就放弃了之后的面试,选择入职。至此,经过一周的奔波,我从一个失业者又变成了打工人。 3. 蓝城的开始 新公司,感觉一切都好。更大的环境,更广的业务,更多的受众。同样伴随而来的是更大的压力。这里的每个人都很努力,都有着自己的特长。跟同事们交流的越多,越意识到自己的不足。回想起以前,确实是太安逸了,甚至有些沾沾自喜。现在看来,不禁羞愧不止。 目前业务用的是react,后台用的是node,正好是我想要研究的领域。当时选择蓝城也是因为业务需求很合胃口。由于现在刚入职不久,所以这几个月就做了几个简单的活动业务,还有对之前已有的需求进行迭代和修复。虽然需求都不难,但每次都感觉用尽我的全力,比之前写系统业务更吃力。 为什么会出现这种情况?细细思考了一下,大概有这几点原因。 - 之前环境太安逸,导致自己接需求的能力和思维能力都有下滑。 - 多环境、还要自己写接口,很乱,以前只负责前端代码,所以对需求的拆解以及前后端代码的管理能力不足。 - 新的校验规则和typescript写法,之前没有系统研究过,所以本能会怵一些。 总之,一切都是新的,困难只是暂时的。上面的这些问题,说白了,还是自己能力不够,将作为新的一年工作的重点去突破自己。 ### 4. 学习 1. 服务端渲染 上半年用了nuxt.js做服务端渲染,这个是vue框架的ssr解决方案,感觉跟vue的写法差不多,就是把页面的初始化请求放在服务端,再通过nuxt提供的Head方法,对页面的title、meta等seo信息做处理,方便爬虫去爬取。 之后想着我自己的博客网站是用react搭的,就去看了看next.js框架,跟nuxt很像,就是在next中使用cookie和redux废了一番周折,其他的例如页面请求,head自定义,首屏渲染,按照给出的文档做就能实现。最后只简单搭了个架子,[https://life.xuweijin.com](https://life.xuweijin.com),很多内容还有待补充。 2. 服务器迁移 之前服务器用的是阿里的,当时想着能(其)用(实)就(是)行(穷),就买了个最低配的,1核2G1M带宽,服务器跟内存还可以忍受,因为不跑大的项目,所以还算顺畅,就是1M带宽简直是噩梦。博客用的是react搭建的,每次进博客都得等20多s,后来开启了gzip,还是得10多S! 今年双十一,看着腾讯云优惠力度挺大,2核4G3M带宽3年才800块,当时还犹豫了一下,因为我阿里云的还有半年才到期,最后想着早买早享受,双十一也不能啥都不买呀。别人双十一都是买衣服买鞋买化妆品,然后我双十一买了个服务器。不愧是我哈哈哈。 买完之后,就着手迁移了。之前阿里的服务器各种配置实在是不想再配一次。咨询腾讯客服,原以为会很麻烦,结果只是在服务器下载一个工具,然后就可以迁移了,很简单。等待了近8个小时,总算是成功了。迫不及待地登上服务器开启各种服务,数据库、nginx、后台服务等。 把我半成品的服务端渲染项目的博客打包上去,访问,居然只要1s多就进去了!跟之前10多s的访问速度相比,简直一个天上一个地下。果然没有花钱的不是! ![https://img.xuweijin.com/16097680907374img.png](https://img.xuweijin.com/16097680907374img.png) 可以看到打开首页只需要1.6s 3. CI/CD 其实去年就大致了解了一下CI/CD,当时用的是jenkins,搭到一半觉得效果跟我预想的不一样,提交了代码之后还得去控制台点击构建,就放弃了。 来到蓝城,公司用的是自建的gitlab,自动化用的是gitlab官方提供的action。把代码提交到git后,不用做多余的操作,它会根据仓库里的gitlab.yml文件去自动运行检测打包构建等一系列操作,正是我想要的结果。 我上网查了下自建gitlab需要的配置,新买的服务器刚好满足。按照gitlab官方文档开始搭建自己的gitlab,这个过程很简单,很快就完成。接下来是在服务器上开启gitlab-run服务,用来监听代码的提交,以及gitlab.yml文件的解析执行。后续没有什么问题,就是做免密登录的时候,费了一番周折,最终也算是成功了。 之前觉得这个很简单,真的是自己眼高手低,实际操作才发现,会看和会用还是有一定区别的。有些坑不自己动手操作一遍,可能永远也遇不到。有些问题看起来很简单,但是在不了解其背后原理的情况下,排查起来真的非常麻烦。有很多因素,比如环境,比如版本,比如权限等等。 ### 5. 结束 & 展望未来 洋洋洒洒写了一大篇,很乱。自打从高考结束,就没写过作文。也算是一个开始,希望以后坚持,不管写的好坏,每年都留下一篇年终。 1. 总结、遗憾 总体来说,今年算是好坏参半吧。生活就是这样,不可能事事称心如意,好在我还算乐观,自嘲是鲁迅先生说的阿Q精神。 换了一家公司,对我个人成长有很大帮助,工资也稍稍涨了一点。 遗憾的是,原打算利用十一骑着小黑出去转转,可惜后面没走成。 > 曾梦想仗剑走天涯,回头一看马被偷了 通过跟政府打交道也明白了社会从来不像网上的那么美好。 今年的技术水平几乎没有提升,用nuxt重构博客也只开了个头,自制力依旧那么差。一年至少去一个城市转转的目标也没有实现。 2. 明年的计划 & 目标 > 梦想总是要有的,万一实现了呢。 - 首先是提升自己的竞争力,以设计模式为主,掌握10种以上设计模式。 - 提升自己react开发能力,现在实在太弱,勉强会用。 - 完成博客的重构。 - 2个月读一本课外书(实在是不怎么爱看课外书,所以时间拉长一些)。 - 理财收益达到12%以上。 - 去至少一个城市。 2020,多灾多难的一年,无论好坏,无论得失,就这么过去了。2021,又是充满希望的一年! 加油吧,朝着自己的目标,一步一步脚印,你可以的!!
  • 徐伟晋日常问题解决办法汇总3年前评论数:3
    next.js引入antd,使用less文件,配置时报错。
    ## 前因 按照网上的博文方法引入antd,配置完后,启动一直报错,报错信息如下: ```js > Location: "/Users/xuweijin/Desktop/study/nextJsdemo/nextjsdemo/.babelrc" error - ./node_modules/_antd@4.3.3@antd/dist/antd.less ValidationError: Invalid options object. Less Loader has been initialized using an options object that does not match the API schema. - options has an unknown property 'javascriptEnabled'. These properties are valid: object { lessOptions?, prependData?, appendData?, sourceMap?, implementation? } ``` next.config.js文件如下: ```js const withLess = require('@zeit/next-less') const lessToJS = require('less-vars-to-js') const fs = require('fs') const path = require('path') const themeVariables = lessToJS( fs.readFileSync(path.resolve(__dirname, './assets/antd-custom.less'), 'utf8') ) if (typeof require !== 'undefined') { require.extensions['.less'] = file => {} } module.exports = withLess({ lessLoaderOptions: { javascriptEnabled: true, modifyVars: themeVariables // make your antd custom effective } }) ``` 我就在网上查解决办法,但几乎所有的博文都这么写。去next.js官方github下面看[antd例子]('https://github.com/dreamHeroK/next.js/blob/canary/examples/with-ant-design-less/next.config.js'),写法也是如此: ![alt](http://img.xuweijin.com/1592119600841bgsuibian.png) 看起来跟我的一模一样,甚至后来直接把整个内容复制粘贴下来,还是报错。 ## 解决 后来经历了各种尝试,都没能解决。最后没办法了,看到报错的有这么一句: ```js - options has an unknown property 'javascriptEnabled'. These properties are valid: object { lessOptions?, prependData?, appendData?, sourceMap?, implementation? } ``` 然后我死马当活马医,在`lessLoaderOptions`外面又套了一层`lessOptions`,如下: ```js module.exports = withLess({ lessLoaderOptions: { lessOptions:{ javascriptEnabled: true, modifyVars: themeVariables // make your antd custom effective } } }) ``` 一套非常娴熟的重启操作,然后刷新页面,成了!如下,`button`组件和日历组件都正常了: ![alt](http://img.xuweijin.com/1592119960498antddadad.png) ## 总结 这次报错,网上的方法都不好使,事后回想了一下,是因为网上那些博文基本都是18年或者19年早期的,跟我现在所用的版本有些差距。以后再遇到问题,还是要以控制台报错为切入点,而不能盲目去网上搜寻解决办法,否则就有可能做很多无用功。 **切记切记~~**
  • 徐伟晋日常问题解决办法汇总3年前评论数:0
    实用网站大全
    ## 中国国家图书馆 [**中国国家图书馆**](http://www.nlc.cn) 是中国国家图书馆的网站,每个人都可以免费阅读。 ## 在线识别器 [**在线识别器**](https://web.baimiaoapp.com) 可以快速识别图片中的文字,准确快速。 ## learn-korean [**learn-korean**](http://world.kbs.co.kr/learn_korean/lessons/c_index.htm) 顾名思义就是用来学韩语的网站。 学习分为三个部分: 1. 基础篇 2. 场景篇 3. 生活篇 每个环节都有配套的小动画片,简单易懂而且很有趣。 ## 医学微视 [**医学微视**](https://www.mvyxws.com) 是一个国家出品的,以视频分享各种医学知识的网站。 ## templates.office [**templates.office**](http://templates.office) 是微软官方的主题网站,里面有各类office主题 ppt之类的,种类丰富,免费下载。 ## 持续更新,未完待续。。。
  • 徐伟晋Vue4年前评论数:0
    需求:Vue中,若用户操作了表单,退出前给用户提示
    ## 解决方案 监听form表单里的值,判断用户是否有输入。通过vue提供的watch方法,然后深度监听。直接贴代码吧。 ```js let defaultForm = { name:'', job:'' } export default{ watch:{ formData:{ var $this = this; handler(nowVal,oldVal){ for (let i in defaultForm) { if (nowVal[i] != defaultForm[i] ) { //有变更,重置可点 $this.resetDisabled = false; break; } else { $this.resetDisabled = true; } } }, deep:true } }, created(){ this.formData = Object.assign({},defaultForm) }, data(){ return{ formData:null } } } ```
  • 徐伟晋日常问题解决办法汇总4年前评论数:0
    el-checkBox,checked通过js动态修改后,页面渲染不生效
    ## 解决办法 将checked改为:value就可以了,如下图: ![alt](http://img.xuweijin.com/1589183569999wentihuizong.png)
  • 徐伟晋日常问题解决办法汇总4年前评论数:2
    Nuxt项目部署到服务器后favicon.ico不显示
    ## 解决办法 很简单,nuxt.config.js配置icon的时候在后面带一个随机的参数。如下: ```js export default { ..... head: { ..... link: [ { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico?v=2' } ] } ...... } ```
  • 徐伟晋日常问题解决办法汇总4年前评论数:1
    有时候控制台报的跨域错误,不一定真的是跨域导致的。
    ## 先说结论 后台上传接口是koa2写的,nginx转发。 nginx上传文件有大小限制,默认最多1m,超过1m控制台返回**跨域错误**,而没有给我返回**413状态码**。 需要在nginx.conf中修改默认文件大小。 ```js http{ ... client_max_body_size 200000000000m;/*随便输入你需要设置的大小*/ ... } ``` ## 心路历程 !["残忍啊"](https://user-gold-cdn.xitu.io/2020/4/20/1719729c3f958556?w=300&h=300&f=jpeg&s=12453) 找错过程后面再补吧,至少吐了二斤血,先调养两天。。
  • 徐伟晋日常问题解决办法汇总4年前评论数:0
    Nuxt 项目部署到服务器后,电脑访问正常,手机打开报错:data undefined
    ## 写在前面 由于现在前端框架越来越流行,基本上新开的项目都会考虑使用框架而不是传统的js。但现在流行的vue、react由于是单页面虚拟dom,所以基本不能做seo。 而服务端渲染恰好能解决这个问题,虽然暂时工作上用不到,但以后是一个流行的趋势,迟早都要掌握。 所以最近用nuxt写了一个小demo。 ## 问题出现 本来写的时候开开心心的,虽然多多少少有点小问题,最后也都解决。本地运行没问题后,开开心心地把demo部署到线上。 打开浏览器,输入网址,回车。然后激动地等待页面呈现。。。 完美!一点问题么得! 再用手机打开,哇,太完美了! 跳到其他页面看看,卧槽!居然报错了!!! 不应该啊,我电脑访问好好的,电脑开手机模式也好好的,怎么到手机上就报错了!太坑了吧!! 页面上只显示有个data undefined,由于是移动端,具体的控制台报错我也看不到。试了好几次,都不行。有点绝望。 最后把手机连到电脑上,通过Safari的开发者模式,看到了错误信息,如下 ![alt](http://img.xuweijin.com/1585796895857WX20200402-110613@2x.png) ## 解决问题 一开始以为是无法连接服务器的问题,尝试了半天,没有头绪,也想不通,明明其他网页都能打开,就这个连不上服务器。未果,不管了,看第二条, ```js due to access control checks ``` 看起来像是跨域问题啊。谷歌搜了一下,stackflow上有同样的问题,下面有人给出了答案,说是要在nuxt.config.js里面配置axios,如下: ```js export default{ ... axios:{ proxyHeaders: false, credentials: false } } ``` 也不知道好不好使,死马当活马医吧。 打包上传重启服务,一通操作之后,怀着激动的心情,重新打开网页。。 完美!!!手机端也可以正常运行了。 ## 总结 一开始想法错了,觉得电脑访问正常,手机不正常,可能是移动端兼容问题,导致走了很多弯路。以后遇到问题还是要以控制台报错为主,这样才能更有效率地去解决问题。
  • 徐伟晋日常问题解决办法汇总4年前评论数:0
    常用工具类软件集锦
    ## 常用工具集锦 OBS: Mac端与windows端的一个直播软件,比直播姬要好用,操作也挺简单的 transmit: 一个ftp客户端,支持链接多种平台,如Amazon S3, WebDev,dropBox等 gistPal:github gist管理小工具,比Lepton更加轻量级,操作也更加简单 Mac downloader: 点击直接下载,解压密码:newlearner 支持直接下载mac系统镜像,包括10.13、10.14、10.15这三个大版本; uTools: 比ItTools更好用的一款搜索软件,类似于聚焦搜索,但是可以安装很多插件使用; itTools: 工具目前包括“正则表达式”、“时间戳转化”、“颜色盒子”、“Json转化”、“Base64转化“ shellCraft: 服务器ssh工具 SSH Copy: App store下载,服务器文件操作工具,可直接拖上传、下载服务器文件 simpleNote: App store下载,笔记工具,多端共用账号,实时同步 SnippetsLab: 代码片段管理器,但是我把它当笔记工具用 Regextor: 提取码:xj3j,App store下载,正则表达式测试工具 Helm: Host管理工具 GitKraken: git代码管理客户端 YoMail: App store下载,一款比较好用的邮件客户端 PopClip: 在Mac上使用鼠标选择文本时,会出现PopClip。 即时复制和粘贴,并访问搜索,拼写,字典和超过100个以上的操作。 NewFileMenu: App store下载,右键新建文件工具 Image2Icon: App store下载,可将图片转换为ICON Blotter: 提取码hwpm,App store下载,(推荐) 提醒事项的桌面版显示,直接在Mac自带的提醒事项里面添加内容,这款软件就直接将内容显示在桌面 Manico: 程序快捷切换,推荐,很方便 Mounty: NTFS硬盘读取、操作工具 WidsMob Viewer: 图片预览工具,比Mac自带的好用 Pine: 一款MarkDown编辑器,开源,挺好用的 静态博客写作工具: 支持MarkDown,开源 Cd To - new terminal here: App Store下载,在指定文件夹打开终端的工具,省去了很多次的cd命令 tmux: homeBrew下载,命令:brew install tmux,终端分屏工具,使用各种命令解决分屏问题 snipaste: 一款开源的十分好用的截图工具,各平台版本都有 Mob: 一款喜马拉雅的PC端客户端,支持Mac,Windows,开源 Lepton: 一款github gist同步工具,代码文件都可以同步,十分好用! code Notes: 一款笔记工具,开源,支持多种文件类型,支持github gist genymotion: 一款安卓模拟器工具,非免费,但是官网有下载地址未屏蔽 duet: 一款可以连接Mac与iPad的工具,通过数据线可以实现将iPad作为外接屏幕 pxCook: 一款类似马克曼一样的UI稿查看工具,可以查看UI中的各类元素的样式,可以直接显示html代码 ENFI下载器: 告别百度网盘,可以直接使用百度网盘的分享连接进行下载,速度还不错,里面的下载流量需要购买,但是很便宜,完全可以接受 迅雷: 提取码: 1999 免登录版,可直接使用会员速度 TinyCal: 一款状态栏日历显示软件,精致小巧 IINA: 一个精简的视频播放器,还不错 > 引自 [webbx-github](https://github.com/webbx/MacSoftware-recommend)
  • 徐伟晋React4年前评论数:3
    WebSocket实现实时推送通知提醒功能
    ## 前言 现在很多网站都有通知提示功能,比如知乎、微博,当我们有新的评论或者粉丝时,就会在页面上告知我们。 大家都知道正常情况下,服务端是不能主动给客户端推送消息的,所以按照常规做法,我们要想知道是否有新的通知,只能在前端定时循环请求接口,这样对服务端来说就会有大量“重复”的请求,造成资源浪费。 这时候我们就需要用另外一种方法去替代上面的方法,用的最多的便是__WebSocket__. ## 什么是WebSocket > WebSocket 是一种__网络通信协议__,在2008年诞生,2011年成为国际标准。所有浏览器都已经支持了。 它的最大特点就是,服务器可以__主动向客户端推送信息__,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。 其他特点包括: 1. 建立在 TCP 协议之上,服务器端的实现比较容易; 2. 与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器; 3. 数据格式比较轻量,性能开销小,通信高效; 4. 可以发送文本,也可以发送二进制数据; 5. 没有同源限制,客户端可以与任意服务器通信; 6. 协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。
  • 徐伟晋日常问题解决办法汇总4年前评论数:0
    Webstorm激活码
    # 如下 ``` QYYBAC9D3J-eyJsaWNlbnNlSWQiOiJRWVlCQUM5RDNKIiwibGljZW5zZWVOYW1lIjoi6LaF57qnIOeoi+W6j+WRmCIsImFzc2lnbmVlTmFtZSI6IiIsImFzc2lnbmVlRW1haWwiOiIiLCJsaWNlbnNlUmVzdHJpY3Rpb24iOiIiLCJjaGVja0NvbmN1cnJlbnRVc2UiOmZhbHNlLCJwcm9kdWN0cyI6W3siY29kZSI6IklJIiwiZmFsbGJhY2tEYXRlIjoiMjAyMC0wMS0wNCIsInBhaWRVcFRvIjoiMjAyMS0wMS0wMyJ9LHsiY29kZSI6IkFDIiwiZmFsbGJhY2tEYXRlIjoiMjAyMC0wMS0wNCIsInBhaWRVcFRvIjoiMjAyMS0wMS0wMyJ9LHsiY29kZSI6IkRQTiIsImZhbGxiYWNrRGF0ZSI6IjIwMjAtMDEtMDQiLCJwYWlkVXBUbyI6IjIwMjEtMDEtMDMifSx7ImNvZGUiOiJQUyIsImZhbGxiYWNrRGF0ZSI6IjIwMjAtMDEtMDQiLCJwYWlkVXBUbyI6IjIwMjEtMDEtMDMifSx7ImNvZGUiOiJHTyIsImZhbGxiYWNrRGF0ZSI6IjIwMjAtMDEtMDQiLCJwYWlkVXBUbyI6IjIwMjEtMDEtMDMifSx7ImNvZGUiOiJETSIsImZhbGxiYWNrRGF0ZSI6IjIwMjAtMDEtMDQiLCJwYWlkVXBUbyI6IjIwMjEtMDEtMDMifSx7ImNvZGUiOiJDTCIsImZhbGxiYWNrRGF0ZSI6IjIwMjAtMDEtMDQiLCJwYWlkVXBUbyI6IjIwMjEtMDEtMDMifSx7ImNvZGUiOiJSUzAiLCJmYWxsYmFja0RhdGUiOiIyMDIwLTAxLTA0IiwicGFpZFVwVG8iOiIyMDIxLTAxLTAzIn0seyJjb2RlIjoiUkMiLCJmYWxsYmFja0RhdGUiOiIyMDIwLTAxLTA0IiwicGFpZFVwVG8iOiIyMDIxLTAxLTAzIn0seyJjb2RlIjoiUkQiLCJmYWxsYmFja0RhdGUiOiIyMDIwLTAxLTA0IiwicGFpZFVwVG8iOiIyMDIxLTAxLTAzIn0seyJjb2RlIjoiUEMiLCJmYWxsYmFja0RhdGUiOiIyMDIwLTAxLTA0IiwicGFpZFVwVG8iOiIyMDIxLTAxLTAzIn0seyJjb2RlIjoiUk0iLCJmYWxsYmFja0RhdGUiOiIyMDIwLTAxLTA0IiwicGFpZFVwVG8iOiIyMDIxLTAxLTAzIn0seyJjb2RlIjoiV1MiLCJmYWxsYmFja0RhdGUiOiIyMDIwLTAxLTA0IiwicGFpZFVwVG8iOiIyMDIxLTAxLTAzIn0seyJjb2RlIjoiREIiLCJmYWxsYmFja0RhdGUiOiIyMDIwLTAxLTA0IiwicGFpZFVwVG8iOiIyMDIxLTAxLTAzIn0seyJjb2RlIjoiREMiLCJmYWxsYmFja0RhdGUiOiIyMDIwLTAxLTA0IiwicGFpZFVwVG8iOiIyMDIxLTAxLTAzIn0seyJjb2RlIjoiUlNVIiwiZmFsbGJhY2tEYXRlIjoiMjAyMC0wMS0wNCIsInBhaWRVcFRvIjoiMjAyMS0wMS0wMyJ9XSwiaGFzaCI6IjE2MDgwOTA5LzAiLCJncmFjZVBlcmlvZERheXMiOjcsImF1dG9Qcm9sb25nYXRlZCI6ZmFsc2UsImlzQXV0b1Byb2xvbmdhdGVkIjpmYWxzZX0=-I7c5mu4hUCMxcldrwZEJMaT+qkrzrF1bjJi0i5QHcrRxk2LO0jqzUe2fBOUR4L+x+7n6kCwAoBBODm9wXst8dWLXdq179EtjU3rfJENr1wXGgtef//FNow+Id5iRufJ4W+p+3s5959GSFibl35YtbELELuCUH2IbCRly0PUBjitgA0r2y+9jV5YD/dmrd/p4C87MccC74NxtQfRdeUEGx87vnhsqTFH/sP4C2VljSo/F/Ft9JqsSlGfwSKjzU8BreYt1QleosdMnMK7a+fkfxh7n5zg4DskdVlNbfe6jvYgMVE16DMXd6F1Zhwq+lrmewJA2jPToc+H5304rcJfa9w==-MIIElTCCAn2gAwIBAgIBCTANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1KZXRQcm9maWxlIENBMB4XDTE4MTEwMTEyMjk0NloXDTIwMTEwMjEyMjk0NlowaDELMAkGA1UEBhMCQ1oxDjAMBgNVBAgMBU51c2xlMQ8wDQYDVQQHDAZQcmFndWUxGTAXBgNVBAoMEEpldEJyYWlucyBzLnIuby4xHTAbBgNVBAMMFHByb2QzeS1mcm9tLTIwMTgxMTAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxcQkq+zdxlR2mmRYBPzGbUNdMN6OaXiXzxIWtMEkrJMO/5oUfQJbLLuMSMK0QHFmaI37WShyxZcfRCidwXjot4zmNBKnlyHodDij/78TmVqFl8nOeD5+07B8VEaIu7c3E1N+e1doC6wht4I4+IEmtsPAdoaj5WCQVQbrI8KeT8M9VcBIWX7fD0fhexfg3ZRt0xqwMcXGNp3DdJHiO0rCdU+Itv7EmtnSVq9jBG1usMSFvMowR25mju2JcPFp1+I4ZI+FqgR8gyG8oiNDyNEoAbsR3lOpI7grUYSvkB/xVy/VoklPCK2h0f0GJxFjnye8NT1PAywoyl7RmiAVRE/EKwIDAQABo4GZMIGWMAkGA1UdEwQCMAAwHQYDVR0OBBYEFGEpG9oZGcfLMGNBkY7SgHiMGgTcMEgGA1UdIwRBMD+AFKOetkhnQhI2Qb1t4Lm0oFKLl/GzoRykGjAYMRYwFAYDVQQDDA1KZXRQcm9maWxlIENBggkA0myxg7KDeeEwEwYDVR0lBAwwCgYIKwYBBQUHAwEwCwYDVR0PBAQDAgWgMA0GCSqGSIb3DQEBCwUAA4ICAQAF8uc+YJOHHwOFcPzmbjcxNDuGoOUIP+2h1R75Lecswb7ru2LWWSUMtXVKQzChLNPn/72W0k+oI056tgiwuG7M49LXp4zQVlQnFmWU1wwGvVhq5R63Rpjx1zjGUhcXgayu7+9zMUW596Lbomsg8qVve6euqsrFicYkIIuUu4zYPndJwfe0YkS5nY72SHnNdbPhEnN8wcB2Kz+OIG0lih3yz5EqFhld03bGp222ZQCIghCTVL6QBNadGsiN/lWLl4JdR3lJkZzlpFdiHijoVRdWeSWqM4y0t23c92HXKrgppoSV18XMxrWVdoSM3nuMHwxGhFyde05OdDtLpCv+jlWf5REAHHA201pAU6bJSZINyHDUTB+Beo28rRXSwSh3OUIvYwKNVeoBY+KwOJ7WnuTCUq1meE6GkKc4D/cXmgpOyW/1SmBz3XjVIi/zprZ0zf3qH5mkphtg6ksjKgKjmx1cXfZAAX6wcDBNaCL+Ortep1Dh8xDUbqbBVNBL4jbiL3i3xsfNiyJgaZ5sX7i8tmStEpLbPwvHcByuf59qJhV/bZOl8KqJBETCDJcY6O2aqhTUy+9x93ThKs1GKrRPePrWPluud7ttlgtRveit/pcBrnQcXOl1rHq7ByB8CFAxNotRUYL9IF5n3wJOgkPojMy6jetQA5Ogc8Sm7RG6vg1yow== ```
  • 徐伟晋日常问题解决办法汇总4年前评论数:19
    日常常用指令及快捷键
    ## 前言 有一些操作指令及快捷键很常用,但奈何脑子不好使,每次都去谷歌查询有点麻烦,所以在这里做下汇总,方便日后查询使用。 ## shell指令 * 连接服务器 `ssh -p 22 root@39.105.20.201 ` * 重启node服务 `pm2 restart all` * 重启nginx `/usr/nginx/sbin/nginx -s reload` * 全局安装cnpm `npm install -g cnpm --registry=https://registry.npm.taobao.org` * 查看centos硬盘使用情况 `df -hl` * 更新ssl有效期 `/certbot-auto renew`
  • 徐伟晋Vue4年前评论数:0
    VUEX解决浏览器刷新状态丢失问题
    ## 前言 vuex的主要作用是组件之间的通信以及对数据进行中心化管理。 但是由于vuex中的数据是存在运行内存中的,所以当我们刷新页面的时候会导致store中的数据清空。  ## 问题分析 怎么解决这个问题呢?  __我们可以使用传统的存储方式将store中的数据存起来__,比如cookie、localstorage或者sessionstorage,这样刷新页面数据也不会丢失了。 只是为了保留浏览器刷新前的数据,所以我们选用sessionstorage,这样关闭浏览器,存储的数据就会被清空,不会产生重复数据。  ## 实现方案 具体实现思路是这样的,我们__监听页面刷新事件,在刷新前将store中的数据存sessionstorge中。每次进入页面的时候先读取sessionstorage中的值并把它赋给store__,这样就保留了刷新前的数据。 代码如下: ```js export default { name: 'App', created () { if (sessionStorage.getItem("store") ) { //页面加载前读取sessionStorage里的状态信息    this.$store.replaceState(Object.assign({}, this.$store.state,JSON.parse(sessionStorage.getItem("store")))) } window.addEventListener("beforeunload",()=>{ //在页面刷新前将vuex里的信息保存到sessionStorage里    sessionStorage.setItem("store",JSON.stringify(this.$store.state)) }) } } ```
  • 徐伟晋React4年前评论数:0
    React Markdown 编辑及渲染解决方案
    ## 前言 之前用的富文本编辑框,感觉格式特别乱,写出来的文章布局根本没眼看,代码高亮也没找到合适的。所以一直想着把富文本改为markdown。 ## 插件的选择 我们需要写文章和看文章,所以得有markdown编辑器插件和markdown渲染插件。 github上有很多插件,我最终选定的是[for-editor](https://github.com/kkfor/for-editor)和[react-markdown](https://github.com/rexxars/react-markdown),前者用于编写,后者用于加载。 选择好插件之后,让我们开始在项目中使用吧! ## for-editor 安装使用方法 ### 安装 ```shell npm install for-editor --save ``` #### 使用 代码如下: ```jsx import React from 'react' import Editor from 'for-editor' class WriteBlog extends React.Component{ constructor(props){ super(props) this.state = { editorValue:'', imageUrl:'' } } handleChange(value){ this.setState({ editorValue:value }) } uploadHandler(params){ fetch.get('getQiniuToken',{ token:JSON.parse(Cookies.get('loginInfo')).token }).then(res=>{ utils.uploadFile(params,res.data.qiniuToken).then(res=>{ this.setState({ imageUrl:'http://img.xuweijin.com/'+res }) let str = this.state.editorValue + '![alt](http://img.xuweijin.com/'+res+')' this.setState({ editorValue:str }) }) }) } render(){ return( <Editor className="my-editor" subfield = {true} preview = {true} addImg = {(file) => this.uploadHandler(file)} value={this.state.editorValue} onChange={(value) => this.handleChange(value)} /> ) } ``` _图片上传没有使用官方的方法,上传成功手动往编辑器里加入图片的字符串。_ 上面只是简单贴了一些代码,具体参数请直接前往[for-editor github主页](https://github.com/kkfor/for-editor)查看。 ## react-markdown 安装使用办法 ### 安装 ```shell npm install --save react-markdown ``` ### 使用 代码如下: ```jsx import React from 'react' import ReactMarkdown from 'react-markdown' class BlogDetail extends React.Component{ constructor(props){ super(props) this.state = { articleDetail:'', } } render(){ return( <ReactMarkdown source={this.state.articleDetail.article_content} escapeHtml={false}></ReactMarkdown> ) } } ``` 上面只是简单贴了代码,具体配置参数请前往[github react-markdown主页](https://github.com/rexxars/react-markdown)查看。 <hr> _以上就是markdown文本的解决办法,但到此还不算结束,我们解析时还要加上代码高亮,否则当我们文章里有代码时,阅览体验将会极差。_ ## 代码高亮 ### 安装代码高亮插件包 我这边选择的是_react-syntax-highlighter_ ```shell npm install react-syntax-highlighter --save ``` ### 使用 1. 首先新建一个CodeBlock.jsx文件,代码如下 ```jsx import React, { PureComponent } from "react"; import PropTypes from "prop-types"; import { PrismLight as SyntaxHighlighter } from "react-syntax-highlighter"; // 设置高亮样式 import { xonokai } from "react-syntax-highlighter/dist/esm/styles/prism"; // 设置高亮的语言 import { jsx, javascript, sass, scss } from "react-syntax-highlighter/dist/esm/languages/prism"; class CodeBlock extends PureComponent { static propTypes = { value: PropTypes.string.isRequired, language: PropTypes.string }; static defaultProps = { language: null }; componentWillMount() { // 注册要高亮的语法, // 注意:如果不设置打包后供第三方使用是不起作用的 SyntaxHighlighter.registerLanguage("jsx", jsx); SyntaxHighlighter.registerLanguage("javascript", javascript); SyntaxHighlighter.registerLanguage("js", javascript); } render() { const { language, value } = this.props; return ( <figure className="highlight"> <SyntaxHighlighter language={language} style={xonokai}> {value} </SyntaxHighlighter> </figure> ); } } export default CodeBlock; ``` 2. 解析时使用 根据react-markdown提供的方法,我们在解析md文件是,对code标签进行处理,加入高亮的样式类名,简单贴下代码: ```jsx import CodeBlock from '../components/CodeBlock' class BlogDetail extends React.Component{ constructor(props){ super(props) this.state = { articleDetail:'', } } render(){ return( <ReactMarkdown source={this.state.articleDetail.article_content} renderers={{ code: CodeBlock }} escapeHtml={false}></ReactMarkdown> ) } } ``` 这样我们就可以看到文章解析时,代码部分会出现高亮样式了。 ## 文章目录 当我们文章过长时,我们需要加入文章目录以便读者对整体有个概览,也方便读者迅速切换到想要了解的部分,类似于掘金这种 ![alt](http://img.xuweijin.com/1576390971320WX20191215-142135@2x.png) 通过github,最后找到[markdown-navbar](https://github.com/parksben/markdown-navbar)这个插件,虽然star数不多,但是使用起来还是很方便的。 #### markdown-navbar 安装 ```shell npm install markdown-navbar --save ``` #### 使用 这个插件使用起来还是很方便的,只需要在项目中引入这个插件,然后把需要解析的md文件传入,就会自动生成一个目录树。一般目录树需要固定,所以我这里使用了antd的Anchor组件,将目录固定在了右侧,代码如下: ```jsx import { Anchor } from 'antd'; import MarkNav from 'markdown-navbar'; import 'markdown-navbar/dist/navbar.css'; class BlogDetail extends React.Component{ constructor(props){ super(props) this.state = { articleDetail:'', } } render(){ return( <Anchor> <div className="markNav-title">文章目录</div> <MarkNav className="article-menu" source={this.state.articleDetail.article_content} headingTopOffset={80} /> </Anchor> ) } } ``` 这里只是简单贴了代码,具体配置还请前往[github markdown主页](https://github.com/parksben/markdown-navbar)自行查看。 ## 结论 以上就是react markdown语法编辑及渲染整体的解决方案啦,贴一张渲染后的文章图片: ![alt](http://img.xuweijin.com/1576391866729WX20191215-143729@2x.png) 可以看到渲染后的样式还是挺工整的,大功告成! 第一次写这种小长篇,基本都是流水账的形式,非常感谢您能看到最后,最后欢迎您来我的[个人主页](https://www.xuweijin.com)留言互动~
  • 徐伟晋日常问题解决办法汇总4年前评论数:0
    MacOs 升级系统后,git提示xcrun错误
    ## 问题截图 如下图所示: ![alt](http://img.xuweijin.com/1574672072044WX20191125-165420@2x.png) ## 解决办法 打开终端,输入 ```js xcode-select --install ``` 根据提示下载安装软件,即可解决此问题。
  • 徐伟晋日常问题解决办法汇总4年前评论数:1
    shell命令数据库自动备份及失败解决办法
    ## 前言 上个月被黑客入侵数据库,删库勒索导致之前写的所有博客全被清空,联系阿里云官方人员被告知由于没开数据库备份,所以数据无法恢复。为了避免以后再遇到这种情况,我决定每天晚上备份一次数据库,这样即使以后被删库了,数据也能还原。可是每天手动备份太麻烦了,而且有时候容易忘,通过网上查阅资料,发现可以使用crontab+shell指令的方式实现自动备份。 ## 编写shell脚本指令 新建一个shell脚本文件以.sh结尾(我的是mysqlbak.sh),把它放到服务器里(我的文件地址是:/data/mysqlbak/)指令代码如下: ```sh #!/bin/bash #数据库IP dbserver='你的数据库ip' #数据库用户名 dbuser='你的用户名' #数据密码 dbpasswd='你的数据库密码' #数据库,如有多个库用空格分开 dbname='你的数据库名称' #备份时间 backtime=`date +%Y%m%d` #备份输出日志路径 logpath='/data/mysqlbak/' echo "################## ${backtime} #############################" echo "开始备份" #日志记录头部 echo "" >> ${logpath}/mysqlback.log echo "-------------------------------------------------" >> ${logpath}/mysqlback.log echo "备份时间为${backtime},备份数据库表 ${dbname} 开始" >> ${logpath}/mysqlback.log #正式备份数据库 for table in $dbname; do source=`mysqldump -h ${dbserver} -u ${dbuser} -p${dbpasswd} ${table} > ${logpath}/${backtime}.sql` 2>> ${logpath}/mysqlback.log; #备份成功以下操作 if [ "$?" == 0 ];then cd $datapath #为节约硬盘空间,将数据库压缩 tar zcf ${table}${backtime}.tar.gz ${backtime}.sql > /dev/null #删除原始文件,只留压缩后文件 rm -f ${datapath}/${backtime}.sql #删除七天前备份,也就是只保存7天内的备份 find $datapath -name "*.tar.gz" -type f -mtime +7 -exec rm -rf {} \; > /dev/null 2>&1 echo "数据库表 ${dbname} 备份成功!!" >> ${logpath}/mysqlback.log else #备份失败则进行以下操作 echo "数据库表 ${dbname} 备份失败!!" >> ${logpath}/mysqlback.log fi done echo "完成备份" echo "################## ${backtime} #############################" ``` 编辑好之后要记得给它权限: ```js #chmod +x /data/mysqlbak/mysqlbak.sh ``` ## 使用crontab自动执行该备份指令 ### 首页我们要了解一下crontab有哪些常用指令 * crontab -e : 修改crontab文件,如果文件不存在,则会自动创建 * crontab -l :显示crontab文件 * crontab -r :删除crontab文件 * crontab -ir :删除crontab文件前提醒用户 ### 执行备份指令 终端输入 ``` crontab -e ``` 进入vim编辑页面 ```js 59 23 * * * /data/mysqlbak/mysqlbak.sh ``` 保存并退出,这样每天晚上11点59 crontab就会自动执行备份指令了。 ### 参数说明: * 格式为 分 时 日 月 周 指令 * 59 23 * * * :每天23:59分自动执行脚本 * M: 分钟(0-59)。每分钟用*或者 */1表示 * H:小时(0-23)。(0表示0点) * D:天(1-31)。 * m: 月(1-12)。 * d: 一星期内的天(0~6,0为星期天)。 ## 失败原因 本来以为大功告成,第二天满心欢喜的打开服务器文件夹,找到备份文件,才发现里面空空如也,啥也么得。查看log日志说是备份失败。最后查看指令时发现source里面直接写的mysqldump,由于我没有关联到全局指令,所以这条命令是找不到的,要在前面加上路径,最后source完整的命令是 ```js source=`/usr/local/mysql/bin/mysqldump -h ${dbserver} -u ${dbuser} -p${dbpasswd} ${table} > ${logpath}/${backtime}.sql` 2>> ${logpath}/mysqlback.log; ``` 为了验证是否正确,我把指令改为每分钟执行一次,等了大概一分钟后,进入备份文件夹,发现已经有备份后的文件了,打开文件,里面各个表及内容都有,完美!再把指令改回到每晚11点23分执行。 早上来到之后发现昨晚备份的文件已经在文件夹里躺着了。如下图: ![alt](http://img.xuweijin.com/1576115621084WX20191212-095315@2x.png) ## 结论 通过这次事件了解了一些shell指令和自动执行方法crontab,也不怕再被人删库啦! 虽然数据库被清空很难受,但亡羊补牢为时未晚,继续努力!
  • 徐伟晋日常问题解决办法汇总4年前评论数:0
    MacOs git修改密码后,sourceTree提交拉取报错
    ## 操作步骤如下 1. 进入 ~/Library/Application Support/SourceTree 文件夹 2. 删除该项目的密码缓存文件 3. 重启sourceTree,拉取代码后会弹出输入密码的弹窗,输入正确密码即可 ![alt](http://img.xuweijin.com/157352632267307B014FD-CFA5-4FF2-9005-2CAE6D832151.png) <center>(红框圈出的即为密码缓存文件)</center> ## 备注 __ 如果删除密码文件后拉取代码没有出现弹窗,就多重启几次sourceTree __
  • 徐伟晋公告4年前评论数:0
    所有数据库全被清空,只给我留下一条冰冷的勒索公告。
    怪自己没有安全意识,数据库一直在裸奔而不自知。直到昨天数据库被清空。而且我数据库没开备份,之前写的博客所有的心血全部白费,欲哭无泪! 吃一堑长一智吧。