用Gatsby和Strapi创建一个静态博客

本文以简单通俗的方式讲解了结合Gatsby和Strapi创建一个静态博客的方法和具体步骤, 也额外插入了许多创建过程中遇到的各种问题和解决办法.

原文参阅: Building a static blog using Gatsby and Strapihttps://blog.strapi.io/buildi…. 本篇首发在SegmentFault上, 用Markdown语法, 所以美观性相比更强. 本篇主要是对原文精华内容进行翻译, 以及实操过程中遇到的问题解决和探索. 一些具体的操作步骤和细节, 我将忽略, 结合原文一起阅读效果更佳!

注: 本文操作环境是Linux VPS, CentOS 6 64bit

介绍

这是一个包含很多静态内容页面的站点, 从技术上来说就如同一系列HTML文件, 展示给访问者. 与动态网站不同的是, 他不需要后端开发或者数据库支撑. 发布静态站点之所以容易, 是因为文件只需要上传到服务器或者存储器. 没有额外的渲染页面的请求, 也没有数据库被黑的风险, 所以它既安全也快速.

为了快速建站, 其实很多开源的静态页面生成框架可用, 比如前阵子我搞的Jekyll, Hugo, 好似国人偏爱的Hexo等等, 他们的工作原理相似, 内容都是通过静态文件(比如Markdown)或者带有内容的API, 通过获取这些内容, 注入到开发者做好的模板, 最后生成一大堆HTML文件.

Progressive Web Apps (PWA)实际上是网页应用, 几乎基于Javascript, 并且可靠, 快速, 有吸引力的. 这几年比较火的Angular, Vue, React都是类似的前端框架.

静态站点遇见了PWA就产生了Gatsby

将这两点组合起来的最佳选择看起来就是Gatsby了, 但是同样需要一个内容接口, 这就是我将要展示的, 通过Strapi创建一个内容API提供给Gatsby, 然后打包发布出一个静态站点.


Gatsby是什么

这个并不是型男熟知的杰士派, 虽然我也用过这个发泥, 好像不是很好用. Gatsby是基于React的快速静态网站框架, 有了它, 你就可以感觉飘飘然的开发React网站了.

Strapi是什么

Strapi是一个基于高级的Nodejs API内容管理框架. 听起来有点绕口, 通俗来说就是让你能简单, 安全, 高效的开发出强大API的开源的内容管理框架. 它是免费的, 人们都爱免费的, 可以随意在你的服务器上使用, 也非常具有可个性化, 可扩展性的玩意.

我真想不到国内几乎没有人用Gatsby和Strapi, 百度上查不到任何资料…

创建API

见证奇迹的时刻即将到来, 我们快创建个Strapi API, 添加点内容吧!

创建Strapi项目

Requirements: please make sure Node 8 (or higher) and MongoDB are installed and running on your machine.

此时, 暗喜前阵子已经琢磨出来了并装好了Node 8, 不过装MongoDB就没有了. 因此这里就要插入一段关于MongoDB的内容了. 如果已经有了请自动跳过此内容.

MongoDB安装及相关问题

果断找到文档Install MongoDB Community Edition on Red Hat Enterprise or CentOS Linux, 这个redhat和centOS应该是通用的吧- -! 看到Configure the package management system (yum)., 发现原来还有这种操作, 创建repo文件, 来安装对应版本的软件. 闲话少说, 直接上代码:

# cd /etc/yum.repos.d/
# touch mongodb-org-3.6.repo
# vi mongodb-org-3.6.repo

将以下内容copy进去保存

[mongodb-org-3.6]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.6/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-3.6.asc

再进行安装

# sudo yum install -y mongodb-org

如果有特殊需求, 请参阅上文提到的官方文档, 我这里装的是MongoDB Community Edition

按以上步骤很快就装好了. 接下来启动mongod(如果没有启动的话), 如下命令:

# service mongod start

完成后, 我们接着创建Strapi项目的主题, 推荐安装strapi@alpha版本:

# npm i strapi@alpha -g

完成后, 去到你要创建本文项目的目录, 比如我这里的路径是/home/web/, 我在这里创建一个gatsby-strapi-tutorial目录:

# mkdir gatsby-strapi-tutorial

