现在webpack 可以说是,前端人员的必备工具,它在配置你的单页面程序(这里指定的是打包成一个js文件)这无疑是很牛逼的工具,如果你是用做vue 程序和 react ,ng 等mvvp程序的话,可是做pc端的话,大多情况先是用多页面程序,一般的人都会使用next.js来解决seo的问题(这个没办法,这能怪我国百度是混蛋,谷歌对vue , react 的蜘蛛支持是挺不错的),但是对于很多三线城市的it来说,使用vue + react 的情况,并没有北上广深这么普遍,还是停留在前端切图完毕,然后叫个渲染层的小伙伴去套页面。
为了前端团队更好的协作开发同时提高项目编码质量,需要将Web前端使用工程化方式构建。
目前最知名的构建工具: Gulp、Grunt、NPM + Webpack;
grunt是前端工程化的先驱
gulp更自然基于流的方式连接任务
Webpack最年轻,擅长用于依赖管理,配置稍较复杂
在天朝的项目的PC端项目中,我推荐使用Gulp,Gulp基于nodejs中stream,工作流,效率更好语法更自然,不需要编写复杂的配置文件,毕竟天朝IE8这个东西只能用牛这个词来形容。还有就是bootstarp4的话,想到不用想了,除非你的项目打算不支持IE8-9.
| .babelrc
| .editorconfig
| .eslintignore // eslint 过滤文件
| .eslintrc.js // eslint 配置文件
| .gitignore // git 过滤提交文件
| .postcssrc.js //postcss 配置文件
| .gulpfile.js // gulpfile.js 配置文件
| package.json // node 依赖文件等
| webpack.config.js //webpack 配置文件
| src
| index.html //网站的默认入口文件
| static //静态资源文件
| css
| images
| js
| lib
| views // page 页面
| config // 配置文件
| index.js // gulp的打包配置文件
| poxy.js // url 的代理配置
| server.js // 服务配置项目
gulpfile文件
ps: 在 dev 开发环境中使用的是browserSync来替换了webpack-server,好让gulp也有热更新的服务功能。
const config = require('./config')
const path = require('path')
const chalk = require('chalk')
const gulp = require('gulp')
const gulpif = require('gulp-if')
const htmlmin = require('gulp-htmlmin')
const fileinclude = require('gulp-file-include')
const sass = require('gulp-sass')
const postcss = require('gulp-postcss')
const cleanCSS = require('gulp-clean-css')
const plumber = require('gulp-plumber')
const notify = require('gulp-notify')
const cache = require('gulp-cache')
const imagemin = require('gulp-imagemin')
const pngquant = require('imagemin-pngquant')
const uglify = require('gulp-uglify')
const eslint = require('gulp-eslint')
const stripDebug = require('gulp-strip-debug')
const babel = require('gulp-babel')
const sequence = require('gulp-sequence')
const zip = require('gulp-zip')
const del = require('del')
// webpack
const webpack = require('webpack')
const webpackStream = require('webpack-stream')
const webpackConfig = require('./webpack.config.js')
// server
const browserSync = require('browser-sync').create()
const reload = browserSync.reload
// NODE_ENV
const env = process.env.NODE_ENV || 'development'
const condition = env === 'production'
function respath(dir) {
return path.join(__dirname, './', dir)
}
function onError(error) {
const title = error.plugin + ' ' + error.name
const msg = error.message
const errContent = msg.replace(/\n/g, '\\A ')
notify.onError({
title: title,
message: errContent,
sound: true
})(error)
this.emit('end')
}
function cbTask(task) {
return new Promise((resolve, reject) => {
del(respath('dist'))
.then(paths => {
console.log(chalk.green(`
-----------------------------
Clean tasks are completed
-----------------------------`))
sequence(task, () => {
console.log(chalk.green(`
-----------------------------
All tasks are completed
-----------------------------`))
resolve('completed')
})
})
})
}
gulp.task('html', () => {
return gulp.src(config.dev.html)
.pipe(plumber(onError))
.pipe(fileinclude({
prefix: '@@',
basepath: respath('src/include/')
}))
.pipe(gulpif(condition, htmlmin({
removeComments: true,
collapseWhitespace: true,
minifyJS: true,
minifyCSS: true
})))
.pipe(gulp.dest(config.build.html))
})
gulp.task('styles', () => {
return gulp.src(config.dev.styles)
.pipe(plumber(onError))
.pipe(sass())
.pipe(gulpif(condition, cleanCSS({debug: true})))
.pipe(postcss('./.postcssrc.js'))
.pipe(gulp.dest(config.build.styles))
})
gulp.task('images', () => {
return gulp.src(config.dev.images)
.pipe(plumber(onError))
.pipe(cache(imagemin({
progressive: true, // 无损压缩JPG图片
svgoPlugins: [{removeViewBox: false}], // 不移除svg的viewbox属性
use: [pngquant()] // 使用pngquant插件进行深度压缩
})))
.pipe(gulp.dest(config.build.images))
})
gulp.task('eslint', () => {
return gulp.src(config.dev.script)
.pipe(plumber(onError))
.pipe(gulpif(condition, stripDebug()))
.pipe(eslint({ configFle: './.eslintrc' }))
.pipe(eslint.format())
.pipe(eslint.failAfterError());
})
const useEslint = config.useEslint ? ['eslint'] : [];
gulp.task('script', useEslint, () => {
return gulp.src(config.dev.script)
.pipe(plumber(onError))
.pipe(gulpif(condition, babel({
presets: ['env']
})))
.pipe(gulpif(config.useWebpack, webpackStream(webpackConfig, webpack)))
.pipe(gulpif(condition, uglify()))
.pipe(gulp.dest(config.build.script))
})
gulp.task('static', () => {
return gulp.src(config.dev.static)
.pipe(gulp.dest(config.build.static))
})
gulp.task('clean', () => {
del('./dist').then(paths => {
console.log('Deleted files and folders:\n', paths.join('\n'));
});
})
gulp.task('watch', () => {
gulp.watch(config.dev.allhtml, ['html']).on('change', reload)
gulp.watch(config.dev.styles, ['styles']).on('change', reload)
gulp.watch(config.dev.script, ['script']).on('change', reload)
gulp.watch(config.dev.images, ['images']).on('change', reload)
gulp.watch(config.dev.static, ['static']).on('change', reload)
})
gulp.task('zip', () => {
return gulp.src(config.zip.path)
.pipe(plumber(onError))
.pipe(zip(config.zip.name))
.pipe(gulp.dest(config.zip.dest))
})
gulp.task('server', () => {
const task = ['html', 'styles', 'script', 'images', 'static']
cbTask(task).then(() => {
browserSync.init(config.server)
console.log(chalk.cyan(' Server complete.\n'))
gulp.start('watch')
})
})
gulp.task('build', () => {
const task = ['html', 'styles', 'script', 'images', 'static']
cbTask(task).then(() => {
console.log(chalk.cyan(' Build complete.\n'))
if (config.productionZip) {
gulp.start('zip', () => {
console.log(chalk.cyan(' Zip complete.\n'))
})
}
})
})
gulp.task('default', () => {
console.log(chalk.green(
`
Build Setup
开发环境: npm run dev
生产环境: npm run build
执行压缩: gulp zip
编译页面: gulp html
编译脚本: gulp script
编译样式: gulp styles
语法检测: gulp eslint
压缩图片: gulp images
`
))
})
现在webpack 可以说是,前端人员的必备工具,它在配置你的单页面程序(这里指定的是打包成一个js文件)这无疑是很牛逼的工具,如果你是用做vue 程序和 react ,ng 等mvvp程序的话,可是做pc端的话,大多情况先是用多页面程序,一般的人都会使用next.js来解决seo的问题(这个没办法,这能怪我国百度是混蛋,谷歌对vue , react 的蜘蛛支持是挺不错的),但是对于很多三线城市的it来说,使用vue + react 的情况,并没有北上广深这么普遍,还是停留在前端切图完毕,然后叫个渲染层的小伙伴去套页面。
为了前端团队更好的协作开发同时提高项目编码质量,需要将Web前端使用工程化方式构建。
目前最知名的构建工具: Gulp、Grunt、NPM + Webpack;
grunt是前端工程化的先驱
gulp更自然基于流的方式连接任务
Webpack最年轻,擅长用于依赖管理,配置稍较复杂
在天朝的项目的PC端项目中,我推荐使用Gulp,Gulp基于nodejs中stream,工作流,效率更好语法更自然,不需要编写复杂的配置文件,毕竟天朝IE8这个东西只能用牛这个词来形容。还有就是bootstarp4的话,想到不用想了,除非你的项目打算不支持IE8-9.
| .babelrc
| .editorconfig
| .eslintignore // eslint 过滤文件
| .eslintrc.js // eslint 配置文件
| .gitignore // git 过滤提交文件
| .postcssrc.js //postcss 配置文件
| .gulpfile.js // gulpfile.js 配置文件
| package.json // node 依赖文件等
| webpack.config.js //webpack 配置文件
| src
| index.html //网站的默认入口文件
| static //静态资源文件
| css
| images
| js
| lib
| views // page 页面
| config // 配置文件
| index.js // gulp的打包配置文件
| poxy.js // url 的代理配置
| server.js // 服务配置项目
gulpfile文件
ps: 在 dev 开发环境中使用的是browserSync来替换了webpack-server,好让gulp也有热更新的服务功能。
const config = require('./config')
const path = require('path')
const chalk = require('chalk')
const gulp = require('gulp')
const gulpif = require('gulp-if')
const htmlmin = require('gulp-htmlmin')
const fileinclude = require('gulp-file-include')
const sass = require('gulp-sass')
const postcss = require('gulp-postcss')
const cleanCSS = require('gulp-clean-css')
const plumber = require('gulp-plumber')
const notify = require('gulp-notify')
const cache = require('gulp-cache')
const imagemin = require('gulp-imagemin')
const pngquant = require('imagemin-pngquant')
const uglify = require('gulp-uglify')
const eslint = require('gulp-eslint')
const stripDebug = require('gulp-strip-debug')
const babel = require('gulp-babel')
const sequence = require('gulp-sequence')
const zip = require('gulp-zip')
const del = require('del')
// webpack
const webpack = require('webpack')
const webpackStream = require('webpack-stream')
const webpackConfig = require('./webpack.config.js')
// server
const browserSync = require('browser-sync').create()
const reload = browserSync.reload
// NODE_ENV
const env = process.env.NODE_ENV || 'development'
const condition = env === 'production'
function respath(dir) {
return path.join(__dirname, './', dir)
}
function onError(error) {
const title = error.plugin + ' ' + error.name
const msg = error.message
const errContent = msg.replace(/\n/g, '\\A ')
notify.onError({
title: title,
message: errContent,
sound: true
})(error)
this.emit('end')
}
function cbTask(task) {
return new Promise((resolve, reject) => {
del(respath('dist'))
.then(paths => {
console.log(chalk.green(`
-----------------------------
Clean tasks are completed
-----------------------------`))
sequence(task, () => {
console.log(chalk.green(`
-----------------------------
All tasks are completed
-----------------------------`))
resolve('completed')
})
})
})
}
gulp.task('html', () => {
return gulp.src(config.dev.html)
.pipe(plumber(onError))
.pipe(fileinclude({
prefix: '@@',
basepath: respath('src/include/')
}))
.pipe(gulpif(condition, htmlmin({
removeComments: true,
collapseWhitespace: true,
minifyJS: true,
minifyCSS: true
})))
.pipe(gulp.dest(config.build.html))
})
gulp.task('styles', () => {
return gulp.src(config.dev.styles)
.pipe(plumber(onError))
.pipe(sass())
.pipe(gulpif(condition, cleanCSS({debug: true})))
.pipe(postcss('./.postcssrc.js'))
.pipe(gulp.dest(config.build.styles))
})
gulp.task('images', () => {
return gulp.src(config.dev.images)
.pipe(plumber(onError))
.pipe(cache(imagemin({
progressive: true, // 无损压缩JPG图片
svgoPlugins: [{removeViewBox: false}], // 不移除svg的viewbox属性
use: [pngquant()] // 使用pngquant插件进行深度压缩
})))
.pipe(gulp.dest(config.build.images))
})
gulp.task('eslint', () => {
return gulp.src(config.dev.script)
.pipe(plumber(onError))
.pipe(gulpif(condition, stripDebug()))
.pipe(eslint({ configFle: './.eslintrc' }))
.pipe(eslint.format())
.pipe(eslint.failAfterError());
})
const useEslint = config.useEslint ? ['eslint'] : [];
gulp.task('script', useEslint, () => {
return gulp.src(config.dev.script)
.pipe(plumber(onError))
.pipe(gulpif(condition, babel({
presets: ['env']
})))
.pipe(gulpif(config.useWebpack, webpackStream(webpackConfig, webpack)))
.pipe(gulpif(condition, uglify()))
.pipe(gulp.dest(config.build.script))
})
gulp.task('static', () => {
return gulp.src(config.dev.static)
.pipe(gulp.dest(config.build.static))
})
gulp.task('clean', () => {
del('./dist').then(paths => {
console.log('Deleted files and folders:\n', paths.join('\n'));
});
})
gulp.task('watch', () => {
gulp.watch(config.dev.allhtml, ['html']).on('change', reload)
gulp.watch(config.dev.styles, ['styles']).on('change', reload)
gulp.watch(config.dev.script, ['script']).on('change', reload)
gulp.watch(config.dev.images, ['images']).on('change', reload)
gulp.watch(config.dev.static, ['static']).on('change', reload)
})
gulp.task('zip', () => {
return gulp.src(config.zip.path)
.pipe(plumber(onError))
.pipe(zip(config.zip.name))
.pipe(gulp.dest(config.zip.dest))
})
gulp.task('server', () => {
const task = ['html', 'styles', 'script', 'images', 'static']
cbTask(task).then(() => {
browserSync.init(config.server)
console.log(chalk.cyan(' Server complete.\n'))
gulp.start('watch')
})
})
gulp.task('build', () => {
const task = ['html', 'styles', 'script', 'images', 'static']
cbTask(task).then(() => {
console.log(chalk.cyan(' Build complete.\n'))
if (config.productionZip) {
gulp.start('zip', () => {
console.log(chalk.cyan(' Zip complete.\n'))
})
}
})
})
gulp.task('default', () => {
console.log(chalk.green(
`
Build Setup
开发环境: npm run dev
生产环境: npm run build
执行压缩: gulp zip
编译页面: gulp html
编译脚本: gulp script
编译样式: gulp styles
语法检测: gulp eslint
压缩图片: gulp images
`
))
})
看到这类即可
在浏览器中输入localhost:8080即可
Ctrl + S 即可看到效果
同时生成对应的合并后的多页面项目结构
项目地址
https://github.com/vincentSea/gulp-cli