前端工程化——脚手架及自动化构建

定义

  • 一切以提高效率、降低成本、质量保证为目的的手段,都属于工程化

前端工程化主要解决的问题

  • 传统语言或语法的弊端
  • 无法使用模块化/组件化
  • 重复性的机械工作
  • 代码风格统一、质量保证
  • 依赖后端服务接口的保证
  • 整体依赖后端项目

工程化的表现

体现在项目的整个流程:

  • 创建项目

  • 创建项目结构

  • 创建特定类型文件

  • 编码

    • 格式化校验

    • 校验代码风格

    • 编译 / 构建 / 打包

  • 预览/测试

    • Web Server / Mock

    • Live Reloading / HMR

    • Source Map

  • 提交

    • Git Hooks

    • Lint-staged

    • 持续集成

  • 部署

    • CI / CD

    • 自动发布

工具和工程化

  • 工具不等于工程化,比如webpack不是工程化,它是工具
  • 工程化是对项目的整体的规划或者架构而不是某个工具
  • 工具是实现这种规划或者架构落地的手段
  • 成熟的工程化的集成:
    • create-react-cli
    • vue-cli
    • angular-cli
  • 上述的集成工具不仅实现自动化构建项目
  • 更多的是约定vue项目应该有什么样的目录结构、什么特定的文件
  • 提供热更新等服务

工程化与node

  • 前端工程化是由node强力驱动的

项目创建环节——脚手架

脚手架的本质作用

  • 创建项目基础结构
  • 提供项目规定和约定

用于解决的问题

  • 相同的组织结构
  • 相同的开发范式
  • 相同的模块依赖
  • 相同的工具配置
  • 相同的基础代码

常用的脚手架工具

专用型脚手架

如create-react-cli

  • 作用
    • 根据信息创建对应的项目接触结构
    • 服务于专用的框架项目
通用型脚手架

如Yeoman

  • 作用
    • 在项目创建时使用
    • 根据一套模板生成对应的项目结构
    • 灵活易扩展

如plop

  • 作用
    • 在项目过程中用于创建特定类型的文件(组件化项目中创建行的组件,模块化的项目中创建新的模块)
    • 更稳定,更方便,更快捷

通用型脚手架Yeoman

  • 更像是一款脚手架运行平台
  • Yeoman需要搭配generator创建任何类型的项目
  • 不够专注,细节上没有专用型细致
  • 想要使用Yeoman来创建项目的话必须要找到对应的generator
Yeoman使用

以创建node模块项目为例

  • 在全局范围安装yo

    • yarn global add yo / npm install yo --global
  • 安装对应的generator (不同的generator可生成不同的项目)

    • yarn global add generator-node / npm install generator-node
  • 通过yo运行generator(运行方式是把包名前面的generator-去掉通过yo来运行)

    • cd path/to/project-dir
    • mkdir my-module
    • yo node // 生成node项目结构

如果想要在原有的项目基础上去添加一些配置文件需要使用Sub Generator

下面以向node项目中添加cli功能举例:

  • Sub Generator

    • 在原有的基础上加上配置文件

    • 基本使用,把上述项目变成一个cli命令,所以需要使用node:cli子集Generator来进行生成

      • yo node:cli

      • yarn link // 将本地的项目link到全局范围,就相当于 yarn link 自动给全局配置了一个 映射关系

      • 因为转遍成cli项目后新增了新的依赖,所以需要安装一下新的依赖,使用yarn命令即可

      • my-module --help // 这样就不用使用yo node来使用了

注意,并不是所有的generator都提供子集sub生成器,需要根据Yeoman官网中给出的generator来

Yeoman使用流程
  1. 明确你的需求
  2. 找到合适的Generator(去Yeoman官网上去找合适的Generator)
  3. 全局范围安装找到的Generator
  4. 通过Yo运行对应的Generator
  5. 通过命令行交互填写选项
  6. 生成你所需要的项目结构
自定义Generator

因为不同的Generator会生成不同的手脚架,那么我们自定义一个Generator将会生成自己所需要的项目结构