在这里面搭一个API脚手架

# cd gatsby-strapi-tutorial
# strapi new api

进入项目目录, 并运行Node.js服务器

# cd api
# strapi start

遇到了一些小问题

这里突然时不时卡住了, 如果你很顺利, 那么可以跳过此内容, 频繁报错如下

[root@whidy api]# strapi start
DEBUG (24910 on whidy): Server wasn't able to start properly.
ERROR (24910 on whidy): (hook:mongoose) takes too long to load

大概是网络原因, 我联通网络出问题, 换了电信几番尝试就好了.

操作过程中频繁出现刚才的问题, 我觉得不是网络问题那么简单, 我打算从数据库方面着手完善一下试试, 当然后来证明, 一切问题都与MongoDB无关, 所以下面缩进内容可以选择性阅读大多数情况下我是不愿意理睬WARNING信息的, 只要不是ERROR就好, 但是这次我有点不爽, 后来折腾了半天发现有的很难处理, 好吧我错了, 我想我还是不死磕了吧😱.

  • soft rlimits too low
    WARNING: soft rlimits too low. rlimits set to 1024 processes, 64000 files. Number of processes should be at least 32000 : 0.5 times number of files.

    参阅:

  • versions of RHEL older than RHEL6
    WARNING: You are running in OpenVZ which can cause issues on versions of RHEL older than RHEL6.

    服务器硬件限制? 可以安全忽略.

    参阅: WARNING: You are running in OpenVZ which can cause issues on versions of RHEL older than RHEL6.

  • Access Control
    以为要搞账户什么的, 然后运行mongo命令, 创建了一个admin账户:

    # mango
    > use admin
    > db.createUser(
        {
          user: "username",
          pwd: "userpassword",
          roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
        }
      )
    # mongo --port 27017 -u "username" -p "userpassword" --authenticationDatabase "admin"

    其实我自己当时也不知道是搞啥, 其实完全没关系的操作. 很多人甚至官方文档Start MongoDB without access control.也提到:

    mongod --port 27017 --dbpath /data/db1

    可是我一直报错, 要么说不存在, 搞半天才明白, 要手动创建, 创建好了, 又说服务被占用, service mongod stop停了服务, 连上去了, show dbs发现跟之前的又不一样, 没有找到我之前看到的strapi库, 才恍然大悟, 原来其实我创建了一个跟之前无关的库…

    事实上, 启动mongod服务的时候, 它连接了一个默认配置库, 这个库的路径时早就创建好的, 通过查看/etc/mongod.conf这个文件就知道了. 因此删了那个没用的db目录. 接着操作.

    后来第二天早上, 再次执行strapi start很顺利. 我也没办法再研究昨天究竟是为什么总是连不上了. 反正就是渣渣网络经常会带来各种坑!😡, 这段没什么作用的内容就过去了.

回到刚才strapi start, 成功之后, 我们如果是本地操作的, 带有界面的操作系统的话就可以直接访问http://localhost:1337/admin了, 如果也是远程操作, 就改成IP就好了.

接下来的操作是创建用户, 原文已经图文并茂, 傻子都能看懂的步骤了, 由于篇幅过大, 我就简单翻译一下, 不详细复述了嘿嘿~

按照原文操作:

  1. 创建管理员账号(Create your first User)
  2. 创建内容类型(Create a Content Type)
    名为article的内容类型有三个字段: title(字符串), content(文本), author(关系, 多文章对应一个用户).
  3. 添加几项内容到数据库
    1. 访问文章列表页
    2. 点击Add New Article
    3. 插入值, 连接对应的作者并保存
    4. 重复以上操作, 创建额外两篇文章
  4. 允许API权限, 依原文对应勾选保存

完成后, 就可以访问http://localhost:1337/article了.

创建静态站

到目前, 你的API搞定了, 我们要搞静态网站啦

安装Gatsby

首先, 全局安装Gatsby CLI:

# npm install --global gatsby-cli

生成Gatsby项目

回到之前提到的gatsby-strapi-tutorial目录, 创建一个新博客:

# gatsby new blog

事情总是不是那么顺利.

报错, 需要git. 然而我的这台崭新的服务器还没装, 那就装一个吧.

