es6運(yùn)行在瀏覽器的前端項目工作流, 基于gulp,express,webpack構(gòu)建

項目自動化構(gòu)建思路

image.png

自動化構(gòu)建邏輯

  1. 若app文件夾(前端靜. 態(tài)頁面)資源發(fā)生改變 ->
  2. 調(diào)用browser.js腳本 ->
  3. browser.js運(yùn)行script腳本 ->
  4. 將新的js文件打包后寫入server目錄public目錄下 ->
  5. 此行為觸發(fā)server.js監(jiān)聽到服務(wù)端js靜態(tài)資源文件被修改 ->
  6. 執(zhí)行服務(wù)器重啟重新渲染頁面 ->
  7. 前臺看到瀏覽器熱更新

構(gòu)建目錄結(jié)構(gòu),安裝服務(wù)端腳手架工具

  1. 創(chuàng)建項目目錄 app(放置靜態(tài)頁面資源),server(用express腳手架初始化,將來放入熱更新后的靜態(tài)資源),tasks放置所有上述過程的腳本文件
  2. 初始化服務(wù)端express
    npm install -g express-generator //安裝express腳手架
    express -e . //使用express腳手架命令,初始化腳手架,-e代表使用ejs模板引擎
  3. 在根目錄創(chuàng)建 .babelrc文件,此為babel轉(zhuǎn)碼器
  4. 在根目錄創(chuàng)建gulpfile.js, 若用es6語法寫gulpfile文件就創(chuàng)建gulpfile.babel.js

gulp工作流代碼構(gòu)建流程


處理命令行參數(shù)

import yargs from 'yargs'; //處理命令行參數(shù)的包
//區(qū)分開發(fā)環(huán)境和線上環(huán)境
const args = yargs  
  //提取--production參數(shù)
  .option('production',{ 
    boolean:true,//選項是布爾類型
    default:false,//默認(rèn)是false
    describe:'min all scripts' //只是給人看的描述
  })
  //用來監(jiān)聽文件改變的選項
  .option('watch',{
    boolean:true,
    default:false,
    describe:'watch all files'
  })
  //要不要輸出命令行詳細(xì)監(jiān)視的日志
  .option('verbose',{
    boolean:true,
    default:false,
    describe:'log'
  })
  //強(qiáng)制生成sourcemaps映射
  .option('sourcemaps',{
    describe:'force the creation of sroucemaps'
  })
  //端口號
  .option('port',{
    string:true,
    default:8080,
    describe:'server port'
  })
  //表示把輸入的命令以字符串的方式進(jìn)行解析
  .argv

export default args;

處理js

import gulp from 'gulp';
import gulpif from 'gulp-if'; //gulp語句中做if判斷
import concat from 'gulp-concat'; //gulp中處理文件拼接
import webpack from 'webpack';
import gulpWebpack from 'webpack-stream'; //支持webpack在gulp stream中的功能
import named from 'vinyl-named'; //保證webpack生成的文件名能夠和原文件對上
import livereload from 'gulp-livereload'; //瀏覽器熱更新
import plumber from 'gulp-plumber'; //處理文件信息流
import rename from 'gulp-rename'; //對文件重命名
import uglify from 'gulp-uglify'; //壓縮js
import {log, colors} from 'gulp-util'; //命令行工具包,log與色彩輸出
import args from './util/args'; //剛自己寫的對命令行參數(shù)進(jìn)行解析的包

