1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > JavaScript性能优化-脚手架工具及自动化构建(12)

JavaScript性能优化-脚手架工具及自动化构建(12)

时间:2018-10-11 04:48:06

相关推荐

JavaScript性能优化-脚手架工具及自动化构建(12)

Part2 · 前端工程化实战

JavaScript性能优化-工具及代码优化

文章说明:本专栏内容为本人参加【拉钩大前端高新训练营】的学习笔记以及思考总结,学徒之心,仅为分享。如若有误,请在评论区支出,如果您觉得专栏内容还不错,请点赞、关注、评论。共同进步!

上一篇:【JavaScript性能优化-工具及代码优化】

本篇主要内容是前端脚手架工具及自动化构建

超长文、多图预警!!!超长文、多图预警!!!

一、脚手架工具

脚手架的本质作用:创建项目基础结构、提供项目规范和约定

相同的组织架构相同的开发范式相同的模块依赖相同的工具配置相同的基础代码

二、前端脚手架

1.内容概要

脚手架的作用常用的脚手架工具通用脚手架工具剖析开发一款脚手架

2.常用的脚手架

React.js项目–>create-react-appVue.js项目–>vue-cliAngular项目–>angular-cliYeomanPlop

3.Yeoman基本使用

在全局范围安装yo

npm install yo --global # or yarn global add yo

安装对应的generator

npm install generator-node --global # or yarn global add generator-node

通过yo运行generator

cd project-dirmkdir my-moduleyo node

4.Yeoman Sub Generator

常规使用步骤:

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

Sub Generator使用示例:yo node:cli

使用yo node:cli命令安装yarn link引导全局使用my-module --help查看

5.创建Generator模块

Generator本质上就是一个NPM模块

Generator模块需求:名称必须为generator-

基本使用步骤

命令行内容

mkdir generator-sample # 创建项目目录cd generator-sampleyarn init #初始化项目yarn add yeoman-generator # 安装依赖

根据模板创建文件

进入generator-sample,创建目录generators进入generators创建index.js

编写index.js

// 此文件作为 Generator 的核心入口// 需要导出一个继承自 Yeoman Generator 的类型// Yeoman Generator 在工作时会自动调用我们在此类型中定义的一些生命周期方法// 我们在这些方法中可以通过调用父类提供的一些工具方法实现一些功能,例如文件写入const Generator = require('yeoman-generator')module.exports = class extends Generator {// Yeoman 自动在生成文件阶段调用此方法// 我们这里尝试往项目目录中写入文件writing () {this.fs.write(this.destinationPath('temp.text'),Math.random().toString())}}

命令行运行

yarn link # 将模块包引至全局cd .. # 切回上级目录mkdir my-projectcd my-projectyo sample # 运行yo sample命令,查看生成的文件temp.txt

进阶使用步骤

上述过程中除index.js文件内容不同,其余都相同

// 此文件作为 Generator 的核心入口// 需要导出一个继承自 Yeoman Generator 的类型// Yeoman Generator 在工作时会自动调用我们在此类型中定义的一些生命周期方法// 我们在这些方法中可以通过调用父类提供的一些工具方法实现一些功能,例如文件写入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 () {// Yeoman 自动在生成文件阶段调用此方法// // 我们这里尝试往项目目录中写入文件// this.fs.write(// this.destinationPath('temp.txt'), // 文件绝对路径// Math.random().toString()// )// -------------------------------------------------------// // 通过模板方式写入文件到目标目录// // 模板文件路径// const tmpl = this.templatePath('foo.txt')// // 输出目标路径// const output = this.destinationPath('foo.txt')// // 模板数据上下文// const context = { title: 'Hello zce~', success: false }// this.fs.copyTpl(tmpl, output, context)// -------------------------------------------------------// 模板文件路径const tmpl = this.templatePath('bar.html')// 输出目标路径const output = this.destinationPath('bar.html')// 模板数据上下文const context = this.answersthis.fs.copyTpl(tmpl, output, context)}}

6.Plop使用

官方简介:

