究竟什么是前端脚手架?

栏目: Node.js · 发布时间: 5年前

内容简介::pensive: 咱也不知道咱也不敢问啊先查查百度百科里对“脚手架”的定义吧:脚手架是为了保证各施工过程顺利进行而搭设的工作平台。

:pensive: 咱也不知道咱也不敢问啊

先查查百度百科里对“脚手架”的定义吧:

脚手架是为了保证各施工过程顺利进行而搭设的工作平台。

然后搜一下“脚手架”,基本上都是以下几类:

  • Vue/React 脚手架
  • 使用 Node、yeoman 打造自己的脚手架
  • 从零搭建 webpack 脚手架

此时还是无法确定什么是“脚手架”,也许我心目中的脚手架应该是 vue/cli 或者 create-react-app 吧,然后我打开他们的文档,但是他们的介绍上并没有说这是一款脚手架...

谈一下我自己的“脚手架”

:pensive: 我最怕别人看到我的“脚手架”后说这有什么卵用...

看了一下我第一次在 Github 上的提交记录 Commits on Feb 13, 2017,我入行三年多,那时应该是我第一次进入前端工程化的时候吧。在此之前我在公司接手的都是一些很简单的项目,直接新建文件夹,随手下载一个jQuery,然后新建 index.html main.js style.css,有没有同样经历的小伙伴们?

后来做的项目多了,觉得每次这么新建项目太麻烦,我新建了一个文件夹,专门存放初始的模板,然后复制粘贴,继续撸。

再后来,接触到 vue,他可以实现在终端内输入一行指令就能生成模板,这可比我复制粘贴看起来高端多了,为了装逼我开始了研究如何开发自己的“脚手架”。

当时还真是没有几篇文章把这种操作说的很明白,甚至我并不知道我要做的东西叫什么(脚手架)。

我理解的“脚手架”

百科里说的很对我的思路,首要的就是保证我的项目可以顺利进行。

  • 能够快速帮我生成新项目的目录模板(Node.js)。
  • 能够提升我的开发效率和开发的舒适性(webpack)。

分享点干货

从零搭建这种我就不说了,毕竟一搜一堆,基本上就是推荐几个库,例如 commander、inquirer、ora 等等。分享一些在我的脚手架开发时遇到的一些问题和需求,分享想给大家。

版本验证

首先推荐 工具 库:

semver ,版本对比。

request ,发送请求,当然你也可以用 axios。

const semver = require('semver');
const request = require('request');
  • Node.js 版本验证

如果你的脚手架想分享给别人用,这步最好不要避免,因为如果你用了一些现代化的 ES 语法,比如说 async await,老版本跑不起来的。

function checkNodeVersion (wanted) {
  // process.version 可以获取当前的 node 版本
  if (!semver.satisfies(process.version, wanted)) {
    console.log('Node版本不支持巴拉巴拉');
    // 退出进程
    process.exit(1);
  }
}
  • 脚手架版本验证

正如上面所说,你如果分享给别人用,在你修改了一些 bug 后,希望其他人用最新的版本,那就应该提示他。

function checkPackageVersion(url) {
  return new Promise((resolve, reject) => {
    request(url, function (error, response, body) {
      if (!error && response.statusCode === 200){
        let version = JSON.parse(body).version;
        if (semver.lte(version, requiredVersion)) {
          resolve();
        } else {
          console.log('需要更新你的包巴拉巴拉');
          process.exit(1);
        }
      } else {
        console.log('发送请求失败巴拉巴拉');
        resolve();
      }
    });
  });
}

参数 url 当然传入 npm 的链接 https://registry.npmjs.org/ [你的包名]/latest

当前路径下是否存在相同的文件夹

如果不做这层判断,你新生成的项目很可能会覆盖你已有的项目,别问我为啥想到这么做 :sob:

function hasFolder(name) {
  return new Promise (resolve => {
    fs.exists(name, exists => {
      if (exists) {
        console.log('已经存在相同目录巴拉巴拉');
        process.exit(1);
      } else {
        resolve();
      }
    });
  });
};

