工程化定义
前端工程化,遵循一定的标准和规范,通过工具提高效率、降低开发成本、被关注和探讨,是互联网时代不可或缺技术,前端占据整个互联网开发的半壁江山,从传统网站到h5到桌面应用再到小程序 无所不能全面覆盖。前端行业对开发人员的要求发生翻天覆的变换,前端工程化被提出,成为前端开发必备的手段。node.js,让js有新舞台,让前端行业进行一次工业革命,很多工具都是使用node.js 开发。工程化是一个庞大概念,不管如何发展,始终为了解决问题,切莫为了技术而技术。
工程化解决问题
- 传统语言弊端,使用es6、es7新特性,提高编码效率、实际用会发现兼容有问题,使用less、sass、postcss 提高css的编程性 但是在运行环境中不被支持
- 模块化组织代码,使用模块化、组件化、提高项目的可维护性
- 大量重复机械操作,部署上线需要手动压缩代码,重复性工作,手动将项目上传到服务器,容易出现问题,机器取代人做重复性操作,不会犯错
- 统一代码风格,保障仓库代码质量,多人协同开发,不能保证代码风格,代码质量
- 依赖后端服务接口,整体依赖后端项目,开发具体功能需要等待接口服务完成才可以做编码,以上都是没有工程化所面临的典型问题
工程化特点
- 相同的组织结构
- 相同的开发范式
- 相同的模块依赖
- 相同的工具配置
- 相同的基础代码
项目工程化表现方式
一切重复的工作都应该被自动化
- 创建项目:创建固定项目结构,创建特定类型文件,脚手架搭建基础结构
- 编码:格式化代码,校验代码风格,编译/构建/打包,提交之前做代码风格验证,保证项目质量,对gitlog做严格模式限制,开发阶段使用新特性,将编写的代码和运行的代码进行转换
- 预览测试:web-server、mock,传统的预览环节使用apache、nginx运行项目,没有热更新,工程化实现编码完成之后在浏览器直接看到结构,无需刷新
- 提交:Git-Hooks、Lint-staged、持续集成
- 部署:CI/CD 、 自动发布,代替上传到ftp
脚手架工具
- vue=>vue-vli
- react=>create-react-app
- angular=>angular-cli
yeoman简介
脚手架运行平台,有自己的仓库,已经实现了很多脚手架yeoman官网generators库,yeoman搭配不同generator创建任何类型项目,可以通过创建自己的generator,从而创建我们自己的脚手架。每一个generator都是一个单独的npm包
yeoman基础用法
- 在全局范围安装yo
$ npm install yo -g
- 安装对应generator
$ npm install fenerator-node -g
- 通过yeom 运行generator
$ cd path/to/project-dir
$ mkdir my-module
$ yo node
简单使用
sub-generator
项目目录,运行特定的subgenerator
使用步骤
- 明确需求
- 找到合适的Generator
- 全局范围安装找到Generator
- 通过Yo 运行对应的generator
- 通过命令行交互填写选项
- 生成需要的项目结构
自定义generator
不同的generator可以用来生成不同的项目,创建自己的generator,生成自定义的项目结构,市面上的generator是通用的,但是在我们开发过程中,需要生成一部分基础代码和一部分业务代码,,把公共部分放在脚手架生成,例如项目中用到的sso。generator本质上是一个npm模块。
名称规范
采用generator-<name>规范
generator基本结构
$ mkdir test-customize-generator
$ cd test-customize-generator
$ npm init
|-- part2-前端工程化
|-- package.json 模块包配置文件
|-- generators 生成器目录
|-- app 默认生成器目录
| |-- index.js 默认生成器实现
|-- component 其他生成器目录
|-- index.js 其他生成器实现
基础用法
- 安装
Generator生成器
# 创建目录
$ mkdir generator-gxrtestdemo
# 进入目录
$ cd generator-gxrtestdemo
# init项目
$ npm init
# 安装基类生成器
$ npm install yeoman-generator -d
- 创建生成器实现目录
$ mkdir generators
$ cd generators
$ mkdir app
$ cd app
$ touch index.js
- 编写
generators/app/index.js核心文件
此文件是generator的核心入口文件,需要导出一个继承自 Yeoman Genarator的类型,Yeoman Generator 在工作时会自动调用我们此类型中定义的一些生命周期,我们在这些方法中通过调用父类提供的一些工具方法实现一些功能,例如文件写入
const Generator = require("yeoman-generator");
module.exports = class extends (
Generator
) {
writing() {
// yeoman自动在生成文件阶段调用这个方法
// 我们这里尝试往项目目录中写入文件
this.fs.write(this.destinationPath("test.txt"),
Math.random().toString());
}
};
- 在当前目录中运行
npm link,会自动创建一个package-lock.json文件
{
"name": "generator-gxrtestdemo",
"version": "1.0.0",
"lockfileVersion": 1
}
- 当前项目运行
yoe run gxrtestdemo
create test.txt
- 项目目录下生成
|-- part2-前端工程化
|-- package-lock.json
|-- package.json
|-- test.txt
|-- generators
|-- app
|-- index.js
0.1643974097348393
用法:模板文件
- 创建模板文件
$ cd generators
$ cd app
$ mkdir templates
$ cd templates
$ touch template.txt
内部可以使用EJS语法
我是测试模板文件<%= title %>
- 编写
generators/app/index.js核心文件
const Generator = require("yeoman-generator");
module.exports = class extends (
Generator
) {
writing() {
// 通过模板方式写入文件到目标目录
// 模板文件目录
const tmpl = this.templatePath("template.txt");
// 输出目标路径
const output = this.destinationPath("test-template.txt");
// 模板数据上下文
const context = {
title: "我是标题",
// success: false,
};
this.fs.copyTpl(tmpl, output, context);
}
};
- 当前项目运行
yoe run gxrtestdemo
create test-template.txt
我是测试模板文件我是标题
用法:接受用户输入
- 创建模板文件
$ cd generators
$ cd app
$ mkdir templates
$ cd templates
$ touch input.txt
接受用户输入的name <%= name %>
- 编写
generators/app/index.js核心文件
const Generator = require("yeoman-generator");
module.exports = class extends (
Generator
) {
prompting() {
// Yeoman在询问用户环节会自动调用此方法
// 在此方法中可以调用父类 的prompt()方法发出对用户的命令的询问
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;
});
}
writing() {
// 通过模板方式写入文件到目标目录
// 模板文件目录
const tmpl = this.templatePath("input.txt");
// 输出目标路径
const output = this.destinationPath("test-input.txt");
// 模板数据上下文
const context = this.answers;
this.fs.copyTpl(tmpl, output, context);
}
};
- 当前项目运行
yoe run gxrtestdemo
? your project name (generator gxrtestdemo) gxrtestdemo1231231
create test-input.txt
接受用户输入的name:generator gxrtestdemo1231231
发布generator
- 当前项目目录
// 忽略`node_modules`的提交
$ echo node_modules > .gitignore
// 初始化仓库
$ git init
// 暂存代码
$ git add ./
// 提交代码到本地仓库
$ git commit -m '提交代码'
// 关联远程仓库
$ git remote add origin 远程github仓库
// 提交代码
$ git push origin master
// 查看当前镜像源
$ npm config get registry
https://registry.npm.taobao.org/
// 发布代码
$ npm publish
结果401 Unauthorized - PUT https://registry.npm.taobao.org/generator-gxrtestdemo - [unauthorized] Login first
说明:淘宝镜像源是可读镜像源,不可像上传入代码。必需使用官方经镜像源
// 切换镜像源
$ npm config set registry http://www.npmjs.org
// 查看当前镜像源
$ npm config get registry
http://www.npmjs.org/
// 发布代码
$ npm publish
+ generator-gxrtestdemo@1.0.0
- 说明:npm publish 发布到仓库必需有github用户,如果没有就去创建一个github注册
- 淘宝镜像源是可读镜像源,发布代码需要替换设置npm镜像源是npm官网镜像源
- 如果
generator要在官方的仓库列表中出现,需要在项目名称中添加yeoman-的keywords,对应package.json中的配置项目。- 以上用法只是在生成器文件中使用了
prompting事件方法,还有其他特殊的事件方法,按照优先级排序:
- initializing - 初始化开始
- prompting - 调用this.prompt()与用户产生交互
- configuring - 创建配置文件(package.json,config.js等)
- default - 方法都不匹配这些优先级时,就会是default优先级(自定义方法会被划入default)
- writing - 创建项目文件
- conflicts - 文件创建中产生冲突的处理
- install - 调用(npm, bower)包install
- end - 结束项目初始化 其他自定义方法在configuring和writing按顺序优先级调用