我喜欢把Plop称为“微型发电机框架”。现在,我称其为“小工具”,因为它为您提供了一种以一致的方式生成代码或任何其他类型的纯文本文件的简单方法。您会看到,我们都在代码中创建了结构和模式(路由,控制器,组件,帮助程序等)。这些模式会随着时间的推移而变化和改进,因此当您需要在此处创建新的模式插入名称时,在代码库中查找代表当前“最佳实践”的文件并不总是那么容易。那就是挽救您的地方。使用plop,您将拥有在code中创建任何给定模式的“最佳实践”方法。可以通过输入plop轻松地从终端运行代码。这不仅使您免于在代码库中四处寻找要复制的正确文件,而且还使“正确的方式”变成了“创建新文件的最简单的方式”。

React项目中使用plop步骤

项目初始结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dhLtMGaC-1606035018990)(%E6%93%B7%E5%8F%96-1605681121108.JPG)]

安装plop至开发环境中

yarn add plop --dev

在项目根目录中创建plopfile.js文件,并编写以下代码

// Plop入口文件,需要导出一个函数// 此函数接受一个plop对象,用于创建生成器任务module.exports = plop => {plop.setGenerator('component', {description: 'Create a component',prompts: [{type: 'input', // 问题的输入方式name:'name', // 问题返回值的键message: 'Component name:', // 屏幕上给出的提示default: 'MyComponent', // 问题的默认答案}],actions: [{type: 'add', // 添加一个全新的文件path: 'src/components/{{name}}/{{name}}.js', // 添加文件的存放位置templateFile: 'plop-templates/component.hbs', // 模板文件的位置}]})}

创建plop-templates目录,在其中添加模板文件component.hbs,内容如下:

import React from 'react'export default () => {<div className="{{name}}"><h1>{{name}}</h1></div>}

命令行运行

yarn plop component # component是我们在plop中plop.setGenerator中的第一个参数yarn run v1.22.10$ F:\\Others\important\lagou\02-01-study-materials\code\02-01-02-05-react-app\node_modules\.bin\plop component? Component name: Footer√ ++ \src\components\Footer\Footer.jsDone in 3.79s.

至此我们就可以在src/components中看到我们生成的Footer目录,其中文件为Footer.js

三、自动化构建工具

1.自动化构建初体验

项目结构:

我们使用sass使编写css提高效率,但需要对sass进行编译。

yarn init --yes # 初始化项目目录yarn add sass --dev # 在开发环境安装sassyarn add browser-sync --dev # 在开发环境安装browser-syncyarn add npm-run-all --dev # 在开发环境安装npm-run-all用来运行所有script

编辑package.json文件:

{"name": "my-web-app","version": "0.1.0","main": "index.js","author": "zce <w@zce.me> (https://zce.me)","license": "MIT","scripts": {"build": "sass scss/main.scss css/style.css --watch", "serve": "browser-sync . --files \"css/*.css\"","start": "run-p build serve"},"devDependencies": {"browser-sync": "^2.26.7","npm-run-all": "^4.1.5","sass": "^1.29.0"}}

命令行运行:

yarn start

自动执行:

yarn build

yarn browser-sync

2.常用的自动化构建工具

在这里插入图片描述

为什么要使用自动化构建工具:

一句话:自动化。对于需要反复重复的任务,例如压缩(minification)、编译、单元测试、linting等,自动化工具可以减轻你的劳动,简化你的工作。

2.1Grunt

Grunt 生态系统非常庞大,并且一直在增长。由于拥有数量庞大的插件可供选择,因此,你可以利用 Grunt自动完成任何事,并且花费最少的代价。如果找不到你所需要的插件,那就自己动手创造一个 Grunt 插件,然后将其发布到 npm 上吧。

由于其工作过程是基于临时文件的,所以构建的速度相对较慢,频繁的磁盘读写导致速度慢

2.2Gulp

gulp 将开发流程中让人痛苦或耗时的任务自动化,从而减少你所浪费的时间、创造更大价值。

工作过程是基于内存实现的,解决了Grunt的速度问题。默认支持同时去处理多个任务,效率大大提高,使用方式相对于Grunt相对通俗易懂,插件生态也同样完善。个人安利。

2.3FIS

解决前端开发中自动化工具、性能优化、模块化框架、开发规范、代码部署、开发流程等问题

百度团队的工具,捆绑套餐,将很多功能都提供给我们。

