当我们使用上一节的资源处理方式,已经能够将对应资源进行打包处理,但实际应用中,我们不想每次都手动打包,或者需要本地起一个服务器,又甚至需要代理到服务器等等等等,这时候就需要一些辅助工具来帮助我们完成这些工作。
另外,额外说明的是,我们在上一节,已经创建了名为 js、css、html 以及 image 的任务。
在本节相关代码中,读者需加以关联逻辑、注意区别。
Copy Static
在打包时,我们可能需要将一些资源直接拷贝到 dist 目录下,而不需要做任何处理。
安装 gulp-copy :
yarn add gulp-copy -Dconst { src, dest } = require('gulp')
const gulpCopy = require('gulp-copy')
function copy () {
return src('lib/*')
// prefix 表示拷贝时去掉lib目录
.pipe(gulpCopy('dist', { prefix: 1 }))
}
exports.copy = copyClean Directory
在每次打包之前,我们都需要清理一下 dist 目录,以免出现冗余文件。
安装 gulp-clean :
yarn add gulp-clean -Dconst { 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 -Dconst { 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 = jsTIP
启用 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 -Dconst { 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())
}