IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 开发测试 -> 前端训练营学习笔记——工程化实践一:创建自己的脚手架工具 -> 正文阅读

[开发测试]前端训练营学习笔记——工程化实践一:创建自己的脚手架工具

0 引言

前面几篇博客介绍的是组件化知识和实践,组件化是从架构的角度解决如何通过程序复用将项目做大的问题,而本篇博客将要介绍的工程化则是解决如何通过制作工具、搭建系统等方式带领一个团队把项目做好。

1 什么是工程化

  • 工具、流程、系统:从没有到有,从少到多
  • 质量和效率:由低到高

2 初始化与构建

2.1 初始化工具Yeoman

Yeoman是社区流行的一个初始化工具,可以用来创建脚手架工具,相当于generator的generator

利用Yeoman创建generator的方法:

  1. 利用npm init新建一个模块
  2. 安装yeoman-generator包并全局安装yo命令
npm install yeoman-generator
npm install -g yo
  1. 在index.js中参考Yeoman官网的例子编写一个Generator类
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);
  }
  method1() {
    this.log('method 1 just ran');
  }

  method2() {
    this.log('method 2 just ran');
  }
};

  1. 修改package.json中的name(generator-模块名)和main路径(指向index.js的路径)
  2. 利用npm link将本地的模块链接到标准全局模块中去
  3. 最后执行yo 模块名启动脚手架

2.2 利用yeoman创建脚手架的简单用法

2.2.1 通过yeoman进行命令行交互

  // 在Generator中增加prompting异步方法
  async prompting() {
    this.answers = await this.prompt([
      {
        type: "input",
        name: "name",
        message: "Your project name",
        default: this.appname // Default to current folder name
      },
      {
        type: "confirm",
        name: "cool",
        message: "Would you like to enable the Cool feature?"
      },
      {
        type: "input",
        name: "title",
        message: "Your project title"
      }
    ]);

    this.log("app name", this.answers.name);
    this.log("cool feature", this.answers.cool);
  }

2.2.2 通过yeoman进行HTML模板填充

  // 在Generator中增加writing方法并执行this.fs.copyTpl
  writing() {
    this.fs.copyTpl(
      this.templatePath('index.html'), // templatePath在与当前文件同级的templates文件夹下
      this.destinationPath('public/index.html'), // 相对于根目录
      { title: this.answers.title } // 使用2.2.1中用户输入的`title`
    );
  }

2.2.3 通过yeoman管理依赖

利用this.fs.extendJSON()函数更改package.json并执行npmInstall自动安装依赖

class extends Generator {
  writing() {
    const pkgJson = {
      devDependencies: {
        eslint: '^3.15.0'
      },
      dependencies: {
        react: '^16.2.0'
      }
    };

    // Extend or create package.json file in destination path
    this.fs.extendJSON(this.destinationPath('package.json'), pkgJson);
  }

  install() {
    this.npmInstall();
  }
};

2.3 webpack基本知识

2.3.1 webpack的设计初衷和基本理解

  1. 设计初衷:webpack最初是为Node设计的打包工具,提供的能力是将node代码打包成浏览器可用的代码
  2. 基本理解:webpack能够进行多文件合并,在合并过程中通过各种loader和plugin去控制合并的规则以及对文本进行一些转换

2.3.2 webpack安装使用的两种方式

  1. 全局安装webpack-cli和webpack
  2. 本地安装webpack-cli然后使用npx webpack命令执行webpack

2.3.3 webpack的基础概念

  1. entry:用于设置入口文件
  2. output:用于设置输出文件路径
  3. loader:一种文件格式转换工具,用于将其它形式语言书写的文件转译成能被webpack识别的json或js格式,常见的loader有css-loader,vue-loader
  4. plugin: 用于完成除Loader之外的其它功能,如打包优化、拷贝文件等

2.4 babel基本知识

2.4.1 babel的作用

将新版本的js文件转换成老版本的js文件,以便能够运行在老版本的浏览器中

2.4.2 babel安装和使用

需要全局安装@babel/core和@babel/cli和用来设定默认配置的@babel/preset-env,并在.babelrc文件中配置@babel/preset-env

{
  "presets": ["@babel/preset-env"]
}

安装好后执行babel filename.js即可

2.4.3 在webpack中通过babel-loader使用babel

作用是能够在webpack打包过程中,自动利用babel对js文件进行处理

rules: [
      {
        test: /\.js$/,
        use: {
          loader: "babel-loader",
          options: {
            presets: ["@babel/preset-env"],
            plugins: [...]
          }
        }
      }
    ]

