为了提高开发效率、减少重复的操作,现在几乎全部的前端项目都需要依赖一些构建工具来实现自动化打包,主流的有webpack, gulp, grunt等。加上各种各样的配置文件就会形成了一个相对复杂的构建环境。一般的,我们可以把构建项目需要用到的参数写死在配置文件,但是,有些是需要动态配置的那怎么办呢?比方说,我们用express来启动本地服务器,这需要分配一个端口吧?写死一个端口如8080在配置文件是可以的,可是,如果端口被占用了那怎么办?难道要把占用端口的进程kill掉、或者修改配置文件,再重新run一次吗?如果把全部的参数都写死在配置文件里面,一旦启动了构建脚本,就如同脱僵之马,是不可控制的,会一直跑下去。那可以换个思路,能不能做一个交互式的脚本呢,就是启动了构建脚本之后,还允许我们插手去修改一些配置,比方说如果端口被占用了,可以在终端输入一个新的端口,然后继续运行项目,是不是会更加友好一些?

前端构建环境一般都是基于Node脚本的。对于交互式操作,社区上有了个叫做 inquirer的第三方库,至于这个库具体怎么用,这里就不说了,如果没有使用过的可以到官网看一下它的文档。

另外,我们还需要提前检查端口是否被占用了,可以使用第三方库portscanner。就直接上一个demo哈:

  1. const inquirer = require('inquirer');
  2. const portscanner = require('portscanner');
  3. const questions = [];
  4. questions.push({
  5. type: 'input',
  6. name: 'port',
  7. default: 3000, // 默认端口是3000
  8. message: `请输入调试端口号`,
  9. validate(input) {
  10. const port = Number(input);
  11. return new Promise((resolve, reject) => {
  12. if (isNaN(port)) {
  13. reject('端口号必须为数字');
  14. } else {
  15. // 检查端口是否被占用了,如果被占用则重新输入
  16. portscanner.checkPortStatus(
  17. port,
  18. '127.0.0.1',
  19. (error, status) => {
  20. if (error) {
  21. reject(error);
  22. } else if (status === 'open') {
  23. reject(`${port} 端口号已经被占用`);
  24. } else {
  25. resolve(true);
  26. }
  27. }
  28. );
  29. }
  30. });
  31. }
  32. });
  33. inquirer
  34. .prompt(questions)
  35. .then(answer => {
  36. console.log(answer);
  37. }).catch(console.log);

就这么简单的一个demo,下面就来测试一下它的效果。

输入3002,正常执行:

输入一个非数字的端口,就会提示如下错误,并要求重新输入:

如果端口被其他进程占用了,会提示如下错误 ,并要求重新输入:

关于输入端口的问题就写到这里了。

接下来,看一下稍微复杂一点的栗子,在启动项目之前,可以通过向上或向下箭头来选择项目,如图所示:

下面就step by step的说明一下如何实现这样的需求哈。

这一次,我们就来模拟真实一点的环境,假设有个projects的目录,它里面有很多的项目,分别叫做project1, project2, project3......。如下:

  1. f2e-workflow
  2. |--build
  3. |--index.js
  4. |--src
  5. |--projects
  6. |--project1
  7. |--project2
  8. |--project3
  9. |--project4
  10. |--package.json

如何遍历文件目录呢?有个很好用的库,叫做blob。也不介绍如何使用了,还是直接上个例子吧。

  1. const inquirer = require('inquirer');
  2. const glob = require('glob');
  3. const path = require('path');
  4. // 项目的根目录
  5. const projectRoot = path.resolve(__dirname, '../');
  6. // 获取指定路径下的入口文件
  7. const projects = {};
  8. glob.sync(path.join(projectRoot, 'src/projects/*')).forEach((item) => {
  9. const projectName = item.split('/').pop();
  10. projects[projectName] = item;
  11. });
  12. const questions = [];
  13. questions.push({
  14. type: 'list', // 选择List类型,就可以通过上下移动键了
  15. name: 'project',
  16. message: '请选择需要运行的项目',
  17. choices: Object.keys(projects)
  18. });
  19. inquirer
  20. .prompt(questions)
  21. .then(answer => {
  22. // 选择了项目之后,就可以运行它了
  23. console.log(answer);
  24. }).catch(console.log);

现在我们的需要已经实现了,但是,还有个问题,就是如果项目太多,上下移动效率也不高,如果可以直接输入项目名称进行筛选那就完美了。这也很简单,社区有个叫做fuzzy的第三方库,可以支持模糊模糊查询。然后,配合inquirer-autocomplete-prompt 这个库使用就好了。下面就是支持模糊查询优化过的代码:

  1. const inquirer = require('inquirer');
  2. const glob = require('glob');
  3. const path = require('path');
  4. const fuzzy = require('fuzzy');
  5. // 项目的根目录在
  6. const projectRoot = path.resolve(__dirname, '../');
  7. // 注册一个inquirer的新类型
  8. inquirer.registerPrompt('autocomplete', require('inquirer-autocomplete-prompt'))
  9. // 获取指定路径下的入口文件
  10. const projects = {};
  11. glob.sync(path.join(projectRoot, 'src/projects/*')).forEach((item) => {
  12. const projectName = item.split('/').pop();
  13. projects[projectName] = item;
  14. });
  15. const questions = [];
  16. questions.push({
  17. type: 'autocomplete',
  18. name: 'project',
  19. message: '请选择需要运行的项目',
  20. source(answers, input) {
  21. input = input || '';
  22. const projectNames = Object.keys(projects);
  23. return new Promise(function(resolve) {
  24. setTimeout(function() {
  25. var fuzzyResult = fuzzy.filter(input, projectNames);
  26. resolve(fuzzyResult.map(function(el) {
  27. return el.original;
  28. }));
  29. }, 100);
  30. });
  31. }
  32. });
  33. inquirer
  34. .prompt(questions)
  35. .then(answer => {
  36. // 选择了项目之后,就可以运行它了
  37. console.log(answer);
  38. }).catch(console.log);const inquirer = require('inquirer');