这里加了一层 Promise 是因为 Node 去检测是否存在文件夹是个异步操作,也需要耗时,这么做比较保险。

清空控制台

当你输入完命令后,好像进入了新的页面一样,看起来很舒服。

function clearConsole(color, str) {
  if (process.stdout.isTTY && store.cmd !== 'test') {
    const blank = '\n'.repeat(process.stdout.rows);
    console.log(blank);
    readline.cursorTo(process.stdout, 0, 0);
    readline.clearScreenDown(process.stdout);
  }
}

拷贝模板

很多关于如果构建脚手架里提到一个工具 download-git-repo,在 github 或其他仓库中下载模板。我并不是很喜欢这种操作,1、耗时,让脚手架构建速度更慢了,在没有网络的情况下无法构建。2、在 git 仓库中还需要新建项目模板,感觉把一个项目分离成了两个,不方便管理。

所以我打算直接从全局目录下将模板文件夹拷贝到当前路径下:

使用一个工具 fs-extra ,node.js 新手最好不要试图用原生接口拷贝一个文件夹。

const src = path.resolve(__dirname, '../template');

const dest = path.resolve(process.cwd(), store.dirname);

两个概念:

全局环境路径:

const src = path.resolve(__dirname, '你的模板文件夹相对路径')

当前环境路径:

const dest = path.resolve(process.cwd(), '你创建项目的名称');
fs.copy(src, dest).then(() => /* 巴拉巴拉 */);

自动选择包管理器

现在用 yarn 的人越来越多,而且确实效率很高,如果安装过 yarn 就让它作为默认包管理器去自动安装依赖吧。

function packageManagement() {
  try {
    child_process.execSync('yarnpkg --version', { stdio: 'ignore' });
    return 'yarn';
  } catch (e) {
    return 'npm';
  }
}

自动安装依赖

这里用到 Node.js 中的 child_process.spawn 方法

这里举个例子,想要执行 npm install webpack -D

const ls = spawn('npm', ['isntall', 'webpack', '-D'], {shell: true});
ls.on('close', (code) => /* 巴拉巴拉 */)
  • 第一个参数:要运行的命令。
  • 第二个参数:数组,字符串参数的列表。
  • 第三个参数:配置,这里把 shell 设置为 true。
  • 使用 on 方法监听执行结果。

这里推荐安装的包带有版本号,如果直接安装会安装最新版,可能会导致不兼容。

提一个 webpack 的插件

ProgressPlugin ,用于监听编译进度。

plugins: [
  new webpack.ProgressPlugin(function(percentage) {
    // percentage 进度 0-1
  })
]

这里配合前面说到的清空控制台,可以实现更好的体验。

使用 IP 访问项目

这里指的是通过 webpack 启动的 devServer。

host 配置为 0.0.0.0

通过下面的函数获取到本机的 IP 地址,这样就可以在同网下使用移动设备做测试了。

function getIPAdress() {
  let interfaces = require('os').networkInterfaces();
  // eslint-disable-next-line guard-for-in
  for (let devName in interfaces) {
    let iface = interfaces[devName];
    for (let i = 0; i < iface.length; i++) {
      let alias = iface[i];
      if (alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal) {
        return alias.address;
      }
    }
  }
}

再逼逼几句

这是我理解中的“脚手架”,希望其他小伙伴也评论一下自己理解的脚手架。

:cry: 已经近一年没有做过技术分享了,每天在掘金里潜水,偶尔发点沸点,不敢在首页发内容,总觉得自己技术不足,怕大佬喷,自尊心受到创伤。

最后分享一下我的“脚手架”,这个项目在我面试中也起到了不错的效果:

文档: https://codexu.github.io/


以上所述就是小编给大家介绍的《究竟什么是前端脚手架?》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Rationality for Mortals

Rationality for Mortals

Gerd Gigerenzer / Oxford University Press, USA / 2008-05-02 / USD 65.00

Gerd Gigerenzer's influential work examines the rationality of individuals not from the perspective of logic or probability, but from the point of view of adaptation to the real world of human behavio......一起来看看 《Rationality for Mortals》 这本书的介绍吧!

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具