如果你的git已经部署OK, 并且上面这个操作没有问题, 以下内容可忽略:

参考Download for Linux and Unix执行:

# yum install git

再次执行后依旧报错(当前git版本1.7.1)

error Command failed: git clone git://github.com/gatsbyjs/gatsby-starter-default.git blog --single-branch

推测是版本问题. 只好手动安装了. 于是又找到这个安装 Git

# yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel
# wget https://www.kernel.org/pub/software/scm/git/git-2.16.1.tar.gz
# tar -zxf git-2.16.1.tar.gz
# cd git-2.16.1
# make prefix=/usr/local all
# sudo make prefix=/usr/local install

漫长的make prefix=/usr/local all之后, 提示:

    SUBDIR perl
/usr/bin/perl Makefile.PL PREFIX=\'/usr/local\' INSTALL_BASE=\'\' --localedir=\'/usr/local/share/locale\'
Can\'t locate ExtUtils/MakeMaker.pm in @INC (@INC contains: /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .) at Makefile.PL line 3.
BEGIN failed--compilation aborted at Makefile.PL line 3.
make[1]: *** [perl.mak] Error 2
make: *** [perl/perl.mak] Error 2

蛋疼, 等了半天, 又要解决这个问题, 好在看起来比较容易处理, 参考git fails to build in Fedora 14, 然后继续执行最后两条make命令, 虽然最后出来很多看起来很奇怪的内容, 不过似乎是成功了. 执行:

# git --version
git version 2.16.1

接下来我们再一次执行gatsby new blog, 我擦还提示刚才的...single-branch的error, 这就坑爹了- -. 经过简短的排查. 原来似乎他还是跑的旧版git, 需要删掉之前yum自动安装的git 1.7.1, 我单纯的以为直接自动升级了. 于是:

# yum remove git

按照提示删除成功后, 再次检测git还是ok的, 这次我第三次执行gatsby new blog, 终于成功了!

我这小白也不知道linux软件管理是咋整的. 反正能继续执行卡了我半天的gatsby就好了吧…每次创建速度很慢, 执行gatsby new blog完成的时候提示added 1398 packages in 137.652s, 大概就是2分钟多, 可能是安装依赖包费时吧

启动开发模式

创建成功后, 接着操作, 进入博客目录

# cd blog

启动服务器

# gatsby develop

理论上你就可以通过http://localhost:8000访问到默认的效果博客站点了.

然而又一次出现小插曲, 如果你是和我一样远程访问, 也许以下内容对你有用

每次执行gatsby develop的时间甚至更长, 完成时提示如下:

info bootstrap finished - 334.876 s

DONE  Compiled successfully in 90373ms 21:15:06


You can now view gatsby-starter-default in the browser.

http://localhost:8000/

View GraphiQL, an in-browser IDE, to explore your site's data and schema

http://localhost:8000/___graphql

Note that the development build is not optimized.
To create a production build, use gatsby build

大概用了6分钟左右, 糟糕的是并不能通过远程IP来访问! 查看了目录下的配置文件和官方文档, 也没查到. 绝望之时, 突然在大量资料中看到webpack也有这样的问题, 想起来之前webpack的server默认配置也是无法通过ip访问, 但是webpack的devServer配置host: "0.0.0.0"即可, 试了下:

# gatsby develop --host 0.0.0.0

又经过4分钟左右漫长等待, 这次成功了! 不过我尝试搜索Gatsby究竟用的什么服务器启动, 为何不能像webpack那样加一段配置呢, 却没有找到. 后来凑巧找到了一篇webpack下的issue, Server can’t be accessed via IP, 有人提到过这条命令.

因此, 从小插曲中来看, 远程访问控制的开发者, 需要加个参数, 具体命令:

# gatsby develop --host 0.0.0.0

这样, 至此开发模式服务器搞定.

安装Strapi插件(Install the Strapi source plugin)

Gatsby understands this pretty well. So its creators decided to build a specific and independent layer: the data layer. This entire system is strongly powered by GraphQL.

前面有一些插件介绍不多说了, 执行安装:

# npm install --save gatsby-source-strapi

完成后, 需要做些配置, 修改gatsby-config.js文件, 替换成以下内容:

module.exports = {
  siteMetadata: {
    title: `Gatsby Default Starter`,
  },
  plugins: [
    `gatsby-plugin-react-helmet`,
    {
      resolve: `gatsby-source-strapi`,
      options: {
        apiURL: `http://localhost:1337`,
        contentTypes: [ // List of the Content Types you want to be able to request from Gatsby.
          `article`,
          `user`
        ]
      },
    },
  ],
}

保存后, 重启Gatsby服务器

文章列表

为了在首页显示文章列表, 我们需要修改首页代码如下:

路径: src/pages/index.js

import React from 'react'
import Link from 'gatsby-link'
const IndexPage = ({ data }) => (
  <div>
    <h1>Hi people</h1>
    <p>Welcome to your new Gatsby site.</p>
    <p>Now go build something great.</p>
    <ul>
      {data.allStrapiArticle.edges.map(document => (
        <li key={document.node.id}>
          <h2>
            <Link to={`/${document.node.id}`}>{document.node.title}</Link>
          </h2>
          <p>{document.node.content}</p>
        </li>
      ))}
    </ul>
    <Link to="/page-2/">Go to page 2</Link>
  </div>
)
export default IndexPage
export const pageQuery = graphql`
  query IndexQuery {
    allStrapiArticle {
      edges {
        node {
          id
          title
          content
        }
      }
    }
  }
`

这里就应用到了GraphQL啦, 好激动呢. 我们导出pageQuery, 一个GraphQL查询会请求文章列表, 我们只需要将需要查询的字段添加进去就好了~

然后我们传递{ data }这个结构对象作为IndexPage参数, 遍历它的allStrapiArticles对象, 来展示数据.

GraphQL查询可以快速生成, 你可以尝试在http://localhost:8000/___graphql修改, 并测试.

文章页

首页有了列表之后, 我们还要访问文章页面呢, 接下来写一个模板:

路径: src/templates/article.js

import React from 'react'
import Link from 'gatsby-link'
const ArticleTemplate = ({ data }) => (
  <div>
    <h1>{data.strapiArticle.title}</h1>
    <p>by <Link to={`/authors/${data.strapiArticle.author.id}`}>{data.strapiArticle.author.username}</Link></p>
    <p>{data.strapiArticle.content}</p>
  </div>
)
export default ArticleTemplate
export const query = graphql`
  query ArticleTemplate($id: String!) {
    strapiArticle(id: {eq: $id}) {
      title
      content
      author {
        id
        username
      }
    }
  }
`

你需要手动创建这个目录和文件, 当然Gatsby并不知道模板何时展示. 每篇文章都需要一个特别的URL, 感谢Gatsby提供的createPage函数.

首先, 我们写个makeRequest函数来处理GraphQL请求. 然后通过createPage函数使我们在获取的文章列表后为它们创建一个页面, 路径为文章id的URL, 回到blog目录, 修改gatsby-node.js文件

const path = require(`path`);
const makeRequest = (graphql, request) => new Promise((resolve, reject) => {
  // Query for nodes to use in creating pages.
  resolve(
    graphql(request).then(result => {
      if (result.errors) {
        reject(result.errors)
      }
      return result;
    })
  )
});
// Implement the Gatsby API “createPages”. This is called once the
// data layer is bootstrapped to let plugins create pages from data.
exports.createPages = ({ boundActionCreators, graphql }) => {
  const { createPage } = boundActionCreators;
  const getArticles = makeRequest(graphql, `
    {
      allStrapiArticle {
        edges {
          node {
            id
          }
        }
      }
    }
    `).then(result => {
    // Create pages for each article.
    result.data.allStrapiArticle.edges.forEach(({ node }) => {
      createPage({
        path: `/${node.id}`,
        component: path.resolve(`src/templates/article.js`),
        context: {
          id: node.id,
        },
      })
    })
  });
  // Query for articles nodes to use in creating pages.
  return getArticles;
};

再次重启Gatsby服务器.

现在你就能通过点击首页的文章进入到文章内容页面了.

作者页

虽然这个似乎并不重要, 不过还是加上学习一下吧😁

添加作者页和创建文章页很相似, 我们还是先创建个模板:

