最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 认识前端工具链(三)

    正文概述 掘金(彤爱)   2021-06-07   449

    前端工具链综述

    工具链在前端领域扮演着很重要的角色。如何为Javascript生产环境构建去构建一套工具链,来覆盖前端各个开发环节,是我们需要了解学习的。而一套高效的工具链体系,对于每一个前端团队来说都有着至关重要的意义,它不仅可以提高团队的开发效率,还可以在一定程度上规范前端开发的各个环节,进而为团队节省一些人员协作和调整的成本。

    综上,前端工具链旨在友好开发体验,提升开发团队开发效率

    而要构建一个工具链,首先我们先要了解在前端开发领域有哪几个环节:

    • 项目初始化
    • 开发、调试、构建
    • 单元测试
    • 发布

    所以一个前端工具链,它大致都会包含上面这一系列功能。而一个典型的示例就类似于下面:

    • Yeoman
    • Webpack
    • Mocha
    • 发布系统

    我们可以将进而将它总结成下面几块:

    • 脚手架
    • 构建⼯具
    • 测试工具
    • 发布系统

    而上了规模的团队也都会针对以上的流程,制定一个工具链,并将它包装成一个黑盒形式,让程序员在每个环节只需要运行简单命令行,即可进入开发流程。

    而从整体上了解工具链相关的知识体系,熟悉其大致结构以及运作方式,也是十分重要的。

    所以,下面这里是本人将对于工具链相关基础知识的一些整理。这一篇我们首先来介绍的是,工具链中的测试工具。

    工具链系列文章指路:

    认识前端工具链(一)

    认识前端工具链(二)

    单元测试工具

    测试工具是前端工具链里非常重要的一环,对于大部分的开源项目来说,测试都是一个必需品。如果我们某个项目是一个被高度复用的东西,那测试的收益也是很高的,所以除非是一次性使用的代码,我们还都是要使用单元测试 。

    下面介绍一些当前最流行的测试工具和一些配套设施:

    这里有流行的两个库一个是Mocha,一个是Jest

    Mocha

    Mocha最早是一个针对Node.js的一个测试框架,它默认在使用Webpoack之前,它都是不支持import export的,这里我们例子里使用的是require。

    1. 安装
    npm install -g mocha
    npm install --save-dev mocha
    
    2.基本使用
    //test/test.js
    var assert = require('assert');
    var add = require('../add.js')
    
    describe('add function testing', function () {
      it('1 + 2 shuold be 3', function() {
        assert.equal(add(1, 2), 3);
      });
      it('-5 + 2 shuold be -3', function() {
        assert.equal(add(-5, 2), -3);
      });
    })
    
    
    // add.js
    function add (a, b) {
      return a + b
    }
    module.exports = add
    
    3.引入babel

    这里我们引入babel来解决一下add.js必须用node的方式module.exports的问题。而简单的方法,我们可以用webpack项目,然后在dist里面去做单元测试,但从理论上考虑,测试这个环节依赖于build这个环节,是一件不太好的做法。另外,这对后面做code coverage话以上面这种方式的话,会带来不必要的麻烦。

    所以我们这里用babel给我们提供一个方案,去解决。

    这个方案是babel register。

    安装
    npm install --save-dev @babel/core @babel/register
    npm install --save-dev @babel/preset-env
    

    然后配置一下babel。

    命令
    ./node_moudules/.bin/mocha --require @babel/register
    
    4. code coverage

    code coverage表示我们的测试到底覆盖了源文件的哪些代码。这里我们介绍一个新的工具叫做nyc,它可以在一个复杂的文件中,测试它最终测试的覆盖比例。

    • 安装
    npm install --save-dev nyc
    
    • 命令
    nyc ./node_modules/.bin/mocha
    

    这里我们加入babel使用:

    npm install --save-dev @istanbuljs/nys-config-babel
    npm install --save-dev babel-plugin-istanbul
    
    • 在package.json中添加两个script项
      "scripts": {
        "test": "mocha --require @babel/register",
        "coverage": "nyc mocha"
      },
    
    • 我们写测试用例的时候用npm run coverage,写业务代码的时候用的是npm run test

    对html-parser进行单元测试

    这里要完成的是对我之前写一个html-parser添加单元测试。

    这里将之前的代码拷贝,新建一个目录然后重复完成上述操作。

    然后执行命令,将单元测试跑起来。

    结果

    认识前端工具链(三)

    认识前端工具链(三) 由上图可知,测试用例覆盖率是30%多,下面我们将通过修改用例实现90%以上覆盖。

    // parser-test.js
    var assert = require('assert');
    import {parseHTML} from '../src/parser'
    
    describe('parse html:', function () {
      it('<a></a>', function() {
        let tree = parseHTML('<a></a>')
        assert.equal(tree.children[0].tagName, 'a');
        assert.equal(tree.children.length, 1);
      });
      it('<a href="//time.geekbang.org"></a>', function() {
        let tree = parseHTML('<a href="//time.geekbang.org"></a>')
        assert.equal(tree.children[0].tagName, 'a');
        assert.equal(tree.children.length, 1);
      });
      it('<a href></a>', function() {
        // 127-135
        let tree = parseHTML('<a href></a>')
        assert.equal(tree.children[0].tagName, 'a');
        assert.equal(tree.children.length, 1);
      });
      it('<a href id></a>', function() {
        // 135-143
        let tree = parseHTML('<a href id></a>')
        assert.equal(tree.children[0].tagName, 'a');
        assert.equal(tree.children.length, 1);
      });
      it('<a id=\'a\'></a>', function() {
        // 168-171
        let tree = parseHTML('<a id=\'a\'></a>')
        assert.equal(tree.children[0].tagName, 'a');
        assert.equal(tree.children.length, 1);
      });
      it('<a id=abc></a>', function() {
        // 171-175
        let tree = parseHTML('<a id=abc></a>')
        assert.equal(tree.children[0].tagName, 'a');
        assert.equal(tree.children.length, 1);
      });
      it('<a id="abc" href></a>', function() {
        // 230
        let tree = parseHTML('<a id="abc" href></a>')
        assert.equal(tree.children[0].tagName, 'a');
        assert.equal(tree.children.length, 1);
      });
      it('<a id=abc href></a>', function() {
        // 209-210
        let tree = parseHTML('<a id=abc href></a>')
        assert.equal(tree.children[0].tagName, 'a');
        assert.equal(tree.children.length, 1);
      });
      it('<a id=\'a\'/>', function() {
        // 
        let tree = parseHTML('<a id=\'a\'/>')
        assert.equal(tree.children[0].tagName, 'a');
        assert.equal(tree.children.length, 1);
      });
    
      it('<a />', function() {
        // 130
        let tree = parseHTML('<a />')
        assert.equal(tree.children[0].tagName, 'a');
        assert.equal(tree.children.length, 1);
      });
      it('<A /> upper casse', function() {
        // 100
        let tree = parseHTML('<A />')
        assert.equal(tree.children[0].tagName, 'A');
        assert.equal(tree.children.length, 1);
      });
      it('<a/>', function() {
        // 98
        let tree = parseHTML('<a/>')
        assert.equal(tree.children[0].tagName, 'a');
        assert.equal(tree.children.length, 1);
      });
      it('<a id=a/>', function() {
        let tree = parseHTML('<a id=a/>')
        assert.equal(tree.children[0].tagName, 'a');
        assert.equal(tree.children.length, 1);
      });
      it('<>', function() {
        let tree = parseHTML('<>')
        assert.equal(tree.children[0].type, 'text');
        assert.equal(tree.children[0].content, '<>');
      });
    })
    
    
    
    • 结果

    认识前端工具链(三)

    Vscode:调试配置示例

    {
      // 使用 IntelliSense 了解相关属性。 
      // 悬停以查看现有属性的描述。
      // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
      "version": "0.2.0",
      "configurations": [
        {
          "type": "node",
          "request": "launch",
          "name": "启动程序",
          "skipFiles": [
            "<node_internals>/**"
          ],
          "sourceMaps": true,
          "runtimeArgs": [
            "--require", "@babel/register"
          ],
          "args": [],
          "program": "${workspaceFolder}/node_modules/.bin/mocha"
        }
      ]
    }
    

    工具链与generator集成

    • generator修改,package.json中需要安装的依赖,将单元测试模块也引入
    • generator引入文件.babelrc、.nycrc
    • 引入simple-test.js 简单测试用例对文件
    • webpack.config中的相关babel配置的引入
    // generator/app/index.js
    var Generator = require('yeoman-generator');
    
    module.exports = class extends Generator {
        // The name `constructor` is important here
        constructor(args, opts) {
          // Calling the super constructor is important so our generator is correctly set up
          super(args, opts);
        }
        async initPackge () {
          const answers = await this.prompt([
            {
              type: "input",
              name: "name",
              message: "Your project name",
              default: this.appname // Default to current folder name
            },
            {
              type: "input",
              name: "title",
              message: "Your html title",
              default: this.appname // Default to current folder name
            }
          ]);
          const pkgJson = {
            "name": answers.name,
            "version": "1.0.0",
            "description": "",
            "main": "index.js",
            "scripts": {
              "test": "./node_modules/.bin/mocha --require @babel/register",
              "coverage": "nyc ./node_modules/.bin/mocha",
              "build": "./node_modules/.bin/webpack",
            },
            "author": "",
            "license": "ISC",
            "devDependencies": {
            },
            "dependencies": {
            }
          };
          this.fs.extendJSON(this.destinationPath('package.json'), pkgJson);
          this.npmInstall(['vue'], {'save-dev': false});
          this.npmInstall([
            'webpack',
            'babel-loader',
            '@babel/core',
            '@babel/preset-env',
            '@babel/register',
            '@istanbuljs/nyc-config-babel',
            'babel-plugin-istanbul',
            'mocha',
            'nyc',
            'webpack-cli',
            'vue-loader', 
            'vue-template-compiler', 
            'vue-style-loader', 
            'css-loader',
            'copy-webpack-plugin'
          ], {'save-dev': true});
          this.fs.copyTpl(
            this.templatePath('HelloWorld.vue'),
            this.destinationPath('src/HelloWorld.vue'),
            {}
          );
          this.fs.copyTpl(
            this.templatePath('webpack.config.js'),
            this.destinationPath('webpack.config.js'),
            {}
          );
          this.fs.copyTpl(
            this.templatePath('main.js'),
            this.destinationPath('src/main.js'),
            {}
          );
          this.fs.copyTpl(
            this.templatePath('index.html'),
            this.destinationPath('src/index.html'),
            { title: answers.title }
          );
          this.fs.copyTpl(
            this.templatePath('.babelrc'),
            this.destinationPath('.babelrc')
          );
          this.fs.copyTpl(
            this.templatePath('.nycrc'),
            this.destinationPath('.nycrc')
          );
          this.fs.copyTpl(
            this.templatePath('simple-test.js'),
            this.destinationPath('test/simple-test.js')
          );
        }
    };
    

    参考附录

    mocha

    后记

    我是彤爱,一个在沉溺于寂寞代码海洋里的前端程序员??‍?

    欢迎各位大佬的赐教?

    期待与同样在努力摸索的小伙伴们交流?


    起源地下载网 » 认识前端工具链(三)

    常见问题FAQ

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

    发表评论

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

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

    联系作者

    请选择支付方式

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