使用构建工具的原因
自从 nodejs 诞生以来,很多前端工作都可以在本地进行,其中就包括 JS 调试和工作流等。最开始应用工作流的插件叫 Grunt,因为起步早,因此插件多,内容丰富,但是执行速度比较慢。后来就出了 Gulp,和 Grunt 类似,不过由于 Gulp 利用了 nodejs 的流(stream),因此效率十分给力,唯一的缺点就是插件没有 Grunt 多,不过发展到今天,插件也逐渐多起来了。大家有可能还听说过 Webpack,最近几年非常热门,但是 Webpack 的亮点主要是模块打包,可以和 Gulp 配合使用。
使用 Gulp 不仅能对资源进行优化,而且在开发过程中能够通过配置自动完成很多重复的任务,让我们可以专注于代码,提高工作效率;而使用 Webpack,可以把众多模块打包成一个文件,减少网络请求次数。尽管 Gulp 和 Webpack 的许多功能可以互相代替,但是它们各自的核心功能还是不同的。
用 Gulp 完成的工作:
- 模块化
- 编译 sass
- 合并优化压缩 css
- 校验压缩 js
- 优化图片
- 添加文件指纹(md5)
- 浏览器实时刷新
用 Webpack 完成的工作:
- 打包所有 js 文件
安装配置 Gulp 和 Webpack
首先安装好最新的 nodejs(10.0.0)和 npm(6.0.0)。然后全局安装 gulp,由于我用的 ES6 的语法,因此还安装了 Babel:
- 第一步:项目中新建以下目录结构
dist
src
├──layout/
├──sass/
├──img/
├──js/
└──index.html
.babelrc
package.json
gulpfile.babel.js
- 第二步:完成 package.json
{
"name": "gulp-build",
"version": "1.0.0",
"description": "Gulp.js",
"private": true,
"scripts": { // 提供 npm 脚本用于编译
"start": "gulp",
"watch": "gulp watch",
"build": "gulp build --production"
}
}
- 第三步:完成 .babelrc
{
"presets": ["env"], // 使用 babel 默认的转换规则
"plugins": []
}
- 第四步:完成 gulpfile.babel.js
/**
* Gulp Build File
* Version: 2.0.0
* User: NickHopps
*/
import gulp from 'gulp';
import plugins from 'gulp-load-plugins';
import yargs from 'yargs';
import browser from 'browser-sync';
import named from 'vinyl-named';
import webpackStream from 'webpack-stream';
import webpack from 'webpack'
const $ = plugins({
rename: {
'gulp-rev-append': 'rev',
'gulp-file-include': 'fileinclude'
}
});
const PORT = 8000;
const PRODUCTION = !!(yargs.argv.production);
const PATHS = {
pages: {
src: 'src/*.html',
dist: 'dist/'
},
styles: {
vendor: ['node_modules/foundation-sites/scss', 'node_modules/bootstrap/scss/'],
src: 'src/sass/**/*.scss',
dist: 'dist/css/'
},
scripts: {
src: 'src/js/**/*.js',
dist: 'dist/js/'
},
images: {
src: 'src/img/**/*.{jpg,jpeg,png}',
dist: 'dist/img/'
}
};
const WPCONFIG = {
mode: PRODUCTION ? 'production' : 'development',
module: {
rules: [{
test: /.js$/,
use: [{
loader: 'babel-loader'
}]
}]
},
devtool: '#source-map'
};
/* Task to build files */
gulp.task('build', gulp.series(clean, gulp.parallel(html, image, sass, javascript)));
/* Default Task */
gulp.task('default', gulp.series('build', server, watch));
/* Task to watch */
gulp.task('watch', gulp.series(server, watch));
function html() {
return gulp.src(PATHS.pages.src)
.pipe($.fileinclude())
.pipe($.cached('html'))
.pipe($.rev())
.pipe(gulp.dest(PATHS.pages.dist));
}
function image() {
return gulp.src(PATHS.images.src)
.pipe($.cached('image'))
.pipe($.if(PRODUCTION, $.imagemin({progressive: true})))
.pipe(gulp.dest(PATHS.images.dist));
}
function sass() {
return gulp.src(PATHS.styles.src)
.pipe($.plumber({errorHandler: $.notify.onError('Error: <%= error.message %>')}))
.pipe($.sourcemaps.init())
.pipe($.sass({includePaths: PATHS.styles.vendor}))
.pipe($.cached('sass'))
.pipe($.autoprefixer('last 2 version'))
.pipe($.if(PRODUCTION, $.cssnano()))
.pipe($.if(PRODUCTION, $.rename({suffix: '.min'})))
.pipe($.sourcemaps.write(''))
.pipe(gulp.dest(PATHS.styles.dist))
.pipe(browser.reload({ stream: true }));
}
function javascript() {
return gulp.src(PATHS.scripts.src)
.pipe(named())
.pipe($.cached('script'))
.pipe(webpackStream(WPCONFIG, webpack))
.pipe($.if(PRODUCTION, $.rename({suffix: '.min'})))
.pipe(gulp.dest(PATHS.scripts.dist));
}
function clean() {
return gulp.src(`${PATHS.pages.dist}/*`)
.pipe($.clean());
}
function server(done) {
browser.init({
server: PATHS.pages.dist,
port: PORT
});
done();
}
function watch() {
gulp.watch('src/**/*.html').on('all', gulp.series(html, browser.reload));
gulp.watch('src/img/**/*.{jpg,jpeg,png}').on('all', gulp.series(image, browser.reload));
gulp.watch('src/sass/**/*.scss').on('all', sass);
gulp.watch('src/js/**/*.js').on('all', gulp.series(javascript, browser.reload));
}
- 第四步:安装项目开发依赖
npm i -D babel-core babel-loader babel-preset-env browser-sync gulp gulp autoprefixer gulp-babel gulp-cached gulp-clean gulp-cssnano gulp-file-include gulp-if gulp-imagemin gulp-load-plugins gulp-notify gulp-plumber gulp-rename gulp rev-append gulp-sass gulp-sourcemaps vinyl-named webpack webpack-stream yargs
使用的各个包及其功能
babel-core : babel 的核心部分
babel-loader : babel 提供给外部的加载器
babel-preset-env : babel 的 env 规则
browser-sync : 提供浏览器实时更新
gulp : gulp 主程序
gulp-autoprefixer : gulp 的 autoprefixer 插件
gulp-babel : gulp 的 babel 插件
gulp-cached : 缓存 gulp 的文件流
gulp-clean : 清理文件
gulp-cssnano : 压缩 CSS
gulp-file-include : 在 HTML 中使用 include
gulp-if : 提供 if 判断功能
gulp-imagemin : 压缩图片
gulp-load-plugins : 加载 gulp 插件
gulp-notify : 弹窗提醒
gulp-plumber : 处理 gulp 的错误流
gulp-rename : 重命名
gulp-rev-append : 给文件添加 MD5
gulp-sass : sass 编译插件
gulp-sourcemaps : 生成 sourcemap
vinyl-named : 给 vinyl 文件命名
webpack : webpack 主程序
webpack-stream : 把 webpack 转成流供 gulp 处理
yargs : 提供命令参数功能
使用 Gulp 和 Webpack 构建项目
创建好自己的项目文件之后,可运行下列命令构建:
npm start # 相当于执行 gulp
npm run watch # 相当于执行 gulp watch
npm run build # 相当于执行 gulp build --production