NodeJS+3D酷炫动画玩转纯手工打造个人博客,不用博客框架

12,988 阅读10分钟

前言

那些优秀的程序猿,特别是大佬级别的开发者,都会有自己的个人博客网站。曾经有个老铁跟我说,一个程序猿爱好者没有属于自己的博客,还不算真正进入我们这个行当,用球迷的话来说,就是伪球迷。此言差矣,其实每个人的追求不一样。也可能是精力有限为了生计,不过借助一些知名的社交平台(掘金、思否、CSDN、博客园、简书、知乎、公众号)也是不错的选择。但小编还是希望小伙伴们能抽出一点点时间,撸一个出来。为什么要弄个人博客?

为什么要弄个人博客?

建立知识体系

写博客,可以将你学的七零八碎的知识点整合到一起,形成完整的个人笔记。这份笔记,记录了你囫囵吞枣的内容,也记录了你从理论到实践的历程。如果有一天,你想回顾这些知识点,对照着曾经记录的笔记,会起到事半功倍的效果。

那么光是记录笔记就可以了么?

你还要把笔记分享出来,因为有人监督与无人监督的效果大相径庭。如果是自己私下的笔记,可能不由自主地会松上一口气,往往做着做着就半途而废以至于前功尽弃。就好比你可以肆无忌惮在自己的房间里自言自语,然而发布朋友圈的时候却往往谨小慎微,因为不是只有你一个人可以看到这些内容。你知道你的文章会被别人阅读,自然要打起十二分精神全力以赴,希望获得别人的认可。态度决定成败,在别人“眼皮底下”写作,更能拿出认真的精神气儿。

如果觉得自己已经掌握某个知识点的时候,不妨写一篇文章,如果能让大部分读者读懂,说明这个知识点你掌握得还不错。除此之外,读者的点赞👍或评论,也是鼓励你查漏补缺的突破口。

总之,这些文章会成为你珍贵的个人财富。:muscle:

养成写作习惯

人往往是懒惰的,除非明天就会失业,不然很难会在今天狠狠逼自己一把。

写个人博客的好处就在于:你总是紧绷着一根弦,不断提醒自己,这个月还有一篇博客要写,不能让读者们等急了。有压力,才有动力,不至于浑浑噩噩度日。

提升个人品牌

坚持写博客,你的影响力便不知不觉地渗透出去,“酒香也怕巷子深”,现代社会绝不能孤芳自赏。才华转化为影响力的那一瞬间,才是你的价值所在。

你的影响力越大,身边的机会就越多。你的个人品牌,是你最好的“护城河”。

快乐写作

写个人博客其实也是一件蛮快乐的事,一天之中难得的放松机会,得以反思工作的得失。特别是将写好的文章分享出去,自豪感油然而生。

读者也可以从中汲取养分,互惠互利,岂不乐乎?😋

回归主题

接下来实战分享,由于参考了一些官网的示例,觉得很不错,自己就简单的研究了一下,动手弄着玩玩。纯手工打造酷炫个人博客网站,适配PC端和移动端。

Web3研习社👉:54web3.cc/

部分截图

目录结构

│  app.js                            // 入口文件
│  ecosystem.config.js               // pm2默认配置文件
│  package.json                      // npm包管理所需模块及配置信息
└─public
    │  favicon.ico                   // 图标
    │  index.html                    // 入口html文件
    ├─assets                         // 存放公共文件夹
    │  └─audios                      // 存放音频MP3文件夹
    │  └─css                         // 存放样式文件夹
    │  └─fonts                       // 存放字体文件夹
    │  └─images                      // 存放图片文件夹
    │  └─js
    │          index.js              // JS封装公共方法文件
    │          three.r112.js         // JS三维模型库TweenLite.js          // JS动画库

技术栈

  • NodeJS v10
  • Express v4.17
  • Normalize.css
  • CSS3动画
  • 媒介查询
  • Three.r112.js
  • TweenLite.js
  • nodemon
  • pm2

