别被题目吓到,哈哈,即便当初vite
横空出世,社区光芒四射,两个字很快,然而webpack
仍旧宝刀未老,仍然扛起前端工程化的大梁,然而明天我为啥说要拥抱gulp
,因为咱们经经常吃一道菜,所以要换个口味,这样才养分平衡。
gulp
定义是:用自动化构建工具
加强你的工作流程
,是一种基于工作文件流
形式,你能够在前端写一些自动化脚本,或者降级历史传统我的项目,解放你反复打包,压缩,解压之类的操作。
集体了解gulp
是一种命令式编程
的体验,更重视构建过程,所有的工作须要你本人手动创立,你会对构建流程会十分分明,这点不像webpack
,webpack
就是一个开箱即用的申明式
形式,webpack
是一个模块化打包工具,外部细节暗藏十分之深,你也不需关注细节,你只须要照着提供的API
以及引入对应的loader
和plugin
应用就行。
言归正传,为了饮食平衡
,明天一起学习下gulpjs
注释开始...
搭建一个简略的前端利用
相比拟webpack
,其实gulp
的我的项目构造更偏差传统的利用,只是咱们借助gulp
工具解放咱们的一些代码压缩
、es6编译
、打包
以及在传统我的项目中都能够应用less
体验。
在gulp
目录下新建01-simple-demo
根目录下生成默认package.json
npm init -y
而后在public
目录下新建images
、css
、js
、index.html
文件构造,大略就这样
而后在装置gulp
npm i gulp --save-dev
在根目录下新建gulpfile.js
咱们先在gulpfile.js
中写入一点内容,测试一下
const defaultTask = (cb) => { console.log('hello gulp'); cb();};exports.default = defaultTask;
而后咱们在命令行执行
npx gulp
当咱们执行npx gulp
时会默认运行gulpfile.js
导出的default
,在gulpfile.js
导出的工作会注册到gulp
工作中
在gulp
中工作次要分两种,一种是公开工作
、另一种是公有工作
公开工作
能够间接在命令执行npx gulp xxx
调用执行,比方上面的defaultTask
就是一个公开工作,只有被导出就是一个公开工作,没有被导出就是一个公有工作。
...exports.default = defaultTask;
私有工作taskJS
// gulpfile.jsconst { src, dest } = require('gulp');const pathDir = (dir) => { return path.resolve(__dirname, dir);};// todo 执行ts工作,将js目录下的js打包到dist/js目录下const taskJS = () => { return src(pathDir('public/**/*.js'), { sourcemaps: true }).pipe(dest(pathDir('dist/js')));};exports.taskJS = taskJS;
而后你在命令行执行
npx gulp taskJS
至此你会发现dist
目录下就有生成的js
了
装置 less
npm i less gulp-less --save-dev
在css/index.less
中写入测试 css 的代码
@bgcolor: yellow;@defaultsize: 20px;body { background-color: @bgcolor;}h1 { font-size: @defaultsize;}
在gulpfile.js
中写入编译less
的工作,须要gulp-less
const { src, dest } = require('gulp');const less = require('gulp-less');const pathDir = (dir) => { return path.resolve(__dirname, dir);}...// todo less工作const taskLess = () => { // css目录洗的所有.less文件,dest输入到dist/css目录下 return src(pathDir('public/css/*.less')).pipe(less()).pipe(dest(pathDir('dist/css')))}exports.taskLess = taskLess;
命令行运行npx gulp taskLess
,后果如下
图片资源
应用一个gulp-image
插件对图片进行无损压缩解决
// gulpfile.jsconst { src, dest } = require('gulp');const image = require('gulp-image');const path = require('path');const pathDir = (dir) => { return path.resolve(__dirname, dir);}...// todo 图片资源const taskImage = () => { return src(pathDir('public/images/*.*')).pipe(image()).pipe(dest(pathDir('dist/images')))}exports.taskImage = taskImage;
一顿操作发现,最新版本不反对esm
,所以还是升高版本版本,这里升高到6.2.1
版本
而后运行npx gulp taskImage
图片压缩得不小
在这之前,咱们别离定义了三个不同的工作,gulp
导出的工作有
公开工作和公有工作,多个公开工作能够串行组合
应用
组合工作 series 与 parallel
因而我能够将之前的介个工作组合在一起
// gulpfile.jsconst { src, dest, series } = require('gulp');const less = require('gulp-less');const image = require('gulp-image');const path = require('path');const pathDir = (dir) => { return path.resolve(__dirname, dir);}// todo js工作const taskJS = () => { return src(pathDir('public/**/*.js'), { sourcemaps: true }).pipe(dest(pathDir('dist/js')))}...// series组合多个工作const seriseTask = series(taskJS, taskLess, taskLess, taskImage)exports.seriseTask = seriseTask;
当我在命令行npx gulp seriseTask
时
曾经在dist
生成对应的文件了
编译转换 es6
在咱们index.js
,很多时候是写的es6
,在gulp
中咱们须要一些借助一些插件gulp-babel
,另外咱们须要装置另外两个babel
外围插件@babel/core
,@babel/preset-env
npm i gulp-babel @babel/core @babel/preset-env
在gulpfile.js
中咱们须要批改下
...const babel = require('gulp-babel');// todo js工作// 用babel转换es6语法糖const taskJS = () => { return src(pathDir('public/**/*.js'), { sourcemaps: true }).pipe(babel({ presets: ['@babel/preset-env'] })).pipe(dest(pathDir('dist/js')))}
当咱们在js/index.js
写入一段测试代码
js / index.js;const appDom = document.getElementById('app');appDom.innerHTML = 'hello gulp';const fn = () => { console.log('公众号:Web技术学苑,好好学习,天天向上');};fn();
运行npx gulp seriseTask
箭头函数和const
申明的变量就变成了es5
了
通常状况下,个别打包后的dist
下的css
或者js
都会被压缩,在gulp
中也是须要借助插件来实现
压缩 js 与 css
压缩js
...const teser = require('gulp-terser');// todo js工作const taskJS = () => { return src(pathDir('public/**/*.js'), { sourcemaps: true }).pipe(babel({ presets: ['@babel/preset-env'] })).pipe(teser({ mangle: { toplevel: true // 混同代码 } })).pipe(dest(pathDir('dist/js')))}...
压缩css
...const uglifycss = require('gulp-uglifycss');// todo less工作const taskLess = () => { return src(pathDir('public/css/*.less')).pipe(less()).pipe(uglifycss()).pipe(dest(pathDir('dist/css')))}...
在这之前咱们在输入dest
时候咱们都执向了一个具体的文件目录,在src
这个api
中是创立流,从文件中读取vunyl
对象,自身也提供了一个base
属性,因而你能够像上面这样写
const { src, dest, series } = require('gulp');const less = require('gulp-less');const image = require('gulp-image');const babel = require('gulp-babel');const teser = require('gulp-terser');const uglifycss = require('gulp-uglifycss');const path = require('path');const pathDir = (dir) => { return path.resolve(__dirname, dir);};// 设置base,当输入文件指标dist文件时,会主动拷贝以后文件夹到目标目录const basePath = { base: './public'};// todo js工作const taskJS = () => { return src(pathDir('public/**/*.js', basePath)) .pipe( babel({ presets: ['@babel/preset-env'] }) ) .pipe( teser({ mangle: { toplevel: true // 混同代码 } }) ) .pipe(dest(pathDir('dist')));};// todo less工作const taskLess = () => { return src(pathDir('public/css/*.less'), basePath) .pipe(less()) .pipe(uglifycss()) .pipe(dest(pathDir('dist')));};// todo 图片资源,有压缩,并输入到对应的dist/images文件夹下const taskImage = () => { return src(pathDir('public/images/*.*'), basePath) .pipe(image()) .pipe(dest(pathDir('dist')));};// todo htmlconst taskHtml = () => { return src(pathDir('public/index.html'), basePath).pipe(dest(pathDir('dist')));};const defaultTask = (cb) => { console.log('hello gulp'); cb();};// series组合多个工作const seriseTask = series(taskHtml, taskJS, taskLess, taskLess, taskImage);exports.default = defaultTask;exports.taskJS = taskJS;exports.taskLess = taskLess;exports.taskImage = taskImage;exports.seriseTask = seriseTask;
将资源注入 html 中
在gulp
中,工作之间的依赖关系须要咱们本人手动写一些执行工作流,当初一些打包后的dist
的文件并不会主动注入html
中。
参考gulp-inject
...const inject = require('gulp-inject');...// 将css,js插入html中const injectHtml = () => { // 指标资源 const targetSources = src(['./dist/**/*.js', './dist/**/*.css'], { read: false }); // 指标html const targetHtml = src('./dist/*.html') // 把指标资源插入指标html中,同时输入到dist文件下 const result = targetHtml.pipe(inject(targetSources)).pipe(dest('dist')); return result}// series串行组合多个工作const seriseTask = series(taskHtml, taskJS, taskLess, taskLess, taskImage, injectHtml)exports.seriseTask = seriseTask;
留神一个执行程序,必须是等后面工作执行完了,再注入,所以在series
工作的最初才执行injectHtml
操作
并且在public/index.html
下,还须要退出一段正文
<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>gulp</title> <!-- inject:css --> <!-- endinject --> </head> <body> <div id="app"></div> <!-- inject:js --> <!-- endinject --> </body></html>
当咱们运行npx gulp seriseTask
时
创立本地服务
参考browser-sync
const { src, dest, series, watch } = require('gulp');const browserSync = require('browser-sync');...const taskBuild = seriseTask;// 本地服务const taskDevServer = () => { // 监听public所有目录下,只有文件产生扭转,就从新加载 watch(pathDir('public'), taskBuild); // 创立服务 const server = browserSync.create(); // 调用init开启端口拜访 server.init({ port: '8081', //设置端口 open: true, // 主动关上浏览器 files: './dist/*', // dist文件 server: { baseDir: './dist' } })}exports.taskDevServer = taskDevServer;
当咱们运行npx gulp taskDevServer
时,浏览器会默认关上http://localhost:8081
咱们应用了一个watch
监听public
目录下的所有文件,如果文件有变动时,会执行taskBuild
工作会在dist
目录下生成对应的文件,而后会启动一个本地服务,关上一个8081
的端口就能够拜访利用了。
至此一个一个用gulp
搭建的前端利用终于能够了。
从新组织 gulpfile
最初咱们能够再从新组织一下gulpfile.js
,因为多个工作写在一个文件里貌似不太那么好保护,随着业务迭代,会越来越多,因而,有必要将工作合成一下
在根目录新建task
,咱们把所有的工作如下
common.js
// task/common.jsconst path = require('path');const pathDir = (dir) => { return path.join(__dirname, '../', dir);};const rootDir = path.resolve(__dirname, '../');const basePath = { base: './public'};const targetDest = 'dist';module.exports = { rootDir, pathDir, basePath, targetDest};
injectHtml.js
// task/injectHtml.jsconst { src, dest } = require('gulp');const inject = require('gulp-inject');const { targetDest, rootDir } = require('./common.js');// 将css,js插入html中const injectHtml = () => { // 指标资源 const targetSources = src([`${rootDir}/${targetDest}/**/*.js`, `${rootDir}/${targetDest}/**/*.css`]); // 指标html const targetHtml = src(`${rootDir}/${targetDest}/*.html`); // 把指标资源插入指标html中,同时输入到dist文件下 const result = targetHtml.pipe(inject(targetSources, { relative: true })).pipe(dest(targetDest)); return result;};module.exports = injectHtml;
taskDevServer.js
const { watch } = require('gulp');const path = require('path');const browserSync = require('browser-sync');const { pathDir, targetDest, rootDir } = require('./common.js');const taskDevServer = (taskBuild) => { return (options = {}) => { const defaultOption = { port: '8081', //设置端口 open: true, // 主动关上浏览器 files: `${rootDir}/${targetDest}/*`, // 当dist文件下有改变时,会主动刷新页面 server: { baseDir: `${rootDir}/${targetDest}` // 基于以后dist目录 }, ...options }; // 监听public所有目录下,只有文件产生扭转,就从新加载 watch(pathDir('public'), taskBuild); const server = browserSync.create(); server.init(defaultOption); };};module.exports = taskDevServer;
...
task/index.js
const injectHtml = require('./injectHtml.js');const taskDevServer = require('./taskDevServer.js');const taskHtml = require('./taskHtml.js');const taskImage = require('./taskImage.js');const taskJS = require('./taskJS.js');const taskLess = require('./taskLess.js');module.exports = { injectHtml, taskDevServer, taskHtml, taskImage, taskJS, taskLess};
在gulpfile.js
中,咱们批改下
// gulpfile.jsconst { series } = require('gulp');const { injectHtml, taskDevServer, taskHtml, taskImage, taskJS, taskLess } = require('./task/index.js');// series组合多个工作const seriseTask = series(taskHtml, taskJS, taskLess, taskLess, taskImage, injectHtml);// 本地服务const devServer = taskDevServer(seriseTask);// 启动服务const server = () => { devServer({ port: 9000 });};const taskBuild = seriseTask;const defaultTask = (cb) => { console.log('hello gulp'); cb();};exports.default = defaultTask;exports.server = server;exports.build = taskBuild;
咱们在package.json
中新增命令
"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "server": "gulp server", "build": "gulp build" },
npm run build
在启动server
之前,咱们先执行npm run build
,而后再执行上面命令,保障browserSync
创立的服务文件夹存在,不然页面关上就404
谬误
npm run server
至此gulp
搭建一个简略的应该就曾经齐全 ok 了
页面背景貌似有点黄
总结
gulpjs
开发是一个工作流的开发方式,它的核心思想就是用自动化构建工具加强你的工作流
,所有的自动化工作流操作都牢牢的把握在本人手上,你能够用gulp
写一些自动化脚本,比方,文件上传,打包,压缩,或者革新传统的前端利用。- 用
gulp
写了一个简略的利用,然而发现中途须要找好多gulp
插件,gulp
的生态还算能够,3w
多个 star,生态绝对丰盛,然而有些插件长年不更新,或者版本更新不反对,比方gulp-image
,当你依照官网文档应用最新的包时,不反对 esm,你必须升高版本6.2.1
,改用cjs
才行 - 应用
gulp
的一些罕用的 api,比方src
、dest
、series
,以及browser-sync
实现本地服务,更多api参考官网文档。 - 即便我的项目工夫再多,也不要用
gulp
搭建前端利用,因为webpack
生态很弱小了,看gulp
的最近更新还是 2 年前,然而写个自动化脚本,还算能够,毕竟gulp
的理念就是用自动化构建工具加强你工作流程
,兴许当你接盘传统我的项目时,一些打包,拷贝,压缩文件之类的,能够尝试用用这个。 - 本文示例code-example
欢送关注公众号:Web技术学苑
好好学习,天天向上!