2.5 利用yeoman搭建一个vue脚手架

2.5.1 创建generator-vue项目

按照2.1中介绍的步骤创建一个generator-vue项目,注意package.json中的name(需要以generator-开头,执行脚手架时会被用户输入的项目名覆盖)和main路径要正确,入口文件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 prompting() {
    this.answers = await this.prompt([
      {
        type: "input",
        name: "name",
        message: "Your project name",
        default: this.appname // Default to current folder name
      }
    ])
    this.log("app name", this.answers.name);
  }

  async initPackages() {
    const pkgJson = {
      "name": this.answers.name,
      "version": "1.0.0",
      "description": "",
      "main": "generators/app/index.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      "author": "",
      "license": "ISC",
      "dependencies": {
        "yeoman-generator": "^4.11.0"
      },
    }
    // Extend or create package.json file in destination path
    this.fs.extendJSON(this.destinationPath('package.json'), pkgJson);
    this.npmInstall(["vue"], {"save-dev": false}); // 如果要装vue3,改成vue@next
    this.npmInstall(["webpack", "vue-loader"],  {"save-dev": true})
  }
  
  copyFiles() {
    this.fs.copyTpl(
      this.templatePath('HelloVue.vue'),
      this.destinationPath('src/HelloVue.vue'),
      {}
    );
  }

};

2.5.2 配置webpack

在templates文件夹中新建一个webpack配置文件webpack.config.js,配置vue-loader,vue-stytle-loader,css-loader以及webpack的copy-plugin插件, 如下

const webpack = require('webpack'); // 访问内置的插件
const VueLoaderPlugin  = require("vue-loader/lib/plugin")
const CopyPlugin = require("copy-webpack-plugin");
module.exports = {
  entry: './src/main.js',
  module: {
    rules: [
      {
        test: /\.vue$/,
        use: 'vue-loader', // 实现将vue文件转换成webpack能识别的js或json文件
      },
      {
        test: /\.css$/,
        use: ['vue-style-loader', 'css-loader'], // css-loader要在后面,否则会报错
      }
    ],
  },
  plugins: [
    new VueLoaderPlugin(), // VueLoader插件
    new CopyPlugin({ // 拷贝插件
      patterns: [
        { from: "src/*.html", to: "[name].[ext]" },
      ],
    })
  ],
  mode: "development"
};

2.5.3 拷贝相关模板文件

在template中添加index.html、main.js文件,并在index.js中将它们和webpack.config.js一同copy到src内

3 单元测试

3.1 单元测试的适用场景

  1. 可能会被很多人使用的开源项目
  2. 复用度比较高的商业项目
  3. 其它需要保证已有功能正确不受影响的复杂大型项目

3.2 前端单测工具

  • Mocha:有趣、简单且灵活的JavaScript测试框架
  • Jest:一个令人愉快的 JavaScript 测试框架,专注于简洁明快

3.3 Mocha的安装和简单使用

3.3.1 安装

  • 全局安装: npm install -g mocha
  • 项目安装: npm install --save-dev mocha

3.3.2 简单使用

add.js

function add(a, b) {
  return a+b
}

module.exports = add

test.js

let add = require("./add")
var assert = require('assert');

describe('test add function', function() {
    it('1 + 2 should return 3', function() {
      assert.equal(add(1, 2), 3);
    });
});

最后在test.js目录下执行mocha即可运行单元测试

3.3.3 将require/exports改成import/export语法

在3.3.2中引入和导出模块使用的是node的require/exports,如果想改成import/export语法,需要借助babel
- 本地安装mocha
- 本地安装@babel/core,@babel/preset-env,@babel-register
- 配置.babelrc的presets

{
  "presets": ["@babel/preset-env"],
}
  • 在package.json中的test字段添加运行mocha的脚本mocha --require @babel/register
{
  "name": "unit-test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "mocha --require @babel/register",
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.14.6",
    "@babel/preset-env": "^7.14.7",
    "@babel/register": "^7.14.5",
    "@istanbuljs/nyc-config-babel": "^3.0.0",
    "babel-plugin-istanbul": "^6.0.0",
    "mocha": "^9.0.1"
  }
}
  • 最后执行npm run test即可

3.4 单元测试的核心概念code coverage

3.4.1 code coverage含义

code coverage是用来检测编写的单元测试用例是否完整覆盖了项目代码,可以使用nyc插件
单测应达到的目标:函数覆盖率100%,行覆盖率>90%

3.4.2 code coverage插件nyc用法