路径: src/templates/user.js

import React from 'react'
import Link from 'gatsby-link'
const UserTemplate = ({ data }) => (
  <div>
    <h1>{data.strapiUser.username}</h1>
    <ul>
      {data.strapiUser.articles.map(article => (
        <li key={article.id}>
          <h2>
            <Link to={`/${article.id}`}>{article.title}</Link>
          </h2>
          <p>{article.content}</p>
        </li>
      ))}
    </ul>
  </div>
)
export default UserTemplate
export const query = graphql`
  query UserTemplate($id: String!) {
    strapiUser(id: { eq: $id }) {
      id
      username
      articles {
        id
        title
        content
      }
    }
  }
`

然后再次修改gatsby-node.js来创建作者URLs:

const path = require(`path`);
const makeRequest = (graphql, request) => new Promise((resolve, reject) => {
  // Query for article nodes to use in creating pages.
  resolve(
    graphql(request).then(result => {
      if (result.errors) {
        reject(result.errors)
      }
      return result;
    })
  )
});

// Implement the Gatsby API “createPages”. This is called once the
// data layer is bootstrapped to let plugins create pages from data.
exports.createPages = ({ boundActionCreators, graphql }) => {
  const { createPage } = boundActionCreators;
  const getArticles = makeRequest(graphql, `
    {
      allStrapiArticle {
        edges {
          node {
            id
          }
        }
      }
    }
    `).then(result => {
    // Create pages for each article.
    result.data.allStrapiArticle.edges.forEach(({ node }) => {
      createPage({
        path: `/${node.id}`,
        component: path.resolve(`src/templates/article.js`),
        context: {
          id: node.id,
        },
      })
    })
  });
  const getAuthors = makeRequest(graphql, `
    {
      allStrapiUser {
        edges {
          node {
            id
          }
        }
      }
    }
    `).then(result => {
    // Create pages for each user.
    result.data.allStrapiUser.edges.forEach(({ node }) => {
      createPage({
        path: `/authors/${node.id}`,
        component: path.resolve(`src/templates/user.js`),
        context: {
          id: node.id,
        },
      })
    })
  });
  // Queries for articles and authors nodes to use in creating pages.
  return Promise.all([
    getArticles,
    getAuthors,
  ])
};

重启服务器, 刷新页面, Wow! 大功告成! 时不时很酷!!!

原文总结

恭喜, 你成功的创建了一个超快的很好维护的博客! 然后各种夸奖Blabla

接下来做什么呢? 你可以去更多的挖掘Gatsby和Strapi的各种优点, 你可以试着增加这些功能:

  • 作者列表
  • 文章分类
  • 用Strapi API创建评论系统, 或者直接用Disqus
  • 当然你也可以试着搞其他站点, 例如电商站, 企业站等等

当然为了进一步方便开发, 你可能需要一个方便的发布在网上的存储载体, Blablabla…

本教程GitHub源码地址, 你可以clone下来, 运行npm run setup, blablabla… 我是个爱研究的人, 我要一步步操作, 才不要clone.

个人总结

这次通过Gatsby和Strapi搭建一个简单的博客站点, 还是挺不容易的, 总共花了将近两天的时间. 不过个人感觉还是值得的! 其中有很多地方是可以更加深入的学习和了解的, 这也算初步接触了react, mongodb, graphQL等相关知识实操, 同时也可以在后期完善更多的功能, 了解并学习一些ES6, 模板的写法技巧等等. 也希望通过此次研究以后能更进一步熟悉其他框架, 数据库, 后端等思想~

相关参阅汇总

最后打个小广告, 我有个GitHub项目, 用于记录我每天学习或者瞎折腾的技术, 范围不限, 有兴趣可以star我的whidy daily

Visual Studio Code几款FTP插件使用总结

投入Visual Studio Code后,很久没有使用过sublime text了,也很久没有用过基于编辑器的ftp工具了,这次专门探索了一下Visual Studio Code几款FTP插件,并作了简单的总结,ftp-sync是最棒的!

