Gulp 多页应用开发(支持es6)

源码

源码目录

.
+-- src
|   +-- assets  [各页面引用文件]
|   |   +-- css
|   |   +-- js  [可使用es6语法,tools下文件需引入才可用]
|   |   |   +-- tools
|   |   |   |   +-- axios.js
|   |   |   |   +-- global.js
|   |   |   +-- index.js
|   |   |   +-- login.js
|   |   +-- less
|   |   |   +-- index.less
|   |   |   +-- login.less
|   +-- common  [框架、插件]
|   |   +-- css
|   |   |   +-- bootstrap.min.css
|   |   +-- img
|   |   +-- js
|   |   |   +-- bootstrap.min.js
|   +-- part  [公用模块]
|   |   +-- less
|   |   |   +-- common.less
|   |   |   +-- footer.less
|   |   |   +-- header.less
|   |   |   +-- variable.less
|   |   +-- tpl
|   |   |   +-- header.html
|   |   |   +-- footer.html
|   |   |   +-- meta.html
|   +-- index.html
|   +-- login.html
+-- gulpfile.js
+-- package.json
+-- webpack.config.js

gulpfile.js

const gulp = require('gulp');
const plugins = require("gulp-load-plugins")({
        pattern: '*' //让gulp-load-plugins插件能匹配除了gulp插件之外的其他插件
      });
const fileinclude = require('gulp-file-include'); // 合并 html 文件
const cleanCSS = require('gulp-clean-css');
const path = require('path');
const webpack = require('webpack-stream');
const browserSync = require('browser-sync');
const reload = browserSync.reload;
const proxy = require('http-proxy-middleware');
var sftp = require('gulp-sftp');

var isDev = !(process.env.NODE_ENV === 'production');

console.log('process.env.NODE_ENV',process.env.NODE_ENV)

// html 中环境变量
const envOptions = (isDev) => {
  return {
    serverStaticPath: isDev ? './' : 'http://portal.yanxiu.com/statics/2018_yunnan_university/'
  }
};

// 文件目录结构
const pathDir = {
  html: {
    from: './src/*.html',
    to: './dist'
  },
  less: {
    from: './src/assets/less/*.less',
    to: './dist/css'
  },
  js: {
    from: './src/assets/js/*.js',
    to: './dist/js'
  }
}

gulp.task('html', () => {
  return gulp.src(pathDir.html.from)
    .pipe(fileinclude({
      prefix: '@@',
      basepath: '@file'
    }))
    .pipe(plugins.template(envOptions(isDev)))
    // .pipe(plugins.changed(pathDir.html.to))
    .pipe(gulp.dest(pathDir.html.to))
    .pipe(reload({ stream:true }));
});

gulp.task('less', () => {
  return gulp.src(pathDir.less.from)
    .pipe(plugins.less())
    // .pipe(plugins.watch(path.LESS)) //只重新编译被更改过的文件
    .pipe(plugins.autoprefixer({
      browsers: ['last 5 version', 'Android >= 4.0'],
      cascade: true, //是否美化属性值
      remove: true //是否去掉不必要的前缀
    }))
    .pipe(cleanCSS({
      compatibility: 'ie7',
      keepSpecialComments: '*' //保留所有特殊前缀
    }))
    .pipe(gulp.dest(pathDir.less.to))
    .pipe(reload({ stream:true }));
});

gulp.task('js', () => {
  return gulp.src(pathDir.js.from)
    // .pipe(plugins.changed(path.JSDIR))
    .pipe(webpack({
      config: require('./webpack.config.js')
    }))
    .pipe(gulp.dest(pathDir.js.to))
    .pipe(reload({ stream:true }));
});

gulp.task('copy', () => {
  return gulp.src('./src/common/**')
    .pipe(gulp.dest('./dist/'))
});

// 测试 - 上传至服务器
gulp.task('dev-build', () => {
  return gulp.src('./dist/**')
    .pipe(sftp({
      remotePath: '/App/web/phpcms/test/yxb-web',
      host: '192.168.11.11',
      user: 'root',
      pass: '123456'
    }))
})

const taskArr = ['html', 'less', 'js', 'copy'];
// 确保数组里面的任务完成之后,再运行serve任务
gulp.task("serve", taskArr, () => {
  // const aipProxy = proxy('/api', {
  //   target: 'http://orz.yanxiu.com',
  //   changeOrigin: true,
  //   pathRewrite: {
  //     '^/api' : '/'
  //   },
  // });

  browserSync.init({
    server : {
      baseDir: './dist',
      index: 'login_teacher.html'
      // ,
      // middleware: [aipProxy]
    },
    port: 8080
  });

  gulp.watch([pathDir.html.from, './src/part/tpl/*.html'], ['html']);
  gulp.watch([pathDir.less.from, './src/part/less/*.less'], ['less']);
  gulp.watch([pathDir.js.from, './src/assets/tools/*.js'], ['js']);
  gulp.watch('./src/common/*/*.*', ['copy'])
});

package.json