启动脚本后,可以输入关键字进行过滤,比如,输入2,就会默认匹配到project2:

OK,关于如何搭建一个交互式的前端构建环境就写这么多啦。如果有什么问题和建议欢迎发评论交流~

最后,demo的代码放到了github上面啦,可以点击这里,欢迎star~

搭建一个交互式的前端构建环境.md的更多相关文章

  1. 【前端福利】用grunt搭建自动化的web前端开发环境-完整教程

    jQuery在使用grunt,bootstrap在使用grunt,百度UEditor在使用grunt,你没有理由不学.不用! 1. 前言 各位web前端开发人员,如果你现在还不知道grunt或者听说过 ...

  2. 转:【前端福利】用grunt搭建自动化的web前端开发环境-完整教程

    原文地址:http://blog.csdn.net/wangfupeng1988/article/details/46418203 jQuery在使用grunt,bootstrap在使用grunt,百 ...

  3. 用grunt搭建自动化的web前端开发环境实战教程(详细步骤)

    用grunt搭建自动化的web前端开发环境实战教程(详细步骤) jQuery在使用grunt,bootstrap在使用grunt,百度UEditor在使用grunt,你没有理由不学.不用!前端自动化, ...

  4. 用grunt搭建自动化的web前端开发环境-完整教程

    原稿:http://www.cnblogs.com/wangfupeng1988/p/4561993.html#!comments jQuery在使用grunt,bootstrap在使用grunt,百 ...

  5. 用grunt搭建自动化的web前端开发环境

    用grunt搭建自动化的web前端开发环境 jQuery在使用grunt,bootstrap在使用grunt,百度UEditor在使用grunt,你没有理由不学.不用! 1. 前言 各位web前端开发 ...

  6. grunt搭建自动化的web前端开发环境(转)

    1. 前言 各位web前端开发人员,如果你现在还不知道grunt或者听说过.但是不会熟练使用grunt,那你就真的真的真的out了(三个“真的”重复,表示重点).至于grunt的作用,这里不详细说了, ...

  7. 使用grunt搭建自动化的web前端开发环境

    使用grunt搭建自动化的web前端开发环境 我们一定经常听过grunt和gulp,它们都是用于搭建自动化的web前端开发环境的,这里主要介绍grunt的使用,值得一提的是,jQuery.bootst ...

  8. 搭建一个完整的Java开发环境

    搭建一个完整的Java开发环境 作为一个Java程序员,配置一个java开发环境是必备的技能,今天给广大菜鸟初学者补上一课.环境的配置,大概就分三个1,JDK 2,Tomcat(或者其他的)3,ecl ...

  9. 搭建一个高可用的redis环境

    一.环境准备 我的环境: Fedora 25 server  64位版 6台: 192.168.10.204 192.168.10.205 192.168.10.206 192.168.10.203 ...

随机推荐

  1. IT技术有感

    今天看技术文章,spring相关的,某一个点以前每次看一直不理解, 可是不知道为什么隔了1年左右,中间什么都没做,现在却都懂了. 在看懂的那一刻,笼罩在我心上的躁动突然平静了许多,我的心这一年来前所未 ...

  2. 深入理解Javascript单线程谈Event Loop

    假如面试回答js的运行机制时,你可能说出这么一段话:"Javascript的事件分同步任务和异步任务,遇到同步任务就放在执行栈中执行,而碰到异步任务就放到任务队列之中,等到执行栈执行完毕之后 ...

  3. 文本处理三剑客之grep

    grep grep(支持基本正则表达式),egrep(支持扩展的正则表达式),fgrep(快速的grep,不支持正则表达式) grep是一个最初用于Unix操作系统的命令行工具.在给出文件列表或标准输 ...

  4. Sublime Text3 运行Python 出现Error:Decode error - output not utf-8

    问题描述: Sublime Text 3 在build Python时,如果python源代码输出有中文,例如"print('中文')",Sublime Text 会报 [Deco ...

  5. Collections、Arrays 简明

    Collections : 它的出现给集合操作提供了更多的功能.这个类不需要创建对象,内部提供的都是静态方法. 一般方法 Collections. sort (list); list 集合进行元素的自 ...

  6. JEECG中的模糊查询

    以一个使用代码生成器创建的通讯录(maillist)为例: @RequestMapping(params = "datagrid") public void datagrid(Ma ...

  7. ES6 继续 变量的解构赋值

    春节放假这几天,感觉跟梦一样,瞬间就过去了.现在上班的前几天,都感觉有点不真实,不过看到口袋里的钱,就知道,是真真实实的度过了这个假期. 现在得开始重新工作了: 变量的解构赋值 ES6 允许按照一定模 ...

  8. socket编程实例

    TCP/IP层次模型 当然这里我们只讨论重要的四层 01,应用层(Application):应用层是个很广泛的概念,有一些基本相同的系统级TCP/IP应用以及应用协议,也有许多的企业应用和互联网应用. ...

  9. 利用JS去做响应式布局

    利用JS去做响应式布局 js动态改变布局方式 // 取浏览器可视区高宽 var lw = $(window).width(); var lh = $(window).height();// 页面加载完 ...

  10. selenium 设置代理的话,可以使用这种方式,代码是我刚才测试过的,亲测可用

    from selenium import webdriver chrome_options = webdriver.ChromeOptions() chrome_options.add_argumen ...