// 為了集中處理項目js文件拋出異常引起gulp流出現(xiàn)問題,需用plumber統(tǒng)一處理錯誤
gulp.task('scripts', () => {
  return gulp
    .src(['app/js/index.js'])
    .pipe(plumber({errorHandle: function () {}}))
    .pipe(named())
    .pipe(gulpWebpack({
      module: {
        loaders: [
          {
            test: /\.js$/,
            loader: 'babel-loader'
          }
        ]
      }
    }), null, (err, stats) => {
      log(`Finished '${colors.cyan('scripts')}'`, stats.toString({chunks: false}))
    })
    //gulp處理完的js指定寫入路徑,api:gulp.dest
    .pipe(gulp.dest('server/public/js'))
    //js文件重命名為cp.min.js,還沒壓縮,只是復(fù)制一份
    .pipe(rename({basename: 'cp', extname: '.min.js'}))
    // 壓縮
    .pipe(uglify({
      compress: {
        properties: false
      },
      output: {
        'quote_keys': true
      }
    }))
    // 把壓縮后的文件放入服務(wù)器目錄
    .pipe(gulp.dest('server/public/js'))
    // 使用gulpif監(jiān)視命令行傳入的參數(shù),若有--watch,則執(zhí)行熱更新
    .pipe(gulpif(args.watch, livereload()))
})

處理后臺頁面模板

import gulp from 'gulp';
import gulpif from 'gulp-if';
import livereload from 'gulp-livereload';
import args from './util/args';

gulp.task('pages',()=>{
  return gulp.src('app/**/*.ejs')
    .pipe(gulp.dest('server')) //文件被寫入的路徑是以所給的相對路徑根據(jù)所給的目標(biāo)目錄計算而來。類似的,相對路徑也可以根據(jù)所給的 base 來計算。這里實際寫到的路徑是server下的/**/*.ejs,即server/views/*.ejs
    .pipe(gulpif(args.watch,livereload()))
})

處理css

import gulp from 'gulp';
import gulpif from 'gulp-if';
import livereload from 'gulp-livereload';
import args from './util/args';

gulp.task('css',()=>{
  return gulp.src('app/**/*.css')
    .pipe(gulp.dest('server/public'))
    //文件被寫入的路徑是以所給的相對路徑根據(jù)所給的目標(biāo)目錄計算而來。類似的,相對路徑也可以根據(jù)所給的 base 來計算。這里實際寫到的路徑是server下的/**/*.css,即server/public/css/*.css
    .pipe(gulpif(args.watch,livereload()))
})

處理服務(wù)端熱重啟

import gulp from 'gulp';
import gulpif from 'gulp-if';
import liveserver from 'gulp-live-server'; //啟動gulp服務(wù)器的包
import args from './util/args';

gulp.task('serve',(cb)=>{
  //如果沒在監(jiān)聽,直接運(yùn)行回調(diào)函數(shù)
  if(!args.watch) return cb(); 
  //啟動express腳手架默認(rèn)的服務(wù)器腳本
  const server = liveserver.new(['--harmony','server/bin/www']); 
  server.start();
  //監(jiān)聽server目錄下的js文件和ejs模板文件,通知服務(wù)器哪些文件改變了
  gulp.watch(['server/public/**/*.js','server/views/**/*.ejs'],function(file){
    server.notify.apply(server,[file]);
  })
  //監(jiān)視服務(wù)器路由及入口文件的改變,進(jìn)行服務(wù)器重啟
  gulp.watch(['server/routes/**/*.js','server/app.js'],function(){
    server.start.bind(server)()
  });
})

處理瀏覽器熱更新

import gulp from 'gulp';
import gulpif from 'gulp-if';
import gutil from 'gulp-util';
import args from './util/args';

gulp.task('browser',(cb)=>{
  if(!args.watch) return cb();//若沒監(jiān)聽,則直接執(zhí)行回調(diào)
  gulp.watch('app/**/*.js',['scripts']);//若js文件發(fā)生改變,則調(diào)用剛才創(chuàng)建的scripts腳本
  gulp.watch('app/**/*.ejs',['pages']); //同上
  gulp.watch('app/**/*.css',['css']); //同上
});

處理服務(wù)器清除舊文件

每次服務(wù)器監(jiān)聽到靜態(tài)資源文件的改變, 會觸發(fā)重啟, 用新的靜態(tài)資源去render頁面,此時需要刪除舊的靜態(tài)資源文件

