前端工程化

225 阅读2分钟
全副武装:通过工程化提升“战斗力”

面临的问题

  • 想要使用ES6+ 新特性,但是兼容有问题
  • 想要使用Less/Sass/PostCss增强的编程性,但是运行环境不能直接支持
  • 想要使用模块化的方式提高项目的可维护性,但是运行环境不能直接支持
  • 部署上线前需要手动压缩代码及资源文件,部署过程需要手动上传代码到服务器
  • 多人协作开发,无法硬性统一大家的代码风格,从仓库中pull回来的代码质量无法保证
  • 部分功能开发时需要等待后端服务接口提前完成

主要解决的问题

  • 传统语言或语法的弊端
  • 无法使用模块、组件化
  • 重复的机械式工作
  • 代码风格统一、质量保证
  • 依赖后端服务接口支持
  • 整体依赖后端项目 一切重复的工作都应该被自动化

内容概要

  • 脚手架工具开发
  • 自动化构建系统
  • 模块化打包
  • 项目代码规范化
  • 自动化部署

脚手架工具开发

  • 脚手架的本质作用是创建项目基础结构、提供项目规范和约定
  • 脚手架比手动修改更可靠

常用的脚手架工具

  • React.js项目 -> create-react-app
  • Vue.js 项目 -> vue-cli
  • Angular 项目 -> angular-cli
  • Yeoman
  • Plop

Yeoman的基本使用

  • 在全局范围安装yo
  $ yarn global add yo
  • 安装对应的generator
   $ yarn global add generator-node
  • 通过yo运行generator
  $ mkdir my-module
  $ yarn global add generator-node

Yeoman Sub Generator

常规的使用步骤:

  • 1.明确你的需求;
  • 2.找到合适的Generator
  • 3.全局范围安装找到的Generator
  • 4.通过yo运行对应的Generator
  • 5.通过命令行交互填写选项
  • 6.生成你所需要的项目结构

创建Generator模块

Generator 本质上就是一个NPM模块 Generator的基本结构

  • 文件命名必须是generator-的形式命名 比如 generator-sample

  generator-<name>

创建过程

  • 创建package.json,根据模板创建文件
  $ yarn init
  • 创建目录结构
    • generator-sample
      • generator
        • app
          • templates
          • index.js
      • package.json
  • 接收用户输入数据
/*
    index.js
    此文件作为 Generator 的核心入口
    需要导出一个继承自 Yeoman Generator 的类型
    Yeoman Generator 在工作时会自动调用我们在此类型中定义的一些生命周期方法
    我们在这些方法中可以通过调用父类提供的一些工具方法实现一些功能,例如文件写入
*/
const Generator = require('yeoman-generator');
module.exports = class extends Generator{
  // 获取当前项目状态,获取基本配置参数等
  initianlizing(){}
  /*
        向用户展示交互式问题收集关键参数
    Yeoman 在询问用户环节会自动调用此方法
    在此方法中可以调用父类的 prompt() 方法发出对用户的命令行询问
  */
  prompting(){
        return this.prompt([
      {
        type: 'input',
        name: 'name',
        message: 'Your project name',
        default: this.appname // appname 为项目生成目录名称
      }
    ]).then(answers => {
      // answers => { name: 'user input value' }
      this.answers = answers
    })
  }
  // 保存配置相关信息且生成配置文件(名称多为'.'开头的配置文件,例如.editorconfig)
  configuring(){}
  // 未匹配任何生命周期方法的非私有方法均在此环节*自动*执行
  default(){}
  /* 
    依据模板进行新项目结构的写操作
    Yeoman 自动在生成文件阶段调用此方法
    我们这里尝试通过模板方式写入文件到目标目录
  */
  writing(){
        // 模板文件路径
    const tmpl = this.templatePath('bar.html');
    // 输出目标路径
    const output = this.destinationPath('bar.html');
    // 模板数据上下文
    const context = this.answers;
    this.fs.copyTpl(tmpl, output, context);
  }
  // 处理冲突(内部调用,一般不用处理)
  conflicts(){}
  // 使用指定的包管理工具进行依赖安装(支持npm,bower,yarn)
  install(){}
  // 结束动作,例如清屏,输出结束信息,say GoodBye等等
  end(){}
}
<!-- bar.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title><%= name %></title>
</head>
<body>
    <h1>Hello, <%= name %></h1>
</body>
</html>
  • 使用Generator
  $ yarn link
  $ yo <name>

脚手架工作原理

自己创建脚手架

  • 新建项目文件夹,mkdir xgh-cli
  • 初始化项目创建package.json, yarn init
  • 在package.json中 输入 bin入口,cli.js
{
  "name": "gh-cli",
  "version": "1.0.0",
  "description": "cli demo",
  "main": "index.js",
  "bin": "cli.js",
  "license": "MIT"
}
  • 在根目录创建 cli.js文件 添加bin 入口标识和测试代码
    #!/usr/bin/env node
    console.log('xgh-cli work~~~')
  • 引入inquirer 模块 创建用户与命令行交互的工具 编写所需问题及字段
  • 创建模板目录templates 将项目文件导入到目录中
  • 引入ejs模块 结合所需功能问题变量 改写 templates 下项目文件 达到所需功能
  • 在inquirer回调中 结合nodejs 读写功能 和ejs 模块将问题变量 重写到项目中
  • yarn publish 发布到npm上 www.npmjs.com/package/xgh…