首页   注册   登录
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
宝塔
V2EX  ›  前端开发

究竟什么是前端脚手架?

  •  
  •   461229187 · 155 天前 · 1261 次点击
    这是一个创建于 155 天前的主题,其中的信息可能已经有所发展或是发生改变。

    😔 咱也不知道咱也不敢问啊

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

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

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

    • Vue/React 脚手架

    • 使用 Node、yeoman 打造自己的脚手架

    • 从零搭建 webpack 脚手架

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

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

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

    看了一下我第一次在 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

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

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

    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;
          }
        }
      }
    }
    

    再逼逼几句

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

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

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

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

    7 回复  |  直到 2019-06-20 15:42:04 +08:00
        1
    Tink   155 天前 via iPhone
    同问
        2
    wu67   155 天前
    其实就我用过的 vue 来说, 只要会看文档改配置就行了, 从 0 开始过于蛋疼, 也看不进去...
        3
    billlee   155 天前   ♥ 1
    不是前端,但我觉得各种手脚架就是各种框架、开发工具不够完善的产物。框架和开发工具步完善导致每个项目都要写很多重复的代码或配置,这些就被做成了手脚架。
        4
    xrr2016   155 天前 via Android
    666 赞一个
        5
    aleung   155 天前 via Android
    基于 mrm 开发自己的 preset,比较好的做脚手架的基础工具。https://github.com/sapegin/mrm
        6
    lxml   155 天前
    @billlee #3 是这样的,js 太烂,比如光 lint 就一堆标准,太多标准的根本原因就是因为毫无标准
        7
    kalasoo   149 天前
    掘友爱你
    来自掘金的爱
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   1353 人在线   最高记录 5043   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.3 · 21ms · UTC 00:19 · PVG 08:19 · LAX 16:19 · JFK 19:19
    ♥ Do have faith in what you're doing.