前端工程化
前端工程化概述
定义和解决的问题
是指遵循一定的标准和规范,通过工具去提高效率,降低成本的一种手段。通过模块化去提高项目的可维护性,运行环境不能被支持
解决的问题:
部署上线前亚索代码以及资源文件
手动上传部署代码到服务器
多人协同开发时,无法硬性统一大家的代码风格,从仓库拉下来的代码质量无法保证
项目中工程化的表现
一切以提高效率,降低成本,质量保证为目的的手段都属于工程化
一切重复的工作都应该被自动化
工程化不等于工具
类似于,不是有了webpack就代表了工程化。工具不是工程化的核心,工程化代表了对项目的规划和架构。工具只是实现架构的一项手段。
是由node.js强力驱动的
脚手架工具
概要
就是自动的创建项目基础文件的工具,提供项目规范和约定,解决创建项目的过程中那些复杂的工作。
Yeoman
是一种高效、开源的 Web 应用脚手架搭建系统,支持使用各种不同的工具和接口协同优化项目的生成
是一种广泛的脚手架工具,不同于vue-cli这种专注某一项技术的工具
安装Yeoman
yarn global add yo
单有Yeoman是无法正常使用的,需要搭配特定的generator去使用。
yarn global add generator-node
通过yeoman提供的yo命令运行刚才实现的generator-node
安装 yo node
发现报错yo不是内部文件之类的错误,yarn没有安装成功,所以换了种方式。
cnpm install -g yo
cnpm install -g generator-node
新建文件夹之后运行yo node搭建脚手架
文件夹内部生成的一系列目录文件
sub generator
通过生成器生成基本的配置文件,提高开发效率
通过generator-node的子集生成器cli,生成cli应用所需要的文件,这些文件都有一些基础代码,自己手动去配很容易配错
将模块变成cli应用
yo node:cli
重写了package.json,创建了cli.js文件
通过yarn link到全局范围
通过模块名去运行刚才的模块
cli --help
报错cli不是内部也不是外部命令,这时候需要配置环境变量
找到yo在npm或者yarn下的yo.cmd等
有的在C盘,有的在其他node安装下的npm内部,我的就是安装在node下的
cli --help
此时就会正常工作了
macbookpro
command+shift+. 显示所有隐藏文件夹
sudo npm install - yo
sudo npm install -g generator-node
yo node
yo node:cli
npm link
sudo test --help
Yeoman使用步骤
自定义generator
创建generator模块
实际上就是创建一个npm模块
Yeoman的generator模块名称是generator-的格式
yarn init创建 package.json
安装yeoman-generator的模块,提供一些工具函数去创建生成器的时候更加便捷
sudo yarn init
//报错:requires yeoman-environment at least 3.0.0-beta.1解决方案
sudo yarn add yeoman-generator@4.0.0
generators/app/index.js
//此文件作为generator的核心入口
//需要倒入一个继承自Yeoman Generator的类型
//Yeoman Generator在使用时会自动调用我们在此类型中定义的一些生命周期方法
//我们在方法中需要可以通过调用父类提供 的一些工具方法来实现一些功能,例如文件写入
const Generator = require('yeoman-generator')
module.exports = class extends Generator{
writing() {
//Yeoman自动生成文件调用此方法
//尝试往项目里写入文件
this.fs.write(
//生成项目目录下文件的绝对路径
this.destinationPath('temp.txt'),
//写入的内容
Math.random().toString()
)
}
}
sudo npm link
新建文件夹 my-pro
cd my-pro
yo sample
根据模板创建文件
app下新建templates/fjs.txt,随便写入内容
这是个模版文件
内部可以使用EJS模版输出数据
例如<%= title %>
其他的EJS也支持
<%if(success){%>
...
<%}%>
修改index.js文件
//此文件作为generator的核心入口
//需要倒入一个继承自Yeoman Generator的类型
//Yeoman Generator在使用时会自动调用我们在此类型中定义的一些生命周期方法
//我们在方法中需要可以通过调用父类提供 的一些工具方法来实现一些功能,例如文件写入
const Generator = require('yeoman-generator')
module.exports = class extends Generator{
writing() {
//Yeoman自动生成文件调用此方法
//尝试往项目里写入文件
// this.fs.write(
// //生成项目目录下文件的绝对路径
// this.destinationPath('temp.txt'),
// //写入的内容
// Math.random().toString()
// )
//有了fjs.txt上面的代码就可以注视掉了
//通过模版引擎方写入文件到目录
//三个参数:模版文件的路径,输出文件的路径,模版文件的上下文
const tmpt = this.templatePath('fjs.txt')
//输出路径
const output = this.destinationPath('fjs.txt')
//模版文件的上下文
const context = {title:'Hello world', success:false }
//自动将模版文件映射到输出文件上
this.fs.copyTpl(tmpt, output, context)
}
}
cd my-pro
yo sample
新建了一个fjs.txt文件
相对于手动创建文件,模版的方式大大提高了效率
动态接收用户输入数据
通过命令行交互,得到数据
templates下新增bar.html
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>表单标签</title>
</head>
<body>
<form method="post">
<label for="username">用户名:</label>
<input type="text" name="username" id="username" value="" />
<br/>
<label for="pass">密 码:</label>
<input type="password" name="pass" id="pass" value="" />
<input type="submit" value="确定" name="submit" />
<input type="reset" value="重置" name="reset" />
</form>
</body>
</html>
修改index.js文件
//此文件作为generator的核心入口
//需要倒入一个继承自Yeoman Generator的类型
//Yeoman Generator在使用时会自动调用我们在此类型中定义的一些生命周期方法
//我们在方法中需要可以通过调用父类提供 的一些工具方法来实现一些功能,例如文件写入
const Generator = require('yeoman-generator')
module.exports = class extends Generator{
prompting() {
//Yeoman在询问用户环节会调用此方法
//此方法可以调用promt()方法发出对用户命令行进行询问
return this.prompt([//返回promise,拥有更好的异步流程控制
{
type:'input',//询问类型
name:'name',
message:'Your project name',//询问内容
default:this.appname//项目生成的目录名称
}
]).then(answers=> {
this.answers = answers
})
}
writing() {
//Yeoman自动生成文件调用此方法
//尝试往项目里写入文件
// this.fs.write(
// //生成项目目录下文件的绝对路径
// this.destinationPath('temp.txt'),
// //写入的内容
// Math.random().toString()
// )
//有了fjs.txt上面的代码就可以注视掉了
//通过模版引擎方写入文件到目录
//三个参数:模版文件的路径,输出文件的路径,模版文件的上下文
const tmpt = this.templatePath('bar.html')
//输出路径
const output = this.destinationPath('bar.html')
//模版文件的上下文
const context = this.answers//{title:'Hello world', success:false }
//自动将模版文件映射到输出文件上
this.fs.copyTpl(tmpt, output, context)
}
}
Vue Generator案例
新建文件夹
generator开头
generator-vue
sudo yarn init
sudo yarn add yeoman-generator@4.0.0
新建
generators/app/templates
将整个Vue脚手架考入进去
并修改README.md ,package.json,public/index.html
<%= name %>
“name”: “<%= name %>”,
generators/app/index.js
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 => {
this.answers = answers
})
}
writing() {
//将每一个文件都通过模版转换成目标路径
//通过循环的方式批量生成每一个文件
const templates = [
'public',
'src/api',
'src/assets',
'src/components',
'src/mock',
'src/plugins',
'src/utils',
'src/views',
'src/App.vue',
'src/element-variables.scss',
'src/main.js',
'src/permission.js',
'src/router.js',
'src/store.js',
'.browserslistrc',
'.gitignore',
'babel.config.js',
'package.json',
'package-lock.json',
'postcss.config.js',
'README.md',
'remark.txt',
'vue.config.js',
'yarn.lock'
]
templates.forEach(item =>{
this.fs.copyTpl(
this.templatePath(item),
this.destinationPath(item),
this.answers
)
})
}
}
当前文件夹下
sudo npm link
新建文件夹
yo vue
发布generator
Generator就是npm
发布Generator就是发布一个npm模块
将项目的源代码托管到一个公开的仓库里
generator-cjg-vue
echo node_modules > .gitignore
git init
git status
git add .
git commit -m ‘first commit’
git remote add origin https://github.com/xiaodashi12/generator-vue.git
git push -u origin master
git config --global core.quotepath
yarn publish --registry=https://registry.yarnpkg.com
脚手架的工作原理
脚手架工具是基于node开发的cli应用
新建文件夹 sample-scaff
#!/usr/bin/env node
//node cli应用入口必须要有这样的文件夹
//如果是linux或者mac系统还要修改文件的读写权限755
//具体就是通过chmod 755cli.js或者chmod u+x *.js实现修改
console.log("cli working")
//脚手架工作过程
//1、通过命令行交互询问用户问题
//2、根据用户的回答结果生成文件
//命令行询问引入inquirer模块
//sudo yarn add inquirer
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(answers=>{
//根据用户的回答生成文件
//模版目录
const tmplDir = path.join(__dirname, "templates")
//目标目录
const destDir = process.cwd()
//将模版下的文件全部输出到目标目录
fs.readdir(tmplDir, (err, files)=>{
if(err) throw err
files.forEach(file=>{
//通过模版引擎渲染对应的文件
ejs.renderFile(path.join(tmplDir, file), answers, (err, result)=>{
if(err) throw err
//将结果写入目标文件路径
fs.writeFileSync(path.join(destDir, file), result)
})
console.log(file)
})
})
console.log(answers)
})
sudo yarn init
sudo yarn link
chmod u+x *.js
sample-scaff
sudo yarn add inquirer
sudo yarn add ejs
sample-scaff
mkdir demo
cd demo
sample-scaff