基于Yeoman搭建自己的脚手架,以Vue为例

  • Generator本质上就是一个npm模块

  • 创建Generator模块

    • Generator与npm模块不同的是他的名称得是以generator-name的形式来命名
    • Generator 基本结构

前端工程化——脚手架及自动化构建_第1张图片

默认是app文件夹存放的是生成器对应的代码,如果有sub生成器的话就直接和app同级新建一个文件夹即可,如上图中就有了个component生成器

基本流程:

  1. 新建一个项目文件夹,并用yarn init -y初始化 (注意,这个文件夹的名字就是最终的生成器的名字,使用yo name 就能使用了)
  2. 安装yeoman-generator,提供了一些便于创建生成器的工具函数
  3. cd到这个项目文件夹,创建上述图片中的Generator结构
    • 其中,index.js就是Generator的核心入口,需要导入一个继承自Yeoman Generator的类型
    • Yeoman Generator 在工作时会自动调用我们在此类型中定义的一些生命周期方法
    • 我们在这些方法中就可以调用父类提供的一些工具方法来实现功能,如文字的写入
// index.js
// 此文件作为Generator的核心入口
// 需要导出一个继承自Yeoman Generator的类型
// Yeoman Generator 在工作时会自动调用我们在此类型中定义的一些生命周期方法
// 我们在这些方法中可以通过调用父类提供的一些工具方法实现一些功能,如文件的写入


const Generator = require('yeoman-generator')

module.exports = class extends Generator {
   
  prompting () {
     // 可以和用户交互,根据用户输入进行配置
    return this.prompt([
      {
   
        type: 'input', // 以用户输入的方式来接收信息
        name: 'name',  // 得到结果的键名
        message: 'Your project name',  // 用户看到的问题提示
        default: this.appname   // 当前生成目录的文件夹的名字
      }
    ])
    .then(answers => {
     //  这个answer是个对象,对象里面的键就是name,值就是用户输入的数据:{name:'用户输入的数据'}
      this.answers = answers
    })
  }

  writing () {
     // Yeoman会在自动生成文件阶段调用此方法
    this.fs.write(
    	this.destinationPath('temp.txt'),   // 自动获取生成项目目录下的文件路径
        Math.random().toString()
   )
  }
}
  • 还可以使用模板的方式来创建文件,使用模板语法ejs

首先新建一个template模板文件夹,里面放模板文件,然后项目会根据这个模板文件来进行创建

// index.js
// 此文件作为Generator的核心入口
// 需要导出一个继承自Yeoman Generator的类型
// Yeoman Generator 在工作时会自动调用我们在此类型中定义的一些生命周期方法
// 我们在这些方法中可以通过调用父类提供的一些工具方法实现一些功能,如文件的写入


const Generator = require('yeoman-generator')

module.exports = class extends Generator {
   
   prompting () {
     // 可以和用户交互,根据用户输入进行配置
    return this.prompt([
      {
   
        type: 'input', // 以用户输入的方式来接收信息
        name: 'name',  // 得到结果的键名
        message: 'Your project name',  // 用户看到的问题提示
        default: this.appname   // 当前生成目录的文件夹的名字
      }
    ])
    .then(answers => {
     //  这个answer是个对象,对象里面的键就是name,值就是用户输入的数据:{name:'用户输入的数据'}
      this.answers = answers
    })
  }

  writing () {
   
    /*this.fs.write(
    	this.destinationPath('temp.txt'),  
        Math.random().toString()
   )*/   // 若使用模板方法就不用这种方式写入了
   
   // 通过模板方法写入文件到目标目录
   // 模板文件路径:
    const tmpl = this.templagePath('foo.txt')  // 模板文件
    const output = this.destinationPath('foo.txt')  // 输出路径
    const context = this.answers  // 模板数据上下文
    this.fs.copyTpl(templ, output, context)  // 将模板文件映射到输出文件中
  }
}
  • 可以使用prompting接受用户数据