3.Grunt使用

3.1 Grunt基本使用

创建空项目grunt-sample

yarn init --yes

安装grunt模块

yarn add grunt --dev

项目根目录添加gruntfile.js文件,并编写以下内容

// grunt入口文件// 用于定义一些需要Grunt自动执行的任务// 需要导出一个函数// 此函数接收一个grtun对象,内部体用一些创建任务时可以用的APImodule.exports = grunt => {// 第二个字符串为任务描述grunt.registerTask('foo','a sample task', () => {console.log('hello grunt');})grunt.registerTask('bar', () => {console.log('other task');})// // default 是默认任务名称// // 通过grunt执行时可以省略任务名// // grunt.registerTask('default', () => {// //console.log('default task');// // })// // 第二个参数可以指定此任务的映射任务// // 这样执行default就相当于执行对应的任务// // 这里的映射的任务会按照顺序一次执行,不会同步执行// grunt.registerTask('default', ['foo', 'bar'])// // 也可以在任务函数中执行其他任务// grunt.registerTask('run-other', () => {//// foo和bar会在当前任务执行完成过后自动依次执行//grunt.task.run('foo', 'bar')//console.log('current task runing');// })// // 默认grunt采用同步模式编码// // 如果需要异步可以使用this.async()方法创建回调函数// // 下面代码不会再settimeout后打印语句// // grunt.registerTask('async-task', () => {// //setTimeout(() => {// // console.log('async task working');// //}, 1000);// // })// // 由于函数体重需要使用this,所以这里不能使用箭头函数grunt.registerTask('async-task', function () {const done = this.async()setTimeout(() => {console.log('async task working');done()}, 1000);})}

命令行运行

yarn grunt # 后面添加任务名或不添加任务名默认执行default

3.2 Grunt标记任务失败

标记任务失败需要在函数体中返回false。默认情况下(yarn grunt default),如果为任务列表,则当前面的任务执行失败后,后续的任务不再执行。如果在yarn grunt default后面添加–force时,则前面任务失败后,强制执行后面的任务yarn grunt default --force。

异步函数中标记当前任务执行失败的方式是为回调函数指定一个 false 的实参

