大前端【2-1练习】开发脚手架及封装自动化构建工作流
简答题
1、谈谈你对工程化的初步认识,结合你之前遇到过的问题说出三个以上工程化能够解决问题或者带来的价值。
答:
初步认识:所谓工程化是指遵循一定的标准和规范通过工具提高效率的一种手段,一切以提高效率、降低成本、质量保证为目的的手段都属于工程化。
解决的问题:
(1)重复的机械工作,比如部署上线前需要手动压缩代码及资源文件,部署过程需要手动上传代码到服务器。
(2)团队开发时,很难做到风格统一,保证质量的完成需求开发
(3)部分功能需要等待后端服务接口完成以后才可以进行开发
(4)无法使用模块化或组件化组织代码
2、你认为脚手架除了为我们创建项目结构,还有什么更深的意义?
脚手架可以帮我们快速生成项目,创建项目基础结构。不仅是创建项目基础结构,更重要的是给开发者提供一种约束和规范,例如:相同的组织结构,相同的代码开发范式、相同的模块依赖、相同的工具配置,相同的基础代码。更加利于代码维护与团队开发。
编程题
1、概述脚手架实现的过程,并使用 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 //询问
yarn 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关联到全局变量
yarn link
(8)执行测试
mkdir test //创建测试文件夹
cd test //切换文件夹
ZYJ-DEMO //执行脚手架
2、尝试使用 Gulp 完成项目的自动化构建
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"
}
}
3、使用 Grunt 完成项目的自动化构建
grunt自动化构建
(1)准备工作
mkdir my-grunt
cd my-grunt
yarn init --yes //初始化package文件
(2)安装gulp
yarn add grunt --dev //安裝gulp模块
(3)安装所需插件
//將sass转化为浏览器可识别的css文件
yarn add grunt-sass sass -dev
//将ECMAScript新特性转化
yarn add grunt-babel @babel/core @babel/preset-env --dev
//自动载入文件
yarn add load-grunt-tasks --dev
//监视文件变化
yarn add grunt-contrib-watch --dev
//清除指定文件夹下的文件
yarn add grunt-contrib-clean --dev
//浏览器
yarn add browser-sync --dev
//html文件编译处理
yarn add grunt-web-swig --dev
(3)创建gruntfile.js文件
//Grunt的入口文件
//用于定义一些需要Grunt自动执行的任务
//需要导出一个函数,接收一个grunt的参数
/**
* yarn add grunt-contrib-clean
* 自动清除临时文件
*/
const sass = require("sass")
const loadGruntTasks = require("load-grunt-tasks")
const browserSync = require("browser-sync")
const bs = browserSync.create()
module.exports = grunt => {
grunt.initConfig({
//sass转化为css功能
sass: {
options: {
sourceMap: true, //设置后会生成相应的sourceMap文件
implementation: sass
},
main: {
files: {
// 目标文件:源文件
'dist/css/main.css': 'src/scss/main.scss'
}
}
},
//js转化功能
babel: {
options: {
sourceMap: true,//设置后会生成相应的sourceMap文件
presets: ["@babel/preset-env"]
},
main: {
files: {
// 目标文件:源文件
'dist/js/app.css': 'src/js/app.js'
}
}
},
web_swig: {
options: {
swigOptions: {
//缓存设置为false
cache: false
},
getData: function (tpl) {
//模板文件的数据
return { myGruntTitle: 'hello,grunt-web-swig' };
}
},
main: {
expand: true,
cwd: 'src/',//源文件文件夹
src: "**/*.html",//后缀名匹配
dest: "dist/"//目标文件夹
},
},
//监视功能
watch: {
js: {
//文件地址
files: ['src/js/*.js'],
//执行的任务
tasks: ['babel']
},
css: {
//文件地址
files: ['src/scss/*.scss'],
//执行的任务
tasks: ['sass']
},
html: {
//文件地址
files: ['src/*.html'],
//执行的任务
tasks: ['web_swig', 'bs-reload']
}
},
//清除功能
clean: {
//所要清除的文件路径
files: 'dist/**'
}
})
// grunt.loadNpmTasks('grunt-sass')
loadGruntTasks(grunt) //自动加载所有的grunt插件
grunt.registerTask('default', ['clean', 'sass', 'babel', 'watch'])
grunt.registerTask('bs-reload', function () {
bs.reload()
})
grunt.registerTask('bs', function () {
const done = this.async()
bs.init({
server: {
port: 8080,
// baseDir: 'dist',
baseDir: ["dist", "public", "src"],
files: 'dist/**',
// open:false,
routes: {
'/node_modules': "node_modules"
}
}
})
})
grunt.registerTask('compile', ['clean', 'sass', 'babel'])
}
(4)package.json
将命令通过scripts进行暴露,例如:可以直接“yarn clean”进行文件的清除
{
"name": "my-grunt",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"scripts": {
// yarn clean ---->清除dist文件夹
"clean":"grunt clean",
// yarn compile ---->编译
"compile":"grunt compile",
//yarn reload ----->重载
"reload":"grunt bs-reload"
},
"dependencies": {
"@babel/core": "^7.10.4",
"@babel/preset-env": "^7.10.4",
"grunt": "^1.2.1",
"grunt-babel": "^8.0.0",
"grunt-sass": "^3.1.0"
},
"devDependencies": {
"browser-sync": "^2.26.7",
"grunt-contrib-clean": "^2.0.0",
"grunt-contrib-watch": "^1.1.0",
"grunt-tasks": "^1.0.0",
"grunt-web-swig": "^0.3.1",
"load-grunt-tasks": "^5.1.0",
"sass": "^1.26.10"
}
}
本文地址:https://blog.csdn.net/qiuqiu1628480502/article/details/107290004