开发脚手架及封装自动化构建工作流
一、谈谈你对工程化的初步认识,结合你之前遇到过的问题说出三个以上工程化能够解决问题或者带来的价值。
初步认识:所谓工程化是指遵循一定的标准和规范通过工具提高效率的一种手段,一切以提高效率、降低成本、质量保证为目的的手段都属于工程化。
解决的问题:
1.重复的机械工作,比如部署上线前需要手动压缩代码及资源文件,部署过程需要手动上传代码到服务器。
2.团队开发时,很难做到风格统一,保证质量的完成需求开发
3.部分功能需要等待后端服务接口完成以后才可以进行开发
4.无法使用模块化或组件化组织代码
二、你认为脚手架除了为我们创建项目结构,还有什么更深的意义?
脚手架可以帮我们快速生成项目,创建项目基础结构。不仅是创建项目基础结构,更重要的是给开发者提供一种约束和规范,例如:相同的组织结构,相同的代码开发范式、相同的模块依赖、相同的工具配置,相同的基础代码。更加利于代码维护与团队开发。
三、概述脚手架实现的过程,并使用 NodeJS 完成一个自定义的小型脚手架工具
工作原理就是:在启动的时候,会询问一些预设的问题,然后将回答的结果与模板文件生成项目结构
(1)创建目录 ZYJ-DEMO
(2)创建 package.json //yarn init
(3)在package.json中添加bin字段,指定cli文件的入口文件: “bin”:“cli.js”
{
"name": "zyj-demo",
"version": "1.0.0",
"bin":"cli.js",
"main": "index.js",
"license": "MIT"
}
(4)安装所需依赖 yarn add inquirer //询问; add ejs //添加模板引擎
(5)创建cli.js文件
#!/usr/bin/env node
// NODE CLI 应用入口文件必须要有这样的文件名
// console.log('cli,working~~~') //测试
/**
* 脚手架的工作流程
* 1、通过命令行交互询问用户问题
* 2、根据用户回答的结果生成文件
*/
const path = require('path')
const inquirer = require('inquirer')
const fs = require('fs')
const ejs = require('ejs')
inquirer.prompt([
{
type: 'input',
name: 'name',
message: 'Project name?'
}
]).then(anwsers => {
// console.log(anwsers) // { name: 'myName' }
// 根据用户回答的结果生成文件
//模板目录
const temDir = path.join(__dirname,'templates')
//目标目录
const destDir = process.cwd()
fs.readdir(temDir,(err,files)=>{
if (err) throw err
files.forEach(file => {
// console.log(file)
//通过模板引擎渲染文件
ejs.renderFile(path.join(temDir,file),anwsers,(err,result) => {
if(err) throw err
fs.writeFileSync(path.join(destDir,file),result)
})
});
})
})
(6)templates/index.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>
</body>
</html>
(7)yarn link关联到全局变量
(8)执行测试
!!!!尝试使用 Gulp 完成项目的自动化构建
(1)准备工作
mkdir my-gulp
cd my-gulp
yarn init --yes //初始化package文件
(2)安装gulp //yarn add gulp --dev //安裝gulp模块
(3)创建gulpfile.js文件
// gulpfile.js
//gulp的入口文件
//导入文件路径API
const { dest, src,series,parallel,watch } = require('gulp')
const loadPlugins = require('gulp-load-plugins')
const browserSync = require('browser-sync')
const plugin = new loadPlugins()
const bs = browserSync.create()
const data = {
menus: [
{
name: 'Home',
icon: 'aperture',
link: 'index.html'
},
{
name: 'Features',
link: 'features.html'
},
{
name: 'About',
link: 'about.html'
},
{
name: 'Contact',
link: '#',
children: [
{
name: 'Twitter',
link: 'https://twitter.com/w_zce'
},
{
name: 'About',
link: 'https://weibo.com/zceme'
},
{
name: 'divider'
},
{
name: 'About',
link: 'https://github.com/zce'
}
]
}
],
pkg: require('./package.json'),
date: new Date()
}
const clean = () => {
return del(['dist', 'temp'])
}
const style = () => {
/**
* 但是并没有与src一样的路径。所以需要指定 {base:'src'}
*/
return src('src/assets/styles/*.scss', { base: 'src' }).pipe(plugin.sass())
.pipe(dest('dist'))
}
const script = () => {
return src('src/assets/scripts/*.js', { base: 'src' }).pipe(plugin.babel({
presets: ['@babel/preset-env']
}))
.pipe(dest('dist'))
}
const page = () => {
return src("src/*.html", { base: 'src' }).pipe(plugin.swig({data})).pipe(dest('dist'))
}
const image = () => {
return src("src/assets/images/**", { base: 'src' }).pipe(plugin.imagemin()).pipe(dest('dist'))
}
const fonts = () => {
return src("src/assets/fonts/**", { base: 'src' }).pipe(plugin.imagemin()).pipe(dest('dist'))
}
const extra = () => {
return src("public/**", { base: 'public' }).pipe(dest('dist'))
}
const serve = () => {
watch("src/assets/styles/*.scss",style)
watch("src/assets/scripts/*.js",script)
watch("src/*.html",page)
// watch("src/assets/images/**",image)
// watch("src/assets/fonts/**",fonts)
// watch("public/**",extra)
watch([
'src/assets/images/**',
'src/assets/scripts/*.js',
'src/*.html'
],bs.reload)
bs.init({
server: {
port:8080,
// baseDir: 'dist',
baseDir:["dist","public","src"],
files:'dist/**',
// open:false,
routes: {
'/node_modules': "node_modules"
}
}
})
}
const compile = parallel(page, script)
//上线之前执行的任务
const build = parallel(compile,fonts,image,extra)
const develop = series(compile,serve)
module.exports = {
clean,
compile,build,develop
}
(4)package.json
{
"name": "zce-gulp-demo",
"version": "1.0.0",
"main": "index.js",
"repository": "https://github.com/zce/zce-gulp-demo.git",
"author": "张艳杰0310 <1628480502@qq.com>",
"license": "MIT",
"scripts": {
"clean":"gulp clean",
"build":"gulp build",
"develop":"gulp develop"
},
"devDependencies": {
"@babel/core": "^7.10.4",
"@babel/preset-env": "^7.10.4",
"bootstrap": "4.0.0-alpha.6",
"browser-sync": "^2.26.7",
"gulp": "^4.0.2",
"gulp-babel": "^8.0.0",
"gulp-clean-css": "^4.3.0",
"gulp-htmlmin": "^5.0.1",
"gulp-if": "^3.0.0",
"gulp-imagemin": "^7.1.0",
"gulp-load-plugins": "^2.0.3",
"gulp-rename": "^2.0.0",
"gulp-swig": "^0.9.1",
"gulp-uglify": "^3.0.2"
}
}