平时要维护类似wordpress这样的网站,然后虚拟主机又不支持远程仓的版本管理。总而言之,只能通过下载到本地修改后再通过FTP上传的情况,每次修改后都要开启FTP进行代码提交,相当繁琐。因此就诞生了一些编辑器的FTP插件,其实以前用sublime text的时候还有款插件叫SFTP不错(如果配置好了连接不上可以参考SFTP连接超时),可惜VSCODE上面没有,截至目前(2018年1月17日)可以用的FTP插件如下图:

vscode的ftp插件
vscode的ftp插件

为了找出最合适的插件,我全部都一个个试过了(关于如何使用参考插件说明,十分简单就不多说了)。然后有以下感想:

  1. ftp-sync是测试中的唯一一个感觉还可以的,但是菜单为啥不全,感觉是一个BUG吧.希望后期能够优化.

    ftp-sync菜单
    ftp-sync菜单
  2. SFTP/FTP sync总是回莫名其妙的卡住(左下角提示transfer就不动了),而且相同文件好像也会再次覆盖,不会跳过.文件比较多的时候出问题,不建议使用.
  3. ftp-kr跟Simple FTP/SFTP一样没啥暖用,还不如就用ftp软件操作
  4. Simple FTP/SFTP没啥暖用,还不如就用ftp软件操作

感觉很惨,没有一个真正好用的,而且连ftp传输状态信息也没有.有时候比较惨的误操作了需要中断传输,貌似只能强制关闭编辑器…

最后感觉,还是用sublime text 的SFTP来维护会比较好一点.如果不怎么用sublime text的话,个人建议使用ftp-sync在VSCode上表现还是不错的,有潜力,期待作者进一步优化~

Linux下无法正常安装(升级)和删除Nodejs的解决方法

Linux(CentOS6)下安装Nodejs,删除Nodejs,升级Nodejs遇到的一些问题,以及相关解决方案的介绍

接着上次说,自从买了VPS后就没闲着,总想要充分利用起来倒腾点东西。于是决定安装nodejs搭建web服务器等,如今nodejs稳定版本已经更新到8.x了,因此我就试着装一下8.x吧,没想到又遇到了坑,一搞搞了好几天。

我的操作系统是CentOS 6 64 Bit的,我查阅了Nodejs官方升级文档(包含各种可支持的系统),针对我的系统需要分别执行以下几条命令:

curl --silent --location https://rpm.nodesource.com/setup_8.x | sudo bash -
sudo yum -y install nodejs

当然你也许需要通过以下命令额外安装构建工具:

sudo yum install gcc-c++ make
# or: sudo yum groupinstall 'Development Tools'

如果其他系统则可以参考文档中其他内容。

在这里我就遇到坑了(可能存在该情况较少,所以稍后具体解决放在文章最后来说)。上面第一条应该是静默指定使用8.x的资源,便于安装时采用这个而不是yum自己原来的远程仓,不知道这个解释对不对。

我反复试过了,命令明明提示请执行 sudo yum -y install nodejs 来安装nodejs8.x,却一直安装的是6.x,难道是依赖问题?找不出原因的我,没有办法只能找其他安装途径,于是发现了第二种安装办法,手动获取最新的安装包,并进行解压缩安装,可能依赖Python2.7以上版本,我一步步来说。

如果是仅手动安装Nodejs8.x,执行以下命令:

yum install gcc-c++ openssl-devel
cd /usr/local/src
wget http://nodejs.org/dist/v8.9.4/node-v8.9.4.tar.gz
tar zxvf node-v8.9.4.tar.gz
(cd into extracted folder: ex "cd node-v8.9.4.tar.gz")
./configure
make
make install

顺利的话应该不会有什么问题,大概会过一段时间,稍微有点长,就提示安装好了,可以执行

node -v

来查看是否是8.x,如果好了,基本上关于安装部分就大功告成了。如果没好,太惨了,跟Python有关系的话,请查看Linux下Python安装升级心得

接着我们来看看删除,因为你已经安装了一个低版本,需要升级,那就是要先删除旧版本了,nodejs应该是向下兼容的,所以我就没有去研究可能闲着蛋疼才会去研究如果保存多个版本nodejs,当然在新版中可能会存在部分旧的功能废除而造成异常,虽然一般来说升级利大于弊,不过还是要考虑老项目环境是否要升级!如果你是闲着蛋疼的人,必有理由说服我,请在下方留言。差点跑题,删除命令简直是太简单了。

