使用grunt
完成项目的自动化构建
一、准备工作
grunt快要退出历史舞台了,简单学习下
1
2
3
4
5mkdir my-grunt yarn init --yes //创建package模块 yarn add grunt //安装grunt模块
二、创建gruntfile.js文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21//Grunt的入口文件 //用于定义一些需要Grunt自动执行的任务 //需要导出一个函数,接收一个grunt的参数 // 运行 yarn grunt foo module.exports = grunt => { grunt.registerTask('foo',() => { console.log("hello grunt") }) } //可以在第二个参数添加描述信息,会作为当前任务的描述信息存在 grunt.registerTask('bar',"任务描述",() => { console.log("hello grunt") }) //如果任务名称为default,则会作为默认任务存在,yarn grunt即可执行 grunt.registerTask('default',"任务描述",() => { console.log("hello default grunt") }) //也可通过数组进行任务组合,会依次执行数组中的任务,串联操作 grunt.registerTask("default",["foo","bar"])
注意:grunt默认执行同步任务,所以如果是异步任务,则需要通过this.async进行
1
2
3
4
5
6
7
8
9grunt.registerTask("async-task",function(){ const done = this.async() setTimeout(()=>{ console.log("async...") done() },1000) })
测试运行
1
2
3
4
5
6yarn grunt foo yarn grunt bar yarn grunt default yarn grunt async-task
三、grunt标记任务失败
可以通过在任务体中直接return false实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15//grunt标记任务失败 grunt.registerTask('bad', "任务描述", () => { console.log("bad") return false }) //异步标记失败 grunt.registerTask("bad-async",function(){ const done = this.async() setTimeout(()=>{ console.log("bad-async") done(false) },1000) })
如果是串行的任务,如果有一个出现问题,则后续任务不会被执行,但是可以指定参数--force
强制执行
1
2
3
4
5grunt.registerTask("testBad",["foo","bad","bar"]) //执行 yarn grunt testBad --force
四、grunt配置方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16module.exports = grunt => { grunt.initConfig({ // foo:'bar', foo:{ bar:123 } }) grunt.registerTask('foo', () => { // grunt.config 可以取出配置中foo对应的值 console.log(grunt.config('foo')) //属性值 console.log(grunt.config('foo.bar')) //对象值 }) }
五、grunt多目标任务
多目标任务需要使用registerMultiTask进行任务的注册,必须要为对应的多目标任务在initConfig中添加target,如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24//grunt多目标任务 module.exports = grunt => { grunt.initConfig({ build: { //options作为任务的配置选项 options:{ foo:"bar" }, css: { options:{ foo:"baz" //会覆盖任务中的options } }, js: "2" } }) grunt.registerMultiTask('build', function () { console.log(this.options()) console.log(`target:${this.target},data:${this.data}`) }) }
六、Grunt插件的使用
流程:安装插件载入插件根据插件文档完成相关选项
1
2
3yarn add grunt-contrib-clean //安裝插件 自动清除临时文件
使用方法,使用loadNpmTasks载入插件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17/** * yarn add grunt-contrib-clean * 自动清除临时文件 */ module.exports = grunt => { grunt.initConfig({ clean: { // temp: 'temp/app.js' // temp: 'temp/*.txt' temp: 'temp/**' } }) grunt.loadNpmTasks('grunt-contrib-clean') }
yarn grunt clean
七、grunt常用插件
- babel:将es6语法新特性进行转化
- sass:将sass转化为可识别的css
- html:将文件模板输出到指定目录
- watch:监视变化,热更新
- clean:清除指定文件夹的文件
sass
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24//安装依赖 yarn add grunt-sass sass -dev //引入插件 const sass = require("sass") //使用 module.exports = grunt => { grunt.initConfig({ //sass转化为css功能 sass: { options: { sourceMap: true, implementation: sass }, main: { files: { 'dist/css/main.css': 'src/scss/main.scss' } } } }) } grunt.loadNpmTasks('grunt-sass')
yarn grunt sass
babel
gruntfile中使用loadGruntTasks载入所有安装的插件,最后完成相关的配置选项。
1
2
3
4
5
6
7//安裝 yarn add load-grunt-tasks --dev //使用 const loadGruntTasks = require("load-grunt-tasks") //自动加载所有的grunt插件 loadGruntTasks(grunt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45const 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'] }, 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']) }
八、Gulp的基本使用
https://www.cnblogs.com/xqbiii/p/8406978.html
1
2
3
4yarn init --yes yarn add gulp --dev
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22exports.foo = (done) => { console.log('任务foo') done() // 标识任务执行完成 } //yarn gulp foo // default 是默认任务 // 在运行是可以省略任务名参数 exports.default = done => { console.log('default task working~') done() } // yarn gulp // v4.0 之前需要通过 gulp.task() 方法注册任务 // 这种方式已经不被推荐了 const gulp = require('gulp') gulp.task('bar', done => { console.log('bar task working~') done() })
九、Gulp的组合任务
const { series, parallel } = require('gulp')
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30const { series, parallel } = require('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)
十、Gulp的异步任务
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41const fs = require('fs') // 一回调 exports.callback = done => { console.log('callback task') done() } exports.callback_error = done => { console.log('回调报错处理') done(new Error('task failed')) } //二 通过promise,这里也是支持promise的,resolve不需要返回值,就算返回也会被忽略,直接resolve() exports.promise = done => { console.log('promise') return Promise.resolve() } exports.promise_error = () => { console.log('promise_error') return Promise.reject(new Error('promise failed')) } // 三async await const timeOut = (time) => { return new Promise(resolve => { setTimeout(resolve(), time); }) } exports.async = async () => { await timeOut(1000) console.log('1秒后打印') } // stream exports.stream = () => { const read = fs.createReadStream('yarn.lock') const write = fs.createWriteStream('a.txt') read.pipe(write) return read }
十一、Gulp构建过程核心工作原理
eg:这里用node自带的读取流写入流
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26const fs = require('fs') const { Transform } = require('stream') exports.default = () => { // 文件读取流 const readStream = fs.createReadStream('normalize.css') // 文件写入流 const writeStream = fs.createWriteStream('normalize.min.css') // 文件转换流 const transformStream = new Transform({ // 核心转换过程 transform: (chunk, encoding, callback) => { const input = chunk.toString() const output = input.replace(/s+/g, '').replace(//*.+?*//g, '') callback(null, output) } }) return readStream .pipe(transformStream) // 转换 .pipe(writeStream) // 写入 }
十二、文件操作API
1
2
3
4
5
6
7
8
9
10
11
12const { src, dest } = require('gulp') const cleanCSS = require('gulp-clean-css')//转换流插件压缩css const rename = require('gulp-rename')//重命名后缀 exports.default = () => { return src('src/*.css') .pipe(cleanCSS()) .pipe(rename({ extname: '.min.css' })) .pipe(dest('dist')) }
十三、Gulp案例-样式编译
1
2
3
4
5
6
7
8
9
10
11
12const { src, dest } = require('gulp') const cleanCSS = require('gulp-clean-css')//转换流插件压缩css const rename = require('gulp-rename')//重命名后缀 exports.default = () => { return src('src/*.css') .pipe(cleanCSS()) .pipe(rename({ extname: '.min.css' })) .pipe(dest('dist')) }
十四、脚本编译
1
2
3
4
5
6
7
8
9
10
11
12const { src, dest } = require('gulp') const babel = require('gulp-babel') const script = () => { return src('src/assets/scripts/*.js', { base: 'src' }) .pipe(plugins.babel({ presets: ['@babel/preset-env'] })) .pipe(dest('temp')) .pipe(bs.reload({ stream: true })) } module.exports = { script }
十五、页面模板编译
1
2
3
4<div class="row"> {% for item in [1, 2, 3, 4, 5, 6] %} </div>
以上面模板为例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53const 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 { src, dest } = require('gulp') const swig = require('gulp-swig') // 编译模板 const page = () => { return src('src/*.html', { base: 'src' }) .pipe(plugins.swig({ data})) .pipe(dest('dist')) } module.exports = { page }
十六、图片和文字字体转换
安装依赖
1
2yarn add gulp-imagemin --dev
1
2
3
4
5
6
7
8
9
10
11
12
13const imagemin = require('gulp-imagemin') const image = () => { return src("src/assets/images/**",{base:'src'}).pipe(imagemin()).pipe(dest('dist')) } const fonts = () => { return src("src/assets/fonts/**",{base:'src'}).pipe(imagemin()).pipe(dest('dist')) } module.exports = { image,fonts }
十七、其他文件及文件清除
1
2npm i del -D // 不是gulp插件
1
2
3
4
5
6
7
8
9
10
11
12const { src, dest, parallel, series, watch } = require('gulp') const del = require('del') const clean = () => { return del(['dist', 'temp']) } const compile = parallel(style,script,page,image,font) const build = series(clean,parallel(compile,extra)) module.exports = { compile, build }
十八、自动加载插件
1
2yarn add gulp-load-plugins --dev
不用每次都去引入插件,可以使用plugins自动引入插件
1
2
3
4
5
6const loadPlugins = require('gulp-load-plugins') const plugin = new loadPlugins() const page = () => { return src("src/*.html",{base:'src'}).pipe(plugin.swig({data})).pipe(dest('dist')) }
十九、开发服务器
安装依赖
1
2
3yarn add browser-sync --dev yarn add bootstrap@4.0.0-alpha.6 --dev
任务创建
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20const browserSync = require('browser-sync') const bs = browserSync.create() const serve = () => { bs.init({ server: { baseDir: 'dist', files: 'dist/**', routes: { //处理静态文件,进行路由映射 '/node_modules': "node_modules" } } }) } module.exports = { compile, image, fonts, extra, serve }
1
2yarn gulp serve
二十、监视变化以及构建优化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21const { dest, src,series,parallel,watch } = require('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/**",fonts) watch("public/**",extra) bs.init({ server: { baseDir: 'dist', files:'dist/**', //监听的是哪个文件 // open:false, routes: { '/node_modules': "node_modules" } } }) }
可以简化
1
2
3
4
5
6
7
8
9
10
11
12
13const 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)
font与image以及额外的文件,热更没有太大的必要,因为图片压缩是无损压缩,太多的监视会一定程度上消耗性能,所以一般不对其就行监视,修改
1
2
3
4
5
6
7watch("src/assets/styles/*.scss",style) watch("src/assets/scripts/*.js",script) watch("src/*.html",page) //修改basedir baseDir:["dist","public","src"]
二十一、useref文件引用处理
打包之后部署线上找不到引入文件,用useref插件,注意注释,都是有规律的
1
2
3
4
5
6
7const userref = () => { return src('dist/*.html',{base: 'dist'}) .pipe(plugins.useref({ searchPath: ['dist', '.'] })) .pipe(dest('dist')) }
二十二、文件压缩
npm i gulp-htmlmin gulp-uglify gulp-clean-css -D
gulp-uglify压缩js
npm i gulp-if -D
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15const 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')) }
二十三、处理文件重命名添加hash编码
gulp-rev
、gulp-rev-collector
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31// 压缩html gulp.task('html', async function () { const options = { removeComments: true, //清除HTML注释 collapseWhitespace: true, //压缩HTML collapseBooleanAttributes: true, //省略布尔属性的值 <input checked="true"/> ==> <input checked /> removeEmptyAttributes: true, //删除所有空格作属性值 <input id="" /> ==> <input /> removeScriptTypeAttributes: true, //删除<script>的type="text/javascript" removeStyleLinkTypeAttributes: true, //删除<style>和<link>的type="text/css" minifyJS: true, //压缩页面JS minifyCSS: true, //压缩页面CSS } await gulp .src(['./rev/*/*.json', './*.html']) //要压缩的html文件 .pipe(revCollector()) // 做路径替换 .pipe(htmlmin(options)) .pipe(gulp.dest('./share-page')) .pipe(browserSync.reload({ stream: true })) // 服务重载 html }) // 压缩css gulp.task('css', function () { return gulp.src('./css/*.css') //要压缩的css文件 .pipe(rev()) //给文件添加hash编码 .pipe(minifyCss()) .pipe(gulp.dest('./share-page/css')) .pipe(rev.manifest()) //生成rev-mainfest.json文件作为文件名字映射记录 .pipe(gulp.dest('rev/css/')) .pipe(browserSync.reload({ stream: true })) // 服务重载 css })
生成的rev-manifest.json
文件,作用是做文件名字映射。方便打包是html做路径替换
最后效果
二十四、补充
1
2
3
4
5
6"scripts": { "clean": "gulp clean", "build": "gulp build", "develop": "gulp develop" }
yarn clean
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156const { src, dest, parallel, series, watch } = require('gulp') const del = require('del') const browserSync = require('browser-sync') const loadPlugins = require('gulp-load-plugins') const plugins = 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 = () => { return src('src/assets/styles/*.scss', { base: 'src' }) .pipe(plugins.sass({ outputStyle: 'expanded' })) .pipe(dest('temp')) .pipe(bs.reload({ stream: true })) } const script = () => { return src('src/assets/scripts/*.js', { base: 'src' }) .pipe(plugins.babel({ presets: ['@babel/preset-env'] })) .pipe(dest('temp')) .pipe(bs.reload({ stream: true })) } const page = () => { return src('src/*.html', { base: 'src' }) .pipe(plugins.swig({ data, defaults: { cache: false } })) // 防止模板缓存导致页面不能及时更新 .pipe(dest('temp')) .pipe(bs.reload({ stream: true })) } 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 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 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')) } const compile = parallel(style, script, page) // 上线之前执行的任务 const build = series( clean, parallel( series(compile, useref), image, font, extra ) ) const develop = series(compile, serve) module.exports = { clean, build, develop }
二十五、gulp项目实战
本人做了一个gulp的简单打包示例:
目录结构:
static里面放的是不需要打包的资源
package.json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31{ "name": "share-page-dev-glup", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "build": "gulp build", "server": "gulp server" }, "repository": { "type": "git", "url": "https://codeup.aliyun.com/619eeba89cbfc1b4f046737c/share-page.git" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "browser-sync": "^2.29.1", "del": "^6.0.0", "gulp": "^4.0.2", "gulp-htmlmin": "^5.0.1", "gulp-imagemin": "^6.0.0", "gulp-minify-css": "^1.2.4", "gulp-nodemon": "^2.5.0", "gulp-rev": "^9.0.0", "gulp-rev-collector": "^1.3.3", "gulp-uglify": "^3.0.2" } }
gulpfile.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109const gulp = require('gulp'); const del = require('del'); const htmlmin = require('gulp-htmlmin'); const minifyCss = require('gulp-minify-css'); const rev = require('gulp-rev'); const revCollector = require('gulp-rev-collector'); const uglify = require('gulp-uglify'); const imagemin = require('gulp-imagemin'); const browserSync = require('browser-sync').create(); const nodemon = require('gulp-nodemon'); // 压缩html gulp.task('html', async function () { const options = { removeComments: true, //清除HTML注释 collapseWhitespace: true, //压缩HTML collapseBooleanAttributes: true, //省略布尔属性的值 <input checked="true"/> ==> <input checked /> removeEmptyAttributes: true, //删除所有空格作属性值 <input id="" /> ==> <input /> removeScriptTypeAttributes: true, //删除<script>的type="text/javascript" removeStyleLinkTypeAttributes: true, //删除<style>和<link>的type="text/css" minifyJS: true, //压缩页面JS minifyCSS: true, //压缩页面CSS } await gulp .src(['./rev/*/*.json', './*.html']) //要压缩的html文件 .pipe(revCollector()) .pipe(htmlmin(options)) .pipe(gulp.dest('./share-page')) .pipe(browserSync.reload({ stream: true })) // 服务重载 html }) // 压缩css gulp.task('css', function () { return gulp.src('./css/*.css') //要压缩的css文件 .pipe(rev()) //给文件添加hash编码 .pipe(minifyCss()) .pipe(gulp.dest('./share-page/css')) .pipe(rev.manifest()) //生成rev-mainfest.json文件作为记录 .pipe(gulp.dest('rev/css/')) .pipe(browserSync.reload({ stream: true })) // 服务重载 css }) // 压缩js gulp.task('js', async function () { await gulp .src('./js/*.js') .pipe(rev()) //给文件添加hash编码 .pipe(uglify()) .pipe(gulp.dest('./share-page/js')) .pipe(rev.manifest()) //生成rev-mainfest.json文件作为记录 .pipe(gulp.dest('rev/js/')) .pipe(browserSync.reload({ stream: true })) // 服务重载 js }) gulp.task('imagemin', () => { return gulp.src('image/**/*') .pipe(imagemin()) .pipe(gulp.dest('share-page/image/')) }) gulp.task('copy', function () { return gulp.src('static/**/*') .pipe(gulp.dest('share-page/static')) }); gulp.task('clean', function () { return del(['share-page']) }) // 热更新 const update = gulp.parallel('css', 'html', 'js') // 打包 const build = gulp.series('clean', gulp.parallel('copy', 'css', 'js', 'imagemin'), 'html') gulp.task('build', build, function () { }) gulp.task('server', async function () { browserSync.init( { port: 8080, open: true, startPath: "./index.html", server: { baseDir: ['./'] } }, function () { console.log('browser refreshed.') } ) await build() // nodemon({ // script: 'cluster.js', // // 忽略部分对程序运行无影响的文件的改动,nodemon只监视js文件,可用ext项来扩展别的文件类型 // ignore: ['*'], // env: { // NODE_ENV: 'development', // }, // }).on('start', async function () { await gulp .watch(['./*.html', './js/', './css/']) .on('change', async function () { await update() browserSync.reload() }) // }) })
二十六、webpack和gulp有哪些区别
想必面试会经常被问到这个问题,本人做了一些总结 仅供参考:
面试,我觉得应该先把重点的工作原理说出来,gulp 其实是配置的任务流,一个一个执行,让它怎么执行,就怎么执行,webpack 是全是模块,给个入口,剩下的全交给它处理
- 工作原理不同:
webpack
:- 首先通过入口文件(
entry
)找到项目中所有的模块(module
)。
将这些模块进行静态分析和处理,最终打包成一个或多个bundle
文件。 - 在打包的过程中,
webpack
会根据依赖关系进行代码拆分,将公共代码抽离成独立的chunk
,使得代码的加载变得更加高效。 webpack
还可以通过loade
r来转换非JavaScript
文件,并且可以使用各种插件
进行自定义构建流程和优化。
- 首先通过入口文件(
gulp
:gulp
通过定义不同的任务(task)
来执行各种构建操作。- 通过
gulp.src
获取需要进行处理的文件流,再通过一系列插件进行处理,最后通过gulp.dest
输出到指定的位置。 gulp
的插件可以进行多个操作,比如压缩、合并、重命名等,同时也可以定制自己的插件并加以使用。
HMR
是Webpack的一个功能,即热模块替换,它可以在不刷新浏览器的情况下更新模块。和热更新不同,HMR只会更新其中一个模块,而不是整个页面。这种机制是针对模块化开发而设计的。Gulp并没有自带的HMR功能,但可以使用一些插件或工具来实现类似的效果。例如,使用gulp-connect、browser-sync和lite-server等插件,可以实现自动刷新浏览器,节省手动刷新时间。但是,它们并没有模块热替换的功能。如果需要使用模块热替换,还是需要结合webpack等打包工具来实现。- webpack可以很容易地做
tree-shaking
,gulp不行 - 但是gulp解决不了模块化js文件的问题,于是使用
ts
或者配置sea.js
、require.js
的插件用来解决js模块化,而webpack本身就是模块化为核心。。 gulp
在单页面应用方面输出乏力,而且对流行的单页技术有些难以处理(比如 Vue 单文件组件,使用 gulp 处理就会很困难,而 webpack 一个 loader 就能轻松搞定)- 使用方式上不同,
webpack
里面有大量的loader
和plugin
用来处理和打包资源文件,gulp
有大量的插件,根据定义不同的task
任务去处理和打包资源 - gulp更易于学习,易于使用,webpack相对学习难度更难一些
- 这里没有明确的好坏界限,只是看你的项目使用场景而做选择,也不乏有很多大型项目使用
gulp
,比如vscode
二十七、FIS的基本使用
百度团队开发的构建工具
yarn global add fis3
fis3 release
fis3 release -d output
// 指定到output文件夹
fis-conf.js
1
2
3
4fis.match('*.{js,scss,png}',{ release:'/assets/$0' })
静态资源配置
yarn global add fis-parser-node-sass
把sass语法转换为正常的css语法
1
2
3
4
5
6
7
8
9
10
11
12fis.match('*.{js,scss,png}',{ release: '/assets/$0' }) fis.match('**/*.scss',{ rExt: '.css', // rename paeser: fis.plugin('node-sass') }) fis.match('**/*.js',{ parser: fis.plugin('babel-6.x'), optimizer: fis.plugin('uglify-js') //压缩 })
最后
以上就是稳重纸鹤最近收集整理的关于自动化构建工具Grunt、Gulp的全部内容,更多相关自动化构建工具Grunt、Gulp内容请搜索靠谱客的其他文章。
发表评论 取消回复