import gulp from 'gulp';
import del from 'del';
import args from './util/args';
//清除服務(wù)端的靜態(tài)資源文件和模板文件
gulp.task('clean',()=>{
  return del(['server/public','server/views'])
})

build.js處理所有g(shù)ulp文件運(yùn)行關(guān)聯(lián)順序

import gulp from 'gulp';
import gulpSequence from 'gulp-sequence'; //處理文件關(guān)聯(lián)關(guān)系和先后順序

//先clean,再css,再pages,再編譯js,最后一個數(shù)組說明數(shù)組里的任務(wù)都放在前面四個任務(wù)執(zhí)行過一次之后再執(zhí)行,且serve端更新一定 在 browser靜態(tài)資源改變之后 
gulp.task('build',gulpSequence('clean','css','pages','scripts',['browser','serve']));

default.js gulp工作流默認(rèn)入口

gulp在無命令行參數(shù)時會優(yōu)先運(yùn)行defalut.js

import gulp from 'gulp';
gulp.task('default',['build']);

gulp程序入口

import requireDir from 'require-dir';//需要運(yùn)行某一文件夾的gulp任務(wù)
requireDir('./tasks'); //放入tasks目錄

編輯.babelrc

{
  "presets":["es2015"],
  "plugins":["transform-decorators-legacy"]
}

給express腳手架添加熱更新中間件

//在處理路由前,express優(yōu)先處理靜態(tài)資源,若在這個static方法定義的目錄中沒有找到req.url對應(yīng)的靜態(tài)資源,則調(diào)用Next()方法傳入下一個中間件,最終會傳遞到路由中間件上
app.use(express.static(path.join(__dirname, 'public')));
//一定要再靜態(tài)資源設(shè)置之后使用熱更新中間件,此插件的安裝要再最外層項目目錄下的依賴安裝,而不是server目錄的依賴
app.use(require('connect-livereload')());

gulp程序啟動

gulp --watch
在app/public/js下寫一個簡單的js,再在app/public/css下寫一個chotee.css,例如

class Chotee{
  constructor(){
    this.name = 'chotee 啊,成功!'
  }
}

const ct1 = new Chotee

document.body.innerHTML = ct1.name;
body {
  background-color: pink;
}

在app/views/目錄下的index.ejs模板中引入

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <link rel="stylesheet" href="/css/chotee.css">
</head>

<body>
  hello chotee
  <script src="/js/index.js" charset="utf-8"></script>
</body>
</html>

打開瀏覽器訪問localhost:3000端口(express腳手架默認(rèn)端口), 看到

image.png

成功! 此時再去修改js文件,模板文件,熱更新文件,成功,成功,成功!

整個項目github地址: https://github.com/choteewang/gulp-es6-work-flow

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 在現(xiàn)在的前端開發(fā)中,前后端分離、模塊化開發(fā)、版本控制、文件合并與壓縮、mock數(shù)據(jù)等等一些原本后端的思想開始...
    Charlot閱讀 5,653評論 1 32
  • gulpjs是一個前端構(gòu)建工具,與gruntjs相比,gulpjs無需寫一大堆繁雜的配置參數(shù),API也非常簡單,學(xué)...
    依依玖玥閱讀 3,299評論 7 55
  • gulpjs是一個前端構(gòu)建工具,與gruntjs相比,gulpjs無需寫一大堆繁雜的配置參數(shù),API也非常簡單,學(xué)...
    井皮皮閱讀 1,393評論 0 10
  • gulpjs是一個前端構(gòu)建工具,與gruntjs相比,gulpjs無需寫一大堆繁雜的配置參數(shù),API也非常簡單,學(xué)...
    小裁縫sun閱讀 1,020評論 0 3
  • 對網(wǎng)站資源進(jìn)行優(yōu)化,并使用不同瀏覽器測試并不是網(wǎng)站設(shè)計過程中最有意思的部分,但是這個過程中的很多重復(fù)的任務(wù)能夠使用...
    懵逼js閱讀 1,160評論 0 8

友情鏈接更多精彩內(nèi)容