最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 前端脚手架开发入门

    正文概述 掘金(腾讯VTeam技术团队)   2021-01-06   879

    为什么需要脚手架

    脚手架本质上是一个工具,使用脚手架的目的就是摆脱构建工程时重复性的工作,尤其是当一个工程具有一定通用性时,工程脚手架的意义就更为突出。它可以让我们只需要一行命令,就可以初始化好一项工程,而不用费心费力的去做配置环境,安装依赖,解决依赖冲突这样的支线任务,可以直奔主线任务,早早下班~~

    概览

    开发一个的脚手架,通常需要如下npm包:

    • commander: 强大的node命令行处理工具。能轻松的获取命令行的参数。
    • inquirer: 命令行交互工具,让你能以“问答”的交互方式来完成一系列的命令行操作。
    • download-git-repo: git仓库下载工具,通常用来下载模板代码。
    • ora: 终端loading美化工具。
    • chalk: 命令行输入/输出美化工具,想要五彩版本的命令行,选它就对了。
    • handlebars: 模板引擎

    实现的功能:

    • 一条简单的命令初始化项目
    • 提供友好的交互体验
    • 可选择安装不同模板
    • 自动安装项目依赖

    开始干活

    STEP1: 打开一个终端,在你喜欢的地方新建一个空项目

    mkdir meo-cli
    cd meo-cli
    

    在项目更目录下执行:

    npm init -y
    

    你会得到一个package.json

    {
      "name": "meo-cli",
      "version": "1.0.0",
      "description": "",
      "main": "index.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      "keywords": [],
      "author": "",
      "license": "ISC"
    }
    

    关键点来了,在 package.json中加以一个bin字段,在安装时,npm 会将文件符号链接到 prefix/bin 以进行全局安装或./node_modules/.bin/本地安装。这样,就可以全局使用了。例如,下面的将meo-cli作为命令名称,执行文件是根目录的index.js

    {
      "name": "meo-cli",
      "version": "1.0.0",
      "description": "",
      "main": "index.js",
      "bin": {
          "meo-cli": "index.js"
      },
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      "keywords": [],
      "author": "",
      "license": "ISC"
    }
    

    STEP2 : 先写一个简单代码试一试吧~。在根目录下创建index.js文件,然后狠狠敲入下面的代码:

    #!/usr/bin/env node
    
    console.log('helo, world!')
    

    然后在命令行执行 meo-cli, 不出意外的话,你应该看不到输出hello,world。只会有个报错提示:

    zsh: command not found: meo-cli
    

    这是为什呢?因为我们并没有安装对应的包,当然就不会链接到全局啦。一个办法是发包,然后安装到本地,就可以了。但是这样太麻烦,难道每次调试都要发包??

    有没有更优雅的方法呢?答案是:有 npm早就想好了对策,就是npm link,它可以把指定的执行文件链接到全局,使用也非常简单,在项目根目录下执行:

    npm link
    

    就可以了。如果你执行命令后,显示类似安装npm包的提示,就说明链接成功了。在执行一下 meo-cli,就可以看到令人欣慰的hello world了。这里要注意一下首行的代码

    #!/usr/bin/env node
    

    这段并不是注释,这段代码是告诉你的脚本工具(bash/zsh), 下面的内容是要在node环境下运行的代码。千万不能省略!!!进行下一步之前,让我们下来回顾一下vue-cli脚手架是怎么使用的。

    前端脚手架开发入门

    可以看出来,脚手架会提供一个问答交互的方式,让使用者输入或选择参数,然后根据获取的参数做出相应的动作(action)。

    STEP3: 交互式脚手架的另一个特点是灵活,使用者可以根据自己的需求,可以清晰的去选择让脚手架做什么,不做什么。要实现这样的功能,就是要用到开头提到的插件

    • commander
    • inquirer

    commander是可以用来获取命令行的参数,并对参数做响应函数,inquirer则可以为我们提供一个’问答’式的交互体验。我们修改一下index.js的代码:

    // index.js
    #!/usr/bin/env node
    
    const { program } = require('commander');
    program.version('1.0.0')
    
    program.parse(process.argv)
    

    然后我们在命令行输入:

    meo-cli -V  // 1,0,0
    

    就会得到版本号信息。输入

    meo-cli -h
    

    前端脚手架开发入门

    就会得到这样的帮助信息。

    这和我们使用其他脚手架的体验是一样的。

    这样的体验要归功于commander.js

    commander用法如下:.command(‘init [name]’, ‘init a project’, opts) 功能:注册一个命令
    第一个参数:设置的命令的名称,后面可以跟参数,<> 表示必选参数,[]表示可选参数

    第二个参数: 命令的描述,可选,注意,当有第二个参数时,不能显示的调用action作为命令的回调,需要使用独立的可执行文件作为命令

    第三个参数:配置参数,如noHelp,isDefault等 .option(’-n, --name | [name]’, ‘desc’, ‘GK’)

    功能:定义命令选项,(类似命令的额外参数, 用于辅助命令)

    .description(‘this is a command desc’)
    功能:命令的描述, 同时会应用到命令的帮助信息中,使用help命令时会显示
    .action(cb):命令的回调函数

    .parse() 命令行参数解析, 通常用于最后 e.g.

    前端脚手架开发入门

    前端脚手架开发入门

    上面的代码,定义了一个命令init, 对命令做了描述(description), 并对init命令做了额外参数-t, 表示初始化工程的类型。action是init命令的回调,在回调用打印了参数,即我们定义一个工程,名字为demo, 工程类型为vue。这样后续工作中就可以用工程名拼接下载模板到本地的路径,type=vue 代表我们会去拉取vue的模板。STEP4: ok, 我们已经可以通过自定义命令获取到参数,接下来就可以拉取对应模板了。这时我们就需要使用 download-git-repo 这个包,它可以用来下载github, gitlab等远程仓库的代码。用法如下:

    download(repository, destination, options, callback)
    

    repository: 远程仓库的地址。destination:下载到本地的路径 options: 配置参数 callback: 回调函数 需要注意一下,远程仓库地址可以写成:

    direct: http: //github.com/xxx
    

    即需要完成的仓库路径,默认情况下,会下载master分支,如果要下载其他分支,在链接后加入分支名,

    direct:http://github.com/name/xxx.git#my-branch
    

    小技巧我们可以将模板分配到不同的分支,然后通过分支来下载不同模板。回调函数中会返回下载的结果,根据结果可以做出不同状态的处理。例如,根据返回状态判断是否下载成功,下载成功后提示是否要进行其他操作(安装项目依赖,后面会提到哦~)

    到此,一个初始化工程的脚手架就完成了。是的,真没骗人,命令行执行指定命令,获取参数,拉取模板代码,就这些~~。

    但是, 还可以做更多。

    通常我们在初始化一个项目时,会提示填写项目名称(已经做了),项目描述,作者等信息,这些都是使用者输入的,也就是命令行的参数,而且会提供一个更友好的“你问我答” 的方式教你做事,不, 求你填写信息??。这时候就是inquirer上场的时候了,它通过极为简单函数方式来提供交互操作。例如,我们要提示使用者输入项目描述和作者信息,就可以这样写,在action回调函数中

    // ...
    inquirer.prompt([
            {
                name: 'description',
                message: '请输入项目描述'
            },
            {
                name: 'author',
                message: '请输入项目作者',
                default: 'robot'
            }
        ])
        .then((res) => {})
    

    name表示输入的键名,输入的值为value, 即结果会以键值对的形式返回。default为默认值,当直接回车跳过时,会使用默认值。如果希望默认值是空,可以写成 default:'' 或省略default。

    inquirer.prompt() 的参数是一个对象数组,可以这样理解,inquirer是流程化的结构,流程可以是等待输入,列表选择,confirm确认yes or no。例如选择项目模板是,使用者可以从提供的模板列表中选择,而不是自己去输入,就可以这样定义参数:

    {
         name:'type',
         type: 'list',
         message: 'choose a type of project to init',
         choices: ['react', 'vue', 'h5'],
         default: 'react',
        }
    

    type表示类型,choices为列表数组,使用者可以从react,vue,h5中选择模板,默认会是react模板。

    前端脚手架开发入门

    然后根据type的值去拼接git仓库地址,下载对应模板。

    更多inquirer的用法,大家可以参考 github.com/SBoudrias/I… 来使用,这里不再赘述。

    STEP5: 我们已经通过交互方式拿到了项目描述,作者等信息,但是我们的目的是将这些信息写入到下载的模板中,也就是package.json中对应的description,author以及项目名称name中。这要怎么做呢?这就需要handlebars.js的帮助了,handlebars是一个强大的模板引擎,它可以解析指定模板,然后根据参数渲染模板。因为我们要将name, description, author写入到package.json中,因此我们要稍微修改一下模板文件:

    前端脚手架开发入门

    如图,将要填写的字段用{{}} 方式表示,内容就是对应要写入的变量名字,这和inquirer交互时拿到的字段要保持一致。当然,handlebars不止这么简单,更多的用法可以参考官网 handlebarsjs.com/guide/

    这样,我们就可以在模板下载完成后做写入工作了。

    download(url,'./template', { clone: true }, (error) => {
      if(!error) {
        const packagePath = path.join(downloadPath, 'package.json');
        // 判断是否有package.json, 要把输入的数据回填到模板中
        if (fs.existsSync(packagePath)) {
            const content = fs.readFileSync(packagePath).toString();
            // handlebars 模板处理引擎
            const template = handlebars.compile(content);
            const result = template(param);
            fs.writeFileSync(packagePath, result);
            
        } else {
            console.log('failed! no package.json');
        }
      }
    })
    

    这样在下载成功后,并且有package.json时才会去写入,否则给出错误提示。

    然而…

    我们发现,到目前为止,我们的命令行的输入一点也不好看,没有下载中的提示,没有五彩斑斓醒目的文字… ora 和 chalk这时就起作用了。ora可以美化命令行的loading,你是转圈圈,动态的小点点,还是自定义的gif都可以满足你,chalk就可以让你的命令行文字有了颜色,失败的红色告警,成功的绿色提示,都没问题。

    下面是拉取仓库模板的部分代码:

    const downloadPath = path.join(process.cwd(), name);
    const param = {name, ...parameter};
    const spinner = ora('正在下载模板, 请稍后...');
    spinner.start();
    download(
        // 直连下载,默认下载master
        `direct:http://git.code.oa.com/name/xxx.git#${type}-tpl`,
        downloadPath,
        { clone: true },
        (error) => {
            if (!error) {
                // success download
                spinner.succeed();
                const packagePath = path.join(downloadPath, 'package.json');
                // 判断是否有package.json, 要把输入的数据回填到模板中
                if (fs.existsSync(packagePath)) {
                    const content = fs.readFileSync(packagePath).toString();
                    // handlebars 模板处理引擎
                    const template = handlebars.compile(content);
                    const result = template(param);
                    fs.writeFileSync(packagePath, result);
        console.log(chalk.green('success! 项目初始化成功!'));
              console.log(
                      chalk.greenBright('开启项目') + '\n' +
                      chalk.greenBright('cd ' + name) + '\n' +
                      chalk.greenBright('start to dvelop~~~!')
                   )
                    
                } else {
                    spinner.fail();
                    console.log(chalk.red('failed! no package.json'));
                    return;
                }
            } else {
                console.log(chalk.red('failed! 拉取模板失败', error));
                return;
            }
        }
    )
    

    到此为止,一个基础的工程脚手架就完成了,它可以通过简单一条命令,根据输入的参数,拉取不同模板代码,并将用户信息回填到模板中,提供了交互式的友好体验。嗯~,挺香的,收工喽!!

    cd vue-demo
    npm run serve
    

    但是… 我们会发现一个问题,使用vue-cli的时候,在最后会有个运行提示:

    它并没有提示我们要npm install, 这说明下载模板的时候项目的依赖也同时安装。可我们的没有这个功能,不行,搞起!!STEP6 : 模板下载好后,我们要进入模板目录,然后根据它的package.json安装依赖,这里我们可以丰富一下,让使用者在安装依赖时有选择:1. 先不安装依赖,稍后自行安装, 2. 选择安装工具,这时最后的提示要给个npm intall的提示才算完美。是否安装依赖。即我们需要从使用者那里得到一个confirm, 根据返回的true或false来决定是否进行下一项安装。选择安装工具。如果使用者选择安装,就要提示他选择安装工具。这两个交互同样可以使用inquirer来完成

    const continueToInstall  = {
        type: 'confirm',
        name:'next',
        message: 'continue to install the project',
        default: true,
    }
    const installTool = {
        name: 'tool',
        type: 'list',
        message: 'choose the tool to install',
        choices: ['npm', 'tnpm', 'yarn'],
        default: 'npm',
    }
    

    这里做了简单的封装:

    const { next } = await inquirer.prompt(continueToInstall);
    if (next) {
        const { tool } = await inquirer.prompt(installTool);
        // 安装项目依赖
        const res = await installFunc({ cwd: downloadPath, command: tool });
        if (res && res.code === 0) {
            processSuccess(name, true, type);
        }
    } else {
        processSuccess(name, false, type);
    }
    

    至此,一个简单的工程脚手架就完成了。

    小结

    1. 本篇文章按照step by step的方式,在每一步详细的阐述了开发脚手架过程中使用的工具和注意事项。
    2. 本篇文章阐述的方法只实现了基础功能,好的脚手架还可以做更多,如集成单元测试,第三方库的选择安装,项目打包发布等。更多符合项目特点的脚手架还需要根据实际项目去开发。

    未经同意,禁止转载


    起源地下载网 » 前端脚手架开发入门

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元