将nyc应用于使用了babel的mocha项目的方法:

  • 本地安装nycnpm i --save-dev nyc
  • 安装两个插件:npm i --save-dev babel-plugin-istanbul @istanbuljs/nyc-config-babel
  • 在.babelrc中添加"plugins": ["istanbul"]然后在.nycrc配置文件中添加如下配置
{
    "extends": "@istanbuljs/nyc-config-babel"
}
  • 在package.json中的test字段添加coverage的脚本"coverage": "nyc mocha"
  • 最后执行npm run coverage命令即可

3.4.3 code covrage测试结果示例

File% Stmts% Branch% Funcs% LinesUncovered Line #s
All files90.4382.0410090.29
parser.js90.4382.0410090.2925,80,105,170-171,227,237,249,260,265,271,273,293,297,316,356,362-365,373,392

3.5 实例:对parseHTML函数进行单元测试

详见HTML-parser/test/test.js,几点注意:

  1. 为方便对babel处理过的代码跟踪调试,需要在调试的配置文件launch.json中加入两个额外的配置,并在.babelrc中加入配置"sourceMaps": "inline" /*不会产生额外的输出文件*/
      "runtimeArgs": ["--require", "@babel/register"],
      "sourceMaps": true, // 开启源映射,以便调试的时候能够映射到真实的代码而非babel转译的代码
  1. launch.json中的program配置要指定到node_modules/bin/mocha目录

3.6 将单测集成到工具链中

参考2.5.1在pkgJson中添加test和coverage命令,安装单测相关依赖并将.babelrc,.nycrc和单测模板文件test.js拷贝到destinationPath中,详细请参考generator-vuetool/generators/app/index.js

4 利用集成了单测的脚手架搭建vue项目

  1. 在脚手架项目根目录下创建新的项目文件夹my_vue_app
  2. 在my_vue_app文件夹中执行yo vuetool命令
  3. 按照命令行提示依次输入相关设置等待项目搭建完成
yo vuetool
? Your project name my_vue_app
app name my_vue_app
   create package.json
   create src\HelloVue.vue
   create src\main.js
   create webpack.config.js
   create src\index.html
   create .babelrc
   create .nycrc
   create test\test.js
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN my_vue_app@1.0.0 No description
npm WARN my_vue_app@1.0.0 No repository field.

+ vue@3.1.5
added 14 packages from 41 contributors in 3.095s

+ vue-style-loader@4.1.3
+ copy-webpack-plugin@9.0.1
+ webpack-cli@4.7.2
+ vue-template-compiler@2.6.14
+ @babel/core@7.14.6
+ @babel/preset-env@7.14.7
+ css-loader@6.1.0
+ @vue/compiler-sfc@3.1.5
+ vue-loader@16.3.1
+ @babel/register@7.14.5
+ babel-plugin-istanbul@6.0.0
+ babel-loader@8.2.2
+ webpack@5.45.1
+ mocha@9.0.2
+ @istanbuljs/nyc-config-babel@3.0.0
+ nyc@15.1.0
added 520 packages from 257 contributors in 71.987s

48 packages are looking for funding
  run `npm fund` for details

生成的项目目录结构如下图所示
目录结构
4. 等项目搭建好后便可以愉快地进行开发和测试了

  1. 运行npm run test可以执行单测
  2. 运行npm run coverage可以执行单测覆盖率检查
  3. 运行npm run build可以打包构建项目生成dist目标代码

5 小结

本篇博客首先阐述了对前端工程化的基本理解:前端工程化体现在工具、规范、系统等从无到有,由少到多,目标是提升项目开发的效率和质量。然后以一个实际的项目——创建自己的脚手架工具为例,分项目初始化和构建以及单元测试两部分介绍如何创建自己的脚手架工具。最后利用创建的脚手架工具快速搭建一个包含测试模块的vue项目。希望读者能从中体会到工程化是如何提升项目开发效率和质量的,当然笔者目前也还处在工程化刚学习入门阶段,后续需要通过不断地实践加深认识和理解。

ps:如果觉得此文对你有帮助或启发,请不要吝惜你的点赞和分享,如有疑问,请留言或私信交流

  开发测试 最新文章
pytest系列——allure之生成测试报告(Wind
某大厂软件测试岗一面笔试题+二面问答题面试
iperf 学习笔记
关于Python中使用selenium八大定位方法
【软件测试】为什么提升不了?8年测试总结再
软件测试复习
PHP笔记-Smarty模板引擎的使用
C++Test使用入门
【Java】单元测试
Net core 3.x 获取客户端地址
上一篇文章      下一篇文章      查看所有文章
加:2021-07-22 23:05:08  更:2021-07-22 23:05:41 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/2 4:47:21-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码