{
  "name": "second",
  "version": "1.0.0",
  "description": "",
  "main": "gulpfile.js",
  "dependencies": {
    "axios": "^0.18.0",
    "yanxiu-passport": "^1.0.6"
  },
  "devDependencies": {
    "@babel/core": "^7.1.2",
    "@babel/preset-env": "^7.1.0",
    "babel-loader": "^8.0.4",
    "browser-sync": "^2.24.5",
    "cross-env": "^5.2.0",
    "gulp": "^3.9.1",
    "gulp-autoprefixer": "^5.0.0",
    "gulp-changed": "^3.2.0",
    "gulp-clean-css": "^3.10.0",
    "gulp-file-include": "^2.0.1",
    "gulp-if": "^2.0.2",
    "gulp-less": "^3.5.0",
    "gulp-load-plugins": "^1.5.0",
    "gulp-postcss": "^8.0.0",
    "gulp-sftp": "^0.1.5",
    "gulp-template": "^5.0.0",
    "gulp-uglify": "^3.0.1",
    "gulp-watch": "^5.0.0",
    "http-proxy-middleware": "^0.19.0",
    "path": "^0.12.7",
    "webpack": "^4.23.1",
    "webpack-stream": "^5.1.1"
  },
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "cross-env NODE_ENV=development gulp serve",
    "build": "cross-env NODE_ENV=production gulp serve"
  },
  "author": "",
  "license": "ISC"
}

webpack.config.js

const path = require('path');

module.exports = {
  mode: 'development',
  entry: {
    index: './src/assets/js/index.js',
    login: './src/assets/js/login.js'
  },
  output: {
    filename: '[name].js',
    chunkFilename: '[name].bundle.js',
    path: path.resolve(__dirname, 'dist/js')
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /(node_modules|bower_components|common)/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env']
          }
        }
      }
    ]
  }
};

其他文件源码

src/index.html

<!DOCTYPE html>
<html lang="en">
<head>
  @@include('./part/tpl/meta.html', {
    "title": "首页"
  })

  <link rel="stylesheet" href="./css/swiper.min.css">
  <link rel="stylesheet" href="./css/index.css">
</head>
<body>
  @@include('./part/tpl/header-nav.html')
  @@include('./part/tpl/banner-swiper.html')

  <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
  <script type="text/javascript" src="./js/bootstrap.min.js"></script>
  <script src="./js/swiper.min.js"></script>

  <script src="./js/index.js"></script>
</body>
</html>

src/part/tpl/meta.html

<meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
  <meta name="description" content="">
  <meta name="author" content="">
  <link rel="icon" href="./favicon.ico">

  <title>@@title</title>

  <link href="./css/bootstrap.min.css" rel="stylesheet">

src/assets/js/login.js

import passport from 'yanxiu-passport';
import { _axios } from './tools/axios'

const $techUser = document.querySelector("#teacherUser"),
      $techPwd = document.querySelector("#teacherPwd"),
      $techRemb = document.querySelector("#teacherRemb");

passport.init({
  passportHost: 'orz.yanxiu.com'
});

function login () {
  passport.login({
    'appKey': 'f749edf6-bc39-6ef9-8f81-158se5fds842',
    'path': '/uc/newLogin',
    'data': {
        'type': 'ALL'// IDCARD,PASSPORT,MOBILE,ALL
    },
    'passport': $techUser.value,
    'password':$techPwd.value
  }).then(err => {
    debugger
    if(!err) {
      console.log('登录成功');

      _axios({
        url: '/pxt/platform/data.api?method=app.platform.getUserRoles',
        method: 'get',
        params: { 'platId': '101' }
      }).then(response => {
        console.log('users', response)
      })
    } else {
      if(err.code === 16){
          err.msg = "账号或密码错误";
      }
      console.log(err.msg || '登录失败')
    }
  });
}

$("#loginBtn").click(() => {
  login();
});

src/assets/js/tools/axios.js

axios.js

知识点

这个配置方案,支持less、postcss的autoprefixer、代码压缩、es6、模板引用等。
下面是部分知识点的说明。

设置及使用环境变量

cross-env

  1. 下载 npm install --save-dev cross-env
  2. 配置
// package.json
{
  // ...
  "scripts": {
    "dev": "cross-env NODE_ENV=development gulp serve",
    "build": "cross-env NODE_ENV=production gulp serve"
  }
}
  1. 使用
// gulpfile.js
var isDev = !(process.env.NODE_ENV === 'production');

支持es6

webpack-stream
babel-loader

模板引用

复用 html 公用部分
gulp-file-include

html 中路径前缀使用变量

gulp-template
本项目中,主要用来处理 html 文件中,不同环境下 js、css文件引入路径前缀的动态编译问题。

开发过程中请求跨域解决方案

http-proxy-middleware

上传至服务器

gulp-sftp

// 测试 - 上传至服务器
gulp.task('dev-build', () => {
  return gulp.src('./dist/**')  // 上传 dist 文件夹下所有内容
    .pipe(sftp({
      remotePath: '/App/web/phpcms/test/yxb-web',  // 上传目录
      host: '192.168.11.11',  // 服务器地址
      user: 'root',  // 用户名
      pass: '123456'  // 密码
    }))
})

相关推荐