如果你需要一个 pc 的多页面自动化工具(webpack(typescript) & gulp... - 简书

826 阅读7分钟
原文链接: www.jianshu.com

现在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
    `
  ))
})

image.png

看到这类即可 在浏览器中输入localhost:8080即可


image.png image.png image.png

Ctrl + S 即可看到效果


image.png

同时生成对应的合并后的多页面项目结构


image.png

项目地址
github.com/vincentSea/…