功能模块

  • 顶部导航翻转
  • 首屏3D人物动画
  • 屏幕滚动视差效果
  • 背景音乐
  • 鼠标点击首屏人物动效
  • 博客栏目粒子动效
  • 联系我栏目人群穿梭动效

代码实现

个人博客分三个栏目:关于我、技术博客、联系我。

准备工作

  1. windows 10系统
  2. 下载安装 nodejs v10+ nodejs.org/zh-cn/
  3. 代码编辑器工具 Sublime Text 3 & VS Code

代码实现

生成package.json文件

npm init -y

安装nodemon & express

npm i -D nodemon
npm i -S express

根目录新建app.js文件

const express = require('express')
const app = express()

// 设置静态文件目录
app.use(express.static(__dirname + '/public'))

// 路由重定向
app.all('*', (req, res) => {
	res.redirect(302, '/'); 
})

// 监听8888端口
app.listen(8888, () => { 
	console.log('服务启动成功 http://localhost:8888')
})

http-server构建本地服务替代Express

npm i http-server -g
  • 启动服务
http-server -c-1 -p 8888
  • 关闭服务
快捷键Ctrl+C

入口html引入以下文件

项目中引入对应的Normalize.css、Three.r112.js、TweenLite.js等css和js文件。

  • Normalize.css

Normalize.css 只是一个很小的css文件,但它在默认的HTML元素样式上提供了跨浏览器的高度一致性。相比于传统的css reset,Normalize.css是一种现代的,为HTML5准备的优质替代方案。Normalize.css现在已经被用于Twitter Bootstrap,HTML5 Boilerplate,GOV.UK,Rdio,CSS Tricks以及许许多多其他的框架,工具和网站上。

  • Three.js

Threejs 是一款运行在浏览器中的 3D 引擎,你可以用它创建各种三维场景,包括摄影机、光影、材质等各种对象。你可以在它的主页上看到许多精彩的演示。

Threejs 是一个让用户通过javascript入手进入搭建webgl项目的类库。众所周知学习webgl需要图形学知识,而webgl需要通过js和glsl两种语言。如果我们不通过threejs使用webgl势必逃不过底层知识:你必须全面了解着色器语法和自己编写顶点着色片元着色;但你使用了threejs显然可以便捷的逃过这些难懂的底层,对于传统js从业人员挑战的shader确实是有难度的。

快速上手threejs需要什么基础?

  1. 对于3D美术知识的了解
  2. 对于Javascript的能力以及OOP程序开发能力,游戏开发能力
  • TweenLite.js

TweenLite 是一个非常快速、轻量级和灵活的动画工具,它是GreenSock动画平台(GSAP)的基础。TweenLite实例处理随时间推移对任何对象(或对象数组)的一个或多个属性进行渐变。TweenLite可以用最小的文件大小来完成大部分的动画任务,或者它可以与先进的排序工具(如TimelineLite或TimelineMax)一起使用,使复杂的任务变得更简单。

如需了解更多详情请移步到对应的官网,以上样式库和JS库都有提供官网地址。小编只是了解,这里就不班门弄斧了。

主页index.html代码如下:

<!DOCTYPE html>
<html class="no-js wf-loading is-en" lang="en">
 <head> 
  <meta charset="utf-8" /> 
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /> 
  <meta name="theme-color" content="#0c0720" /> 
  <meta name="msapplication-TileColor" content="#da532c" /> 
  <meta name="theme-color" content="#ffffff" />
  <link rel=icon href=/favicon.ico> 
  <title>JackChen个人官网</title> 
  <meta name="description" content="blog is a real-time, development focussed, creative studio." /> 
  <meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1,user-scalable=no" /> 
  <script> 
    // 判断手机端或PC端
    var ua = (navigator.userAgent || navigator.vendor || window.opera).toLowerCase();
    document.documentElement.className += /(iPad|iPhone|Android)/i.test(ua) ? ' is-mobile' : ' is-desktop';
    document.documentElement.className = document.documentElement.className.replace('no-js','js');
    var supportedLangs = ['en', 'cn'];
    var lang = 'en'; 
  </script> 
  <link rel="stylesheet" href="/assets/css/index.css" /> 
 </head> 
 <body> 
  <canvas id="canvas"></canvas> 
  <div id="app"> 
   <div id="main" data-scroll-tooltip="Scroll to begin"> 
    <div id="main-scroll"> 
     <div id="page-container">
      <main id="about" class="page is-about" data-id="about" data-page-id="about" data-url="about" data-title="JackChen个人官网"> 

       <section id="about-hero" class="hero is-full"> 
        <div id="about-hero-context" class="hero-context flex-vertical"> 
         <div class="hero-inner"> 
          <h1 id="about-hero-title" class="hero-title flex-vertical">Hello, I am JackChen</h1> 
          <h4 id="about-hero-desc" class="hero-desc flex-vertical">认真做好每一个细节,用心写好每一段代码</h4> 
         </div> 
        </div> 
       </section> 

       <section id="about-blog" class="is-full margin-bottom-full"> 
        <div id="about-blog-context" class="sec-context flex-vertical"> 
         <div class="sec-context-inner is-right darker-bg"> 
          <h3 id="about-blog-title" class="about-sec-title font-header"></h3> 
          <h4 id="about-blog-subtitle" class="about-sec-subtitle font-header">个人信息</h4> 
          <div id="about-blog-desc" class="about-sec-desc">
            我是<b>「JackChen」</b>,很幸运成为80后,坐标湖南省长沙县,一名非常热爱学习的<b>「高级前端开发工程师」</b>。有着不平凡的工作经历,让我对自己的人生方向更加坚定,因为自己的兴趣而踏足前端,是一件让我毕生难忘的事情。
            <br />
            <br />
            <b>「学习和写作」</b>是目前唯一每天都能坚持完成的事情,业余时间的我,喜欢写作和分享。我运营着自己的公众号<b>「懒人码农」</b>和有着一群喜欢阅读我文章的读者,每天最大的快乐就是能和各位同学一起交流学习一起共同进步。
          </div> 
         </div> 
        </div> 
       </section> 

       <section id="about-services" class="is-full"> 
        <div id="about-services-context" class="sec-context flex-vertical"> 
         <div class="sec-context-inner is-right darker-bg"> 
          <h3 id="about-services-title" class="about-sec-subtitle font-header">自我评价</h3> 
          <h4 id="about-services-subtitle" class="about-sec-title">1. 热爱学习,工作认真,心思细腻,乐于沟通,服从安排。<br>2. 有轻微代码洁癖,追求编码细节和代码规范,认真写好每一行代码。<br>3. 拥有扎实的前端基础,擅长基于JavaScript开发各种Web应用和Node应用。<br>4. 几年工作都在电商、汽车、文娱、区块链等行业的大中厂,对大中公司的产品开发流程有一定的了解。</h4> 
          <div id="about-services-items"> 
           <div class="about-services-item"> 
            <div class="about-services-item-title font-bold">发现</div> 
            <ul class="about-services-subitems nav"> 
             <li class="about-services-subitem">个人能力</li> 
             <li class="about-services-subitem">团队精神</li> 
             <li class="about-services-subitem">目标管理</li> 
            </ul>
           </div> 
           <div class="about-services-item"> 
            <div class="about-services-item-title font-bold">标签</div> 
            <ul class="about-services-subitems nav"> 
             <li class="about-services-subitem">执行力</li> 
             <li class="about-services-subitem">责任心</li> 
             <li class="about-services-subitem">自驱动</li>
            </ul>
           </div> 
           <div class="about-services-item"> 
            <div class="about-services-item-title font-bold">爱好</div> 
            <ul class="about-services-subitems nav"> 
             <li class="about-services-subitem">学习</li> 
             <li class="about-services-subitem">阅读</li> 
             <li class="about-services-subitem">写作</li> 
            </ul>
           </div> 
          </div> 
         </div> 
        </div>
       </section> 
       
       <div class="is-full"></div> 
      </main>
     </div> 

     <div id="featured"> 
      <div id="featured-context" class="sec-context"> 
       <div class="sec-context-inner"> 
        <h3 id="featured-title" class="sec-title font-header">精选文章</h3> 
        <div id="featured-desc" class="sec-desc font-bold">「懒人码农」公众号作者,实战开发者,支持文章投稿及相互开白名单。一切技术问题,都要服从产品交付和市场反馈。</div> 
       </div> 
       <div id="featured-items-container"> 

        <div class="featured-item" data-id="img-1"> 
          <a class="featured-item-link" href="https://juejin.im/post/5ef0a38af265da0291786b6e"> 
            <div class="featured-item-image">
              <div class="featured-item-image-inner"></div>
            </div> 
            <div class="featured-item-context is-white-content" data-base-color="#00f"> 
             <div class="featured-item-desc font-header-bold split-line-mask-effect">NodeJS全栈开发一个功能完善的Express项目(附完整源码)</div> 
             <div class="featured-item-client split-line-mask-effect">NodeJS全栈入门</div> 
             <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 8 8">
              <polygon points="6.767 0.603 6.767 5.897 0.871 0 0 0.872 5.894 6.767 0.605 6.767 0.605 8 8 8 8 0.603 6.767 0.603" />
             </svg> 
            </div> 
          </a> 
        </div>

        <div class="featured-item" data-id="img-2"> 
          <a class="featured-item-link" href="https://juejin.im/post/5efca542f265da22c058d8ed"> 
            <div class="featured-item-image">
             <div class="featured-item-image-inner"></div>
            </div> 
            <div class="featured-item-context is-white-content" data-base-color="#00f"> 
             <div class="featured-item-desc font-header-bold split-line-mask-effect">Vue+Echarts构建大数据可视化酷炫展示公司品牌实战项目分享(附源码)</div> 
             <div class="featured-item-client split-line-mask-effect">大数据可视化平台</div> 
             <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 8 8">
              <polygon points="6.767 0.603 6.767 5.897 0.871 0 0 0.872 5.894 6.767 0.605 6.767 0.605 8 8 8 8 0.603 6.767 0.603" />
             </svg> 
            </div> 
          </a> 
        </div>

        <div class="featured-item" data-id="img-3"> 
          <a class="featured-item-link" href="https://juejin.im/post/5f01b5325188252e6e15095c"> 
            <div class="featured-item-image">
             <div class="featured-item-image-inner"></div>
            </div> 
            <div class="featured-item-context is-white-content" data-base-color="#00f"> 
             <div class="featured-item-desc font-header-bold split-line-mask-effect">开发一款微信小程序的个性简历,能打开大厂之门并获得门票?(附源码)</div> 
             <div class="featured-item-client split-line-mask-effect">微信小程序</div> 
             <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 8 8">
              <polygon points="6.767 0.603 6.767 5.897 0.871 0 0 0.872 5.894 6.767 0.605 6.767 0.605 8 8 8 8 0.603 6.767 0.603" />
             </svg> 
            </div> 
          </a> 
        </div>

        <div class="featured-item" data-id="img-4"> 
          <a class="featured-item-link" href="https://juejin.im/post/5ef8a8ed6fb9a07e944ed6d6"> 
            <div class="featured-item-image">
             <div class="featured-item-image-inner"></div>
            </div> 
            <div class="featured-item-context is-white-content" data-base-color="#00f"> 
             <div class="featured-item-desc font-header-bold split-line-mask-effect">2020值得收藏与学习280多款H5小游戏,从入门到彻底了解它(附源码)</div> 
             <div class="featured-item-client split-line-mask-effect">H5小游戏</div> 
             <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 8 8">
              <polygon points="6.767 0.603 6.767 5.897 0.871 0 0 0.872 5.894 6.767 0.605 6.767 0.605 8 8 8 8 0.603 6.767 0.603" />
             </svg> 
            </div> 
          </a> 
        </div> 

        <div class="featured-item" data-id="img-5"> 
          <a class="featured-item-link" href="https://juejin.im/post/5f05c351f265da22fe241ade"> 
            <div class="featured-item-image">
             <div class="featured-item-image-inner"></div>
            </div> 
            <div class="featured-item-context is-white-content" data-base-color="#00f"> 
             <div class="featured-item-desc font-header-bold split-line-mask-effect">Vue+Express+Webpack自建脚手架完善单页面应用,档次瞬间提高(附完整源码</div> 
             <div class="featured-item-client split-line-mask-effect">NodeJS全栈进阶</div> 
             <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 8 8">
              <polygon points="6.767 0.603 6.767 5.897 0.871 0 0 0.872 5.894 6.767 0.605 6.767 0.605 8 8 8 8 0.603 6.767 0.603" />
             </svg> 
            </div> 
          </a> 
        </div>

       </div> 
      </div> 
     </div> 

     <div id="contact"> 
      <div id="contact-main"> 
       <div id="contact-context" class="sec-context flex-vertical"> 
        <div class="sec-context-inner darker-bg is-left"> 
         <h4 id="contact-title">联系我😃</h4> 
         <div id="contact-desc">听说你在找我哦,👉明智的选择👍</div> 
         <div id="contact-columns"> 
          <div class="contact-column"> 
           <div class="contact-column-title font-bold">联络</div> 
           <ul class="nav">
            <li class="contact-column-item">手机:13787081615</li>
            <li class="contact-column-item">邮箱:278910933@qq.com</li>
            <li class="contact-column-item">Q<span style="padding-left: 8px;"></span>Q:278910933</li>
            <li class="contact-column-item">微信:13787081615</li>
           </ul> 
          </div> 
          <div class="contact-column"> 
           <div class="contact-column-title font-bold">社交</div> 
           <ul class="nav">
            <li class="contact-column-item"><a href="https://github.com/jackchen0120" target="_blank" rel="noreferrer">Github</a></li>
            <li class="contact-column-item"><a href="https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2020/7/5/1731eb762d539047~tplv-t2oaga2asx-image.image" target="_blank" rel="noreferrer">公众号</a></li>
            <li class="contact-column-item"><a href="https://juejin.im/user/5eafd5fff265da7be959f56a/posts" target="_blank" rel="noreferrer">掘金</a></li>
            <li class="contact-column-item"><a href="https://blog.csdn.net/qq_15041931" target="_blank" rel="noreferrer">CSDN</a></li>
           </ul> 
          </div> 
         </div> 
         <div class="clear-fix"></div>
        </div> 
       </div> 
      </div> 

      <footer id="contact-footer"> 
       <div id="contact-footer-copyright" class="font-subheader">
        &copy; 2020-2025 微信公众号@懒人码农 All Rights Reserved.
       </div> 
      </footer> 
     </div> 
    </div> 
   </div> 

   <div id="main-scrollbar">
    <div id="main-scrollbar-indicator"></div>
   </div>

   <div id="menu"> 
    <canvas id="menu-canvas"></canvas> 
    <div id="menu-content" class="flex-vertical"> 
     <ul id="menu-menu" class="nav">  
      <li class="menu-menu-item is-about"><a href="/about">关于我</a></li> 
      <li class="menu-menu-item is-blog"><a href="/blog">技术博客</a></li> 
      <li class="menu-menu-item is-contact"><a href="/contact">联系我</a></li> 
     </ul> 
     <div id="menu-lang-selector"></div> 
    </div> 
   </div> 

   <header id="header" class="font-subheader cache"> 
    <div id="header-content"> 
     <a aria-label="homepage" href="/about" id="header-logo">JackChen</a> 
     <ul id="header-menu" class="nav"> 
      <li class="header-menu-item header-item is-contact">
        <a aria-label="contact" href="/contact">
          <div class="header-menu-item-mask">联系我</div>
        </a>
      </li> 
      <li class="header-menu-item header-item is-blog">
        <a aria-label="blog" href="/blog">
          <div class="header-menu-item-mask">技术博客</div>
        </a>
      </li> 
      <li class="header-menu-item header-item is-about">
        <a aria-label="about" href="/about">
          <div class="header-menu-item-mask">关于我</div>
        </a>
      </li>
     </ul> 
    </div> 
    <div id="header-menu-btn"></div> 
   </header> 

   <div id="main-scroll-indicator"> 
    <div id="main-scroll-indicator-text">滚动查看更多</div> 
    <div id="main-scroll-indicator-arrow-container">
     <svg xmlns="http://www.w3.org/2000/svg" width="5" height="40" viewbox="0 0 5 40">
      <title>智能矢量图箭头</title>
      <path d="M0,40V0H1V35H5Z" />
     </svg>
    </div> 
   </div>

  </div>

  <a id="snd-btn" class="cache"></a> 
  <div id="preloader" class="cache" data-gesture="Click anywhere to begin">
   <canvas id="preloader-canvas"></canvas>
  </div> 
  <div id="not-support" class="cache">
   We are sorry to inform you that your browser is not compatible with our website.
   <br />
   <br />Please do consider upgrading your browser.
  </div> 
  <div id="cursor-follow" class="font-bold"></div>

  <script src="/assets/js/TweenLite.js"></script> 
  <script src="/assets/js/three.r112.js"></script> 
  <script src="/assets/js/index.js"></script>   
 </body>
</html>

线上部署&优化

PM2 - Node 进程管理

PM2 是 Node 进程管理工具,可以利用它来简化很多 Node 应用管理的繁琐任务,如性能监控、自动重启、负载均衡等,而且使用非常简单。

下面就对 PM2 进行入门性的介绍,基本涵盖了 PM2 的常用功能和配置:

  • 全局安装PM2:npm i pm2 -g
  • 监听应用:pm2 start index.js
  • 查看所有进程:pm2 list
  • 查看某个进程:pm2 describe name/id
  • 停止某个进程:pm2 stop name/id
  • 停止所有进程:pm2 stop all
  • 重启某个进程:pm2 restart name/id
  • 删除某个进程:pm2 delete name/id

配置文件信息如下:

module.exports = {
  apps : [{
    name: 'node_blog',
    script: 'app.js',
    instances: 1,
    autorestart: true,
    watch: false,
    max_memory_restart: '1G',
    env: {
      NODE_ENV: 'development'
    },
    env_production: {
      NODE_ENV: 'production'
    }
  }],
};

这里作者就不详细介绍 pm2,如需了解更多请移步到PM2实用入门指南 | 博客园 - 程序猿小卡

Nginx

Nginx基本是上线必备,这里就不多说了,开启Gzip效果确实很显著,css和js文件可以压缩到70%-80%,简直帅呆了!😆

开启Gzip配置Nginx找到目录文件:

cd /etc/nginx/nginx.conf
gzip on;
gzip_disable "msie6";
gzip_min_length 20;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/javascript text/xml application/xml+rss;
gzip_types font/ttf font/otf image/svg+xml;

写在最后

小编就分享到这,文章如有不妥之处,欢迎批评指正。如果觉得不错,就请点个👍和❤️收藏,您们的点赞是小编继续创作的动力。

最后,关于写作个人博客这件事,要么去做,要么不做,不要尝试。抱着试一试的心情,往往容易半途而废。拿出认真的态度,脚踏实地。哪怕一开始无从下手也罢,哪怕自己是初学者也罢,勇于分享自己的经验与学习历程,本身就是一件值得赞许的事。😃

推荐相关优质文章阅读

欢迎关注作者公众号:懒人码农