module.exports = grunt => {// 任务函数执行过程中如果返回 false// 则意味着此任务执行失败grunt.registerTask('bad', () => {console.log('bad working~')return false})grunt.registerTask('foo', () => {console.log('foo working~')})grunt.registerTask('bar', () => {console.log('bar working~')})// 如果一个任务列表中的某个任务执行失败// 则后续任务默认不会运行// 除非 grunt 运行时指定 --force 参数强制执行grunt.registerTask('default', ['foo', 'bad', 'bar'])// 异步函数中标记当前任务执行失败的方式是为回调函数指定一个 false 的实参grunt.registerTask('bad-async', function () {const done = this.async()setTimeout(() => {console.log('async task working~')done(false)}, 1000)})}

3.3 Grunt的配置方法

除了grunt.registerTask外,grunt还提供了一个去添加配置选项的API:initConfig

module.exports = grunt => {// grunt.initConfig() 用于为任务添加一些配置选项grunt.initConfig({// 键一般对应任务的名称// 值可以是任意类型的数据foo: {bar: 'baz'}})grunt.registerTask('foo', () => {// 任务中可以使用 grunt.config() 获取配置console.log(grunt.config('foo'))// 如果属性值是对象的话,config 中可以使用点的方式定位对象中属性的值console.log(grunt.config('foo.bar'))})}

3.4 Grunt多目标任务

命令行运行yarn grunt build时,可以同时运行目标任务。如果需要运行指定目标任务,可以使用yarn grunt build:foo命令

module.exports = grunt => {// 多目标模式,可以让任务根据配置形成多个子任务// grunt.initConfig({// build: {//foo: 100,//bar: '456'// }// })// grunt.registerMultiTask('build', function () {// console.log(`task: build, target: ${this.target}, data: ${this.data}`)// })grunt.initConfig({build: {// 任务配置选项,并不会执行options: {msg: 'task options'},foo: {// 会覆盖build中的optionoptions: {msg: 'foo target options'}},bar: '456'}})grunt.registerMultiTask('build', function () {console.log(this.options())})}

3.5 Grunt插件的使用

安装插件gruntfile中载入插件根据文档完成相关的配置选项
grunt sass

项目初始

安装插件grunt-sass以及npm模块sass

yarn add grunt-sass sass --dev

编写gruntfile.js

const sass = require('sass')module.exports = grunt => {grunt.initConfig({sass: {options: {implementation:sass,},main: {files: {'dist/css/main.css': 'src/scss/main.scss' // 键为目标文件路径,值为需要编译的文件}}}})grunt.loadNpmTasks('grunt-sass')}

命令运行后的目录

grunt-babel

初始目录

安装grunt-babel

yarn add grunt-babel @babel/core @babel/preset-env --devyarn add load-grunt-tasks --dev

编辑上面sass中js

const sass = require('sass')const loadGruntTasks = require('load-grunt-tasks')module.exports = grunt => {grunt.initConfig({sass: {options: {sourceMap: true,implementation:sass,},main: {files: {'dist/css/main.css': 'src/scss/main.scss' // 键为目标文件路径,值为需要编译的文件}}},babel: {options: {sourceMap: true,presets: ['@babel/preset-env'] // 最新的ECMAScript中的特性加载进来},main:{files: {'dist/js/app.js': 'src/js/app.js'}}}})// grunt.loadNpmTasks('grunt-sass')loadGruntTasks(grunt) // 自动加载所有的grunt插件中的所有任务}

命令后的目录

grunt-contrib-watch

源文件变化时,实时编译文件

安装grunt-contrib-watch

yarn add grunt-contrib-watch --dev

编辑js文件

const sass = require('sass')const loadGruntTasks = require('load-grunt-tasks')module.exports = grunt => {grunt.initConfig({sass: {options: {sourceMap: true,implementation:sass,},main: {files: {'dist/css/main.css': 'src/scss/main.scss' // 键为目标文件路径,值为需要编译的文件}}},babel: {options: {sourceMap: true,presets: ['@babel/preset-env'] // 最新的ECMAScript中的特性加载进来},main:{files: {'dist/js/app.js': 'src/js/app.js'}}},watch: {js: {files:['src/js/*.js'],tasks: ['babel']},css: {files:['src/scss/*.scss'],tasks: ['sass']}}})// grunt.loadNpmTasks('grunt-sass')loadGruntTasks(grunt) // 自动加载所有的grunt插件中的所有任务grunt.registerTask('default', ['sass', 'babel']) // 确保启动watch瞬间先执行sass任务和babel}

监听文件时terminal的状态:

3.6 Grunt总结

4.Gulp使用

当下最流行的前端构建系统,其核心特性就是高效、易用。现在项目中安装gulp开发依赖。添加gulpfile.js,用于编写需要gulp自动执行的任务。随后可以再命令行使用gulp提供cli工具运行构建任务。

4.1 Gulp的基本使用

初始化项目目录

mkdir gulp-test # 创建项目目录cd gulp-test # 切换目录yarn init --yes # 初始化目录yarn add gulp --dev # 安装gulp到开发环境

根目录创建gulpfile.js文件

// gulp入口文件// 导出函数成员exports.foo = () => {console.log('foo task working~');}

通过命令行运行任务

yarn gulp foo# [22:23:50] Using gulpfile D:\DeskTop\02-01-study-materials\gulp-test\gulpfile.js# [22:23:50] Starting 'foo'...# foo task working~# [22:23:50] The following tasks did not complete: foo# [22:23:50] Did you forget to signal async completion?# error Command failed with exit code 1.# info Visit /en/docs/cli/run for documentation about this command.

The following tasks did not complete: foo,foo任务未完成,因为最新的gulp中取消了同步代码运行模式,默认约定为异步任务,任务执行完成后,需要调用回调函数或其他方式去标记这个任务表示完成。这里我们手动的调用回调函数。

// gulp入口文件// 导出函数成员exports.foo = done => {console.log('foo task working~');done() // 表示任务完成}exports.default = done => {console.log('default task working~');done() // 标记任务完成}

此时foo任务会正常启动,正常结束。此时我们直接运行yarn gulp,他会自动运行default任务,同grunt一样。除此之外,gulp4.0前,注册gulp任务需要通过gulp模块中的方法来实现,具体来看:

const gulp = require('gulp')gulp.task('bar',done => {console.log('bar task working~')})

4.2 Gulp的组合使用

glup中需要使用到并行任务和串行任务,在我们项目过程中,编译scss文件和js文件是不冲突的,所以我们需要使用并行任务。而我们在编译文件和部署服务时,我们需要先进行编译scss和css文件,然后进行服务部署,这时候需要使用串行任务。在glup中提供了两个API serires以及parallel,分别提供串行和并行任务。

const {series, parallel} = reqire(‘gulp’)const task1 = done => {SetTimeout(() => {console.log(‘task1 working~’)done()}, 1000)}const task2 = done => {SetTimeout(() => {console.log(‘task2 working~’)done()}, 1000)}const task3 = done => {SetTimeout(() => {console.log(‘task3 working~’)done()}, 1000)}exports.foo = series(task1, task2, task3) // 执行串行任务exports.bar = parallel(task1, task2, task3) // 执行并行任务

yarn gulp foo # 此时三个任务会依次等待1秒后执行console.log()方法yarn gulp bar # 此时三个任务会同时开始,在1秒后同时执行conssole.log()方法。

4.3 Gulp的异步任务

gulp中的任务都是异步任务,也就是我们经常提到的一部函数。我们调用一个异步函数时是没有办法去直接明确这个调用是否完成的。都是在函数内部通过回调或者事件去通知外部这个函数是否调用完成。在异步任务中,同样面临如何去通知gulp任务的完成情况。上面我们使用同步任务done()来模仿异步任务。

// 通过同步任务进行模拟exports.call ask = done => {console.log(‘callback task’)done()}// 同步任务失败情况export.callback_error = done => {console.log(‘callback_error task’)done(new Error(‘callback_error task failed!’))}// 使用promise去完成异步任务exports.promise = () => {console.log(‘promise task~’)return Promise.resolve() // 标记promise任务完成}// promise任务失败情况exports.promise_error = () => {console.log(‘promise_error task’)return Promise.reject(new Error(‘promise_error failed!’))}// 使用ES7中提供的async和await语法糖const timeout = time => {return new Promise(resolve => {setTimeout(resolve, time)})}exports.async = async () => {await timeout(1000)console.log(‘async task~’)}// 使用streamconst {doesNotMatch } = require('assert')const fs = require('fs')exports.stream = () => {const read = fs.createReadStream('yarn.lock')const write = fs.createWriteStream('a.txt')read.pipe(write)return read}// 模仿streamexports.stream_copy = done => {const read = fs.createReadStream('yarn.lock')const write = fs.createWriteStream('b.txt')read.pipe(write)read.on('end', () => {done()})}

4.4 Gulp构建过程核心工作原理

构建过程大多数都是将文件读取然后进行一些转换,最后写入另外一个位置。

这里我们模拟压缩css到吗为min.css的过程,主要分为以下几个步骤:

创建文件读取流-目标css创建文件写入流-目标min.css文件转换流,将读取的文件流使用replace进行替换空白字符与注释使用pipe将文件流先转换,然后再讲转换流写入

具体代码如下:

const fs = require('fs')const {Transform} = require('stream')exports.default = () => {// 文件流读取const readStream = fs.createReadStream('normalize.css')// 写入文件流const writeStream = fs.createWriteStream('normalize.min.css')// readStream.pipe(writeStream)//// return readStream// 文件流转换const transformStream = new Transform({// 核心转换过程transform: (chunk, encoding, callback) => {const input = chunk.toString()const output = input.replace(/\s+/g, '').replace(/\/\*.+?\*\//g, '')callback(null, output) // 第一个参数为错误对象,output为转换完的结果}})return readStream.pipe(transformStream) // 先转换.pipe(writeStream) // 再写入}

4.5 Gulp文件操作API

Gulp中为我们提供读取流和写入流 的API,相比于底层Node的API,Gulp的API更强大、更易用,至于负责文件的转换流,绝大多数情况我们都是通过独立的插件来提供。我们在实际去通过Gulp创建构建任务时的流程就是:先通过src方法去创建一个读取流,然后再借助插件提供的转换流来实现文件加工,最后我们再通过Gulp提供的dest方法去创建一个写入流,从而写入到目标文件。具体工作过程如下:

const {src, dest} = require('gulp')const cleanCSS = require('gulp-clean-css')const rename = require('gulp-rename')exports.default = () => {return src('src/*.css').pipe(cleanCSS()).pipe(rename({extname: '.min.css'})).pipe(dest('dist'))}

4.6 Gulp案例-样式编译

const {src, dest} = require('gulp')// gulp.src:gulp底层是使用的nodejs的stream,首先获取到stream流,然后使用pipe()方法把流数据导入到你想让它去的地方。// gulp.dest:src函数是读取文件,那dest函数就是写文件,gulp.dest(path[,options]),path是要写入的文件的路径,这里注意只能是路径,不能是具体的文件const sass = require('gulp-sass') // 真是执行css编译的,其调用node-sass,而node-sass是c++的二进制模块,所以安装时需要设置淘宝镜像进行安装const style = () => {return src('src/assets/styles/*.scss', {base: 'src'}) // base作用是以src为基准,原样输出目录结构.pipe(sass({outputStyle: 'expanded'})) // outputStyle作用是将sass生成的css文件最后的花括号放在块末尾.pipe(dest('dist'))}module.exports = {style}

命令行运行:

yarn gulp style

4.7 Gulp案例-脚本编译

安装依赖:

yarn add gulp-babel --devyarn add @babel/core @babel/preset-env # preset-env会将ECMAScript中所有的新特性进行转换

const babel = require('gulp-babel')const script = () => {return src('src/assets/scripts/*.js', {base: 'src'}).pipe(babel({presets: ['@babel/preset-env']})).pipe(dest('dist'))}module.exports = {style,script}

命令行运行:

yarn gulp script

4.8 Gulp案例-页面编译

安装依赖:

yarn add gulp-swig --dev

const {src, dest, parallel, series} = require('gulp')// gulp.src:gulp底层是使用的nodejs的stream,首先获取到stream流,然后使用pipe()方法把流数据导入到你想让它去的地方。// gulp.dest:要说src函数是读取文件,那么dest函数就是写文件,gulp.dest(path[,options]),path是要写入的文件的路径,这里注意只能是路径,不能是具体的文件const sass = require('gulp-sass')const babel = require('gulp-babel')const swig = require('gulp-swig')const data = {...}const style = () => {return src('src/assets/styles/*.scss', {base: 'src'}) // base作用是以src为基准,原样输出目录结构.pipe(sass({outputStyle: 'expanded'})) // outputStyle作用是将sass生成的css文件最后的花括号放在块末尾.pipe(dest('dist'))}const script = () => {return src('src/assets/scripts/*.js', {base: 'src'}).pipe(babel({presets: ['@babel/preset-env']})).pipe(dest('dist'))}const page = () => {return src('src/*.html', {base: 'src'}).pipe(swig({data})) // 填充模板页面的数据.pipe(dest('dist'))}const compile = parallel(style, script, page) // 任务并行module.exports = {compile}

命令行输入:

yarn gulp compile

4.9 Gulp案例-图片和字体文件转换

安装依赖:

yarn add gulp-imagemin --dev # 与node-sass相同,需要引入二进制文件,科学上网

const {src, dest, parallel, series} = require('gulp')// gulp.src:gulp底层是使用的nodejs的stream,首先获取到stream流,然后使用pipe()方法把流数据导入到你想让它去的地方。// gulp.dest:要说src函数是读取文件,那么dest函数就是写文件,gulp.dest(path[,options]),path是要写入的文件的路径,这里注意只能是路径,不能是具体的文件const sass = require('gulp-sass')const babel = require('gulp-babel')const swig = require('gulp-swig')const imagemin = require('gulp-imagemin')const data = {...}const style = () => {return src('src/assets/styles/*.scss', {base: 'src'}) // base作用是以src为基准,原样输出目录结构.pipe(sass({outputStyle: 'expanded'})) // outputStyle作用是将sass生成的css文件最后的花括号放在块末尾.pipe(dest('dist'))}const script = () => {return src('src/assets/scripts/*.js', {base: 'src'}).pipe(babel({presets: ['@babel/preset-env']})).pipe(dest('dist'))}const page = () => {return src('src/*.html', {base: 'src'}).pipe(swig({data})) // 填充模板页面的数据.pipe(dest('dist'))}const image = () => {return src('src/assets/images/**', {base: 'src' }).pipe(imagemin()).pipe(dest('dist'))}const font = () => {return src('src/assets/fonts/**', {base: 'src' }).pipe(imagemin()).pipe(dest('dist'))}const compile = parallel(style, script, page, image, font) // 任务并行module.exports = {compile,}

运行命令:

yarn gulp imageyarn gulp font

4.10 Gulp案例-其他文件及文件清除

const {src, dest, parallel, series} = require('gulp')// gulp.src:gulp底层是使用的nodejs的stream,首先获取到stream流,然后使用pipe()方法把流数据导入到你想让它去的地方。// gulp.dest:要说src函数是读取文件,那么dest函数就是写文件,gulp.dest(path[,options]),path是要写入的文件的路径,这里注意只能是路径,不能是具体的文件const sass = require('gulp-sass')const babel = require('gulp-babel')const swig = require('gulp-swig')const imagemin = require('gulp-imagemin')const data = {...}const style = () => {return src('src/assets/styles/*.scss', {base: 'src'}) // base作用是以src为基准,原样输出目录结构.pipe(sass({outputStyle: 'expanded'})) // outputStyle作用是将sass生成的css文件最后的花括号放在块末尾.pipe(dest('dist'))}const script = () => {return src('src/assets/scripts/*.js', {base: 'src'}).pipe(babel({presets: ['@babel/preset-env']})).pipe(dest('dist'))}const page = () => {return src('src/*.html', {base: 'src'}).pipe(swig({data})) // 填充模板页面的数据.pipe(dest('dist'))}const image = () => {return src('src/assets/images/**', {base: 'src' }).pipe(imagemin()).pipe(dest('dist'))}const font = () => {return src('src/assets/fonts/**', {base: 'src' }).pipe(imagemin()).pipe(dest('dist'))}const extra = () => {return src('public/**', {base: 'public'}) // 额外拷贝的任务.pipe(dest('dist'))}const compile = parallel(style, script, page, image, font) // 任务并行const build = parallel(compile, extra) // 任务并行module.exports = {build}

需要在build任务之前先自动清除dist文件,因此使用series创建串行任务。

安装依赖

yarn add del --dev

const {src, dest, parallel, series} = require('gulp')// gulp.src:gulp底层是使用的nodejs的stream,首先获取到stream流,然后使用pipe()方法把流数据导入到你想让它去的地方。// gulp.dest:要说src函数是读取文件,那么dest函数就是写文件,gulp.dest(path[,options]),path是要写入的文件的路径,这里注意只能是路径,不能是具体的文件const del = require('del')const sass = require('gulp-sass')const babel = require('gulp-babel')const swig = require('gulp-swig')const imagemin = require('gulp-imagemin')const data = {...}const clean = () => {return del(['dist']) // 返回promise}const style = () => {return src('src/assets/styles/*.scss', {base: 'src'}) // base作用是以src为基准,原样输出目录结构.pipe(sass({outputStyle: 'expanded'})) // outputStyle作用是将sass生成的css文件最后的花括号放在块末尾.pipe(dest('dist'))}const script = () => {return src('src/assets/scripts/*.js', {base: 'src'}).pipe(babel({presets: ['@babel/preset-env']})).pipe(dest('dist'))}const page = () => {return src('src/*.html', {base: 'src'}).pipe(swig({data})) // 填充模板页面的数据.pipe(dest('dist'))}const image = () => {return src('src/assets/images/**', {base: 'src' }).pipe(imagemin()).pipe(dest('dist'))}const font = () => {return src('src/assets/fonts/**', {base: 'src' }).pipe(imagemin()).pipe(dest('dist'))}const extra = () => {return src('public/**', {base: 'public'}) // 额外拷贝的任务.pipe(dest('dist'))}const compile = parallel(style, script, page, image, font) // 任务并行const build = series(clean, parallel(compile, extra)) // 任务并行module.exports = {build}

4.11 Gulp案例-自动加载插件

代码合理化,自动加载所有gulp的插件,使用gulp-load-plugins

const {src, dest, parallel, series} = require('gulp')// gulp.src:gulp底层是使用的nodejs的stream,首先获取到stream流,然后使用pipe()方法把流数据导入到你想让它去的地方。// gulp.dest:要说src函数是读取文件,那么dest函数就是写文件,gulp.dest(path[,options]),path是要写入的文件的路径,这里注意只能是路径,不能是具体的文件const del = require('del')const loadPlugins = require('gulp-load-plugins') // 加载load-pluginsconst plugins = loadPlugins() //以下所有插件使用plugins.[插件名],如果插件名为gulp-xx-xx,那么改为plugins.xxYy,驼峰命名const data = {...}const clean = () => {return del(['dist', 'temp'])}const style = () => {return src('src/assets/styles/*.scss', {base: 'src'}) // base作用是以src为基准,原样输出目录结构.pipe(plugins.sass({outputStyle: 'expanded'})) // outputStyle作用是将sass生成的css文件最后的花括号放在块末尾.pipe(dest('dist'))}const script = () => {return src('src/assets/scripts/*.js', {base: 'src'}).pipe(plugins.babel({presets: ['@babel/preset-env']})).pipe(dest('dist'))}const page = () => {return src('src/*.html', {base: 'src'}).pipe(plugins.swig({data})) // 填充模板页面的数据.pipe(dest('dist'))}const image = () => {return src('src/assets/images/**', {base: 'src'}).pipe(plugins.imagemin()).pipe(dest('dist'))}const font = () => {return src('src/assets/fonts/**', {base: 'src'}).pipe(plugins.imagemin()).pipe(dest('dist'))}const extra = () => {return src('public/**', {base: 'public'}) // 额外拷贝的任务.pipe(dest('dist'))}const compile = parallel(style, script, page, image, font) // 任务并行const build = series(clean, parallel(compile, extra)) // 任务并行module.exports = {build}

4.12 Gulp案例-开发服务器、监视变化以及构建优化

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/**', font)// watch('public/**', extra)watch(['src/assets/images/**','src/assets/fonts/**','public/**'], bs.reload)bs.init({notify: false,port: 2080,// open: false,// files: 'dist/**',server: {baseDir: ['temp', 'src', 'public'],routes: {'/node_modules': 'node_modules'}}})}const develop = series(compile, serve)module.exports = {clean,build,develop}

4.14 Gulp案例-userer文件引用处理

const useref = () => {return src('temp/*.html', {base: 'temp' }).pipe(plugins.useref({searchPath: ['temp', '.'] }))// html js css.pipe(plugins.if(/\.js$/, plugins.uglify())).pipe(plugins.if(/\.css$/, plugins.cleanCss())).pipe(plugins.if(/\.html$/, plugins.htmlmin({collapseWhitespace: true,minifyCSS: true,minifyJS: true}))).pipe(dest('dist'))}

4.16 Gulp案例-重新规划构建过程

暴露出任务

{"name": "zce-gulp-demo","version": "0.1.0","main": "index.js","repository": "/zce/zce-gulp-demo.git","author": "zce <w@zce.me> (https://zce.me)","license": "MIT","scripts": {"clean": "gulp clean", // 此时可以直接执行yarn clean"build": "gulp build","develop": "gulp develop"},"dependencies": {"bootstrap": "^4.3.1","jquery": "^3.4.1","popper.js": "^1.15.0"},"devDependencies": {"@babel/core": "^7.5.5","@babel/preset-env": "^7.5.5","browser-sync": "^2.26.7","del": "^5.1.0","gulp": "^4.0.2","gulp-babel": "^8.0.0","gulp-clean-css": "^4.2.0","gulp-htmlmin": "^5.0.1","gulp-if": "^3.0.0","gulp-imagemin": "^6.1.0","gulp-load-plugins": "^2.0.1","gulp-sass": "^4.0.2","gulp-swig": "^0.9.1","gulp-uglify": "^3.0.2","gulp-useref": "^3.1.6"}}

gitignore忽略生成的目录

disttemp

今日分享就到了这里,上面很多的概念性问题,要完全的理解并使用这些新的知识,需要很长一段时间。多用、多查、多做!

记录:/11/22

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。