sudo yum remove nodejs

然后按提示输入y,回车后很快就删了。一切删除操作都是令人兴奋的。。。

其实,我在安装过程中远没有那么轻松,否则也不会折腾几天了,一个是版本错误,一个是Python升级。版本问题,后来差了很多资料才发现,原来是yum缓存问题导致。如果遇到和我类似的问题,请尝试以下命令:

rm -f /etc/yum.repos.d/nodesource-el.repo
yum clean all
yum -y remove nodejs
yum -y install nodejs

汇总下本文参阅的相关文章:

  1. Nodejs官方文档,通过包管理安装Nodejs
  2. Centos下手动安装Nodejs的方法
  3. 无法在Yum仓下安装正确的Nodejs版本(和刚才示例的代码类似,都是清除缓存,不过对我无效)
  4. CentOS下使用nodejs7.x的包进行安装却安装成了6.9.5(针对我的有效方案)
  5. 如何通过Linux命令删除Nodejs

所以我呢,其实就是应该遇到版本不对的情况就尝试清除缓存,再用官方命令进行安装就好了~

我想既然是Yum仓库缓存的问题,除了Nodejs,别的包也许也会有类似情况吧,如果也发现了选择了需要的版本后依然装的是旧版的,又和依赖没什么关系,就试试清除缓存吧 🙂

Chrome启动关联程序的协议链接误操作被禁用后如何修改设置重新开启

由于误操作,造成Chrome启动关联程序的协议链接被禁用,那么怎么重新修改设置,启动相关的程序呢,这里将为大家解答!

该文章适用于Windows 7 x64下Chrome版本 62.0.3202.94(正式版本) (64 位)的设置,其他设备不明。也许WIN10也可以,但是可能会由于Chrome版本区别而不可用。

今天回到宿舍,要用百度云盘下载点东西,结果,手误,勾选记住后,点了不要打开,为什么要高亮不要打开,泪奔。。。界面是这样的:

百度云的链接协议设置protocol settings

继续阅读“Chrome启动关联程序的协议链接误操作被禁用后如何修改设置重新开启”

表单中readonly的input等标签,禁止光标进入(focus)的几种方式

在做移动端页面,表单内的部分元素如果设置了readonly=”readonly”,CHROME模拟移动端是看不出问题的。而手机上虽然表单元素不能编辑内容,但是会出现闪动的光标以及页面底部有一条系统自带的控制bar。这样的体验很差,于是我总结了几个方案。

在做移动端页面,需要在订单页面中显示表单数据,由于UI统一,所以就依旧采用form的结构来写结构,只读数据的标签自然要加readonly=”readonly”,以为这样就行了,CHROME模拟移动端是看不出问题的。手机上一看,虽然表单元素不能编辑内容,但是会出现闪动的光标以及页面底部有一条系统自带的控制bar。

表单readonly元素依然有光标
表单readonly元素依然有光标,底部还有BAR,感觉不好

这种情况对我来说并不好。于是网上找了一些解决方案,现在总结一下:

方案一(JS):

<input type="text" value="test" onfocus="this.blur()" readonly="readonly">

这个很好理解就是进入的时候自动跳出。但是缺点是一方面js处理没有css好,二是如果需要在该元素上绑定其他事件,其他人开发不留意可能会造成事件覆盖。

方案二(CSS):

[readonly="readonly"] {
  user-select: none;
}

这是个新的实验性属性,具体说明及兼容性可参考user-select MDN
用起来感觉很好,但是同样有两个问题:一,非标准属性(请尽量不要在生产环境中使用它!);二,如果用户想要复制该表单内容就不行了,这个问题个人感觉很严重!

方案三(CSS):

[readonly="readonly"] {
  pointer-events: none;
}

这个是我感觉比较适合我的,因此最后我采纳了该方案,当然也是有弊端的,绑定在只读表单元素的所有事件将无法生效。除此之外都表现完美,就我目前需求来看,也不需要什么事件。因此采用了~

当然,如果你也遇到相似的问题,可以根据情况选择对应的方案,当然,如果你也有更好的方法也欢迎留言~