From 401dd8a83409459a5b213717a96e8f8ad93e2870 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A9=AC=E7=90=AA=E6=96=8C?= Date: Sun, 19 May 2024 21:31:14 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E5=8D=9A=E5=AE=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...45\344\275\234\347\216\260\347\212\266.md" | 135 +++++++++++ ...21\345\244\261\344\270\232\344\272\206.md" | 45 ++++ ...I \347\273\204\344\273\266\345\272\223.md" | 223 ++++++++++++++++++ ...250\345\230\262\347\254\221 Next.js 14.md" | 124 ++++++++++ ...203\250\347\275\262\345\210\260 Vercel.md" | 183 ++++++++++++++ ...34\345\217\230\347\216\260\357\274\237.md" | 94 ++++++++ 6 files changed, 804 insertions(+) create mode 100644 "data/blog/35 \345\262\201\357\274\214\350\242\253\350\243\201\345\220\216\357\274\214\344\270\200\344\270\252\346\234\210\346\211\276\345\267\245\344\275\234\347\216\260\347\212\266.md" create mode 100644 "data/blog/35\345\262\201\357\274\214\346\210\221\345\244\261\344\270\232\344\272\206.md" create mode 100644 "data/blog/Shadcn UI \347\216\260\344\273\243 UI \347\273\204\344\273\266\345\272\223.md" create mode 100644 "data/blog/\345\244\247\345\256\266\351\203\275\345\234\250\345\230\262\347\254\221 Next.js 14.md" create mode 100644 "data/blog/\345\260\206 Node \345\272\224\347\224\250 Express.js \351\203\250\347\275\262\345\210\260 Vercel.md" create mode 100644 "data/blog/\346\231\256\351\200\232\347\250\213\345\272\217\345\221\230\350\246\201\345\246\202\344\275\225\346\212\200\346\234\257\345\206\231\344\275\234\345\217\230\347\216\260\357\274\237.md" diff --git "a/data/blog/35 \345\262\201\357\274\214\350\242\253\350\243\201\345\220\216\357\274\214\344\270\200\344\270\252\346\234\210\346\211\276\345\267\245\344\275\234\347\216\260\347\212\266.md" "b/data/blog/35 \345\262\201\357\274\214\350\242\253\350\243\201\345\220\216\357\274\214\344\270\200\344\270\252\346\234\210\346\211\276\345\267\245\344\275\234\347\216\260\347\212\266.md" new file mode 100644 index 0000000..20eaddc --- /dev/null +++ "b/data/blog/35 \345\262\201\357\274\214\350\242\253\350\243\201\345\220\216\357\274\214\344\270\200\344\270\252\346\234\210\346\211\276\345\267\245\344\275\234\347\216\260\347\212\266.md" @@ -0,0 +1,135 @@ +--- +title: 35 岁,被裁后,一个月找工作现状 +date: 2024/4/9 22:05:48 +lastmod: 2024/5/19 21:24:14 +tags: [前端, 面试] +draft: false +summary: 失业一个月,聊聊被裁后这一个月,我找工作的情况,这个月内总共打招呼了 385 家,投递了 56 家,实际应该不止 56,因为我把简历写在了自己的博客中。约面 5 家,最后只通过了 1 家。 +images: + [ + 'https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/3649164a4b934348b008d714943039f0~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=1080\&h=458\&s=354538\&e=png\&b=0d0b0e', + ] +authors: ['default'] +layout: PostLayout +--- + +--- + +## title: 35 岁,被裁后,一个月找工作现状 + +失业一个月,聊聊被裁后这一个月,我找工作的情况,这个月内总共打招呼了 385 家,投递了 56 家,实际应该不止 56,因为我把简历写在了自己的博客中。约面 5 家,最后只通过了 1 家。 + +先说说自己的情况,我是 90 后,12 年大专毕业,做前端 10 年多了,16 年报考了浙大远程,也算混了一个本科文凭,但是实际没一点卵用。现在大部分公司都要本科起步,很多厂都卡一本院校了。 + +### 第一家:哈啰出行 + +让前同事内推的我,过了一个星期才约的面试,是去现场面试,没有进行笔试,面试官跟我差不多年纪,主要针对我简历上的技术栈和项目进行了提问,包括微前端、canvas、 组件设计开发等、主要考察业务理解能力、前端基础建设能力,以及系统设计能力等,总体面试时间为 50 分钟左右,面试完后,自我感觉还可以,都回答上来了,但是也没回答特别完美,主要是也没特殊亮点。 + +印象最深的问题是:你为什么能够在一家公司待 8 年?我的回答是:我的要求不高,工作和生活达到平衡就好。 + +面试常规最后一个问题:你有什么问题要问我的? + +我也是常规回答:如果我有幸加入贵公司,我将承担什么样的业务与角色。 + +面试官给我的回答,当前部门有 15+ 人的前端团队,整个公司有几百个前端,未来公司很多产品上需要对接 AI,希望 AI 能够在公司内部快速对接落地,推动业务增长。 + +几天后,让同事查了下面试进度,很遗憾,没通过。后面内推也没有 HC 了,最后一个 HC 要留给外包转正。 + +### 第二家:魔云智算 + +魔云智算是一家美国全资的互联网小公司,主要做 Saas 化的工业软件,杭州属于研发分部,BOSS 上写的福利待遇还不错,但要求英语作为工作语言,也就是在杭州,讲话都是中文,但工作文档沟通都是英语,显然我的英语是过不了关的,但工作上可以试一试,我们可以通过划词翻译,GPT 等协助完成。也就是其运营总监放的水,约的我面试,人很好,面试之前,跟我电话沟通了大半个小时,问了一些常见的面试问题,以及告诉我回答技巧。 + +除了 hr 面,还有一轮笔试和面试,笔试是一个专门的笔试系统,考察了 3 道算法题,时间是 40 分钟。 + +1. 求时钟时针和分针的夹角 + +2. 给你 n 个台阶,你的最大步幅是 2 步,可以一次走 1 步,也可以一次走 2 步,问有多少种走法? + +3. leetcode:300-最长递增子序列 + +第二轮面试被安排晚上 8 点半到 10 点,2 位面试官轮流提问,一位面试官还在公司,另一位大概在路上开车,但也不影响面试,面试官很有实力,也是针对简历上的技术栈并且撺杂了八股文进行提问。包括 Javascript 事件循环、 webpack Loader 和插件,react fiber 原理、babel 编译原理等。 + +印象较深的一个问题是: + +用户有 1000 个文件同时下载,可能会造成服务器 done 掉,要如何优化? + +我的回答是将 1000 个文件打包成 zip 文件供用户下载,或者说在做一个列表页面让用户选择性下载。 + +但是面试官说,这是需求,我不能改需求只能在前端实现,无奈当时被面试官问的有点懵,只能说没有想到方案,现在想想,面试官想要考察的是异步请求控制或者说并发请求控制。 + +聊完,最后还有半小时,还有一道简单笔试题,题目不难,使用 html 和 css 实现一个 9\*9 的棋盘,点击一个按钮能够实现交替换色,点击每一小格,可以行高亮和列高亮。题目是英文的,没敢用划词翻译,由于最后一步对题目理解错误,所以没过。 + +不过面试官也没有立刻拒绝我,还是礼貌的问了我,还有什么问题要问他的,我也同上面一样,问了未来需要工作的内容以及技术栈,没想到的是,问了很多 react 相关问题,结果开发技术栈是 angular。 + +### 第三家:大厂外包 + +离职后,我发现工作岗位这么少,就打算先面个外包,先拿一个 offer 吧,结果,投了外包岗后,本来约来下周面试,结果到了下周,HR 说简历没过,这让我更加焦虑了。 + +虽然 BOSS 隔三差五会有外包 HR 主动打招呼,有很多外包公司,但杭州招外包的主要就 4 家、阿里外包、字节外包、网易外包和华为 OD,并且需要提供身份证号,一旦给了身份证号就会进入锁定期,大概 2 周左右,也就是 2 周内一厂只能面一次。 + +虽然外包岗薪资上要少很多,但面试也需要考笔试题,面试内容也主要跟简历上的内容来的,笔试题: + +1\. 是实现 JavaScript 柯里化函数 + +2\. 实现防抖和节流函数。 + +### 第四家:光年数据 + +光年数据,一家做流量运营的小公司,自带电脑去现场面试。面试之前先是 5 道笔试题 + +1. 使用 HTMl 和 CSS 实现 3 列布局,左右固定宽度,移动端显示为单列垂直布局 + +2\. 实现 deepClone + +3\. 实现一个自定义 Hook,实现表单保存输入、输入以及验证以及错误信息 + +4\. 前端性能优化的方案 + +5\. 如何确保用户上传的文件不会对 web 服务器造成安全风险 + +做完笔试后,就是面试,技术面试官和 HR 同时面试,大概聊了 1 个小时、简历上的每个项目和技术栈都会细问,比较注重业务逻辑,快要结束时,HR 问了一个问题,“常见的 HTTP 请求头有哪些?”我回答:`Content-type` `Cookie` `Cache-Control`  等,当然回答的不是很全。 + +面试结束后, HR 还找我复盘了下:首先对我有博客和开源项目,给予了肯定,能够加分,又说了面试官对我的印象是:不够注重业务。至于具体能不能通过,还需要跟老板汇报,现状是公司不加班,AI 需要对接业务,人手有点欠缺,是否需要一个全职的人还是待定状态。 + +临走时,我问他,您是 HR,为什么会问 HTTP 相关的问题,他说,他干 HR 之前是干前端的,做了 10 年,由于喜欢跟人沟通,就当了 HR,前端太卷了。 + +### 第五家:蚂蚁金服 + +蚂蚁金服是找了《前端桃园》的号主内推的,以我的学历,如果是正常投递,简历应该是到不了业务部门手中的,他们部门是做创意互动相关的,大概理解为 3D,支付宝中的互动小游戏这些。游戏、 3D、以及图形学这些虽然也是前端,但和前端算是 2 个方向了,我之前没做过这些,但也安排了我进行面试。蚂蚁面试会在面试之前发送一个邮件链接,点开这个网页链接,可以进行面试,该网页通过 WebRTC 等技术实现了实时的音视频通话和写代码。 + +首先是一道笔试题: 实现大数相加 + +做完题后接着面试 + +1. 在上一家公司主导或攻艰了哪些技术? + +2. 微前端与模块联邦 + +3. Javascript 事件循环 + +4. 浏览器渲染原理 + +5. 前端性能优化方案 + +6. 前端脚手架实现的功能点 + +总体面试时间 1 小时,以前端基础和八股文为主。 + +### 总结 + +1. 作为一线码农,现下找工作,面试机会并不多,除非拥有高学历和大厂工作经验; + +2. 八股文还得继续背,这里推荐前端充电宝的[语雀文档](https://www.yuque.com/cuggz/interview),[掘金专栏](https://juejin.cn/column/6964717704712290317) + +3. 能找人内推的话尽量找人内推,这样简历可以尽快到业务部门手里 + +4. 有开源项目和在线项目会是一个加分项,虽然加分也不多,可以节约一定面试考察成本,我之前分享过好多次网站部署的文章。 + +GitHub:https://github.com/maqi1520  可以给我点个赞。 +今天就分享这边多,欢迎留下你的想法有建议。 + +## 补充 + +2024 年 5 月 12 日,这篇文章受到到了举报,所以要在文末补充下,关于失业后,我就写了 2 篇文章,《35 岁,我失业了》失业 2 周多,主要讲失业后可能干什么,另一篇也就是本文主要讲最近一个月的面试情况,只是前一篇我忘记在掘金发布,2 篇算是同时发布的。这些是我个人的真实情况,发在掘金的目的是为了参加掘金金石计划,可能失业的话题最近比较敏感,大家点的比较多,请评论区大神口下留情。 + +![image.png](https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/861127426bf74d97980195d1ca6aeaaa~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=1590&h=976&s=242307&e=png&b=ffffff) diff --git "a/data/blog/35\345\262\201\357\274\214\346\210\221\345\244\261\344\270\232\344\272\206.md" "b/data/blog/35\345\262\201\357\274\214\346\210\221\345\244\261\344\270\232\344\272\206.md" new file mode 100644 index 0000000..3879c2b --- /dev/null +++ "b/data/blog/35\345\262\201\357\274\214\346\210\221\345\244\261\344\270\232\344\272\206.md" @@ -0,0 +1,45 @@ +--- +title: 35岁,我失业了 +date: 2024/5/9 22:13:02 +lastmod: 2024/5/19 21:24:15 +tags: [程序员] +draft: false +summary: Hello 大家好,我是一名 90 后、工作 10年+ 的前端程序员。 其实已经离职 2 周多了,本以为这只是一个短暂的过渡期,但是没想到会这么长,甚至会长时间。在 BOSS 上沟通了 250+ +images: + [ + 'https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/98f154251fe74a6f88315fdba2ac6295~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=1080&h=479&s=143219&e=png&b=030303', + ] +authors: ['default'] +layout: PostLayout +--- + +Hello 大家好,我是一名 90 后、工作 10 年+ 的前端程序员。 + +其实已经离职 2 周多了,本以为这只是一个短暂的过渡期,但是没想到会这么长,甚至会长时间。在 BOSS 上沟通了 250+,投递了 35 家,面试了 2 家,并且其中一家是内推的,其他 APP 如猎聘和拉勾基本都是未读或者已读不回,因此我也就不怎么投递了。今天这 2 家公司都拒绝了我,因此我决定写下这篇文章,总结和思考下当前的现状,以及未来可能要走的路。 + +我在上一家公司呆了 8 年,已经签了无固定期限劳动合同,本以为给自己带来了一定的安全感。突然的失业让我有些措手不及,面临的不只是经济压力,还有对未来的不确定感。公司的经济效益连续下滑,其实去年年初就已经开始裁员,各种福利标准都在下降,包括公积金,相当于降薪了。去年我甚至有些羡慕被裁的同学,因为他们可以领个大礼包,并且都找到了新工作,而留下的人工作量都在增加,大家都变得更卷了,但更卷也没有改变现状,终于还是轮到了我,被约谈那天,我心中是愤怒的,人生能有几个 8 年,毕竟在这里奋斗过,拼搏过,有成长、也有汗水。 + +第二天,我便同意了,我没有急着找下家,也没有准备面试背题,而是决定完成手上的工作,站好最后一班岗,给自己在公司的旅程画上一个句号。离职那天,眼角不自觉还是留下了一滴眼泪,是遗憾,是无奈,更是迷茫。 + +其实工作只是雇佣关系,只是我们将工作看得太重,工作是为了更好的生活,既然不能一起走到终点,还不如就此下车。虽然现在市场上僧多粥少,一旦下了车便很难再挤上去。 + +![image.png](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/07bcf03a488b41cd921a1e4f0feb390f~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=1080&h=503&s=686552&e=png&b=06161b) + +程序员失业后,未来的路要怎么走? + +我还是一头雾水,认真思考后总结了 4 条路: + +第一条路:继续寻找下家,坐班打工无疑是现下最好的选择,因为收入稳定,哪怕降薪也在预期之内,不至于饿死; + +第二条路:学好英语,做远程工作;英语是全球的首要沟通语言,学好英语不仅能够打开更广阔的职业机会,还可以让我们进入远程工作的领域;加上外币兑 RMB 的汇率,只要能找到远程工作,相对于国内来说还是比较自由和吃香的。 + +第三条路:做独立开发;作为程序员,我们拥有丰富的技术背景和开发经验,考虑成为独立开发者,开发自己的网站、小程序等,通过自己的产品变现,将收入方式从贩卖时间转变为一种一劳多得的模式,实现自己的创业梦。当然这条路还是比较困难的,包括前期投入,产品 idea,变现模式,后期推广等,尤其是国内针对个人开发者还是不太友好,比如开发一个抖音小程序就需要企业资格,对接支付方式也需要企业资格等,这条路也很漫长,投入和收入也不一定成正比。我认为这条路不一定要马上去实践,但未来可以往这个方向靠拢。 + +第四条路:自媒体;作为程序员可以分享技术经验、创意想法、软件使用技巧等,通过写作、视频等形式输出内容,吸引粉丝和流量,建立个人品牌,实现收益。程序员全职自媒体这条路我是不看好的,因为这条路的收入是可预见的,我之前也在 B 站发了几个视频,广告收益快到 100 块了,一位拥有 1 万粉 B 站 Up  主,一年考广告收入仅 3000 多,更多的全职 Up  主 收入,不仅仅靠广告收入,更重要的商单,而程序员的受众面相对较小,因此程序员做视频大多是兴趣使然,当然不排除下面 2 种 + +1. 海外自媒体,(youtube  和  medium)拥有更广的人群和受众面; +2. 使用 AI 和自动化工具批量产出内容和视频等; + +![image.png](https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/722f153a612a4d8da3f86849f8dc31cf~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=904&h=732&s=102427&e=png&b=ffffff) + +当然还有很多其他的路,如果你与我一样情况,或者对于失业挑战有建议,都可以在下方留言,未来我会不定期分享个人经历与实践。无论选择何种道路,重要的是保持积极的态度和持续的努力,相信自己的能力和潜力。 diff --git "a/data/blog/Shadcn UI \347\216\260\344\273\243 UI \347\273\204\344\273\266\345\272\223.md" "b/data/blog/Shadcn UI \347\216\260\344\273\243 UI \347\273\204\344\273\266\345\272\223.md" new file mode 100644 index 0000000..4886451 --- /dev/null +++ "b/data/blog/Shadcn UI \347\216\260\344\273\243 UI \347\273\204\344\273\266\345\272\223.md" @@ -0,0 +1,223 @@ +--- +title: Shadcn UI 现代 UI 组件库 +date: 2023/11/15 21:17:55 +lastmod: 2024/5/19 21:24:10 +tags: [JavaScript, React.js] +draft: false +summary: Shadcn UI 现代 UI 组件库 前言 不知道大家是否使用过 Shadcn UI,它在Github 上拥有了 35k star,它与大多数 UI 组件库(如 Ant desgin 和 Chakr +images: + [ + 'https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e24919ee73e34d079b4696987938523c~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=3014&h=1714&s=781239&e=png&b=0b0b0d', + ] +authors: ['default'] +layout: PostLayout +--- + +## 前言 + +不知道大家是否使用过 Shadcn UI,它在[Github](https://github.com/shadcn-ui/ui) 上拥有了 35k star,它与大多数 UI 组件库(如 Ant desgin 和 Chakra UI)不同,一般组件库都是通过 npm 的方式给项目使用,代码都是存在 `node_modules` 中,而 Shadcn UI 可以将单个 UI 组件的源代码下载到项目源代码中(src 目录下),开发者可以自由的修改和使用想要的 UI 组件,它已经被一些知名的网站([vercel.com](https://vercel.com/)、[bestofjs.org](https://bestofjs.org/))等使用。那么它到底有什么优势呢? 一起来来探讨下。 + +## Shadcn UI 介绍 + +Shadcn UI 实际上并不是组件库或 UI 框架。相反,它是可以根据文档“让我们复制并粘贴到应用程序中的可复用组件的集合”。它是由 vercel 的工程师[Shadcn](https://twitter.com/shadcn)创建的,他还创建了一些知名的开源项目,如 [Taxonomy](https://vercel.com/templates/next.js/taxonomy),[Next.js for Drupal](https://next-drupal.org/)和[Reflexjs](https://reflexjs.org/)。 + +Radix UI - 是一个无头 UI 库。也就是说,它有组件 API,但没有样式。Shadcn UI 建立在 Tailwind CSS 和 Radix UI 之上,目前支持 Next.js、Gatsby、Remix、Astro、Laravel 和 Vite,并且拥有与其他项目快速集成的能力——[安装指南](https://ui.shadcn.com/docs/installation/manual)。 + +## Shadcn UI 功能特点 + +### 多主题和主题编辑器 + +![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/4883667e8bc74325a211636668b68f75~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=690&h=388&s=1613672&e=gif&f=172&b=030510) + +在 Shadcn UI 的官网上有一个主题编辑器,我们可以点击 `Customize` 按钮实时切换风格和主题颜色,设计完成后,我们只需要拷贝 css 主要变量到我们的程序中即可。 下图是需要拷贝的 css 颜色变量。 + +![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c206429a817743dcbe6a168788c93e91~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=1012&h=1070&s=381387&e=png&b=09090b) + +颜色使用 hls 表示,主题变量分为背景色(background) 和 前景色(foreground),Shadcn UI 约定 css 变量省略 background,比如 `--card` 就是表示的是 card 组件的背景颜色。 + +### 深色模式 + +可以看到复制的 css 变量支持生成深色模式,如果你使用 react, 可以使用 [next-themes](https://github.com/pacocoursey/next-themes),这个包来实现主题切换,当然也可以通过 js 在 html 上切换 dark 这个样式来实现。 除了 react 版,社区还自发实现了 [vue](https://www.shadcn-vue.com/) 和 [svelte](https://www.shadcn-svelte.com/) 版本 + +### CLI + +除了手动从文档中复制组件代码到项目中,还可以使用 cli 来自动生成代码 + +- 初始化配置 + +```bash +npx shadcn-ui@latest init +``` + +![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/4e4f70aeb84b49c59e227638af0e4f5f~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=1388&h=584&s=366378&e=png&b=010101) + +- 添加组件 + +```bash +npx shadcn-ui@latest add +``` + +![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/10154315b60c4a8a877aff8cb15b4680~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=1614&h=586&s=202441&e=png&b=000000) + +按空格选择想要的组件,按回车就会下载选中的 UI 组件代码 + +![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/40087275c72b452a810b2f61813c5967~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=1058&h=280&s=90516&e=png&b=000000) + +下载的源码在 `components/ui` 目录下,并且自动安装 Radix UI 对应的组件。 + +### 丰富的组件库 + +Shadcn UI 拥有丰富的组件,包括 常见的 Form、 Table、 Tab 等 40+ 组件。 + +![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/d2c108ed421845049ee0c5abdd2d8dbe~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=2686&h=1378&s=750189&e=png&b=ffffff) + +![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2b7d7918343f49fa9f229e3d6f443e92~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=2676&h=1148&s=706659&e=png&b=ffffff) + +![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/b63cd210122844999e0672a436e645b7~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=888&h=820&s=179686&e=png&b=ffffff) + +## 使用 Shadcn UI 创建登录表单 + +接下来我们一起实战下,使用 Shadcn UI 创建登录表单, 由于 Shadcn UI 是一个纯 UI 组件,对于复杂的表单,我们还需要使用 react-hook-form 和 zod。 + +首先下载 UI + +```bash +npx shadcn-ui@latest add form +``` + +安装 react-hook-form 以及 zod 验证相关的包 + +```bash +yarn add add react-hook-form zod @hookform/resolvers +``` + +zod 用于格式验证 + +下面代码是最基本的 Form 结构 + +```js +import { + Form, + FormControl, + FormDescription, + FormField, + FormItem, + FormLabel, + FormMessage, +} from '@/components/ui/form' +import { Input } from '@/components/ui/input' +; ( + + Username + + + + This is your public display name. + + + )} +/> +``` + +- `FormField` 用于生成受控的表单字段 +- `FormMessage` 显示表单错误信息 + +### 登录表单代码 + +```js +'use client' + +import { zodResolver } from '@hookform/resolvers/zod' +import { useForm } from 'react-hook-form' +import * as z from 'zod' + +import { Button } from '@/components/ui/button' +import { + Form, + FormControl, + FormField, + FormItem, + FormLabel, + FormMessage, +} from '@/components/ui/form' +import { Input } from '@/components/ui/input' + +const formSchema = z.object({ + email: z.string().email({ message: '邮箱格式不正确' }), + password: z.string({ required_error: '不能为空' }).min(6, { + message: '密码必须大于6位', + }), +}) + +export default function ProfileForm() { + // 1. Define your form. + const form = + useForm < + z.infer < + typeof formSchema >> + { + resolver: zodResolver(formSchema), + defaultValues: { + email: '', + }, + } + + // 2. Define a submit handler. + function onSubmit(values: z.infer) { + // Do something with the form values. + // ✅ This will be type-safe and validated. + console.log(values) + } + + return ( +
+ + ( + + 邮箱 + + + + + + )} + /> + ( + + 密码 + + + + + + )} + /> + + + + ) +} +``` + +展示效果 + +![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/98033db44c02431dbd5987fb3dd198db~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=634&h=406&s=55832&e=png&b=ffffff) + +## 小结 + +与其他组件库相比,Shadcn UI 提供了几个好处。 + +- 易用性:使用复制和粘贴或 CLI 安装方法可以轻松访问其组件. +- 可访问性:Shadcn UI 的组件是完全可访问的,并符合 Web 内容可访问性指南 (WCAG) 标准,它支持屏幕阅读器、键盘导航和其他辅助设备。 +- 灵活和可扩展性:Shadcn UI 只会下载需要使用的组件在源码中,并且开发者可以灵活定制和修改。 + +当然需要手动拷贝安装每一个组件可能是一件麻烦的事情,这也会导致源码量的增加,因此是否使用 Shadcn UI 还得开发者自行决定,总的来说 Shadcn UI,我还是非常看好,我将配合 next.js 在一些新项目中使用。 diff --git "a/data/blog/\345\244\247\345\256\266\351\203\275\345\234\250\345\230\262\347\254\221 Next.js 14.md" "b/data/blog/\345\244\247\345\256\266\351\203\275\345\234\250\345\230\262\347\254\221 Next.js 14.md" new file mode 100644 index 0000000..0c5f7a7 --- /dev/null +++ "b/data/blog/\345\244\247\345\256\266\351\203\275\345\234\250\345\230\262\347\254\221 Next.js 14.md" @@ -0,0 +1,124 @@ +--- +title: 大家都在嘲笑 Next.js 14 +date: 2023/11/3 19:56:06 +lastmod: 2024/5/19 21:24:07 +tags: [React.js] +draft: false +summary: 上周 Next.js 14 发布了,该版本相较于 13,没有任何 API 变更,主要更新点是 Turbopack 带来了大幅的性能提升以及 Server Actions 功能进入稳定版本。 +images: + [ + 'https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/9eba2a4e4476450ab4250d338b53b535~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=1197\&h=1596\&s=113433\&e=jpg\&b=02163e', + ] +authors: ['default'] +layout: PostLayout +--- + +上周 Next.js 14 发布了,该版本相较于 13,没有任何 API 变更,主要更新点是 Turbopack 带来了大幅的性能提升以及 Server Actions 功能进入稳定版本。 + +![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/24c765b1b20a4c9d90e6e026d535f161~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=1540&h=752&s=341590&e=png&b=000000) + +Next.js 14 带来了三个主要新功能 + +- Turbopack:在 app router 和 page router 中通过了 5,000 个测试 + + - 本地启动服务器时间快了约 50% + - 热模块替换速度快了约 94% + +然而并不是所有的测试都通过了,当前只通过了 90% 的测试,所以 Turbopack 还不稳定。 + +- 第二点 Server Actions 被标记为稳定。 + - 集成了缓存和重新验证 + - 简单的函数调用,与表单原生配合使用 +- 第三点 **部分预渲染(预览)**:快速的初始静态响应 + 流式动态内容 + +其中第二点在 Twitter 中引起了巨大讨论,也就是下面这张图, + +![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/59a2b92e3bab4aeb95e1b7e6ff58af4a~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=972&h=569&s=173045&e=png&b=080608) + +大家都在拿这张图开玩笑,甚至出现了 "use electronics"。 + +![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/4a67e433b27947b2b8e764d1a72350e7~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=559&h=564&s=177245&e=png&b=0c0c0c) + +这种写法好像仿佛回到了 PHP 时代,前端后代码写在一个文件里,它非常容易理解,但是很多人在质疑代码的安全问题,Sql 没有使用占位符,它是否会受到**SQL 注入攻击**。 + +那么我们来分析下,上面幻灯片中的代码是否存在安全问题, +最主要是下面这句。 + +```js +await sql`INSERT INTO Bookmarks (slug) VALUES (${slug})` +``` + +## SQL 注入攻击 + +首先来看下 Sql 是如何注入攻击的。 + +比如,我们需要通过 Url 获得当前用户的 id,查询该用户的信息,使用以下代码来实现。 + +![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/63dc1898734845cbaa52ac6eb9c192e9~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=1436&h=490&s=318737&e=png&b=201f1f) + +一旦用户知道了程序的漏洞,使用以下 url 来访问,那么我们的程序将瞬间被摧毁。 + +![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/3206433053534e5397bf791a523813a7~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=1624&h=382&s=665545&e=png&b=212020) + +这是一个有效的 SQL 命令,查询的同时将删除所有用户。 + +![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/66ee78097fe3466d98e0c4cb95bc13e9~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=1740&h=288&s=356333&e=png&b=212020) + +数据库在这种情况下执行,它会变成两个 sql 查询: + +第一个 sql select 语句,它实际上不做任何事情; + +第二个 sql 会删除你的整个 Users 数据库; + +这就是 sql 注入,因此,直接拼接的 sql,不经过处理,是不安全的。 + +安全的查询方法是需要使用参数化查询, 如下: + +![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/f98e2d80c1ee4cd6bca090c1b0b9c756~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=1542&h=420&s=247601&e=png&b=201f1f) + +`userId` 会替换 sql 中的`$1`,这样 sql 执行就安全了。 + +## 标签模板 + +我们再看上面幻灯片中的 sql 语句,与上面两种操作数据不同的是他使用的是 ES6 中的 **标签模板** + +```js +await sql`INSERT INTO Bookmarks (slug) VALUES (${slug})` +``` + +标签模板其实不是模板字符串,而是函数调用的一种特殊形式。“标签”指的就是函数,紧跟在后面的模板字符串就是它的参数。 + +```js +tag`hello` +// 等同于 +tag(['hello']) +``` + +因此在标签模版之前需要先定义函数 + +```js +function tag(stringArr, ...values) { + // ... +} +``` + +tag 函数的第一个参数是模版字符串,它是一个数组,后面的参数为模版中传入的值,也就是上面的`sql` 是一个函数,执行代码等同于 + +```js +await sql(['INSERT INTO Bookmarks (slug) VALUES (', ')'], slug) +``` + +因此幻灯片中的查询语句并不会直接在数据库上执行,而是经过了 sql 这个函数的封装,调用数据库的查询语言都在 sql 内部实现,它没有 sql 注入的风险。 + +## 小结 + +Next.js 14.0 加快了启动服务器时间和模块热替换,分别提速 50%和 94%,引入了部分预渲染,允许定义一个静态 HTML 壳,然后可以用``流式传输动态内容; Server Actions 虽然引起了争议,那也只是大家工作之余的调侃,相比原先必须先写一个接口,再调接口,但对开发者来说是极大地简化了开发成本,可以直接请求数据库拿数据,对前端来说,真的太方便了。 + +那么,你认为呢? +以上就是本文全部内容,希望这篇文章对大家有所帮助,也可以参考我往期的文章或者在评论区交流你的想法和心得,欢迎一起探索前端。 + +## 参考 + +- https://nextjs.org/blog/next-14 + +- https://youtu.be/2Ggf45daK7k?si=ZxrjR5o2PIMOpM7W diff --git "a/data/blog/\345\260\206 Node \345\272\224\347\224\250 Express.js \351\203\250\347\275\262\345\210\260 Vercel.md" "b/data/blog/\345\260\206 Node \345\272\224\347\224\250 Express.js \351\203\250\347\275\262\345\210\260 Vercel.md" new file mode 100644 index 0000000..307260d --- /dev/null +++ "b/data/blog/\345\260\206 Node \345\272\224\347\224\250 Express.js \351\203\250\347\275\262\345\210\260 Vercel.md" @@ -0,0 +1,183 @@ +--- +title: 将 Node 应用 Express.js 部署到 Vercel +date: 2024/5/9 22:14:19 +lastmod: 2024/5/19 21:24:18 +tags: [Node.js] +draft: false +summary: 前言 之前有期视频介绍过,在 Vercel 上可以免费部署很多应用,包括 Next.js、Nuxt、Remix。除了 Node.js 甚至还支持其他语言,包括 Go、 Python、Ruby +images: + [ + 'https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0da60f59149447b3b05939621e81a6ee~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=1784\&h=752\&s=168101\&e=png\&b=020001', + ] +authors: ['default'] +layout: PostLayout +--- + +--- + +## title: 将 Node 应用 Express.js 部署到 Vercel + +## 前言 + +之前有期视频介绍过,在 Vercel 上可以免费部署很多应用,包括 Next.js、Nuxt、Remix。除了 Node.js 甚至还支持其他语言,包括 Go、 Python、Ruby,但在 Node.js 中有一个老牌的框架 Express.js,很多应用都是通过 Express.js 创建的,本文将记录下,如何将 Express.js 应用部署到 Vercel,以及它在 serverless 环境中应该考虑的因素。 + +在 Vercel 上部署 Express.js 应用程序只需要修改少量代码。让我们使用以下步骤创建一个新的 Express.js 项目并将其部署到 Vercel。 + +## 使用模板 + +Vercel 官网有一个 [Express.js 项目示例](https://github.com/vercel/examples/tree/main/solutions/express 'Express.js 项目示例'),可以将其克隆并部署到 Vercel 作为项目的初始模板。 + +## 迁移现有项目 + +前置条件 + +- 安装 Node.js 环境 +- 拥有 vercel 账号(可使用 Github 账号登录) + +### 创建一个 Express.js 项目 + +```bash +mkdir new-express-project +cd new-express-project +npm init -y +npm install express +``` + +并且我们创建一个`src/index.js` 作为入口文件 + +```js +const express = require('express') +const app = express() + +app.get('/', (req, res) => res.send('Hello Express')) + +app.listen(3000, () => console.log('Server ready on port 3000.')) +``` + +现在,我们运行 `node src/index.js` 便可以在本地启动 Express.js 服务。访问 页面显示 Hello Express。 + +### 适配 vercel + +我们知道 Vercel 是提供的是 serverless 服务,因此他有一个 api 目录作为每个函数的入口程序。 + +比如我们新建一个文件 `api/hello.js` + +```js title=api/hello.js +export default function handler(request, response) { + const { name = 'World' } = request.query + return response.send(`Hello ${name}!`) +} +``` + +部署到 Vercel 之后,访问 + +页面就会显示 Hello Vercel。 + +这就是 serverless,如要将传统 node 程序迁移到 serverless,需要改动大量代码。 + +幸运的是 vercel 已经实现了适配 express.js。 + +1. 新建一个 `api/index.js` 作为主程序的入口。 + +```js +const { app } = require('../src') + +module.exports = app +``` + +并且导出 app。 + +2. 修改在 `src/index.js` 中导出 app + +```diff-js +const express = require("express"); +const app = express(); + +app.get("/", (req, res) => res.send("Hello Express")); + +app.listen(3000, () => console.log("Server ready on port 3000.")); + ++ exports.app = app; +``` + +3. 在根目录下新建一个文件 `vercel.json` + +```json +{ "version": 2, "rewrites": [{ "source": "/(.*)", "destination": "/api" }] +``` + +通过使用 vercel.json 文件,我们可以控制 Vercel 配置应用程序的路由,将告诉 Vercel 将所有传入请求路由到我们的 `/api` 文件夹。 + +## 本地运行 + +我们可以使用 Vercel CLI 在本地模拟 Vercel 部署的环境。这样运行方式与 vercel 保持一致 + +首先,我们需要在终端中运行以下命令来安装 Vercel CLI。 + +```bash +npm i -g vercel +``` + +接下来,登录 Vercel 以授权,Vercel CLI 在您的 Vercel 账户上运行命令。 + +```bash +vercel login +``` + +现在我们使用本地开发命令,该命令还将执行上面创建的`vercel.json`配置。 + +```bash +vercel dev +``` + +运行 `vercel dev` 会问你一些问题,随意回答即可。 + +回答完问题后,您现在应该在 上有一个本地运行的服务器,我们可以在部署到 Vercel 之前测试该应用程序是否正常运行。 + +## 部署 + +我们可以将代码提交到 Github 中, 然后在 vercel 仪表盘中关联 git 项目,这样每次提交代码就会自动部署。也可以使用 vercel cli 来部署。 + +只需要执行 + +```bash +vercel +``` + +就可以打包部署,在控制台中会打印 2 个地址,第一个链接地址可以查看部署情况。第二个链接就是生成的预览地址。 + +![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c9af2d9dbff74cfd99626809f5a7c30d~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=1612&h=580&s=333581&e=png&b=010101) + +使用 `vercel --prod` 可以将预览环境发布到生产环境。 + +## 适配 serverless 环境 + +如果从服务器环境迁移到 vercel serverless 环境,可能还需要考虑几个因素, 因为不再有服务器在后台运行 + +**Websockets**:serverless 函数具有最大执行时间限制,因此需要尽快响应。因此需要客户端定时请求数据,推荐使用使用 [swr](https://swr.vercel.app/zh-CN) 方案代替,或者考虑使用 serverless 友好的[实时数据提供程序](https://vercel.com/docs/solutions/realtime)。 + +**数据库连接**:serverless 函数的本质意味着它们可以打开多个数据库连接以响应不断增加的流量。为了有效地管理这一点,请使用 serverless 友好的数据库或[实时连接池](https://vercel.com/docs/solutions/databases)。这有助于确保最佳连接并维持应用程序的正常运行时间。 + +- **模板和视图引擎**:在 serverless 环境中,优化响应计算至关重要。考虑 React、Pug 或 EJS 等视图引擎的效率。设置正确的标头以启用缓存也很重要,从而避免需要为每个请求计算相同的响应。这种方法最大限度地减少了按需计算,并利用缓存的内容来满足未来的请求。 + +例如在 vercel.json 配置缓存 + +```json +{ + "version": 2, + "rewrites": [{ "source": "/(.*)", "destination": "/api" }], + "headers": [ + { + "source": "/assets/(.*)", + "headers": [ + { + "key": "Cache-Control", + "value": "max-age=31536000, immutable" + } + ] + } + ] +} +``` + +参考: diff --git "a/data/blog/\346\231\256\351\200\232\347\250\213\345\272\217\345\221\230\350\246\201\345\246\202\344\275\225\346\212\200\346\234\257\345\206\231\344\275\234\345\217\230\347\216\260\357\274\237.md" "b/data/blog/\346\231\256\351\200\232\347\250\213\345\272\217\345\221\230\350\246\201\345\246\202\344\275\225\346\212\200\346\234\257\345\206\231\344\275\234\345\217\230\347\216\260\357\274\237.md" new file mode 100644 index 0000000..69b035c --- /dev/null +++ "b/data/blog/\346\231\256\351\200\232\347\250\213\345\272\217\345\221\230\350\246\201\345\246\202\344\275\225\346\212\200\346\234\257\345\206\231\344\275\234\345\217\230\347\216\260\357\274\237.md" @@ -0,0 +1,94 @@ +--- +title: 普通程序员要如何技术写作变现? +date: 2024/3/15 15:42:31 +lastmod: 2024/5/19 21:24:12 +tags: [程序员] +draft: false +summary: AI 爆发,技术写作还有意义吗? 2023 年,人工智能爆发,ChatGPT 的出现对许多行业产生了巨大的冲击。对我来说,原本以为写博客、建立个人知识库等学习方式会变得可有可无,但实际情况是,写作变得 +images: + [ + 'https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/6a33cdd53d49444a886c7491ab41c03e~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=800\&h=450\&s=51350\&e=jpg\&b=2e2a2e', + ] +authors: ['default'] +layout: PostLayout +--- + +--- + +## title: 普通程序员要如何技术写作变现? + +## AI 爆发,技术写作还有意义吗? + +2023 年,人工智能爆发,ChatGPT 的出现对许多行业产生了巨大的冲击。对我来说,原本以为写博客、建立个人知识库等学习方式会变得可有可无,但实际情况是,写作变得越来越重要。 + +这是因为,尽管 AI 技术的发展为我们提供了诸多便利,但它并不能完全替代人类的思考。写作不仅是一种表达,也是一种深度思考的过程,它能帮助我们更好地理解和掌握知识。同时,高质量的内容也能吸引更多的读者,对于程序员来说,这不仅能提升个人品牌影响力,也有可能带来额外的收入。 + +因此,不论是从个人发展,还是从职业发展的角度看,写作都是一项非常重要的技能。即使在 AI 高度发达的今天,我们也不能忽视写作的价值。 + +## 技术写作能赚多少钱? + +笔者是一名写作新手,之前也只是随便写写博客,仅当做是对自己学习过程的积累,从没想过通过写作变现,也就是 2 年前,参加掘金的更文活动,就像升级打怪,每月更文 7 篇、14 篇、就会有不同的奖品,当收到这些礼品的时候,总是满怀欣喜和成就感,付出的到了回报。 + +![image.png](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/36ec362ce8a34d94b59a179701dc50a0~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=1338&h=846&s=269290&e=png&b=fefefe) + +2023 我分别在掘金和微信公众号发布了 15 篇文章,获得了 1000+的收益,这点钱对于工作来说可能是凤毛麟角,但我却觉得这不失为在互联网寒冬的另外一条路,因为这 15 篇文章我并没有花费很多精力去写,而是我学习过程的记录。如果数量和阅读量上去了,收益就会更多。 + +当到达一定阅读量后,就会有出版社的编辑找你,出版书籍,或者出掘金小册,运营自己的知识星球等,通过知识变现。当然这是后话,最重要的的是开始的第一步。总之,写作是一件短期收益少,长期收益长的事。 + +## 如何开始写作? + +回想初高中的时候,如果给你一个作文标题,如果心中没有固定的题材,总感觉写作在“挤牙膏”,硬生生的凑数到 800 字,因此,这才让我(或者说大多数人)不爱写作,但现在,没有人给我固定的标题,没有人给我固定的写什么内容,我们想写什么就写什么,我们可以用文字记录自己的悲与喜,用文字宣泄情绪,用文字记录灵感和想法,用文字复盘总结知识,用文字记录生活中的感动。 + +有这么多可写,但是还是不知道该写什么,怎么办? + +从日记开始,首先给自己定一个日记模板,以下是我的日记模板,你可以根据自己的需要进行修改和补充。 + +```markdown +## 目标/问题 + + - 记录自己的待办事项,以及要完成的目标 + - 心中的疑惑 + +## 思考/经历 + + - 围绕目标写下思考和行动的过程 + - 围绕问题记录解决排查过程 + +## 总结 + + - 总结今天的收获,比如学到的新知识、新技能、新的感悟等 + - 也可以是对自己的成长和进步的思考 +``` + +日记也不是到每天晚上去写,若是每天晚上去写,这会让人有写日报的感觉,而是随时都在写,一般每天早上记录目标,一边思考一边记录,当目标完成时,总结一下,这样就完成了一天的日记。有目标的去生活每一天,我们的生活也会变得更加充实,也不会有浑浑噩噩的感觉。 + +有了 1 天的日记,再根据日记去重新梳理出一篇文章,那就非常轻松,或者将单个目标整理成一篇文章,这样日记就会变得简洁,而我们的文章数量也会逐步增加。 + +## 多平台发布 + +写好一篇文章之后,一定要发布。因为人有一定的惰性,如果文章不发布,只会让我们越记越简单,要发布的文章就会让我们认真对待,至少语句通顺,有头有尾。发布之后就会有读者给你点赞评论,就可以通过社交评论,知道自己文章好与坏。 + +大家也可以找找适合自己的社交平台,不同平台的阅读群体也不同。 + +- 掘金可能更受技术开发者和程序员的青睐,因为它提供了很多关于技术编程、开发工具等方面的内容。 +- CSDN 也是一个技术社区,读者群体可能以程序员、技术爱好者为主。 +- 知乎则更加综合一些,吸引了各个领域的用户,包括知识爱好者、问题寻求者以及喜欢分享观点的人。 +- 简书可能更侧重于文学、写作和创作领域,吸引了一些喜欢写作、分享故事和文章的读者。 + +我会将文章发表在掘金、博客和微信公众号。 + +- 文章发表在掘金、就可以参与活动,获得奖品,到达 v4 后可以参与瓜分现金活动。 +- 文章发表在微信公众号,就可以通过阅读量获得广告收益,公众号有自动推荐功能,就算是个小号,只要认真写也会有阅读量。 +- 如果觉得文章不错,还有时间,可以把文章翻译成英文,发布到 赚取美刀,我看 medium 上的很多技术文章都是通过中文翻译的。 + +## 内外兼顾 + +大部分人都是兼职写作,因此作品内容价值最大化价值并非在外部平台分发,而是在公司内的传播。在公司内部分享知识有利于提升自己在公司内部的形象,对于考核加分甚至于内部晋升都有帮助。 + +也就是从文字到 PPT 分享的过程。有了文字稿,分享的过程也会得心应手。 + +最简单快捷的的方式就是使用 Markdown 制作 PPT,可以使用 [MDX Editor](https://editor.runjs.cool/ 'MDX Editor')、[revealjs](https://revealjs.com/markdown/ 'revealjs')、[sli.dev](https://sli.dev/ 'sli.dev')等工具,文章内容大纲使用`---` 分割,就会成为一张一张的幻灯片。 + +这样,同一主题的内容以文字、课件的形式在公司内外传播,对内外的影响力都会增加。由于知识内容是相同的,只是形式不同,因此创作所需的时间远少于独立创作。 + +当然,如果你有足够的精力,还可以把对外发布的文章和 PPT 剪辑成视频,放在公司内部平台上或者 B 站等外部平台上,进一步增强自己的影响力。