当我们使用上一节的资源处理方式,已经能够将对应资源进行打包处理,但实际应用中,我们不想每次都手动打包,或者需要本地起一个服务器,又甚至需要代理到服务器等等等等,这时候就需要一些辅助工具来帮助我们完成这些工作。
另外,额外说明的是,我们在上一节,已经创建了名为 js
、css
、html
以及 image
的任务。
在本节相关代码中,读者需加以关联逻辑、注意区别。
Copy Static
在打包时,我们可能需要将一些资源直接拷贝到 dist
目录下,而不需要做任何处理。
安装 gulp-copy :
yarn add gulp-copy -D
const { src, dest } = require('gulp')
const gulpCopy = require('gulp-copy')
function copy () {
return src('lib/*')
// prefix 表示拷贝时去掉lib目录
.pipe(gulpCopy('dist', { prefix: 1 }))
}
exports.copy = copy
Clean Directory
在每次打包之前,我们都需要清理一下 dist
目录,以免出现冗余文件。
安装 gulp-clean :
yarn add gulp-clean -D
const { src, dest } = require('gulp')
const gulpClean = require('gulp-clean')
function clean () {
// The { allowEmpty: true } options allows the task to continue running even if the dist directory is empty.
return gulp.src('dist', { allowEmpty: true })
.pipe(gulpClean())
}
exports.clean = clean
// 另外,应该在其他任务之前,优先执行clean任务,因此此处需要使用series串行及parallel并行。
exports.build = gulp.series(clean, gulp.parallel(js, css, html, image, copy))
Watch Files
watch
方法可以用来监听文件的变化,当文件发生变化时,可以执行对应的任务。
const { watch } = require('gulp')
function watchTask() {
watch('js/*.js', js)
watch('styles/*.*', css)
watch('*.html', html)
watch('images/*.{jpg,png}', image)
}
exports.watch = watchTask
虽然 watch
这里看起来同步的方式,但是由于 watch
在执行时,node
进程并没有停止,因此不会报错 Did you forget to signal async completion?
。
在官网中有指明:
由于文件监控程序会让你的
Node
进程保持持续运行,因此不会有错误或警告产生。由于进程没有退出,因此无法确定任务(task
)是否已经完成还是运行了很久很久了。
// 测试gulp对异步任务的限制
exports.async = function () {
// setTimeout(() => {
// console.log('async')
// }, 1000)
// 不中止进程的话 不会提示Did you forget to signal async completion?
process.stdin.resume()
process.stdin.setEncoding('utf8')
process.stdin.on('data', function(data) {
console.log(data.trim())
})
}
Dev Server
Dev Server
可以帮助我们在本地起一个服务器,以便我们在开发时,可以直接在浏览器中查看效果。
安装 gulp-connect :
yarn add gulp-connect -D
const { src, dest } = require('gulp')
const gulpConnect = require('gulp-connect')
function connect () {
gulpConnect.server({
name: 'Dev Server',
root: 'dist', // 服务根目录 设置成dist 默认为gulpfile.js所在目录
port: 8080, // 端口号 默认8080
host: '10.0.41.35', // 主机名 默认localhost
livereload: true, // 是否启用实时刷新 默认false 此处开启之后,还需要设置pipe(gulpConnect.reload())才能生效
middleware: function (connect, opt) {
return []
}
})
}
// 也可以写成gulp.series(gulp.parallel(connect, watch)) 效果一致
exports.start = gulp.parallel(connect, watch)
设置 livereload
为 true
启用之后,还需要在 js
、css
、html
以及 image
任务后面,加上 pipe(gulpConnect.reload())
才能生效。
此处以 js
为例,其他任务类同:
const { src, dest } = require('gulp')
const gulpConnect = require('gulp-connect')
function js() {
return src('js/*.js')
.pipe(babel({
presets: ['@babel/env']
}))
.pipe(uglify())
.pipe(dest('dist/js'))
.pipe(gulpConnect.reload())
}
exports.js = js
TIP
启用 livereload
后,资源变化后,页面会自动重载。
但要注意的是,启用 livereload
的话,则不推荐将 host
设置为 localhost
,因为在 chrome
浏览器中,会报错 webSocket connection to 'ws://localhost:35729/livereload' failed
。
这是因为 Chrome doesn't allow unsecure websocket (ws) connections to localhost (only wss, so you should setup a TLS certificate for your local web/websocket server). However the same should work fine with Firefox.
更多详情可见:stackoverflow
HTTP Proxy
HTTP Proxy
可以帮助我们在本地开发时解决跨域问题。
yarn add http-proxy-middleware -D
const { src, dest } = require('gulp')
const gulpConnect = require('gulp-connect')
const { createProxyMiddleware } = require('http-proxy-middleware')
function connect () {
gulpConnect.server({
name: 'Dev App',
root: 'dist',
port: 8080,
host: '10.0.41.35',
livereload: true,
middleware: function (connect, opt) {
return [
createProxyMiddleware('/api', {
target: 'https://movie.douban.com/subject/1830575/',
changeOrigin: true,
pathRewrite: {
'^/api': ''
}
})
]
}
})
}
exports.start = gulp.parallel(connect, watch)
Module bundler
gulp
本身是 Task runner
,它并不能将 EsModule
或 CommonJS
转换成浏览器能够执行的 API
。
因此,webpack
和 rollup
这俩种工具才属于模块打包机(Module bundler
)。
其中,webpack
能够打包处理 EsModule
和 CommonJS
,而 rollup
专门针对 EsModule
。
在 gulp
项目中,如果使用了 EsModule
,那么可以使用 gulp-webpack
或 gulp-better-gulp
来处理。
以 gulp-better-gulp
为例:
const rollup = require('gulp-better-gulp')
function gulpJs () {
return gulp.src(globPaths.js)
.pipe(sourcemaps.init())
.pipe(rollup({}, 'iife'))
.pipe(babel({
presets: ['@babel/env'],
plugins: [
[
"@babel/plugin-transform-runtime", {
corejs: 3
}
]
]
}))
.pipe(uglifyJs())
.pipe(sourcemaps.write())
.pipe(gulp.dest('dist/js'))
.pipe(gulpConnect.reload())
}