使用構建工具的原因
自從 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