实现Vue-generator
  • 首先准备一个文件夹里面是预想要的文件结构
  • 然后把这个文件夹中的文件作为模板,通过循环遍历的方式根据里面的文件创建新的文件。
  • 最后进行创建完成后可以使用yarn publish进行发布

小型脚手架工具plop

  • 用于项目创建过程中实现自动化创建特定类型的小工具
  • 一般不会独立使用,而是集成到项目当中用于自动化的创建同类型的项目文件
具体使用
  • 将plop模块作为项目开发依赖安装
    • yarn add plop --dev
  • 在项目根目录下创建一个plopfile.js配置文件
  • 在plopfile.js文件中定义脚手架任务
  • 编写用于生成特定类型文件的模版
  • 通过Plop提供的CLI运行脚手架任务 yarn plop component
// plopfile.js
// 这是Plop 入口文件,需要导出一个函数
// 此函数接收一个 plop 对象,用于创建生成器任务

module.exports = plop => {
   
  plop.setGenerator('component', {
   
    description: 'create a component',
    prompts: [
      {
   
        type: 'input',
        name: 'name',
        message: 'component name',
        default: 'MyComponent'
      }
    ],
    actions: [
      {
   
        type: 'add', // 代表添加文件
        path: 'src/components/{
   {name}}/{
   {name}}.js',
        templateFile: 'plop-templates/component.hbs'
      },
      {
   
        type: 'add', // 代表添加文件
        path: 'src/components/{
   {name}}/{
   {name}}.css',
        templateFile: 'plop-templates/component.css.hbs'
      },
      {
   
        type: 'add', // 代表添加文件
        path: 'src/components/{
   {name}}/{
   {name}}.test.js',
        templateFile: 'plop-templates/component.test.hbs'
      }
    ]
  })
}

脚手架的工作原理

  • 启动脚手架后,它会自动去询问一些预设的问题,将用户回答的结果结合一些模板文件来生成项目的结构
  • 意义:在创建项目环节大大提高开发者的效率

基于NodeJS创建一个脚手架

  1. 创建一个项目文件,并通过yarn init-y 进行初始化

  2. 在package.json中指定一个bin字段,用来指定脚手架的入口文件cli.js

    // package.json 文件
    
    {
         
      "name": "sample-scaffolding",   //  脚手架项目名称
      "version": "0.1.0",
      "main": "index.js",
      "bin": "cli.js",  // 指定脚手架的入口文件
      "author": "zce  (https://zce.me)",
      "license": "MIT",
      "dependencies": {
         
        "ejs": "^2.6.2",
        "inquirer": "^7.0.0"
      }
    }
    
    
  3. 创建cli.js文件

    • 必须要有文件头#!/usr/bin/env node
    • 文件创建好后要记得使用yarn link 映射到全局,否则无法使用
    • 需要安装inquirer来实现命令行询问,安装ejs包来使用ejs模板
      • yarn add inquirer ejs
    #!/usr/bin/env node
    // Node CLI 应用入口文件必须要有这样的文件头
    
    // console.log('demo-cli working!');   // test
    
    // 脚手架的工作过程:
    // 1. 通过命令行交互询问用户问题
    // 2. 根据用户回答的结果生成文件
    
    const fs = require('fs')
    const path = require('path')
    const inquirer = require('inquirer')   // 发起命令行的询问
    const ejs = require('ejs')
    
    inquirer.prompt([
      {
         
        type: 'input',  // 方式
        name: 'name',   // 键名
        message: 'Project name?'  // 问题(问题的答案就是键值)
      }
    ])
    .then(anwsers => {
         
      // console.log(anwsers)  //  {name:'用户输入的内容'}
      // 根据用户回答的结果生成文件
    
      // 模板目录
      const tmplDir = path.join(__dirname, 'templates')
      // 目标目录
      const destDir = process.cwd()   // 命令行在哪个目录执行就输出到哪个路径,所以借助process的cwd方法
    
      // 将模板下的文件全部转换到目标目录
      fs.readdir(tmplDir, (err, files) => {
         
        

你可能感兴趣的:(前端工程化,javascript,node.js,html)